-- |
-- Module      : Database.Relational.Set
-- Copyright   : 2013-2017 Kei Hibino
-- License     : BSD3
--
-- Maintainer  : ex8k.hibino@gmail.com
-- Stability   : experimental
-- Portability : unknown
--
-- This module defines set operations on monadic Relation operations.
module Database.Relational.Set (
  -- * Direct style join
  JoinRestriction,
  inner', left', right', full',
  inner, left, right, full,
  on',

  -- * Relation append
  union, except, intersect,
  unionAll, exceptAll, intersectAll,

  union', except', intersect',
  unionAll', exceptAll', intersectAll',
  ) where

import Data.Functor.ProductIsomorphic ((|$|), (|*|))

import Database.Relational.Internal.ContextType (Flat)
import Database.Relational.SqlSyntax
  (Duplication (Distinct, All), SubQuery, Predicate, Record, )
import qualified Database.Relational.SqlSyntax as Syntax

import Database.Relational.Monad.BaseType
  (Relation, unsafeTypeRelation, untypeRelation, )
import Database.Relational.Monad.Class (MonadQuery (query', queryMaybe'), on)
import Database.Relational.Monad.Simple (QuerySimple)
import Database.Relational.Projectable (PlaceHolders)
import Database.Relational.Relation (relation', relation, query, queryMaybe, )


-- | Restriction predicate function type for direct style join operator,
--   used on predicates of direct join style as follows.
--
-- @
--   do xy <- query $
--            relX `inner` relY `on'` [ \x y -> ... ] -- this lambda form has JoinRestriction type
--      ...
-- @
type JoinRestriction a b = Record Flat a -> Record Flat b -> Predicate Flat

-- | Basic direct join operation with place-holder parameters.
join' :: (qa -> QuerySimple (PlaceHolders pa, Record Flat a))
      -> (qb -> QuerySimple (PlaceHolders pb, Record Flat b))
      -> qa
      -> qb
      -> [JoinRestriction a b]
      -> Relation (pa, pb) (a, b)
join' :: (qa -> QuerySimple (PlaceHolders pa, Record Flat a))
-> (qb -> QuerySimple (PlaceHolders pb, Record Flat b))
-> qa
-> qb
-> [JoinRestriction a b]
-> Relation (pa, pb) (a, b)
join' qa -> QuerySimple (PlaceHolders pa, Record Flat a)
qL qb -> QuerySimple (PlaceHolders pb, Record Flat b)
qR qa
r0 qb
r1 [JoinRestriction a b]
rs = SimpleQuery (pa, pb) (a, b) -> Relation (pa, pb) (a, b)
forall p r. SimpleQuery p r -> Relation p r
relation' (SimpleQuery (pa, pb) (a, b) -> Relation (pa, pb) (a, b))
-> SimpleQuery (pa, pb) (a, b) -> Relation (pa, pb) (a, b)
forall a b. (a -> b) -> a -> b
$ do
  (PlaceHolders pa
ph0, Record Flat a
pj0) <- qa -> QuerySimple (PlaceHolders pa, Record Flat a)
qL qa
r0
  (PlaceHolders pb
ph1, Record Flat b
pj1) <- qb -> QuerySimple (PlaceHolders pb, Record Flat b)
qR qb
r1
  [Orderings Flat QueryCore ()] -> Orderings Flat QueryCore ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ [ Predicate Flat -> Orderings Flat QueryCore ()
forall (m :: * -> *). MonadQuery m => Predicate Flat -> m ()
on (Predicate Flat -> Orderings Flat QueryCore ())
-> Predicate Flat -> Orderings Flat QueryCore ()
forall a b. (a -> b) -> a -> b
$ JoinRestriction a b
f Record Flat a
pj0 Record Flat b
pj1 | JoinRestriction a b
f <- [JoinRestriction a b]
rs ]
  (PlaceHolders (pa, pb), Record Flat (a, b))
-> SimpleQuery (pa, pb) (a, b)
forall (m :: * -> *) a. Monad m => a -> m a
return ((,) (pa -> pb -> (pa, pb))
-> PlaceHolders pa -> PlaceHolders (pb -> (pa, pb))
forall (f :: * -> *) a b.
(ProductIsoFunctor f, ProductConstructor (a -> b)) =>
(a -> b) -> f a -> f b
|$| PlaceHolders pa
ph0 PlaceHolders (pb -> (pa, pb))
-> PlaceHolders pb -> PlaceHolders (pa, pb)
forall (f :: * -> *) a b.
ProductIsoApplicative f =>
f (a -> b) -> f a -> f b
|*| PlaceHolders pb
ph1, (,) (a -> b -> (a, b)) -> Record Flat a -> Record Flat (b -> (a, b))
forall (f :: * -> *) a b.
(ProductIsoFunctor f, ProductConstructor (a -> b)) =>
(a -> b) -> f a -> f b
|$| Record Flat a
pj0 Record Flat (b -> (a, b)) -> Record Flat b -> Record Flat (a, b)
forall (f :: * -> *) a b.
ProductIsoApplicative f =>
f (a -> b) -> f a -> f b
|*| Record Flat b
pj1)

-- | Direct inner join with place-holder parameters.
inner' :: Relation pa a            -- ^ Left query to join
       -> Relation pb b            -- ^ Right query to join
       -> [JoinRestriction a b]    -- ^ Join restrictions
       -> Relation (pa, pb) (a, b) -- ^ Result joined relation
inner' :: Relation pa a
-> Relation pb b
-> [JoinRestriction a b]
-> Relation (pa, pb) (a, b)
inner' =  (Relation pa a -> QuerySimple (PlaceHolders pa, Record Flat a))
-> (Relation pb b -> QuerySimple (PlaceHolders pb, Record Flat b))
-> Relation pa a
-> Relation pb b
-> [JoinRestriction a b]
-> Relation (pa, pb) (a, b)
forall qa pa a qb pb b.
(qa -> QuerySimple (PlaceHolders pa, Record Flat a))
-> (qb -> QuerySimple (PlaceHolders pb, Record Flat b))
-> qa
-> qb
-> [JoinRestriction a b]
-> Relation (pa, pb) (a, b)
join' Relation pa a -> QuerySimple (PlaceHolders pa, Record Flat a)
forall (m :: * -> *) p r.
MonadQuery m =>
Relation p r -> m (PlaceHolders p, Record Flat r)
query' Relation pb b -> QuerySimple (PlaceHolders pb, Record Flat b)
forall (m :: * -> *) p r.
MonadQuery m =>
Relation p r -> m (PlaceHolders p, Record Flat r)
query'

-- | Direct left outer join with place-holder parameters.
left' :: Relation pa a                  -- ^ Left query to join
      -> Relation pb b                  -- ^ Right query to join
      -> [JoinRestriction a (Maybe b)]  -- ^ Join restrictions
      -> Relation (pa, pb) (a, Maybe b) -- ^ Result joined relation
left' :: Relation pa a
-> Relation pb b
-> [JoinRestriction a (Maybe b)]
-> Relation (pa, pb) (a, Maybe b)
left'  =  (Relation pa a -> QuerySimple (PlaceHolders pa, Record Flat a))
-> (Relation pb b
    -> QuerySimple (PlaceHolders pb, Record Flat (Maybe b)))
-> Relation pa a
-> Relation pb b
-> [JoinRestriction a (Maybe b)]
-> Relation (pa, pb) (a, Maybe b)
forall qa pa a qb pb b.
(qa -> QuerySimple (PlaceHolders pa, Record Flat a))
-> (qb -> QuerySimple (PlaceHolders pb, Record Flat b))
-> qa
-> qb
-> [JoinRestriction a b]
-> Relation (pa, pb) (a, b)
join' Relation pa a -> QuerySimple (PlaceHolders pa, Record Flat a)
forall (m :: * -> *) p r.
MonadQuery m =>
Relation p r -> m (PlaceHolders p, Record Flat r)
query' Relation pb b
-> QuerySimple (PlaceHolders pb, Record Flat (Maybe b))
forall (m :: * -> *) p r.
MonadQuery m =>
Relation p r -> m (PlaceHolders p, Record Flat (Maybe r))
queryMaybe'

-- | Direct right outer join with place-holder parameters.
right' :: Relation pa a                 -- ^ Left query to join
       -> Relation pb b                 -- ^ Right query to join
       -> [JoinRestriction (Maybe a) b] -- ^ Join restrictions
       -> Relation (pa, pb)(Maybe a, b) -- ^ Result joined relation
right' :: Relation pa a
-> Relation pb b
-> [JoinRestriction (Maybe a) b]
-> Relation (pa, pb) (Maybe a, b)
right' =  (Relation pa a
 -> QuerySimple (PlaceHolders pa, Record Flat (Maybe a)))
