{-# LANGUAGE
DeriveGeneric
, DerivingStrategies
, FlexibleContexts
, FlexibleInstances
, GADTs
, GeneralizedNewtypeDeriving
, LambdaCase
, MultiParamTypeClasses
, OverloadedStrings
, PatternSynonyms
, QuantifiedConstraints
, RankNTypes
, ScopedTypeVariables
, TypeApplications
, TypeFamilies
, TypeInType
, TypeOperators
, UndecidableInstances
#-}
module Squeal.PostgreSQL.Manipulation.Insert
(
insertInto
, insertInto_
, QueryClause (..)
, pattern Values_
, inlineValues
, inlineValues_
, ConflictClause (..)
, ConflictTarget (..)
, ConflictAction (..)
) where
import Data.ByteString hiding (foldr)
import qualified Generics.SOP as SOP
import qualified Generics.SOP.Record as SOP
import Squeal.PostgreSQL.Type.Alias
import Squeal.PostgreSQL.Expression
import Squeal.PostgreSQL.Expression.Default
import Squeal.PostgreSQL.Expression.Inline
import Squeal.PostgreSQL.Expression.Logic
import Squeal.PostgreSQL.Manipulation
import Squeal.PostgreSQL.Type.List
import Squeal.PostgreSQL.Render
import Squeal.PostgreSQL.Query
import Squeal.PostgreSQL.Query.Table
import Squeal.PostgreSQL.Type.Schema
insertInto
:: ( Has sch db schema
, Has tab0 schema ('Table table)
, SOP.SListI (TableToColumns table)
, SOP.SListI row )
=> Aliased (QualifiedAlias sch) (tab ::: tab0)
-> QueryClause with db params (TableToColumns table)
-> ConflictClause tab with db params table
-> ReturningClause with db params '[tab ::: TableToRow table] row
-> Manipulation with db params row
insertInto :: forall (sch :: Symbol) (db :: [(Symbol, [(Symbol, SchemumType)])])
(schema :: [(Symbol, SchemumType)]) (tab0 :: Symbol)
(table :: TableType) (row :: [(Symbol, NullType)]) (tab :: Symbol)
(with :: FromType) (params :: [NullType]).
(Has sch db schema, Has tab0 schema ('Table table),
SListI (TableToColumns table), SListI row) =>
Aliased (QualifiedAlias sch) (tab ::: tab0)
-> QueryClause with db params (TableToColumns table)
-> ConflictClause tab with db params table
-> ReturningClause with db params '[tab ::: TableToRow table] row
-> Manipulation with db params row
insertInto (QualifiedAlias sch ty
tab0 `As` Alias alias
tab) QueryClause with db params (TableToColumns table)
qry ConflictClause tab with db params table
conflict ReturningClause with db params '[tab ::: TableToRow table] row
ret = forall (with :: FromType)
(db :: [(Symbol, [(Symbol, SchemumType)])]) (params :: [NullType])
(columns :: [(Symbol, NullType)]).
ByteString -> Manipulation with db params columns
UnsafeManipulation forall a b. (a -> b) -> a -> b
$
ByteString
"INSERT" ByteString -> ByteString -> ByteString
<+> ByteString
"INTO"
ByteString -> ByteString -> ByteString
<+> forall sql. RenderSQL sql => sql -> ByteString
renderSQL QualifiedAlias sch ty
tab0 ByteString -> ByteString -> ByteString
<+> ByteString
"AS" ByteString -> ByteString -> ByteString
<+> forall sql. RenderSQL sql => sql -> ByteString
renderSQL Alias alias
tab
ByteString -> ByteString -> ByteString
<+> forall sql. RenderSQL sql => sql -> ByteString
renderSQL QueryClause with db params (TableToColumns table)
qry
forall a. Semigroup a => a -> a -> a
<> forall sql. RenderSQL sql => sql -> ByteString
renderSQL ConflictClause tab with db params table
conflict
forall a. Semigroup a => a -> a -> a
<> forall sql. RenderSQL sql => sql -> ByteString
renderSQL ReturningClause with db params '[tab ::: TableToRow table] row
ret
insertInto_
:: ( Has sch db schema
, Has tab0 schema ('Table table)
, SOP.SListI (TableToColumns table) )
=> Aliased (QualifiedAlias sch) (tab ::: tab0)
-> QueryClause with db params (TableToColumns table)
-> Manipulation with db params '[]
insertInto_ :: forall (sch :: Symbol) (db :: [(Symbol, [(Symbol, SchemumType)])])
(schema :: [(Symbol, SchemumType)]) (tab0 :: Symbol)
(table :: TableType) (tab :: Symbol) (with :: FromType)
(params :: [NullType]).
(Has sch db schema, Has tab0 schema ('Table table),
SListI (TableToColumns table)) =>
Aliased (QualifiedAlias sch) (tab ::: tab0)
-> QueryClause with db params (TableToColumns table)
-> Manipulation with db params '[]
insertInto_ Aliased (QualifiedAlias sch) (tab ::: tab0)
tab QueryClause with db params (TableToColumns table)
qry =
forall (sch :: Symbol) (db :: [(Symbol, [(Symbol, SchemumType)])])
(schema :: [(Symbol, SchemumType)]) (tab0 :: Symbol)
(table :: TableType) (row :: [(Symbol, NullType)]) (tab :: Symbol)
(with :: FromType) (params :: [NullType]).
(Has sch db schema, Has tab0 schema ('Table table),
SListI (TableToColumns table), SListI row) =>
Aliased (QualifiedAlias sch) (tab ::: tab0)
-> QueryClause with db params (TableToColumns table)
-> ConflictClause tab with db params table
-> ReturningClause with db params '[tab ::: TableToRow table] row
-> Manipulation with db params row
insertInto Aliased (QualifiedAlias sch) (tab ::: tab0)
tab QueryClause with db params (TableToColumns table)
qry forall (tab :: Symbol) (with :: FromType)
(db :: [(Symbol, [(Symbol, SchemumType)])]) (params :: [NullType])
(table :: TableType).
ConflictClause tab with db params table
OnConflictDoRaise (forall (row :: [(Symbol, NullType)]) (with :: FromType)
(db :: [(Symbol, [(Symbol, SchemumType)])]) (params :: [NullType])
(from :: FromType).
SListI row =>
NP (Aliased (Expression 'Ungrouped '[] with db params from)) row
-> ReturningClause with db params from row
Returning_ forall {k} (a :: k -> *). NP a '[]
Nil)
data QueryClause with db params columns where
Values
:: SOP.SListI columns
=> NP (Aliased (Optional (Expression 'Ungrouped '[] with db params from))) columns
-> [NP (Aliased (Optional (Expression 'Ungrouped '[] with db params from))) columns]
-> QueryClause with db params columns
Select
:: SOP.SListI columns
=> NP (Aliased (Optional (Expression grp '[] with db params from))) columns
-> TableExpression grp '[] with db params from
-> QueryClause with db params columns
Subquery
:: ColumnsToRow columns ~ row
=> Query '[] with db params row
-> QueryClause with db params columns
instance RenderSQL (QueryClause with db params columns) where
renderSQL :: QueryClause with db params columns -> ByteString
renderSQL = \case
Values NP
(Aliased
(Optional (Expression 'Ungrouped '[] with db params from)))
columns
row0 [NP
(Aliased
(Optional (Expression 'Ungrouped '[] with db params from)))
columns]
rows ->
ByteString -> ByteString
parenthesized (forall {k} (xs :: [k]) (expression :: k -> *).
SListI xs =>
(forall (x :: k). expression x -> ByteString)
-> NP expression xs -> ByteString
renderCommaSeparated forall (grp :: Grouping) (from :: FromType)
(column :: (Symbol, (Optionality, NullType))).
Aliased (Optional (Expression grp '[] with db params from)) column
-> ByteString
renderSQLPart NP
(Aliased
(Optional (Expression 'Ungrouped '[] with db params from)))
columns
row0)
ByteString -> ByteString -> ByteString
<+> ByteString
"VALUES"
ByteString -> ByteString -> ByteString
<+> [ByteString] -> ByteString
commaSeparated
( ByteString -> ByteString
parenthesized
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {k} (xs :: [k]) (expression :: k -> *).
SListI xs =>
(forall (x :: k). expression x -> ByteString)
-> NP expression xs -> ByteString
renderCommaSeparated forall (grp :: Grouping) (from :: FromType)
(column :: (Symbol, (Optionality, NullType))).
Aliased (Optional (Expression grp '[] with db params from)) column
-> ByteString
renderValuePart forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NP
(Aliased
(Optional (Expression 'Ungrouped '[] with db params from)))
columns
row0 forall a. a -> [a] -> [a]
: [NP
(Aliased
(Optional (Expression 'Ungrouped '[] with db params from)))
columns]
rows )
Select NP
(Aliased (Optional (Expression grp '[] with db params from)))
columns
row0 TableExpression grp '[] with db params from
tab ->
ByteString -> ByteString
parenthesized (forall {k} (xs :: [k]) (expression :: k -> *).
SListI xs =>
(forall (x :: k). expression x -> Maybe ByteString)
-> NP expression xs -> ByteString
renderCommaSeparatedMaybe forall (grp :: Grouping) (from :: FromType)
(column :: (Symbol, (Optionality, NullType))).
Aliased (Optional (Expression grp '[] with db params from)) column
-> Maybe ByteString
renderSQLPartMaybe NP
(Aliased (Optional (Expression grp '[] with db params from)))
columns
row0)
ByteString -> ByteString -> ByteString
<+> ByteString
"SELECT"
ByteString -> ByteString -> ByteString
<+> forall {k} (xs :: [k]) (expression :: k -> *).
SListI xs =>
(forall (x :: k). expression x -> Maybe ByteString)
-> NP expression xs -> ByteString
renderCommaSeparatedMaybe forall (grp :: Grouping) (from :: FromType)
(column :: (Symbol, (Optionality, NullType))).
Aliased (Optional (Expression grp '[] with db params from)) column
-> Maybe ByteString
renderValuePartMaybe NP
(Aliased (Optional (Expression grp '[] with db params from)))
columns
row0
ByteString -> ByteString -> ByteString
<+> forall sql. RenderSQL sql => sql -> ByteString
renderSQL TableExpression grp '[] with db params from
tab
Subquery Query '[] with db params row
qry -> forall (lat :: FromType) (with :: FromType)
(db :: [(Symbol, [(Symbol, SchemumType)])]) (params :: [NullType])
(row :: [(Symbol, NullType)]).
Query lat with db params row -> ByteString
renderQuery Query '[] with db params row
qry
where
renderSQLPartMaybe, renderValuePartMaybe
:: Aliased (Optional (Expression grp '[] with db params from)) column
-> Maybe ByteString
renderSQLPartMaybe :: forall (grp :: Grouping) (from :: FromType)
(column :: (Symbol, (Optionality, NullType))).
Aliased (Optional (Expression grp '[] with db params from)) column
-> Maybe ByteString
renderSQLPartMaybe = \case
Optional (Expression grp '[] with db params from) ty
Default `As` Alias alias
_ -> forall a. Maybe a
Nothing
Set Expression grp '[] with db params from ty
_ `As` Alias alias
name -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall sql. RenderSQL sql => sql -> ByteString
renderSQL Alias alias
name
renderValuePartMaybe :: forall (grp :: Grouping) (from :: FromType)
(column :: (Symbol, (Optionality, NullType))).
Aliased (Optional (Expression grp '[] with db params from)) column
-> Maybe ByteString
renderValuePartMaybe = \case
Optional (Expression grp '[] with db params from) ty
Default `As` Alias alias
_ -> forall a. Maybe a
Nothing
Set Expression grp '[] with db params from ty
value `As` Alias alias
_ -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall (grp :: Grouping) (lat :: FromType) (with :: FromType)
(db :: [(Symbol, [(Symbol, SchemumType)])]) (params :: [NullType])
(from :: FromType) (ty :: NullType).
Expression grp lat with db params from ty -> ByteString
renderExpression Expression grp '[] with db params from ty
value
renderSQLPart, renderValuePart
:: Aliased (Optional (Expression grp '[] with db params from)) column
-> ByteString
renderSQLPart :: forall (grp :: Grouping) (from :: FromType)
(column :: (Symbol, (Optionality, NullType))).
Aliased (Optional (Expression grp '[] with db params from)) column
-> ByteString
renderSQLPart (Optional (Expression grp '[] with db params from) ty
_ `As` Alias alias
name) = forall sql. RenderSQL sql => sql -> ByteString
renderSQL Alias alias
name
renderValuePart :: forall (grp :: Grouping) (from :: FromType)
(column :: (Symbol, (Optionality, NullType))).
Aliased (Optional (Expression grp '[] with db params from)) column
-> ByteString
renderValuePart (Optional (Expression grp '[] with db params from) ty
value `As` Alias alias
_) = forall sql. RenderSQL sql => sql -> ByteString
renderSQL Optional (Expression grp '[] with db params from) ty
value
pattern Values_
:: SOP.SListI columns
=> NP (Aliased (Optional (Expression 'Ungrouped '[] with db params from))) columns
-> QueryClause with db params columns
pattern $bValues_ :: forall (columns :: [(Symbol, (Optionality, NullType))])
(with :: FromType) (db :: [(Symbol, [(Symbol, SchemumType)])])
(params :: [NullType]) (from :: FromType).
SListI columns =>
NP
(Aliased
(Optional (Expression 'Ungrouped '[] with db params from)))
columns
-> QueryClause with db params columns
$mValues_ :: forall {r} {columns :: [(Symbol, (Optionality, NullType))]}
{with :: FromType} {db :: [(Symbol, [(Symbol, SchemumType)])]}
{params :: [NullType]}.
SListI columns =>
QueryClause with db params columns
-> (forall {from :: FromType}.
NP
(Aliased
(Optional (Expression 'Ungrouped '[] with db params from)))
columns
-> r)
-> ((# #) -> r)
-> r
Values_ vals = Values vals []
inlineValues_
:: ( SOP.IsRecord hask xs
, SOP.AllZip InlineColumn xs columns )
=> hask
-> QueryClause with db params columns
inlineValues_ :: forall hask (xs :: RecordCode)
(columns :: [(Symbol, (Optionality, NullType))]) (with :: FromType)
(db :: [(Symbol, [(Symbol, SchemumType)])]) (params :: [NullType]).
(IsRecord hask xs, AllZip InlineColumn xs columns) =>
hask -> QueryClause with db params columns
inlineValues_ = forall (columns :: [(Symbol, (Optionality, NullType))])
(with :: FromType) (db :: [(Symbol, [(Symbol, SchemumType)])])
(params :: [NullType]) (from :: FromType).
SListI columns =>
NP
(Aliased
(Optional (Expression 'Ungrouped '[] with db params from)))
columns
-> QueryClause with db params columns
Values_ forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall hask (xs :: RecordCode)
(columns :: [(Symbol, (Optionality, NullType))]) (with :: FromType)
(db :: [(Symbol, [(Symbol, SchemumType)])]) (params :: [NullType]).
(IsRecord hask xs, AllZip InlineColumn xs columns) =>
hask
-> NP
(Aliased (Optional (Expression 'Ungrouped '[] with db params '[])))
columns
inlineColumns
inlineValues
:: ( SOP.IsRecord hask xs
, SOP.AllZip InlineColumn xs columns )
=> hask
-> [hask]
-> QueryClause with db params columns
inlineValues :: forall hask (xs :: RecordCode)
(columns :: [(Symbol, (Optionality, NullType))]) (with :: FromType)
(db :: [(Symbol, [(Symbol, SchemumType)])]) (params :: [NullType]).
(IsRecord hask xs, AllZip InlineColumn xs columns) =>
hask -> [hask] -> QueryClause with db params columns
inlineValues hask
hask [hask]
hasks = forall (columns :: [(Symbol, (Optionality, NullType))])
(with :: FromType) (db :: [(Symbol, [(Symbol, SchemumType)])])
(params :: [NullType]) (from :: FromType).
SListI columns =>
NP
(Aliased
(Optional (Expression 'Ungrouped '[] with db params from)))
columns
-> [NP
(Aliased
(Optional (Expression 'Ungrouped '[] with db params from)))
columns]
-> QueryClause with db params columns
Values (forall hask (xs :: RecordCode)
(columns :: [(Symbol, (Optionality, NullType))]) (with :: FromType)
(db :: [(Symbol, [(Symbol, SchemumType)])]) (params :: [NullType]).
(IsRecord hask xs, AllZip InlineColumn xs columns) =>
hask
-> NP
(Aliased (Optional (Expression 'Ungrouped '[] with db params '[])))
columns
inlineColumns hask
hask) (forall hask (xs :: RecordCode)
(columns :: [(Symbol, (Optionality, NullType))]) (with :: FromType)
(db :: [(Symbol, [(Symbol, SchemumType)])]) (params :: [NullType]).
(IsRecord hask xs, AllZip InlineColumn xs columns) =>
hask
-> NP
(Aliased (Optional (Expression 'Ungrouped '[] with db params '[])))
columns
inlineColumns forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [hask]
hasks)
data ConflictClause tab with db params table where
OnConflictDoRaise :: ConflictClause tab with db params table
OnConflict
:: ConflictTarget table
-> ConflictAction tab with db params table
-> ConflictClause tab with db params table
instance SOP.SListI (TableToColumns table)
=> RenderSQL (ConflictClause tab with db params table) where
renderSQL :: ConflictClause tab with db params table -> ByteString
renderSQL = \case
ConflictClause tab with db params table
OnConflictDoRaise -> ByteString
""
OnConflict ConflictTarget table
target ConflictAction tab with db params table
action -> ByteString
" ON CONFLICT"
ByteString -> ByteString -> ByteString
<+> forall sql. RenderSQL sql => sql -> ByteString
renderSQL ConflictTarget table
target ByteString -> ByteString -> ByteString
<+> forall sql. RenderSQL sql => sql -> ByteString
renderSQL ConflictAction tab with db params table
action
data ConflictAction tab with db params table where
DoNothing :: ConflictAction tab with db params table
DoUpdate
:: ( row ~ TableToRow table
, from ~ '[tab ::: row, "excluded" ::: row]
, Updatable table updates )
=> NP (Aliased (Optional (Expression 'Ungrouped '[] with db params from))) updates
-> [Condition 'Ungrouped '[] with db params from]
-> ConflictAction tab with db params table
instance RenderSQL (ConflictAction tab with db params table) where
renderSQL :: ConflictAction tab with db params table -> ByteString
renderSQL = \case
ConflictAction tab with db params table
DoNothing -> ByteString
"DO NOTHING"
DoUpdate NP
(Aliased
(Optional (Expression 'Ungrouped '[] with db params from)))
updates
updates [Expression 'Ungrouped '[] with db params from ('Null 'PGbool)]
whs'
-> ByteString
"DO UPDATE SET"
ByteString -> ByteString -> ByteString
<+> forall {k} (xs :: [k]) (expression :: k -> *).
SListI xs =>
(forall (x :: k). expression x -> ByteString)
-> NP expression xs -> ByteString
renderCommaSeparated forall {k} (expr :: k -> *) (ty :: (Symbol, (Optionality, k))).
(forall (x :: k). RenderSQL (expr x)) =>
Aliased (Optional expr) ty -> ByteString
renderUpdate NP
(Aliased
(Optional (Expression 'Ungrouped '[] with db params from)))
updates
updates
forall a. Semigroup a => a -> a -> a
<> case [Expression 'Ungrouped '[] with db params from ('Null 'PGbool)]
whs' of
[] -> ByteString
""
Expression 'Ungrouped '[] with db params from ('Null 'PGbool)
wh:[Expression 'Ungrouped '[] with db params from ('Null 'PGbool)]
whs -> ByteString
" WHERE" ByteString -> ByteString -> ByteString
<+> forall sql. RenderSQL sql => sql -> ByteString
renderSQL (forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr forall (null :: PGType -> NullType).
Operator (null 'PGbool) (null 'PGbool) (null 'PGbool)
(.&&) Expression 'Ungrouped '[] with db params from ('Null 'PGbool)
wh [Expression 'Ungrouped '[] with db params from ('Null 'PGbool)]
whs)
renderUpdate
:: (forall x. RenderSQL (expr x))
=> Aliased (Optional expr) ty
-> ByteString
renderUpdate :: forall {k} (expr :: k -> *) (ty :: (Symbol, (Optionality, k))).
(forall (x :: k). RenderSQL (expr x)) =>
Aliased (Optional expr) ty -> ByteString
renderUpdate (Optional expr ty
expr `As` Alias alias
col) = forall sql. RenderSQL sql => sql -> ByteString
renderSQL Alias alias
col ByteString -> ByteString -> ByteString
<+> ByteString
"=" ByteString -> ByteString -> ByteString
<+> forall sql. RenderSQL sql => sql -> ByteString
renderSQL Optional expr ty
expr
data ConflictTarget table where
OnConstraint
:: Has con constraints constraint
=> Alias con
-> ConflictTarget (constraints :=> columns)
instance RenderSQL (ConflictTarget constraints) where
renderSQL :: ConflictTarget constraints -> ByteString
renderSQL (OnConstraint Alias con
con) =
ByteString
"ON" ByteString -> ByteString -> ByteString
<+> ByteString
"CONSTRAINT" ByteString -> ByteString -> ByteString
<+> forall sql. RenderSQL sql => sql -> ByteString
renderSQL Alias con
con