packages feed

sqlc-hs-0.4.0.0: test/golden/hasql-features/Queries/Internal.hs

{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE TypeFamilies #-}
module Queries.Internal (
    Query(..),
    Params,
    Result,
    Queries.Internal.Enum,

    -- * :execResult
    ExecResult(..),
    execResult,
    execResultSession,

    -- * :exec
    exec,
    execSession,

    -- * :execrows
    execRows,
    execRowsSession,

    -- * :one
    queryOne,
    queryOneSession,

    -- * :many
    queryMany,
    queryManySession,

    -- * :copyfrom
    execMany,
    execManySession,

    -- * Reexports
    Hasql.Connection.Connection,
    Hasql.Session.Session,
    -- Without @(..)@: the class re-exports an associated type called @Result@,
    -- which would collide with the row family of the same name above. A caller
    -- that needs to name the statement's result imports
    -- "Hasql.Mapping.IsStatement" directly.
    Hasql.Mapping.IsStatement.IsStatement,
    RunnerError,
    Hasql.Errors.SessionError,
  ) where

import Data.Foldable (Foldable)
import GHC.TypeLits (Symbol)
import qualified Data.Foldable
import qualified Data.Int
import qualified Data.Text
import qualified Hasql.Connection
import qualified Hasql.Errors
import qualified Hasql.Mapping.IsStatement
import qualified Hasql.Pipeline
import qualified Hasql.Session

-- | What a runner reports when it fails.
--
-- hasql 2.1 replaced the single session-error type that
-- 'Hasql.Connection.use' returned with @UseError@, which distinguishes a
-- statement that failed on a live connection (@SessionUseError@, wrapping the
-- 'Hasql.Errors.SessionError' the old type expressed) from a connection that is
-- gone and has already been closed (@ConnectionUseError@).
--
-- Named through this alias so the generated module compiles against both, and
-- so a call site that only passes the error along does not have to care.
#if MIN_VERSION_hasql(2,1,0)
type RunnerError = Hasql.Errors.UseError
#else
type RunnerError = Hasql.Errors.SessionError
#endif

-- | The SQL of a query, with PostgreSQL's positional @$1@, @$2@ placeholders
-- left as sqlc emitted them.
--
-- The generated 'Hasql.Mapping.IsStatement.IsStatement' instance builds its
-- statement from this, so a runner does not need it to execute anything. It is
-- still an argument to every runner below, for two reasons: the @command@ tag
-- is what makes @queryMany@ reject a @:one@ query at compile time, and the SQL
-- is the obvious thing to attach to a trace span.
newtype Query (name :: Symbol) (command :: Symbol)
  = Query Data.Text.Text

data family Params (name :: Symbol)

data family Result (name :: Symbol)

data family Enum (name :: Symbol)

data ExecResult = ExecResult
  { rowsAffected :: !Data.Int.Int64
  }

-- | The codecs come from the query's
-- 'Hasql.Mapping.IsStatement.IsStatement' instance, and the shape of what it
-- returns is that instance's @Result@ -- @Maybe@ a row for @:one@, a @Vector@
-- of them for @:many@, @()@ for @:exec@, and so on. Naming it through the
-- associated type rather than spelling each shape out is what lets these
-- signatures stay free of equality constraints.
exec ::
  (Hasql.Mapping.IsStatement.IsStatement (Params name)) =>
  Hasql.Connection.Connection ->
  Query name ":exec" ->
  Params name ->
  IO (Either RunnerError (Hasql.Mapping.IsStatement.Result (Params name)))
exec connection query params =
  Hasql.Connection.use connection (execSession query params)

execSession ::
  (Hasql.Mapping.IsStatement.IsStatement (Params name)) =>
  Query name ":exec" ->
  Params name ->
  Hasql.Session.Session (Hasql.Mapping.IsStatement.Result (Params name))
execSession _query params =
  Hasql.Mapping.IsStatement.toSession params

execRows ::
  (Hasql.Mapping.IsStatement.IsStatement (Params name)) =>
  Hasql.Connection.Connection ->
  Query name ":execrows" ->
  Params name ->
  IO (Either RunnerError (Hasql.Mapping.IsStatement.Result (Params name)))
execRows connection query params =
  Hasql.Connection.use connection (execRowsSession query params)

execRowsSession ::
  (Hasql.Mapping.IsStatement.IsStatement (Params name)) =>
  Query name ":execrows" ->
  Params name ->
  Hasql.Session.Session (Hasql.Mapping.IsStatement.Result (Params name))
execRowsSession _query params =
  Hasql.Mapping.IsStatement.toSession params

execResult ::
  (Hasql.Mapping.IsStatement.IsStatement (Params name)) =>
  Hasql.Connection.Connection ->
  Query name ":execresult" ->
  Params name ->
  IO (Either RunnerError (Hasql.Mapping.IsStatement.Result (Params name)))
execResult connection query params =
  Hasql.Connection.use connection (execResultSession query params)

execResultSession ::
  (Hasql.Mapping.IsStatement.IsStatement (Params name)) =>
  Query name ":execresult" ->
  Params name ->
  Hasql.Session.Session (Hasql.Mapping.IsStatement.Result (Params name))
execResultSession _query params =
  Hasql.Mapping.IsStatement.toSession params

queryOne ::
  (Hasql.Mapping.IsStatement.IsStatement (Params name)) =>
  Hasql.Connection.Connection ->
  Query name ":one" ->
  Params name ->
  IO (Either RunnerError (Hasql.Mapping.IsStatement.Result (Params name)))
queryOne connection query params =
  Hasql.Connection.use connection (queryOneSession query params)

queryOneSession ::
  (Hasql.Mapping.IsStatement.IsStatement (Params name)) =>
  Query name ":one" ->
  Params name ->
  Hasql.Session.Session (Hasql.Mapping.IsStatement.Result (Params name))
queryOneSession _query params =
  Hasql.Mapping.IsStatement.toSession params

queryMany ::
  (Hasql.Mapping.IsStatement.IsStatement (Params name)) =>
  Hasql.Connection.Connection ->
  Query name ":many" ->
  Params name ->
  IO (Either RunnerError (Hasql.Mapping.IsStatement.Result (Params name)))
queryMany connection query params =
  Hasql.Connection.use connection (queryManySession query params)

queryManySession ::
  (Hasql.Mapping.IsStatement.IsStatement (Params name)) =>
  Query name ":many" ->
  Params name ->
  Hasql.Session.Session (Hasql.Mapping.IsStatement.Result (Params name))
queryManySession _query params =
  Hasql.Mapping.IsStatement.toSession params

-- | Runs the query once per set of parameters, pipelined into a single
-- round trip.
execMany ::
  (Hasql.Mapping.IsStatement.IsStatement (Params name), Foldable f) =>
  Hasql.Connection.Connection ->
  Query name ":copyfrom" ->
  f (Params name) ->
  IO (Either RunnerError [Hasql.Mapping.IsStatement.Result (Params name)])
execMany connection query params =
  Hasql.Connection.use connection (execManySession query params)

execManySession ::
  (Hasql.Mapping.IsStatement.IsStatement (Params name), Foldable f) =>
  Query name ":copyfrom" ->
  f (Params name) ->
  Hasql.Session.Session [Hasql.Mapping.IsStatement.Result (Params name)]
execManySession _query params =
  Hasql.Session.pipeline
    (traverse pipelined (Data.Foldable.toList params))
  where
    pipelined param =
      Hasql.Pipeline.statement param Hasql.Mapping.IsStatement.statement