The sqlite3_trace() callback now prints a message as each trigger fires

within a statement. (CVS 4709)

FossilOrigin-Name: 110c000d86bd4a0b4b946c62d11a435426b02d16
This commit is contained in:
drh 2008-01-12 21:35:57 +00:00
parent 2dcef11bb9
commit 949f9cd565
10 changed files with 90 additions and 63 deletions

View File

@ -1,5 +1,5 @@
C Continuing\swork\stoward\sconverting\sthe\sVM\sto\sa\sregister\smachine.\s(CVS\s4708)
D 2008-01-12T19:03:49
C The\ssqlite3_trace()\scallback\snow\sprints\sa\smessage\sas\seach\strigger\sfires\nwithin\sa\sstatement.\s(CVS\s4709)
D 2008-01-12T21:35:57
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@ -86,7 +86,7 @@ F src/btmutex.c 5d39da37c9d1282f3c6f9967afae6a34ee36b7ff
F src/btree.c 5164b32950cfd41f2c5c31e8ff82c4a499918aef
F src/btree.h 19dcf5ad23c17b98855da548e9a8e3eb4429d5eb
F src/btreeInt.h 1c5a9da165718ef7de81e35ce9ab5d9ba9283f76
F src/build.c 353cce0f4e773b0889d94663dca6dc99598d6b3d
F src/build.c c0f9dba7028d415fb8d282e34a8ebcf69614befd
F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
@ -127,11 +127,11 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
F src/pager.c 0cb6ccea4b9615627d61d7c4417cedc45776d429
F src/pager.h f504f7ae84060fee0416a853e368d3d113c3d6fa
F src/parse.y 2ae06e8d3190faace49c5b82e7cea1fc60d084a1
F src/pragma.c 1d3d9deefcf325e14a99b94f9f506f1a90a9232b
F src/pragma.c b4e77e057990bb2c295c63327406d9bcbf6c9c08
F src/prepare.c c31a879d6795f4765fd0b113675c6debbc96b7fd
F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da
F src/select.c fc9cebb2033a84b31472405114ad36d73c30b967
F src/select.c 34c138d90771a5919fa181f7ddde75277d6a9fc6
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
F src/shell.c 5391e889384d2062249f668110d64ed16f601c4b
F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
@ -163,16 +163,16 @@ F src/test_server.c a6ece6c835e7eae835054124e09e947e422b1ac5
F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59
F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
F src/tokenize.c a4e04438c11fed2c67ec47fe3edbef9cca2d1b48
F src/trigger.c 69df777f7626507d04ef23b9cb185d31ebd8e91a
F src/trigger.c da3e11df34d34c4341d9417d8033facbae16d9e8
F src/update.c aad823f97a930e6982264299863837d4c6107d3b
F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624
F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0
F src/vdbe.c a05947fba057311149cb0635cccdee9bed42f3cb
F src/vdbe.c f36700465fe35af303d33d59fef03779d93b2570
F src/vdbe.h a9166e1601f5b74c20516a74182773a20baee43e
F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346
F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c
F src/vdbeaux.c db33a4c2477546da05e772352be43896d24d51d5
F src/vdbeapi.c cb8c427a3ab646490c83204a98e94eff03ee2e89
F src/vdbeaux.c ac5d274b175e078eb90b1ad7c8f45419c485e92b
F src/vdbeblob.c e386d49d8354aa5a58f0a7f2794303442c149120
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
F src/vdbemem.c a86119b5ccc41ab8653e4746f83d591ff0ae892e
@ -486,7 +486,7 @@ F test/tkt2820.test 017fdee33aaef7abc092beab6088816f1942304b
F test/tkt2822.test 8b1526b1e5b0d38a1a993f7828fbb81759093686
F test/tkt2832.test cd56dc66bb31898b7eb2146baa5bde2eb80f96fe
F test/tkt2854.test aebd5a9904d36d1ef7a074fc5e7c7da3ab00c32a
F test/trace.test 75ffc1b992c780d054748a656e3e7fd674f18567
F test/trace.test 951cd0f5f571e7f36bf7bfe04be70f90fb16fb00
F test/trans.test b73289992b46d38d9479ecc4fdc03d8edb2413dc
F test/trigger1.test 7c13f39ca36f529bf856e05c7d004fc0531d48b4
F test/trigger2.test 33bf8ae9b788013be194efe5f66c04a202facbb4
@ -606,7 +606,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
P a6dddebcc5ccbbf3009c9d06163a8b59036331de
R 537e4808d9b23703b914b666ccd36884
P 426f31ecdd05d1179a2e49c2ca1666011cede9c6
R 3435d52d4f2b4750bec1183c99c98b94
U drh
Z 1569ded7274b37b8c39c0600e4142054
Z 0d14628a3647710d605d98d6d56b6e09

