on dev help sign in
RenderSQL in manipuations
commit1609239ae4886522e0a3f25db2fdae4c5f0d1b74 authorEitan Chatav <eitan.chatav@gmail.com> dateFri 7 Dec 2018, 17:01 (8 years ago) parent1600aa6
2 files changed+124−141
squeal-postgresql/src/Squeal/PostgreSQL/Manipulation.hs+65−78 squeal-postgresql/src/Squeal/PostgreSQL/Query.hs+59−63
squeal-postgresql/src/Squeal/PostgreSQL/Manipulation.hs+65−78
@@ -43,9 +43,6 @@ module Squeal.PostgreSQL.Manipulation
4343 -- * Insert
4444 , insertInto
4545 , insertInto_
46− , renderConflictClause
47− , renderConflictTarget
48− , renderConflictAction
4946 -- * Update
5047 , update
5148 , update_
@@ -206,14 +203,14 @@ instance RenderSQL (Manipulation db params columns) where
206203instance With Manipulation where
207204 with Done manip = manip
208205 with (cte :>> ctes) manip = UnsafeManipulation $
209− "WITH" <+> renderCommonTableExpressions renderManipulation cte ctes
210− <+> renderManipulation manip
206+ "WITH" <+> renderCommonTableExpressions renderSQL cte ctes
207+ <+> renderSQL manip
211208
212209-- | Convert a `Query` into a `Manipulation`.
213210queryStatement
214211 :: Query db params columns
215212 -> Manipulation db params columns
216−queryStatement q = UnsafeManipulation $ renderQuery q
213+queryStatement q = UnsafeManipulation $ renderSQL q
217214
218215{-----------------------------------------
219216INSERT statements
@@ -241,8 +238,8 @@ insertInto
241238 -> Manipulation db params row1
242239insertInto tab qry conflict ret = UnsafeManipulation $
243240 "INSERT" <+> "INTO" <+> renderSQL tab
244− <+> renderQueryClause qry
245− <> renderConflictClause conflict
241+ <+> renderSQL qry
242+ <> renderSQL conflict
246243 <> renderSQL ret
247244
248245insertInto_
@@ -274,39 +271,37 @@ data QueryClause db params columns where
274271 => Query db params row
275272 -> QueryClause db params columns
276273
277−renderQueryClause
278− :: QueryClause db params columns
279− -> ByteString
280−renderQueryClause = \case
281− Values row0 rows ->
282− parenthesized (renderCommaSeparated renderSQLPart row0)
283− <+> "VALUES"
284− <+> commaSeparated
285− ( parenthesized
286− . renderCommaSeparated renderValuePart <$> row0 : rows )
287− Select row0 tab ->
288− parenthesized (renderCommaSeparatedMaybe renderSQLPartMaybe row0)
289− <+> "SELECT"
290− <+> renderCommaSeparatedMaybe renderValuePartMaybe row0
291− <+> renderTableExpression tab
292− Subquery qry -> renderQuery qry
293− where
294− renderSQLPartMaybe, renderValuePartMaybe
295− :: ColumnExpression db params grp from column -> Maybe ByteString
296− renderSQLPartMaybe = \case
297− DefaultAs _ -> Nothing
298− Specific (_ `As` name) -> Just $ renderSQL name
299− renderValuePartMaybe = \case
300− DefaultAs _ -> Nothing
301− Specific (value `As` _) -> Just $ renderExpression value
302− renderSQLPart, renderValuePart
303− :: ColumnExpression db params grp from column -> ByteString
304− renderSQLPart = \case
305− DefaultAs name -> renderSQL name
306− Specific (_ `As` name) -> renderSQL name
307− renderValuePart = \case
308− DefaultAs _ -> "DEFAULT"
309− Specific (value `As` _) -> renderExpression value
274+instance RenderSQL (QueryClause db params columns) where
275+ renderSQL = \case
276+ Values row0 rows ->
277+ parenthesized (renderCommaSeparated renderSQLPart row0)
278+ <+> "VALUES"
279+ <+> commaSeparated
280+ ( parenthesized
281+ . renderCommaSeparated renderValuePart <$> row0 : rows )
282+ Select row0 tab ->
283+ parenthesized (renderCommaSeparatedMaybe renderSQLPartMaybe row0)
284+ <+> "SELECT"
285+ <+> renderCommaSeparatedMaybe renderValuePartMaybe row0
286+ <+> renderSQL tab
287+ Subquery qry -> renderQuery qry
288+ where
289+ renderSQLPartMaybe, renderValuePartMaybe
290+ :: ColumnExpression db params grp from column -> Maybe ByteString
291+ renderSQLPartMaybe = \case
292+ DefaultAs _ -> Nothing
293+ Specific (_ `As` name) -> Just $ renderSQL name
294+ renderValuePartMaybe = \case
295+ DefaultAs _ -> Nothing
296+ Specific (value `As` _) -> Just $ renderExpression value
297+ renderSQLPart, renderValuePart
298+ :: ColumnExpression db params grp from column -> ByteString
299+ renderSQLPart = \case
300+ DefaultAs name -> renderSQL name
301+ Specific (_ `As` name) -> renderSQL name
302+ renderValuePart = \case
303+ DefaultAs _ -> "DEFAULT"
304+ Specific (value `As` _) -> renderExpression value
310305
311306pattern Values_
312307 :: SOP.SListI columns
@@ -389,14 +384,12 @@ instance
389384 (NP (ColumnExpression db params ('Grouped bys) from) columns) where
390385 tab ! col = tab ! col :* Nil
391386
392−renderColumnExpression
393− :: ColumnExpression db params grp from column
394− -> ByteString
395−renderColumnExpression = \case
396− DefaultAs col ->
397− renderSQL col <+> "=" <+> "DEFAULT"
398− Specific (expression `As` col) ->
399− renderSQL col <+> "=" <+> renderExpression expression
387+instance RenderSQL (ColumnExpression db params grp from column) where
388+ renderSQL = \case
389+ DefaultAs col ->
390+ renderSQL col <+> "=" <+> "DEFAULT"
391+ Specific (expression `As` col) ->
392+ renderSQL col <+> "=" <+> renderSQL expression
400393
401394-- | A `ReturningClause` computes and return value(s) based
402395-- on each row actually inserted, updated or deleted. This is primarily
@@ -435,14 +428,12 @@ data ConflictClause tab db params table where
435428 -> ConflictClause tab db params (constraints :=> columns)
436429
437430-- | Render a `ConflictClause`.
438−renderConflictClause
439− :: SOP.SListI (TableToColumns table)
440− => ConflictClause tab db params table
441− -> ByteString
442−renderConflictClause = \case
443− OnConflictDoRaise -> ""
444− OnConflict target action -> " ON CONFLICT"
445− <+> renderConflictTarget target <+> renderConflictAction action
431+instance SOP.SListI (TableToColumns table)
432+ => RenderSQL (ConflictClause tab db params table) where
433+ renderSQL = \case
434+ OnConflictDoRaise -> ""
435+ OnConflict target action -> " ON CONFLICT"
436+ <+> renderSQL target <+> renderSQL action
446437
447438data ConflictAction tab db params columns where
448439 DoNothing :: ConflictAction tab db params columns
@@ -456,17 +447,15 @@ data ConflictAction tab db params columns where
456447 -> [Condition db params 'Ungrouped '[tab ::: row, "excluded" ::: row]]
457448 -> ConflictAction tab db params columns
458449
459−renderConflictAction
460− :: ConflictAction tab db params columns
461− -> ByteString
462−renderConflictAction = \case
463− DoNothing -> "DO NOTHING"
464− DoUpdate updates whs'
465− -> "DO UPDATE SET"
466− <+> renderCommaSeparated renderColumnExpression updates
467− <> case whs' of
468− [] -> ""
469− wh:whs -> " WHERE" <+> renderExpression (foldr (.&&) wh whs)
450+instance RenderSQL (ConflictAction tab db params columns) where
451+ renderSQL = \case
452+ DoNothing -> "DO NOTHING"
453+ DoUpdate updates whs'
454+ -> "DO UPDATE SET"
455+ <+> renderCommaSeparated renderSQL updates
456+ <> case whs' of
457+ [] -> ""
458+ wh:whs -> " WHERE" <+> renderSQL (foldr (.&&) wh whs)
470459
471460-- | A `ConflictTarget` specifies the constraint violation that triggers a
472461-- `ConflictAction`.
@@ -477,11 +466,9 @@ data ConflictTarget constraints where
477466 -> ConflictTarget constraints
478467
479468-- | Render a `ConflictTarget`
480−renderConflictTarget
481− :: ConflictTarget constraints
482− -> ByteString
483−renderConflictTarget (OnConstraint con) =
484− "ON" <+> "CONSTRAINT" <+> renderSQL con
469+instance RenderSQL (ConflictTarget constraints) where
470+ renderSQL (OnConstraint con) =
471+ "ON" <+> "CONSTRAINT" <+> renderSQL con
485472
486473{-----------------------------------------
487474UPDATE statements
@@ -510,8 +497,8 @@ update tab columns wh returning = UnsafeManipulation $
510497 "UPDATE"
511498 <+> renderSQL tab
512499 <+> "SET"
513− <+> renderCommaSeparated renderColumnExpression columns
514− <+> "WHERE" <+> renderExpression wh
500+ <+> renderCommaSeparated renderSQL columns
501+ <+> "WHERE" <+> renderSQL wh
515502 <> renderSQL returning
516503
517504-- | Update a row returning `Nil`.
@@ -561,8 +548,8 @@ deleteFrom tab using wh returning = UnsafeManipulation $
561548 <+> renderSQL tab
562549 <> case using of
563550 NoUsing -> ""
564− Using tables -> " USING" <+> renderFromClause tables
565− <+> "WHERE" <+> renderExpression wh
551+ Using from -> " USING" <+> renderSQL from
552+ <+> "WHERE" <+> renderSQL wh
566553 <> renderSQL returning
567554
568555-- | Delete rows returning `Nil`.
@@ -591,4 +578,4 @@ also
591578 -- ^ left
592579 -> FromClause schema params (Join left right)
593580also right left = UnsafeFromClause $
594− renderFromClause left <> "," <+> renderFromClause right
581+ renderSQL left <> "," <+> renderSQL right
squeal-postgresql/src/Squeal/PostgreSQL/Query.hs+59−63
@@ -69,7 +69,6 @@ module Squeal.PostgreSQL.Query
6969 , jsonbToRecordSet
7070 -- * Table Expressions
7171 , TableExpression (..)
72− , renderTableExpression
7372 , from
7473 , where_
7574 , groupBy
@@ -90,7 +89,6 @@ module Squeal.PostgreSQL.Query
9089 , fullOuterJoin
9190 -- * Grouping
9291 , By (..)
93− , renderBy
9492 , GroupByClause (..)
9593 , HavingClause (..)
9694 -- * Sorting
@@ -329,9 +327,9 @@ union
329327 -> Query db params columns
330328 -> Query db params columns
331329q1 `union` q2 = UnsafeQuery $
332− parenthesized (renderQuery q1)
330+ parenthesized (renderSQL q1)
333331 <+> "UNION"
334− <+> parenthesized (renderQuery q2)
332+ <+> parenthesized (renderSQL q2)
335333
336334-- | The results of two queries can be combined using the set operation
337335-- `unionAll`, the disjoint union. Duplicate rows are retained.
@@ -340,9 +338,9 @@ unionAll
340338 -> Query db params columns
341339 -> Query db params columns
342340q1 `unionAll` q2 = UnsafeQuery $
343− parenthesized (renderQuery q1)
341+ parenthesized (renderSQL q1)
344342 <+> "UNION" <+> "ALL"
345− <+> parenthesized (renderQuery q2)
343+ <+> parenthesized (renderSQL q2)
346344
347345-- | The results of two queries can be combined using the set operation
348346-- `intersect`, the intersection. Duplicate rows are eliminated.
@@ -351,9 +349,9 @@ intersect
351349 -> Query db params columns
352350 -> Query db params columns
353351q1 `intersect` q2 = UnsafeQuery $
354− parenthesized (renderQuery q1)
352+ parenthesized (renderSQL q1)
355353 <+> "INTERSECT"
356− <+> parenthesized (renderQuery q2)
354+ <+> parenthesized (renderSQL q2)
357355
358356-- | The results of two queries can be combined using the set operation
359357-- `intersectAll`, the intersection. Duplicate rows are retained.
@@ -362,9 +360,9 @@ intersectAll
362360 -> Query db params columns
363361 -> Query db params columns
364362q1 `intersectAll` q2 = UnsafeQuery $
365− parenthesized (renderQuery q1)
363+ parenthesized (renderSQL q1)
366364 <+> "INTERSECT" <+> "ALL"
367− <+> parenthesized (renderQuery q2)
365+ <+> parenthesized (renderSQL q2)
368366
369367-- | The results of two queries can be combined using the set operation
370368-- `except`, the set difference. Duplicate rows are eliminated.
@@ -373,9 +371,9 @@ except
373371 -> Query db params columns
374372 -> Query db params columns
375373q1 `except` q2 = UnsafeQuery $
376− parenthesized (renderQuery q1)
374+ parenthesized (renderSQL q1)
377375 <+> "EXCEPT"
378− <+> parenthesized (renderQuery q2)
376+ <+> parenthesized (renderSQL q2)
379377
380378-- | The results of two queries can be combined using the set operation
381379-- `exceptAll`, the set difference. Duplicate rows are retained.
@@ -384,9 +382,9 @@ exceptAll
384382 -> Query db params columns
385383 -> Query db params columns
386384q1 `exceptAll` q2 = UnsafeQuery $
387− parenthesized (renderQuery q1)
385+ parenthesized (renderSQL q1)
388386 <+> "EXCEPT" <+> "ALL"
389− <+> parenthesized (renderQuery q2)
387+ <+> parenthesized (renderSQL q2)
390388
391389{-----------------------------------------
392390SELECT queries
@@ -456,7 +454,7 @@ select
456454select selection tabexpr = UnsafeQuery $
457455 "SELECT"
458456 <+> renderSQL selection
459− <+> renderTableExpression tabexpr
457+ <+> renderSQL tabexpr
460458
461459select_
462460 :: (SListI row, row ~ (x ': xs))
@@ -477,7 +475,7 @@ selectDistinct
477475selectDistinct selection tabexpr = UnsafeQuery $
478476 "SELECT DISTINCT"
479477 <+> renderSQL selection
480− <+> renderTableExpression tabexpr
478+ <+> renderSQL tabexpr
481479
482480selectDistinct_
483481 :: (SListI columns, columns ~ (col ': cols))
@@ -511,11 +509,11 @@ values rw rws = UnsafeQuery $ "SELECT * FROM"
511509 ( parenthesized
512510 . renderCommaSeparated renderValuePart <$> rw:rws )
513511 ) <+> "AS t"
514− <+> parenthesized (renderCommaSeparated renderSQLPart rw)
512+ <+> parenthesized (renderCommaSeparated renderAliasPart rw)
515513 where
516− renderSQLPart, renderValuePart
514+ renderAliasPart, renderValuePart
517515 :: Aliased (Expression db params 'Ungrouped '[] ) ty -> ByteString
518− renderSQLPart (_ `As` name) = renderSQL name
516+ renderAliasPart (_ `As` name) = renderSQL name
519517 renderValuePart (value `As` _) = renderSQL value
520518
521519-- | `values_` computes a row value or set of row values
@@ -585,34 +583,32 @@ data TableExpression
585583 }
586584
587585-- | Render a `TableExpression`
588−renderTableExpression
589− :: TableExpression db params grp from
590− -> ByteString
591−renderTableExpression
592− (TableExpression frm' whs' grps' hvs' srts' lims' offs') = mconcat
593− [ "FROM ", renderFromClause frm'
594− , renderWheres whs'
595− , renderSQL grps'
596− , renderSQL hvs'
597− , renderOrderByClause srts'
598− , renderLimits lims'
599− , renderOffsets offs'
600− ]
601− where
602− renderWheres = \case
603− [] -> ""
604− wh:[] -> " WHERE" <+> renderSQL wh
605− wh:whs -> " WHERE" <+> renderSQL (foldr (.&&) wh whs)
606− renderOrderByClause = \case
607− [] -> ""
608− srts -> " ORDER BY"
609− <+> commaSeparated (renderSQL <$> srts)
610− renderLimits = \case
611− [] -> ""
612− lims -> " LIMIT" <+> fromString (show (minimum lims))
613− renderOffsets = \case
614− [] -> ""
615− offs -> " OFFSET" <+> fromString (show (sum offs))
586+instance RenderSQL (TableExpression db params grp from) where
587+ renderSQL
588+ (TableExpression frm' whs' grps' hvs' srts' lims' offs') = mconcat
589+ [ "FROM ", renderSQL frm'
590+ , renderWheres whs'
591+ , renderSQL grps'
592+ , renderSQL hvs'
593+ , renderOrderByClause srts'
594+ , renderLimits lims'
595+ , renderOffsets offs'
596+ ]
597+ where
598+ renderWheres = \case
599+ [] -> ""
600+ wh:[] -> " WHERE" <+> renderSQL wh
601+ wh:whs -> " WHERE" <+> renderSQL (foldr (.&&) wh whs)
602+ renderOrderByClause = \case
603+ [] -> ""
604+ srts -> " ORDER BY"
605+ <+> commaSeparated (renderSQL <$> srts)
606+ renderLimits = \case
607+ [] -> ""
608+ lims -> " LIMIT" <+> fromString (show (minimum lims))
609+ renderOffsets = \case
610+ [] -> ""
611+ offs -> " OFFSET" <+> fromString (show (sum offs))
616612
617613-- | A `from` generates a `TableExpression` from a table reference that can be
618614-- a table name, or a derived table such as a subquery, a JOIN construct,
@@ -835,6 +831,8 @@ as a subquery, a @JOIN@ construct, or complex combinations of these.
835831newtype FromClause db params from
836832 = UnsafeFromClause { renderFromClause :: ByteString }
837833 deriving (GHC.Generic,Show,Eq,Ord,NFData)
834+instance RenderSQL (FromClause db params from) where
835+ renderSQL = renderFromClause
838836
839837-- | A real `table` is a table from the database.
840838table
@@ -878,7 +876,7 @@ crossJoin
878876 -- ^ left
879877 -> FromClause db params (Join left right)
880878crossJoin right left = UnsafeFromClause $
881− renderFromClause left <+> "CROSS JOIN" <+> renderFromClause right
879+ renderSQL left <+> "CROSS JOIN" <+> renderSQL right
882880
883881{- | @left & innerJoin right on@. The joined table is filtered by
884882the @on@ condition.
@@ -892,7 +890,7 @@ innerJoin
892890 -- ^ left
893891 -> FromClause db params (Join left right)
894892innerJoin right on left = UnsafeFromClause $
895− renderFromClause left <+> "INNER JOIN" <+> renderFromClause right
893+ renderSQL left <+> "INNER JOIN" <+> renderSQL right
896894 <+> "ON" <+> renderSQL on
897895
898896{- | @left & leftOuterJoin right on@. First, an inner join is performed.
@@ -909,7 +907,7 @@ leftOuterJoin
909907 -- ^ left
910908 -> FromClause db params (Join left (NullifyFrom right))
911909leftOuterJoin right on left = UnsafeFromClause $
912− renderFromClause left <+> "LEFT OUTER JOIN" <+> renderFromClause right
910+ renderSQL left <+> "LEFT OUTER JOIN" <+> renderSQL right
913911 <+> "ON" <+> renderSQL on
914912
915913{- | @left & rightOuterJoin right on@. First, an inner join is performed.
@@ -927,7 +925,7 @@ rightOuterJoin
927925 -- ^ left
928926 -> FromClause db params (Join (NullifyFrom left) right)
929927rightOuterJoin right on left = UnsafeFromClause $
930− renderFromClause left <+> "RIGHT OUTER JOIN" <+> renderFromClause right
928+ renderSQL left <+> "RIGHT OUTER JOIN" <+> renderSQL right
931929 <+> "ON" <+> renderSQL on
932930
933931{- | @left & fullOuterJoin right on@. First, an inner join is performed.
@@ -947,7 +945,7 @@ fullOuterJoin
947945 -> FromClause db params
948946 (Join (NullifyFrom left) (NullifyFrom right))
949947fullOuterJoin right on left = UnsafeFromClause $
950− renderFromClause left <+> "FULL OUTER JOIN" <+> renderFromClause right
948+ renderSQL left <+> "FULL OUTER JOIN" <+> renderSQL right
951949 <+> "ON" <+> renderSQL on
952950
953951{-----------------------------------------
@@ -974,6 +972,10 @@ data By
974972deriving instance Show (By from by)
975973deriving instance Eq (By from by)
976974deriving instance Ord (By from by)
975+instance RenderSQL (By from by) where
976+ renderSQL = \case
977+ By1 column -> renderSQL column
978+ By2 rel column -> renderSQL rel <> "." <> renderSQL column
977979
978980instance (HasUnique rel rels cols, Has col cols ty, by ~ '(rel, col))
979981 => IsLabel col (By rels by) where fromLabel = By1 fromLabel
@@ -985,12 +987,6 @@ instance (Has rel rels cols, Has col cols ty, bys ~ '[ '(rel, col)])
985987 => IsQualified rel col (NP (By rels) bys) where
986988 rel ! col = By2 rel col :* Nil
987989
988−-- | Renders a `By`.
989−renderBy :: By from by -> ByteString
990−renderBy = \case
991− By1 column -> renderSQL column
992− By2 rel column -> renderSQL rel <> "." <> renderSQL column
993−
994990-- | A `GroupByClause` indicates the `Grouping` of a `TableExpression`.
995991-- A `NoGroups` indicates `Ungrouped` while a `Group` indicates `Grouped`.
996992-- @NoGroups@ is distinguised from @Group Nil@ since no aggregation can be
@@ -1009,7 +1005,7 @@ instance RenderSQL (GroupByClause grp from) where
10091005 renderSQL = \case
10101006 NoGroups -> ""
10111007 Group Nil -> ""
1012− Group bys -> " GROUP BY" <+> renderCommaSeparated renderBy bys
1008+ Group bys -> " GROUP BY" <+> renderCommaSeparated renderSQL bys
10131009
10141010-- | A `HavingClause` is used to eliminate groups that are not of interest.
10151011-- An `Ungrouped` `TableExpression` may only use `NoHaving` while a `Grouped`
@@ -1083,7 +1079,7 @@ unsafeSubqueryExpression
10831079 -> Query db params '[alias ::: ty]
10841080 -> Expression db params grp from (nullity 'PGbool)
10851081unsafeSubqueryExpression op x q = UnsafeExpression $
1086− renderSQL x <+> op <+> parenthesized (renderQuery q)
1082+ renderSQL x <+> op <+> parenthesized (renderSQL q)
10871083
10881084unsafeRowSubqueryExpression
10891085 :: SListI row
@@ -1092,7 +1088,7 @@ unsafeRowSubqueryExpression
10921088 -> Query db params row
10931089 -> Expression db params grp from (nullity 'PGbool)
10941090unsafeRowSubqueryExpression op xs q = UnsafeExpression $
1095− renderSQL (row xs) <+> op <+> parenthesized (renderQuery q)
1091+ renderSQL (row xs) <+> op <+> parenthesized (renderSQL q)
10961092
10971093-- | The right-hand side is a sub`Query`, which must return exactly one column.
10981094-- The left-hand expression is evaluated and compared to each row of the
@@ -1404,5 +1400,5 @@ class With statement where
14041400instance With Query where
14051401 with Done query = query
14061402 with (cte :>> ctes) query = UnsafeQuery $
1407− "WITH" <+> renderCommonTableExpressions renderQuery cte ctes
1408− <+> renderQuery query
1403+ "WITH" <+> renderCommonTableExpressions renderSQL cte ctes
1404+ <+> renderSQL query