{-# LANGUAGE
ConstraintKinds
, DeriveGeneric
, DerivingStrategies
, FlexibleContexts
, FlexibleInstances
, GADTs
, GeneralizedNewtypeDeriving
, LambdaCase
, MultiParamTypeClasses
, OverloadedLabels
, OverloadedStrings
, QuantifiedConstraints
, ScopedTypeVariables
, StandaloneDeriving
, TypeApplications
, TypeFamilies
, TypeInType
, TypeOperators
, RankNTypes
, UndecidableInstances
#-}
module Squeal.PostgreSQL.Query.From.Join
(
JoinItem (..)
, cross, crossJoin, crossJoinLateral
, inner, innerJoin, innerJoinLateral
, leftOuter, leftOuterJoin, leftOuterJoinLateral
, rightOuter, rightOuterJoin, rightOuterJoinLateral
, fullOuter, fullOuterJoin, fullOuterJoinLateral
) where
import Generics.SOP hiding (from)
import qualified Generics.SOP as SOP
import Squeal.PostgreSQL.Type.Alias
import Squeal.PostgreSQL.Expression
import Squeal.PostgreSQL.Expression.Logic
import Squeal.PostgreSQL.Query
import Squeal.PostgreSQL.Query.From
import Squeal.PostgreSQL.Query.From.Set
import Squeal.PostgreSQL.Render
import Squeal.PostgreSQL.Type.List
import Squeal.PostgreSQL.Type.Schema
data JoinItem
(lat :: FromType)
(with :: FromType)
(db :: SchemasType)
(params :: [NullType])
(left :: FromType)
(right :: FromType) where
Join
:: FromClause lat with db params right
-> JoinItem lat with db params left right
JoinLateral
:: Aliased (Query (Join lat left) with db params) query
-> JoinItem lat with db params left '[query]
JoinFunction
:: SetFun db arg set
-> Expression 'Ungrouped lat with db params left arg
-> JoinItem lat with db params left '[set]
JoinFunctionN
:: SListI args
=> SetFunN db args set
-> NP (Expression 'Ungrouped lat with db params left) args
-> JoinItem lat with db params left '[set]
instance RenderSQL (JoinItem lat with db params left right) where
renderSQL = \case
Join tab -> "JOIN" <+> renderSQL tab
JoinLateral qry -> "JOIN LATERAL" <+>
renderAliased (parenthesized . renderSQL) qry
JoinFunction fun x -> "JOIN" <+>
renderSQL (fun (UnsafeExpression (renderSQL x)))
JoinFunctionN fun xs -> "JOIN" <+>
renderSQL (fun (SOP.hmap (UnsafeExpression . renderSQL) xs))
cross
:: JoinItem lat with db params left right
-> FromClause lat with db params left
-> FromClause lat with db params (Join left right)
cross item tab = UnsafeFromClause $
renderSQL tab <+> "CROSS" <+> renderSQL item
crossJoin
:: FromClause lat with db params right
-> FromClause lat with db params left
-> FromClause lat with db params (Join left right)
crossJoin = cross . Join
crossJoinLateral
:: Aliased (Query (Join lat left) with db params) query
-> FromClause lat with db params left
-> FromClause lat with db params (Join left '[query])
crossJoinLateral = cross . JoinLateral
inner
:: JoinItem lat with db params left right
-> Condition 'Ungrouped lat with db params (Join left right)
-> FromClause lat with db params left
-> FromClause lat with db params (Join left right)
inner item on tab = UnsafeFromClause $
renderSQL tab <+> "INNER" <+> renderSQL item <+> "ON" <+> renderSQL on
innerJoin
:: FromClause lat with db params right
-> Condition 'Ungrouped lat with db params (Join left right)
-> FromClause lat with db params left
-> FromClause lat with db params (Join left right)
innerJoin = inner . Join
innerJoinLateral
:: Aliased (Query (Join lat left) with db params) query
-> Condition 'Ungrouped lat with db params (Join left '[query])
-> FromClause lat with db params left
-> FromClause lat with db params (Join left '[query])
innerJoinLateral = inner . JoinLateral
leftOuter
:: JoinItem lat with db params left right
-> Condition 'Ungrouped lat with db params (Join left right)
-> FromClause lat with db params left
-> FromClause lat with db params (Join left (NullifyFrom right))
leftOuter item on tab = UnsafeFromClause $
renderSQL tab <+> "LEFT OUTER" <+> renderSQL item <+> "ON" <+> renderSQL on
leftOuterJoin
:: FromClause lat with db params right
-> Condition 'Ungrouped lat with db params (Join left right)
-> FromClause lat with db params left
-> FromClause lat with db params (Join left (NullifyFrom right))
leftOuterJoin = leftOuter . Join
leftOuterJoinLateral
:: Aliased (Query (Join lat left) with db params) query
-> Condition 'Ungrouped lat with db params (Join left '[query])
-> FromClause lat with db params left
-> FromClause lat with db params (Join left (NullifyFrom '[query]))
leftOuterJoinLateral = leftOuter . JoinLateral
rightOuter
:: JoinItem lat with db params left right
-> Condition 'Ungrouped lat with db params (Join left right)
-> FromClause lat with db params left
-> FromClause lat with db params (Join (NullifyFrom left) right)
rightOuter item on tab = UnsafeFromClause $
renderSQL tab <+> "RIGHT OUTER" <+> renderSQL item <+> "ON" <+> renderSQL on
rightOuterJoin
:: FromClause lat with db params right
-> Condition 'Ungrouped lat with db params (Join left right)
-> FromClause lat with db params left
-> FromClause lat with db params (Join (NullifyFrom left) right)
rightOuterJoin = rightOuter . Join
rightOuterJoinLateral
:: Aliased (Query (Join lat left) with db params) query
-> Condition 'Ungrouped lat with db params (Join left '[query])
-> FromClause lat with db params left
-> FromClause lat with db params (Join (NullifyFrom left) '[query])
rightOuterJoinLateral = rightOuter . JoinLateral
fullOuter
:: JoinItem lat with db params left right
-> Condition 'Ungrouped lat with db params (Join left right)
-> FromClause lat with db params left
-> FromClause lat with db params (NullifyFrom (Join left right))
fullOuter item on tab = UnsafeFromClause $
renderSQL tab <+> "FULL OUTER" <+> renderSQL item <+> "ON" <+> renderSQL on
fullOuterJoin
:: FromClause lat with db params right
-> Condition 'Ungrouped lat with db params (Join left right)
-> FromClause lat with db params left
-> FromClause lat with db params (NullifyFrom (Join left right))
fullOuterJoin = fullOuter . Join
fullOuterJoinLateral
:: Aliased (Query (Join lat left) with db params) query
-> Condition 'Ungrouped lat with db params (Join left '[query])
-> FromClause lat with db params left
-> FromClause lat with db params (NullifyFrom (Join left '[query]))
fullOuterJoinLateral = fullOuter . JoinLateral