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