@@ -28,6 +28,7 @@ defmodule Exqlite.Connection do
2828 alias Exqlite.Query
2929 alias Exqlite.Result
3030 alias Exqlite.Sqlite3
31+ require Logger
3132
3233 defstruct [
3334 :db ,
@@ -128,6 +129,32 @@ defmodule Exqlite.Connection do
128129 * `:soft_heap_limit` - The size limit in bytes for the heap limit.
129130 * `:hard_heap_limit` - The size limit in bytes for the heap.
130131 * `:custom_pragmas` - A list of custom pragmas to set on the connection, for example to configure extensions.
132+ * `:load_extensions` - A list of paths identifying extensions to load. Defaults to `[]`.
133+ The provided list will be merged with the global extensions list, set on `:exqlite, :load_extensions`.
134+ Be aware that the path should handle pointing to a library compiled for the current architecture.
135+ Example configuration:
136+
137+ ```
138+ arch_dir =
139+ System.cmd("uname", ["-sm"])
140+ |> elem(0)
141+ |> String.trim()
142+ |> String.replace(" ", "-")
143+ |> String.downcase() # => "darwin-arm64"
144+
145+ config :myapp, arch_dir: arch_dir
146+
147+ # global
148+ config :exqlite, load_extensions: [ "./priv/sqlite/\# {arch_dir}/rotate" ]
149+
150+ # per connection in a Phoenix app
151+ config :myapp, Myapp.Repo,
152+ database: "path/to/db",
153+ load_extensions: [
154+ "./priv/sqlite/\# {arch_dir}/vector0",
155+ "./priv/sqlite/\# {arch_dir}/vss0"
156+ ]
157+ ```
131158
132159 For more information about the options above, see [sqlite documentation][1]
133160
@@ -460,6 +487,30 @@ defmodule Exqlite.Connection do
460487 set_pragma ( db , "busy_timeout" , Pragma . busy_timeout ( options ) )
461488 end
462489
490+ defp load_extensions ( db , options ) do
491+ global_extensions = Application . get_env ( :exqlite , :load_extensions , [ ] )
492+
493+ extensions =
494+ Keyword . get ( options , :load_extensions , [ ] )
495+ |> Enum . concat ( global_extensions )
496+ |> Enum . uniq ( )
497+
498+ do_load_extensions ( db , extensions )
499+ end
500+
501+ defp do_load_extensions ( _db , [ ] ) , do: :ok
502+
503+ defp do_load_extensions ( db , extensions ) do
504+ Sqlite3 . enable_load_extension ( db , true )
505+
506+ Enum . each ( extensions , fn extension ->
507+ Logger . debug ( fn -> "Exqlite: loading extension `#{ extension } `" end )
508+ Sqlite3 . execute ( db , "SELECT load_extension('#{ extension } ')" )
509+ end )
510+
511+ Sqlite3 . enable_load_extension ( db , false )
512+ end
513+
463514 defp do_connect ( database , options ) do
464515 with { :ok , directory } <- resolve_directory ( database ) ,
465516 :ok <- mkdir_p ( directory ) ,
@@ -480,7 +531,8 @@ defmodule Exqlite.Connection do
480531 :ok <- set_busy_timeout ( db , options ) ,
481532 :ok <- set_journal_size_limit ( db , options ) ,
482533 :ok <- set_soft_heap_limit ( db , options ) ,
483- :ok <- set_hard_heap_limit ( db , options ) do
534+ :ok <- set_hard_heap_limit ( db , options ) ,
535+ :ok <- load_extensions ( db , options ) do
484536 state = % __MODULE__ {
485537 db: db ,
486538 directory: directory ,
0 commit comments