-> (Relation pb b -> QuerySimple (PlaceHolders pb, Record Flat b))
-> Relation pa a
-> Relation pb b
-> [JoinRestriction (Maybe a) b]
-> Relation (pa, pb) (Maybe a, b)
forall qa pa a qb pb b.
(qa -> QuerySimple (PlaceHolders pa, Record Flat a))
-> (qb -> QuerySimple (PlaceHolders pb, Record Flat b))
-> qa
-> qb
-> [JoinRestriction a b]
-> Relation (pa, pb) (a, b)
join' Relation pa a
-> QuerySimple (PlaceHolders pa, Record Flat (Maybe a))
forall (m :: * -> *) p r.
MonadQuery m =>
Relation p r -> m (PlaceHolders p, Record Flat (Maybe r))
queryMaybe' Relation pb b -> QuerySimple (PlaceHolders pb, Record Flat b)
forall (m :: * -> *) p r.
MonadQuery m =>
Relation p r -> m (PlaceHolders p, Record Flat r)
query'

-- | Direct full outer join with place-holder parameters.
full' :: Relation pa a                         -- ^ Left query to join
      -> Relation pb b                         -- ^ Right query to join
      -> [JoinRestriction (Maybe a) (Maybe b)] -- ^ Join restrictions
      -> Relation (pa, pb) (Maybe a, Maybe b)  -- ^ Result joined relation
