@@ -4,6 +4,8 @@ defmodule Sqlite.Ecto.Query do
4
4
import Sqlite.Ecto.Transaction , only: [ with_savepoint: 2 ]
5
5
import Sqlite.Ecto.Util
6
6
7
+ alias Sqlite.Ecto.Result
8
+
7
9
# ALTER TABLE queries:
8
10
def query ( pid , << "ALTER TABLE " , _ :: binary >> = sql , params , opts ) do
9
11
sql
@@ -208,56 +210,30 @@ defmodule Sqlite.Ecto.Query do
208
210
# busy error means another process is writing to the database; try again
209
211
{ :error , { :busy , _ } } -> do_query ( pid , sql , params , opts )
210
212
{ :error , msg } -> { :error , Sqlite.Ecto.Error . exception ( msg ) }
211
- { :ok , rows } when is_list ( rows ) -> query_result ( pid , sql , rows )
213
+ { :ok , rows } when is_list ( rows ) -> query_result ( pid , sql , rows , opts )
212
214
end
213
215
end
214
216
215
217
# If this is an INSERT, UPDATE, or DELETE, then return the number of changed
216
218
# rows. Otherwise (e.g. for SELECT) return the queried column values.
217
- defp query_result ( pid , << "INSERT " , _ :: binary >> , [ ] ) , do: changes_result ( pid )
218
- defp query_result ( pid , << "UPDATE " , _ :: binary >> , [ ] ) , do: changes_result ( pid )
219
- defp query_result ( pid , << "DELETE " , _ :: binary >> , [ ] ) , do: changes_result ( pid )
220
- defp query_result ( _pid , _sql , rows ) do
221
- rows = Enum . map ( rows , fn row ->
222
- row
223
- |> cast_any_datetimes
224
- |> Keyword . values
225
- |> Enum . map ( fn
226
- { :blob , binary } -> binary
227
- other -> other
228
- end )
229
- end )
230
- { :ok , % { rows: rows , num_rows: length ( rows ) } }
219
+ defp query_result ( pid , << "INSERT " , _ :: binary >> , [ ] , _opts ) , do: changes_result ( pid )
220
+ defp query_result ( pid , << "UPDATE " , _ :: binary >> , [ ] , _opts ) , do: changes_result ( pid )
221
+ defp query_result ( pid , << "DELETE " , _ :: binary >> , [ ] , _opts ) , do: changes_result ( pid )
222
+ defp query_result ( _pid , _sql , rows , opts ) do
223
+ { :ok , decode ( rows , Keyword . fetch ( opts , :decode ) ) }
231
224
end
232
225
233
- defp changes_result ( pid ) do
234
- { :ok , [ [ "changes()": count ] ] } = Sqlitex.Server . query ( pid , "SELECT changes()" )
235
- { :ok , % { rows: nil , num_rows: count } }
236
- end
237
-
238
- # HACK: We have to do a special conversion if the user is trying to cast to
239
- # a DATETIME type. Sqlitex cannot determine that the type of the cast is a
240
- # datetime value because datetime defaults to an integer type in SQLite.
241
- # Thus, we cast the value to a TEXT_DATETIME pseudo-type to preserve the
242
- # datetime string. Then when we get here, we convert the string to an Ecto
243
- # datetime tuple if it looks like a cast was attempted.
244
- defp cast_any_datetimes ( row ) do
245
- Enum . map row , fn { key , value } ->
246
- str = Atom . to_string ( key )
247
- if String . contains? ( str , "CAST (" ) && String . contains? ( str , "TEXT_DATE" ) do
248
- { key , string_to_datetime ( value ) }
249
- else
250
- { key , value }
251
- end
252
- end
226
+ defp decode ( rows , { :ok , :manual } ) do
227
+ % Result { rows: rows , num_rows: length ( rows ) , decoder: :deferred }
253
228
end
254
-
255
- defp string_to_datetime ( << yr :: binary - size ( 4 ) , "-" , mo :: binary - size ( 2 ) , "-" , da :: binary - size ( 2 ) >> ) do
256
- { String . to_integer ( yr ) , String . to_integer ( mo ) , String . to_integer ( da ) }
229
+ defp decode ( rows , _ ) do # not specified or :auto
230
+ % Result { rows: rows , num_rows: length ( rows ) , decoder: :deferred }
231
+ |> Result . decode
257
232
end
258
- defp string_to_datetime ( str ) do
259
- << yr :: binary - size ( 4 ) , "-" , mo :: binary - size ( 2 ) , "-" , da :: binary - size ( 2 ) , " " , hr :: binary - size ( 2 ) , ":" , mi :: binary - size ( 2 ) , ":" , se :: binary - size ( 2 ) , "." , fr :: binary - size ( 6 ) >> = str
260
- { { String . to_integer ( yr ) , String . to_integer ( mo ) , String . to_integer ( da ) } , { String . to_integer ( hr ) , String . to_integer ( mi ) , String . to_integer ( se ) , String . to_integer ( fr ) } }
233
+
234
+ defp changes_result ( pid ) do
235
+ { :ok , [ [ "changes()": count ] ] } = Sqlitex.Server . query ( pid , "SELECT changes()" )
236
+ { :ok , % Result { rows: nil , num_rows: count } }
261
237
end
262
238
263
239
# SQLite does not have a returning clause, but we append a pseudo one so
0 commit comments