@@ -1,1193 +0,0 @@
1−{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
2−{-# LANGUAGE
3− DataKinds
4− , FlexibleContexts
5− , FlexibleInstances
6− , FunctionalDependencies
7− , GADTs
8− , LambdaCase
9− , MagicHash
10− , OverloadedStrings
11− , ScopedTypeVariables
12− , TypeApplications
13− , TypeFamilies
14− , TypeOperators
15− , UndecidableInstances
16−#-}
17−
18−module Squeel.PostgreSQL.Statement where
19−
20−import Control.Category
21−import Data.ByteString (ByteString)
22−import Data.Foldable
23−import Data.Maybe
24−import Data.Monoid
25−import Data.Ratio
26−import Data.String
27−import Data.Word
28−import Generics.SOP
29−import GHC.Exts
30−import GHC.OverloadedLabels
31−import GHC.TypeLits
32−import Prelude hiding (RealFrac(..), id, (.))
33−
34−import qualified Data.ByteString as ByteString
35−
36−import Squeel.PostgreSQL.Schema
37−
38−{-----------------------------------------
39−column expressions
40−-----------------------------------------}
41−
42−newtype Expression
43− (params :: [ColumnType])
44− (tables :: [(Symbol,[(Symbol,ColumnType)])])
45− (grouping :: Grouping)
46− (ty :: ColumnType)
47− = UnsafeExpression { renderExpression :: ByteString }
48− deriving (Show,Eq)
49−
50−class KnownNat n => HasParameter (n :: Nat) params ty | n params -> ty where
51− param :: Proxy# n -> Expression params tables grouping ty
52− param p = UnsafeExpression $ ("$" <>) $ fromString $ show $ natVal' p
53−instance {-# OVERLAPPING #-} HasParameter 1 (ty1:tys) ty1
54−instance {-# OVERLAPPABLE #-} (KnownNat n, HasParameter (n-1) params ty)
55− => HasParameter n (ty' : params) ty
56−
57−param1 :: Expression (ty1:tys) tables grouping ty1
58−param1 = param (proxy# :: Proxy# 1)
59−param2 :: Expression (ty1:ty2:tys) tables grouping ty2
60−param2 = param (proxy# :: Proxy# 2)
61−param3 :: Expression (ty1:ty2:ty3:tys) tables grouping ty3
62−param3 = param (proxy# :: Proxy# 3)
63−param4 :: Expression (ty1:ty2:ty3:ty4:tys) tables grouping ty4
64−param4 = param (proxy# :: Proxy# 4)
65−param5 :: Expression (ty1:ty2:ty3:ty4:ty5:tys) tables grouping ty5
66−param5 = param (proxy# :: Proxy# 5)
67−
68−class KnownSymbol column => HasColumn column columns ty
69− | column columns -> ty where
70− getColumn
71− :: Proxy# column
72− -> Expression params '[table ::: columns] 'Ungrouped ty
73− getColumn column = UnsafeExpression $ fromString $ symbolVal' column
74−instance {-# OVERLAPPING #-} KnownSymbol column
75− => HasColumn column ((column ::: optionality ty) ': tys) ('Required ty)
76−instance {-# OVERLAPPABLE #-} (KnownSymbol column, HasColumn column table ty)
77− => HasColumn column (ty' ': table) ty
78−
79−instance (HasColumn column columns ty, tables ~ '[table ::: columns])
80− => IsLabel column (Expression params tables 'Ungrouped ty) where
81− fromLabel = getColumn
82−
83−instance (HasTable table tables columns, HasColumn column columns ty)
84− => TableColumn table column (Expression params tables 'Ungrouped ty) where
85− table &. column = UnsafeExpression $
86− renderAlias table <> "." <> renderAlias column
87−
88−def :: Expression params '[] grouping ('Optional (nullity ty))
89−def = UnsafeExpression "DEFAULT"
90−
91−unDef
92− :: Expression params '[] grouping ('Required (nullity ty))
93− -> Expression params '[] grouping ('Optional (nullity ty))
94−unDef = UnsafeExpression . renderExpression
95−
96−null :: Expression params tables grouping (optionality ('Null ty))
97−null = UnsafeExpression "NULL"
98−
99−unNull
100− :: Expression params tables grouping (optionality ('NotNull ty))
101− -> Expression params tables grouping (optionality ('Null ty))
102−unNull = UnsafeExpression . renderExpression
103−
104−coalesce
105− :: [Expression params tables grouping ('Required ('Null x))]
106− -> Expression params tables grouping ('Required ('NotNull x))
107− -> Expression params tables grouping ('Required ('NotNull x))
108−coalesce nulls isn'tNull = UnsafeExpression $ mconcat
109− [ "COALESCE("
110− , ByteString.intercalate ", " $ map renderExpression nulls
111− , ", ", renderExpression isn'tNull
112− , ")"
113− ]
114−
115−unsafeBinaryOp
116− :: ByteString
117− -> Expression params tables grouping ty0
118− -> Expression params tables grouping ty1
119− -> Expression params tables grouping ty2
120−unsafeBinaryOp op x y = UnsafeExpression $ mconcat
121− ["(", renderExpression x, " ", op, " ", renderExpression y, ")"]
122−
123−unsafeUnaryOp
124− :: ByteString
125− -> Expression params tables grouping ty0
126− -> Expression params tables grouping ty1
127−unsafeUnaryOp op x = UnsafeExpression $ mconcat
128− ["(", op, " ", renderExpression x, ")"]
129−
130−unsafeFunction
131− :: ByteString
132− -> Expression params tables grouping xty
133− -> Expression params tables grouping yty
134−unsafeFunction fun x = UnsafeExpression $ mconcat
135− [fun, "(", renderExpression x, ")"]
136−
137−instance PGNum ty
138− => Num (Expression params tables grouping ('Required (nullity ty))) where
139− (+) = unsafeBinaryOp "+"
140− (-) = unsafeBinaryOp "-"
141− (*) = unsafeBinaryOp "*"
142− abs = unsafeFunction "abs"
143− signum = unsafeFunction "sign"
144− fromInteger
145− = UnsafeExpression
146− . (<> if decimal (Proxy :: Proxy ty) then "." else "")
147− . fromString
148− . show
149−
150−instance PGFractional ty => Fractional
151− (Expression params tables grouping ('Required (nullity ty))) where
152− (/) = unsafeBinaryOp "/"
153− fromRational x = fromInteger (numerator x) / fromInteger (denominator x)
154−
155−instance (PGFloating ty, PGCast 'PGNumeric ty, PGTyped ty) => Floating
156− (Expression params tables grouping ('Required (nullity ty))) where
157− pi = UnsafeExpression "pi()"
158− exp = unsafeFunction "exp"
159− log = unsafeFunction "ln"
160− sqrt = unsafeFunction "sqrt"
161− b ** x = UnsafeExpression $
162− "power(" <> renderExpression b <> ", " <> renderExpression x <> ")"
163− logBase b y = cast pgtype $ logBaseNumeric b y
164− where
165− logBaseNumeric
166− :: Expression params tables grouping ('Required (nullity ty))
167− -> Expression params tables grouping ('Required (nullity ty))
168− -> Expression params tables grouping ('Required (nullity 'PGNumeric))
169− logBaseNumeric b' y' = UnsafeExpression $ mconcat
170− [ "log("
171− , renderExpression b' <> "::numeric"
172− , ", "
173− , renderExpression y' <> "::numeric"
174− , ")"
175− ]
176− sin = unsafeFunction "sin"
177− cos = unsafeFunction "cos"
178− tan = unsafeFunction "tan"
179− asin = unsafeFunction "asin"
180− acos = unsafeFunction "acos"
181− atan = unsafeFunction "atan"
182− sinh x = (exp x - exp (-x)) / 2
183− cosh x = (exp x + exp (-x)) / 2
184− tanh x = sinh x / cosh x
185− asinh x = log (x + sqrt (x*x + 1))
186− acosh x = log (x + sqrt (x*x - 1))
187− atanh x = log ((1 + x) / (1 - x)) / 2
188−
189−atan2
190− :: PGFloating float
191− => Expression params tables grouping ('Required (nullity float))
192− -> Expression params tables grouping ('Required (nullity float))
193− -> Expression params tables grouping ('Required (nullity float))
194−atan2 y x = UnsafeExpression $
195− "atan2(" <> renderExpression y <> ", " <> renderExpression x <> ")"
196−
197−class PGCast (ty0 :: PGType) (ty1 :: PGType) where
198− cast
199− :: TypeExpression ('Required ('Null ty1))
200− -> Expression params tables grouping ('Required (nullity ty0))
201− -> Expression params tables grouping ('Required (nullity ty1))
202− cast ty x = UnsafeExpression $
203− "(" <> renderExpression x <> "::" <> renderTypeExpression ty <> ")"
204−instance PGCast 'PGInt2 'PGInt2
205−instance PGCast 'PGInt2 'PGInt4
206−instance PGCast 'PGInt2 'PGInt8
207−instance PGCast 'PGInt4 'PGInt2
208−instance PGCast 'PGInt4 'PGInt4
209−instance PGCast 'PGInt4 'PGInt8
210−instance PGCast 'PGInt8 'PGInt2
211−instance PGCast 'PGInt8 'PGInt4
212−instance PGCast 'PGInt8 'PGInt8
213−instance PGCast 'PGInt8 'PGFloat4
214−instance PGCast 'PGInt8 'PGFloat8
215−instance PGCast 'PGInt8 'PGNumeric
216−
217−div
218− :: (PGNum ty, PGTyped ty, PGCast 'PGInt8 ty, PGCast ty 'PGInt8)
219− => Expression params tables grouping ('Required (nullity ty))
220− -> Expression params tables grouping ('Required (nullity ty))
221− -> Expression params tables grouping ('Required (nullity ty))
222−div = unsafeBinaryOp "/"
223−
224−mod
225− :: (PGNum ty, PGTyped ty, PGCast 'PGInt8 ty, PGCast ty 'PGInt8)
226− => Expression params tables grouping ('Required (nullity ty))
227− -> Expression params tables grouping ('Required (nullity ty))
228− -> Expression params tables grouping ('Required (nullity ty))
229−mod = unsafeBinaryOp "%"
230−
231−truncate
232− :: (PGFractional frac, PGCast 'PGInt4 int, PGTyped int)
233− => Expression params tables grouping ('Required (nullity frac))
234− -> Expression params tables grouping ('Required (nullity int))
235−truncate = cast pgtype . truncate'
236− where
237− truncate'
238− :: Expression params tables grouping ('Required (nullity frac))
239− -> Expression params tables grouping ('Required (nullity 'PGInt4))
240− truncate' = unsafeFunction "trunc"
241−
242−round
243− :: (PGFractional frac, PGCast 'PGInt4 int, PGTyped int)
244− => Expression params tables grouping ('Required (nullity frac))
245− -> Expression params tables grouping ('Required (nullity int))
246−round = cast pgtype . round'
247− where
248− round'
249− :: Expression params tables grouping ('Required (nullity frac))
250− -> Expression params tables grouping ('Required (nullity 'PGInt4))
251− round' = unsafeFunction "round"
252−
253−ceiling
254− :: (PGFractional frac, PGCast 'PGInt4 int, PGTyped int)
255− => Expression params tables grouping ('Required (nullity frac))
256− -> Expression params tables grouping ('Required (nullity int))
257−ceiling = cast pgtype . ceiling'
258− where
259− ceiling'
260− :: Expression params tables grouping ('Required (nullity frac))
261− -> Expression params tables grouping ('Required (nullity 'PGInt4))
262− ceiling' = unsafeFunction "ceiling"
263−
264−instance IsString
265− (Expression params tables grouping ('Required (nullity 'PGText))) where
266− fromString str = UnsafeExpression $
267− "E\'" <> fromString (escape =<< str) <> "\'"
268− where
269− escape = \case
270− '\NUL' -> "\\0"
271− '\'' -> "''"
272− '"' -> "\\\""
273− '\b' -> "\\b"
274− '\n' -> "\\n"
275− '\r' -> "\\r"
276− '\t' -> "\\t"
277− '\\' -> "\\\\"
278− c -> [c]
279−
280−type Condition params tables grouping =
281− Expression params tables grouping ('Required ('NotNull 'PGBool))
282−
283−true :: Condition params tables grouping
284−true = UnsafeExpression "TRUE"
285−
286−false :: Condition params tables grouping
287−false = UnsafeExpression "FALSE"
288−
289−not_
290− :: Condition params tables grouping
291− -> Condition params tables grouping
292−not_ = unsafeUnaryOp "NOT"
293−
294−(&&*)
295− :: Condition params tables grouping
296− -> Condition params tables grouping
297− -> Condition params tables grouping
298−(&&*) = unsafeBinaryOp "AND"
299−
300−(||*)
301− :: Condition params tables grouping
302− -> Condition params tables grouping
303− -> Condition params tables grouping
304−(||*) = unsafeBinaryOp "OR"
305−
306−caseWhenThenElse
307− :: [(Condition params tables grouping, Expression params tables grouping ty)]
308− -> Expression params tables grouping ty
309− -> Expression params tables grouping ty
310−caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
311− [ "CASE"
312− , mconcat
313− [ mconcat
314− [ " WHEN ", renderExpression when_
315− , " THEN ", renderExpression then_
316− ]
317− | (when_,then_) <- whenThens
318− ]
319− , " ELSE ", renderExpression else_
320− , " END"
321− ]
322−
323−ifThenElse
324− :: Condition params tables grouping
325− -> Expression params tables grouping ty
326− -> Expression params tables grouping ty
327− -> Expression params tables grouping ty
328−ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
329−
330−(==*)
331− :: Expression params tables grouping ('Required (nullity ty))
332− -> Expression params tables grouping ('Required (nullity ty))
333− -> Expression params tables grouping ('Required (nullity 'PGBool))
334−(==*) = unsafeBinaryOp "="
335−
336−(/=*)
337− :: Expression params tables grouping ('Required (nullity ty))
338− -> Expression params tables grouping ('Required (nullity ty))
339− -> Expression params tables grouping ('Required (nullity 'PGBool))
340−(/=*) = unsafeBinaryOp "<>"
341−
342−(>=*)
343− :: Expression params tables grouping ('Required (nullity ty))
344− -> Expression params tables grouping ('Required (nullity ty))
345− -> Expression params tables grouping ('Required (nullity 'PGBool))
346−(>=*) = unsafeBinaryOp ">="
347−
348−(<*)
349− :: Expression params tables grouping ('Required (nullity ty))
350− -> Expression params tables grouping ('Required (nullity ty))
351− -> Expression params tables grouping ('Required (nullity 'PGBool))
352−(<*) = unsafeBinaryOp "<"
353−
354−(<=*)
355− :: Expression params tables grouping ('Required (nullity ty))
356− -> Expression params tables grouping ('Required (nullity ty))
357− -> Expression params tables grouping ('Required (nullity 'PGBool))
358−(<=*) = unsafeBinaryOp "<="
359−
360−(>*)
361− :: Expression params tables grouping ('Required (nullity ty))
362− -> Expression params tables grouping ('Required (nullity ty))
363− -> Expression params tables grouping ('Required (nullity 'PGBool))
364−(>*) = unsafeBinaryOp ">"
365−
366−data SortExpression params tables grouping where
367− Asc
368− :: Expression params tables grouping ty
369− -> SortExpression params tables grouping
370− Desc
371− :: Expression params tables grouping ty
372− -> SortExpression params tables grouping
373−
374−renderSortExpression :: SortExpression params tables grouping -> ByteString
375−renderSortExpression = \case
376− Asc expression -> renderExpression expression <> " ASC"
377− Desc expression -> renderExpression expression <> " DESC"
378−
379−unsafeAggregate
380− :: ByteString
381− -> Expression params tables 'Ungrouped xty
382− -> Expression params tables ('Grouped distincts) yty
383−unsafeAggregate fun x = UnsafeExpression $ mconcat
384− [fun, "(", renderExpression x, ")"]
385−
386−sum_
387− :: PGNum ty
388− => Expression params tables 'Ungrouped ('Required (nullity ty))
389− -> Expression params tables ('Grouped distincts) ('Required (nullity ty))
390−sum_ = unsafeAggregate "sum"
391−
392−class (KnownSymbol table, KnownSymbol column)
393− => GroupedBy table column distincts where
394− getGroup
395− :: (HasTable table tables columns, HasColumn column columns ty)
396− => Alias table
397− -> Alias column
398− -> Expression params tables ('Grouped distincts) ty
399− getGroup table column = UnsafeExpression $
400− renderAlias table <> "." <> renderAlias column
401−instance {-# OVERLAPPING #-} (KnownSymbol table, KnownSymbol column)
402− => GroupedBy table column '[ '(table,column)]
403−instance {-# OVERLAPPABLE #-}
404− ( KnownSymbol table
405− , KnownSymbol column
406− , GroupedBy table column distincts
407− ) => GroupedBy table column (tabcol ': distincts)
408−
409−instance
410− ( tables ~ '[table ::: columns]
411− , HasColumn column columns ty
412− , GroupedBy table column distincts
413− ) => IsLabel column
414− (Expression params tables ('Grouped distincts) ty) where
415− fromLabel p = getGroup (Alias (proxy# :: Proxy# table)) (Alias p)
416−
417−instance
418− ( HasTable table tables columns
419− , HasColumn column columns ty
420− , GroupedBy table column distincts
421− ) => TableColumn table column
422− (Expression params tables ('Grouped distincts) ty) where
423− (&.) = getGroup
424−
425−{-----------------------------------------
426−tables
427−-----------------------------------------}
428−
429−newtype Table
430− (schema :: [(Symbol,[(Symbol,ColumnType)])])
431− (columns :: [(Symbol,ColumnType)])
432− = UnsafeTable { renderTable :: ByteString }
433− deriving (Show,Eq)
434−
435−class KnownSymbol table => HasTable table tables columns
436− | table tables -> columns where
437− getTable :: Proxy# table -> Table tables columns
438− getTable table = UnsafeTable $ fromString $ symbolVal' table
439−instance {-# OVERLAPPING #-} KnownSymbol table
440− => HasTable table ((table ::: columns) ': tables) columns
441−instance {-# OVERLAPPABLE #-}
442− (KnownSymbol table, HasTable table schema columns)
443− => HasTable table (table' ': schema) columns
444−
445−instance HasTable table schema columns
446− => IsLabel table (Table schema columns) where
447− fromLabel = getTable
448−
449−data TableReference params schema tables where
450− Table
451− :: Aliased (Table schema) table
452− -> TableReference params schema '[table]
453− Subquery
454− :: Aliased (Query schema params) table
455− -> TableReference params schema '[table]
456− CrossJoin
457− :: TableReference params schema right
458− -> TableReference params schema left
459− -> TableReference params schema (Join left right)
460− InnerJoin
461− :: TableReference params schema right
462− -> Condition params (Join left right) 'Ungrouped
463− -> TableReference params schema left
464− -> TableReference params schema (Join left right)
465− LeftOuterJoin
466− :: TableReference params schema right
467− -> Condition params (Join left right) 'Ungrouped
468− -> TableReference params schema left
469− -> TableReference params schema (Join left (NullifyTables right))
470− RightOuterJoin
471− :: TableReference params schema right
472− -> Condition params (Join left right) 'Ungrouped
473− -> TableReference params schema left
474− -> TableReference params schema (Join (NullifyTables left) right)
475− FullOuterJoin
476− :: TableReference params schema right
477− -> Condition params (Join left right) 'Ungrouped
478− -> TableReference params schema left
479− -> TableReference params schema
480− (Join (NullifyTables left) (NullifyTables right))
481−
482−renderTableReference :: TableReference params schema tables -> ByteString
483−renderTableReference = \case
484− Table table -> renderAliased renderTable table
485− Subquery selection -> renderAliased renderQuery selection
486− CrossJoin right left -> mconcat
487− [ renderTableReference left
488− , " CROSS JOIN "
489− , renderTableReference right
490− ]
491− InnerJoin right on left -> mconcat
492− [ renderTableReference left
493− , " INNER JOIN "
494− , renderTableReference right
495− , " ON "
496− , renderExpression on
497− ]
498− LeftOuterJoin right on left -> mconcat
499− [ renderTableReference left
500− , " LEFT OUTER JOIN "
501− , renderTableReference right
502− , " ON "
503− , renderExpression on
504− ]
505− RightOuterJoin right on left -> mconcat
506− [ renderTableReference left
507− , " RIGHT OUTER JOIN "
508− , renderTableReference right
509− , " ON "
510− , renderExpression on
511− ]
512− FullOuterJoin right on left -> mconcat
513− [ renderTableReference left
514− , " FULL OUTER JOIN "
515− , renderTableReference right
516− , " ON "
517− , renderExpression on
518− ]
519−
520−data By
521− (tables :: [(Symbol,[(Symbol,ColumnType)])])
522− (tabcol :: (Symbol,Symbol)) where
523− By
524− :: (HasTable table tables columns, HasColumn column columns ty)
525− => (Alias table, Alias column)
526− -> By tables '(table, column)
527−
528−by
529− :: ( KnownSymbol table
530− , tables ~ '[table ::: columns]
531− , HasColumn column columns ty
532− )
533− => Alias column
534− -> By tables '(table, column)
535−by column = By (Alias (proxy# :: Proxy# (table :: Symbol)), column)
536−
537−renderBy :: By tables tabcolty -> ByteString
538−renderBy (By (table, column)) = renderAlias table <> "." <> renderAlias column
539−
540−data GroupByClause tables grouping where
541− NoGroups :: GroupByClause tables 'Ungrouped
542− Distinct
543− :: SListI distincts
544− => NP (By tables) distincts
545− -> GroupByClause tables ('Grouped distincts)
546−
547−renderGroupByClause :: GroupByClause tables grouping -> ByteString
548−renderGroupByClause = \case
549− NoGroups -> ""
550− Distinct Nil -> ""
551− Distinct distincts -> " GROUP BY " <> ByteString.intercalate ", "
552− (hcollapse (hmap (K . renderBy) distincts))
553−
554−data HavingClause params tables grouping where
555− NoHaving :: HavingClause params tables 'Ungrouped
556− Having
557− :: [Condition params tables ('Grouped distincts)]
558− -> HavingClause params tables ('Grouped distincts)
559−
560−renderHavingClause :: HavingClause params tables grouping -> ByteString
561−renderHavingClause = \case
562− NoHaving -> ""
563− Having [] -> ""
564− Having conditions -> " HAVING " <> ByteString.intercalate ", "
565− (renderExpression <$> conditions)
566−
567−data TableExpression
568− (params :: [ColumnType])
569− (schema :: [(Symbol,[(Symbol,ColumnType)])])
570− (tables :: [(Symbol,[(Symbol,ColumnType)])])
571− (grouping :: Grouping)
572− = TableExpression
573− { fromClause :: TableReference params schema tables
574− , whereClause :: [Condition params tables 'Ungrouped]
575− , groupByClause :: GroupByClause tables grouping
576− , havingClause :: HavingClause params tables grouping
577− , orderByClause :: [SortExpression params tables grouping]
578− , limitClause :: [Word64]
579− , offsetClause :: [Word64]
580− }
581−
582−renderTableExpression
583− :: TableExpression params schema tables grouping
584− -> ByteString
585−renderTableExpression
586− (TableExpression tables whs' grps' hvs' srts' lims' offs') = mconcat
587− [ "FROM ", renderTableReference tables
588− , renderWheres whs'
589− , renderGroupByClause grps'
590− , renderHavingClause hvs'
591− , renderSorts srts'
592− , renderLimits lims'
593− , renderOffsets offs'
594− ]
595− where
596− renderWheres = \case
597− [] -> ""
598− wh:[] -> " WHERE " <> renderExpression wh
599− wh:whs -> " WHERE " <> renderExpression (foldr (&&*) wh whs)
600− renderSorts = \case
601− [] -> ""
602− srts -> " SORT BY "
603− <> ByteString.intercalate ", " (renderSortExpression <$> srts)
604− renderLimits = \case
605− [] -> ""
606− lims -> " LIMIT " <> fromString (show (minimum lims))
607− renderOffsets = \case
608− [] -> ""
609− offs -> " OFFSET " <> fromString (show (sum offs))
610−
611−from
612− :: TableReference params schema tables
613− -> TableExpression params schema tables 'Ungrouped
614−from tables = TableExpression tables [] NoGroups NoHaving [] [] []
615−
616−where_
617− :: Condition params tables 'Ungrouped
618− -> TableExpression params schema tables grouping
619− -> TableExpression params schema tables grouping
620−where_ wh tables = tables {whereClause = wh : whereClause tables}
621−
622−group
623− :: SListI distincts
624− => NP (By tables) distincts
625− -> TableExpression params schema tables 'Ungrouped
626− -> TableExpression params schema tables ('Grouped distincts)
627−group distincts tables = TableExpression
628− { fromClause = fromClause tables
629− , whereClause = whereClause tables
630− , groupByClause = Distinct distincts
631− , havingClause = Having []
632− , orderByClause = []
633− , limitClause = limitClause tables
634− , offsetClause = offsetClause tables
635− }
636−
637−having
638− :: Condition params tables ('Grouped distincts)
639− -> TableExpression params schema tables ('Grouped distincts)
640− -> TableExpression params schema tables ('Grouped distincts)
641−having hv tables = tables
642− { havingClause = case havingClause tables of Having hvs -> Having (hv:hvs) }
643−
644−orderBy
645− :: [SortExpression params tables grouping]
646− -> TableExpression params schema tables grouping
647− -> TableExpression params schema tables grouping
648−orderBy srts tables = tables {orderByClause = orderByClause tables ++ srts}
649−
650−limit
651− :: Word64
652− -> TableExpression params schema tables grouping
653− -> TableExpression params schema tables grouping
654−limit lim tables = tables {limitClause = lim : limitClause tables}
655−
656−offset
657− :: Word64
658− -> TableExpression params schema tables grouping
659− -> TableExpression params schema tables grouping
660−offset off tables = tables {offsetClause = off : offsetClause tables}
661−
662−{-----------------------------------------
663−type expressions
664−-----------------------------------------}
665−
666−newtype TypeExpression (ty :: ColumnType)
667− = UnsafeTypeExpression { renderTypeExpression :: ByteString }
668− deriving (Show,Eq)
669−
670−bool :: TypeExpression ('Required ('Null 'PGBool))
671−bool = UnsafeTypeExpression "bool"
672−int2 :: TypeExpression ('Required ('Null 'PGInt2))
673−int2 = UnsafeTypeExpression "int2"
674−smallint :: TypeExpression ('Required ('Null 'PGInt2))
675−smallint = UnsafeTypeExpression "smallint"
676−int4 :: TypeExpression ('Required ('Null 'PGInt4))
677−int4 = UnsafeTypeExpression "int4"
678−int :: TypeExpression ('Required ('Null 'PGInt4))
679−int = UnsafeTypeExpression "int"
680−integer :: TypeExpression ('Required ('Null 'PGInt4))
681−integer = UnsafeTypeExpression "integer"
682−int8 :: TypeExpression ('Required ('Null 'PGInt8))
683−int8 = UnsafeTypeExpression "int8"
684−bigint :: TypeExpression ('Required ('Null 'PGInt8))
685−bigint = UnsafeTypeExpression "bigint"
686−numeric :: TypeExpression ('Required ('Null 'PGNumeric))
687−numeric = UnsafeTypeExpression "numeric"
688−float4 :: TypeExpression ('Required ('Null 'PGFloat4))
689−float4 = UnsafeTypeExpression "float4"
690−real :: TypeExpression ('Required ('Null 'PGFloat4))
691−real = UnsafeTypeExpression "real"
692−float8 :: TypeExpression ('Required ('Null 'PGFloat8))
693−float8 = UnsafeTypeExpression "float8"
694−doublePrecision :: TypeExpression ('Required ('Null 'PGFloat8))
695−doublePrecision = UnsafeTypeExpression "double precision"
696−serial2 :: TypeExpression ('Optional ('NotNull 'PGInt2))
697−serial2 = UnsafeTypeExpression "serial2"
698−smallserial :: TypeExpression ('Optional ('NotNull 'PGInt2))
699−smallserial = UnsafeTypeExpression "smallserial"
700−serial4 :: TypeExpression ('Optional ('NotNull 'PGInt4))
701−serial4 = UnsafeTypeExpression "serial4"
702−serial :: TypeExpression ('Optional ('NotNull 'PGInt4))
703−serial = UnsafeTypeExpression "serial"
704−serial8 :: TypeExpression ('Optional ('NotNull 'PGInt8))
705−serial8 = UnsafeTypeExpression "serial8"
706−bigserial :: TypeExpression ('Optional ('NotNull 'PGInt8))
707−bigserial = UnsafeTypeExpression "bigserial"
708−money :: TypeExpression ('Required ('Null 'PGMoney))
709−money = UnsafeTypeExpression "money"
710−text :: TypeExpression ('Required ('Null 'PGText))
711−text = UnsafeTypeExpression "text"
712−char
713− :: KnownNat n
714− => proxy n
715− -> TypeExpression ('Required ('Null ('PGChar n)))
716−char (_ :: proxy n) = UnsafeTypeExpression $
717− "char(" <> fromString (show (natVal' (proxy# :: Proxy# n))) <> ")"
718−character
719− :: KnownNat n
720− => proxy n
721− -> TypeExpression ('Required ('Null ('PGChar n)))
722−character (_ :: proxy n) = UnsafeTypeExpression $
723− "character(" <> fromString (show (natVal' (proxy# :: Proxy# n))) <> ")"
724−varchar
725− :: KnownNat n
726− => proxy n
727− -> TypeExpression ('Required ('Null ('PGVarChar n)))
728−varchar (_ :: proxy n) = UnsafeTypeExpression $
729− "varchar(" <> fromString (show (natVal' (proxy# :: Proxy# n))) <> ")"
730−characterVarying
731− :: KnownNat n
732− => proxy n
733− -> TypeExpression ('Required ('Null ('PGVarChar n)))
734−characterVarying (_ :: proxy n) = UnsafeTypeExpression $
735− "character varying(" <> fromString (show (natVal' (proxy# :: Proxy# n))) <> ")"
736−bytea :: TypeExpression ('Required ('Null ('PGBytea)))
737−bytea = UnsafeTypeExpression "bytea"
738−timestamp :: TypeExpression ('Required ('Null ('PGTimestamp)))
739−timestamp = UnsafeTypeExpression "timestamp"
740−timestampWithTimeZone :: TypeExpression ('Required ('Null ('PGTimestampTZ)))
741−timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
742−date :: TypeExpression ('Required ('Null ('PGDate)))
743−date = UnsafeTypeExpression "date"
744−time :: TypeExpression ('Required ('Null ('PGTime)))
745−time = UnsafeTypeExpression "time"
746−timeWithTimeZone :: TypeExpression ('Required ('Null ('PGTimeTZ)))
747−timeWithTimeZone = UnsafeTypeExpression "time with time zone"
748−interval :: TypeExpression ('Required ('Null ('PGInterval)))
749−interval = UnsafeTypeExpression "interval"
750−uuid :: TypeExpression ('Required ('Null ('PGUuid)))
751−uuid = UnsafeTypeExpression "uuid"
752−json :: TypeExpression ('Required ('Null ('PGJson)))
753−json = UnsafeTypeExpression "json"
754−jsonb :: TypeExpression ('Required ('Null ('PGJsonb)))
755−jsonb = UnsafeTypeExpression "jsonb"
756−
757−notNull
758− :: TypeExpression ('Required ('Null ty))
759− -> TypeExpression ('Required ('NotNull ty))
760−notNull ty = UnsafeTypeExpression $ renderTypeExpression ty <> " NOT NULL"
761−default_
762− :: Expression '[] '[] 'Ungrouped ('Required ty)
763− -> TypeExpression ('Required ty)
764− -> TypeExpression ('Optional ty)
765−default_ x ty = UnsafeTypeExpression $
766− renderTypeExpression ty <> " DEFAULT " <> renderExpression x
767−
768−class PGTyped (ty :: PGType) where
769− pgtype :: TypeExpression ('Required ('Null ty))
770−instance PGTyped 'PGBool where pgtype = bool
771−instance PGTyped 'PGInt2 where pgtype = int2
772−instance PGTyped 'PGInt4 where pgtype = int4
773−instance PGTyped 'PGInt8 where pgtype = int8
774−instance PGTyped 'PGNumeric where pgtype = numeric
775−instance PGTyped 'PGFloat4 where pgtype = float4
776−instance PGTyped 'PGFloat8 where pgtype = float8
777−instance PGTyped 'PGMoney where pgtype = money
778−instance PGTyped 'PGText where pgtype = text
779−instance KnownNat n => PGTyped ('PGChar n) where pgtype = char (Proxy @n)
780−instance KnownNat n => PGTyped ('PGVarChar n) where pgtype = varchar (Proxy @n)
781−instance PGTyped 'PGBytea where pgtype = bytea
782−instance PGTyped 'PGTimestamp where pgtype = timestamp
783−instance PGTyped 'PGTimestampTZ where pgtype = timestampWithTimeZone
784−instance PGTyped 'PGDate where pgtype = date
785−instance PGTyped 'PGTime where pgtype = time
786−instance PGTyped 'PGTimeTZ where pgtype = timeWithTimeZone
787−instance PGTyped 'PGInterval where pgtype = interval
788−instance PGTyped 'PGUuid where pgtype = uuid
789−instance PGTyped 'PGJson where pgtype = json
790−instance PGTyped 'PGJsonb where pgtype = jsonb
791−
792−{-----------------------------------------
793−statements
794−-----------------------------------------}
795−
796−newtype Definition
797− (schema0 :: [(Symbol,[(Symbol,ColumnType)])])
798− (schema1 :: [(Symbol,[(Symbol,ColumnType)])])
799− = UnsafeDefinition { renderDefinition :: ByteString }
800−
801−instance Category Definition where
802− id = UnsafeDefinition ";"
803− dd1 . dd0 = UnsafeDefinition $
804− renderDefinition dd0 <> " " <> renderDefinition dd1
805−
806−newtype Manipulation
807− (schema :: [(Symbol,[(Symbol,ColumnType)])])
808− (params :: [ColumnType])
809− (columns :: [(Symbol,ColumnType)])
810− = UnsafeManipulation { renderManipulation :: ByteString }
811−
812−newtype Query
813− (schema :: [(Symbol,[(Symbol,ColumnType)])])
814− (params :: [ColumnType])
815− (columns :: [(Symbol,ColumnType)])
816− = UnsafeQuery { renderQuery :: ByteString }
817−
818−query
819− :: Query schema params columns
820− -> Manipulation schema params columns
821−query q = UnsafeManipulation $ renderQuery q <> ";"
822−
823−union, unionAll, intersect, intersectAll, except, exceptAll
824− :: Query schema params columns
825− -> Query schema params columns
826− -> Query schema params columns
827−q1 `union` q2 = UnsafeQuery $
828− renderQuery q1 <> " UNION " <> renderQuery q2
829−q1 `unionAll` q2 = UnsafeQuery $
830− renderQuery q1 <> " UNION ALL " <> renderQuery q2
831−q1 `intersect` q2 = UnsafeQuery $
832− renderQuery q1 <> " INTERSECT " <> renderQuery q2
833−q1 `intersectAll` q2 = UnsafeQuery $
834− renderQuery q1 <> " INTERSECT ALL " <> renderQuery q2
835−q1 `except` q2 = UnsafeQuery $
836− renderQuery q1 <> " EXCEPT " <> renderQuery q2
837−q1 `exceptAll` q2 = UnsafeQuery $
838− renderQuery q1 <> " EXCEPT ALL " <> renderQuery q2
839−
840−{-----------------------------------------
841−SELECT statements
842−-----------------------------------------}
843−
844−select
845− :: SListI columns
846− => NP (Aliased (Expression params tables grouping)) columns
847− -> TableExpression params schema tables grouping
848− -> Query schema params columns
849−select list tabs = UnsafeQuery $
850− "SELECT " <> renderList list <> " " <> renderTableExpression tabs
851− where
852− renderList
853− = ByteString.intercalate ", "
854− . hcollapse
855− . hmap (K . renderAliased renderExpression)
856−
857−selectStar
858− :: (tables ~ '[table ::: columns])
859− => TableExpression params schema tables 'Ungrouped
860− -> Query schema params columns
861−selectStar tabs = UnsafeQuery $ "SELECT * " <> renderTableExpression tabs
862−
863−selectDotStar
864− :: HasTable table tables columns
865− => Alias table
866− -> TableExpression params schema tables 'Ungrouped
867− -> Query schema params columns
868−selectDotStar table tables = UnsafeQuery $
869− "SELECT " <> renderAlias table <> ".* " <> renderTableExpression tables
870−
871−{-----------------------------------------
872−CREATE statements
873−-----------------------------------------}
874−
875−createTable
876− :: (KnownSymbol table, SListI columns)
877− => Alias table
878− -> NP (Aliased TypeExpression) columns
879− -> Definition schema (Create table columns schema)
880−createTable table columns = UnsafeDefinition $ mconcat
881− [ "CREATE TABLE "
882− , renderAlias table
883− , " ("
884− , ByteString.intercalate ", " . hcollapse $
885− hmap (K . renderColumn) columns
886− , ");"
887− ]
888− where
889− renderColumn :: Aliased TypeExpression x -> ByteString
890− renderColumn (ty `As` column) =
891− renderAlias column <> " " <> renderTypeExpression ty
892−
893−{-----------------------------------------
894−DROP statements
895−-----------------------------------------}
896−
897−dropTable
898− :: KnownSymbol table
899− => Alias table
900− -> Definition schema (Drop table schema)
901−dropTable table = UnsafeDefinition $ "DROP TABLE " <> renderAlias table <> ";"
902−
903−{-----------------------------------------
904−ALTER statements
905−-----------------------------------------}
906−
907−alterTable
908− :: HasTable table schema columns0
909− => Alias table
910− -> AlterTable columns0 columns1
911− -> Definition schema (Alter table schema columns1)
912−alterTable table alteration = UnsafeDefinition $
913− "ALTER TABLE "
914− <> renderAlias table
915− <> " "
916− <> renderAlterTable alteration
917− <> ";"
918−
919−alterTableRename
920− :: (KnownSymbol table0, KnownSymbol table1)
921− => Alias table0
922− -> Alias table1
923− -> Definition schema (Rename table0 table1 schema)
924−alterTableRename table0 table1 = UnsafeDefinition $
925− "ALTER TABLE "
926− <> renderAlias table0
927− <> " RENAME TO "
928− <> renderAlias table1
929− <> ";"
930−
931−data AlterTable
932− (columns0 :: [(Symbol, ColumnType)])
933− (columns1 :: [(Symbol, ColumnType)]) =
934− UnsafeAlterTable {renderAlterTable :: ByteString}
935−
936−addColumnDefault
937− :: KnownSymbol column
938− => Alias column
939− -> TypeExpression ('Optional ty)
940− -> AlterTable columns (Create column ('Optional ty) columns)
941−addColumnDefault column ty = UnsafeAlterTable $
942− "ADD COLUMN "
943− <> renderAlias column
944− <> " "
945− <> renderTypeExpression ty
946−
947−addColumnNull
948− :: KnownSymbol column
949− => Alias column
950− -> TypeExpression ('Required ('Null ty))
951− -> AlterTable columns ((column ::: 'Required ('Null ty)) ': columns)
952−addColumnNull column ty = UnsafeAlterTable $
953− "ADD COLUMN "
954− <> renderAlias column
955− <> " "
956− <> renderTypeExpression ty
957−
958−dropColumn
959− :: KnownSymbol column
960− => Alias column
961− -> AlterTable columns (Drop column columns)
962−dropColumn column = UnsafeAlterTable $
963− "DROP COLUMN " <> renderAlias column
964−
965−renameColumn
966− :: (KnownSymbol column0, KnownSymbol column1)
967− => Alias column0
968− -> Alias column1
969− -> AlterTable columns (Rename column0 column1 columns)
970−renameColumn column0 column1 = UnsafeAlterTable $
971− "RENAME COLUMN " <> renderAlias column0
972− <> " TO " <> renderAlias column1
973−
974−alterColumn
975− :: (KnownSymbol column, HasColumn column columns ty0)
976− => Alias column
977− -> AlterColumn ty0 ty1
978− -> AlterTable columns (Alter column columns ty1)
979−alterColumn column alteration = UnsafeAlterTable $
980− "ALTER COLUMN " <> renderAlias column
981− <> " " <> renderAlterColumn alteration
982−
983−data AlterColumn (ty0 :: ColumnType) (ty1 :: ColumnType) =
984− UnsafeAlterColumn {renderAlterColumn :: ByteString}
985−
986−setDefault
987− :: Expression '[] '[] 'Ungrouped ('Required ty)
988− -> AlterColumn ('Required ty) ('Optional ty)
989−setDefault expression = UnsafeAlterColumn $
990− "SET DEFAULT " <> renderExpression expression
991−
992−dropDefault :: AlterColumn ('Optional ty) ('Required ty)
993−dropDefault = UnsafeAlterColumn $ "DROP DEFAULT"
994−
995−setNotNull
996− :: AlterColumn (optionality ('Null ty)) (optionality ('NotNull ty))
997−setNotNull = UnsafeAlterColumn $ "SET NOT NULL"
998−
999−dropNotNull
1000− :: AlterColumn (optionality ('NotNull ty)) (optionality ('Null ty))
1001−dropNotNull = UnsafeAlterColumn $ "DROP NOT NULL"
1002−
1003−alterType
1004− :: PGCast ty0 ty1
1005− => TypeExpression (optionality (nullity ty1))
1006− -> AlterColumn (optionality (nullity ty0)) (optionality (nullity ty1))
1007−alterType ty = UnsafeAlterColumn $ "TYPE " <> renderTypeExpression ty
1008−
1009−{-----------------------------------------
1010−INSERT statements
1011−-----------------------------------------}
1012−
1013−insertInto
1014− :: (SListI columns, HasTable table schema columns)
1015− => Alias table
1016− -> NP (Aliased (Expression params '[] 'Ungrouped)) columns
1017− -> Manipulation schema params '[]
1018−insertInto table expressions = UnsafeManipulation $ "INSERT INTO "
1019− <> renderAlias table
1020− <> " (" <> ByteString.intercalate ", " aliases
1021− <> ") VALUES ("
1022− <> ByteString.intercalate ", " values
1023− <> ");"
1024− where
1025− aliases = hcollapse $ hmap
1026− (\ (_ `As` name) -> K (renderAlias name))
1027− expressions
1028− values = hcollapse $ hmap
1029− (\ (expression `As` _) -> K (renderExpression expression))
1030− expressions
1031−
1032−insertIntoReturning
1033− :: (SListI columns, SListI results, HasTable table schema columns)
1034− => Alias table
1035− -> NP (Aliased (Expression params '[] 'Ungrouped)) columns
1036− -> NP (Aliased (Expression params '[table ::: columns] 'Ungrouped)) results
1037− -> Manipulation schema params results
1038−insertIntoReturning table inserts results
1039− = UnsafeManipulation . mconcat $
1040− [ "INSERT INTO "
1041− , renderAlias table
1042− , " (" <> ByteString.intercalate ", " aliases
1043− , ") VALUES ("
1044− , ByteString.intercalate ", " values
1045− , ") RETURNING "
1046− , renderList results
1047− , ";"
1048− ]
1049− where
1050− aliases = hcollapse $ hmap
1051− (\ (_ `As` name) -> K (renderAlias name))
1052− inserts
1053− values = hcollapse $ hmap
1054− (\ (expression `As` _) -> K (renderExpression expression))
1055− inserts
1056− renderList
1057− = ByteString.intercalate ", "
1058− . hcollapse
1059− . hmap (K . renderAliased renderExpression)
1060−
1061−{-----------------------------------------
1062−UPDATE statements
1063−-----------------------------------------}
1064−
1065−data UpdateExpression params table ty
1066− = Same
1067− | Set (Expression params table 'Ungrouped ty)
1068−
1069−renderUpdateExpression
1070− :: Aliased (UpdateExpression params '[table ::: columns]) column
1071− -> Maybe ByteString
1072−renderUpdateExpression = \case
1073− Same `As` _ -> Nothing
1074− Set expression `As` column -> Just $ mconcat
1075− [ renderAlias column
1076− , " = "
1077− , renderExpression expression
1078− ]
1079−
1080−update
1081− :: (HasTable table schema columns, SListI columns)
1082− => Alias table
1083− -> NP (Aliased (UpdateExpression params '[table ::: columns])) columns
1084− -> Condition params '[table ::: columns] 'Ungrouped
1085− -> Manipulation schema params '[]
1086−update table columns wh = UnsafeManipulation $ mconcat
1087− [ "UPDATE "
1088− , renderAlias table
1089− , " SET "
1090− , ByteString.intercalate ", " . catMaybes . hcollapse $
1091− hmap (K . renderUpdateExpression) columns
1092− , " WHERE ", renderExpression wh, ";"
1093− ]
1094−
1095−updateReturning
1096− :: (SListI columns, SListI results, HasTable table schema columns)
1097− => Alias table
1098− -> NP (Aliased (UpdateExpression params '[table ::: columns])) columns
1099− -> Condition params '[table ::: columns] 'Ungrouped
1100− -> NP (Aliased (Expression params '[table ::: columns] 'Ungrouped)) results
1101− -> Manipulation schema params results
1102−updateReturning table updates wh results = UnsafeManipulation $ mconcat
1103− [ "UPDATE "
1104− , renderAlias table
1105− , " SET "
1106− , ByteString.intercalate ", " . catMaybes . hcollapse $
1107− hmap (K . renderUpdateExpression) updates
1108− , " WHERE ", renderExpression wh
1109− , " RETURNING ", renderList results
1110− , ";"
1111− ]
1112− where
1113− renderList
1114− = ByteString.intercalate ", "
1115− . hcollapse
1116− . hmap (K . renderAliased renderExpression)
1117−
1118−upsertInto
1119− :: (SListI columns, HasTable table schema columns)
1120− => Alias table
1121− -> NP (Aliased (Expression params '[] 'Ungrouped)) columns
1122− -> NP (Aliased (UpdateExpression params '[table ::: columns])) columns
1123− -> Condition params '[table ::: columns] 'Ungrouped
1124− -> Manipulation schema params '[]
1125−upsertInto table inserts updates wh = UnsafeManipulation . mconcat $
1126− [ "INSERT INTO "
1127− , renderAlias table
1128− , " (" <> ByteString.intercalate ", " aliases
1129− , ") VALUES ("
1130− , ByteString.intercalate ", " values
1131− , ") ON CONFLICT UPDATE "
1132− , renderAlias table
1133− , " SET "
1134− , ByteString.intercalate ", " . catMaybes . hcollapse $
1135− hmap (K . renderUpdateExpression) updates
1136− , " WHERE ", renderExpression wh, ";"
1137− ] where
1138− aliases = hcollapse $ hmap
1139− (\ (_ `As` name) -> K (renderAlias name))
1140− inserts
1141− values = hcollapse $ hmap
1142− (\ (expression `As` _) -> K (renderExpression expression))
1143− inserts
1144−
1145−upsertIntoReturning
1146− :: (SListI columns, SListI results, HasTable table schema columns)
1147− => Alias table
1148− -> NP (Aliased (Expression params '[] 'Ungrouped)) columns
1149− -> NP (Aliased (UpdateExpression params '[table ::: columns])) columns
1150− -> Condition params '[table ::: columns] 'Ungrouped
1151− -> NP (Aliased (Expression params '[table ::: columns] 'Ungrouped)) results
1152− -> Manipulation schema params results
1153−upsertIntoReturning table inserts updates wh results =
1154− UnsafeManipulation . mconcat $
1155− [ "INSERT INTO "
1156− , renderAlias table
1157− , " (" <> ByteString.intercalate ", " aliases
1158− , ") VALUES ("
1159− , ByteString.intercalate ", " values
1160− , ") ON CONFLICT UPDATE "
1161− , renderAlias table
1162− , " SET "
1163− , ByteString.intercalate ", " . catMaybes . hcollapse $
1164− hmap (K . renderUpdateExpression) updates
1165− , " WHERE ", renderExpression wh
1166− , " RETURNING ", renderList results
1167− , ";"
1168− ] where
1169− aliases = hcollapse $ hmap
1170− (\ (_ `As` name) -> K (renderAlias name))
1171− inserts
1172− values = hcollapse $ hmap
1173− (\ (expression `As` _) -> K (renderExpression expression))
1174− inserts
1175− renderList
1176− = ByteString.intercalate ", "
1177− . hcollapse
1178− . hmap (K . renderAliased renderExpression)
1179−
1180−{-----------------------------------------
1181−DELETE statements
1182−-----------------------------------------}
1183−
1184−deleteFrom
1185− :: HasTable table schema columns
1186− => Alias table
1187− -> Condition params '[table ::: columns] 'Ungrouped
1188− -> Manipulation schema params '[]
1189−deleteFrom table wh = UnsafeManipulation $ mconcat
1190− [ "DELETE FROM "
1191− , renderAlias table
1192− , " WHERE ", renderExpression wh, ";"
1193− ]