full' :: Relation pa a
-> Relation pb b
-> [JoinRestriction (Maybe a) (Maybe b)]
-> Relation (pa, pb) (Maybe a, Maybe b)
full'  =  (Relation pa a
 -> QuerySimple (PlaceHolders pa, Record Flat (Maybe a)))
-> (Relation pb b
    -> QuerySimple (PlaceHolders pb, Record Flat (Maybe b)))
-> Relation pa a
-> Relation pb b
-> [JoinRestriction (Maybe a) (Maybe b)]
-> Relation (pa, pb) (Maybe a, Maybe b)
forall qa pa a qb pb b.
(qa -> QuerySimple (PlaceHolders pa, Record Flat a))
-> (qb -> QuerySimple (PlaceHolders pb, Record Flat b))
-> qa
-> qb
-> [JoinRestriction a b]
-> Relation (pa, pb) (a, b)
join' Relation pa a
-> QuerySimple (PlaceHolders pa, Record Flat (Maybe a))
forall (m :: * -> *) p r.
MonadQuery m =>
Relation p r -> m (PlaceHolders p, Record Flat (Maybe r))
queryMaybe' Relation pb b
-> QuerySimple (PlaceHolders pb, Record Flat (Maybe b))
forall (m :: * -> *) p r.
MonadQuery m =>
Relation p r -> m (PlaceHolders p, Record Flat (Maybe r))
queryMaybe'

-- | Basic direct join operation.
join_ :: (qa -> QuerySimple (Record Flat a))
      -> (qb -> QuerySimple (Record Flat b))
      -> qa
      -> qb
      -> [JoinRestriction a b]
      -> Relation () (a, b)
join_ :: (qa -> QuerySimple (Record Flat a))
-> (qb -> QuerySimple (Record Flat b))
-> qa
-> qb
-> [JoinRestriction a b]
-> Relation () (a, b)
join_ qa -> QuerySimple (Record Flat a)
qL qb -> QuerySimple (Record Flat b)
qR qa
r0 qb
r1 [JoinRestriction a b]
rs = QuerySimple (Record Flat (a, b)) -> Relation () (a, b)
forall r. QuerySimple (Record Flat r) -> Relation () r
relation (QuerySimple (Record Flat (a, b)) -> Relation () (a, b))
-> QuerySimple (Record Flat (a, b)) -> Relation () (a, b)
forall a b. (a -> b) -> a -> b
$ do
  Record Flat a
