{-# 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 = zipPrimExprsWith (Opaleye.BinExpr (Opaleye.:<)) le :: DBOrd a => Expr a -> Expr a -> Expr Bool le = zipPrimExprsWith (Opaleye.BinExpr (Opaleye.:<=)) gt :: DBOrd a => Expr a -> Expr a -> Expr Bool gt = zipPrimExprsWith (Opaleye.BinExpr (Opaleye.:>)) ge :: DBOrd a => Expr a -> Expr a -> Expr Bool ge = zipPrimExprsWith (Opaleye.BinExpr (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 '( Expr a -> Expr a -> Expr Bool (<.) = case nullable @a of Null -> \ma mb -> isNull ma &&. isNonNull mb ||. ma 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 (<=.) = case nullable @a of Null -> \ma mb -> isNull ma ||. ma <=? mb NotNull -> 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 (>.) = case nullable @a of Null -> \ma mb -> isNonNull ma &&. isNull mb ||. ma >? mb NotNull -> 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 (>=.) = case nullable @a of Null -> \ma mb -> isNull mb ||. ma >=? mb NotNull -> ge infix 4 >=. -- | Corresponds to the SQL @<@ operator. Returns @null@ if either arguments -- are @null@. ( Expr (Maybe a) -> Expr (Maybe a) -> Expr Bool a Expr (Maybe a) -> Expr (Maybe a) -> Expr Bool a <=? b = coalesce $ unsafeLiftOpNull le 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 a >? b = coalesce $ unsafeLiftOpNull gt 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 a >=? b = coalesce $ unsafeLiftOpNull ge 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 ma mb = case nullable @a of Null -> nullableExpr ma (\a -> nullableExpr mb (least_ a) mb) ma NotNull -> least_ ma mb where least_ a b = Expr (Opaleye.FunExpr "LEAST" [toPrimExpr a, toPrimExpr 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 ma mb = case nullable @a of Null -> nullableExpr mb (\a -> nullableExpr ma (greatest_ a) mb) ma NotNull -> greatest_ ma mb where greatest_ a b = Expr (Opaleye.FunExpr "GREATEST" [toPrimExpr a, toPrimExpr b])