squeal-postgresql-0.9.2.0: src/Squeal/PostgreSQL/Expression/Composite.hs
{-|
Module: Squeal.PostgreSQL.Expression.Composite
Description: composite functions
Copyright: (c) Eitan Chatav, 2019
Maintainer: eitan@morphism.tech
Stability: experimental
composite functions
-}
{-# LANGUAGE
AllowAmbiguousTypes
, DataKinds
, FlexibleContexts
, FlexibleInstances
, MultiParamTypeClasses
, OverloadedLabels
, OverloadedStrings
, RankNTypes
, ScopedTypeVariables
, TypeApplications
, TypeFamilies
, TypeOperators
, UndecidableInstances
#-}
module Squeal.PostgreSQL.Expression.Composite
( -- * Composite Functions
row
, rowStar
, field
) where
import qualified Generics.SOP as SOP
import Squeal.PostgreSQL.Type.Alias
import Squeal.PostgreSQL.Expression
import Squeal.PostgreSQL.Type.List
import Squeal.PostgreSQL.Render
import Squeal.PostgreSQL.Type.Schema
-- $setup
-- >>> import Squeal.PostgreSQL
-- | A row constructor is an expression that builds a row value
-- (also called a composite value) using values for its member fields.
--
-- >>> :{
-- type Complex = 'PGcomposite
-- '[ "real" ::: 'NotNull 'PGfloat8
-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
-- :}
--
-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression grp lat with db params from ('NotNull Complex)
-- >>> printSQL i
-- ROW((0.0 :: float8), (1.0 :: float8))
row
:: SOP.SListI row
=> NP (Aliased (Expression grp lat with db params from)) row
-- ^ zero or more expressions for the row field values
-> Expression grp lat with db params from (null ('PGcomposite row))
row exprs = UnsafeExpression $ "ROW" <> parenthesized
(renderCommaSeparated (\ (expr `As` _) -> renderSQL expr) exprs)
-- | A row constructor on all columns in a table expression.
rowStar
:: Has tab from row
=> Alias tab -- ^ intermediate table
-> Expression grp lat with db params from (null ('PGcomposite row))
rowStar tab = UnsafeExpression $ "ROW" <>
parenthesized (renderSQL tab <> ".*")
-- | >>> :{
-- type Complex = 'PGcomposite
-- '[ "real" ::: 'NotNull 'PGfloat8
-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
-- type Schema = '["complex" ::: 'Typedef Complex]
-- :}
--
-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression lat '[] grp (Public Schema) from params ('NotNull Complex)
-- >>> printSQL $ i & field #complex #imaginary
-- (ROW((0.0 :: float8), (1.0 :: float8))::"complex")."imaginary"
field
:: ( relss ~ DbRelations db
, Has sch relss rels
, Has rel rels row
, Has field row ty
)
=> QualifiedAlias sch rel -- ^ row type
-> Alias field -- ^ field name
-> Expression grp lat with db params from ('NotNull ('PGcomposite row))
-> Expression grp lat with db params from ty
field rel fld expr = UnsafeExpression $
parenthesized (renderSQL expr <> "::" <> renderSQL rel)
<> "." <> renderSQL fld