pj0 <- qa -> QuerySimple (Record Flat a)
qL qa
r0
  Record Flat b
pj1 <- qb -> QuerySimple (Record Flat b)
qR qb
r1
  [Orderings Flat QueryCore ()] -> Orderings Flat QueryCore ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ [ Predicate Flat -> Orderings Flat QueryCore ()
forall (m :: * -> *). MonadQuery m => Predicate Flat -> m ()
on (Predicate Flat -> Orderings Flat QueryCore ())
-> Predicate Flat -> Orderings Flat QueryCore ()
forall a b. (a -> b) -> a -> b
$ JoinRestriction a b
f Record Flat a
pj0 Record Flat b
pj1 | JoinRestriction a b
f <- [JoinRestriction a b]
rs ]
  Record Flat (a, b) -> QuerySimple (Record Flat (a, b))
forall (m :: * -> *) a. Monad m => a -> m a
return (Record Flat (a, b) -> QuerySimple (Record Flat (a, b)))
-> Record Flat (a, b) -> QuerySimple (Record Flat (a, b))
forall a b. (a -> b) -> a -> b
$ (,) (a -> b -> (a, b)) -> Record Flat a -> Record Flat (b -> (a, b))
forall (f :: * -> *) a b.
(ProductIsoFunctor f, ProductConstructor (a -> b)) =>
(a -> b) -> f a -> f b
|$| Record Flat a
pj0 Record Flat (b -> (a, b)) -> Record Flat b -> Record Flat (a, b)
forall (f :: * -> *) a b.
ProductIsoApplicative f =>
f (a -> b) -> f a -> f b
|*| Record Flat b
pj1

-- | Direct inner join.
inner :: Relation () a         -- ^ Left query to join
      -> Relation () b         -- ^ Right query to join
      -> [JoinRestriction a b] -- ^ Join restrictions
      -> Relation () (a, b)    -- ^ Result joined relation
inner :: Relation () a
-> Relation () b -> [JoinRestriction a b] -> Relation () (a, b)
inner =  (Relation () a -> QuerySimple (Record Flat a))
-> (Relation () b -> QuerySimple (Record Flat b))
-> Relation () a
-> Relation () b
-> [JoinRestriction a b]
-> Relation () (a, b)
forall qa a qb b.
(qa -> QuerySimple (Record Flat a))
-> (qb -> QuerySimple (Record Flat b))
-> qa
-> qb
-> [JoinRestriction a b]
-> Relation () (a, b)
join_ Relation () a -> QuerySimple (Record Flat a)
forall (m :: * -> *) r.
(MonadQualify ConfigureQuery m, MonadQuery m) =>
Relation () r -> m (Record Flat r)
query Relation () b -> QuerySimple (Record Flat b)
forall (m :: * -> *) r.
(MonadQualify ConfigureQuery m, MonadQuery m) =>
Relation () r -> m (Record Flat r)
query

-- | Direct left outer join.
left :: Relation () a                 -- ^ Left query to join
     -> Relation () b                 -- ^ Right query to join
     -> [JoinRestriction a (Maybe b)] -- ^ Join restrictions
     -> Relation () (a, Maybe b)      -- ^ Result joined relation
left :: Relation () a
-> Relation () b
-> [JoinRestriction a (Maybe b)]
-> Relation () (a, Maybe b)
left  =  (Relation () a -> QuerySimple (Record Flat a))
-> (Relation () b -> QuerySimple (Record Flat (Maybe b)))
-> Relation () a
-> Relation () b
-> [JoinRestriction a (Maybe b)]
-> Relation () (a, Maybe b)
forall qa a qb b.
(qa -> QuerySimple (Record Flat a))
-> (qb -> QuerySimple (Record Flat b))
-> qa
-> qb
-> [JoinRestriction a b]
-> Relation () (a, b)
join_ Relation () a -> QuerySimple (Record Flat a)
forall (m :: * -> *) r.
(MonadQualify ConfigureQuery m, MonadQuery m) =>
Relation () r -> m (Record Flat r)
query Relation () b -> QuerySimple (Record Flat (Maybe b))
forall (m :: * -> *) r.
(MonadQualify ConfigureQuery m, MonadQuery m) =>
Relation () r -> m (Record Flat (Maybe r))
queryMaybe

