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