/ Check-in [c4295725]
Login

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

Overview
Comment:Use a separate list of aux-data structures for each trigger program at the VDBE level. Fix for [dc9b1c91].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c4295725015d394f01b8563f47236e0890f1cc0d
User & Date: dan 2016-02-19 18:54:29
References
2016-02-22
09:45
Add an extra test case for the change in commit [c4295725]. check-in: a48ac4c3 user: dan tags: trunk
2016-02-19
18:55 Ticket [dc9b1c91] One trigger may use auxdata belonging to another. status still Open with 6 other changes artifact: 0bea5f1c user: dan
Context
2016-02-19
19:46
Further enhancements to the MSVC batch build tool. check-in: 06f1495f user: mistachkin tags: trunk
18:54
Use a separate list of aux-data structures for each trigger program at the VDBE level. Fix for [dc9b1c91]. check-in: c4295725 user: dan tags: trunk
16:19
Enhance speedtest1 to display the particular version of SQLite under test. check-in: 0cb728c1 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

5692
5693
5694
5695
5696
5697
5698



5699
5700
5701
5702
5703
5704
5705
  }

  p->nFrame++;
  pFrame->pParent = p->pFrame;
  pFrame->lastRowid = lastRowid;
  pFrame->nChange = p->nChange;
  pFrame->nDbChange = p->db->nChange;



  p->nChange = 0;
  p->pFrame = pFrame;
  p->aMem = aMem = &VdbeFrameMem(pFrame)[-1];
  p->nMem = pFrame->nChildMem;
  p->nCursor = (u16)pFrame->nChildCsr;
  p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
  p->aOp = aOp = pProgram->aOp;







>
>
>







5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
  }

  p->nFrame++;
  pFrame->pParent = p->pFrame;
  pFrame->lastRowid = lastRowid;
  pFrame->nChange = p->nChange;
  pFrame->nDbChange = p->db->nChange;
  assert( pFrame->pAuxData==0 );
  pFrame->pAuxData = p->pAuxData;
  p->pAuxData = 0;
  p->nChange = 0;
  p->pFrame = pFrame;
  p->aMem = aMem = &VdbeFrameMem(pFrame)[-1];
  p->nMem = pFrame->nChildMem;
  p->nCursor = (u16)pFrame->nChildCsr;
  p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
  p->aOp = aOp = pProgram->aOp;

Changes to src/vdbeInt.h.

157
158
159
160
161
162
163

164
165
166
167
168
169
170
  Op *aOp;                /* Program instructions for parent frame */
  i64 *anExec;            /* Event counters from parent frame */
  Mem *aMem;              /* Array of memory cells for parent frame */
  u8 *aOnceFlag;          /* Array of OP_Once flags for parent frame */
  VdbeCursor **apCsr;     /* Array of Vdbe cursors for parent frame */
  void *token;            /* Copy of SubProgram.token */
  i64 lastRowid;          /* Last insert rowid (sqlite3.lastRowid) */

  int nCursor;            /* Number of entries in apCsr */
  int pc;                 /* Program Counter in parent (calling) frame */
  int nOp;                /* Size of aOp array */
  int nMem;               /* Number of entries in aMem */
  int nOnceFlag;          /* Number of entries in aOnceFlag */
  int nChildMem;          /* Number of memory cells for child frame */
  int nChildCsr;          /* Number of cursors for child frame */







>







157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
  Op *aOp;                /* Program instructions for parent frame */
  i64 *anExec;            /* Event counters from parent frame */
  Mem *aMem;              /* Array of memory cells for parent frame */
  u8 *aOnceFlag;          /* Array of OP_Once flags for parent frame */
  VdbeCursor **apCsr;     /* Array of Vdbe cursors for parent frame */
  void *token;            /* Copy of SubProgram.token */
  i64 lastRowid;          /* Last insert rowid (sqlite3.lastRowid) */
  AuxData *pAuxData;      /* Linked list of auxdata allocations */
  int nCursor;            /* Number of entries in apCsr */
  int pc;                 /* Program Counter in parent (calling) frame */
  int nOp;                /* Size of aOp array */
  int nMem;               /* Number of entries in aMem */
  int nOnceFlag;          /* Number of entries in aOnceFlag */
  int nChildMem;          /* Number of memory cells for child frame */
  int nChildCsr;          /* Number of cursors for child frame */

Changes to src/vdbeaux.c.

1471
1472
1473
1474
1475
1476
1477















1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490

1491
1492
1493
1494
1495
1496
1497
....
2012
2013
2014
2015
2016
2017
2018



2019
2020
2021
2022
2023
2024
2025
        p->szMalloc = 0;
      }

      p->flags = MEM_Undefined;
    }while( (++p)<pEnd );
  }
}
















/*
** Delete a VdbeFrame object and its contents. VdbeFrame objects are
** allocated by the OP_Program opcode in sqlite3VdbeExec().
*/
void sqlite3VdbeFrameDelete(VdbeFrame *p){
  int i;
  Mem *aMem = VdbeFrameMem(p);
  VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem];
  for(i=0; i<p->nChildCsr; i++){
    sqlite3VdbeFreeCursor(p->v, apCsr[i]);
  }
  releaseMemArray(aMem, p->nChildMem);

  sqlite3DbFree(p->v->db, p);
}

