mirror of
https://github.com/DBD-SQLite/DBD-SQLite
synced 2025-06-07 22:28:47 -04:00
DBD-SQLite: applied the online backup patch from Toby Corkindale (with a little modification)
This commit is contained in:
parent
b30d014286
commit
87baa98f67
7 changed files with 218 additions and 4 deletions
1
Changes
1
Changes
|
@ -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)
|
||||
|
|
23
SQLite.xs
23
SQLite.xs
|
@ -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
|
||||
|
|
60
dbdimp.c
60
dbdimp.c
|
@ -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 */
|
||||
|
|
2
dbdimp.h
2
dbdimp.h
|
@ -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
|
||||
|
||||
|
|
|
@ -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
64
t/34_online_backup.t
Normal 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
58
t/34_online_backup_func.t
Normal 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;
|
||||
}
|
Loading…
Add table
Reference in a new issue