{-# 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.With
(
With (..)
, CommonTableExpression (..)
, withRecursive
) where
import Data.Quiver.Functor
import GHC.TypeLits
import Squeal.PostgreSQL.Type.Alias
import Squeal.PostgreSQL.Query
import Squeal.PostgreSQL.Type.List
import Squeal.PostgreSQL.Render
import Squeal.PostgreSQL.Type.Schema
class With statement where
with
:: Path (CommonTableExpression statement db params) with0 with1
-> statement with1 db params row
-> statement with0 db params row
instance With (Query lat) where
with Done query = query
with ctes query = UnsafeQuery $
"WITH" <+> commaSeparated (qtoList renderSQL ctes) <+> renderSQL query
withRecursive
:: Aliased (Query lat (recursive ': with) db params) recursive
-> Query lat (recursive ': with) db params row
-> Query lat with db params row
withRecursive (recursive `As` cte) query = UnsafeQuery $
"WITH RECURSIVE" <+> renderSQL cte
<+> "AS" <+> parenthesized (renderSQL recursive)
<+> renderSQL query
data CommonTableExpression statement
(db :: SchemasType)
(params :: [NullType])
(with0 :: FromType)
(with1 :: FromType) where
CommonTableExpression
:: Aliased (statement with db params) (cte ::: common)
-> CommonTableExpression statement db params with (cte ::: common ': with)
instance
( KnownSymbol cte
, with1 ~ (cte ::: common ': with)
) => Aliasable cte
(statement with db params common)
(CommonTableExpression statement db params with with1) where
statement `as` cte = CommonTableExpression (statement `as` cte)
instance
( KnownSymbol cte
, with1 ~ (cte ::: common ': with)
) => Aliasable cte
(statement with db params common)
(Path (CommonTableExpression statement db params) with with1) where
statement `as` cte = qsingle (statement `as` cte)
instance (forall c s p r. RenderSQL (statement c s p r)) => RenderSQL
(CommonTableExpression statement db params with0 with1) where
renderSQL (CommonTableExpression (statement `As` cte)) =
renderSQL cte <+> "AS" <+> parenthesized (renderSQL statement)