{-# language FlexibleContexts #-}
{-# language NamedFieldPuns #-}
{-# language ScopedTypeVariables #-}
{-# language TypeFamilies #-}

{-# options_ghc -fno-warn-redundant-constraints #-}

module Rel8.Expr.Opaleye
  ( castExpr, unsafeCastExpr
  , scastExpr, sunsafeCastExpr
  , unsafeLiteral
  , fromPrimExpr, toPrimExpr, mapPrimExpr, zipPrimExprsWith, traversePrimExpr
  , toColumn, fromColumn
  )
where

-- base
import Prelude

-- opaleye
import qualified Opaleye.Internal.Column as Opaleye
import qualified Opaleye.Internal.HaskellDB.PrimQuery as Opaleye

-- rel8
import {-# SOURCE #-} Rel8.Expr ( Expr( Expr ) )
import Rel8.Schema.Null ( Unnullify, Sql )
import Rel8.Type ( DBType, typeInformation )
import Rel8.Type.Information ( TypeInformation(..) )


castExpr :: Sql DBType a => Expr a -> Expr a
castExpr :: Expr a -> Expr a
castExpr = TypeInformation (Unnullify a) -> Expr a -> Expr a
forall a. TypeInformation (Unnullify a) -> Expr a -> Expr a
scastExpr TypeInformation (Unnullify a)
forall a. DBType a => TypeInformation a
typeInformation


-- | Cast an expression to a different type. Corresponds to a @CAST()@ function
-- call.
unsafeCastExpr :: Sql DBType b => Expr a -> Expr b
unsafeCastExpr :: Expr a -> Expr b
unsafeCastExpr = TypeInformation (Unnullify b) -> Expr a -> Expr b
forall b a. TypeInformation (Unnullify b) -> Expr a -> Expr b
sunsafeCastExpr TypeInformation (Unnullify b)
forall a. DBType a => TypeInformation a
typeInformation


scastExpr :: TypeInformation (Unnullify a) -> Expr a -> Expr a
scastExpr :: TypeInformation (Unnullify a) -> Expr a -> Expr a
scastExpr = TypeInformation (Unnullify a) -> Expr a -> Expr a
forall b a. TypeInformation (Unnullify b) -> Expr a -> Expr b
sunsafeCastExpr


sunsafeCastExpr :: ()
  => TypeInformation (Unnullify b) -> Expr a -> Expr b
sunsafeCastExpr :: TypeInformation (Unnullify b) -> Expr a -> Expr b
sunsafeCastExpr TypeInformation {String
typeName :: forall a. TypeInformation a -> String
typeName :: String
typeName} =
  PrimExpr -> Expr b
forall a. PrimExpr -> Expr a
fromPrimExpr (PrimExpr -> Expr b) -> (Expr a -> PrimExpr) -> Expr a -> Expr b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> PrimExpr -> PrimExpr
Opaleye.CastExpr String
typeName (PrimExpr -> PrimExpr)
-> (Expr a -> PrimExpr) -> Expr a -> PrimExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr a -> PrimExpr
forall a. Expr a -> PrimExpr
toPrimExpr


-- | Unsafely construct an expression from literal SQL.
--
-- This is an escape hatch, and can be used if Rel8 can not adequately express
-- the query you need. If you find yourself using this function, please let us
-- know, as it may indicate that something is missing from Rel8!
unsafeLiteral :: String -> Expr a
unsafeLiteral :: String -> Expr a
unsafeLiteral = PrimExpr -> Expr a
forall a. PrimExpr -> Expr a
Expr (PrimExpr -> Expr a) -> (String -> PrimExpr) -> String -> Expr a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Literal -> PrimExpr
Opaleye.ConstExpr (Literal -> PrimExpr) -> (String -> Literal) -> String -> PrimExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Literal
Opaleye.OtherLit


fromPrimExpr :: Opaleye.PrimExpr -> Expr a
fromPrimExpr :: PrimExpr -> Expr a
fromPrimExpr = PrimExpr -> Expr a
forall a. PrimExpr -> Expr a
Expr


toPrimExpr :: Expr a -> Opaleye.PrimExpr
toPrimExpr :: Expr a -> PrimExpr
toPrimExpr (Expr PrimExpr
a) = PrimExpr
a


mapPrimExpr :: (Opaleye.PrimExpr -> Opaleye.PrimExpr) -> Expr a -> Expr b
mapPrimExpr :: (PrimExpr -> PrimExpr) -> Expr a -> Expr b
mapPrimExpr PrimExpr -> PrimExpr
f = PrimExpr -> Expr b
forall a. PrimExpr -> Expr a
fromPrimExpr (PrimExpr -> Expr b) -> (Expr a -> PrimExpr) -> Expr a -> Expr b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrimExpr -> PrimExpr
f (PrimExpr -> PrimExpr)
-> (Expr a -> PrimExpr) -> Expr a -> PrimExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr a -> PrimExpr
forall a. Expr a -> PrimExpr
toPrimExpr


zipPrimExprsWith :: ()
  => (Opaleye.PrimExpr -> Opaleye.PrimExpr -> Opaleye.PrimExpr)
  -> Expr a -> Expr b -> Expr c
zipPrimExprsWith :: (PrimExpr -> PrimExpr -> PrimExpr) -> Expr a -> Expr b -> Expr c
zipPrimExprsWith PrimExpr -> PrimExpr -> PrimExpr
f Expr a
a Expr b
b = PrimExpr -> Expr c
forall a. PrimExpr -> Expr a
fromPrimExpr (PrimExpr -> PrimExpr -> PrimExpr
f (Expr a -> PrimExpr
forall a. Expr a -> PrimExpr
toPrimExpr Expr a
a) (Expr b -> PrimExpr
forall a. Expr a -> PrimExpr
toPrimExpr Expr b
b))


traversePrimExpr :: Functor f
  => (Opaleye.PrimExpr -> f Opaleye.PrimExpr) -> Expr a -> f (Expr b)
traversePrimExpr :: (PrimExpr -> f PrimExpr) -> Expr a -> f (Expr b)
traversePrimExpr PrimExpr -> f PrimExpr
f = (PrimExpr -> Expr b) -> f PrimExpr -> f (Expr b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap PrimExpr -> Expr b
forall a. PrimExpr -> Expr a
fromPrimExpr (f PrimExpr -> f (Expr b))
-> (Expr a -> f PrimExpr) -> Expr a -> f (Expr b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrimExpr -> f PrimExpr
f (PrimExpr -> f PrimExpr)
-> (Expr a -> PrimExpr) -> Expr a -> f PrimExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr a -> PrimExpr
forall a. Expr a -> PrimExpr
toPrimExpr


toColumn :: Opaleye.PrimExpr -> Opaleye.Field_ n b
toColumn :: PrimExpr -> Field_ n b
toColumn = PrimExpr -> Field_ n b
forall (n :: Nullability) sqlType. PrimExpr -> Field_ n sqlType
Opaleye.Column


fromColumn :: Opaleye.Field_ n b -> Opaleye.PrimExpr
fromColumn :: Field_ n b -> PrimExpr
fromColumn (Opaleye.Column PrimExpr
a) = PrimExpr
a