1{-# language FlexibleContexts #-}
2{-# language TupleSections #-}
4module Rel8.Query.Evaluate
11import Control.Monad ( (>=>) )
12import Data.Foldable ( foldl' )
13import Data.List.NonEmpty ( NonEmpty( (:|) ), nonEmpty )
14import Data.Monoid ( Any( Any ) )
15import Prelude hiding ( undefined )
18import qualified Opaleye.Internal.HaskellDB.PrimQuery as Opaleye
19import qualified Opaleye.Internal.PackMap as Opaleye
20import qualified Opaleye.Internal.PrimQuery as Opaleye
21import qualified Opaleye.Internal.QueryArr as Opaleye
22import qualified Opaleye.Internal.Tag as Opaleye
23import qualified Opaleye.Internal.Unpackspec as Opaleye
26import Rel8.Expr ( Expr )
27import Rel8.Expr.Bool ( (&&.) )
28import Rel8.Expr.Opaleye ( fromPrimExpr )
29import Rel8.Query ( Query( Query ) )
30import Rel8.Table ( Table )
31import Rel8.Table.Bool ( case_ )
32import Rel8.Table.Opaleye ( unpackspec )
33import Rel8.Table.Undefined
36-- | 'evaluate' takes expressions that could potentially have side effects and
37-- \"runs\" them in the 'Query' monad. The returned expressions have no side
38-- effects and can safely be reused.
39evaluate :: Table Expr a => a -> Query a
40evaluate = laterally >=> rebind
43laterally :: Table Expr a => a -> Query a
44laterally a = Query $ \bindings -> pure $ (Any True,) $
45 case nonEmpty bindings of
47 Just bindings' -> case_ [(condition, a)] undefined
49 condition = foldl1' (&&.) (fmap go bindings')
51 go = fromPrimExpr . Opaleye.UnExpr Opaleye.OpIsNotNull
54-- | 'rebind' takes some expressions, and binds each of them to a new
55-- variable in the SQL. The @a@ returned consists only of these
56-- variables. It's essentially a @let@ binding for Postgres expressions.
57rebind :: Table Expr a => a -> Query a
58rebind a = Query $ \_ -> Opaleye.QueryArr $ \(_, tag) ->
60 tag' = Opaleye.next tag
61 (a', bindings) = Opaleye.run $
62 Opaleye.runUnpackspec unpackspec (Opaleye.extractAttr "eval" tag) a
64 ((mempty, a'), \_ -> Opaleye.Rebind True bindings, tag')
67foldl1' :: (a -> a -> a) -> NonEmpty a -> a
68foldl1' f (a :| as) = foldl' f a as
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list