1
0
Fork 0
mirror of https://github.com/DBD-SQLite/DBD-SQLite synced 2025-06-07 14:19:10 -04:00

DBD-SQLite: applied the online backup patch from Toby Corkindale (with a little modification)

This commit is contained in:
Kenichi Ishigaki 2009-05-06 07:55:35 +00:00
parent b30d014286
commit 87baa98f67
7 changed files with 218 additions and 4 deletions

View file

@ -3,6 +3,7 @@ Changes for Perl extension DBD-SQLite
1.26_02 to be released
- Started using install_method() suggested by TIMB (#44882)
Ported last_insert_rowid as the first attempt (ISHIGAKI)
- Added access to Online Backup functionality. (TJC)
1.26_01 Tue 5 May 2009
- Added ORDINAL_POSITION support for $dbh->column_info (ADAMK)

View file

@ -94,6 +94,29 @@ busy_timeout(dbh, timeout=0)
OUTPUT:
RETVAL
static int
backup_from_file(dbh, filename)
SV *dbh
char *filename
ALIAS:
DBD::SQLite::db::sqlite_backup_from_file = 1
CODE:
RETVAL = sqlite_db_backup_from_file(aTHX_ dbh, filename);
OUTPUT:
RETVAL
static int
backup_to_file(dbh, filename)
SV *dbh
char *filename
ALIAS:
DBD::SQLite::db::sqlite_backup_to_file = 1
CODE:
RETVAL = sqlite_db_backup_to_file(aTHX_ dbh, filename);
OUTPUT:
RETVAL
MODULE = DBD::SQLite PACKAGE = DBD::SQLite::st
PROTOTYPES: DISABLE

View file

@ -1254,7 +1254,6 @@ sqlite_db_collation_dispatcher_utf8(
return cmp;
}
void
sqlite3_db_create_collation(pTHX_ SV *dbh, const char *name, SV *func )
{
@ -1293,7 +1292,6 @@ sqlite3_db_create_collation(pTHX_ SV *dbh, const char *name, SV *func )
}
}
static int
sqlite_db_progress_handler_dispatcher( void *handler )
{
@ -1318,8 +1316,6 @@ sqlite_db_progress_handler_dispatcher( void *handler )
return retval;
}
void
sqlite3_db_progress_handler(pTHX_ SV *dbh, int n_opcodes, SV *handler )
{
@ -1342,4 +1338,60 @@ sqlite3_db_progress_handler(pTHX_ SV *dbh, int n_opcodes, SV *handler )
}
}
/* Accesses the SQLite Online Backup API, and fills the currently loaded
* database from the passed filename.
* Usual usage of this would be when you're operating on the :memory:
* special database connection and want to copy it in from a real db.
*/
int
sqlite_db_backup_from_file(pTHX_ SV *dbh, char *filename)
{
int rc;
sqlite3 *pFrom;
sqlite3_backup *pBackup;
D_imp_dbh(dbh);
rc = sqlite3_open(filename, &pFrom);
if (rc==SQLITE_OK) {
pBackup = sqlite3_backup_init(imp_dbh->db, "main", pFrom, "main");
if (pBackup) {
(void)sqlite3_backup_step(pBackup, -1);
(void)sqlite3_backup_finish(pBackup);
}
rc = sqlite3_errcode(imp_dbh->db);
(void)sqlite3_close(pFrom);
}
return rc;
}
/* Accesses the SQLite Online Backup API, and copies the currently loaded
* database into the passed filename.
* Usual usage of this would be when you're operating on the :memory:
* special database connection, and want to back it up to an on-disk file.
*/
int
sqlite_db_backup_to_file(pTHX_ SV *dbh, char *filename)
{
int rc;
sqlite3 *pTo;
sqlite3_backup *pBackup;
D_imp_dbh(dbh);
rc = sqlite3_open(filename, &pTo);
if (rc==SQLITE_OK) {
pBackup = sqlite3_backup_init(pTo, "main", imp_dbh->db, "main");
if (pBackup) {
(void)sqlite3_backup_step(pBackup, -1);
(void)sqlite3_backup_finish(pBackup);
}
rc = sqlite3_errcode(pTo);
(void)sqlite3_close(pTo);
}
return rc;
}
/* end */

View file

@ -79,6 +79,8 @@ void sqlite3_db_progress_handler(pTHX_ SV *dbh, int n_opcodes, SV *handler);
void sqlite_st_reset(pTHX_ SV *sth );
int sqlite_bind_col( SV *sth, imp_sth_t *imp_sth, SV *col, SV *ref, IV sql_type, SV *attribs );
int dbd_set_sqlite3_busy_timeout (pTHX_ SV *dbh, int timeout );
int sqlite_db_backup_from_file(pTHX_ SV *dbh, char *filename);
int sqlite_db_backup_to_file(pTHX_ SV *dbh, char *filename);
#ifdef SvUTF8_on

