From 3be75f683882d0ea783664261390c1a7b5a376d1 Mon Sep 17 00:00:00 2001 From: Kenichi Ishigaki Date: Wed, 19 Sep 2012 14:55:20 +0000 Subject: [PATCH] implemented sqlite_load_extension --- SQLite.xs | 14 ++++++++++++++ dbdimp.c | 22 ++++++++++++++++++++++ dbdimp.h | 1 + lib/DBD/SQLite.pm | 5 +++++ 4 files changed, 42 insertions(+) diff --git a/SQLite.xs b/SQLite.xs index d6c72d1..bac5bc7 100644 --- a/SQLite.xs +++ b/SQLite.xs @@ -55,6 +55,20 @@ enable_load_extension(dbh, onoff) OUTPUT: RETVAL +static int +load_extension(dbh, file, proc = 0) + SV *dbh + const char *file + const char *proc + ALIAS: + DBD::SQLite::db::sqlite_load_extension = 1 + CODE: + { + RETVAL = sqlite_db_load_extension(aTHX_ dbh, file, proc); + } + OUTPUT: + RETVAL + #endif static int diff --git a/dbdimp.c b/dbdimp.c index 284c2e4..f574da7 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1504,6 +1504,28 @@ sqlite_db_enable_load_extension(pTHX_ SV *dbh, int onoff) return TRUE; } +int +sqlite_db_load_extension(pTHX_ SV *dbh, const char *file, const char *proc) +{ + D_imp_dbh(dbh); + int rc; + + if (!DBIc_ACTIVE(imp_dbh)) { + sqlite_error(dbh, -2, "attempt to load extension on inactive database handle"); + return FALSE; + } + + croak_if_db_is_null(); + + /* COMPAT: sqlite3_load_extension is only available for 3003006 or newer */ + rc = sqlite3_load_extension( imp_dbh->db, file, proc, NULL ); + if ( rc != SQLITE_OK ) { + sqlite_error(dbh, rc, form("sqlite_load_extension failed with error %s", sqlite3_errmsg(imp_dbh->db))); + return FALSE; + } + return TRUE; +} + #endif HV* diff --git a/dbdimp.h b/dbdimp.h index d480545..cde9f20 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -89,6 +89,7 @@ int sqlite_db_create_function(pTHX_ SV *dbh, const char *name, int argc, SV *fun #ifndef SQLITE_OMIT_LOAD_EXTENSION int sqlite_db_enable_load_extension(pTHX_ SV *dbh, int onoff); +int sqlite_db_load_extension(pTHX_ SV *dbh, const char *file, const char *proc); #endif int sqlite_db_create_aggregate(pTHX_ SV *dbh, const char *name, int argc, SV *aggr ); diff --git a/lib/DBD/SQLite.pm b/lib/DBD/SQLite.pm index 487fe9a..acf9727 100644 --- a/lib/DBD/SQLite.pm +++ b/lib/DBD/SQLite.pm @@ -48,6 +48,7 @@ sub driver { DBD::SQLite::db->install_method('sqlite_backup_from_file'); DBD::SQLite::db->install_method('sqlite_backup_to_file'); 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'); DBD::SQLite::db->install_method('sqlite_trace', { O => 0x0004 }); DBD::SQLite::db->install_method('sqlite_profile', { O => 0x0004 }); @@ -1745,6 +1746,10 @@ sqlite3 extensions. After the call, you can load extensions like this: $sth = $dbh->prepare("select load_extension('libsqlitefunctions.so')") or die "Cannot prepare: " . $dbh->errstr(); +=head2 $dbh->sqlite_load_extension( $file, $proc ) + +Loading an extension by a select statement (with the "load_extension" sqlite3 function like above) has some limitations. If you need to, say, create other functions from an extension, use this method. $file (a path to the extension) is mandatory, and $proc (an entry point name) is optional. You need to call C before calling C. + =head2 $dbh->sqlite_trace( $code_ref ) This method registers a trace callback to be invoked whenever