opaleye-0.5.1.0: src/Opaleye/Join.hs
-- | Left, right, and full outer joins. If you want inner joins, just use 'restrict' instead.
--
-- The use of the 'D.Default' typeclass means that the compiler will
-- have trouble inferring types. It is strongly recommended that you
-- provide full type signatures when using the join functions.
--
-- Example specialization:
--
-- @
-- leftJoin :: Query (Column a, Column b)
-- -> Query (Column c, Column (Nullable d))
-- -> (((Column a, Column b), (Column c, Column (Nullable d))) -> Column 'Opaleye.PGTypes.PGBool')
-- -> Query ((Column a, Column b), (Column (Nullable c), Column (Nullable d)))
-- @
{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses #-}
module Opaleye.Join where
import qualified Opaleye.Internal.Unpackspec as U
import qualified Opaleye.Internal.Join as J
import qualified Opaleye.Internal.PrimQuery as PQ
import Opaleye.QueryArr (Query)
import Opaleye.Internal.Column (Column)
import qualified Opaleye.PGTypes as T
import qualified Data.Profunctor.Product.Default as D
leftJoin :: (D.Default U.Unpackspec columnsA columnsA,
D.Default U.Unpackspec columnsB columnsB,
D.Default J.NullMaker columnsB nullableColumnsB)
=> Query columnsA -- ^ Left query
-> Query columnsB -- ^ Right query
-> ((columnsA, columnsB) -> Column T.PGBool) -- ^ Condition on which to join
-> Query (columnsA, nullableColumnsB) -- ^ Left join
leftJoin = leftJoinExplicit D.def D.def D.def
rightJoin :: (D.Default U.Unpackspec columnsA columnsA,
D.Default U.Unpackspec columnsB columnsB,
D.Default J.NullMaker columnsA nullableColumnsA)
=> Query columnsA -- ^ Left query
-> Query columnsB -- ^ Right query
-> ((columnsA, columnsB) -> Column T.PGBool) -- ^ Condition on which to join
-> Query (nullableColumnsA, columnsB) -- ^ Right join
rightJoin = rightJoinExplicit D.def D.def D.def
fullJoin :: (D.Default U.Unpackspec columnsA columnsA,
D.Default U.Unpackspec columnsB columnsB,
D.Default J.NullMaker columnsA nullableColumnsA,
D.Default J.NullMaker columnsB nullableColumnsB)
=> Query columnsA -- ^ Left query
-> Query columnsB -- ^ Right query
-> ((columnsA, columnsB) -> Column T.PGBool) -- ^ Condition on which to join
-> Query (nullableColumnsA, nullableColumnsB) -- ^ Full outer join
fullJoin = fullJoinExplicit D.def D.def D.def D.def
-- We don't actually need the Unpackspecs any more, but I'm going to
-- leave them here in case they're ever needed again. I don't want to
-- have to break the API to add them back.
leftJoinExplicit :: U.Unpackspec columnsA columnsA
-> U.Unpackspec columnsB columnsB
-> J.NullMaker columnsB nullableColumnsB
-> Query columnsA -> Query columnsB
-> ((columnsA, columnsB) -> Column T.PGBool)
-> Query (columnsA, nullableColumnsB)
leftJoinExplicit _ _ nullmaker =
J.joinExplicit id (J.toNullable nullmaker) PQ.LeftJoin
rightJoinExplicit :: U.Unpackspec columnsA columnsA
-> U.Unpackspec columnsB columnsB
-> J.NullMaker columnsA nullableColumnsA
-> Query columnsA -> Query columnsB
-> ((columnsA, columnsB) -> Column T.PGBool)
-> Query (nullableColumnsA, columnsB)
rightJoinExplicit _ _ nullmaker =
J.joinExplicit (J.toNullable nullmaker) id PQ.RightJoin
fullJoinExplicit :: U.Unpackspec columnsA columnsA
-> U.Unpackspec columnsB columnsB
-> J.NullMaker columnsA nullableColumnsA
-> J.NullMaker columnsB nullableColumnsB
-> Query columnsA -> Query columnsB
-> ((columnsA, columnsB) -> Column T.PGBool)
-> Query (nullableColumnsA, nullableColumnsB)
fullJoinExplicit _ _ nullmakerA nullmakerB =
J.joinExplicit (J.toNullable nullmakerA) (J.toNullable nullmakerB) PQ.FullJoin