-- | Direct right outer join.
right :: Relation () a                 -- ^ Left query to join
      -> Relation () b                 -- ^ Right query to join
      -> [JoinRestriction (Maybe a) b] -- ^ Join restrictions
      -> Relation () (Maybe a, b)      -- ^ Result joined relation
right :: Relation () a
-> Relation () b
-> [JoinRestriction (Maybe a) b]
-> Relation () (Maybe a, b)
right =  (Relation () a -> QuerySimple (Record Flat (Maybe a)))
-> (Relation () b -> QuerySimple (Record Flat b))
-> Relation () a
-> Relation () b
-> [JoinRestriction (Maybe a) b]
-> Relation () (Maybe a, b)
forall qa a qb b.
(qa -> QuerySimple (Record Flat a))
-> (qb -> QuerySimple (Record Flat b))
-> qa
-> qb
-> [JoinRestriction a b]
-> Relation () (a, b)
join_ Relation () a -> QuerySimple (Record Flat (Maybe a))
forall (m :: * -> *) r.
(MonadQualify ConfigureQuery m, MonadQuery m) =>
Relation () r -> m (Record Flat (Maybe r))
queryMaybe Relation () b -> QuerySimple (Record Flat b)
forall (m :: * -> *) r.
(MonadQualify ConfigureQuery m, MonadQuery m) =>
Relation () r -> m (Record Flat r)
query

-- | Direct full outer join.
full :: Relation () a                         -- ^ Left query to join
     -> Relation () b                         -- ^ Right query to join
     -> [JoinRestriction (Maybe a) (Maybe b)] -- ^ Join restrictions
     -> Relation () (Maybe a, Maybe b)        -- ^ Result joined relation
full :: Relation () a
-> Relation () b
-> [JoinRestriction (Maybe a) (Maybe b)]
-> Relation () (Maybe a, Maybe b)
full  =  (Relation () a -> QuerySimple (Record Flat (Maybe a)))
-> (Relation () b -> QuerySimple (Record Flat (Maybe b)))
-> Relation () a
-> Relation () b
-> [JoinRestriction (Maybe a) (Maybe b)]
-> Relation () (Maybe a, Maybe b)
forall qa a qb b.
(qa -> QuerySimple (Record Flat a))
-> (qb -> QuerySimple (Record Flat b))
-> qa
-> qb
-> [JoinRestriction a b]
-> Relation () (a, b)
join_ Relation () a -> QuerySimple (Record Flat (Maybe a))
forall (m :: * -> *) r.
(MonadQualify ConfigureQuery m, MonadQuery m) =>
Relation () r -> m (Record Flat (Maybe r))
queryMaybe Relation () b -> QuerySimple (Record Flat (Maybe b))
forall (m :: * -> *) r.
(MonadQualify ConfigureQuery m, MonadQuery m) =>
Relation () r -> m (Record Flat (Maybe r))
queryMaybe

-- | Apply restriction for direct join style.
on' :: ([JoinRestriction a b] -> Relation pc (a, b))
    -> [JoinRestriction a b]
    -> Relation pc (a, b)
on' :: ([JoinRestriction a b] -> Relation pc (a, b))
-> [JoinRestriction a b] -> Relation pc (a, b)
on' =  ([JoinRestriction a b] -> Relation pc (a, b))
-> [JoinRestriction a b] -> Relation pc (a, b)
forall a b. (a -> b) -> a -> b
($)

infixl 8 `inner'`, `left'`, `right'`, `full'`, `inner`, `left`, `right`, `full`, `on'`

unsafeLiftAppend :: (SubQuery -> SubQuery -> SubQuery)
           -> Relation p a
           -> Relation q a
           -> Relation r a
unsafeLiftAppend :: (SubQuery -> SubQuery -> SubQuery)
-> Relation p a -> Relation q a -> Relation r a
unsafeLiftAppend SubQuery -> SubQuery -> SubQuery
op Relation p a
a0 Relation q a
a1 = ConfigureQuery SubQuery -> Relation r a
forall p r. ConfigureQuery SubQuery -> Relation p r
unsafeTypeRelation (ConfigureQuery SubQuery -> Relation r a)
-> ConfigureQuery SubQuery -> Relation r a
forall a b. (a -> b) -> a -> b
$ do
  SubQuery
