diff --git a/manifest b/manifest index e2cbfd5a9d..da8ce35bc8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\s".backup"\sand\s".restore"\scommands\sto\sthe\sCLI\s-\simplemented\susing\sthe\nnew\sbackup\sAPI.\s(CVS\s6259) -D 2009-02-04T20:55:58 +C Add\s"backup"\sand\s"restore"\smethods\sto\sthe\sTCL\sinterfaces\sand\stest\scases\nto\sexercise\sthose\smethods.\s(CVS\s6260) +D 2009-02-04T22:46:47 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in c7a5a30fb6852bd7839b1024e1661da8549878ee F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -156,14 +156,14 @@ F src/random.c 676b9d7ac820fe81e6fb2394ac8c10cff7f38628 F src/resolve.c 18dc9f0df1d60048e012ce6632251063e0dd356a F src/rowset.c ba9375f37053d422dd76965a9c370a13b6e1aac4 F src/select.c ae72b604e47092521c4d9ae54e1b1cbeb872a747 -F src/shell.c 6c674a4a4cc56c70ecfb26b07d486d43740b475f +F src/shell.c f109ebbb50132926ebbc173a6c2d8838d5d78527 F src/sqlite.h.in 31fa12602f784adea9be66424a2e8b052116736f F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17 F src/sqliteInt.h 73c1d4f9716fe21f202f9d05c4fd9e6281f2636f F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76 F src/table.c 332ab0ea691e63862e2a8bdfe2c0617ee61062a3 -F src/tclsqlite.c 7b3e7fc4856e8280939c9ca0c3a6e49bd2c4bb46 +F src/tclsqlite.c 524c1f49ccf9b6a5e3917591cf3b6c4f4204e607 F src/test1.c f88b447699786d58a0136a3a48b12990abc72c8a F src/test2.c 9689e7d3b7791da8c03f9acd1ea801802cb83c17 F src/test3.c 88a246b56b824275300e6c899634fbac1dc94b14 @@ -233,9 +233,10 @@ F test/autoinc.test ab549b48b389cabd92967b86c379ec8b31fa6c16 F test/autovacuum.test 61260e25744189ff766f61ca3df23c1eeec0060e F test/autovacuum_ioerr2.test 598b0663074d3673a9c1bc9a16e80971313bafe6 F test/avtrans.test 1e901d8102706b63534dbd2bdd4d8f16c4082650 -F test/backup.test 3683d4d3d04e4db6ebba6a4dc9b9d882c3d03bff -F test/backup_ioerr.test 2edd5e347e263733cae8c08f41bf3dbd7277b33d -F test/backup_malloc.test 471fb098dae228ca840d4d51e41481901ac03578 +F test/backup.test f3592c6759de90fa7a7dcd4bce380aed97115c88 +F test/backup2.test 392318e059b83e87e5e4175f08be181a6ddce468 +F test/backup_ioerr.test a9b8084e488154341719833783ac9db321e14284 +F test/backup_malloc.test 1e063c6d75143d0d6e0ae77971dd690070369387 F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f F test/between.test 16b1776c6323faadb097a52d673e8e3d8be7d070 F test/bigfile.test 6adfef13d24bbe0c504b4547f292b9a170184f25 @@ -548,10 +549,10 @@ F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a F test/sync.test ded6b39d8d8ca3c0c5518516c6371b3316d3e3a3 F test/table.test 0aac9468b69d2683e68ee2682cdae28d82a453ec F test/tableapi.test 505031f15b18a750184d967d2c896cf88fcc969c -F test/tclsqlite.test 30636c3151ccc2d553aa09020b885054141a1963 +F test/tclsqlite.test 413a8a887d89ea8fa7055e8d118ffb03b0a4c91a F test/tempdb.test b88ac8a19823cf771d742bf61eef93ef337c06b1 F test/temptable.test 19b851b9e3e64d91e9867619b2a3f5fffee6e125 -F test/tester.tcl 3d11a8c1d05535400880ac4f8c5402b8dee14b7f +F test/tester.tcl 94dc2fe5f8d9179e58ebfe1c7ce2618bdb44799d F test/thread001.test 7595e58213eda498794860f608e0ea7e499d18d0 F test/thread002.test 0258a50c55f2371de2e4c7e02bec2576c1eef359 F test/thread003.test e17754799649c2b732c295620dca041c32f01e16 @@ -700,7 +701,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P 0882a028c8cee868bb79728499fb1fa7c0630fa6 -R 6acad12f687e13cb8812850fc6ee53f0 +P 003e1d62189e9e37f901d86a696cfccd22bd3b38 +R 007c4ac680893970254b4f79c5bdeaaf U drh -Z 7b9fc40e749f6a4e8493cccb068ac51f +Z b11130f7853d25d09c92b1b009dfc517 diff --git a/manifest.uuid b/manifest.uuid index 46fa374815..b533e76b5f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -003e1d62189e9e37f901d86a696cfccd22bd3b38 \ No newline at end of file +e420a3cedc7ee086a77cd719f6b9fb85415eb5f3 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index b1f0f6cab3..93e4816e78 100644 --- a/src/shell.c +++ b/src/shell.c @@ -12,7 +12,7 @@ ** This file contains code to implement the "sqlite" command line ** utility for accessing SQLite databases. ** -** $Id: shell.c,v 1.200 2009/02/04 20:55:58 drh Exp $ +** $Id: shell.c,v 1.201 2009/02/04 22:46:47 drh Exp $ */ #if defined(_WIN32) || defined(WIN32) /* This needs to come before any includes for MSVC compiler */ @@ -1113,6 +1113,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ sqlite3_close(pDest); return 1; } + open_db(p); pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb); if( pBackup==0 ){ fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); @@ -1506,6 +1507,8 @@ static int do_meta_command(char *zLine, struct callback_data *p){ sqlite3 *pSrc; sqlite3_backup *pBackup; int rc; + int nTimeout = 0; + if( nArg==2 ){ zSrcFile = azArg[1]; zDb = "main"; @@ -1519,20 +1522,25 @@ static int do_meta_command(char *zLine, struct callback_data *p){ sqlite3_close(pSrc); return 1; } + open_db(p); pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main"); if( pBackup==0 ){ fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); sqlite3_close(pSrc); return 1; } - while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){ - if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){ - sqlite3_sleep(10); + while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK + || rc==SQLITE_BUSY ){ + if( rc==SQLITE_BUSY ){ + if( nTimeout++ >= 3 ) break; + sqlite3_sleep(100); } } sqlite3_backup_finish(pBackup); if( rc==SQLITE_DONE ){ rc = SQLITE_OK; + }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){ + fprintf(stderr, "source database is busy\n"); }else{ fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); } diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 1516728d55..4e7f77dd2e 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -12,7 +12,7 @@ ** A TCL Interface to SQLite. Append this file to sqlite3.c and ** compile the whole thing to build a TCL-enabled version of SQLite. ** -** $Id: tclsqlite.c,v 1.235 2009/02/03 16:51:25 danielk1977 Exp $ +** $Id: tclsqlite.c,v 1.236 2009/02/04 22:46:47 drh Exp $ */ #include "tcl.h" #include @@ -983,30 +983,31 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ int choice; int rc = TCL_OK; static const char *DB_strs[] = { - "authorizer", "busy", "cache", - "changes", "close", "collate", - "collation_needed", "commit_hook", "complete", - "copy", "enable_load_extension","errorcode", - "eval", "exists", "function", - "incrblob", "interrupt", "last_insert_rowid", - "nullvalue", "onecolumn", "profile", - "progress", "rekey", "rollback_hook", - "status", "timeout", "total_changes", - "trace", "transaction", "update_hook", - "version", 0 + "authorizer", "backup", "busy", + "cache", "changes", "close", + "collate", "collation_needed", "commit_hook", + "complete", "copy", "enable_load_extension", + "errorcode", "eval", "exists", + "function", "incrblob", "interrupt", + "last_insert_rowid", "nullvalue", "onecolumn", + "profile", "progress", "rekey", + "restore", "rollback_hook", "status", + "timeout", "total_changes", "trace", + "transaction", "update_hook", "version", + 0 }; enum DB_enum { - DB_AUTHORIZER, DB_BUSY, DB_CACHE, - DB_CHANGES, DB_CLOSE, DB_COLLATE, - DB_COLLATION_NEEDED, DB_COMMIT_HOOK, DB_COMPLETE, - DB_COPY, DB_ENABLE_LOAD_EXTENSION,DB_ERRORCODE, - DB_EVAL, DB_EXISTS, DB_FUNCTION, - DB_INCRBLOB, DB_INTERRUPT, DB_LAST_INSERT_ROWID, - DB_NULLVALUE, DB_ONECOLUMN, DB_PROFILE, - DB_PROGRESS, DB_REKEY, DB_ROLLBACK_HOOK, - DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES, - DB_TRACE, DB_TRANSACTION, DB_UPDATE_HOOK, - DB_VERSION + DB_AUTHORIZER, DB_BACKUP, DB_BUSY, + DB_CACHE, DB_CHANGES, DB_CLOSE, + DB_COLLATE, DB_COLLATION_NEEDED, DB_COMMIT_HOOK, + DB_COMPLETE, DB_COPY, DB_ENABLE_LOAD_EXTENSION, + DB_ERRORCODE, DB_EVAL, DB_EXISTS, + DB_FUNCTION, DB_INCRBLOB, DB_INTERRUPT, + DB_LAST_INSERT_ROWID, DB_NULLVALUE, DB_ONECOLUMN, + DB_PROFILE, DB_PROGRESS, DB_REKEY, + DB_RESTORE, DB_ROLLBACK_HOOK, DB_STATUS, + DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE, + DB_TRANSACTION, DB_UPDATE_HOOK, DB_VERSION, }; /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ @@ -1074,6 +1075,55 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ break; } + /* $db backup ?DATABASE? FILENAME + ** + ** Open or create a database file named FILENAME. Transfer the + ** content of local database DATABASE (default: "main") into the + ** FILENAME database. + */ + case DB_BACKUP: { + const char *zDestFile; + const char *zSrcDb; + sqlite3 *pDest; + sqlite3_backup *pBackup; + + if( objc==3 ){ + zSrcDb = "main"; + zDestFile = Tcl_GetString(objv[2]); + }else if( objc==4 ){ + zSrcDb = Tcl_GetString(objv[2]); + zDestFile = Tcl_GetString(objv[3]); + }else{ + Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME"); + return TCL_ERROR; + } + rc = sqlite3_open(zDestFile, &pDest); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, "cannot open target database: ", + sqlite3_errmsg(pDest), (char*)0); + sqlite3_close(pDest); + return TCL_ERROR; + } + pBackup = sqlite3_backup_init(pDest, "main", pDb->db, zSrcDb); + if( pBackup==0 ){ + Tcl_AppendResult(interp, "backup failed: ", + sqlite3_errmsg(pDest), (char*)0); + sqlite3_close(pDest); + return TCL_ERROR; + } + while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){} + sqlite3_backup_finish(pBackup); + if( rc==SQLITE_DONE ){ + rc = TCL_OK; + }else{ + Tcl_AppendResult(interp, "backup failed: ", + sqlite3_errmsg(pDest), (char*)0); + rc = TCL_ERROR; + } + sqlite3_close(pDest); + break; + } + /* $db busy ?CALLBACK? ** ** Invoke the given callback if an SQL statement attempts to open @@ -2151,6 +2201,65 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ break; } + /* $db restore ?DATABASE? FILENAME + ** + ** Open a database file named FILENAME. Transfer the content + ** of FILENAME into the local database DATABASE (default: "main"). + */ + case DB_RESTORE: { + const char *zSrcFile; + const char *zDestDb; + sqlite3 *pSrc; + sqlite3_backup *pBackup; + int nTimeout = 0; + + if( objc==3 ){ + zDestDb = "main"; + zSrcFile = Tcl_GetString(objv[2]); + }else if( objc==4 ){ + zDestDb = Tcl_GetString(objv[2]); + zSrcFile = Tcl_GetString(objv[3]); + }else{ + Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME"); + return TCL_ERROR; + } + rc = sqlite3_open_v2(zSrcFile, &pSrc, SQLITE_OPEN_READONLY, 0); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, "cannot open source database: ", + sqlite3_errmsg(pSrc), (char*)0); + sqlite3_close(pSrc); + return TCL_ERROR; + } + pBackup = sqlite3_backup_init(pDb->db, zDestDb, pSrc, "main"); + if( pBackup==0 ){ + Tcl_AppendResult(interp, "restore failed: ", + sqlite3_errmsg(pDb->db), (char*)0); + sqlite3_close(pSrc); + return TCL_ERROR; + } + while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK + || rc==SQLITE_BUSY ){ + if( rc==SQLITE_BUSY ){ + if( nTimeout++ >= 3 ) break; + sqlite3_sleep(100); + } + } + sqlite3_backup_finish(pBackup); + if( rc==SQLITE_DONE ){ + rc = TCL_OK; + }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){ + Tcl_AppendResult(interp, "restore failed: source database busy", + (char*)0); + rc = TCL_ERROR; + }else{ + Tcl_AppendResult(interp, "restore failed: ", + sqlite3_errmsg(pDb->db), (char*)0); + rc = TCL_ERROR; + } + sqlite3_close(pSrc); + break; + } + /* ** $db status (step|sort) ** diff --git a/test/backup.test b/test/backup.test index aff4d5d9c4..f6e1d5c25b 100644 --- a/test/backup.test +++ b/test/backup.test @@ -1,4 +1,4 @@ -# 2008 January 30 +# 2009 January 30 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing the sqlite3_backup_XXX API. # -# $Id: backup.test,v 1.2 2009/02/04 17:40:58 drh Exp $ +# $Id: backup.test,v 1.3 2009/02/04 22:46:47 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl diff --git a/test/backup2.test b/test/backup2.test new file mode 100644 index 0000000000..6a7bc4f9fb --- /dev/null +++ b/test/backup2.test @@ -0,0 +1,175 @@ +# 2009 February 4 +# +# 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. The +# focus of this file is testing the "backup" and "restore" methods +# of the TCL interface - methods which are based on the +# sqlite3_backup_XXX API. +# +# $Id: backup2.test,v 1.1 2009/02/04 22:46:47 drh Exp $ + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +# Fill a database with test data. +# +do_test backup2-1 { + db eval { + CREATE TABLE t1(x); + INSERT INTO t1 VALUES(randstr(8000,8000)); + INSERT INTO t1 VALUES(randstr(8000,8000)); + INSERT INTO t1 VALUES(randstr(8000,8000)); + INSERT INTO t1 VALUES(randstr(8000,8000)); + INSERT INTO t1 VALUES(randstr(8000,8000)); + CREATE VIEW v1 AS SELECT substr(x,10,10) FROM t1; + CREATE TABLE t2(a,b); + INSERT INTO t2 VALUES(1,2); + INSERT INTO t2 VALUES(2,4); + INSERT INTO t2 SELECT a+2, (a+2)*2 FROM t2; + INSERT INTO t2 SELECT a+4, (a+4)*2 FROM t2; + INSERT INTO t2 SELECT a+8, (a+8)*2 FROM t2; + INSERT INTO t2 SELECT a+16, (a+16)*2 FROM t2; + INSERT INTO t2 SELECT a+32, (a+32)*2 FROM t2; + INSERT INTO t2 SELECT a+64, (a+64)*2 FROM t2; + INSERT INTO t2 SELECT a+128, (a+128)*2 FROM t2; + CREATE INDEX t2i1 ON t2(a,b); + CREATE TRIGGER r1 AFTER INSERT ON t2 BEGIN + SELECT 'hello'; + END; + ANALYZE; + PRAGMA integrity_check; + } +} {ok} + +# Remember a check-sum on the database file. +# +unset -nocomplain cksum +set cksum [dbcksum db main] + +# Make a backup of the test data. Verify that the backup copy +# is identical to the original. +# +do_test backup2-2 { + file delete -force bu1.db + db backup bu1.db + sqlite3 db2 bu1.db + dbcksum db2 main +} $cksum + +# Delete the original. Restore from backup. Verify the content is +# unchanged. +# +do_test backup2-3.1 { + db close + file delete -force test.db test.db-journal + sqlite3 db test.db + db2 eval {BEGIN EXCLUSIVE} + set rc [catch {db restore bu1.db} res] + lappend rc $res + db2 eval {ROLLBACK} + set rc +} {1 {restore failed: source database busy}} +do_test backup2-3.2 { + db close + file delete -force test.db test.db-journal + sqlite3 db test.db + db restore bu1.db + dbcksum db main +} $cksum + +# Use alternative databases - other than "main". +# +do_test backup2-4 { + db restore temp bu1.db + dbcksum db temp +} $cksum +do_test backup2-5 { + db2 close + file delete -force bu1.db bu2.db + db backup temp bu2.db + sqlite3 db2 bu2.db + dbcksum db2 main +} $cksum + +# Try to backup to a readonly file. +# +do_test backup2-6 { + db2 close + catch {file attributes bu2.db -permissions r--------} + catch {file attributes bu2.db -readonly 1} + set rc [catch {db backup temp bu2.db} res] + lappend rc $res +} {1 {backup failed: attempt to write a readonly database}} + +# Try to backup to something that is not a database file. +# +do_test backup2-7 { + catch {file attributes bu2.db -permissions rw-------} + catch {file attributes bu2.db -readonly 0} + set out [open bu2.db w] + puts $out "This is not a valid database file" + close $out + set rc [catch {db backup temp bu2.db} res] + lappend rc $res +} {1 {backup failed: file is encrypted or is not a database}} + +# Try to backup database that does not exist +# +do_test backup2-8 { + file delete -force bu1.db + set rc [catch {db backup aux1 bu1.db} res] + lappend rc $res +} {1 {backup failed: unknown database aux1}} + +# Invalid syntax on the backup method +# +do_test backup2-9 { + set rc [catch {db backup} res] + lappend rc $res +} {1 {wrong # args: should be "db backup ?DATABASE? FILENAME"}} + +# Try to restore from an unreadable file. +# +do_test backup2-10 { + file delete -force bu3.db + file mkdir bu3.db + set rc [catch {db restore temp bu3.db} res] + lappend rc $res +} {1 {cannot open source database: disk I/O error}} + +# Try to restore from something that is not a database file. +# +do_test backup2-11 { + set rc [catch {db restore temp bu2.db} res] + lappend rc $res +} {1 {restore failed: file is encrypted or is not a database}} + +# Try to restore a database that does not exist +# +do_test backup2-12 { + set rc [catch {db restore aux1 bu2.db} res] + lappend rc $res +} {1 {restore failed: unknown database aux1}} +do_test backup2-13 { + file delete -force bu4.db + set rc [catch {db restore bu4.db} res] + lappend rc $res +} {1 {cannot open source database: unable to open database file}} + +# Invalid syntax on the restore method +# +do_test backup2-14 { + set rc [catch {db restore} res] + lappend rc $res +} {1 {wrong # args: should be "db restore ?DATABASE? FILENAME"}} + +file delete -force bu1.db bu2.db bu3.db bu4.db + +finish_test diff --git a/test/backup_ioerr.test b/test/backup_ioerr.test index eae88641ea..e94cd4a80a 100644 --- a/test/backup_ioerr.test +++ b/test/backup_ioerr.test @@ -1,4 +1,4 @@ -# 2008 January 30 +# 2009 January 30 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: @@ -12,7 +12,7 @@ # focus of this file is testing the handling of IO errors by the # sqlite3_backup_XXX APIs. # -# $Id: backup_ioerr.test,v 1.1 2009/02/03 16:51:25 danielk1977 Exp $ +# $Id: backup_ioerr.test,v 1.2 2009/02/04 22:46:47 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -284,4 +284,3 @@ for {set iError 1} {$bStop == 0} {incr iError} { catch { sdb close } catch { ddb close } finish_test - diff --git a/test/backup_malloc.test b/test/backup_malloc.test index 53486cdbe0..17718b228f 100644 --- a/test/backup_malloc.test +++ b/test/backup_malloc.test @@ -1,4 +1,4 @@ -# 2008 January 30 +# 2009 January 30 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: @@ -12,7 +12,7 @@ # focus of this file is testing the handling of OOM errors by the # sqlite3_backup_XXX APIs. # -# $Id: backup_malloc.test,v 1.1 2009/02/03 16:51:25 danielk1977 Exp $ +# $Id: backup_malloc.test,v 1.2 2009/02/04 22:46:47 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl diff --git a/test/tclsqlite.test b/test/tclsqlite.test index e021fcbc9b..a8ac08ddf6 100644 --- a/test/tclsqlite.test +++ b/test/tclsqlite.test @@ -15,7 +15,7 @@ # interface is pretty well tested. This file contains some addition # tests for fringe issues that the main test suite does not cover. # -# $Id: tclsqlite.test,v 1.71 2009/01/02 17:33:46 danielk1977 Exp $ +# $Id: tclsqlite.test,v 1.72 2009/02/04 22:46:47 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -35,7 +35,7 @@ do_test tcl-1.1 { do_test tcl-1.2 { set v [catch {db bogus} msg] lappend v $msg -} {1 {bad option "bogus": must be authorizer, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, profile, progress, rekey, rollback_hook, status, timeout, total_changes, trace, transaction, update_hook, or version}} +} {1 {bad option "bogus": must be authorizer, backup, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, profile, progress, rekey, restore, rollback_hook, status, timeout, total_changes, trace, transaction, update_hook, or version}} do_test tcl-1.2.1 { set v [catch {db cache bogus} msg] lappend v $msg diff --git a/test/tester.tcl b/test/tester.tcl index 6b2d749a7d..0a8c4dc11f 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -11,7 +11,7 @@ # This file implements some common TCL routines used for regression # testing the SQLite library # -# $Id: tester.tcl,v 1.137 2009/02/03 16:51:25 danielk1977 Exp $ +# $Id: tester.tcl,v 1.138 2009/02/04 22:46:47 drh Exp $ # # What for user input before continuing. This gives an opportunity @@ -869,6 +869,24 @@ proc allcksum {{db db}} { return [md5 $txt] } +# Generate a checksum based on the contents of a single database with +# a database connection. The name of the database is $dbname. +# Examples of $dbname are "temp" or "main". +# +proc dbcksum {db dbname} { + if {$dbname=="temp"} { + set master sqlite_temp_master + } else { + set master $dbname.sqlite_master + } + set alltab [$db eval "SELECT name FROM $master WHERE type='table'"] + set txt [$db eval "SELECT * FROM $master"]\n + foreach tab $alltab { + append txt [$db eval "SELECT * FROM $dbname.$tab"]\n + } + return [md5 $txt] +} + proc memdebug_log_sql {{filename mallocs.sql}} { set data [sqlite3_memdebug_log dump]