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