@@ -18,6 +18,7 @@ Squeal data manipulation language.
18 , MultiParamTypeClasses
18 , MultiParamTypeClasses
19 , OverloadedStrings
19 , OverloadedStrings
20 , PatternSynonyms
20 , PatternSynonyms
21+ , QuantifiedConstraints
21 , RankNTypes
22 , RankNTypes
22 , ScopedTypeVariables
23 , ScopedTypeVariables
23 , TypeApplications
24 , TypeApplications
@@ -34,8 +35,7 @@ module Squeal.PostgreSQL.Manipulation
34 , queryStatement
35 , queryStatement
35 , QueryClause (..)
36 , QueryClause (..)
36 , pattern Values_
37 , pattern Values_
37− , DefaultAliasable (..)
38+ , Optional (..)
38− , ColumnExpression (..)
39 , ReturningClause (..)
39 , ReturningClause (..)
40 , pattern Returning_
40 , pattern Returning_
41 , ConflictClause (..)
41 , ConflictClause (..)
@@ -56,7 +56,6 @@ module Squeal.PostgreSQL.Manipulation
56import Control.DeepSeq
56import Control.DeepSeq
57import Data.ByteString hiding (foldr)
57import Data.ByteString hiding (foldr)
58import Data.Kind (Type)
58import Data.Kind (Type)
59−import GHC.TypeLits (KnownSymbol)
61import qualified Generics.SOP as SOP
60import qualified Generics.SOP as SOP
62import qualified GHC.Generics as GHC
61import qualified GHC.Generics as GHC
@@ -86,7 +85,7 @@ simple insert:
87 manipulation :: Manipulation '[] (Public Schema) '[] '[]
86 manipulation :: Manipulation '[] (Public Schema) '[] '[]
88 manipulation =
87 manipulation =
89− insertInto_ #tab (Values_ (2 `as` #col1 :* defaultAs #col2))
88+ insertInto_ #tab (Values_ (Set 2 `as` #col1 :* Default `as` #col2))
90in printSQL manipulation
89in printSQL manipulation
92INSERT INTO "tab" ("col1", "col2") VALUES (2, DEFAULT)
91INSERT INTO "tab" ("col1", "col2") VALUES (2, DEFAULT)
@@ -99,7 +98,7 @@ parameterized insert:
100 manipulation :: Manipulation '[] (Public Schema) '[ 'NotNull 'PGint4, 'NotNull 'PGint4 ] '[]
99 manipulation :: Manipulation '[] (Public Schema) '[ 'NotNull 'PGint4, 'NotNull 'PGint4 ] '[]
101 manipulation =
100 manipulation =
102− insertInto_ #tab (Values_ (param @1 `as` #col1 :* param @2 `as` #col2))
101+ insertInto_ #tab (Values_ (Set (param @1) `as` #col1 :* Set (param @2) `as` #col2))
103in printSQL manipulation
102in printSQL manipulation
105INSERT INTO "tab" ("col1", "col2") VALUES (($1 :: int4), ($2 :: int4))
104INSERT INTO "tab" ("col1", "col2") VALUES (($1 :: int4), ($2 :: int4))
@@ -110,7 +109,7 @@ returning insert:
111 manipulation :: Manipulation '[] (Public Schema) '[] '["fromOnly" ::: 'NotNull 'PGint4]
110 manipulation :: Manipulation '[] (Public Schema) '[] '["fromOnly" ::: 'NotNull 'PGint4]
112 manipulation =
111 manipulation =
113− insertInto #tab (Values_ (2 `as` #col1 :* 3 `as` #col2))
112+ insertInto #tab (Values_ (Set 2 `as` #col1 :* Set 3 `as` #col2))
114 OnConflictDoRaise (Returning (#col1 `as` #fromOnly))
113 OnConflictDoRaise (Returning (#col1 `as` #fromOnly))
115in printSQL manipulation
114in printSQL manipulation
@@ -126,9 +125,9 @@ let
126 manipulation :: Manipulation '[] (Public CustomersSchema) '[] '[]
125 manipulation :: Manipulation '[] (Public CustomersSchema) '[] '[]
127 manipulation =
126 manipulation =
128 insertInto #customers
127 insertInto #customers
129− (Values_ ("John Smith" `as` #name :* "john@smith.com" `as` #email))
128+ (Values_ (Set "John Smith" `as` #name :* Set "john@smith.com" `as` #email))
130 (OnConflict (OnConstraint #uq)
129 (OnConflict (OnConstraint #uq)
131− (DoUpdate (((#excluded ! #email) <> "; " <> (#customers ! #email)) `as` #email) []))
130+ (DoUpdate (Set (#excluded ! #email <> "; " <> #customers ! #email) `as` #email) []))
132 (Returning_ Nil)
131 (Returning_ Nil)
133in printSQL manipulation
132in printSQL manipulation
@@ -149,7 +148,7 @@ update:
151 manipulation :: Manipulation '[] (Public Schema) '[] '[]
150 manipulation :: Manipulation '[] (Public Schema) '[] '[]
152− manipulation = update_ #tab (2 `as` #col1) (#col1 ./= #col2)
151+ manipulation = update_ #tab (Set 2 `as` #col1) (#col1 ./= #col2)
153in printSQL manipulation
152in printSQL manipulation
155UPDATE "tab" SET "col1" = 2 WHERE ("col1" <> "col2")
154UPDATE "tab" SET "col1" = 2 WHERE ("col1" <> "col2")
@@ -268,12 +267,12 @@ insertInto_ tab qry =
268data QueryClause commons schemas params columns where
267data QueryClause commons schemas params columns where
270 :: SOP.SListI columns
269 :: SOP.SListI columns
271− => NP (ColumnExpression 'Ungrouped schemas params '[]) columns
270+ => NP (Aliased (Optional (Expression '[] '[] 'Ungrouped schemas params '[]))) columns
272− -> [NP (ColumnExpression 'Ungrouped schemas params '[]) columns]
271+ -> [NP (Aliased (Optional (Expression '[] '[] 'Ungrouped schemas params '[]))) columns]
273 -> QueryClause commons schemas params columns
272 -> QueryClause commons schemas params columns
275 :: SOP.SListI columns
274 :: SOP.SListI columns
276− => NP (ColumnExpression grp schemas params from) columns
275+ => NP (Aliased (Optional (Expression '[] '[] grp schemas params from))) columns
277 -> TableExpression '[] commons grp schemas params from
276 -> TableExpression '[] commons grp schemas params from
278 -> QueryClause commons schemas params columns
277 -> QueryClause commons schemas params columns
@@ -297,109 +296,34 @@ instance RenderSQL (QueryClause commons schemas params columns) where
297 Subquery qry -> renderQuery qry
296 Subquery qry -> renderQuery qry
299 renderSQLPartMaybe, renderValuePartMaybe
298 renderSQLPartMaybe, renderValuePartMaybe
300− :: ColumnExpression grp schemas params from column -> Maybe ByteString
299+ :: Aliased (Optional (Expression '[] '[] grp schemas params from)) column
301 renderSQLPartMaybe = \case
301 renderSQLPartMaybe = \case
302− DefaultAs _ -> Nothing
302+ Default `As` _ -> Nothing
303− Specific (_ `As` name) -> Just $ renderSQL name
303+ Set _ `As` name -> Just $ renderSQL name
304 renderValuePartMaybe = \case
304 renderValuePartMaybe = \case
305− DefaultAs _ -> Nothing
305+ Default `As` _ -> Nothing
306− Specific (value `As` _) -> Just $ renderExpression value
306+ Set value `As` _ -> Just $ renderExpression value
307 renderSQLPart, renderValuePart
307 renderSQLPart, renderValuePart
308− :: ColumnExpression grp schemas params from column -> ByteString
308+ :: Aliased (Optional (Expression '[] '[] grp schemas params from)) column
309− renderSQLPart = \case
309+ -> ByteString
310− DefaultAs name -> renderSQL name
311− Specific (_ `As` name) -> renderSQL name
310+ renderSQLPart (_ `As` name) = renderSQL name
312− renderValuePart = \case
311+ renderValuePart (value `As` _) = renderSQL value
313− DefaultAs _ -> "DEFAULT"
314− Specific (value `As` _) -> renderExpression value
316pattern Values_
313pattern Values_
317 :: SOP.SListI columns
314 :: SOP.SListI columns
318− => NP (ColumnExpression 'Ungrouped schemas params '[]) columns
315+ => NP (Aliased (Optional (Expression '[] '[] 'Ungrouped schemas params '[]))) columns
319 -> QueryClause commons schemas params columns
316 -> QueryClause commons schemas params columns
320pattern Values_ vals = Values vals []
317pattern Values_ vals = Values vals []
322−data ColumnExpression grp schemas params from column where
319+data Optional expr ty where
323− DefaultAs
320+ Default :: Optional expr ('Def :=> ty)
324− :: KnownSymbol col
321+ Set :: expr ty -> Optional expr (def :=> ty)
326− -> ColumnExpression grp schemas params from (col ::: 'Def :=> ty)
323+instance (forall x. RenderSQL (expr x)) => RenderSQL (Optional expr ty) where
328− :: Aliased (Expression '[] '[] grp schemas params from) (col ::: ty)
329− -> ColumnExpression grp schemas params from (col ::: defness :=> ty)
331−instance (KnownSymbol col, column ~ (col ::: defness :=> ty))
333− (Expression '[] '[] grp schemas params from ty)
334− (ColumnExpression grp schemas params from column) where
335− expression `as` col = Specific (expression `As` col)
336−instance (KnownSymbol col, columns ~ '[col ::: defness :=> ty])
338− (Expression '[] '[] grp schemas params from ty)
339− (NP (ColumnExpression grp schemas params from) columns) where
340− expression `as` col = expression `as` col :* Nil
341−instance (KnownSymbol col, column ~ (col ::: 'Def :=> ty))
342− => DefaultAliasable col (ColumnExpression grp schemas params from column) where
343− defaultAs = DefaultAs
344−instance (KnownSymbol col, columns ~ '[col ::: 'Def :=> ty])
345− => DefaultAliasable col (NP (ColumnExpression grp schemas params from) columns) where
346− defaultAs col = defaultAs col :* Nil
348−instance (HasUnique tab from row, Has col row ty, column ~ (col ::: defness :=> ty))
349− => IsLabel col (ColumnExpression 'Ungrouped schemas params from column) where
350− fromLabel = fromLabel @col `as` Alias
351−instance (HasUnique tab from row, Has col row ty, columns ~ '[col ::: defness :=> ty])
353− (NP (ColumnExpression 'Ungrouped schemas params from) columns) where
354− fromLabel = fromLabel @col `as` Alias
356−instance (Has tab from row, Has col row ty, column ~ (col ::: defness :=> ty))
357− => IsQualified tab col (ColumnExpression 'Ungrouped schemas params from column) where
358− tab ! col = tab ! col `as` col
359−instance (Has tab from row, Has col row ty, columns ~ '[col ::: defness :=> ty])
360− => IsQualified tab col (NP (ColumnExpression 'Ungrouped schemas params from) columns) where
361− tab ! col = tab ! col `as` col
364− ( HasUnique tab from row
366− , GroupedBy tab col bys
367− , column ~ (col ::: defness :=> ty)
369− (ColumnExpression ('Grouped bys) schemas params from column) where
370− fromLabel = fromLabel @col `as` Alias
372− ( HasUnique tab from row
374− , GroupedBy tab col bys
375− , columns ~ '[col ::: defness :=> ty]
377− (NP (ColumnExpression ('Grouped bys) schemas params from) columns) where
378− fromLabel = fromLabel @col `as` Alias
383− , GroupedBy tab col bys
384− , column ~ (col ::: defness :=> ty)
385− ) => IsQualified tab col
386− (ColumnExpression ('Grouped bys) schemas params from column) where
387− tab ! col = tab ! col `as` col
391− , GroupedBy tab col bys
392− , columns ~ '[col ::: defness :=> ty]
393− ) => IsQualified tab col
394− (NP (ColumnExpression ('Grouped bys) schemas params from) columns) where
395− tab ! col = tab ! col :* Nil
397−instance RenderSQL (ColumnExpression grp schemas params from column) where
398 renderSQL = \case
324 renderSQL = \case
400− renderSQL col <+> "=" <+> "DEFAULT"
325+ Default -> "DEFAULT"
401− Specific (expression `As` col) ->
326+ Set expr -> renderSQL expr
402− renderSQL col <+> "=" <+> renderSQL expression
404-- | A `ReturningClause` computes and return value(s) based
328-- | A `ReturningClause` computes and return value(s) based
405-- on each row actually inserted, updated or deleted. This is primarily
329-- on each row actually inserted, updated or deleted. This is primarily
@@ -453,7 +377,7 @@ data ConflictAction tab commons schemas params columns where
453 , columns ~ (col0 ': cols)
377 , columns ~ (col0 ': cols)
454 , SOP.All (HasIn columns) subcolumns
378 , SOP.All (HasIn columns) subcolumns
455 , AllUnique subcolumns )
379 , AllUnique subcolumns )
456− => NP (ColumnExpression 'Ungrouped schemas params '[tab ::: row, "excluded" ::: row]) subcolumns
380+ => NP (Aliased (Optional (Expression '[] commons 'Ungrouped schemas params '[tab ::: row, "excluded" ::: row]))) subcolumns
457 -> [Condition '[] commons 'Ungrouped schemas params '[tab ::: row, "excluded" ::: row]]
381 -> [Condition '[] commons 'Ungrouped schemas params '[tab ::: row, "excluded" ::: row]]
458 -> ConflictAction tab commons schemas params columns
382 -> ConflictAction tab commons schemas params columns
@@ -462,11 +386,17 @@ instance RenderSQL (ConflictAction tab commons schemas params columns) where
462 DoNothing -> "DO NOTHING"
386 DoNothing -> "DO NOTHING"
463 DoUpdate updates whs'
387 DoUpdate updates whs'
464 -> "DO UPDATE SET"
388 -> "DO UPDATE SET"
465− <+> renderCommaSeparated renderSQL updates
389+ <+> renderCommaSeparated renderUpdate updates
466 <> case whs' of
390 <> case whs' of
468 wh:whs -> " WHERE" <+> renderSQL (foldr (.&&) wh whs)
392 wh:whs -> " WHERE" <+> renderSQL (foldr (.&&) wh whs)
395+ :: (forall x. RenderSQL (expr x))
396+ => Aliased (Optional expr) ty
398+renderUpdate (expr `As` col) = renderSQL col <+> "=" <+> renderSQL expr
470-- | A `ConflictTarget` specifies the constraint violation that triggers a
400-- | A `ConflictTarget` specifies the constraint violation that triggers a
471-- `ConflictAction`.
401-- `ConflictAction`.
472data ConflictTarget constraints where
402data ConflictTarget constraints where
@@ -497,7 +427,7 @@ update
497 , SOP.All (HasIn columns) subcolumns
427 , SOP.All (HasIn columns) subcolumns
498 , AllUnique subcolumns )
428 , AllUnique subcolumns )
499 => QualifiedAlias sch tab -- ^ table to update
429 => QualifiedAlias sch tab -- ^ table to update
500− -> NP (ColumnExpression 'Ungrouped schemas params '[tab ::: row0]) subcolumns
430+ -> NP (Aliased (Optional (Expression '[] '[] 'Ungrouped schemas params '[tab ::: row0]))) subcolumns
501 -- ^ modified values to replace old values
431 -- ^ modified values to replace old values
502 -> Condition '[] commons 'Ungrouped schemas params '[tab ::: row0]
432 -> Condition '[] commons 'Ungrouped schemas params '[tab ::: row0]
503 -- ^ condition under which to perform update on a row
433 -- ^ condition under which to perform update on a row
@@ -507,7 +437,7 @@ update tab columns wh returning = UnsafeManipulation $
508 <+> renderSQL tab
438 <+> renderSQL tab
509 <+> "SET"
439 <+> "SET"
510− <+> renderCommaSeparated renderSQL columns
440+ <+> renderCommaSeparated renderUpdate columns
511 <+> "WHERE" <+> renderSQL wh
441 <+> "WHERE" <+> renderSQL wh
512 <> renderSQL returning
442 <> renderSQL returning
@@ -522,7 +452,7 @@ update_
522 , SOP.All (HasIn columns) subcolumns
452 , SOP.All (HasIn columns) subcolumns
523 , AllUnique subcolumns )
453 , AllUnique subcolumns )
524 => QualifiedAlias sch tab -- ^ table to update
454 => QualifiedAlias sch tab -- ^ table to update
525− -> NP (ColumnExpression 'Ungrouped schemas params '[tab ::: row]) subcolumns
455+ -> NP (Aliased (Optional (Expression '[] '[] 'Ungrouped schemas params '[tab ::: row]))) subcolumns
526 -- ^ modified values to replace old values
456 -- ^ modified values to replace old values
527 -> Condition '[] commons 'Ungrouped schemas params '[tab ::: row]
457 -> Condition '[] commons 'Ungrouped schemas params '[tab ::: row]
528 -- ^ condition under which to perform update on a row
458 -- ^ condition under which to perform update on a row