mirror of
https://github.com/DBD-SQLite/DBD-SQLite
synced 2025-06-07 14:19:10 -04:00
Merge branch 'backup_between_dbhs'
This commit is contained in:
commit
45f473b587
5 changed files with 168 additions and 1 deletions
22
SQLite.xs
22
SQLite.xs
|
@ -259,6 +259,28 @@ backup_to_file(dbh, filename)
|
||||||
OUTPUT:
|
OUTPUT:
|
||||||
RETVAL
|
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*
|
HV*
|
||||||
table_column_metadata(dbh, dbname, tablename, columnname)
|
table_column_metadata(dbh, dbname, tablename, columnname)
|
||||||
SV* dbh
|
SV* dbh
|
||||||
|
|
86
dbdimp.c
86
dbdimp.c
|
@ -2615,6 +2615,49 @@ sqlite_db_backup_from_file(pTHX_ SV *dbh, char *filename)
|
||||||
#endif
|
#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
|
/* Accesses the SQLite Online Backup API, and copies the currently loaded
|
||||||
* database into the passed filename.
|
* database into the passed filename.
|
||||||
* Usual usage of this would be when you're operating on the :memory:
|
* 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
|
#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
|
int
|
||||||
sqlite_db_limit(pTHX_ SV *dbh, int id, int new_value)
|
sqlite_db_limit(pTHX_ SV *dbh, int id, int new_value)
|
||||||
{
|
{
|
||||||
|
|
2
dbdimp.h
2
dbdimp.h
|
@ -117,6 +117,8 @@ int sqlite_bind_col( SV *sth, imp_sth_t *imp_sth, SV *col, SV *ref, IV sql_type,
|
||||||
int sqlite_db_busy_timeout (pTHX_ SV *dbh, SV *timeout );
|
int sqlite_db_busy_timeout (pTHX_ SV *dbh, SV *timeout );
|
||||||
int sqlite_db_backup_from_file(pTHX_ SV *dbh, char *filename);
|
int sqlite_db_backup_from_file(pTHX_ SV *dbh, char *filename);
|
||||||
int sqlite_db_backup_to_file(pTHX_ SV *dbh, char *filename);
|
int sqlite_db_backup_to_file(pTHX_ SV *dbh, char *filename);
|
||||||
|
int sqlite_db_backup_from_dbh(pTHX_ SV *dbh, SV *from);
|
||||||
|
int sqlite_db_backup_to_dbh(pTHX_ SV *dbh, SV *to);
|
||||||
void sqlite_db_collation_needed(pTHX_ SV *dbh, SV *callback );
|
void sqlite_db_collation_needed(pTHX_ SV *dbh, SV *callback );
|
||||||
SV* sqlite_db_commit_hook( pTHX_ SV *dbh, SV *hook );
|
SV* sqlite_db_commit_hook( pTHX_ SV *dbh, SV *hook );
|
||||||
SV* sqlite_db_rollback_hook( pTHX_ SV *dbh, SV *hook );
|
SV* sqlite_db_rollback_hook( pTHX_ SV *dbh, SV *hook );
|
||||||
|
|
|
@ -47,6 +47,8 @@ sub driver {
|
||||||
DBD::SQLite::db->install_method('sqlite_set_authorizer');
|
DBD::SQLite::db->install_method('sqlite_set_authorizer');
|
||||||
DBD::SQLite::db->install_method('sqlite_backup_from_file');
|
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_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_enable_load_extension');
|
||||||
DBD::SQLite::db->install_method('sqlite_load_extension');
|
DBD::SQLite::db->install_method('sqlite_load_extension');
|
||||||
DBD::SQLite::db->install_method('sqlite_register_fts3_perl_tokenizer');
|
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
|
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.
|
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 )
|
=head2 $dbh->sqlite_enable_load_extension( $bool )
|
||||||
|
|
||||||
Calling this method with a true value enables loading (external)
|
Calling this method with a true value enables loading (external)
|
||||||
|
|
|
@ -12,7 +12,7 @@ BEGIN { requires_sqlite('3.6.11') }
|
||||||
use Test::NoWarnings;
|
use Test::NoWarnings;
|
||||||
use DBI;
|
use DBI;
|
||||||
|
|
||||||
plan tests => 6 * @CALL_FUNCS + 1;
|
plan tests => 11 * @CALL_FUNCS + 1;
|
||||||
|
|
||||||
foreach my $call_func (@CALL_FUNCS) {
|
foreach my $call_func (@CALL_FUNCS) {
|
||||||
# Connect to the test db and add some stuff:
|
# Connect to the test db and add some stuff:
|
||||||
|
@ -69,3 +69,45 @@ foreach my $call_func (@CALL_FUNCS) {
|
||||||
|
|
||||||
unlink $dbfile;
|
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;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue