@@ -47,66 +47,73 @@ defmodule Sqlitex.Server do
47
47
48
48
alias Sqlitex.Statement
49
49
alias Sqlitex.Server.StatementCache , as: Cache
50
+ alias Sqlitex.Config
50
51
51
52
@ doc """
52
53
Starts a SQLite Server (GenServer) instance.
53
54
54
55
In addition to the options that are typically provided to `GenServer.start_link/3`,
55
- you can also specify `stmt_cache_size: (positive_integer)` to override the default
56
- limit (20) of statements that are cached when calling `prepare/3`.
56
+ you can also specify:
57
+
58
+ - `stmt_cache_size: (positive_integer)` to override the default limit (20) of statements
59
+ that are cached when calling `prepare/3`.
60
+ - `db_timeout: (positive_integer)` to override `:esqlite3`'s default timeout of 5000 ms for
61
+ interactions with the database. This can also be set in `config.exs` as
62
+ `config :sqlitex, esqlite3_timeout: 5_000`.
57
63
"""
58
64
def start_link ( db_path , opts \\ [ ] ) do
59
65
stmt_cache_size = Keyword . get ( opts , :stmt_cache_size , 20 )
60
- GenServer . start_link ( __MODULE__ , { db_path , stmt_cache_size } , opts )
66
+ timeout = Keyword . get ( opts , :db_timeout , Config . esqlite3_timeout ( ) )
67
+ GenServer . start_link ( __MODULE__ , { db_path , stmt_cache_size , timeout } , opts )
61
68
end
62
69
63
70
## GenServer callbacks
64
71
65
- def init ( { db_path , stmt_cache_size } )
72
+ def init ( { db_path , stmt_cache_size , timeout } )
66
73
when is_integer ( stmt_cache_size ) and stmt_cache_size > 0
67
74
do
68
- case Sqlitex . open ( db_path ) do
69
- { :ok , db } -> { :ok , { db , __MODULE__ . StatementCache . new ( db , stmt_cache_size ) } }
75
+ case Sqlitex . open ( db_path , [ db_timeout: timeout ] ) do
76
+ { :ok , db } -> { :ok , { db , __MODULE__ . StatementCache . new ( db , stmt_cache_size ) , timeout } }
70
77
{ :error , reason } -> { :stop , reason }
71
78
end
72
79
end
73
80
74
- def handle_call ( { :exec , sql } , _from , { db , stmt_cache } ) do
75
- result = Sqlitex . exec ( db , sql )
76
- { :reply , result , { db , stmt_cache } }
81
+ def handle_call ( { :exec , sql } , _from , { db , stmt_cache , timeout } ) do
82
+ result = Sqlitex . exec ( db , sql , [ db_timeout: timeout ] )
83
+ { :reply , result , { db , stmt_cache , timeout } }
77
84
end
78
85
79
- def handle_call ( { :query , sql , opts } , _from , { db , stmt_cache } ) do
80
- case query_impl ( sql , opts , stmt_cache ) do
81
- { :ok , result , new_cache } -> { :reply , { :ok , result } , { db , new_cache } }
82
- err -> { :reply , err , { db , stmt_cache } }
86
+ def handle_call ( { :query , sql , opts } , _from , { db , stmt_cache , timeout } ) do
87
+ case query_impl ( sql , opts , stmt_cache , timeout ) do
88
+ { :ok , result , new_cache } -> { :reply , { :ok , result } , { db , new_cache , timeout } }
89
+ err -> { :reply , err , { db , stmt_cache , timeout } }
83
90
end
84
91
end
85
92
86
- def handle_call ( { :query_rows , sql , opts } , _from , { db , stmt_cache } ) do
87
- case query_rows_impl ( sql , opts , stmt_cache ) do
88
- { :ok , result , new_cache } -> { :reply , { :ok , result } , { db , new_cache } }
89
- err -> { :reply , err , { db , stmt_cache } }
93
+ def handle_call ( { :query_rows , sql , opts } , _from , { db , stmt_cache , timeout } ) do
94
+ case query_rows_impl ( sql , opts , stmt_cache , timeout ) do
95
+ { :ok , result , new_cache } -> { :reply , { :ok , result } , { db , new_cache , timeout } }
96
+ err -> { :reply , err , { db , stmt_cache , timeout } }
90
97
end
91
98
end
92
99
93
- def handle_call ( { :prepare , sql } , _from , { db , stmt_cache } ) do
94
- case prepare_impl ( sql , stmt_cache ) do
95
- { :ok , result , new_cache } -> { :reply , { :ok , result } , { db , new_cache } }
96
- err -> { :reply , err , { db , stmt_cache } }
100
+ def handle_call ( { :prepare , sql } , _from , { db , stmt_cache , timeout } ) do
101
+ case prepare_impl ( sql , stmt_cache , timeout ) do
102
+ { :ok , result , new_cache } -> { :reply , { :ok , result } , { db , new_cache , timeout } }
103
+ err -> { :reply , err , { db , stmt_cache , timeout } }
97
104
end
98
105
end
99
106
100
- def handle_call ( { :create_table , name , table_opts , cols } , _from , { db , stmt_cache } ) do
101
- result = Sqlitex . create_table ( db , name , table_opts , cols )
102
- { :reply , result , { db , stmt_cache } }
107
+ def handle_call ( { :create_table , name , table_opts , cols } , _from , { db , stmt_cache , timeout } ) do
108
+ result = Sqlitex . create_table ( db , name , table_opts , cols , [ db_timeout: timeout ] )
109
+ { :reply , result , { db , stmt_cache , timeout } }
103
110
end
104
111
105
- def handle_cast ( :stop , { db , stmt_cache } ) do
106
- { :stop , :normal , { db , stmt_cache } }
112
+ def handle_cast ( :stop , { db , stmt_cache , timeout } ) do
113
+ { :stop , :normal , { db , stmt_cache , timeout } }
107
114
end
108
115
109
- def terminate ( _reason , { db , _stmt_cache } ) do
116
+ def terminate ( _reason , { db , _stmt_cache , _timeout } ) do
110
117
Sqlitex . close ( db )
111
118
:ok
112
119
end
@@ -157,24 +164,28 @@ defmodule Sqlitex.Server do
157
164
158
165
## Helpers
159
166
160
- defp query_impl ( sql , opts , stmt_cache ) do
161
- with { % Cache { } = new_cache , stmt } <- Cache . prepare ( stmt_cache , sql ) ,
162
- { :ok , stmt } <- Statement . bind_values ( stmt , Keyword . get ( opts , :bind , [ ] ) ) ,
167
+ defp query_impl ( sql , opts , stmt_cache , db_timeout ) do
168
+ db_opts = [ db_timeout: db_timeout ]
169
+
170
+ with { % Cache { } = new_cache , stmt } <- Cache . prepare ( stmt_cache , sql , db_opts ) ,
171
+ { :ok , stmt } <- Statement . bind_values ( stmt , Keyword . get ( opts , :bind , [ ] ) , db_opts ) ,
163
172
{ :ok , rows } <- Statement . fetch_all ( stmt , Keyword . get ( opts , :into , [ ] ) ) ,
164
173
do: { :ok , rows , new_cache }
165
174
end
166
175
167
- defp query_rows_impl ( sql , opts , stmt_cache ) do
168
- with { % Cache { } = new_cache , stmt } <- Cache . prepare ( stmt_cache , sql ) ,
169
- { :ok , stmt } <- Statement . bind_values ( stmt , Keyword . get ( opts , :bind , [ ] ) ) ,
176
+ defp query_rows_impl ( sql , opts , stmt_cache , db_timeout ) do
177
+ db_opts = [ db_timeout: db_timeout ]
178
+
179
+ with { % Cache { } = new_cache , stmt } <- Cache . prepare ( stmt_cache , sql , db_opts ) ,
180
+ { :ok , stmt } <- Statement . bind_values ( stmt , Keyword . get ( opts , :bind , [ ] ) , db_opts ) ,
170
181
{ :ok , rows } <- Statement . fetch_all ( stmt , :raw_list ) ,
171
182
do: { :ok ,
172
183
% { rows: rows , columns: stmt . column_names , types: stmt . column_types } ,
173
184
new_cache }
174
185
end
175
186
176
- defp prepare_impl ( sql , stmt_cache ) do
177
- with { % Cache { } = new_cache , stmt } <- Cache . prepare ( stmt_cache , sql ) ,
187
+ defp prepare_impl ( sql , stmt_cache , db_timeout ) do
188
+ with { % Cache { } = new_cache , stmt } <- Cache . prepare ( stmt_cache , sql , [ db_timeout: db_timeout ] ) ,
178
189
do: { :ok , % { columns: stmt . column_names , types: stmt . column_types } , new_cache }
179
190
end
180
191
0 commit comments