module Rel8.Query.Filter
  ( filter
  , where_
  )
where

-- base
import Prelude hiding ( filter )

-- opaleye
import qualified Opaleye.Operators as Opaleye

-- profunctors
import Data.Profunctor ( lmap )

-- rel8
import Rel8.Expr ( Expr )
import Rel8.Expr.Opaleye ( toColumn, toPrimExpr )
import Rel8.Query ( Query )
import Rel8.Query.Opaleye ( fromOpaleye )


-- | @filter f x@ will be a zero-row query when @f x@ is @False@, and will
-- return @x@ unchanged when @f x@ is @True@. This is similar to
-- 'Control.Monad.guard', but as the predicate is separate from the argument,
-- it is easy to use in a pipeline of 'Query' transformations.
filter :: (a -> Expr Bool) -> a -> Query a
filter :: (a -> Expr Bool) -> a -> Query a
filter a -> Expr Bool
f a
a = a
a a -> Query () -> Query a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Expr Bool -> Query ()
where_ (a -> Expr Bool
f a
a)


-- | Drop any rows that don't match a predicate.  @where_ expr@ is equivalent
-- to the SQL @WHERE expr@.
where_ :: Expr Bool -> Query ()
where_ :: Expr Bool -> Query ()
where_ Expr Bool
condition =
  Select () -> Query ()
forall a. Select a -> Query a
fromOpaleye (Select () -> Query ()) -> Select () -> Query ()
forall a b. (a -> b) -> a -> b
$ (() -> Column SqlBool)
-> SelectArr (Column SqlBool) () -> Select ()
forall (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> p b c -> p a c
lmap (\()
_ -> PrimExpr -> Column SqlBool
forall b. PrimExpr -> Column b
toColumn (PrimExpr -> Column SqlBool) -> PrimExpr -> Column SqlBool
forall a b. (a -> b) -> a -> b
$ Expr Bool -> PrimExpr
forall a. Expr a -> PrimExpr
toPrimExpr Expr Bool
condition) SelectArr (Field SqlBool) ()
SelectArr (Column SqlBool) ()
Opaleye.restrict