View File

@ -1 +1 @@
426f31ecdd05d1179a2e49c2ca1666011cede9c6
110c000d86bd4a0b4b946c62d11a435426b02d16

View File

@ -22,7 +22,7 @@
** COMMIT
** ROLLBACK
**
** $Id: build.c,v 1.464 2008/01/12 12:48:08 drh Exp $
** $Id: build.c,v 1.465 2008/01/12 21:35:57 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -184,14 +184,15 @@ void sqlite3FinishCoding(Parse *pParse){
}
#ifndef SQLITE_OMIT_TRACE
/* Add a No-op that contains the complete text of the compiled SQL
** statement as its P4 argument. This does not change the functionality
** of the program.
**
** This is used to implement sqlite3_trace().
*/
sqlite3VdbeAddOp4(v, OP_Noop, 0, 0, 0,
pParse->zSql, pParse->zTail-pParse->zSql);
if( !db->init.busy ){
/* Change the P4 argument of the first opcode (which will always be
** an OP_Trace) to be the complete text of the current SQL statement.
*/
VdbeOp *pOp = sqlite3VdbeGetOp(v, 0);
if( pOp && pOp->opcode==OP_Trace ){
sqlite3VdbeChangeP4(v, 0, pParse->zSql, pParse->zTail-pParse->zSql);
}
}
#endif /* SQLITE_OMIT_TRACE */
}

View File

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.165 2008/01/10 23:50:11 drh Exp $
** $Id: pragma.c,v 1.166 2008/01/12 21:35:57 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -250,7 +250,7 @@ void sqlite3Pragma(
int iDb; /* Database index for <database> */
sqlite3 *db = pParse->db;
Db *pDb;
Vdbe *v = sqlite3GetVdbe(pParse);
Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db);
if( v==0 ) return;
pParse->nMem = 1;

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.399 2008/01/12 19:03:49 drh Exp $
** $Id: select.c,v 1.400 2008/01/12 21:35:57 drh Exp $
*/
#include "sqliteInt.h"
@ -1722,6 +1722,11 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
Vdbe *v = pParse->pVdbe;
if( v==0 ){
v = pParse->pVdbe = sqlite3VdbeCreate(pParse->db);
#ifndef SQLITE_OMIT_TRACE
if( v ){
sqlite3VdbeAddOp0(v, OP_Trace);
}
#endif
}
return v;
}

View File

