sqlc-hs-0.1.0.0: templates/internal.sqlite.hs.jinja
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE TypeFamilies #-}
module {{ moduleName }} (
Query(..),
Params,
Result,
-- * :execResult
ExecResult(..),
execResult,
-- * :exec
exec,
-- * :execrows
execRows,
-- * :execlastid
execLastId,
-- * :one
queryOne,
-- * :many
queryMany,
fold,
-- * Reexports
Database.SQLite.Simple.Connection,
Database.SQLite.Simple.ToRow,
Database.SQLite.Simple.FromRow,
) where
import Database.SQLite.Simple (Connection, FromRow, ToRow)
import GHC.TypeLits (Symbol)
import qualified Data.Int
import qualified Database.SQLite.Simple
import qualified Data.Vector
import qualified Data.Vector.Mutable
newtype Query (name :: Symbol) (command :: Symbol)
= Query Database.SQLite.Simple.Query
data family Params (name :: Symbol)
data family Result (name :: Symbol)
data ExecResult = ExecResult
{ lastInsertId :: !Data.Int.Int64,
rowsAffected :: !Data.Int.Int64
}
exec ::
(ToRow (Params name)) =>
Connection ->
Query name ":exec" ->
Params name ->
IO ()
exec connection (Query sql) =
Database.SQLite.Simple.execute connection sql
execRows ::
(ToRow (Params name)) =>
Connection ->
Query name ":execrows" ->
Params name ->
IO Data.Int.Int64
execRows connection (Query sql) params = do
Database.SQLite.Simple.execute connection sql params
rowsAffected <- Database.SQLite.Simple.changes connection
pure (fromIntegral rowsAffected)
execLastId ::
(ToRow (Params name)) =>
Connection ->
Query name ":execlastid" ->
Params name ->
IO Data.Int.Int64
execLastId connection (Query sql) params = do
Database.SQLite.Simple.execute connection sql params
lastInsertId <- Database.SQLite.Simple.lastInsertRowId connection
pure lastInsertId
execResult ::
(ToRow (Params name)) =>
Connection ->
Query name ":execresult" ->
Params name ->
IO ExecResult
execResult connection (Query sql) params = do
Database.SQLite.Simple.execute connection sql params
rowsAffected <- Database.SQLite.Simple.changes connection
lastInsertId <- Database.SQLite.Simple.lastInsertRowId connection
pure ExecResult {
lastInsertId,
rowsAffected = fromIntegral rowsAffected
}
queryOne ::
(ToRow (Params name), FromRow (Result name)) =>
Connection ->
Query name ":one" ->
Params name ->
IO (Maybe (Result name))
queryOne connection (Query sql) params = do
result <- Database.SQLite.Simple.query connection sql params
case result of
[] -> pure Nothing
x : _ -> pure (Just x)
data Grow v = Grow !Int !v
queryMany ::
(ToRow (Params name), FromRow (Result name)) =>
Connection ->
Query name ":many" ->
Params name ->
IO (Data.Vector.Vector (Result name))
queryMany connection query params = do
vector <- Data.Vector.Mutable.unsafeNew 4
Grow i vector <- fold connection query params (Grow 0 vector) step
vector <- Data.Vector.unsafeFreeze vector
pure $! Data.Vector.unsafeTake i vector
where
step (Grow i vector) !result
| i < Data.Vector.Mutable.length vector = do
Data.Vector.Mutable.unsafeWrite vector i result
pure $! Grow (i + 1) vector
| otherwise = do
-- Grow vector exponentially by doubling its size
vector <- Data.Vector.Mutable.unsafeGrow vector i
Data.Vector.Mutable.unsafeWrite vector i result
pure $! Grow (i + 1) vector
fold ::
(ToRow (Params name), FromRow (Result name)) =>
Connection ->
Query name ":many" ->
Params name ->
a ->
(a -> Result name -> IO a) ->
IO a
fold connection (Query sql) =
Database.SQLite.Simple.fold connection sql
{-# INLINABLE fold #-}