squeal-postgresql-0.9.2.0: src/Squeal/PostgreSQL/Expression/Logic.hs
{-|
Module: Squeal.PostgreSQL.Expression.Logic
Description: logical expressions and operators
Copyright: (c) Eitan Chatav, 2019
Maintainer: eitan@morphism.tech
Stability: experimental
logical expressions and operators
-}
{-# LANGUAGE
DataKinds
, OverloadedStrings
, TypeOperators
#-}
module Squeal.PostgreSQL.Expression.Logic
( -- * Condition
Condition
, true
, false
-- * Logic
, not_
, (.&&)
, (.||)
-- * Conditional
, caseWhenThenElse
, ifThenElse
) where
import Squeal.PostgreSQL.Expression
import Squeal.PostgreSQL.Render
import Squeal.PostgreSQL.Type.Schema
-- | A `Condition` is an `Expression`, which can evaluate
-- to `true`, `false` or `Squeal.PostgreSQL.Null.null_`. This is because SQL uses
-- a three valued logic.
type Condition grp lat with db params from =
Expression grp lat with db params from ('Null 'PGbool)
-- | >>> printSQL true
-- TRUE
true :: Expr (null 'PGbool)
true = UnsafeExpression "TRUE"
-- | >>> printSQL false
-- FALSE
false :: Expr (null 'PGbool)
false = UnsafeExpression "FALSE"
-- | >>> printSQL $ not_ true
-- (NOT TRUE)
not_ :: null 'PGbool --> null 'PGbool
not_ = unsafeLeftOp "NOT"
-- | >>> printSQL $ true .&& false
-- (TRUE AND FALSE)
(.&&) :: Operator (null 'PGbool) (null 'PGbool) (null 'PGbool)
infixr 3 .&&
(.&&) = unsafeBinaryOp "AND"
-- | >>> printSQL $ true .|| false
-- (TRUE OR FALSE)
(.||) :: Operator (null 'PGbool) (null 'PGbool) (null 'PGbool)
infixr 2 .||
(.||) = unsafeBinaryOp "OR"
-- | >>> :{
-- let
-- expression :: Expression grp lat with db params from (null 'PGint2)
-- expression = caseWhenThenElse [(true, 1), (false, 2)] 3
-- in printSQL expression
-- :}
-- CASE WHEN TRUE THEN (1 :: int2) WHEN FALSE THEN (2 :: int2) ELSE (3 :: int2) END
caseWhenThenElse
:: [ ( Condition grp lat with db params from
, Expression grp lat with db params from ty
) ]
-- ^ whens and thens
-> Expression grp lat with db params from ty
-- ^ else
-> Expression grp lat with db params from ty
caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
[ "CASE"
, mconcat
[ mconcat
[ " WHEN ", renderSQL when_
, " THEN ", renderSQL then_
]
| (when_,then_) <- whenThens
]
, " ELSE ", renderSQL else_
, " END"
]
-- | >>> :{
-- let
-- expression :: Expression grp lat with db params from (null 'PGint2)
-- expression = ifThenElse true 1 0
-- in printSQL expression
-- :}
-- CASE WHEN TRUE THEN (1 :: int2) ELSE (0 :: int2) END
ifThenElse
:: Condition grp lat with db params from
-> Expression grp lat with db params from ty -- ^ then
-> Expression grp lat with db params from ty -- ^ else
-> Expression grp lat with db params from ty
ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_