@@ -27,6 +27,7 @@ module Squeal.PostgreSQL.Manipulation
2727 , ColumnValue (..)
2828 , ReturningClause (ReturningStar, Returning)
2929 , ConflictClause (OnConflictDoRaise, OnConflictDoNothing, OnConflictDoUpdate)
30+ , UsingClause (..)
3031 -- * Insert
3132 , insertRows
3233 , insertRow
@@ -42,6 +43,7 @@ module Squeal.PostgreSQL.Manipulation
4243 -- * Delete
4344 , deleteFrom
4445 , deleteFrom_
46+ , also
4547 ) where
4648
4749import Control.DeepSeq
@@ -148,11 +150,31 @@ let
148150 manipulation :: Manipulation (DBof (Public Schema)) '[]
149151 '[ "col1" ::: 'NotNull 'PGint4
150152 , "col2" ::: 'NotNull 'PGint4 ]
151− manipulation = deleteFrom #tab (#col1 .== #col2) ReturningStar
153+ manipulation = deleteFrom #tab NoUsing (#col1 .== #col2) ReturningStar
152154in printSQL manipulation
153155:}
154156DELETE FROM "tab" WHERE ("col1" = "col2") RETURNING *
155157
158+delete and using clause:
159+
160+>>> :{
161+type Schema3 =
162+ '[ "tab" ::: 'Table ('[] :=> Columns)
163+ , "other_tab" ::: 'Table ('[] :=> Columns)
164+ , "third_tab" ::: 'Table ('[] :=> Columns) ]
165+:}
166+
167+>>> :{
168+let
169+ manipulation :: Manipulation (DBof (Public Schema3)) '[] '[]
170+ manipulation =
171+ deleteFrom_ #tab (Using (table #other_tab & also (table #third_tab)))
172+ ( (#tab ! #col2 .== #other_tab ! #col2)
173+ .&& (#tab ! #col2 .== #third_tab ! #col2) )
174+in printSQL manipulation
175+:}
176+DELETE FROM "tab" USING "other_tab" AS "other_tab", "third_tab" AS "third_tab" WHERE (("tab"."col2" = "other_tab"."col2") AND ("tab"."col2" = "third_tab"."col2"))
177+
156178with manipulation:
157179
158180>>> type ProductsColumns = '["product" ::: 'NoDef :=> 'NotNull 'PGtext, "date" ::: 'Def :=> 'NotNull 'PGdate]
@@ -161,7 +183,7 @@ with manipulation:
161183let
162184 manipulation :: Manipulation (DBof (Public ProductsSchema)) '[ 'NotNull 'PGdate] '[]
163185 manipulation = with
164− (deleteFrom #products (#date .< param @1) ReturningStar `as` #del)
186+ (deleteFrom #products NoUsing (#date .< param @1) ReturningStar `as` #del)
165187 (insertQuery_ #products_deleted (selectStar (from (common (#del)))))
166188in printSQL manipulation
167189:}
@@ -459,7 +481,13 @@ update_ tab columns wh = update tab columns wh (Returning Nil)
459481DELETE statements
460482-----------------------------------------}
461483
462−-- | Delete rows of a table.
484+data UsingClause db params from where
485+ NoUsing :: UsingClause db params '[]
486+ Using
487+ :: FromClause db params from
488+ -> UsingClause db params from
489+
490+-- | Delete rows from a table.
463491deleteFrom
464492 :: ( SOP.SListI results
465493 , db ~ (commons :=> schemas)
@@ -468,12 +496,17 @@ deleteFrom
468496 , row ~ TableToRow table
469497 , columns ~ TableToColumns table )
470498 => QualifiedAlias sch tab -- ^ table to delete from
471− -> Condition db '[tab ::: row] 'Ungrouped params
499+ -> UsingClause db params from
500+ -> Condition db (tab ::: row ': from) 'Ungrouped params
472501 -- ^ condition under which to delete a row
473502 -> ReturningClause db params row results -- ^ results to return
474503 -> Manipulation db params results
475−deleteFrom tab wh returning = UnsafeManipulation $
476− "DELETE FROM" <+> renderQualifiedAlias tab
504+deleteFrom tab using wh returning = UnsafeManipulation $
505+ "DELETE FROM"
506+ <+> renderQualifiedAlias tab
507+ <> case using of
508+ NoUsing -> ""
509+ Using tables -> " USING" <+> renderFromClause tables
477510 <+> "WHERE" <+> renderExpression wh
478511 <> renderReturningClause returning
479512
@@ -485,7 +518,22 @@ deleteFrom_
485518 , row ~ TableToRow table
486519 , columns ~ TableToColumns table )
487520 => QualifiedAlias sch tab -- ^ table to delete from
488− -> (forall t. Condition db '[t ::: row] 'Ungrouped params)
521+ -> UsingClause db params from
522+ -> Condition db (tab ::: row ': from) 'Ungrouped params
489523 -- ^ condition under which to delete a row
490524 -> Manipulation db params '[]
491−deleteFrom_ tab wh = deleteFrom tab wh (Returning Nil)
525+deleteFrom_ tab uses wh = deleteFrom tab uses wh (Returning Nil)
526+
527+-- | This has the behaviour of a cartesian product, taking all
528+-- possible combinations between @left@ and @right@ - exactly like a
529+-- CROSS JOIN. Used when no "CROSS JOIN" syntax is required but simply
530+-- a comma separated list of tables. Typical case is the `USING` clause
531+-- of a DELETE query.
532+also
533+ :: FromClause schema params right
534+ -- ^ right
535+ -> FromClause schema params left
536+ -- ^ left
537+ -> FromClause schema params (Join left right)
538+also right left = UnsafeFromClause $
539+ renderFromClause left <> "," <+> renderFromClause right