Skip to content

Commit ce5fb0e

Browse files
committed
fix: address sqlite open mode review feedback
1 parent 85c76ec commit ce5fb0e

3 files changed

Lines changed: 25 additions & 28 deletions

File tree

lib/exqlite/connection.ex

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,11 @@ defmodule Exqlite.Connection do
9898
* `:default_transaction_mode` - one of `deferred` (default), `immediate`,
9999
or `exclusive`. If a mode is not specified in a call to `Repo.transaction/2`,
100100
this will be the default transaction mode.
101-
* `:mode` - use `:readwrite` to open the database for reading and writing
102-
, `:readonly` to open it in read-only mode or `[:readonly | :readwrite, :nomutex]`
103-
to open it with no mutex mode. `:readwrite` will also create
104-
the database if it doesn't already exist. Defaults to `:readwrite`.
105-
Note: [:readwrite, :nomutex] is not recommended.
101+
* `:mode` - controls the sqlite3_open_v2 flags. Defaults to
102+
`[:readwrite, :create]` (read/write + create if needed). Use
103+
`:readwrite` for read/write without create, `:readonly` for read-only, or
104+
a list such as `[:readwrite, :create]` or `[:readonly, :nomutex]`.
105+
Note: `[:readwrite, :nomutex]` is not recommended.
106106
* `:journal_mode` - Sets the journal mode for the sqlite connection. Can be
107107
one of the following `:delete`, `:truncate`, `:persist`, `:memory`,
108108
`:wal`, or `:off`. Defaults to `:delete`. It is recommended that you use

lib/exqlite/sqlite3.ex

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ defmodule Exqlite.Sqlite3 do
2020
@type reason() :: atom() | String.t()
2121
@type row() :: list()
2222
@type open_mode :: :readwrite | :readonly | :nomutex | :create
23-
@type open_opt :: {:mode, :readwrite | :readonly | [open_mode()]}
23+
@type open_opt :: {:mode, :readwrite | :readonly | :create | [open_mode()]}
2424

2525
@doc """
2626
Opens a new sqlite database at the Path provided.
@@ -31,25 +31,26 @@ defmodule Exqlite.Sqlite3 do
3131
3232
* `:mode` - controls the flags for sqlite3_open_v2 (see
3333
https://www.sqlite.org/c3ref/c_open_autoproxy.html). Defaults to
34-
`:readwrite` (opens for reading and writing and creates the file if it
35-
does not exist — this atom form is preserved for backward compatibility).
34+
`[:readwrite, :create]` (opens for reading and writing and creates the
35+
file if it does not exist).
3636
37-
Finer-grained control (to align with sqlite3_open_v2 flags, see
38-
https://github.com/elixir-sqlite/exqlite/issues/347):
37+
Single modes are permitted:
38+
- `:readwrite` - read/write to the database. Does not create the database
39+
if it is not present. Use in combination with `:create` to create the
40+
database if it does not exist.
41+
- `:readonly` - read-only (file must exist).
42+
- `:create` - creates the database if it does not exist.
3943
40-
- `:readwrite` (atom) — read/write + create if needed (compat default).
41-
- `:readonly` — read-only (file must exist).
42-
- Lists (recommended for new code):
43-
- `[:readwrite]` — read/write only; will *not* create the file.
44-
- `[:readwrite, :create]` — read/write + create if needed.
45-
- `[:readonly, :nomutex]`, `[:readwrite, :nomutex]`, `[:create]` (in lists), etc.
46-
- `:create` is now a valid list element to request the CREATE flag.
44+
Combinations are permitted:
45+
- `[:readwrite, :create]` - read/write + create if needed. This is the
46+
default if not specified.
47+
- `[:readonly, :nomutex]`
4748
4849
Note: `[:readwrite, :nomutex]` is not recommended.
4950
"""
5051
@spec open(String.t(), [open_opt()]) :: {:ok, db()} | {:error, reason()}
5152
def open(path, opts \\ []) do
52-
mode = Keyword.get(opts, :mode, :readwrite)
53+
mode = opts[:mode] || [:readwrite, :create]
5354
Sqlite3NIF.open(path, flags_from_mode(mode))
5455
end
5556

@@ -58,13 +59,8 @@ defmodule Exqlite.Sqlite3 do
5859
"expected mode to be `:readwrite` or `:readonly`, can't use a single :nomutex mode"
5960
end
6061

61-
# Atom `:readwrite` keeps the historical "also create the file" behavior
62-
# for backward compatibility (most existing code and the default rely on it).
63-
defp flags_from_mode(:readwrite),
64-
do: do_flags_from_mode([:readwrite, :create], [])
65-
66-
defp flags_from_mode(:readonly),
67-
do: do_flags_from_mode([:readonly], [])
62+
defp flags_from_mode(mode) when mode in [:readwrite, :readonly, :create],
63+
do: do_flags_from_mode(List.wrap(mode), [])
6864

6965
defp flags_from_mode([_ | _] = modes),
7066
do: do_flags_from_mode(modes, [])

test/exqlite/sqlite3_test.exs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,14 @@ defmodule Exqlite.Sqlite3Test do
109109
end
110110
end
111111

112-
test "opens with list [:readwrite] (no implicit create) vs default atom (creates)" do
112+
test "opens with default create but explicit readwrite does not create" do
113113
{:ok, path} = Temp.path()
114114

115-
# Pure :readwrite list should not create the file
115+
# Pure readwrite modes should not create the file.
116+
assert {:error, _reason} = Sqlite3.open(path, mode: :readwrite)
116117
assert {:error, _reason} = Sqlite3.open(path, mode: [:readwrite])
117118

118-
# Atom default (and [:readwrite, :create]) still create for compat
119+
# The default (and [:readwrite, :create]) still creates.
119120
{:ok, conn} = Sqlite3.open(path)
120121
:ok = Sqlite3.close(conn)
121122
assert File.exists?(path)

0 commit comments

Comments
 (0)