Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Modify the trace callback mechanism so that SQL commands executed from within virtual table or user function callbacks are passed to the trace callback without parameter expansion and enclosed in SQL comments. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
a764915b87564fa91ee68e9b1f41394c |
User & Date: | dan 2011-01-22 13:32:30.000 |
Context
2011-01-24
| ||
19:14 | Fix a harmless compiler warning (a shadowed local variable) in analyze.c. (check-in: a1ad7fb38b user: drh tags: trunk) | |
16:00 | Ensure that if a deferred FK constraint is violated by a statement that creates its own implicit transaction, the statement is not an "active-write" after sqlite3_step() returns. (Closed-Leaf check-in: 8063197ef1 user: dan tags: deferred-fk-quirk) | |
2011-01-22
| ||
13:32 | Modify the trace callback mechanism so that SQL commands executed from within virtual table or user function callbacks are passed to the trace callback without parameter expansion and enclosed in SQL comments. (check-in: a764915b87 user: dan tags: trunk) | |
2011-01-21
| ||
18:25 | Change sqlite3StrAccumAppend() to use realloc instead of malloc. (check-in: 380f61df07 user: dan tags: trunk) | |
Changes
install-sh became executable.
whitespace changes only
Changes to src/sqliteInt.h.
︙ | ︙ | |||
812 813 814 815 816 817 818 819 820 821 822 823 824 825 | u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ } init; int nExtension; /* Number of loaded extensions */ void **aExtension; /* Array of shared library handles */ struct Vdbe *pVdbe; /* List of active virtual machines */ int activeVdbeCnt; /* Number of VDBEs currently executing */ int writeVdbeCnt; /* Number of active VDBEs that are writing */ void (*xTrace)(void*,const char*); /* Trace function */ void *pTraceArg; /* Argument to the trace function */ void (*xProfile)(void*,const char*,u64); /* Profiling function */ void *pProfileArg; /* Argument to profile function */ void *pCommitArg; /* Argument to xCommitCallback() */ int (*xCommitCallback)(void*); /* Invoked at every commit. */ void *pRollbackArg; /* Argument to xRollbackCallback() */ | > | 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 | u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ } init; int nExtension; /* Number of loaded extensions */ void **aExtension; /* Array of shared library handles */ struct Vdbe *pVdbe; /* List of active virtual machines */ int activeVdbeCnt; /* Number of VDBEs currently executing */ int writeVdbeCnt; /* Number of active VDBEs that are writing */ int vdbeExecCnt; /* Number of nested calls to VdbeExec() */ void (*xTrace)(void*,const char*); /* Trace function */ void *pTraceArg; /* Argument to the trace function */ void (*xProfile)(void*,const char*,u64); /* Profiling function */ void *pProfileArg; /* Argument to profile function */ void *pCommitArg; /* Argument to xCommitCallback() */ int (*xCommitCallback)(void*); /* Invoked at every commit. */ void *pRollbackArg; /* Argument to xRollbackCallback() */ |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 | } #ifndef SQLITE_OMIT_EXPLAIN if( p->explain ){ rc = sqlite3VdbeList(p); }else #endif /* SQLITE_OMIT_EXPLAIN */ { rc = sqlite3VdbeExec(p); } #ifndef SQLITE_OMIT_TRACE /* Invoke the profile callback if there is one */ if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy && p->zSql ){ sqlite3_int64 iNow; | > > | 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 | } #ifndef SQLITE_OMIT_EXPLAIN if( p->explain ){ rc = sqlite3VdbeList(p); }else #endif /* SQLITE_OMIT_EXPLAIN */ { db->vdbeExecCnt++; rc = sqlite3VdbeExec(p); db->vdbeExecCnt--; } #ifndef SQLITE_OMIT_TRACE /* Invoke the profile callback if there is one */ if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy && p->zSql ){ sqlite3_int64 iNow; |
︙ | ︙ |
Changes to src/vdbetrace.c.
︙ | ︙ | |||
40 41 42 43 44 45 46 | nTotal += n; zSql += n; } return nTotal; } /* | > | | | > > | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | nTotal += n; zSql += n; } return nTotal; } /* ** This function returns a pointer to a nul-terminated string in memory ** obtained from sqlite3DbMalloc(). If sqlite3.vdbeExecCnt is 1, then the ** string contains a copy of zRawSql but with host parameters expanded to ** their current bindings. Or, if sqlite3.vdbeExecCnt is greater than 1, ** then the returned string holds a copy of zRawSql with "-- " prepended ** to each line of text. ** ** The calling function is responsible for making sure the memory returned ** is eventually freed. ** ** ALGORITHM: Scan the input string looking for host parameters in any of ** these forms: ?, ?N, $A, @A, :A. Take care to avoid text within ** string literals, quoted identifier names, and comments. For text forms, |
︙ | ︙ | |||
73 74 75 76 77 78 79 80 81 82 83 84 85 86 | StrAccum out; /* Accumulate the output here */ char zBase[100]; /* Initial working space */ db = p->db; sqlite3StrAccumInit(&out, zBase, sizeof(zBase), db->aLimit[SQLITE_LIMIT_LENGTH]); out.db = db; while( zRawSql[0] ){ n = findNextHostParameter(zRawSql, &nToken); assert( n>0 ); sqlite3StrAccumAppend(&out, zRawSql, n); zRawSql += n; assert( zRawSql[0] || nToken==0 ); if( nToken==0 ) break; | > > > > > > > > | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | StrAccum out; /* Accumulate the output here */ char zBase[100]; /* Initial working space */ db = p->db; sqlite3StrAccumInit(&out, zBase, sizeof(zBase), db->aLimit[SQLITE_LIMIT_LENGTH]); out.db = db; if( db->vdbeExecCnt>1 ){ while( *zRawSql ){ const char *zStart = zRawSql; while( *(zRawSql++)!='\n' && *zRawSql ); sqlite3StrAccumAppend(&out, "-- ", 3); sqlite3StrAccumAppend(&out, zStart, zRawSql-zStart); } }else{ while( zRawSql[0] ){ n = findNextHostParameter(zRawSql, &nToken); assert( n>0 ); sqlite3StrAccumAppend(&out, zRawSql, n); zRawSql += n; assert( zRawSql[0] || nToken==0 ); if( nToken==0 ) break; |
︙ | ︙ | |||
132 133 134 135 136 137 138 139 140 141 142 | sqlite3StrAccumAppend(&out, "x'", 2); for(i=0; i<pVar->n; i++){ sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff); } sqlite3StrAccumAppend(&out, "'", 1); } } return sqlite3StrAccumFinish(&out); } #endif /* #ifndef SQLITE_OMIT_TRACE */ | > | 143 144 145 146 147 148 149 150 151 152 153 154 | sqlite3StrAccumAppend(&out, "x'", 2); for(i=0; i<pVar->n; i++){ sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff); } sqlite3StrAccumAppend(&out, "'", 1); } } } return sqlite3StrAccumFinish(&out); } #endif /* #ifndef SQLITE_OMIT_TRACE */ |
Added test/trace2.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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | # 2011 Jan 21 # # 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. # # This file implements tests for the "sqlite3_trace()" API. Specifically, # it tests the special handling of nested SQL statements (those executed # by virtual table or user function callbacks). These statements are treated # differently in two respects: # # 1. Each line of the statement is prefixed with "-- " to turn it into # an SQL comment. # # 2. Parameter expansion is not performed. # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !trace { finish_test ; return } set ::testprefix trace2 proc sql {zSql} { db one $zSql } proc trace {zSql} { lappend ::trace $zSql } db func sql sql db trace trace proc do_trace_test {tn sql expected} { # Test that the list of string passed to the trace callback when $sql # is executed is equivalent to the list of strings in $expected. # set ::trace [list] execsql $sql uplevel do_test $tn [list {set ::trace}] [list [list {*}$expected]] } proc do_trace_select_test {tn sql expected} { uplevel [list do_trace_test ${tn}.a $sql $expected] # Now execute each SQL statement passed to the trace callback in the # block above. Check that this causes the same set of strings to be # passed to the trace callback again. i.e. that executing the output # of the trace callback is equivalent to the SQL script in $sql. # set sqllist $::trace set ::trace [list] foreach item $sqllist { execsql $item } uplevel do_test $tn.b [list {set ::trace}] [list $sqllist] } do_trace_select_test 1.1 { SELECT 1, 2, 3; } { "SELECT 1, 2, 3;" } do_trace_select_test 1.2 { SELECT sql('SELECT 1, 2, 3'); } { "SELECT sql('SELECT 1, 2, 3');" "-- SELECT 1, 2, 3" } do_trace_select_test 1.3 { SELECT sql('SELECT 1, 2, 3' ); } { "SELECT sql('SELECT 1, 2, 3' );" "-- SELECT 1, -- 2, -- 3" } do_trace_select_test 1.4 { SELECT sql('SELECT 1, 3' ); } { "SELECT sql('SELECT 1, 3' );" "-- SELECT 1, -- -- -- 3" } do_trace_select_test 1.5 { SELECT $var, sql('SELECT 1, $var, 3' ); } { "SELECT NULL, sql('SELECT 1, $var, 3' );" "-- SELECT 1, -- $var, -- 3" } ifcapable fts3 { do_execsql_test 2.1 { CREATE VIRTUAL TABLE x1 USING fts4; INSERT INTO x1 VALUES('Cloudy, with a high near 16'); INSERT INTO x1 VALUES('Wind chill values as low as -13'); } do_trace_test 2.2 { INSERT INTO x1 VALUES('North northwest wind between 8 and 14 mph'); } { "INSERT INTO x1 VALUES('North northwest wind between 8 and 14 mph');" "-- INSERT INTO 'main'.'x1_content' VALUES(?,?)" "-- REPLACE INTO 'main'.'x1_docsize' VALUES(?,?)" "-- SELECT value FROM 'main'.'x1_stat' WHERE id=0" "-- REPLACE INTO 'main'.'x1_stat' VALUES(0,?)" "-- SELECT (SELECT max(idx) FROM 'main'.'x1_segdir' WHERE level = ?) + 1" "-- SELECT coalesce((SELECT max(blockid) FROM 'main'.'x1_segments') + 1, 1)" "-- INSERT INTO 'main'.'x1_segdir' VALUES(?,?,?,?,?,?)" } do_trace_test 2.3 { INSERT INTO x1(x1) VALUES('optimize'); } { "INSERT INTO x1(x1) VALUES('optimize');" "-- SELECT count(*), max(level) FROM 'main'.'x1_segdir'" "-- SELECT idx, start_block, leaves_end_block, end_block, root FROM 'main'.'x1_segdir' ORDER BY level DESC, idx ASC" "-- SELECT coalesce((SELECT max(blockid) FROM 'main'.'x1_segments') + 1, 1)" "-- DELETE FROM 'main'.'x1_segdir'" "-- INSERT INTO 'main'.'x1_segdir' VALUES(?,?,?,?,?,?)" } } finish_test |