{-# language DataKinds #-}
{-# language FlexibleContexts #-}
{-# language GADTs #-}
{-# language ScopedTypeVariables #-}
{-# language TypeApplications #-}

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

module Rel8.Expr.Ord
  ( (<.), (<=.), (>.), (>=.)
  , (<?), (<=?), (>?), (>=?)
  , leastExpr, greatestExpr
  )
where

-- base
import Prelude

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

-- rel8
import Rel8.Expr ( Expr( Expr ) )
import Rel8.Expr.Bool ( (&&.), (||.), coalesce )
import Rel8.Expr.Null ( isNull, isNonNull, nullableExpr, unsafeLiftOpNull )
import Rel8.Expr.Opaleye ( toPrimExpr, zipPrimExprsWith )
import Rel8.Schema.Null ( Nullity( Null, NotNull ), Sql, nullable )
import Rel8.Type.Ord ( DBOrd )


lt :: DBOrd a => Expr a -> Expr a -> Expr Bool
lt :: Expr a -> Expr a -> Expr Bool
lt = (PrimExpr -> PrimExpr -> PrimExpr) -> Expr a -> Expr a -> Expr Bool
forall a b c.
(PrimExpr -> PrimExpr -> PrimExpr) -> Expr a -> Expr b -> Expr c
zipPrimExprsWith (BinOp -> PrimExpr -> PrimExpr -> PrimExpr
Opaleye.BinExpr BinOp
(Opaleye.:<))


le :: DBOrd a => Expr a -> Expr a -> Expr Bool
le :: Expr a -> Expr a -> Expr Bool
le = (PrimExpr -> PrimExpr -> PrimExpr) -> Expr a -> Expr a -> Expr Bool
forall a b c.
(PrimExpr -> PrimExpr -> PrimExpr) -> Expr a -> Expr b -> Expr c
zipPrimExprsWith (BinOp -> PrimExpr -> PrimExpr -> PrimExpr
Opaleye.BinExpr BinOp
(Opaleye.:<=))


gt :: DBOrd a => Expr a -> Expr a -> Expr Bool
gt :: Expr a -> Expr a -> Expr Bool
gt = (PrimExpr -> PrimExpr -> PrimExpr) -> Expr a -> Expr a -> Expr Bool
forall a b c.
(PrimExpr -> PrimExpr -> PrimExpr) -> Expr a -> Expr b -> Expr c
zipPrimExprsWith (BinOp -> PrimExpr -> PrimExpr -> PrimExpr
Opaleye.BinExpr BinOp
(Opaleye.:>))


ge :: DBOrd a => Expr a -> Expr a -> Expr Bool
ge :: Expr a -> Expr a -> Expr Bool
ge = (PrimExpr -> PrimExpr -> PrimExpr) -> Expr a -> Expr a -> Expr Bool
forall a b c.
(PrimExpr -> PrimExpr -> PrimExpr) -> Expr a -> Expr b -> Expr c
zipPrimExprsWith (BinOp -> PrimExpr -> PrimExpr -> PrimExpr
Opaleye.BinExpr BinOp
(Opaleye.:>=))


-- | Corresponds to the SQL @<@ operator. Note that this differs from SQL @<@
-- as @null@ will sort below any other value. For a version of @<@ that exactly
-- matches SQL, see '(<?)'.
(<.) :: forall a. Sql DBOrd a => Expr a -> Expr a -> Expr Bool
<. :: Expr a -> Expr a -> Expr Bool
(<.) = case Nullable a => Nullity a
forall a. Nullable a => Nullity a
nullable @a of
  Nullity a
Null -> \Expr a
ma Expr a
mb -> Expr (Maybe (Unnullify' (IsMaybe a) a)) -> Expr Bool
forall a. Expr (Maybe a) -> Expr Bool
isNull Expr a
Expr (Maybe (Unnullify' (IsMaybe a) a))
ma Expr Bool -> Expr Bool -> Expr Bool
&&. Expr (Maybe (Unnullify' (IsMaybe a) a)) -> Expr Bool
forall a. Expr (Maybe a) -> Expr Bool
isNonNull Expr a
Expr (Maybe (Unnullify' (IsMaybe a) a))
mb Expr Bool -> Expr Bool -> Expr Bool
||. Expr a
Expr (Maybe (Unnullify' (IsMaybe a) a))
ma Expr (Maybe (Unnullify' (IsMaybe a) a))
-> Expr (Maybe (Unnullify' (IsMaybe a) a)) -> Expr Bool
forall a. DBOrd a => Expr (Maybe a) -> Expr (Maybe a) -> Expr Bool
<? Expr a
Expr (Maybe (Unnullify' (IsMaybe a) a))
mb
  Nullity a
NotNull -> Expr a -> Expr a -> Expr Bool
forall a. DBOrd a => Expr a -> Expr a -> Expr Bool
lt
infix 4 <.


-- | Corresponds to the SQL @<=@ operator. Note that this differs from SQL @<=@
-- as @null@ will sort below any other value. For a version of @<=@ that exactly
-- matches SQL, see '(<=?)'.
(<=.) :: forall a. Sql DBOrd a => Expr a -> Expr a -> Expr Bool
<=. :: Expr a -> Expr a -> Expr Bool
(<=.) = case Nullable a => Nullity a
forall a. Nullable a => Nullity a
nullable @a of
  Nullity a
Null -> \Expr a
ma Expr a
mb -> Expr (Maybe (Unnullify' (IsMaybe a) a)) -> Expr Bool
forall a. Expr (Maybe a) -> Expr Bool
isNull Expr a
Expr (Maybe (Unnullify' (IsMaybe a) a))
ma Expr Bool -> Expr Bool -> Expr Bool
||. Expr a
Expr (Maybe (Unnullify' (IsMaybe a) a))
ma Expr (Maybe (Unnullify' (IsMaybe a) a))
-> Expr (Maybe (Unnullify' (IsMaybe a) a)) -> Expr Bool
forall a. DBOrd a => Expr (Maybe a) -> Expr (Maybe a) -> Expr Bool
<=? Expr a
Expr (Maybe (Unnullify' (IsMaybe a) a))
mb
  Nullity a
NotNull -> Expr a -> Expr a -> Expr Bool
forall a. DBOrd a => Expr a -> Expr a -> Expr Bool
le
infix 4 <=.


-- | Corresponds to the SQL @>@ operator. Note that this differs from SQL @>@
-- as @null@ will sort below any other value. For a version of @>@ that exactly
-- matches SQL, see '(>?)'.
(>.) :: forall a. Sql DBOrd a => Expr a -> Expr a -> Expr Bool
>. :: Expr a -> Expr a -> Expr Bool
(>.) = case Nullable a => Nullity a
forall a. Nullable a => Nullity a
nullable @a of
  Nullity a
Null -> \Expr a
ma Expr a
mb -> Expr (Maybe (Unnullify' (IsMaybe a) a)) -> Expr Bool
forall a. Expr (Maybe a) -> Expr Bool
isNonNull Expr a
Expr (Maybe (Unnullify' (IsMaybe a) a))
ma Expr Bool -> Expr Bool -> Expr Bool
&&. Expr (Maybe (Unnullify' (IsMaybe a) a)) -> Expr Bool
forall a. Expr (Maybe a) -> Expr Bool
isNull Expr a
Expr (Maybe (Unnullify' (IsMaybe a) a))
mb Expr Bool -> Expr Bool -> Expr Bool
||. Expr a
Expr (Maybe (Unnullify' (IsMaybe a) a))
ma Expr (Maybe (Unnullify' (IsMaybe a) a))
-> Expr (Maybe (Unnullify' (IsMaybe a) a)) -> Expr Bool
forall a. DBOrd a => Expr (Maybe a) -> Expr (Maybe a) -> Expr Bool
>? Expr a
Expr (Maybe (Unnullify' (IsMaybe a) a))
mb
  Nullity a
NotNull -> Expr a -> Expr a -> Expr Bool
forall a. DBOrd a => Expr a -> Expr a -> Expr Bool
gt
infix 4 >.


-- | Corresponds to the SQL @>=@ operator. Note that this differs from SQL @>@
-- as @null@ will sort below any other value. For a version of @>=@ that
-- exactly matches SQL, see '(>=?)'.
(>=.) :: forall a. Sql DBOrd a => Expr a -> Expr a -> Expr Bool
>=. :: Expr a -> Expr a -> Expr Bool
(>=.) = case Nullable a => Nullity a
forall a. Nullable a => Nullity a
nullable @a of
  Nullity a
Null -> \Expr a
ma Expr a
mb -> Expr (Maybe (Unnullify' (IsMaybe a) a)) -> Expr Bool
forall a. Expr (Maybe a) -> Expr Bool
isNull Expr a
Expr (Maybe (Unnullify' (IsMaybe a) a))
mb Expr Bool -> Expr Bool -> Expr Bool
||. Expr a
Expr (Maybe (Unnullify' (IsMaybe a) a))
ma Expr (Maybe (Unnullify' (IsMaybe a) a))
-> Expr (Maybe (Unnullify' (IsMaybe a) a)) -> Expr Bool
forall a. DBOrd a => Expr (Maybe a) -> Expr (Maybe a) -> Expr Bool
>=? Expr a
Expr (Maybe (Unnullify' (IsMaybe a) a))
mb
  Nullity a
NotNull -> Expr a -> Expr a -> Expr Bool
forall a. DBOrd a => Expr a -> Expr a -> Expr Bool
ge
infix 4 >=.


-- | Corresponds to the SQL @<@ operator. Returns @null@ if either arguments
-- are @null@.
(<?) :: DBOrd a => Expr (Maybe a) -> Expr (Maybe a) -> Expr Bool
Expr (Maybe a)
a <? :: Expr (Maybe a) -> Expr (Maybe a) -> Expr Bool
<? Expr (Maybe a)
b = Expr (Maybe Bool) -> Expr Bool
coalesce (Expr (Maybe Bool) -> Expr Bool) -> Expr (Maybe Bool) -> Expr Bool
forall a b. (a -> b) -> a -> b
$ (Expr a -> Expr a -> Expr Bool)
-> Expr (Maybe a) -> Expr (Maybe a) -> Expr (Maybe Bool)
forall c a b.
NotNull c =>
(Expr a -> Expr b -> Expr c)
-> Expr (Maybe a) -> Expr (Maybe b) -> Expr (Maybe c)
unsafeLiftOpNull Expr a -> Expr a -> Expr Bool
forall a. DBOrd a => Expr a -> Expr a -> Expr Bool
lt Expr (Maybe a)
a Expr (Maybe a)
b
infix 4 <?


-- | Corresponds to the SQL @<=@ operator. Returns @null@ if either arguments
-- are @null@.
(<=?) :: DBOrd a => Expr (Maybe a) -> Expr (Maybe a) -> Expr Bool
Expr (Maybe a)
a <=? :: Expr (Maybe a) -> Expr (Maybe a) -> Expr Bool
<=? Expr (Maybe a)
b = Expr (Maybe Bool) -> Expr Bool
coalesce (Expr (Maybe Bool) -> Expr Bool) -> Expr (Maybe Bool) -> Expr Bool
forall a b. (a -> b) -> a -> b
$ (Expr a -> Expr a -> Expr Bool)
-> Expr (Maybe a) -> Expr (Maybe a) -> Expr (Maybe Bool)
forall c a b.
NotNull c =>
(Expr a -> Expr b -> Expr c)
-> Expr (Maybe a) -> Expr (Maybe b) -> Expr (Maybe c)
unsafeLiftOpNull Expr a -> Expr a -> Expr Bool
forall a. DBOrd a => Expr a -> Expr a -> Expr Bool
le Expr (Maybe a)
a Expr (Maybe a)
b
infix 4 <=?


-- | Corresponds to the SQL @>@ operator. Returns @null@ if either arguments
-- are @null@.
(>?) :: DBOrd a => Expr (Maybe a) -> Expr (Maybe a) -> Expr Bool
Expr (Maybe a)
a >? :: Expr (Maybe a) -> Expr (Maybe a) -> Expr Bool
>? Expr (Maybe a)
b = Expr (Maybe Bool) -> Expr Bool
coalesce (Expr (Maybe Bool) -> Expr Bool) -> Expr (Maybe Bool) -> Expr Bool
forall a b. (a -> b) -> a -> b
$ (Expr a -> Expr a -> Expr Bool)
-> Expr (Maybe a) -> Expr (Maybe a) -> Expr (Maybe Bool)
forall c a b.
NotNull c =>
(Expr a -> Expr b -> Expr c)
-> Expr (Maybe a) -> Expr (Maybe b) -> Expr (Maybe c)
unsafeLiftOpNull Expr a -> Expr a -> Expr Bool
forall a. DBOrd a => Expr a -> Expr a -> Expr Bool
gt Expr (Maybe a)
a Expr (Maybe a)
b
infix 4 >?


-- | Corresponds to the SQL @>=@ operator. Returns @null@ if either arguments
-- are @null@.
(>=?) :: DBOrd a => Expr (Maybe a) -> Expr (Maybe a) -> Expr Bool
Expr (Maybe a)
a >=? :: Expr (Maybe a) -> Expr (Maybe a) -> Expr Bool
>=? Expr (Maybe a)
b = Expr (Maybe Bool) -> Expr Bool
coalesce (Expr (Maybe Bool) -> Expr Bool) -> Expr (Maybe Bool) -> Expr Bool
forall a b. (a -> b) -> a -> b
$ (Expr a -> Expr a -> Expr Bool)
-> Expr (Maybe a) -> Expr (Maybe a) -> Expr (Maybe Bool)
forall c a b.
NotNull c =>
(Expr a -> Expr b -> Expr c)
-> Expr (Maybe a) -> Expr (Maybe b) -> Expr (Maybe c)
unsafeLiftOpNull Expr a -> Expr a -> Expr Bool
forall a. DBOrd a => Expr a -> Expr a -> Expr Bool
ge Expr (Maybe a)
a Expr (Maybe a)
b
infix 4 >=?


-- | Given two expressions, return the expression that sorts less than the
-- other.
-- 
-- Corresponds to the SQL @least()@ function.
leastExpr :: forall a. Sql DBOrd a => Expr a -> Expr a -> Expr a
leastExpr :: Expr a -> Expr a -> Expr a
leastExpr Expr a
ma Expr a
mb = case Nullable a => Nullity a
forall a. Nullable a => Nullity a
nullable @a of
  Nullity a
Null -> Expr a
-> (Expr (Unnullify' (IsMaybe a) a) -> Expr a)
-> Expr (Maybe (Unnullify' (IsMaybe a) a))
-> Expr a
forall b a.
Expr b -> (Expr a -> Expr b) -> Expr (Maybe a) -> Expr b
nullableExpr Expr a
ma (\Expr (Unnullify' (IsMaybe a) a)
a -> Expr a
-> (Expr (Unnullify' (IsMaybe a) a) -> Expr a)
-> Expr (Maybe (Unnullify' (IsMaybe a) a))
-> Expr a
forall b a.
Expr b -> (Expr a -> Expr b) -> Expr (Maybe a) -> Expr b
nullableExpr Expr a
mb (Expr (Unnullify' (IsMaybe a) a)
-> Expr (Unnullify' (IsMaybe a) a) -> Expr a
forall a a a. Expr a -> Expr a -> Expr a
least_ Expr (Unnullify' (IsMaybe a) a)
a) Expr a
Expr (Maybe (Unnullify' (IsMaybe a) a))
mb) Expr a
Expr (Maybe (Unnullify' (IsMaybe a) a))
ma
  Nullity a
NotNull -> Expr a -> Expr a -> Expr a
forall a a a. Expr a -> Expr a -> Expr a
least_ Expr a
ma Expr a
mb
  where
    least_ :: Expr a -> Expr a -> Expr a
least_ Expr a
a Expr a
b = PrimExpr -> Expr a
forall k (a :: k). (k ~ *) => PrimExpr -> Expr a
Expr (Name -> [PrimExpr] -> PrimExpr
Opaleye.FunExpr Name
"LEAST" [Expr a -> PrimExpr
forall a. Expr a -> PrimExpr
toPrimExpr Expr a
a, Expr a -> PrimExpr
forall a. Expr a -> PrimExpr
toPrimExpr Expr a
b])


-- | Given two expressions, return the expression that sorts greater than the
-- other.
-- 
-- Corresponds to the SQL @greatest()@ function.
greatestExpr :: forall a. Sql DBOrd a => Expr a -> Expr a -> Expr a
greatestExpr :: Expr a -> Expr a -> Expr a
greatestExpr Expr a
ma Expr a
mb = case Nullable a => Nullity a
forall a. Nullable a => Nullity a
nullable @a of
  Nullity a
Null -> Expr a
-> (Expr (Unnullify' (IsMaybe a) a) -> Expr a)
-> Expr (Maybe (Unnullify' (IsMaybe a) a))
-> Expr a
forall b a.
Expr b -> (Expr a -> Expr b) -> Expr (Maybe a) -> Expr b
nullableExpr Expr a
mb (\Expr (Unnullify' (IsMaybe a) a)
a -> Expr a
-> (Expr (Unnullify' (IsMaybe a) a) -> Expr a)
-> Expr (Maybe (Unnullify' (IsMaybe a) a))
-> Expr a
forall b a.
Expr b -> (Expr a -> Expr b) -> Expr (Maybe a) -> Expr b
nullableExpr Expr a
ma (Expr (Unnullify' (IsMaybe a) a)
-> Expr (Unnullify' (IsMaybe a) a) -> Expr a
forall a a a. Expr a -> Expr a -> Expr a
greatest_ Expr (Unnullify' (IsMaybe a) a)
a) Expr a
Expr (Maybe (Unnullify' (IsMaybe a) a))
mb) Expr a
Expr (Maybe (Unnullify' (IsMaybe a) a))
ma
  Nullity a
NotNull -> Expr a -> Expr a -> Expr a
forall a a a. Expr a -> Expr a -> Expr a
greatest_ Expr a
ma Expr a
mb
  where
    greatest_ :: Expr a -> Expr a -> Expr a
greatest_ Expr a
a Expr a
b =
      PrimExpr -> Expr a
forall k (a :: k). (k ~ *) => PrimExpr -> Expr a
Expr (Name -> [PrimExpr] -> PrimExpr
Opaleye.FunExpr Name
"GREATEST" [Expr a -> PrimExpr
forall a. Expr a -> PrimExpr
toPrimExpr Expr a
a, Expr a -> PrimExpr
forall a. Expr a -> PrimExpr
toPrimExpr Expr a
b])