Tim Bunce wrote:
Great, but please don't use the old func() interface.  It's *much*
better for the driver to call install_method() when it loads.
Then applications can invoke the methods directly, without having
to use func(). As a bonus, RaiseError etc work with install_method()
but not with func().

Either way, driver-private methods should begin with the driver's
prefix, 'sqlite_' in this case.

Hi Tim,
Thanks for the feedback.
I'm not entirely sure I'm Doing It Right, but attached is a different patch against trunk, which uses the install_method() method of installing functions.

It works, but produces a warning that "backup_ is not a registered driver prefix". However if i add "sqlite_" to the front, then I get an error that sqlite_backup_from_file() cannot be found. Although the new methods inside dbdimp.c and SQLite.xs all do have that prefix.

Could you suggest what I have done wrong?

thanks,
Toby
Patch to add support for SQLite's Online Backup functions.
Signed off by Toby Corkindale <[email protected]>

 SQLite.xs         |   19 ++++++++++++++++++
 dbdimp.c          |   56 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 dbdimp.h          |    2 +
 lib/DBD/SQLite.pm |   16 +++++++++++++++
 4 files changed, 93 insertions(+), 0 deletions(-)

diff --git a/SQLite.xs b/SQLite.xs
index fda00aa..8e9d0a6 100644
--- a/SQLite.xs
+++ b/SQLite.xs
@@ -92,6 +92,25 @@ busy_timeout(dbh, timeout=0)
   OUTPUT:
     RETVAL
 
+int
+sqlite_backup_from_file(dbh, filename)
+  SV *dbh
+  char *filename
+  CODE:
+    RETVAL = _sqlite_backup_from_file(aTHX_ dbh, filename);
+  OUTPUT:
+    RETVAL
+
+int
+sqlite_backup_to_file(dbh, filename)
+  SV *dbh
+  char *filename
+  CODE:
+    RETVAL = _sqlite_backup_to_file(aTHX_ dbh, filename);
+  OUTPUT:
+    RETVAL
+
+
 MODULE = DBD::SQLite          PACKAGE = DBD::SQLite::st
 
 PROTOTYPES: DISABLE
diff --git a/dbdimp.c b/dbdimp.c
index 89a531e..cce3e30 100644
--- a/dbdimp.c
+++ b/dbdimp.c
@@ -139,6 +139,62 @@ dbd_set_sqlite3_busy_timeout (pTHX_ SV *dbh, int timeout )
   return imp_dbh->timeout;
 }
 
+/* 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_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_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;
+}
+
 int
 sqlite_db_disconnect (SV *dbh, imp_dbh_t *imp_dbh)
 {
diff --git a/dbdimp.h b/dbdimp.h
index 78f7c5e..dea1bcd 100644
--- a/dbdimp.h
+++ b/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_backup_from_file(pTHX_ SV *dbh, char *filename);
+int _sqlite_backup_to_file(pTHX_ SV *dbh, char *filename);
 
 #ifdef SvUTF8_on
 
diff --git a/lib/DBD/SQLite.pm b/lib/DBD/SQLite.pm
index 3e6219a..122cd14 100644
--- a/lib/DBD/SQLite.pm
+++ b/lib/DBD/SQLite.pm
@@ -98,6 +98,10 @@ sub connect {
         $attr->{Warn} = 0;
     }
 
+    # Install online backup private methods:
+    DBD::SQLite::db->install_method('backup_from_file', {});
+    DBD::SQLite::db->install_method('backup_to_file', {});
+
     return $dbh;
 }
 
@@ -723,6 +727,18 @@ progress handler.
 
 =back
 
+=head2 $dbh->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->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.
_______________________________________________
DBD-SQLite mailing list
[email protected]
http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbd-sqlite

Reply via email to