diff --git a/install-sh b/install-sh old mode 100644 new mode 100755 diff --git a/manifest b/manifest index 5dfc84f214..61daaed0f0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\ssqlite3StrAccumAppend()\sto\suse\srealloc\sinstead\sof\smalloc. -D 2011-01-21T18:25:30 +C Modify\sthe\strace\scallback\smechanism\sso\sthat\sSQL\scommands\sexecuted\sfrom\swithin\svirtual\stable\sor\suser\sfunction\scallbacks\sare\spassed\sto\sthe\strace\scallback\swithout\sparameter\sexpansion\sand\senclosed\sin\sSQL\scomments. +D 2011-01-22T13:32:30 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in de6498556d536ae60bb8bb10e8c1ba011448658c F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -97,7 +97,7 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 +F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F main.mk 05d0f3475dd331896bd607cfb45c5e21b94589ad F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a @@ -178,7 +178,7 @@ F src/select.c 8a7ba246b0b4bb45df7fbc52681728a0e3deaaa7 F src/shell.c 83c6f0cc5a79a081c7b9ddfe4f557b47e0bad976 F src/sqlite.h.in 45ae5d463b5b341420b3cbc236fb1dfb5c0cd1a8 F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754 -F src/sqliteInt.h 3ef5fc89a4c9755a08a68de107493785a284e27c +F src/sqliteInt.h 45926deaf59b1ce3f55d21d5f91a8cecb6a7eb4c F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44 F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -231,11 +231,11 @@ F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f F src/vdbe.c 5d310eaf1a4d8383602126fa82e01291ab7d3cf3 F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 F src/vdbeInt.h 6e6f28e9bccc6c703dca1372fd661c57b5c15fb0 -F src/vdbeapi.c 69c82283ab2b64c0c37a07799d771d4058330743 +F src/vdbeapi.c 8e9324fd35eb70d0b5904bd1af40f2598744dc4d F src/vdbeaux.c 33448d23b857654dd69ed2103611f5c733606f68 F src/vdbeblob.c 18955f0ee6b133cd08e1592010cb9a6b11e9984c F src/vdbemem.c 411649a35686f54268ccabeda175322c4697f5a6 -F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2 +F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 F src/vtab.c b297e8fa656ab5e66244ab15680d68db0adbec30 F src/wal.c dbca424f71678f663a286ab2a98f947af1d412a7 F src/wal.h c1aac6593a0b02b15dc625987e619edeab39292e @@ -786,6 +786,7 @@ F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd F test/tkt4018.test 7c2c9ba4df489c676a0a7a0e809a1fb9b2185bd1 F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7 F test/trace.test 4b36a41a3e9c7842151af6da5998f5080cdad9e5 +F test/trace2.test 092bc2c5776272700450d60a36919921095bdc21 F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6 F test/trans2.test d5337e61de45e66b1fcbf9db833fa8c82e624b22 F test/trans3.test d728abaa318ca364dc370e06576aa7e5fbed7e97 @@ -896,7 +897,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 503ad889da675b3dd83da7338e2902e42f69acac -R 581c91bca4bed9e9c246127dfff2a86d +P 380f61df0754ceec6b3f6a758d04e951cce8c3d9 +R 90a5119ad79fbdf46155bfdda925f6c3 U dan -Z 1951ee9d42233f0fe4bd03e6cd0ae9e1 +Z 22ba801a4079136db1b6273b2820344e diff --git a/manifest.uuid b/manifest.uuid index 37337becbb..302247b035 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -380f61df0754ceec6b3f6a758d04e951cce8c3d9 \ No newline at end of file +a764915b87564fa91ee68e9b1f41394ce0f1fc7e \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5233e99f09..41c46fa269 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -816,6 +816,7 @@ struct sqlite3 { 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 */ diff --git a/src/vdbeapi.c b/src/vdbeapi.c index ca454acc20..5578b868e1 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -410,7 +410,9 @@ static int sqlite3Step(Vdbe *p){ }else #endif /* SQLITE_OMIT_EXPLAIN */ { + db->vdbeExecCnt++; rc = sqlite3VdbeExec(p); + db->vdbeExecCnt--; } #ifndef SQLITE_OMIT_TRACE diff --git a/src/vdbetrace.c b/src/vdbetrace.c index 0d6b21211c..b422fa9eb1 100644 --- a/src/vdbetrace.c +++ b/src/vdbetrace.c @@ -44,9 +44,12 @@ static int findNextHostParameter(const char *zSql, int *pnToken){ } /* -** Return a pointer to a string in memory obtained form sqlite3DbMalloc() which -** holds a copy of zRawSql but with host parameters expanded to their -** current bindings. +** 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. @@ -77,63 +80,72 @@ char *sqlite3VdbeExpandSql( 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; - if( zRawSql[0]=='?' ){ - if( nToken>1 ){ - assert( sqlite3Isdigit(zRawSql[1]) ); - sqlite3GetInt32(&zRawSql[1], &idx); - }else{ - idx = nextIndex; - } - }else{ - assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' ); - testcase( zRawSql[0]==':' ); - testcase( zRawSql[0]=='$' ); - testcase( zRawSql[0]=='@' ); - idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken); - assert( idx>0 ); + if( db->vdbeExecCnt>1 ){ + while( *zRawSql ){ + const char *zStart = zRawSql; + while( *(zRawSql++)!='\n' && *zRawSql ); + sqlite3StrAccumAppend(&out, "-- ", 3); + sqlite3StrAccumAppend(&out, zStart, zRawSql-zStart); } - zRawSql += nToken; - nextIndex = idx + 1; - assert( idx>0 && idx<=p->nVar ); - pVar = &p->aVar[idx-1]; - if( pVar->flags & MEM_Null ){ - sqlite3StrAccumAppend(&out, "NULL", 4); - }else if( pVar->flags & MEM_Int ){ - sqlite3XPrintf(&out, "%lld", pVar->u.i); - }else if( pVar->flags & MEM_Real ){ - sqlite3XPrintf(&out, "%!.15g", pVar->r); - }else if( pVar->flags & MEM_Str ){ + }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; + if( zRawSql[0]=='?' ){ + if( nToken>1 ){ + assert( sqlite3Isdigit(zRawSql[1]) ); + sqlite3GetInt32(&zRawSql[1], &idx); + }else{ + idx = nextIndex; + } + }else{ + assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' ); + testcase( zRawSql[0]==':' ); + testcase( zRawSql[0]=='$' ); + testcase( zRawSql[0]=='@' ); + idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken); + assert( idx>0 ); + } + zRawSql += nToken; + nextIndex = idx + 1; + assert( idx>0 && idx<=p->nVar ); + pVar = &p->aVar[idx-1]; + if( pVar->flags & MEM_Null ){ + sqlite3StrAccumAppend(&out, "NULL", 4); + }else if( pVar->flags & MEM_Int ){ + sqlite3XPrintf(&out, "%lld", pVar->u.i); + }else if( pVar->flags & MEM_Real ){ + sqlite3XPrintf(&out, "%!.15g", pVar->r); + }else if( pVar->flags & MEM_Str ){ #ifndef SQLITE_OMIT_UTF16 - u8 enc = ENC(db); - if( enc!=SQLITE_UTF8 ){ - Mem utf8; - memset(&utf8, 0, sizeof(utf8)); - utf8.db = db; - sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC); - sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8); - sqlite3XPrintf(&out, "'%.*q'", utf8.n, utf8.z); - sqlite3VdbeMemRelease(&utf8); - }else + u8 enc = ENC(db); + if( enc!=SQLITE_UTF8 ){ + Mem utf8; + memset(&utf8, 0, sizeof(utf8)); + utf8.db = db; + sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC); + sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8); + sqlite3XPrintf(&out, "'%.*q'", utf8.n, utf8.z); + sqlite3VdbeMemRelease(&utf8); + }else #endif - { - sqlite3XPrintf(&out, "'%.*q'", pVar->n, pVar->z); + { + sqlite3XPrintf(&out, "'%.*q'", pVar->n, pVar->z); + } + }else if( pVar->flags & MEM_Zero ){ + sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero); + }else{ + assert( pVar->flags & MEM_Blob ); + sqlite3StrAccumAppend(&out, "x'", 2); + for(i=0; in; i++){ + sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff); + } + sqlite3StrAccumAppend(&out, "'", 1); } - }else if( pVar->flags & MEM_Zero ){ - sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero); - }else{ - assert( pVar->flags & MEM_Blob ); - sqlite3StrAccumAppend(&out, "x'", 2); - for(i=0; in; i++){ - sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff); - } - sqlite3StrAccumAppend(&out, "'", 1); } } return sqlite3StrAccumFinish(&out); diff --git a/test/trace2.test b/test/trace2.test new file mode 100644 index 0000000000..2cf50d0811 --- /dev/null +++ b/test/trace2.test @@ -0,0 +1,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