Skip to content
This repository was archived by the owner on Mar 19, 2021. It is now read-only.

Commit 168c768

Browse files
the-kennyConnorRigby
authored andcommitted
Add Sqlitex.with_transaction and use it in Sqlitex.Server
1 parent ec34b3a commit 168c768

File tree

3 files changed

+56
-28
lines changed

3 files changed

+56
-28
lines changed

lib/sqlitex.ex

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,33 @@ defmodule Sqlitex do
150150
exec(db, stmt, call_opts)
151151
end
152152

153+
@spec with_transaction(Sqlitex.connection, (Sqlitex.connection -> any()), Keyword.t) :: any
154+
def with_transaction(db, fun, opts \\ []) do
155+
with :ok <- exec(db, "begin", opts),
156+
{:ok, result} <- apply_rescueing(fun, [db]),
157+
:ok <- exec(db, "commit", opts)
158+
do
159+
{:ok, result}
160+
else
161+
err ->
162+
:ok = exec(db, "rollback")
163+
err
164+
end
165+
end
166+
153167
if Version.compare(System.version, "1.3.0") == :lt do
154168
defp string_to_charlist(string), do: String.to_char_list(string)
155169
else
156170
defp string_to_charlist(string), do: String.to_charlist(string)
157171
end
172+
173+
## Private Helpers
174+
175+
defp apply_rescueing(fun, args) do
176+
try do
177+
{:ok, apply(fun, args)}
178+
rescue
179+
error -> {:error, error}
180+
end
181+
end
158182
end

lib/sqlitex/server.ex

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -120,16 +120,8 @@ defmodule Sqlitex.Server do
120120
end
121121

122122
def handle_call({:with_transaction, fun}, _from, {db, stmt_cache, timeout}) do
123-
with :ok <- Sqlitex.exec(db, "begin"),
124-
{:ok, result} <- apply_rescueing(fun, [db]),
125-
:ok <- Sqlitex.exec(db, "commit")
126-
do
127-
{:reply, result, {db, stmt_cache, timeout}}
128-
else
129-
err ->
130-
:ok = Sqlitex.exec(db, "rollback")
131-
{:reply, err, {db, stmt_cache, timeout}}
132-
end
123+
result = Sqlitex.with_transaction(db, fun)
124+
{:reply, result, {db, stmt_cache, timeout}}
133125
end
134126

135127
def handle_cast(:stop, {db, stmt_cache, config}) do
@@ -209,20 +201,13 @@ defmodule Sqlitex.Server do
209201
Runs `fun` inside a transaction. If `fun` returns without raising an exception,
210202
the transaction will be commited via `commit`. Otherwise, `rollback` will be called.
211203
212-
Statements are executed in the server process and are guaranteed to get executed
213-
sequentially without any interleaved statements from other processes.
214-
215-
It's important to use `Sqlitex.exec`, `Sqlitex.query`, ... instead of
216-
`Sqlitex.Server.exec`, ... inside the transaction as the `db` arg to `fun` is of
217-
type `Sqlitex.connection`.
218-
219204
## Examples
220-
iex> {:ok, s} = Sqlitex.Server.start_link(':memory:')
221-
iex> Sqlitex.Server.with_transaction(s, fn(db) ->
205+
iex> {:ok, db} = Sqlitex.open(":memory:")
206+
iex> Sqlitex.with_transaction(db, fn(db) ->
222207
...> Sqlitex.exec(db, "create table foo(id integer)")
223208
...> Sqlitex.exec(db, "insert into foo (id) values(42)")
224209
...> end)
225-
iex> Sqlitex.Server.query(s, "select * from foo")
210+
iex> Sqlitex.query(db, "select * from foo")
226211
{:ok, [[{:id, 42}]]}
227212
"""
228213
@spec with_transaction(pid(), (Sqlitex.connection -> any()), Keyword.t) :: any
@@ -254,12 +239,4 @@ defmodule Sqlitex.Server do
254239
end
255240

256241
defp timeout(kwopts), do: Keyword.get(kwopts, :timeout, 5000)
257-
258-
defp apply_rescueing(fun, args) do
259-
try do
260-
{:ok, apply(fun, args)}
261-
rescue
262-
error -> {:error, error}
263-
end
264-
end
265242
end

test/sqlitex_test.exs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,4 +250,31 @@ defmodule Sqlitex.Test do
250250
assert row[:b] == nil
251251
assert row[:c] == nil
252252
end
253+
254+
test "with_transaction commit" do
255+
{:ok, db} = Sqlitex.open(":memory:")
256+
:ok = Sqlitex.exec(db, "create table foo(id integer)")
257+
258+
Sqlitex.with_transaction(db, fn db ->
259+
:ok = Sqlitex.exec(db, "insert into foo (id) values (42)")
260+
end)
261+
262+
assert Sqlitex.query(db, "select * from foo") == {:ok, [[{:id, 42}]]}
263+
end
264+
265+
test "with_transaction rollback" do
266+
{:ok, db} = Sqlitex.open(':memory:')
267+
:ok = Sqlitex.exec(db, "create table foo(id integer)")
268+
269+
try do
270+
Sqlitex.with_transaction(db, fn db ->
271+
:ok = Sqlitex.exec(db, "insert into foo (id) values (42)")
272+
raise "Error to roll back transaction"
273+
end)
274+
rescue
275+
_ -> nil
276+
end
277+
278+
assert Sqlitex.query(db, "select * from foo") == {:ok, []}
279+
end
253280
end

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy