Added support for load dynamic extensions

This commit is contained in:
Pasquale De Rose 2020-12-31 20:04:07 +01:00
parent 55b8399d7e
commit 464c03efdc
3 changed files with 63 additions and 0 deletions

24
samples/extension_load.cr Normal file
View file

@ -0,0 +1,24 @@
require "db"
require "../src/sqlite3"
db = DB.open "sqlite3://%3Amemory%3A"
db.setup_connection do |connection|
connection.enable_extension_load true
connection.load_extension "/usr/local/lib/mod_spatialite"
connection.enable_extension_load false
end
INSERT_POINT_QUERY = "insert into contacts values (?, SetSRID(MakePoint(?, ?),2261))"
db.exec "create table contacts (name text, position)"
db.exec INSERT_POINT_QUERY, "John Doe", 51.5074, 0.1278
db.exec INSERT_POINT_QUERY, "Mario Rossi", 41.9028, 12.4964
db.exec INSERT_POINT_QUERY, "Dewayne Abara", 9.7054, 43.6327
db.exec INSERT_POINT_QUERY, "Toshiro Ito", 35.6762, 139.6503
db.query "select a.name, b.name, st_distance(a.position, b.position) from contacts a, contacts b where a.name != b.name" do |rs|
rs.each do
puts "Distance between #{rs.read(String)} and #{rs.read(String)} is #{rs.read(Float)}"
end
end

View file

@ -85,6 +85,21 @@ class SQLite3::Connection < DB::Connection
@db @db
end end
# Enable or disable the loading of dynamic extensions in the current SQLite3 Connection
def enable_extension_load(onoff : Bool)
check LibSQLite3.db_config(@db, LibSQLite3::Option::SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, onoff ? 1 : 0, nil)
end
# Load a dynamic extension from file in the current SQLite3 Connection
def load_extension(filename : String)
pzErrMsg : UInt8** = Pointer( UInt8* ).new( ( Pointer( UInt8 ).malloc( 250 ) ).address )
code = LibSQLite3.load_extension(@db, filename, nil, pzErrMsg)
if code != LibSQLite3::Code::OKAY
puts String.new(pzErrMsg.value)
raise Exception.new(@db)
end
end
private def check(code) private def check(code)
raise Exception.new(self) unless code == 0 raise Exception.new(self) unless code == 0
end end

View file

@ -73,11 +73,35 @@ lib LibSQLite3
DONE = 101 DONE = 101
end end
enum Option
SQLITE_DBCONFIG_MAINDBNAME = 1000 # UInt8*
SQLITE_DBCONFIG_LOOKASIDE = 1001 # void* Int32 Int32
SQLITE_DBCONFIG_ENABLE_FKEY = 1002 # Int32 Int32*
SQLITE_DBCONFIG_ENABLE_TRIGGER = 1003 # Int32 Int32*
SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER = 1004 # Int32 Int32*
SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION = 1005 # Int32 Int32*
SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE = 1006 # Int32 Int32*
SQLITE_DBCONFIG_ENABLE_QPSG = 1007 # Int32 Int32*
SQLITE_DBCONFIG_TRIGGER_EQP = 1008 # Int32 Int32*
SQLITE_DBCONFIG_RESET_DATABASE = 1009 # Int32 Int32*
SQLITE_DBCONFIG_DEFENSIVE = 1010 # Int32 Int32*
SQLITE_DBCONFIG_WRITABLE_SCHEMA = 1011 # Int32 Int32*
SQLITE_DBCONFIG_LEGACY_ALTER_TABLE = 1012 # Int32 Int32*
SQLITE_DBCONFIG_DQS_DML = 1013 # Int32 Int32*
SQLITE_DBCONFIG_DQS_DDL = 1014 # Int32 Int32*
SQLITE_DBCONFIG_ENABLE_VIEW = 1015 # Int32 Int32*
SQLITE_DBCONFIG_LEGACY_FILE_FORMAT = 1016 # Int32 Int32*
SQLITE_DBCONFIG_TRUSTED_SCHEMA = 1017 # Int32 Int32*
end
alias Callback = (Void*, Int32, UInt8**, UInt8**) -> Int32 alias Callback = (Void*, Int32, UInt8**, UInt8**) -> Int32
alias FuncCallback = (SQLite3Context, Int32, SQLite3Value*) -> Void alias FuncCallback = (SQLite3Context, Int32, SQLite3Value*) -> Void
fun open_v2 = sqlite3_open_v2(filename : UInt8*, db : SQLite3*, flags : ::SQLite3::Flag, zVfs : UInt8*) : Int32 fun open_v2 = sqlite3_open_v2(filename : UInt8*, db : SQLite3*, flags : ::SQLite3::Flag, zVfs : UInt8*) : Int32
fun db_config = sqlite3_db_config(db : SQLite3, op : Option, ...) : Int32
fun load_extension = sqlite3_load_extension(db : SQLite3, zFile : UInt8*, zProc : UInt8*, pzErrMsg : UInt8**) : Code
fun errcode = sqlite3_errcode(SQLite3) : Int32 fun errcode = sqlite3_errcode(SQLite3) : Int32
fun errmsg = sqlite3_errmsg(SQLite3) : UInt8* fun errmsg = sqlite3_errmsg(SQLite3) : UInt8*