{-# LANGUAGE LambdaCase #-}

module Opaleye.Internal.Optimize where

import           Prelude hiding (product)

import qualified Opaleye.Internal.PrimQuery as PQ
import           Opaleye.Internal.Helpers   ((.:))

import qualified Data.List.NonEmpty as NEL
import           Data.Semigroup ((<>))

import           Control.Applicative ((<$>), (<*>), liftA2, pure)
import           Control.Arrow (first)

optimize :: PQ.PrimQuery' a -> PQ.PrimQuery' a
optimize :: PrimQuery' a -> PrimQuery' a
optimize = PrimQuery' a -> PrimQuery' a
forall a. PrimQuery' a -> PrimQuery' a
mergeProduct (PrimQuery' a -> PrimQuery' a)
-> (PrimQuery' a -> PrimQuery' a) -> PrimQuery' a -> PrimQuery' a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrimQuery' a -> PrimQuery' a
forall a. PrimQuery' a -> PrimQuery' a
removeUnit

removeUnit :: PQ.PrimQuery' a -> PQ.PrimQuery' a
removeUnit :: PrimQuery' a -> PrimQuery' a
removeUnit = PrimQueryFold' a (PrimQuery' a) -> PrimQuery' a -> PrimQuery' a
forall a p. PrimQueryFold' a p -> PrimQuery' a -> p
PQ.foldPrimQuery PrimQueryFold' a (PrimQuery' a)
forall a. PrimQueryFold' a (PrimQuery' a)
PQ.primQueryFoldDefault { product :: NonEmpty (Lateral, PrimQuery' a) -> [PrimExpr] -> PrimQuery' a
PQ.product   = NonEmpty (Lateral, PrimQuery' a) -> [PrimExpr] -> PrimQuery' a
forall a.
NonEmpty (Lateral, PrimQuery' a) -> [PrimExpr] -> PrimQuery' a
product }
  where product :: NonEmpty (Lateral, PrimQuery' a) -> [PrimExpr] -> PrimQuery' a
product NonEmpty (Lateral, PrimQuery' a)
pqs = NonEmpty (Lateral, PrimQuery' a) -> [PrimExpr] -> PrimQuery' a
forall a.
NonEmpty (Lateral, PrimQuery' a) -> [PrimExpr] -> PrimQuery' a
PQ.Product NonEmpty (Lateral, PrimQuery' a)
pqs'
          where pqs' :: NonEmpty (Lateral, PrimQuery' a)
pqs' = case [(Lateral, PrimQuery' a)]
-> Maybe (NonEmpty (Lateral, PrimQuery' a))
forall a. [a] -> Maybe (NonEmpty a)
NEL.nonEmpty (((Lateral, PrimQuery' a) -> Bool)
-> NonEmpty (Lateral, PrimQuery' a) -> [(Lateral, PrimQuery' a)]
forall a. (a -> Bool) -> NonEmpty a -> [a]
NEL.filter (Bool -> Bool
not (Bool -> Bool)
-> ((Lateral, PrimQuery' a) -> Bool)
-> (Lateral, PrimQuery' a)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrimQuery' a -> Bool
forall a. PrimQuery' a -> Bool
PQ.isUnit (PrimQuery' a -> Bool)
-> ((Lateral, PrimQuery' a) -> PrimQuery' a)
-> (Lateral, PrimQuery' a)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Lateral, PrimQuery' a) -> PrimQuery' a
forall a b. (a, b) -> b
snd) NonEmpty (Lateral, PrimQuery' a)
pqs) of
                         Maybe (NonEmpty (Lateral, PrimQuery' a))
Nothing -> (Lateral, PrimQuery' a) -> NonEmpty (Lateral, PrimQuery' a)
forall (m :: * -> *) a. Monad m => a -> m a
return (PrimQuery' a -> (Lateral, PrimQuery' a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure PrimQuery' a
forall a. PrimQuery' a
PQ.Unit)
                         Just NonEmpty (Lateral, PrimQuery' a)
xs -> NonEmpty (Lateral, PrimQuery' a)
xs

mergeProduct :: PQ.PrimQuery' a -> PQ.PrimQuery' a
mergeProduct :: PrimQuery' a -> PrimQuery' a
mergeProduct = PrimQueryFold' a (PrimQuery' a) -> PrimQuery' a -> PrimQuery' a
forall a p. PrimQueryFold' a p -> PrimQuery' a -> p
PQ.foldPrimQuery PrimQueryFold' a (PrimQuery' a)
forall a. PrimQueryFold' a (PrimQuery' a)
PQ.primQueryFoldDefault { product :: NonEmpty (Lateral, PrimQuery' a) -> [PrimExpr] -> PrimQuery' a
PQ.product   = NonEmpty (Lateral, PrimQuery' a) -> [PrimExpr] -> PrimQuery' a
forall a.
NonEmpty (Lateral, PrimQuery' a) -> [PrimExpr] -> PrimQuery' a
product }
  where product :: NonEmpty (Lateral, PrimQuery' a) -> [PrimExpr] -> PrimQuery' a
product NonEmpty (Lateral, PrimQuery' a)
pqs [PrimExpr]
pes = NonEmpty (Lateral, PrimQuery' a) -> [PrimExpr] -> PrimQuery' a
forall a.
NonEmpty (Lateral, PrimQuery' a) -> [PrimExpr] -> PrimQuery' a
PQ.Product NonEmpty (Lateral, PrimQuery' a)
pqs' ([PrimExpr]
pes [PrimExpr] -> [PrimExpr] -> [PrimExpr]
forall a. [a] -> [a] -> [a]
++ [PrimExpr]
pes')
          where pqs' :: NonEmpty (Lateral, PrimQuery' a)
pqs' = NonEmpty (Lateral, PrimQuery' a)
pqs NonEmpty (Lateral, PrimQuery' a)
-> ((Lateral, PrimQuery' a) -> NonEmpty (Lateral, PrimQuery' a))
-> NonEmpty (Lateral, PrimQuery' a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Lateral, PrimQuery' a) -> NonEmpty (Lateral, PrimQuery' a)
forall a.
(Lateral, PrimQuery' a) -> NonEmpty (Lateral, PrimQuery' a)
queries
                queries :: (Lateral, PrimQuery' a) -> NonEmpty (Lateral, PrimQuery' a)
queries (Lateral
lat, PQ.Product NonEmpty (Lateral, PrimQuery' a)
qs [PrimExpr]
_) = ((Lateral, PrimQuery' a) -> (Lateral, PrimQuery' a))
-> NonEmpty (Lateral, PrimQuery' a)
-> NonEmpty (Lateral, PrimQuery' a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Lateral -> Lateral)
-> (Lateral, PrimQuery' a) -> (Lateral, PrimQuery' a)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first (Lateral
lat Lateral -> Lateral -> Lateral
forall a. Semigroup a => a -> a -> a
<>)) NonEmpty (Lateral, PrimQuery' a)
qs
                queries (Lateral, PrimQuery' a)
q = (Lateral, PrimQuery' a) -> NonEmpty (Lateral, PrimQuery' a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Lateral, PrimQuery' a)
q
                pes' :: [PrimExpr]
pes' = NonEmpty (Lateral, PrimQuery' a) -> [(Lateral, PrimQuery' a)]
forall a. NonEmpty a -> [a]
NEL.toList NonEmpty (Lateral, PrimQuery' a)
pqs [(Lateral, PrimQuery' a)]
-> ((Lateral, PrimQuery' a) -> [PrimExpr]) -> [PrimExpr]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Lateral, PrimQuery' a) -> [PrimExpr]
forall a a. (a, PrimQuery' a) -> [PrimExpr]
conds
                conds :: (a, PrimQuery' a) -> [PrimExpr]
conds (a
_lat, PQ.Product NonEmpty (Lateral, PrimQuery' a)
_ [PrimExpr]
cs) = [PrimExpr]
cs
                conds (a, PrimQuery' a)
_ = []

removeEmpty :: PQ.PrimQuery' a -> Maybe (PQ.PrimQuery' b)
removeEmpty :: PrimQuery' a -> Maybe (PrimQuery' b)
removeEmpty = PrimQueryFold' a (Maybe (PrimQuery' b))
-> PrimQuery' a -> Maybe (PrimQuery' b)
forall a p. PrimQueryFold' a p -> PrimQuery' a -> p
PQ.foldPrimQuery PrimQueryFold :: forall a p.
p
-> (a -> p)
-> (TableIdentifier -> Bindings PrimExpr -> p)
-> (NonEmpty (Lateral, p) -> [PrimExpr] -> p)
-> (Bindings (Maybe (AggrOp, [OrderExpr], AggrDistinct), Symbol)
    -> p -> p)
-> (Maybe (NonEmpty PrimExpr) -> [OrderExpr] -> p -> p)
-> (LimitOp -> p -> p)
-> (JoinType -> PrimExpr -> (Lateral, p) -> (Lateral, p) -> p)
-> (SemijoinType -> p -> p -> p)
-> (Symbol -> p -> p)
-> ([Symbol] -> NonEmpty [PrimExpr] -> p)
-> (BinOp -> (p, p) -> p)
-> (String -> p -> p)
-> (PrimExpr -> Bindings PrimExpr -> p)
-> (Bool -> Bindings PrimExpr -> p -> p)
-> (p -> p)
-> PrimQueryFold' a p
PQ.PrimQueryFold {
    unit :: Maybe (PrimQuery' b)
PQ.unit      = PrimQuery' b -> Maybe (PrimQuery' b)
forall (m :: * -> *) a. Monad m => a -> m a
return PrimQuery' b
forall a. PrimQuery' a
PQ.Unit
  , empty :: a -> Maybe (PrimQuery' b)
PQ.empty     = Maybe (PrimQuery' b) -> a -> Maybe (PrimQuery' b)
forall a b. a -> b -> a
const Maybe (PrimQuery' b)
forall a. Maybe a
Nothing
  , baseTable :: TableIdentifier -> Bindings PrimExpr -> Maybe (PrimQuery' b)
PQ.baseTable = PrimQuery' b -> Maybe (PrimQuery' b)
forall (m :: * -> *) a. Monad m => a -> m a
return (PrimQuery' b -> Maybe (PrimQuery' b))
-> (TableIdentifier -> Bindings PrimExpr -> PrimQuery' b)
-> TableIdentifier
-> Bindings PrimExpr
-> Maybe (PrimQuery' b)
forall r z a b. (r -> z) -> (a -> b -> r) -> a -> b -> z
.: TableIdentifier -> Bindings PrimExpr -> PrimQuery' b
forall a. TableIdentifier -> Bindings PrimExpr -> PrimQuery' a
PQ.BaseTable
  , product :: NonEmpty (Lateral, Maybe (PrimQuery' b))
-> [PrimExpr] -> Maybe (PrimQuery' b)
PQ.product   = let sequenceOf :: ((a -> a) -> t) -> t
sequenceOf (a -> a) -> t
l = ((a -> a) -> t) -> (a -> a) -> t
forall a. a -> a
traverseOf (a -> a) -> t
l a -> a
forall a. a -> a
id
                       traverseOf :: a -> a
traverseOf = a -> a
forall a. a -> a
id
                       _2 :: (a -> Maybe b) -> (Lateral, a) -> Maybe (Lateral, b)
_2 = (a -> Maybe b) -> (Lateral, a) -> Maybe (Lateral, b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse
                   in
                   \NonEmpty (Lateral, Maybe (PrimQuery' b))
x [PrimExpr]
y -> NonEmpty (Lateral, PrimQuery' b) -> [PrimExpr] -> PrimQuery' b
forall a.
NonEmpty (Lateral, PrimQuery' a) -> [PrimExpr] -> PrimQuery' a
PQ.Product (NonEmpty (Lateral, PrimQuery' b) -> [PrimExpr] -> PrimQuery' b)
-> Maybe (NonEmpty (Lateral, PrimQuery' b))
-> Maybe ([PrimExpr] -> PrimQuery' b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((Maybe (PrimQuery' b) -> Maybe (PrimQuery' b))
 -> NonEmpty (Lateral, Maybe (PrimQuery' b))
 -> Maybe (NonEmpty (Lateral, PrimQuery' b)))
-> NonEmpty (Lateral, Maybe (PrimQuery' b))
-> Maybe (NonEmpty (Lateral, PrimQuery' b))
forall a t. ((a -> a) -> t) -> t
sequenceOf (((Lateral, Maybe (PrimQuery' b)) -> Maybe (Lateral, PrimQuery' b))
-> NonEmpty (Lateral, Maybe (PrimQuery' b))
-> Maybe (NonEmpty (Lateral, PrimQuery' b))
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse(((Lateral, Maybe (PrimQuery' b)) -> Maybe (Lateral, PrimQuery' b))
 -> NonEmpty (Lateral, Maybe (PrimQuery' b))
 -> Maybe (NonEmpty (Lateral, PrimQuery' b)))
-> ((Maybe (PrimQuery' b) -> Maybe (PrimQuery' b))
    -> (Lateral, Maybe (PrimQuery' b))
    -> Maybe (Lateral, PrimQuery' b))
-> (Maybe (PrimQuery' b) -> Maybe (PrimQuery' b))
-> NonEmpty (Lateral, Maybe (PrimQuery' b))
-> Maybe (NonEmpty (Lateral, PrimQuery' b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Maybe (PrimQuery' b) -> Maybe (PrimQuery' b))
-> (Lateral, Maybe (PrimQuery' b)) -> Maybe (Lateral, PrimQuery' b)
forall a b. (a -> Maybe b) -> (Lateral, a) -> Maybe (Lateral, b)
_2) NonEmpty (Lateral, Maybe (PrimQuery' b))
x
                                      Maybe ([PrimExpr] -> PrimQuery' b)
-> Maybe [PrimExpr] -> Maybe (PrimQuery' b)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [PrimExpr] -> Maybe [PrimExpr]
forall (f :: * -> *) a. Applicative f => a -> f a
pure [PrimExpr]
y
  , aggregate :: Bindings (Maybe (AggrOp, [OrderExpr], AggrDistinct), Symbol)
-> Maybe (PrimQuery' b) -> Maybe (PrimQuery' b)
PQ.aggregate = (PrimQuery' b -> PrimQuery' b)
-> Maybe (PrimQuery' b) -> Maybe (PrimQuery' b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((PrimQuery' b -> PrimQuery' b)
 -> Maybe (PrimQuery' b) -> Maybe (PrimQuery' b))
-> (Bindings (Maybe (AggrOp, [OrderExpr], AggrDistinct), Symbol)
    -> PrimQuery' b -> PrimQuery' b)
-> Bindings (Maybe (AggrOp, [OrderExpr], AggrDistinct), Symbol)
-> Maybe (PrimQuery' b)
-> Maybe (PrimQuery' b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bindings (Maybe (AggrOp, [OrderExpr], AggrDistinct), Symbol)
-> PrimQuery' b -> PrimQuery' b
forall a.
Bindings (Maybe (AggrOp, [OrderExpr], AggrDistinct), Symbol)
-> PrimQuery' a -> PrimQuery' a
PQ.Aggregate
  , distinctOnOrderBy :: Maybe (NonEmpty PrimExpr)
-> [OrderExpr] -> Maybe (PrimQuery' b) -> Maybe (PrimQuery' b)
PQ.distinctOnOrderBy = \Maybe (NonEmpty PrimExpr)
mDistinctOns -> (PrimQuery' b -> PrimQuery' b)
-> Maybe (PrimQuery' b) -> Maybe (PrimQuery' b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((PrimQuery' b -> PrimQuery' b)
 -> Maybe (PrimQuery' b) -> Maybe (PrimQuery' b))
-> ([OrderExpr] -> PrimQuery' b -> PrimQuery' b)
-> [OrderExpr]
-> Maybe (PrimQuery' b)
-> Maybe (PrimQuery' b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe (NonEmpty PrimExpr)
-> [OrderExpr] -> PrimQuery' b -> PrimQuery' b
forall a.
Maybe (NonEmpty PrimExpr)
-> [OrderExpr] -> PrimQuery' a -> PrimQuery' a
PQ.DistinctOnOrderBy Maybe (NonEmpty PrimExpr)
mDistinctOns
  , limit :: LimitOp -> Maybe (PrimQuery' b) -> Maybe (PrimQuery' b)
PQ.limit     = (PrimQuery' b -> PrimQuery' b)
-> Maybe (PrimQuery' b) -> Maybe (PrimQuery' b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((PrimQuery' b -> PrimQuery' b)
 -> Maybe (PrimQuery' b) -> Maybe (PrimQuery' b))
-> (LimitOp -> PrimQuery' b -> PrimQuery' b)
-> LimitOp
-> Maybe (PrimQuery' b)
-> Maybe (PrimQuery' b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LimitOp -> PrimQuery' b -> PrimQuery' b
forall a. LimitOp -> PrimQuery' a -> PrimQuery' a
PQ.Limit
  , join :: JoinType
-> PrimExpr
-> (Lateral, Maybe (PrimQuery' b))
-> (Lateral, Maybe (PrimQuery' b))
-> Maybe (PrimQuery' b)
PQ.join      = \JoinType
jt PrimExpr
pe (Lateral, Maybe (PrimQuery' b))
pq1 (Lateral, Maybe (PrimQuery' b))
pq2 -> JoinType
-> PrimExpr
-> (Lateral, PrimQuery' b)
-> (Lateral, PrimQuery' b)
-> PrimQuery' b
forall a.
JoinType
-> PrimExpr
-> (Lateral, PrimQuery' a)
-> (Lateral, PrimQuery' a)
-> PrimQuery' a
PQ.Join JoinType
jt PrimExpr
pe ((Lateral, PrimQuery' b)
 -> (Lateral, PrimQuery' b) -> PrimQuery' b)
-> Maybe (Lateral, PrimQuery' b)
-> Maybe ((Lateral, PrimQuery' b) -> PrimQuery' b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Lateral, Maybe (PrimQuery' b)) -> Maybe (Lateral, PrimQuery' b)
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence (Lateral, Maybe (PrimQuery' b))
pq1 Maybe ((Lateral, PrimQuery' b) -> PrimQuery' b)
-> Maybe (Lateral, PrimQuery' b) -> Maybe (PrimQuery' b)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Lateral, Maybe (PrimQuery' b)) -> Maybe (Lateral, PrimQuery' b)
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence (Lateral, Maybe (PrimQuery' b))
pq2
  , semijoin :: SemijoinType
-> Maybe (PrimQuery' b)
-> Maybe (PrimQuery' b)
-> Maybe (PrimQuery' b)
PQ.semijoin  = (PrimQuery' b -> PrimQuery' b -> PrimQuery' b)
-> Maybe (PrimQuery' b)
-> Maybe (PrimQuery' b)
-> Maybe (PrimQuery' b)
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 ((PrimQuery' b -> PrimQuery' b -> PrimQuery' b)
 -> Maybe (PrimQuery' b)
 -> Maybe (PrimQuery' b)
 -> Maybe (PrimQuery' b))
-> (SemijoinType -> PrimQuery' b -> PrimQuery' b -> PrimQuery' b)
-> SemijoinType
-> Maybe (PrimQuery' b)
-> Maybe (PrimQuery' b)
-> Maybe (PrimQuery' b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SemijoinType -> PrimQuery' b -> PrimQuery' b -> PrimQuery' b
forall a.
SemijoinType -> PrimQuery' a -> PrimQuery' a -> PrimQuery' a
PQ.Semijoin
  , exists :: Symbol -> Maybe (PrimQuery' b) -> Maybe (PrimQuery' b)
PQ.exists    = (PrimQuery' b -> PrimQuery' b)
-> Maybe (PrimQuery' b) -> Maybe (PrimQuery' b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((PrimQuery' b -> PrimQuery' b)
 -> Maybe (PrimQuery' b) -> Maybe (PrimQuery' b))
-> (Symbol -> PrimQuery' b -> PrimQuery' b)
-> Symbol
-> Maybe (PrimQuery' b)
-> Maybe (PrimQuery' b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Symbol -> PrimQuery' b -> PrimQuery' b
forall a. Symbol -> PrimQuery' a -> PrimQuery' a
PQ.Exists
  , values :: [Symbol] -> NonEmpty [PrimExpr] -> Maybe (PrimQuery' b)
PQ.values    = PrimQuery' b -> Maybe (PrimQuery' b)
forall (m :: * -> *) a. Monad m => a -> m a
return (PrimQuery' b -> Maybe (PrimQuery' b))
-> ([Symbol] -> NonEmpty [PrimExpr] -> PrimQuery' b)
-> [Symbol]
-> NonEmpty [PrimExpr]
-> Maybe (PrimQuery' b)
forall r z a b. (r -> z) -> (a -> b -> r) -> a -> b -> z
.: [Symbol] -> NonEmpty [PrimExpr] -> PrimQuery' b
forall a. [Symbol] -> NonEmpty [PrimExpr] -> PrimQuery' a
PQ.Values
  , binary :: BinOp
-> (Maybe (PrimQuery' b), Maybe (PrimQuery' b))
-> Maybe (PrimQuery' b)
PQ.binary    = \case
      -- Some unfortunate duplication here
      BinOp
PQ.Except       -> (PrimQuery' b -> Maybe (PrimQuery' b))
-> (PrimQuery' b -> Maybe (PrimQuery' b))
-> BinOp
-> (Maybe (PrimQuery' b), Maybe (PrimQuery' b))
-> Maybe (PrimQuery' b)
forall a.
(PrimQuery' a -> Maybe (PrimQuery' a))
-> (PrimQuery' a -> Maybe (PrimQuery' a))
-> BinOp
-> (Maybe (PrimQuery' a), Maybe (PrimQuery' a))
-> Maybe (PrimQuery' a)
binary PrimQuery' b -> Maybe (PrimQuery' b)
forall a. a -> Maybe a
Just            (Maybe (PrimQuery' b) -> PrimQuery' b -> Maybe (PrimQuery' b)
forall a b. a -> b -> a
const Maybe (PrimQuery' b)
forall a. Maybe a
Nothing) BinOp
PQ.Except
      BinOp
PQ.Union        -> (PrimQuery' b -> Maybe (PrimQuery' b))
-> (PrimQuery' b -> Maybe (PrimQuery' b))
-> BinOp
-> (Maybe (PrimQuery' b), Maybe (PrimQuery' b))
-> Maybe (PrimQuery' b)
forall a.
(PrimQuery' a -> Maybe (PrimQuery' a))
-> (PrimQuery' a -> Maybe (PrimQuery' a))
-> BinOp
-> (Maybe (PrimQuery' a), Maybe (PrimQuery' a))
-> Maybe (PrimQuery' a)
binary PrimQuery' b -> Maybe (PrimQuery' b)
forall a. a -> Maybe a
Just            PrimQuery' b -> Maybe (PrimQuery' b)
forall a. a -> Maybe a
Just            BinOp
PQ.Union
      BinOp
PQ.Intersect    -> (PrimQuery' b -> Maybe (PrimQuery' b))
-> (PrimQuery' b -> Maybe (PrimQuery' b))
-> BinOp
-> (Maybe (PrimQuery' b), Maybe (PrimQuery' b))
-> Maybe (PrimQuery' b)
forall a.
(PrimQuery' a -> Maybe (PrimQuery' a))
-> (PrimQuery' a -> Maybe (PrimQuery' a))
-> BinOp
-> (Maybe (PrimQuery' a), Maybe (PrimQuery' a))
-> Maybe (PrimQuery' a)
binary (Maybe (PrimQuery' b) -> PrimQuery' b -> Maybe (PrimQuery' b)
forall a b. a -> b -> a
const Maybe (PrimQuery' b)
forall a. Maybe a
Nothing) (Maybe (PrimQuery' b) -> PrimQuery' b -> Maybe (PrimQuery' b)
forall a b. a -> b -> a
const Maybe (PrimQuery' b)
forall a. Maybe a
Nothing) BinOp
PQ.Intersect

      BinOp
PQ.ExceptAll    -> (PrimQuery' b -> Maybe (PrimQuery' b))
-> (PrimQuery' b -> Maybe (PrimQuery' b))
-> BinOp
-> (Maybe (PrimQuery' b), Maybe (PrimQuery' b))
-> Maybe (PrimQuery' b)
forall a.
(PrimQuery' a -> Maybe (PrimQuery' a))
-> (PrimQuery' a -> Maybe (PrimQuery' a))
-> BinOp
-> (Maybe (PrimQuery' a), Maybe (PrimQuery' a))
-> Maybe (PrimQuery' a)
binary PrimQuery' b -> Maybe (PrimQuery' b)
forall a. a -> Maybe a
Just            (Maybe (PrimQuery' b) -> PrimQuery' b -> Maybe (PrimQuery' b)
forall a b. a -> b -> a
const Maybe (PrimQuery' b)
forall a. Maybe a
Nothing) BinOp
PQ.ExceptAll
      BinOp
PQ.UnionAll     -> (PrimQuery' b -> Maybe (PrimQuery' b))
-> (PrimQuery' b -> Maybe (PrimQuery' b))
-> BinOp
-> (Maybe (PrimQuery' b), Maybe (PrimQuery' b))
-> Maybe (PrimQuery' b)
forall a.
(PrimQuery' a -> Maybe (PrimQuery' a))
-> (PrimQuery' a -> Maybe (PrimQuery' a))
-> BinOp
-> (Maybe (PrimQuery' a), Maybe (PrimQuery' a))
-> Maybe (PrimQuery' a)
binary PrimQuery' b -> Maybe (PrimQuery' b)
forall a. a -> Maybe a
Just            PrimQuery' b -> Maybe (PrimQuery' b)
forall a. a -> Maybe a
Just            BinOp
PQ.UnionAll
      BinOp
PQ.IntersectAll -> (PrimQuery' b -> Maybe (PrimQuery' b))
-> (PrimQuery' b -> Maybe (PrimQuery' b))
-> BinOp
-> (Maybe (PrimQuery' b), Maybe (PrimQuery' b))
-> Maybe (PrimQuery' b)
forall a.
(PrimQuery' a -> Maybe (PrimQuery' a))
-> (PrimQuery' a -> Maybe (PrimQuery' a))
-> BinOp
-> (Maybe (PrimQuery' a), Maybe (PrimQuery' a))
-> Maybe (PrimQuery' a)
binary (Maybe (PrimQuery' b) -> PrimQuery' b -> Maybe (PrimQuery' b)
forall a b. a -> b -> a
const Maybe (PrimQuery' b)
forall a. Maybe a
Nothing) (Maybe (PrimQuery' b) -> PrimQuery' b -> Maybe (PrimQuery' b)
forall a b. a -> b -> a
const Maybe (PrimQuery' b)
forall a. Maybe a
Nothing) BinOp
PQ.IntersectAll
  , label :: String -> Maybe (PrimQuery' b) -> Maybe (PrimQuery' b)
PQ.label     = (PrimQuery' b -> PrimQuery' b)
-> Maybe (PrimQuery' b) -> Maybe (PrimQuery' b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((PrimQuery' b -> PrimQuery' b)
 -> Maybe (PrimQuery' b) -> Maybe (PrimQuery' b))
-> (String -> PrimQuery' b -> PrimQuery' b)
-> String
-> Maybe (PrimQuery' b)
-> Maybe (PrimQuery' b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> PrimQuery' b -> PrimQuery' b
forall a. String -> PrimQuery' a -> PrimQuery' a
PQ.Label
  , relExpr :: PrimExpr -> Bindings PrimExpr -> Maybe (PrimQuery' b)
PQ.relExpr   = PrimQuery' b -> Maybe (PrimQuery' b)
forall (m :: * -> *) a. Monad m => a -> m a
return (PrimQuery' b -> Maybe (PrimQuery' b))
-> (PrimExpr -> Bindings PrimExpr -> PrimQuery' b)
-> PrimExpr
-> Bindings PrimExpr
-> Maybe (PrimQuery' b)
forall r z a b. (r -> z) -> (a -> b -> r) -> a -> b -> z
.: PrimExpr -> Bindings PrimExpr -> PrimQuery' b
forall a. PrimExpr -> Bindings PrimExpr -> PrimQuery' a
PQ.RelExpr
  , rebind :: Bool
-> Bindings PrimExpr
-> Maybe (PrimQuery' b)
-> Maybe (PrimQuery' b)
PQ.rebind    = \Bool
b -> (PrimQuery' b -> PrimQuery' b)
-> Maybe (PrimQuery' b) -> Maybe (PrimQuery' b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((PrimQuery' b -> PrimQuery' b)
 -> Maybe (PrimQuery' b) -> Maybe (PrimQuery' b))
-> (Bindings PrimExpr -> PrimQuery' b -> PrimQuery' b)
-> Bindings PrimExpr
-> Maybe (PrimQuery' b)
-> Maybe (PrimQuery' b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Bindings PrimExpr -> PrimQuery' b -> PrimQuery' b
forall a. Bool -> Bindings PrimExpr -> PrimQuery' a -> PrimQuery' a
PQ.Rebind Bool
b
  , forUpdate :: Maybe (PrimQuery' b) -> Maybe (PrimQuery' b)
PQ.forUpdate = (PrimQuery' b -> PrimQuery' b)
-> Maybe (PrimQuery' b) -> Maybe (PrimQuery' b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap PrimQuery' b -> PrimQuery' b
forall a. PrimQuery' a -> PrimQuery' a
PQ.ForUpdate
  }
  where -- If only the first argument is Just, do n1 on it
        -- If only the second argument is Just, do n2 on it
        binary :: (PrimQuery' a -> Maybe (PrimQuery' a))
-> (PrimQuery' a -> Maybe (PrimQuery' a))
-> BinOp
-> (Maybe (PrimQuery' a), Maybe (PrimQuery' a))
-> Maybe (PrimQuery' a)
binary PrimQuery' a -> Maybe (PrimQuery' a)
n1 PrimQuery' a -> Maybe (PrimQuery' a)
n2 BinOp
jj = \case
          (Maybe (PrimQuery' a)
Nothing, Maybe (PrimQuery' a)
Nothing)   -> Maybe (PrimQuery' a)
forall a. Maybe a
Nothing
          (Maybe (PrimQuery' a)
Nothing, Just PrimQuery' a
pq2)  -> PrimQuery' a -> Maybe (PrimQuery' a)
n2 PrimQuery' a
pq2
          (Just PrimQuery' a
pq1, Maybe (PrimQuery' a)
Nothing)  -> PrimQuery' a -> Maybe (PrimQuery' a)
n1 PrimQuery' a
pq1
          (Just PrimQuery' a
pq1, Just PrimQuery' a
pq2) -> PrimQuery' a -> Maybe (PrimQuery' a)
forall a. a -> Maybe a
Just (BinOp -> (PrimQuery' a, PrimQuery' a) -> PrimQuery' a
forall a. BinOp -> (PrimQuery' a, PrimQuery' a) -> PrimQuery' a
PQ.Binary BinOp
jj (PrimQuery' a
pq1, PrimQuery' a
pq2))