s0 <- Relation p a -> ConfigureQuery SubQuery
forall p r. Relation p r -> ConfigureQuery SubQuery
untypeRelation Relation p a
a0
  SubQuery
s1 <- Relation q a -> ConfigureQuery SubQuery
forall p r. Relation p r -> ConfigureQuery SubQuery
untypeRelation Relation q a
a1
  SubQuery -> ConfigureQuery SubQuery
forall (m :: * -> *) a. Monad m => a -> m a
return (SubQuery -> ConfigureQuery SubQuery)
-> SubQuery -> ConfigureQuery SubQuery
forall a b. (a -> b) -> a -> b
$ SubQuery
s0 SubQuery -> SubQuery -> SubQuery
`op` SubQuery
s1

liftAppend :: (SubQuery -> SubQuery -> SubQuery)
           -> Relation () a
           -> Relation () a
           -> Relation () a
liftAppend :: (SubQuery -> SubQuery -> SubQuery)
-> Relation () a -> Relation () a -> Relation () a
liftAppend = (SubQuery -> SubQuery -> SubQuery)
-> Relation () a -> Relation () a -> Relation () a
forall p a q r.
(SubQuery -> SubQuery -> SubQuery)
-> Relation p a -> Relation q a -> Relation r a
unsafeLiftAppend

-- | Union of two relations.
union     :: Relation () a -> Relation () a -> Relation () a
union :: Relation () a -> Relation () a -> Relation () a
union     =  (SubQuery -> SubQuery -> SubQuery)
-> Relation () a -> Relation () a -> Relation () a
forall a.
(SubQuery -> SubQuery -> SubQuery)
-> Relation () a -> Relation () a -> Relation () a
liftAppend ((SubQuery -> SubQuery -> SubQuery)
 -> Relation () a -> Relation () a -> Relation () a)
-> (SubQuery -> SubQuery -> SubQuery)
-> Relation () a
-> Relation () a
-> Relation () a
forall a b. (a -> b) -> a -> b
$ Duplication -> SubQuery -> SubQuery -> SubQuery
Syntax.union Duplication
Distinct

-- | Union of two relations. Not distinct.
unionAll  :: Relation () a -> Relation () a -> Relation () a
unionAll :: Relation () a -> Relation () a -> Relation () a
unionAll  =  (SubQuery -> SubQuery -> SubQuery)
-> Relation () a -> Relation () a -> Relation () a
forall a.
(SubQuery -> SubQuery -> SubQuery)
-> Relation () a -> Relation () a -> Relation () a
liftAppend ((SubQuery -> SubQuery -> SubQuery)
 -> Relation () a -> Relation () a -> Relation () a)
-> (SubQuery -> SubQuery -> SubQuery)
-> Relation () a
-> Relation () a
-> Relation () a
forall a b. (a -> b) -> a -> b
$ Duplication -> SubQuery -> SubQuery -> SubQuery
Syntax.union Duplication
All

-- | Subtraction of two relations.
except    :: Relation () a -> Relation () a -> Relation () a
except :: Relation () a -> Relation () a -> Relation () a
except    =  (SubQuery -> SubQuery -> SubQuery)
-> Relation () a -> Relation () a -> Relation () a
forall a.
(SubQuery -> SubQuery -> SubQuery)
-> Relation () a -> Relation () a -> Relation () a
liftAppend ((SubQuery -> SubQuery -> SubQuery)
 -> Relation () a -> Relation () a -> Relation () a)
-> (SubQuery -> SubQuery -> SubQuery)
-> Relation () a
-> Relation () a
-> Relation () a
forall a b. (a -> b) -> a -> b
$ Duplication -> SubQuery -> SubQuery -> SubQuery
Syntax.except Duplication
Distinct

-- | Subtraction of two relations. Not distinct.
exceptAll :: Relation () a -> Relation () a -> Relation () a
exceptAll :: Relation () a -> Relation () a -> Relation () a
exceptAll =  (SubQuery -> SubQuery -> SubQuery)
-> Relation () a -> Relation () a -> Relation () a
forall a.
(SubQuery -> SubQuery -> SubQuery)
-> Relation () a -> Relation () a -> Relation () a
liftAppend ((SubQuery -> SubQuery -> SubQuery)
 -> Relation () a -> Relation () a -> Relation () a)