@ -806,6 +806,11 @@ int sqlite3CodeRowTrigger(
AuthContext sContext;
NameContext sNC;
#ifndef SQLITE_OMIT_TRACE
sqlite3VdbeAddOp4(pParse->pVdbe, OP_Trace, 0, 0, 0,
sqlite3_mprintf("-- TRIGGER %s", p->name),
P4_DYNAMIC);
#endif
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;

View File

@ -43,7 +43,7 @@
** 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.694 2008/01/12 19:03:49 drh Exp $
** $Id: vdbe.c,v 1.695 2008/01/12 21:35:57 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -5059,6 +5059,27 @@ case OP_VUpdate: { /* no-push */
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_TRACE
/* Opcode: Trace * * * P4 *
**
** If tracing is enabled (by the sqlite3_trace()) interface, then
** the UTF-8 string contained in P4 is emitted on the trace callback.
*/
case OP_Trace: {
if( pOp->p4.z ){
if( db->xTrace ){
db->xTrace(db->pTraceArg, pOp->p4.z);
}
#ifdef SQLITE_DEBUG
if( (db->flags & SQLITE_SqlTrace)!=0 ){
sqlite3DebugPrintf("SQL-trace: %s\n", pOp->p4.z);
}
#endif /* SQLITE_DEBUG */
}
break;
}
#endif
/* An other opcode is illegal...
*/
default: {

View File

@ -288,20 +288,6 @@ static int sqlite3Step(Vdbe *p){
}
#ifndef SQLITE_OMIT_TRACE
/* Invoke the trace callback if there is one
*/
if( db->xTrace && !db->init.busy ){
assert( p->nOp>0 );
assert( p->aOp[p->nOp-1].opcode==OP_Noop );
assert( p->aOp[p->nOp-1].p4.z!=0 );
assert( p->aOp[p->nOp-1].p4type==P4_DYNAMIC );
sqlite3SafetyOff(db);
db->xTrace(db->pTraceArg, p->aOp[p->nOp-1].p4.z);
if( sqlite3SafetyOn(db) ){
p->rc = SQLITE_MISUSE;
return SQLITE_MISUSE;
}
}
if( db->xProfile && !db->init.busy ){
double rNow;
sqlite3OsCurrentTime(db->pVfs, &rNow);
@ -309,15 +295,6 @@ static int sqlite3Step(Vdbe *p){
}
#endif
/* Print a copy of SQL as it is executed if the SQL_TRACE pragma is turned
** on in debugging mode.
*/
#ifdef SQLITE_DEBUG
if( (db->flags & SQLITE_SqlTrace)!=0 ){
sqlite3DebugPrintf("SQL-trace: %s\n", p->aOp[p->nOp-1].p4.z);
}
#endif /* SQLITE_DEBUG */
db->activeVdbeCnt++;
p->pc = 0;
}
@ -337,17 +314,14 @@ static int sqlite3Step(Vdbe *p){
#ifndef SQLITE_OMIT_TRACE
/* Invoke the profile callback if there is one
*/
if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy ){
if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy && p->nOp>0
&& p->aOp[0].opcode==OP_Trace && p->aOp[0].p4.z!=0 ){
double rNow;
u64 elapseTime;
sqlite3OsCurrentTime(db->pVfs, &rNow);
elapseTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0 - p->startTime;
assert( p->nOp>0 );
assert( p->aOp[p->nOp-1].opcode==OP_Noop );
assert( p->aOp[p->nOp-1].p4.z!=0 );
assert( p->aOp[p->nOp-1].p4type==P4_DYNAMIC );
db->xProfile(db->pProfileArg, p->aOp[p->nOp-1].p4.z, elapseTime);
db->xProfile(db->pProfileArg, p->aOp[0].p4.z, elapseTime);
}
#endif

View File

@ -681,7 +681,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
#endif
default: {
zP4 = pOp->p4.z;
if( zP4==0 || pOp->opcode==OP_Noop ){
if( zP4==0 ){
zP4 = zTemp;
zTemp[0] = 0;
}
@ -854,8 +854,8 @@ void sqlite3VdbePrintSql(Vdbe *p){
int nOp = p->nOp;
VdbeOp *pOp;
if( nOp<1 ) return;
pOp = &p->aOp[nOp-1];
if( pOp->opcode==OP_Noop && pOp->p4.z!=0 ){
pOp = &p->aOp[0];
if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){
const char *z = pOp->p4.z;
while( isspace(*(u8*)z) ) z++;
printf("SQL: [%s]\n", z);
@ -872,11 +872,11 @@ void sqlite3VdbeIOTraceSql(Vdbe *p){
VdbeOp *pOp;
if( sqlite3_io_trace==0 ) return;
if( nOp<1 ) return;
pOp = &p->aOp[nOp-1];
if( pOp->opcode==OP_Noop && pOp->p4.p!=0 ){
pOp = &p->aOp[0];
if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){
int i, j;
char z[1000];
sqlite3_snprintf(sizeof(z), z, "%s", pOp->p4.p);
sqlite3_snprintf(sizeof(z), z, "%s", pOp->p4.z);
for(i=0; isspace((unsigned char)z[i]); i++){}
for(j=0; z[i]; i++){
if( isspace((unsigned char)z[i]) ){

View File

@ -12,7 +12,7 @@
#
# This file implements tests for the "sqlite3_trace()" API.
#
# $Id: trace.test,v 1.6 2006/01/03 00:33:50 drh Exp $
# $Id: trace.test,v 1.7 2008/01/12 21:35:57 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -145,4 +145,25 @@ do_test trace-4.5 {
} {SELECT * FROM t1}
catch {sqlite3_finalize $STMT}
# Trigger tracing.
#
do_test trace-5.1 {
db eval {
CREATE TRIGGER r1t1 AFTER UPDATE ON t1 BEGIN
UPDATE t2 SET a=new.a WHERE rowid=new.rowid;
END;
CREATE TRIGGER r1t2 AFTER UPDATE ON t2 BEGIN
SELECT 'hello';
END;
}
set TRACE_OUT {}
proc trace_proc cmd {
lappend ::TRACE_OUT [string trim $cmd]
}
db eval {
UPDATE t1 SET a=a+1;
}
set TRACE_OUT
} {{UPDATE t1 SET a=a+1;} {-- TRIGGER r1t1} {-- TRIGGER r1t2} {-- TRIGGER r1t1} {-- TRIGGER r1t2} {-- TRIGGER r1t1} {-- TRIGGER r1t2}}
finish_test