rel8-1.7.0.0: src/Rel8/Statement/Returning.hs
{-# language DataKinds #-}
{-# language FlexibleContexts #-}
{-# language GADTs #-}
{-# language LambdaCase #-}
{-# language NamedFieldPuns #-}
{-# language RankNTypes #-}
{-# language ScopedTypeVariables #-}
{-# language StandaloneKindSignatures #-}
{-# language StrictData #-}
{-# language TypeApplications #-}
module Rel8.Statement.Returning
( Returning( NoReturning, Returning )
, runReturning
, ppReturning
)
where
-- base
import Data.Foldable ( toList )
import Data.Kind ( Type )
import Data.List.NonEmpty ( NonEmpty )
import Prelude
-- opaleye
import qualified Opaleye.Internal.HaskellDB.PrimQuery as Opaleye
import qualified Opaleye.Internal.HaskellDB.Sql.Print as Opaleye
import qualified Opaleye.Internal.Sql as Opaleye
import qualified Opaleye.Internal.Tag as Opaleye
-- pretty
import Text.PrettyPrint ( Doc, (<+>), text )
-- rel8
import Rel8.Expr (Expr)
import Rel8.Query (Query)
import Rel8.Schema.Name ( Selects )
import Rel8.Schema.Table ( TableSchema(..) )
import Rel8.Statement (Statement, statementNoReturning, statementReturning)
import Rel8.Table (Table)
import Rel8.Table.Opaleye ( castTable, exprs, view )
-- transformers
import Control.Monad.Trans.State.Strict (State)
-- | 'Rel8.Insert', 'Rel8.Update' and 'Rel8.Delete' all support an optional
-- @RETURNING@ clause.
type Returning :: Type -> Type -> Type
data Returning names a where
-- | No @RETURNING@ clause
NoReturning :: Returning names ()
-- | 'Returning' allows you to project out of the affected rows, which can
-- be useful if you want to log exactly which rows were deleted, or to view
-- a generated id (for example, if using a column with an autoincrementing
-- counter via 'Rel8.nextval').
Returning :: (Selects names exprs, Table Expr a) => (exprs -> a) -> Returning names (Query a)
projections :: ()
=> TableSchema names -> Returning names a -> Maybe (NonEmpty Opaleye.PrimExpr)
projections TableSchema {columns} = \case
NoReturning -> Nothing
Returning f -> Just (exprs (castTable (f (view columns))))
runReturning ::
State Opaleye.Tag Doc ->
Returning names a ->
Statement a
runReturning pp = \case
NoReturning -> statementNoReturning pp
Returning _ -> statementReturning pp
ppReturning :: TableSchema names -> Returning names a -> Doc
ppReturning schema returning = case projections schema returning of
Nothing -> mempty
Just columns ->
text "RETURNING" <+> Opaleye.commaV Opaleye.ppSqlExpr (toList sqlExprs)
where
sqlExprs = Opaleye.sqlExpr <$> columns