-> (SubQuery -> SubQuery -> SubQuery)
-> Relation () a
-> Relation () a
-> Relation () a
forall a b. (a -> b) -> a -> b
$ Duplication -> SubQuery -> SubQuery -> SubQuery
Syntax.except Duplication
All

-- | Intersection of two relations.
intersect :: Relation () a -> Relation () a -> Relation () a
intersect :: Relation () a -> Relation () a -> Relation () a
intersect =  (SubQuery -> SubQuery -> SubQuery)
-> Relation () a -> Relation () a -> Relation () a
forall a.
(SubQuery -> SubQuery -> SubQuery)
-> Relation () a -> Relation () a -> Relation () a
liftAppend ((SubQuery -> SubQuery -> SubQuery)
 -> Relation () a -> Relation () a -> Relation () a)
-> (SubQuery -> SubQuery -> SubQuery)
-> Relation () a
-> Relation () a
-> Relation () a
forall a b. (a -> b) -> a -> b
$ Duplication -> SubQuery -> SubQuery -> SubQuery
Syntax.intersect Duplication
Distinct

-- | Intersection of two relations. Not distinct.
intersectAll :: Relation () a -> Relation () a -> Relation () a
intersectAll :: Relation () a -> Relation () a -> Relation () a
intersectAll =  (SubQuery -> SubQuery -> SubQuery)
-> Relation () a -> Relation () a -> Relation () a
forall a.
(SubQuery -> SubQuery -> SubQuery)
-> Relation () a -> Relation () a -> Relation () a
liftAppend ((SubQuery -> SubQuery -> SubQuery)
 -> Relation () a -> Relation () a -> Relation () a)
-> (SubQuery -> SubQuery -> SubQuery)
-> Relation () a
-> Relation () a
-> Relation () a
forall a b. (a -> b) -> a -> b
$ Duplication -> SubQuery -> SubQuery -> SubQuery
Syntax.intersect Duplication
All

liftAppend' :: (SubQuery -> SubQuery -> SubQuery)
            -> Relation p a
            -> Relation q a
            -> Relation (p, q) a
liftAppend' :: (SubQuery -> SubQuery -> SubQuery)
-> Relation p a -> Relation q a -> Relation (p, q) a
liftAppend' = (SubQuery -> SubQuery -> SubQuery)
-> Relation p a -> Relation q a -> Relation (p, q) a
forall p a q r.
(SubQuery -> SubQuery -> SubQuery)
-> Relation p a -> Relation q a -> Relation r a
unsafeLiftAppend

-- | Union of two relations with place-holder parameters.
union'     :: Relation p a -> Relation q a -> Relation (p, q) a
union' :: Relation p a -> Relation q a -> Relation (p, q) a
union'     =  (SubQuery -> SubQuery -> SubQuery)
-> Relation p a -> Relation q a -> Relation (p, q) a
forall p a q.
(SubQuery -> SubQuery -> SubQuery)
-> Relation p a -> Relation q a -> Relation (p, q) a
liftAppend' ((SubQuery -> SubQuery -> SubQuery)
 -> Relation p a -> Relation q a -> Relation (p, q) a)
-> (SubQuery -> SubQuery -> SubQuery)
-> Relation p a
-> Relation q a
-> Relation (p, q) a
forall a b. (a -> b) -> a -> b
$ Duplication -> SubQuery -> SubQuery -> SubQuery
Syntax.union Duplication
Distinct

-- | Union of two relations with place-holder parameters. Not distinct.
unionAll' :: Relation p a -> Relation q a -> Relation (p, q) a
unionAll' :: Relation p a -> Relation q a -> Relation (p, q) a
unionAll'  =  (SubQuery -> SubQuery -> SubQuery)
-> Relation p a -> Relation q a -> Relation (p, q) a
forall p a q.
(SubQuery -> SubQuery -> SubQuery)
-> Relation p a -> Relation q a -> Relation (p, q) a
liftAppend' ((SubQuery -> SubQuery -> SubQuery)
 -> Relation p a -> Relation q a -> Relation (p, q) a)
