Skip to content

Commit 78e5ca3

Browse files
authored
Allow setting custom pragmas (#229)
This allows for someone to set any PRAGMA keys and values, next to the most common ones. See the documentation for a full list: https://www2.sqlite.org/draft/pragma.html One use-case is to set the `cipher_compatibility` PRAGMA which is supported by the SQLCipher extension: https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_compatibility
1 parent bf5d81b commit 78e5ca3

2 files changed

Lines changed: 40 additions & 0 deletions

File tree

lib/exqlite/connection.ex

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ defmodule Exqlite.Connection do
7171
| {:soft_heap_limit, integer()}
7272
| {:hard_heap_limit, integer()}
7373
| {:key, String.t()}
74+
| {:custom_pragmas, [{keyword(), integer() | boolean() | String.t()}]}
7475

7576
@impl true
7677
@doc """
@@ -126,6 +127,7 @@ defmodule Exqlite.Connection do
126127
* `:journal_size_limit` - The size limit in bytes of the journal.
127128
* `:soft_heap_limit` - The size limit in bytes for the heap limit.
128129
* `:hard_heap_limit` - The size limit in bytes for the heap.
130+
* `:custom_pragmas` - A list of custom pragmas to set on the connection, for example to configure extensions.
129131
130132
For more information about the options above, see [sqlite documentation][1]
131133
@@ -372,6 +374,25 @@ defmodule Exqlite.Connection do
372374
end
373375
end
374376

377+
defp set_custom_pragmas(db, options) do
378+
# we can't use maybe_set_pragma because some pragmas
379+
# are required to be set before the database is e.g. decrypted.
380+
case Keyword.fetch(options, :custom_pragmas) do
381+
{:ok, list} -> do_set_custom_pragmas(db, list)
382+
_ -> :ok
383+
end
384+
end
385+
386+
defp do_set_custom_pragmas(db, list) do
387+
list
388+
|> Enum.reduce_while(:ok, fn {key, value}, :ok ->
389+
case set_pragma(db, key, value) do
390+
:ok -> {:cont, :ok}
391+
{:error, _reason} -> {:halt, :error}
392+
end
393+
end)
394+
end
395+
375396
defp set_pragma_if_present(_db, _pragma, nil), do: :ok
376397
defp set_pragma_if_present(db, pragma, value), do: set_pragma(db, pragma, value)
377398

@@ -444,6 +465,7 @@ defmodule Exqlite.Connection do
444465
:ok <- mkdir_p(directory),
445466
{:ok, db} <- Sqlite3.open(database, options),
446467
:ok <- set_key(db, options),
468+
:ok <- set_custom_pragmas(db, options),
447469
:ok <- set_journal_mode(db, options),
448470
:ok <- set_temp_store(db, options),
449471
:ok <- set_synchronous(db, options),

test/exqlite/connection_test.exs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,24 @@ defmodule Exqlite.ConnectionTest do
8383
File.rm(path)
8484
end
8585

86+
test "setting custom_pragmas" do
87+
path = Temp.path!()
88+
89+
{:ok, state} =
90+
Connection.connect(
91+
database: path,
92+
custom_pragmas: [
93+
checkpoint_fullfsync: 0
94+
]
95+
)
96+
97+
assert state.db
98+
99+
assert {:ok, 0} = get_pragma(state.db, :checkpoint_fullfsync)
100+
101+
File.rm(path)
102+
end
103+
86104
test "setting journal_size_limit" do
87105
path = Temp.path!()
88106
size_limit = 20 * 1024 * 1024

0 commit comments

Comments
 (0)