#ifndef SQLITE_OMIT_EXPLAIN
/*
** Give a listing of the program in the virtual machine.
**
................................................................................
  v->aMem = pFrame->aMem;
  v->nMem = pFrame->nMem;
  v->apCsr = pFrame->apCsr;
  v->nCursor = pFrame->nCursor;
  v->db->lastRowid = pFrame->lastRowid;
  v->nChange = pFrame->nChange;
  v->db->nChange = pFrame->nDbChange;



  return pFrame->pc;
}

/*
** Close all cursors.
**
** Also release any dynamic memory held by the VM in the Vdbe.aMem memory 







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













>







 







>
>
>







1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
....
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
        p->szMalloc = 0;
      }

      p->flags = MEM_Undefined;
    }while( (++p)<pEnd );
  }
}

/*
** Delete the linked list of AuxData structures attached to frame *p.
*/
static void deleteAuxdataInFrame(sqlite3 *db, VdbeFrame *p){
  AuxData *pAux = p->pAuxData;
  while( pAux ){
    AuxData *pNext = pAux->pNext;
    if( pAux->xDelete ){
      pAux->xDelete(pAux->pAux);
    }
    sqlite3DbFree(db, pAux);
    pAux = pNext;
  }
}

/*
** Delete a VdbeFrame object and its contents. VdbeFrame objects are
** allocated by the OP_Program opcode in sqlite3VdbeExec().
*/
void sqlite3VdbeFrameDelete(VdbeFrame *p){
  int i;
  Mem *aMem = VdbeFrameMem(p);
  VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem];
  for(i=0; i<p->nChildCsr; i++){
    sqlite3VdbeFreeCursor(p->v, apCsr[i]);
  }
  releaseMemArray(aMem, p->nChildMem);
  deleteAuxdataInFrame(p->v->db, p);
  sqlite3DbFree(p->v->db, p);
}

#ifndef SQLITE_OMIT_EXPLAIN
/*
** Give a listing of the program in the virtual machine.
**
................................................................................
  v->aMem = pFrame->aMem;
  v->nMem = pFrame->nMem;
  v->apCsr = pFrame->apCsr;
  v->nCursor = pFrame->nCursor;
  v->db->lastRowid = pFrame->lastRowid;
  v->nChange = pFrame->nChange;
  v->db->nChange = pFrame->nDbChange;
  sqlite3VdbeDeleteAuxData(v, -1, 0);
  v->pAuxData = pFrame->pAuxData;
  pFrame->pAuxData = 0;
  return pFrame->pc;
}

/*
** Close all cursors.
**
** Also release any dynamic memory held by the VM in the Vdbe.aMem memory 

Added test/regexp2.test.



















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# 2016 February 19
#
# 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 tests for the REGEXP operator in ext/misc/regexp.c.
# It focuses on the use of the sqlite3_set_auxdata()/get_auxdata() APIs.
#

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

load_static_extension db regexp

#-------------------------------------------------------------------------
# Test that triggers do not become confused and use aux-data created by
# a different trigger for a different REGEXP invocation.
#
do_execsql_test 1.0 {
  CREATE TABLE t1(a, b, c);
  CREATE TABLE x1(x, y, z);
  CREATE TABLE x2(x, y, z);

  CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
    INSERT INTO x1 VALUES(
        new.a REGEXP 'abc',
        new.b REGEXP 'abc',
        new.c REGEXP 'abc'
    );
  END;

  CREATE TRIGGER tr2 AFTER INSERT ON t1 BEGIN
    INSERT INTO x2 VALUES(
        new.a REGEXP 'def',
        new.b REGEXP 'def',
        new.c REGEXP 'def'
    );
  END;

  INSERT INTO t1 VALUES('abc', 'def', 'abc');
  SELECT * FROM t1;
} {abc def abc}

do_execsql_test 1.1 { SELECT * FROM x1 } {1 0 1}
do_execsql_test 1.2 { SELECT * FROM x2 } {0 1 0}

#-------------------------------------------------------------------------
# Test that if an exception is thrown several triggers deep, all aux-data
# objects are cleaned up correctly.
#
proc sql_error {} {
  error "SQL error!"
}
db func error sql_error
do_execsql_test 2.0 {
  CREATE TABLE t2(a, b);
  CREATE TABLE t3(c, d);
  CREATE TABLE t4(e, f);

  CREATE TRIGGER t2_tr1 AFTER UPDATE ON t2 BEGIN
    UPDATE t3 SET d = new.b WHERE c = old.a;
  END;

  CREATE TRIGGER t3_tr1 AFTER UPDATE ON t3 BEGIN
    UPDATE t4 SET f = new.d WHERE e = old.c AND new.d REGEXP 'a.*';
  END;

  CREATE TRIGGER t4_tr1 AFTER UPDATE ON t4 BEGIN
    SELECT CASE WHEN new.f REGEXP '.*y.*' THEN error() ELSE 1 END;
  END;

  INSERT INTO t2 VALUES(1, 'a_x_1');
  INSERT INTO t2 VALUES(2, 'a_y_1');

  INSERT INTO t3 VALUES(1, 'b1');
  INSERT INTO t3 VALUES(2, 'b2');

  INSERT INTO t4 VALUES(1, 'b1');
  INSERT INTO t4 VALUES(2, 'b2');
} {}

do_catchsql_test 2.1 {
  UPDATE t2 SET a=a+1 WHERE b REGEXP 'a.*' AND b REGEXP '.*1';
} {1 {SQL error!}}

# Test that the triggers used in the test above work as expected.
#
do_execsql_test 2.2 {
  UPDATE t2 SET b = 'a_abc_1';
} {}
do_execsql_test 2.3 {
  SELECT * FROM t2;
  SELECT * FROM t3;
  SELECT * FROM t4;
} {1 a_abc_1 2 a_abc_1 1 a_abc_1 2 a_abc_1 1 a_abc_1 2 a_abc_1}

finish_test