on 11bcbbb help sign in
rel8/src/Rel8/Expr/Null.hs
113 lines 3.3 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@.
43--
44-- >>> select c $ pure $ null 0 id (nullExpr :: Expr (Maybe Int32))
45-- [0]
46--
47-- >>> select c $ pure $ null 0 id (lit (Just 42) :: Expr (Maybe Int32))
48-- [42]
49nullable :: Expr b -> (Expr a -> Expr b) -> Expr (Maybe a) -> Expr b
50nullable b f ma = boolExpr (f (unsafeUnnullify ma)) b (isNull ma)
53nullableOf :: DBType a => Maybe (Expr a) -> Expr (Maybe a)
54nullableOf = maybe null nullify
57-- | Like 'isNothing', but for @null@.
58--
59-- >>> select c $ pure $ isNull (nullExpr :: Expr (Maybe Int32))
60-- [True]
61--
62-- >>> select c $ pure $ isNull (lit (Just 42) :: Expr (Maybe Int32))
63-- [False]
64isNull :: Expr (Maybe a) -> Expr Bool
65isNull = mapPrimExpr (Opaleye.UnExpr Opaleye.OpIsNull)
68-- | Like 'isJust', but for @null@.
69isNonNull :: Expr (Maybe a) -> Expr Bool
70isNonNull = mapPrimExpr (Opaleye.UnExpr Opaleye.OpIsNotNull)
73-- | Lift an operation on non-@null@ values to an operation on possibly @null@
74-- values. When given @null@, @mapNullable f@ returns @null@.
75--
76-- This is like 'fmap' for 'Maybe'.
77mapNullable :: DBType b
78 => (Expr a -> Expr b) -> Expr (Maybe a) -> Expr (Maybe b)
79mapNullable f ma = boolExpr (unsafeMapNullable f ma) null (isNull ma)
82-- | Lift a binary operation on non-@null@ expressions to an equivalent binary
83-- operator on possibly @null@ expressions. If either of the final arguments
84-- are @null@, @liftOpNullable@ returns @null@.
85--
86-- This is like 'liftA2' for 'Maybe'.
87liftOpNullable :: DBType c
88 => (Expr a -> Expr b -> Expr c)
89 -> Expr (Maybe a) -> Expr (Maybe b) -> Expr (Maybe c)
90liftOpNullable f ma mb =
91 boolExpr (unsafeLiftOpNullable f ma mb) null
92 (isNull ma ||. isNull mb)
95snull :: TypeInformation a -> Expr (Maybe a)
96snull info = scastExpr info $ Expr $ Opaleye.ConstExpr Opaleye.NullLit
99-- | Corresponds to SQL @null@.
100null :: DBType a => Expr (Maybe a)
101null = snull typeInformation
104unsafeMapNullable :: NotNull b
105 => (Expr a -> Expr b) -> Expr (Maybe a) -> Expr (Maybe b)
106unsafeMapNullable f ma = nullify (f (unsafeUnnullify ma))
109unsafeLiftOpNullable :: NotNull c
110 => (Expr a -> Expr b -> Expr c)
111 -> Expr (Maybe a) -> Expr (Maybe b) -> Expr (Maybe c)
112unsafeLiftOpNullable f ma mb =
113 nullify (f (unsafeUnnullify ma) (unsafeUnnullify mb))