-> (SubQuery -> SubQuery -> SubQuery)
-> Relation p a
-> Relation q a
-> Relation (p, q) a
forall a b. (a -> b) -> a -> b
$ Duplication -> SubQuery -> SubQuery -> SubQuery
Syntax.union Duplication
All

-- | Subtraction of two relations with place-holder parameters.
except'    :: Relation p a -> Relation q a -> Relation (p, q) a
except' :: Relation p a -> Relation q a -> Relation (p, q) a
except'    =  (SubQuery -> SubQuery -> SubQuery)
-> Relation p a -> Relation q a -> Relation (p, q) a
forall p a q.
(SubQuery -> SubQuery -> SubQuery)
-> Relation p a -> Relation q a -> Relation (p, q) a
liftAppend' ((SubQuery -> SubQuery -> SubQuery)
 -> Relation p a -> Relation q a -> Relation (p, q) a)
-> (SubQuery -> SubQuery -> SubQuery)
-> Relation p a
-> Relation q a
-> Relation (p, q) a
forall a b. (a -> b) -> a -> b
$ Duplication -> SubQuery -> SubQuery -> SubQuery
Syntax.except Duplication
Distinct

-- | Subtraction of two relations with place-holder parameters. Not distinct.
exceptAll' :: Relation p a -> Relation q a -> Relation (p, q) a
exceptAll' :: Relation p a -> Relation q a -> Relation (p, q) a
exceptAll' =  (SubQuery -> SubQuery -> SubQuery)
-> Relation p a -> Relation q a -> Relation (p, q) a
forall p a q.
(SubQuery -> SubQuery -> SubQuery)
-> Relation p a -> Relation q a -> Relation (p, q) a
liftAppend' ((SubQuery -> SubQuery -> SubQuery)
 -> Relation p a -> Relation q a -> Relation (p, q) a)
-> (SubQuery -> SubQuery -> SubQuery)
-> Relation p a
-> Relation q a
-> Relation (p, q) a
forall a b. (a -> b) -> a -> b
$ Duplication -> SubQuery -> SubQuery -> SubQuery
Syntax.except Duplication
All

-- | Intersection of two relations with place-holder parameters.
intersect' :: Relation p a -> Relation q a -> Relation (p, q) a
intersect' :: Relation p a -> Relation q a -> Relation (p, q) a
intersect' =  (SubQuery -> SubQuery -> SubQuery)
-> Relation p a -> Relation q a -> Relation (p, q) a
forall p a q.
(SubQuery -> SubQuery -> SubQuery)
-> Relation p a -> Relation q a -> Relation (p, q) a
liftAppend' ((SubQuery -> SubQuery -> SubQuery)
 -> Relation p a -> Relation q a -> Relation (p, q) a)
-> (SubQuery -> SubQuery -> SubQuery)
-> Relation p a
-> Relation q a
-> Relation (p, q) a
forall a b. (a -> b) -> a -> b
$ Duplication -> SubQuery -> SubQuery -> SubQuery
Syntax.intersect Duplication
Distinct

-- | Intersection of two relations with place-holder parameters. Not distinct.
intersectAll' :: Relation p a -> Relation q a -> Relation (p, q) a
intersectAll' :: Relation p a -> Relation q a -> Relation (p, q) a
intersectAll' =  (SubQuery -> SubQuery -> SubQuery)
-> Relation p a -> Relation q a -> Relation (p, q) a
forall p a q.
(SubQuery -> SubQuery -> SubQuery)
-> Relation p a -> Relation q a -> Relation (p, q) a
liftAppend' ((SubQuery -> SubQuery -> SubQuery)
 -> Relation p a -> Relation q a -> Relation (p, q) a)
-> (SubQuery -> SubQuery -> SubQuery)
-> Relation p a
-> Relation q a
-> Relation (p, q) a
forall a b. (a -> b) -> a -> b
$ Duplication -> SubQuery -> SubQuery -> SubQuery
Syntax.intersect Duplication
All

infixl 7 `union`, `except`, `unionAll`, `exceptAll`
infixl 8 `intersect`, `intersectAll`
infixl 7 `union'`, `except'`, `unionAll'`, `exceptAll'`
infixl 8 `intersect'`, `intersectAll'`