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

Implemented backup_to_dbh/backup_from_dbh (#30)

This commit is contained in:
Kenichi Ishigaki 2018-01-20 16:03:55 +09:00
parent 881131445e
commit 6faa8a3c90
4 changed files with 166 additions and 1 deletions

View file

@ -259,6 +259,28 @@ backup_to_file(dbh, filename)
OUTPUT:
RETVAL
static int
backup_from_dbh(dbh, from)
SV *dbh
SV *from
ALIAS:
DBD::SQLite::db::sqlite_backup_from_dbh = 1
CODE:
RETVAL = sqlite_db_backup_from_dbh(aTHX_ dbh, from);
OUTPUT:
RETVAL
static int
backup_to_dbh(dbh, to)
SV *dbh
SV *to
ALIAS:
DBD::SQLite::db::sqlite_backup_to_dbh = 1
CODE:
RETVAL = sqlite_db_backup_to_dbh(aTHX_ dbh, to);
OUTPUT:
RETVAL
HV*
table_column_metadata(dbh, dbname, tablename, columnname)
SV* dbh

View file

@ -2615,6 +2615,49 @@ sqlite_db_backup_from_file(pTHX_ SV *dbh, char *filename)
#endif
}
int
sqlite_db_backup_from_dbh(pTHX_ SV *dbh, SV *from)
{
D_imp_dbh(dbh);
#if SQLITE_VERSION_NUMBER >= 3006011
int rc;
sqlite3_backup *pBackup;
imp_dbh_t *imp_dbh_from = (imp_dbh_t *)DBIh_COM(from);
if (!DBIc_ACTIVE(imp_dbh)) {
sqlite_error(dbh, -2, "attempt to backup from file on inactive database handle");
return FALSE;
}
if (!DBIc_ACTIVE(imp_dbh_from)) {
sqlite_error(dbh, -2, "attempt to backup from inactive database handle");
return FALSE;
}
croak_if_db_is_null();
/* COMPAT: sqlite3_backup_* are only available for 3006011 or newer */
pBackup = sqlite3_backup_init(imp_dbh->db, "main", imp_dbh_from->db, "main");
if (pBackup) {
(void)sqlite3_backup_step(pBackup, -1);
(void)sqlite3_backup_finish(pBackup);
}
rc = sqlite3_errcode(imp_dbh->db);
if ( rc != SQLITE_OK ) {
sqlite_error(dbh, rc, form("sqlite_backup_from_file failed with error %s", sqlite3_errmsg(imp_dbh->db)));
return FALSE;
}
return TRUE;
#else
sqlite_error(dbh, SQLITE_ERROR, form("backup feature requires SQLite 3.6.11 and newer"));
return FALSE;
#endif
}
/* 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:
@ -2663,6 +2706,49 @@ sqlite_db_backup_to_file(pTHX_ SV *dbh, char *filename)
#endif
}
int
sqlite_db_backup_to_dbh(pTHX_ SV *dbh, SV *to)
{
D_imp_dbh(dbh);
#if SQLITE_VERSION_NUMBER >= 3006011
int rc;
sqlite3_backup *pBackup;
imp_dbh_t *imp_dbh_to = (imp_dbh_t *)DBIh_COM(to);
if (!DBIc_ACTIVE(imp_dbh)) {
sqlite_error(dbh, -2, "attempt to backup to file on inactive database handle");
return FALSE;
}
if (!DBIc_ACTIVE(imp_dbh_to)) {
sqlite_error(dbh, -2, "attempt to backup to inactive database handle");
return FALSE;
}
croak_if_db_is_null();
/* COMPAT: sqlite3_backup_* are only available for 3006011 or newer */
pBackup = sqlite3_backup_init(imp_dbh_to->db, "main", imp_dbh->db, "main");
if (pBackup) {
(void)sqlite3_backup_step(pBackup, -1);
(void)sqlite3_backup_finish(pBackup);
}
rc = sqlite3_errcode(imp_dbh_to->db);
if ( rc != SQLITE_OK ) {
sqlite_error(dbh, rc, form("sqlite_backup_to_file failed with error %s", sqlite3_errmsg(imp_dbh->db)));
return FALSE;
}
return TRUE;
#else
sqlite_error(dbh, SQLITE_ERROR, form("backup feature requires SQLite 3.6.11 and newer"));
return FALSE;
#endif
}
int
sqlite_db_limit(pTHX_ SV *dbh, int id, int new_value)
{

View file

@ -47,6 +47,8 @@ sub driver {
DBD::SQLite::db->install_method('sqlite_set_authorizer');
DBD::SQLite::db->install_method('sqlite_backup_from_file');
DBD::SQLite::db->install_method('sqlite_backup_to_file');
DBD::SQLite::db->install_method('sqlite_backup_from_dbh');
DBD::SQLite::db->install_method('sqlite_backup_to_dbh');
DBD::SQLite::db->install_method('sqlite_enable_load_extension');
DBD::SQLite::db->install_method('sqlite_load_extension');
DBD::SQLite::db->install_method('sqlite_register_fts3_perl_tokenizer');
@ -2206,6 +2208,19 @@ special :memory: database, and you wish to populate it from an existing DB.
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.
=head2 $dbh->sqlite_backup_from_dbh( $another_dbh )
This method accesses the SQLite Online Backup API, and will take a backup of
the database for the passed handle, 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.
You can use this to backup from an in-memory database to another in-memory database.
=head2 $dbh->sqlite_backup_to_dbh( $another_dbh )
This method accesses the SQLite Online Backup API, and will take a backup of
the currently connected database, and write it out to the passed database handle.
=head2 $dbh->sqlite_enable_load_extension( $bool )
Calling this method with a true value enables loading (external)

View file

@ -12,7 +12,7 @@ BEGIN { requires_sqlite('3.6.11') }
use Test::NoWarnings;
use DBI;
plan tests => 6 * @CALL_FUNCS + 1;
plan tests => 11 * @CALL_FUNCS + 1;
foreach my $call_func (@CALL_FUNCS) {
# Connect to the test db and add some stuff:
@ -69,3 +69,45 @@ foreach my $call_func (@CALL_FUNCS) {
unlink $dbfile;
}
foreach my $call_func (@CALL_FUNCS) {
# Connect to the test db and add some stuff:
my $foo = connect_ok( dbfile => ':memory:', RaiseError => 1 );
$foo->do(
'CREATE TABLE online_backup_test( id INTEGER PRIMARY KEY, foo INTEGER )'
);
$foo->do("INSERT INTO online_backup_test (foo) VALUES ($$)");
my $dbh = DBI->connect(
'dbi:SQLite:dbname=:memory:',
undef, undef,
{ RaiseError => 1 }
);
ok($dbh->$call_func($foo, 'backup_from_dbh'));
{
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 dbh (foo):
ok($dbh->$call_func($foo, 'backup_to_dbh'));
$dbh->disconnect;
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;
}