Add "backup" and "restore" methods to the TCL interfaces and test cases

to exercise those methods. (CVS 6260)

FossilOrigin-Name: e420a3cedc7ee086a77cd719f6b9fb85415eb5f3
This commit is contained in:
drh 2009-02-04 22:46:47 +00:00
parent 9ff849fc87
commit dc2c491525
10 changed files with 360 additions and 50 deletions

View File

@ -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) 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-04T20:55:58 D 2009-02-04T22:46:47
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in c7a5a30fb6852bd7839b1024e1661da8549878ee F Makefile.in c7a5a30fb6852bd7839b1024e1661da8549878ee
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@ -156,14 +156,14 @@ F src/random.c 676b9d7ac820fe81e6fb2394ac8c10cff7f38628
F src/resolve.c 18dc9f0df1d60048e012ce6632251063e0dd356a F src/resolve.c 18dc9f0df1d60048e012ce6632251063e0dd356a
F src/rowset.c ba9375f37053d422dd76965a9c370a13b6e1aac4 F src/rowset.c ba9375f37053d422dd76965a9c370a13b6e1aac4
F src/select.c ae72b604e47092521c4d9ae54e1b1cbeb872a747 F src/select.c ae72b604e47092521c4d9ae54e1b1cbeb872a747
F src/shell.c 6c674a4a4cc56c70ecfb26b07d486d43740b475f F src/shell.c f109ebbb50132926ebbc173a6c2d8838d5d78527
F src/sqlite.h.in 31fa12602f784adea9be66424a2e8b052116736f F src/sqlite.h.in 31fa12602f784adea9be66424a2e8b052116736f
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17 F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
F src/sqliteInt.h 73c1d4f9716fe21f202f9d05c4fd9e6281f2636f F src/sqliteInt.h 73c1d4f9716fe21f202f9d05c4fd9e6281f2636f
F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76 F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
F src/table.c 332ab0ea691e63862e2a8bdfe2c0617ee61062a3 F src/table.c 332ab0ea691e63862e2a8bdfe2c0617ee61062a3
F src/tclsqlite.c 7b3e7fc4856e8280939c9ca0c3a6e49bd2c4bb46 F src/tclsqlite.c 524c1f49ccf9b6a5e3917591cf3b6c4f4204e607
F src/test1.c f88b447699786d58a0136a3a48b12990abc72c8a F src/test1.c f88b447699786d58a0136a3a48b12990abc72c8a
F src/test2.c 9689e7d3b7791da8c03f9acd1ea801802cb83c17 F src/test2.c 9689e7d3b7791da8c03f9acd1ea801802cb83c17
F src/test3.c 88a246b56b824275300e6c899634fbac1dc94b14 F src/test3.c 88a246b56b824275300e6c899634fbac1dc94b14
@ -233,9 +233,10 @@ F test/autoinc.test ab549b48b389cabd92967b86c379ec8b31fa6c16
F test/autovacuum.test 61260e25744189ff766f61ca3df23c1eeec0060e F test/autovacuum.test 61260e25744189ff766f61ca3df23c1eeec0060e
F test/autovacuum_ioerr2.test 598b0663074d3673a9c1bc9a16e80971313bafe6 F test/autovacuum_ioerr2.test 598b0663074d3673a9c1bc9a16e80971313bafe6
F test/avtrans.test 1e901d8102706b63534dbd2bdd4d8f16c4082650 F test/avtrans.test 1e901d8102706b63534dbd2bdd4d8f16c4082650
F test/backup.test 3683d4d3d04e4db6ebba6a4dc9b9d882c3d03bff F test/backup.test f3592c6759de90fa7a7dcd4bce380aed97115c88
F test/backup_ioerr.test 2edd5e347e263733cae8c08f41bf3dbd7277b33d F test/backup2.test 392318e059b83e87e5e4175f08be181a6ddce468
F test/backup_malloc.test 471fb098dae228ca840d4d51e41481901ac03578 F test/backup_ioerr.test a9b8084e488154341719833783ac9db321e14284
F test/backup_malloc.test 1e063c6d75143d0d6e0ae77971dd690070369387
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
F test/between.test 16b1776c6323faadb097a52d673e8e3d8be7d070 F test/between.test 16b1776c6323faadb097a52d673e8e3d8be7d070
F test/bigfile.test 6adfef13d24bbe0c504b4547f292b9a170184f25 F test/bigfile.test 6adfef13d24bbe0c504b4547f292b9a170184f25
@ -548,10 +549,10 @@ F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
F test/sync.test ded6b39d8d8ca3c0c5518516c6371b3316d3e3a3 F test/sync.test ded6b39d8d8ca3c0c5518516c6371b3316d3e3a3
F test/table.test 0aac9468b69d2683e68ee2682cdae28d82a453ec F test/table.test 0aac9468b69d2683e68ee2682cdae28d82a453ec
F test/tableapi.test 505031f15b18a750184d967d2c896cf88fcc969c F test/tableapi.test 505031f15b18a750184d967d2c896cf88fcc969c
F test/tclsqlite.test 30636c3151ccc2d553aa09020b885054141a1963 F test/tclsqlite.test 413a8a887d89ea8fa7055e8d118ffb03b0a4c91a
F test/tempdb.test b88ac8a19823cf771d742bf61eef93ef337c06b1 F test/tempdb.test b88ac8a19823cf771d742bf61eef93ef337c06b1
F test/temptable.test 19b851b9e3e64d91e9867619b2a3f5fffee6e125 F test/temptable.test 19b851b9e3e64d91e9867619b2a3f5fffee6e125
F test/tester.tcl 3d11a8c1d05535400880ac4f8c5402b8dee14b7f F test/tester.tcl 94dc2fe5f8d9179e58ebfe1c7ce2618bdb44799d
F test/thread001.test 7595e58213eda498794860f608e0ea7e499d18d0 F test/thread001.test 7595e58213eda498794860f608e0ea7e499d18d0
F test/thread002.test 0258a50c55f2371de2e4c7e02bec2576c1eef359 F test/thread002.test 0258a50c55f2371de2e4c7e02bec2576c1eef359
F test/thread003.test e17754799649c2b732c295620dca041c32f01e16 F test/thread003.test e17754799649c2b732c295620dca041c32f01e16
@ -700,7 +701,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
P 0882a028c8cee868bb79728499fb1fa7c0630fa6 P 003e1d62189e9e37f901d86a696cfccd22bd3b38
R 6acad12f687e13cb8812850fc6ee53f0 R 007c4ac680893970254b4f79c5bdeaaf
U drh U drh
Z 7b9fc40e749f6a4e8493cccb068ac51f Z b11130f7853d25d09c92b1b009dfc517

View File

@ -1 +1 @@
003e1d62189e9e37f901d86a696cfccd22bd3b38 e420a3cedc7ee086a77cd719f6b9fb85415eb5f3

View File

@ -12,7 +12,7 @@
** This file contains code to implement the "sqlite" command line ** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases. ** 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) #if defined(_WIN32) || defined(WIN32)
/* This needs to come before any includes for MSVC compiler */ /* 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); sqlite3_close(pDest);
return 1; return 1;
} }
open_db(p);
pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb); pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
if( pBackup==0 ){ if( pBackup==0 ){
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); 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 *pSrc;
sqlite3_backup *pBackup; sqlite3_backup *pBackup;
int rc; int rc;
int nTimeout = 0;
if( nArg==2 ){ if( nArg==2 ){
zSrcFile = azArg[1]; zSrcFile = azArg[1];
zDb = "main"; zDb = "main";
@ -1519,20 +1522,25 @@ static int do_meta_command(char *zLine, struct callback_data *p){
sqlite3_close(pSrc); sqlite3_close(pSrc);
return 1; return 1;
} }
open_db(p);
pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main"); pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
if( pBackup==0 ){ if( pBackup==0 ){
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
sqlite3_close(pSrc); sqlite3_close(pSrc);
return 1; return 1;
} }
while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){ while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){ || rc==SQLITE_BUSY ){
sqlite3_sleep(10); if( rc==SQLITE_BUSY ){
if( nTimeout++ >= 3 ) break;
sqlite3_sleep(100);
} }
} }
sqlite3_backup_finish(pBackup); sqlite3_backup_finish(pBackup);
if( rc==SQLITE_DONE ){ if( rc==SQLITE_DONE ){
rc = SQLITE_OK; rc = SQLITE_OK;
}else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
fprintf(stderr, "source database is busy\n");
}else{ }else{
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
} }

View File

@ -12,7 +12,7 @@
** A TCL Interface to SQLite. Append this file to sqlite3.c and ** A TCL Interface to SQLite. Append this file to sqlite3.c and
** compile the whole thing to build a TCL-enabled version of SQLite. ** 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 "tcl.h"
#include <errno.h> #include <errno.h>
@ -983,30 +983,31 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
int choice; int choice;
int rc = TCL_OK; int rc = TCL_OK;
static const char *DB_strs[] = { static const char *DB_strs[] = {
"authorizer", "busy", "cache", "authorizer", "backup", "busy",
"changes", "close", "collate", "cache", "changes", "close",
"collation_needed", "commit_hook", "complete", "collate", "collation_needed", "commit_hook",
"copy", "enable_load_extension","errorcode", "complete", "copy", "enable_load_extension",
"eval", "exists", "function", "errorcode", "eval", "exists",
"incrblob", "interrupt", "last_insert_rowid", "function", "incrblob", "interrupt",
"nullvalue", "onecolumn", "profile", "last_insert_rowid", "nullvalue", "onecolumn",
"progress", "rekey", "rollback_hook", "profile", "progress", "rekey",
"status", "timeout", "total_changes", "restore", "rollback_hook", "status",
"trace", "transaction", "update_hook", "timeout", "total_changes", "trace",
"version", 0 "transaction", "update_hook", "version",
0
}; };
enum DB_enum { enum DB_enum {
DB_AUTHORIZER, DB_BUSY, DB_CACHE, DB_AUTHORIZER, DB_BACKUP, DB_BUSY,
DB_CHANGES, DB_CLOSE, DB_COLLATE, DB_CACHE, DB_CHANGES, DB_CLOSE,
DB_COLLATION_NEEDED, DB_COMMIT_HOOK, DB_COMPLETE, DB_COLLATE, DB_COLLATION_NEEDED, DB_COMMIT_HOOK,
DB_COPY, DB_ENABLE_LOAD_EXTENSION,DB_ERRORCODE, DB_COMPLETE, DB_COPY, DB_ENABLE_LOAD_EXTENSION,
DB_EVAL, DB_EXISTS, DB_FUNCTION, DB_ERRORCODE, DB_EVAL, DB_EXISTS,
DB_INCRBLOB, DB_INTERRUPT, DB_LAST_INSERT_ROWID, DB_FUNCTION, DB_INCRBLOB, DB_INTERRUPT,
DB_NULLVALUE, DB_ONECOLUMN, DB_PROFILE, DB_LAST_INSERT_ROWID, DB_NULLVALUE, DB_ONECOLUMN,
DB_PROGRESS, DB_REKEY, DB_ROLLBACK_HOOK, DB_PROFILE, DB_PROGRESS, DB_REKEY,
DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES, DB_RESTORE, DB_ROLLBACK_HOOK, DB_STATUS,
DB_TRACE, DB_TRANSACTION, DB_UPDATE_HOOK, DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE,
DB_VERSION DB_TRANSACTION, DB_UPDATE_HOOK, DB_VERSION,
}; };
/* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ /* 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; 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? /* $db busy ?CALLBACK?
** **
** Invoke the given callback if an SQL statement attempts to open ** 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; 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) ** $db status (step|sort)
** **

View File

@ -1,4 +1,4 @@
# 2008 January 30 # 2009 January 30
# #
# The author disclaims copyright to this source code. In place of # The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing: # a legal notice, here is a blessing:
@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The # This file implements regression tests for SQLite library. The
# focus of this file is testing the sqlite3_backup_XXX API. # 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] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl

175
test/backup2.test Normal file
View File

@ -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

View File

@ -1,4 +1,4 @@
# 2008 January 30 # 2009 January 30
# #
# The author disclaims copyright to this source code. In place of # The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing: # a legal notice, here is a blessing:
@ -12,7 +12,7 @@
# focus of this file is testing the handling of IO errors by the # focus of this file is testing the handling of IO errors by the
# sqlite3_backup_XXX APIs. # 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] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
@ -284,4 +284,3 @@ for {set iError 1} {$bStop == 0} {incr iError} {
catch { sdb close } catch { sdb close }
catch { ddb close } catch { ddb close }
finish_test finish_test

View File

@ -1,4 +1,4 @@
# 2008 January 30 # 2009 January 30
# #
# The author disclaims copyright to this source code. In place of # The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing: # a legal notice, here is a blessing:
@ -12,7 +12,7 @@
# focus of this file is testing the handling of OOM errors by the # focus of this file is testing the handling of OOM errors by the
# sqlite3_backup_XXX APIs. # 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] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl

View File

@ -15,7 +15,7 @@
# interface is pretty well tested. This file contains some addition # interface is pretty well tested. This file contains some addition
# tests for fringe issues that the main test suite does not cover. # 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] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
@ -35,7 +35,7 @@ do_test tcl-1.1 {
do_test tcl-1.2 { do_test tcl-1.2 {
set v [catch {db bogus} msg] set v [catch {db bogus} msg]
lappend v $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 { do_test tcl-1.2.1 {
set v [catch {db cache bogus} msg] set v [catch {db cache bogus} msg]
lappend v $msg lappend v $msg

View File

@ -11,7 +11,7 @@
# This file implements some common TCL routines used for regression # This file implements some common TCL routines used for regression
# testing the SQLite library # 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 # What for user input before continuing. This gives an opportunity
@ -869,6 +869,24 @@ proc allcksum {{db db}} {
return [md5 $txt] 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}} { proc memdebug_log_sql {{filename mallocs.sql}} {
set data [sqlite3_memdebug_log dump] set data [sqlite3_memdebug_log dump]