@@ -1,1197 +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−{-----------------------------------------
380−aggregation
381−-----------------------------------------}
382−
383−data By
384− (tables :: [(Symbol,[(Symbol,ColumnType)])])
385− (tabcol :: (Symbol,Symbol)) where
386− By
387− :: (HasTable table tables columns, HasColumn column columns ty)
388− => (Alias table, Alias column)
389− -> By tables '(table, column)
390−
391−by
392− :: ( KnownSymbol table
393− , tables ~ '[table ::: columns]
394− , HasColumn column columns ty
395− )
396− => Alias column
397− -> By tables '(table, column)
398−by column = By (Alias (proxy# :: Proxy# (table :: Symbol)), column)
399−
400−renderBy :: By tables tabcolty -> ByteString
401−renderBy (By (table, column)) = renderAlias table <> "." <> renderAlias column
402−
403−data GroupByClause tables grouping where
404− NoGroups :: GroupByClause tables 'Ungrouped
405− Group
406− :: SListI bys
407− => NP (By tables) bys
408− -> GroupByClause tables ('Grouped bys)
409−
410−renderGroupByClause :: GroupByClause tables grouping -> ByteString
411−renderGroupByClause = \case
412− NoGroups -> ""
413− Group Nil -> ""
414− Group bys -> " GROUP BY " <> ByteString.intercalate ", "
415− (hcollapse (hmap (K . renderBy) bys))
416−
417−data HavingClause params tables grouping where
418− NoHaving :: HavingClause params tables 'Ungrouped
419− Having
420− :: [Condition params tables ('Grouped bys)]
421− -> HavingClause params tables ('Grouped bys)
422−
423−renderHavingClause :: HavingClause params tables grouping -> ByteString
424−renderHavingClause = \case
425− NoHaving -> ""
426− Having [] -> ""
427− Having conditions -> " HAVING " <> ByteString.intercalate ", "
428− (renderExpression <$> conditions)
429−
430−class (KnownSymbol table, KnownSymbol column)
431− => GroupedBy table column bys where
432− getGroup
433− :: (HasTable table tables columns, HasColumn column columns ty)
434− => Alias table
435− -> Alias column
436− -> Expression params tables ('Grouped bys) ty
437− getGroup table column = UnsafeExpression $
438− renderAlias table <> "." <> renderAlias column
439−instance {-# OVERLAPPING #-} (KnownSymbol table, KnownSymbol column)
440− => GroupedBy table column '[ '(table,column)]
441−instance {-# OVERLAPPABLE #-}
442− ( KnownSymbol table
443− , KnownSymbol column
444− , GroupedBy table column bys
445− ) => GroupedBy table column (tabcol ': bys)
446−
447−instance
448− ( tables ~ '[table ::: columns]
449− , HasColumn column columns ty
450− , GroupedBy table column bys
451− ) => IsLabel column
452− (Expression params tables ('Grouped bys) ty) where
453− fromLabel p = getGroup (Alias (proxy# :: Proxy# table)) (Alias p)
454−
455−instance
456− ( HasTable table tables columns
457− , HasColumn column columns ty
458− , GroupedBy table column bys
459− ) => TableColumn table column
460− (Expression params tables ('Grouped bys) ty) where
461− (&.) = getGroup
462−
463−unsafeAggregate
464− :: ByteString
465− -> Expression params tables 'Ungrouped xty
466− -> Expression params tables ('Grouped bys) yty
467−unsafeAggregate fun x = UnsafeExpression $ mconcat
468− [fun, "(", renderExpression x, ")"]
469−
470−sum_
471− :: PGNum ty
472− => Expression params tables 'Ungrouped ('Required (nullity ty))
473− -> Expression params tables ('Grouped bys) ('Required (nullity ty))
474−sum_ = unsafeAggregate "sum"
475−
476−{-----------------------------------------
477−tables
478−-----------------------------------------}
479−
480−newtype Table
481− (schema :: [(Symbol,[(Symbol,ColumnType)])])
482− (columns :: [(Symbol,ColumnType)])
483− = UnsafeTable { renderTable :: ByteString }
484− deriving (Show,Eq)
485−
486−class KnownSymbol table => HasTable table tables columns
487− | table tables -> columns where
488− getTable :: Proxy# table -> Table tables columns
489− getTable table = UnsafeTable $ fromString $ symbolVal' table
490−instance {-# OVERLAPPING #-} KnownSymbol table
491− => HasTable table ((table ::: columns) ': tables) columns
492−instance {-# OVERLAPPABLE #-}
493− (KnownSymbol table, HasTable table schema columns)
494− => HasTable table (table' ': schema) columns
495−
496−instance HasTable table schema columns
497− => IsLabel table (Table schema columns) where
498− fromLabel = getTable
499−
500−data TableReference params schema tables where
501− Table
502− :: Aliased (Table schema) table
503− -> TableReference params schema '[table]
504− Subquery
505− :: Aliased (Query schema params) table
506− -> TableReference params schema '[table]
507− CrossJoin
508− :: TableReference params schema right
509− -> TableReference params schema left
510− -> TableReference params schema (Join left right)
511− InnerJoin
512− :: TableReference params schema right
513− -> Condition params (Join left right) 'Ungrouped
514− -> TableReference params schema left
515− -> TableReference params schema (Join left right)
516− LeftOuterJoin
517− :: TableReference params schema right
518− -> Condition params (Join left right) 'Ungrouped
519− -> TableReference params schema left
520− -> TableReference params schema (Join left (NullifyTables right))
521− RightOuterJoin
522− :: TableReference params schema right
523− -> Condition params (Join left right) 'Ungrouped
524− -> TableReference params schema left
525− -> TableReference params schema (Join (NullifyTables left) right)
526− FullOuterJoin
527− :: TableReference params schema right
528− -> Condition params (Join left right) 'Ungrouped
529− -> TableReference params schema left
530− -> TableReference params schema
531− (Join (NullifyTables left) (NullifyTables right))
532−
533−renderTableReference :: TableReference params schema tables -> ByteString
534−renderTableReference = \case
535− Table table -> renderAliased renderTable table
536− Subquery selection -> renderAliased renderQuery selection
537− CrossJoin right left -> mconcat
538− [ renderTableReference left
539− , " CROSS JOIN "
540− , renderTableReference right
541− ]
542− InnerJoin right on left -> mconcat
543− [ renderTableReference left
544− , " INNER JOIN "
545− , renderTableReference right
546− , " ON "
547− , renderExpression on
548− ]
549− LeftOuterJoin right on left -> mconcat
550− [ renderTableReference left
551− , " LEFT OUTER JOIN "
552− , renderTableReference right
553− , " ON "
554− , renderExpression on
555− ]
556− RightOuterJoin right on left -> mconcat
557− [ renderTableReference left
558− , " RIGHT OUTER JOIN "
559− , renderTableReference right
560− , " ON "
561− , renderExpression on
562− ]
563− FullOuterJoin right on left -> mconcat
564− [ renderTableReference left
565− , " FULL OUTER JOIN "
566− , renderTableReference right
567− , " ON "
568− , renderExpression on
569− ]
570−
571−data TableExpression
572− (params :: [ColumnType])
573− (schema :: [(Symbol,[(Symbol,ColumnType)])])
574− (tables :: [(Symbol,[(Symbol,ColumnType)])])
575− (grouping :: Grouping)
576− = TableExpression
577− { fromClause :: TableReference params schema tables
578− , whereClause :: [Condition params tables 'Ungrouped]
579− , groupByClause :: GroupByClause tables grouping
580− , havingClause :: HavingClause params tables grouping
581− , orderByClause :: [SortExpression params tables grouping]
582− , limitClause :: [Word64]
583− , offsetClause :: [Word64]
584− }
585−
586−renderTableExpression
587− :: TableExpression params schema tables grouping
588− -> ByteString
589−renderTableExpression
590− (TableExpression tables whs' grps' hvs' srts' lims' offs') = mconcat
591− [ "FROM ", renderTableReference tables
592− , renderWheres whs'
593− , renderGroupByClause grps'
594− , renderHavingClause hvs'
595− , renderSorts srts'
596− , renderLimits lims'
597− , renderOffsets offs'
598− ]
599− where
600− renderWheres = \case
601− [] -> ""
602− wh:[] -> " WHERE " <> renderExpression wh
603− wh:whs -> " WHERE " <> renderExpression (foldr (&&*) wh whs)
604− renderSorts = \case
605− [] -> ""
606− srts -> " SORT BY "
607− <> ByteString.intercalate ", " (renderSortExpression <$> srts)
608− renderLimits = \case
609− [] -> ""
610− lims -> " LIMIT " <> fromString (show (minimum lims))
611− renderOffsets = \case
612− [] -> ""
613− offs -> " OFFSET " <> fromString (show (sum offs))
614−
615−from
616− :: TableReference params schema tables
617− -> TableExpression params schema tables 'Ungrouped
618−from tables = TableExpression tables [] NoGroups NoHaving [] [] []
619−
620−where_
621− :: Condition params tables 'Ungrouped
622− -> TableExpression params schema tables grouping
623− -> TableExpression params schema tables grouping
624−where_ wh tables = tables {whereClause = wh : whereClause tables}
625−
626−group
627− :: SListI bys
628− => NP (By tables) bys
629− -> TableExpression params schema tables 'Ungrouped
630− -> TableExpression params schema tables ('Grouped bys)
631−group bys tables = TableExpression
632− { fromClause = fromClause tables
633− , whereClause = whereClause tables
634− , groupByClause = Group bys
635− , havingClause = Having []
636− , orderByClause = []
637− , limitClause = limitClause tables
638− , offsetClause = offsetClause tables
639− }
640−
641−having
642− :: Condition params tables ('Grouped bys)
643− -> TableExpression params schema tables ('Grouped bys)
644− -> TableExpression params schema tables ('Grouped bys)
645−having hv tables = tables
646− { havingClause = case havingClause tables of Having hvs -> Having (hv:hvs) }
647−
648−orderBy
649− :: [SortExpression params tables grouping]
650− -> TableExpression params schema tables grouping
651− -> TableExpression params schema tables grouping
652−orderBy srts tables = tables {orderByClause = orderByClause tables ++ srts}
653−
654−limit
655− :: Word64
656− -> TableExpression params schema tables grouping
657− -> TableExpression params schema tables grouping
658−limit lim tables = tables {limitClause = lim : limitClause tables}
659−
660−offset
661− :: Word64
662− -> TableExpression params schema tables grouping
663− -> TableExpression params schema tables grouping
664−offset off tables = tables {offsetClause = off : offsetClause tables}
665−
666−{-----------------------------------------
667−type expressions
668−-----------------------------------------}
669−
670−newtype TypeExpression (ty :: ColumnType)
671− = UnsafeTypeExpression { renderTypeExpression :: ByteString }
672− deriving (Show,Eq)
673−
674−bool :: TypeExpression ('Required ('Null 'PGBool))
675−bool = UnsafeTypeExpression "bool"
676−int2 :: TypeExpression ('Required ('Null 'PGInt2))
677−int2 = UnsafeTypeExpression "int2"
678−smallint :: TypeExpression ('Required ('Null 'PGInt2))
679−smallint = UnsafeTypeExpression "smallint"
680−int4 :: TypeExpression ('Required ('Null 'PGInt4))
681−int4 = UnsafeTypeExpression "int4"
682−int :: TypeExpression ('Required ('Null 'PGInt4))
683−int = UnsafeTypeExpression "int"
684−integer :: TypeExpression ('Required ('Null 'PGInt4))
685−integer = UnsafeTypeExpression "integer"
686−int8 :: TypeExpression ('Required ('Null 'PGInt8))
687−int8 = UnsafeTypeExpression "int8"
688−bigint :: TypeExpression ('Required ('Null 'PGInt8))
689−bigint = UnsafeTypeExpression "bigint"
690−numeric :: TypeExpression ('Required ('Null 'PGNumeric))
691−numeric = UnsafeTypeExpression "numeric"
692−float4 :: TypeExpression ('Required ('Null 'PGFloat4))
693−float4 = UnsafeTypeExpression "float4"
694−real :: TypeExpression ('Required ('Null 'PGFloat4))
695−real = UnsafeTypeExpression "real"
696−float8 :: TypeExpression ('Required ('Null 'PGFloat8))
697−float8 = UnsafeTypeExpression "float8"
698−doublePrecision :: TypeExpression ('Required ('Null 'PGFloat8))
699−doublePrecision = UnsafeTypeExpression "double precision"
700−serial2 :: TypeExpression ('Optional ('NotNull 'PGInt2))
701−serial2 = UnsafeTypeExpression "serial2"
702−smallserial :: TypeExpression ('Optional ('NotNull 'PGInt2))
703−smallserial = UnsafeTypeExpression "smallserial"
704−serial4 :: TypeExpression ('Optional ('NotNull 'PGInt4))
705−serial4 = UnsafeTypeExpression "serial4"
706−serial :: TypeExpression ('Optional ('NotNull 'PGInt4))
707−serial = UnsafeTypeExpression "serial"
708−serial8 :: TypeExpression ('Optional ('NotNull 'PGInt8))
709−serial8 = UnsafeTypeExpression "serial8"
710−bigserial :: TypeExpression ('Optional ('NotNull 'PGInt8))
711−bigserial = UnsafeTypeExpression "bigserial"
712−money :: TypeExpression ('Required ('Null 'PGMoney))
713−money = UnsafeTypeExpression "money"
714−text :: TypeExpression ('Required ('Null 'PGText))
715−text = UnsafeTypeExpression "text"
716−char
717− :: KnownNat n
718− => proxy n
719− -> TypeExpression ('Required ('Null ('PGChar n)))
720−char (_ :: proxy n) = UnsafeTypeExpression $
721− "char(" <> fromString (show (natVal' (proxy# :: Proxy# n))) <> ")"
722−character
723− :: KnownNat n
724− => proxy n
725− -> TypeExpression ('Required ('Null ('PGChar n)))
726−character (_ :: proxy n) = UnsafeTypeExpression $
727− "character(" <> fromString (show (natVal' (proxy# :: Proxy# n))) <> ")"
728−varchar
729− :: KnownNat n
730− => proxy n
731− -> TypeExpression ('Required ('Null ('PGVarChar n)))
732−varchar (_ :: proxy n) = UnsafeTypeExpression $
733− "varchar(" <> fromString (show (natVal' (proxy# :: Proxy# n))) <> ")"
734−characterVarying
735− :: KnownNat n
736− => proxy n
737− -> TypeExpression ('Required ('Null ('PGVarChar n)))
738−characterVarying (_ :: proxy n) = UnsafeTypeExpression $
739− "character varying(" <> fromString (show (natVal' (proxy# :: Proxy# n))) <> ")"
740−bytea :: TypeExpression ('Required ('Null ('PGBytea)))
741−bytea = UnsafeTypeExpression "bytea"
742−timestamp :: TypeExpression ('Required ('Null ('PGTimestamp)))
743−timestamp = UnsafeTypeExpression "timestamp"
744−timestampWithTimeZone :: TypeExpression ('Required ('Null ('PGTimestampTZ)))
745−timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
746−date :: TypeExpression ('Required ('Null ('PGDate)))
747−date = UnsafeTypeExpression "date"
748−time :: TypeExpression ('Required ('Null ('PGTime)))
749−time = UnsafeTypeExpression "time"
750−timeWithTimeZone :: TypeExpression ('Required ('Null ('PGTimeTZ)))
751−timeWithTimeZone = UnsafeTypeExpression "time with time zone"
752−interval :: TypeExpression ('Required ('Null ('PGInterval)))
753−interval = UnsafeTypeExpression "interval"
754−uuid :: TypeExpression ('Required ('Null ('PGUuid)))
755−uuid = UnsafeTypeExpression "uuid"
756−json :: TypeExpression ('Required ('Null ('PGJson)))
757−json = UnsafeTypeExpression "json"
758−jsonb :: TypeExpression ('Required ('Null ('PGJsonb)))
759−jsonb = UnsafeTypeExpression "jsonb"
760−
761−notNull
762− :: TypeExpression ('Required ('Null ty))
763− -> TypeExpression ('Required ('NotNull ty))
764−notNull ty = UnsafeTypeExpression $ renderTypeExpression ty <> " NOT NULL"
765−default_
766− :: Expression '[] '[] 'Ungrouped ('Required ty)
767− -> TypeExpression ('Required ty)
768− -> TypeExpression ('Optional ty)
769−default_ x ty = UnsafeTypeExpression $
770− renderTypeExpression ty <> " DEFAULT " <> renderExpression x
771−
772−class PGTyped (ty :: PGType) where
773− pgtype :: TypeExpression ('Required ('Null ty))
774−instance PGTyped 'PGBool where pgtype = bool
775−instance PGTyped 'PGInt2 where pgtype = int2
776−instance PGTyped 'PGInt4 where pgtype = int4
777−instance PGTyped 'PGInt8 where pgtype = int8
778−instance PGTyped 'PGNumeric where pgtype = numeric
779−instance PGTyped 'PGFloat4 where pgtype = float4
780−instance PGTyped 'PGFloat8 where pgtype = float8
781−instance PGTyped 'PGMoney where pgtype = money
782−instance PGTyped 'PGText where pgtype = text
783−instance KnownNat n => PGTyped ('PGChar n) where pgtype = char (Proxy @n)
784−instance KnownNat n => PGTyped ('PGVarChar n) where pgtype = varchar (Proxy @n)
785−instance PGTyped 'PGBytea where pgtype = bytea
786−instance PGTyped 'PGTimestamp where pgtype = timestamp
787−instance PGTyped 'PGTimestampTZ where pgtype = timestampWithTimeZone
788−instance PGTyped 'PGDate where pgtype = date
789−instance PGTyped 'PGTime where pgtype = time
790−instance PGTyped 'PGTimeTZ where pgtype = timeWithTimeZone
791−instance PGTyped 'PGInterval where pgtype = interval
792−instance PGTyped 'PGUuid where pgtype = uuid
793−instance PGTyped 'PGJson where pgtype = json
794−instance PGTyped 'PGJsonb where pgtype = jsonb
795−
796−{-----------------------------------------
797−statements
798−-----------------------------------------}
799−
800−newtype Definition
801− (schema0 :: [(Symbol,[(Symbol,ColumnType)])])
802− (schema1 :: [(Symbol,[(Symbol,ColumnType)])])
803− = UnsafeDefinition { renderDefinition :: ByteString }
804−
805−instance Category Definition where
806− id = UnsafeDefinition ";"
807− dd1 . dd0 = UnsafeDefinition $
808− renderDefinition dd0 <> " " <> renderDefinition dd1
809−
810−newtype Manipulation
811− (schema :: [(Symbol,[(Symbol,ColumnType)])])
812− (params :: [ColumnType])
813− (columns :: [(Symbol,ColumnType)])
814− = UnsafeManipulation { renderManipulation :: ByteString }
815−
816−newtype Query
817− (schema :: [(Symbol,[(Symbol,ColumnType)])])
818− (params :: [ColumnType])
819− (columns :: [(Symbol,ColumnType)])
820− = UnsafeQuery { renderQuery :: ByteString }
821−
822−query
823− :: Query schema params columns
824− -> Manipulation schema params columns
825−query q = UnsafeManipulation $ renderQuery q <> ";"
826−
827−union, unionAll, intersect, intersectAll, except, exceptAll
828− :: Query schema params columns
829− -> Query schema params columns
830− -> Query schema params columns
831−q1 `union` q2 = UnsafeQuery $
832− "(" <> renderQuery q1 <> ") UNION (" <> renderQuery q2 <> ")"
833−q1 `unionAll` q2 = UnsafeQuery $
834− "(" <> renderQuery q1 <> ") UNION ALL " <> renderQuery q2
835−q1 `intersect` q2 = UnsafeQuery $
836− "(" <> renderQuery q1 <> ") INTERSECT " <> renderQuery q2
837−q1 `intersectAll` q2 = UnsafeQuery $
838− "(" <> renderQuery q1 <> ") INTERSECT ALL " <> renderQuery q2
839−q1 `except` q2 = UnsafeQuery $
840− "(" <> renderQuery q1 <> ") EXCEPT " <> renderQuery q2
841−q1 `exceptAll` q2 = UnsafeQuery $
842− "(" <> renderQuery q1 <> ") EXCEPT ALL " <> renderQuery q2
843−
844−{-----------------------------------------
845−SELECT statements
846−-----------------------------------------}
847−
848−select
849− :: SListI columns
850− => NP (Aliased (Expression params tables grouping)) columns
851− -> TableExpression params schema tables grouping
852− -> Query schema params columns
853−select list tabs = UnsafeQuery $
854− "SELECT " <> renderList list <> " " <> renderTableExpression tabs
855− where
856− renderList
857− = ByteString.intercalate ", "
858− . hcollapse
859− . hmap (K . renderAliased renderExpression)
860−
861−selectStar
862− :: (tables ~ '[table ::: columns])
863− => TableExpression params schema tables 'Ungrouped
864− -> Query schema params columns
865−selectStar tabs = UnsafeQuery $ "SELECT * " <> renderTableExpression tabs
866−
867−selectDotStar
868− :: HasTable table tables columns
869− => Alias table
870− -> TableExpression params schema tables 'Ungrouped
871− -> Query schema params columns
872−selectDotStar table tables = UnsafeQuery $
873− "SELECT " <> renderAlias table <> ".* " <> renderTableExpression tables
874−
875−{-----------------------------------------
876−CREATE statements
877−-----------------------------------------}
878−
879−createTable
880− :: (KnownSymbol table, SListI columns)
881− => Alias table
882− -> NP (Aliased TypeExpression) columns
883− -> Definition schema (Create table columns schema)
884−createTable table columns = UnsafeDefinition $ mconcat
885− [ "CREATE TABLE "
886− , renderAlias table
887− , " ("
888− , ByteString.intercalate ", " . hcollapse $
889− hmap (K . renderColumn) columns
890− , ");"
891− ]
892− where
893− renderColumn :: Aliased TypeExpression x -> ByteString
894− renderColumn (ty `As` column) =
895− renderAlias column <> " " <> renderTypeExpression ty
896−
897−{-----------------------------------------
898−DROP statements
899−-----------------------------------------}
900−
901−dropTable
902− :: KnownSymbol table
903− => Alias table
904− -> Definition schema (Drop table schema)
905−dropTable table = UnsafeDefinition $ "DROP TABLE " <> renderAlias table <> ";"
906−
907−{-----------------------------------------
908−ALTER statements
909−-----------------------------------------}
910−
911−alterTable
912− :: HasTable table schema columns0
913− => Alias table
914− -> AlterTable columns0 columns1
915− -> Definition schema (Alter table schema columns1)
916−alterTable table alteration = UnsafeDefinition $
917− "ALTER TABLE "
918− <> renderAlias table
919− <> " "
920− <> renderAlterTable alteration
921− <> ";"
922−
923−alterTableRename
924− :: (KnownSymbol table0, KnownSymbol table1)
925− => Alias table0
926− -> Alias table1
927− -> Definition schema (Rename table0 table1 schema)
928−alterTableRename table0 table1 = UnsafeDefinition $
929− "ALTER TABLE "
930− <> renderAlias table0
931− <> " RENAME TO "
932− <> renderAlias table1
933− <> ";"
934−
935−data AlterTable
936− (columns0 :: [(Symbol, ColumnType)])
937− (columns1 :: [(Symbol, ColumnType)]) =
938− UnsafeAlterTable {renderAlterTable :: ByteString}
939−
940−addColumnDefault
941− :: KnownSymbol column
942− => Alias column
943− -> TypeExpression ('Optional ty)
944− -> AlterTable columns (Create column ('Optional ty) columns)
945−addColumnDefault column ty = UnsafeAlterTable $
946− "ADD COLUMN "
947− <> renderAlias column
948− <> " "
949− <> renderTypeExpression ty
950−
951−addColumnNull
952− :: KnownSymbol column
953− => Alias column
954− -> TypeExpression ('Required ('Null ty))
955− -> AlterTable columns ((column ::: 'Required ('Null ty)) ': columns)
956−addColumnNull column ty = UnsafeAlterTable $
957− "ADD COLUMN "
958− <> renderAlias column
959− <> " "
960− <> renderTypeExpression ty
961−
962−dropColumn
963− :: KnownSymbol column
964− => Alias column
965− -> AlterTable columns (Drop column columns)
966−dropColumn column = UnsafeAlterTable $
967− "DROP COLUMN " <> renderAlias column
968−
969−renameColumn
970− :: (KnownSymbol column0, KnownSymbol column1)
971− => Alias column0
972− -> Alias column1
973− -> AlterTable columns (Rename column0 column1 columns)
974−renameColumn column0 column1 = UnsafeAlterTable $
975− "RENAME COLUMN " <> renderAlias column0
976− <> " TO " <> renderAlias column1
977−
978−alterColumn
979− :: (KnownSymbol column, HasColumn column columns ty0)
980− => Alias column
981− -> AlterColumn ty0 ty1
982− -> AlterTable columns (Alter column columns ty1)
983−alterColumn column alteration = UnsafeAlterTable $
984− "ALTER COLUMN " <> renderAlias column
985− <> " " <> renderAlterColumn alteration
986−
987−data AlterColumn (ty0 :: ColumnType) (ty1 :: ColumnType) =
988− UnsafeAlterColumn {renderAlterColumn :: ByteString}
989−
990−setDefault
991− :: Expression '[] '[] 'Ungrouped ('Required ty)
992− -> AlterColumn ('Required ty) ('Optional ty)
993−setDefault expression = UnsafeAlterColumn $
994− "SET DEFAULT " <> renderExpression expression
995−
996−dropDefault :: AlterColumn ('Optional ty) ('Required ty)
997−dropDefault = UnsafeAlterColumn $ "DROP DEFAULT"
998−
999−setNotNull
1000− :: AlterColumn (optionality ('Null ty)) (optionality ('NotNull ty))
1001−setNotNull = UnsafeAlterColumn $ "SET NOT NULL"
1002−
1003−dropNotNull
1004− :: AlterColumn (optionality ('NotNull ty)) (optionality ('Null ty))
1005−dropNotNull = UnsafeAlterColumn $ "DROP NOT NULL"
1006−
1007−alterType
1008− :: PGCast ty0 ty1
1009− => TypeExpression (optionality (nullity ty1))
1010− -> AlterColumn (optionality (nullity ty0)) (optionality (nullity ty1))
1011−alterType ty = UnsafeAlterColumn $ "TYPE " <> renderTypeExpression ty
1012−
1013−{-----------------------------------------
1014−INSERT statements
1015−-----------------------------------------}
1016−
1017−insertInto
1018− :: (SListI columns, HasTable table schema columns)
1019− => Alias table
1020− -> NP (Aliased (Expression params '[] 'Ungrouped)) columns
1021− -> Manipulation schema params '[]
1022−insertInto table expressions = UnsafeManipulation $ "INSERT INTO "
1023− <> renderAlias table
1024− <> " (" <> ByteString.intercalate ", " aliases
1025− <> ") VALUES ("
1026− <> ByteString.intercalate ", " values
1027− <> ");"
1028− where
1029− aliases = hcollapse $ hmap
1030− (\ (_ `As` name) -> K (renderAlias name))
1031− expressions
1032− values = hcollapse $ hmap
1033− (\ (expression `As` _) -> K (renderExpression expression))
1034− expressions
1035−
1036−insertIntoReturning
1037− :: (SListI columns, SListI results, HasTable table schema columns)
1038− => Alias table
1039− -> NP (Aliased (Expression params '[] 'Ungrouped)) columns
1040− -> NP (Aliased (Expression params '[table ::: columns] 'Ungrouped)) results
1041− -> Manipulation schema params results
1042−insertIntoReturning table inserts results
1043− = UnsafeManipulation . mconcat $
1044− [ "INSERT INTO "
1045− , renderAlias table
1046− , " (" <> ByteString.intercalate ", " aliases
1047− , ") VALUES ("
1048− , ByteString.intercalate ", " values
1049− , ") RETURNING "
1050− , renderList results
1051− , ";"
1052− ]
1053− where
1054− aliases = hcollapse $ hmap
1055− (\ (_ `As` name) -> K (renderAlias name))
1056− inserts
1057− values = hcollapse $ hmap
1058− (\ (expression `As` _) -> K (renderExpression expression))
1059− inserts
1060− renderList
1061− = ByteString.intercalate ", "
1062− . hcollapse
1063− . hmap (K . renderAliased renderExpression)
1064−
1065−{-----------------------------------------
1066−UPDATE statements
1067−-----------------------------------------}
1068−
1069−data UpdateExpression params table ty
1070− = Same
1071− | Set (Expression params table 'Ungrouped ty)
1072−
1073−renderUpdateExpression
1074− :: Aliased (UpdateExpression params '[table ::: columns]) column
1075− -> Maybe ByteString
1076−renderUpdateExpression = \case
1077− Same `As` _ -> Nothing
1078− Set expression `As` column -> Just $ mconcat
1079− [ renderAlias column
1080− , " = "
1081− , renderExpression expression
1082− ]
1083−
1084−update
1085− :: (HasTable table schema columns, SListI columns)
1086− => Alias table
1087− -> NP (Aliased (UpdateExpression params '[table ::: columns])) columns
1088− -> Condition params '[table ::: columns] 'Ungrouped
1089− -> Manipulation schema params '[]
1090−update table columns wh = UnsafeManipulation $ mconcat
1091− [ "UPDATE "
1092− , renderAlias table
1093− , " SET "
1094− , ByteString.intercalate ", " . catMaybes . hcollapse $
1095− hmap (K . renderUpdateExpression) columns
1096− , " WHERE ", renderExpression wh, ";"
1097− ]
1098−
1099−updateReturning
1100− :: (SListI columns, SListI results, HasTable table schema columns)
1101− => Alias table
1102− -> NP (Aliased (UpdateExpression params '[table ::: columns])) columns
1103− -> Condition params '[table ::: columns] 'Ungrouped
1104− -> NP (Aliased (Expression params '[table ::: columns] 'Ungrouped)) results
1105− -> Manipulation schema params results
1106−updateReturning table updates wh results = UnsafeManipulation $ mconcat
1107− [ "UPDATE "
1108− , renderAlias table
1109− , " SET "
1110− , ByteString.intercalate ", " . catMaybes . hcollapse $
1111− hmap (K . renderUpdateExpression) updates
1112− , " WHERE ", renderExpression wh
1113− , " RETURNING ", renderList results
1114− , ";"
1115− ]
1116− where
1117− renderList
1118− = ByteString.intercalate ", "
1119− . hcollapse
1120− . hmap (K . renderAliased renderExpression)
1121−
1122−upsertInto
1123− :: (SListI columns, HasTable table schema columns)
1124− => Alias table
1125− -> NP (Aliased (Expression params '[] 'Ungrouped)) columns
1126− -> NP (Aliased (UpdateExpression params '[table ::: columns])) columns
1127− -> Condition params '[table ::: columns] 'Ungrouped
1128− -> Manipulation schema params '[]
1129−upsertInto table inserts updates wh = UnsafeManipulation . mconcat $
1130− [ "INSERT INTO "
1131− , renderAlias table
1132− , " (" <> ByteString.intercalate ", " aliases
1133− , ") VALUES ("
1134− , ByteString.intercalate ", " values
1135− , ") ON CONFLICT UPDATE "
1136− , renderAlias table
1137− , " SET "
1138− , ByteString.intercalate ", " . catMaybes . hcollapse $
1139− hmap (K . renderUpdateExpression) updates
1140− , " WHERE ", renderExpression wh, ";"
1141− ] where
1142− aliases = hcollapse $ hmap
1143− (\ (_ `As` name) -> K (renderAlias name))
1144− inserts
1145− values = hcollapse $ hmap
1146− (\ (expression `As` _) -> K (renderExpression expression))
1147− inserts
1148−
1149−upsertIntoReturning
1150− :: (SListI columns, SListI results, HasTable table schema columns)
1151− => Alias table
1152− -> NP (Aliased (Expression params '[] 'Ungrouped)) columns
1153− -> NP (Aliased (UpdateExpression params '[table ::: columns])) columns
1154− -> Condition params '[table ::: columns] 'Ungrouped
1155− -> NP (Aliased (Expression params '[table ::: columns] 'Ungrouped)) results
1156− -> Manipulation schema params results
1157−upsertIntoReturning table inserts updates wh results =
1158− UnsafeManipulation . mconcat $
1159− [ "INSERT INTO "
1160− , renderAlias table
1161− , " (" <> ByteString.intercalate ", " aliases
1162− , ") VALUES ("
1163− , ByteString.intercalate ", " values
1164− , ") ON CONFLICT UPDATE "
1165− , renderAlias table
1166− , " SET "
1167− , ByteString.intercalate ", " . catMaybes . hcollapse $
1168− hmap (K . renderUpdateExpression) updates
1169− , " WHERE ", renderExpression wh
1170− , " RETURNING ", renderList results
1171− , ";"
1172− ] where
1173− aliases = hcollapse $ hmap
1174− (\ (_ `As` name) -> K (renderAlias name))
1175− inserts
1176− values = hcollapse $ hmap
1177− (\ (expression `As` _) -> K (renderExpression expression))
1178− inserts
1179− renderList
1180− = ByteString.intercalate ", "
1181− . hcollapse
1182− . hmap (K . renderAliased renderExpression)
1183−
1184−{-----------------------------------------
1185−DELETE statements
1186−-----------------------------------------}
1187−
1188−deleteFrom
1189− :: HasTable table schema columns
1190− => Alias table
1191− -> Condition params '[table ::: columns] 'Ungrouped
1192− -> Manipulation schema params '[]
1193−deleteFrom table wh = UnsafeManipulation $ mconcat
1194− [ "DELETE FROM "
1195− , renderAlias table
1196− , " WHERE ", renderExpression wh, ";"
1197− ]