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