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

Commit 4912a73

Browse files
committed
Add prepared statement cache to Sqlitex.Server.
1 parent ca2dfbe commit 4912a73

File tree

1 file changed

+53
-16
lines changed

1 file changed

+53
-16
lines changed

lib/sqlitex/server.ex

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ defmodule Sqlitex.Server do
1717
{:ok, [%{a: 1, b: 1}]}
1818
iex> Sqlitex.Server.query_rows(:example, "SELECT * FROM t ORDER BY a LIMIT 2")
1919
{:ok, %{rows: [[1, 1], [2, 2]], columns: [:a, :b], types: [:INTEGER, :INTEGER]}}
20+
iex> Sqlitex.Server.prepare(:example, "SELECT * FROM t")
21+
{:ok, %{columns: [:a, :b], types: [:INTEGER, :INTEGER]}}
2022
iex> Sqlitex.Server.stop(:example)
2123
:ok
2224
iex> :timer.sleep(10) # wait for the process to exit asynchronously
@@ -39,44 +41,75 @@ defmodule Sqlitex.Server do
3941

4042
use GenServer
4143

44+
alias Sqlitex.Statement
45+
alias Sqlitex.Server.StatementCache, as: Cache
46+
4247
def start_link(db_path, opts \\ []) do
43-
GenServer.start_link(__MODULE__, db_path, opts)
48+
stmt_cache_size = Keyword.get(opts, :stmt_cache_size, 20)
49+
GenServer.start_link(__MODULE__, {db_path, stmt_cache_size}, opts)
4450
end
4551

4652
## GenServer callbacks
4753

48-
def init(db_path) do
54+
def init({db_path, stmt_cache_size})
55+
when is_integer(stmt_cache_size) and stmt_cache_size > 0
56+
do
4957
case Sqlitex.open(db_path) do
50-
{:ok, db} -> {:ok, db}
58+
{:ok, db} -> {:ok, {db, __MODULE__.StatementCache.new(db, stmt_cache_size)}}
5159
{:error, reason} -> {:stop, reason}
5260
end
5361
end
5462

55-
def handle_call({:exec, sql}, _from, db) do
63+
def handle_call({:exec, sql}, _from, {db, stmt_cache}) do
5664
result = Sqlitex.exec(db, sql)
57-
{:reply, result, db}
65+
{:reply, result, {db, stmt_cache}}
66+
end
67+
68+
def handle_call({:query, sql, opts}, _from, {db, stmt_cache}) do
69+
with {%Cache{} = new_cache, stmt} <- Cache.prepare(stmt_cache, sql),
70+
{:ok, stmt} <- Statement.bind_values(stmt, Keyword.get(opts, :bind, [])),
71+
{:ok, rows} <- Statement.fetch_all(stmt, Keyword.get(opts, :into, []))
72+
do
73+
{:reply, {:ok, rows}, {db, new_cache}}
74+
else
75+
err -> {:reply, err, {db, stmt_cache}}
76+
end
5877
end
5978

60-
def handle_call({:query, sql, opts}, _from, db) do
61-
rows = Sqlitex.query(db, sql, opts)
62-
{:reply, rows, db}
79+
def handle_call({:query_rows, sql, opts}, _from, {db, stmt_cache}) do
80+
with {%Cache{} = new_cache, stmt} <- Cache.prepare(stmt_cache, sql),
81+
{:ok, stmt} <- Statement.bind_values(stmt, Keyword.get(opts, :bind, [])),
82+
{:ok, rows} <- Statement.fetch_all(stmt, :raw_list)
83+
do
84+
{:reply,
85+
{:ok, %{rows: rows, columns: stmt.column_names, types: stmt.column_types}},
86+
{db, new_cache}}
87+
else
88+
err -> {:reply, err, {db, stmt_cache}}
89+
end
6390
end
6491

65-
def handle_call({:query_rows, sql, opts}, _from, db) do
66-
rows = Sqlitex.query_rows(db, sql, opts)
67-
{:reply, rows, db}
92+
def handle_call({:prepare, sql}, _from, {db, stmt_cache}) do
93+
with {%Cache{} = new_cache, stmt} <- Cache.prepare(stmt_cache, sql)
94+
do
95+
{:reply,
96+
{:ok, %{columns: stmt.column_names, types: stmt.column_types}},
97+
{db, new_cache}}
98+
else
99+
err -> {:reply, err, {db, stmt_cache}}
100+
end
68101
end
69102

70-
def handle_call({:create_table, name, table_opts, cols}, _from, db) do
103+
def handle_call({:create_table, name, table_opts, cols}, _from, {db, stmt_cache}) do
71104
result = Sqlitex.create_table(db, name, table_opts, cols)
72-
{:reply, result, db}
105+
{:reply, result, {db, stmt_cache}}
73106
end
74107

75-
def handle_cast(:stop, db) do
76-
{:stop, :normal, db}
108+
def handle_cast(:stop, {db, stmt_cache}) do
109+
{:stop, :normal, {db, stmt_cache}}
77110
end
78111

79-
def terminate(_reason, db) do
112+
def terminate(_reason, {db, _stmt_cache}) do
80113
Sqlitex.close(db)
81114
:ok
82115
end
@@ -95,6 +128,10 @@ defmodule Sqlitex.Server do
95128
GenServer.call(pid, {:query_rows, sql, opts}, timeout(opts))
96129
end
97130

131+
def prepare(pid, sql, opts \\ []) do
132+
GenServer.call(pid, {:prepare, sql}, timeout(opts))
133+
end
134+
98135
def create_table(pid, name, table_opts \\ [], cols) do
99136
GenServer.call(pid, {:create_table, name, table_opts, cols})
100137
end

0 commit comments

Comments
 (0)