View file

@ -32,6 +32,8 @@ sub driver {
if (!$methods_are_installed && $DBI::VERSION >= 1.608) {
DBI->setup_driver('DBD::SQLite');
DBD::SQLite::db->install_method('sqlite_last_insert_rowid');
DBD::SQLite::db->install_method('sqlite_backup_from_file');
DBD::SQLite::db->install_method('sqlite_backup_to_file');
$methods_are_installed++;
}
@ -734,6 +736,18 @@ progress handler.
=back
=head2 $dbh->sqlite_backup_from_file( $filename )
This method accesses the SQLite Online Backup API, and will take a backup of
the named database file, copying it to, and overwriting, your current database
connection. This can be particularly handy if your current connection is to the
special :memory: database, and you wish to populate it from an existing DB.
=head2 $dbh->sqlite_backup_to_file( $filename )
This method accesses the SQLite Online Backup API, and will take a backup of
the currently connected database, and write it out to the named file.
=head1 BLOBS
As of version 1.11, blobs should "just work" in SQLite as text columns.

64
t/34_online_backup.t Normal file
View file

@ -0,0 +1,64 @@
#!/usr/bin/perl
use strict;
use warnings;
use Test::More;
use t::lib::Test;
use DBI;
BEGIN {
plan skip_all => 'requires DBI v1.608' if $DBI::VERSION < 1.608;
}
plan tests => 4;
# Connect to the test db and add some stuff:
my $foo = connect_ok( RaiseError => 1 );
$foo->do(
'CREATE TABLE online_backup_test( id INTEGER PRIMARY KEY, foo INTEGER )'
);
$foo->do("INSERT INTO online_backup_test (foo) VALUES ($$)");
# That should be in the "foo" database on disk now, so disconnect and try to
# back it up:
$foo->disconnect;
my $dbh = DBI->connect(
'dbi:SQLite:dbname=:memory:',
undef, undef,
{ RaiseError => 1 }
);
$dbh->sqlite_backup_from_file('foo');
{
my ($count) = $dbh->selectrow_array(
"SELECT count(foo) FROM online_backup_test WHERE foo=$$"
);
is($count, 1, "Found our process ID in backed-up table");
}
# Add more data then attempt to copy it back to file:
$dbh->do(
'CREATE TABLE online_backup_test2 ( id INTEGER PRIMARY KEY, foo INTEGER )'
);
$dbh->do("INSERT INTO online_backup_test2 (foo) VALUES ($$)");
# backup to file (foo):
$dbh->sqlite_backup_to_file('foo');
$dbh->disconnect;
# Reconnect to foo db and check data made it over:
{
my $foo = connect_ok( RaiseError => 1 );
my ($count) = $foo->selectrow_array(
"SELECT count(foo) FROM online_backup_test2 WHERE foo=$$"
);
is($count, 1, "Found our process ID in table back on disk");
$foo->disconnect;
}

58
t/34_online_backup_func.t Normal file
View file

@ -0,0 +1,58 @@
#!/usr/bin/perl
use strict;
use warnings;
use Test::More tests => 4;
use t::lib::Test;
use DBI;
# Connect to the test db and add some stuff:
my $foo = connect_ok( RaiseError => 1 );
$foo->do(
'CREATE TABLE online_backup_test( id INTEGER PRIMARY KEY, foo INTEGER )'
);
$foo->do("INSERT INTO online_backup_test (foo) VALUES ($$)");
# That should be in the "foo" database on disk now, so disconnect and try to
# back it up:
$foo->disconnect;
my $dbh = DBI->connect(
'dbi:SQLite:dbname=:memory:',
undef, undef,
{ RaiseError => 1 }
);
$dbh->func('foo', 'backup_from_file');
{
my ($count) = $dbh->selectrow_array(
"SELECT count(foo) FROM online_backup_test WHERE foo=$$"
);
is($count, 1, "Found our process ID in backed-up table");
}
# Add more data then attempt to copy it back to file:
$dbh->do(
'CREATE TABLE online_backup_test2 ( id INTEGER PRIMARY KEY, foo INTEGER )'
);
$dbh->do("INSERT INTO online_backup_test2 (foo) VALUES ($$)");
# backup to file (foo):
$dbh->func('foo', 'backup_to_file');
$dbh->disconnect;
# Reconnect to foo db and check data made it over:
{
my $foo = connect_ok( RaiseError => 1 );
my ($count) = $foo->selectrow_array(
"SELECT count(foo) FROM online_backup_test2 WHERE foo=$$"
);
is($count, 1, "Found our process ID in table back on disk");
$foo->disconnect;
}