on e6b7de2 help sign in
rel8/src/Rel8/Expr/Null.hs
101 lines 3.0 kB history raw
1{-# language DataKinds #-}
2{-# language FlexibleContexts #-}
3{-# language TypeFamilies #-}
5{-# options -fno-warn-redundant-constraints #-}
7module Rel8.Expr.Null
8 ( null, snull, nullable, nullableOf
9 , isNull, isNonNull
10 , nullify, unsafeUnnullify
11 , mapNullable, liftOpNullable
12 , unsafeMapNullable, unsafeLiftOpNullable
13 )
14where
16-- base
17import Prelude hiding ( null )
19-- opaleye
20import qualified Opaleye.Internal.HaskellDB.PrimQuery as Opaleye
22-- rel8
23import {-# SOURCE #-} Rel8.Expr ( Expr( Expr ) )
24import Rel8.Expr.Bool ( (||.), boolExpr )
25import Rel8.Expr.Opaleye ( scastExpr, mapPrimExpr )
26import Rel8.Schema.Nullability ( NotNull )
27import Rel8.Type ( DBType, typeInformation )
28import Rel8.Type.Information ( TypeInformation )
31-- | Lift an expression that can't be @null@ to a type that might be @null@.
32-- This is an identity operation in terms of any generated query, and just
33-- modifies the query's type.
34nullify :: NotNull a => Expr a -> Expr (Maybe a)
35nullify (Expr a) = Expr a
38unsafeUnnullify :: Expr (Maybe a) -> Expr a
39unsafeUnnullify (Expr a) = Expr a
42-- | Like 'maybe', but to eliminate @null@.
43nullable :: Expr b -> (Expr a -> Expr b) -> Expr (Maybe a) -> Expr b
44nullable b f ma = boolExpr (f (unsafeUnnullify ma)) b (isNull ma)
47nullableOf :: DBType a => Maybe (Expr a) -> Expr (Maybe a)
48nullableOf = maybe null nullify
51-- | Like 'Data.Maybe.isNothing', but for @null@.
52isNull :: Expr (Maybe a) -> Expr Bool
53isNull = mapPrimExpr (Opaleye.UnExpr Opaleye.OpIsNull)
56-- | Like 'Data.Maybe.isJust', but for @null@.
57isNonNull :: Expr (Maybe a) -> Expr Bool
58isNonNull = mapPrimExpr (Opaleye.UnExpr Opaleye.OpIsNotNull)
61-- | Lift an operation on non-@null@ values to an operation on possibly @null@
62-- values. When given @null@, @mapNullable f@ returns @null@.
63--
64-- This is like 'fmap' for 'Maybe'.
65mapNullable :: DBType b
66 => (Expr a -> Expr b) -> Expr (Maybe a) -> Expr (Maybe b)
67mapNullable f ma = boolExpr (unsafeMapNullable f ma) null (isNull ma)
70-- | Lift a binary operation on non-@null@ expressions to an equivalent binary
71-- operator on possibly @null@ expressions. If either of the final arguments
72-- are @null@, @liftOpNullable@ returns @null@.
73--
74-- This is like 'liftA2' for 'Maybe'.
75liftOpNullable :: DBType c
76 => (Expr a -> Expr b -> Expr c)
77 -> Expr (Maybe a) -> Expr (Maybe b) -> Expr (Maybe c)
78liftOpNullable f ma mb =
79 boolExpr (unsafeLiftOpNullable f ma mb) null
80 (isNull ma ||. isNull mb)
83snull :: TypeInformation a -> Expr (Maybe a)
84snull info = scastExpr info $ Expr $ Opaleye.ConstExpr Opaleye.NullLit
87-- | Corresponds to SQL @null@.
88null :: DBType a => Expr (Maybe a)
89null = snull typeInformation
92unsafeMapNullable :: NotNull b
93 => (Expr a -> Expr b) -> Expr (Maybe a) -> Expr (Maybe b)
94unsafeMapNullable f ma = nullify (f (unsafeUnnullify ma))
97unsafeLiftOpNullable :: NotNull c
98 => (Expr a -> Expr b -> Expr c)
99 -> Expr (Maybe a) -> Expr (Maybe b) -> Expr (Maybe c)
100unsafeLiftOpNullable f ma mb =
101 nullify (f (unsafeUnnullify ma) (unsafeUnnullify mb))