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