Skip to content

feat: enable load_extensions config for connections #247

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 28, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 53 additions & 1 deletion lib/exqlite/connection.ex
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ defmodule Exqlite.Connection do
alias Exqlite.Query
alias Exqlite.Result
alias Exqlite.Sqlite3
require Logger

defstruct [
:db,
Expand Down Expand Up @@ -128,6 +129,32 @@ defmodule Exqlite.Connection do
* `:soft_heap_limit` - The size limit in bytes for the heap limit.
* `:hard_heap_limit` - The size limit in bytes for the heap.
* `:custom_pragmas` - A list of custom pragmas to set on the connection, for example to configure extensions.
* `:load_extensions` - A list of paths identifying extensions to load. Defaults to `[]`.
The provided list will be merged with the global extensions list, set on `:exqlite, :load_extensions`.
Be aware that the path should handle pointing to a library compiled for the current architecture.
Example configuration:

```
arch_dir =
System.cmd("uname", ["-sm"])
|> elem(0)
|> String.trim()
|> String.replace(" ", "-")
|> String.downcase() # => "darwin-arm64"

config :myapp, arch_dir: arch_dir

# global
config :exqlite, load_extensions: [ "./priv/sqlite/\#{arch_dir}/rotate" ]

# per connection in a Phoenix app
config :myapp, Myapp.Repo,
database: "path/to/db",
load_extensions: [
"./priv/sqlite/\#{arch_dir}/vector0",
"./priv/sqlite/\#{arch_dir}/vss0"
]
```

For more information about the options above, see [sqlite documentation][1]

Expand Down Expand Up @@ -460,6 +487,30 @@ defmodule Exqlite.Connection do
set_pragma(db, "busy_timeout", Pragma.busy_timeout(options))
end

defp load_extensions(db, options) do
global_extensions = Application.get_env(:exqlite, :load_extensions, [])

extensions =
Keyword.get(options, :load_extensions, [])
|> Enum.concat(global_extensions)
|> Enum.uniq()

do_load_extensions(db, extensions)
end

defp do_load_extensions(_db, []), do: :ok

defp do_load_extensions(db, extensions) do
Sqlite3.enable_load_extension(db, true)

Enum.each(extensions, fn extension ->
Logger.debug(fn -> "Exqlite: loading extension `#{extension}`" end)
Sqlite3.execute(db, "SELECT load_extension('#{extension}')")
end)

Sqlite3.enable_load_extension(db, false)
end

defp do_connect(database, options) do
with {:ok, directory} <- resolve_directory(database),
:ok <- mkdir_p(directory),
Expand All @@ -480,7 +531,8 @@ defmodule Exqlite.Connection do
:ok <- set_busy_timeout(db, options),
:ok <- set_journal_size_limit(db, options),
:ok <- set_soft_heap_limit(db, options),
:ok <- set_hard_heap_limit(db, options) do
:ok <- set_hard_heap_limit(db, options),
:ok <- load_extensions(db, options) do
state = %__MODULE__{
db: db,
directory: directory,
Expand Down