on dev help sign in
Add support for `DELETE FROM table USING`
commit900f0b07e16cd5765f5ff095e69c8a31c5b5d742 authorRaveline <eraveline@gmail.com> dateWed 28 Nov 2018, 15:35 (8 years ago) parent6c4e1f9
1 file changed+67−10
squeal-postgresql/src/Squeal/PostgreSQL/Manipulation.hs+67−10
squeal-postgresql/src/Squeal/PostgreSQL/Manipulation.hs+67−10
@@ -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
@@ -173,11 +175,38 @@ let
173175 , "col2" ::: 'NoDef :=> 'NotNull 'PGint4 ])] '[]
174176 '[ "col1" ::: 'NotNull 'PGint4
175177 , "col2" ::: 'NotNull 'PGint4 ]
176− manipulation = deleteFrom #tab (#col1 .== #col2) ReturningStar
178+ manipulation = deleteFrom #tab NoUsing (#col1 .== #col2) ReturningStar
177179in printSQL manipulation
178180:}
179181DELETE FROM "tab" WHERE ("col1" = "col2") RETURNING *
180182
183+delete and using clause:
184+
185+>>> :{
186+let
187+ manipulation :: Manipulation
188+ '[ "tab" ::: 'Table ('[] :=>
189+ '[ "col1" ::: 'NoDef :=> 'NotNull 'PGint4
190+ , "col2" ::: 'NoDef :=> 'NotNull 'PGint4
191+ ])
192+ , "other_tab" ::: 'Table ('[] :=>
193+ '[ "col1" ::: 'NoDef :=> 'NotNull 'PGint4
194+ , "col2" ::: 'NoDef :=> 'NotNull 'PGint4
195+ ])
196+ , "third_tab" ::: 'Table ('[] :=>
197+ '[ "col1" ::: 'NoDef :=> 'NotNull 'PGint4
198+ , "col2" ::: 'NoDef :=> 'NotNull 'PGint4
199+ ])
200+ ] '[] '[]
201+ manipulation =
202+ deleteFrom #tab (Using (table #other_tab & also (table #third_tab)))
203+ ( (#tab ! #col2 .== #other_tab ! #col2)
204+ .&& (#tab ! #col2 .== #third_tab ! #col2) )
205+ (Returning Nil)
206+in printSQL manipulation
207+:}
208+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"))
209+
181210with manipulation:
182211
183212>>> type ProductsTable = '[] :=> '["product" ::: 'NoDef :=> 'NotNull 'PGtext, "date" ::: 'Def :=> 'NotNull 'PGdate]
@@ -189,7 +218,7 @@ let
189218 , "products_deleted" ::: 'Table ProductsTable
190219 ] '[ 'NotNull 'PGdate] '[]
191220 manipulation = with
192− (deleteFrom #products (#date .< param @1) ReturningStar `as` #deleted_rows)
221+ (deleteFrom #products NoUsing (#date .< param @1) ReturningStar `as` #deleted_rows)
193222 (insertQuery_ #products_deleted (selectStar (from (view (#deleted_rows `as` #t)))))
194223in printSQL manipulation
195224:}
@@ -471,21 +500,33 @@ update_ tab columns wh = update tab columns wh (Returning Nil)
471500DELETE statements
472501-----------------------------------------}
473502
474−-- | Delete rows of a table.
503+data UsingClause schema params from where
504+ NoUsing :: UsingClause schema params '[]
505+ Using
506+ :: FromClause schema params from
507+ -> UsingClause schema params from
508+
509+-- | Delete rows from a table.
475510deleteFrom
476511 :: ( SOP.SListI results
477512 , Has tab schema ('Table table)
478513 , row ~ TableToRow table
479514 , columns ~ TableToColumns table )
480515 => Alias tab -- ^ table to delete from
481− -> Condition schema '[tab ::: row] 'Ungrouped params
516+ -> UsingClause schema params from
517+ -- ^-- tables to add to the scope - more tables can be added through `also`.
518+ -> Condition schema (tab ::: row ': from) 'Ungrouped params
482519 -- ^ condition under which to delete a row
483520 -> ReturningClause schema params row results -- ^ results to return
484521 -> Manipulation schema params results
485−deleteFrom tab wh returning = UnsafeManipulation $
486− "DELETE FROM" <+> renderAlias tab
487− <+> "WHERE" <+> renderExpression wh
488− <> renderReturningClause returning
522+deleteFrom tgt uses cond returning =
523+ let renderUsing NoUsing = mempty
524+ renderUsing (Using fc) = "USING" <+> renderFromClause fc <> " "
525+ in UnsafeManipulation $
526+ "DELETE FROM" <+> renderAlias tgt
527+ <+> renderUsing uses
528+ <> "WHERE" <+> renderExpression cond
529+ <> renderReturningClause returning
489530
490531-- | Delete rows returning `Nil`.
491532deleteFrom_
@@ -493,7 +534,23 @@ deleteFrom_
493534 , row ~ TableToRow table
494535 , columns ~ TableToColumns table )
495536 => Alias tab -- ^ table to delete from
496− -> (forall t. Condition schema '[t ::: row] 'Ungrouped params)
537+ -> UsingClause schema params from
538+ -- ^-- tables to add to the scope - more tables can be added through `also`.
539+ -> Condition schema (tab ::: row ': from) 'Ungrouped params
497540 -- ^ condition under which to delete a row
498541 -> Manipulation schema params '[]
499−deleteFrom_ tab wh = deleteFrom tab wh (Returning Nil)
542+deleteFrom_ tab uses wh = deleteFrom tab uses wh (Returning Nil)
543+
544+-- | This has the behaviour of a cartesian product, taking all
545+-- possible combinations between @left@ and @right@ - exactly like a
546+-- CROSS JOIN. Used when no "CROSS JOIN" syntax is required but simply
547+-- a comma separated list of tables. Typical case is the `USING` clause
548+-- of a DELETE query.
549+also
550+ :: FromClause schema params right
551+ -- ^ right
552+ -> FromClause schema params left
553+ -- ^ left
554+ -> FromClause schema params (Join left right)
555+also right left = UnsafeFromClause $
556+ renderFromClause left <> "," <+> renderFromClause right