on dev help sign in
Merge pull request #17 from echatav/query3
0f0e616Eitan Chatav
squeel-postgresql/squeel-postgresql.cabal−1
@@ -48,7 +48,6 @@ test-suite squeel-postgresql-test
48 build-depends:
48 build-depends:
49 base
49 base
50 , Boolean
50 , Boolean
51− , bytestring
52 , hspec
51 , hspec
53 , squeel-postgresql
52 , squeel-postgresql
54 , vinyl
53 , vinyl
squeel-postgresql/src/Squeel/PostgreSQL/PQ.hs+1−1
@@ -77,7 +77,7 @@ class MonadPQ pq where
77 :: (MonadBase IO io, ToOids ps)
77 :: (MonadBase IO io, ToOids ps)
78 => ByteString
78 => ByteString
79 -> Query ps db0 db1 xs
79 -> Query ps db0 db1 xs
80− -> pq db0 db1 io (Maybe (Result []), PreparedQuery db0 db1 ps xs)
80+ -> pq db0 db1 io (Maybe (Result []), PreparedQuery ps db0 db1 xs)
81
81
82 pqExecPrepared
82 pqExecPrepared
83 :: (MonadBase IO io, ToValues xs ps)
83 :: (MonadBase IO io, ToValues xs ps)
squeel-postgresql/src/Squeel/PostgreSQL/Query.hs+124−93
@@ -6,8 +6,6 @@
6 , LambdaCase
6 , LambdaCase
7 , MagicHash
7 , MagicHash
8 , OverloadedStrings
8 , OverloadedStrings
9− , PolyKinds
10− , ScopedTypeVariables
11 , TypeFamilies
9 , TypeFamilies
12 , TypeOperators
10 , TypeOperators
13 , UndecidableInstances
11 , UndecidableInstances
@@ -62,8 +60,8 @@ instance {-# OVERLAPPING #-} KnownSymbol column
62instance {-# OVERLAPPABLE #-} (KnownSymbol column, HasColumn column table ty)
60instance {-# OVERLAPPABLE #-} (KnownSymbol column, HasColumn column table ty)
63 => HasColumn column (ty' ': table) ty
61 => HasColumn column (ty' ': table) ty
64
62
65−instance HasColumn column columns ty
63+instance (HasColumn column columns ty, tables ~ '[table ::: columns])
66− => IsLabel column (Expression params '[table ::: columns] ty) where
64+ => IsLabel column (Expression params tables ty) where
67 fromLabel = getColumn
65 fromLabel = getColumn
68
66
69(.&.)
67(.&.)
@@ -129,13 +127,25 @@ instance Boolean (Expression params tables 'PGBool) where
129type instance BooleanOf (Expression params tables ty) =
127type instance BooleanOf (Expression params tables ty) =
130 Expression params tables 'PGBool
128 Expression params tables 'PGBool
131
129
130+caseWhenThenElse
132−instance IfB (Expression params tables ty) where
131+ :: [(Expression params tables 'PGBool, Expression params tables ty)]
132+ -> Expression params tables ty
133+ -> Expression params tables ty
133− ifB if_ then_ else_ = UnsafeExpression $ mconcat
134+caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
135+ [ "CASE"
136+ , mconcat
137+ [ mconcat
134− [ "CASE WHEN ",renderExpression if_
138+ [ " WHEN ", renderExpression when_
135− , " THEN ",renderExpression then_
139+ , " THEN ", renderExpression then_
136− , " ELSE ",renderExpression else_
140+ ]
137− , " END"
141+ | (when_,then_) <- whenThens
138 ]
142 ]
143+ , " ELSE ", renderExpression else_
144+ , " END"
145+ ]
146+
147+instance IfB (Expression params tables ty) where
148+ ifB if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
139
149
140instance EqB (Expression params tables ty) where
150instance EqB (Expression params tables ty) where
141 (==*) = unsafeBinaryOp "="
151 (==*) = unsafeBinaryOp "="
@@ -167,120 +177,144 @@ crossJoin
167 :: TableRef params schema '[table]
177 :: TableRef params schema '[table]
168 -> TableRef params schema tables
178 -> TableRef params schema tables
169 -> TableRef params schema (table ': tables)
179 -> TableRef params schema (table ': tables)
170−crossJoin table tables = UnsafeTableRef $
180+crossJoin tab tabs = UnsafeTableRef $
171− renderTableRef tables <> " CROSS JOIN " <> renderTableRef table
181+ renderTableRef tabs <> " CROSS JOIN " <> renderTableRef tab
172
182
173innerJoin
183innerJoin
174 :: TableRef params schema '[table]
184 :: TableRef params schema '[table]
175 -> Expression params (table ': tables) 'PGBool
185 -> Expression params (table ': tables) 'PGBool
176 -> TableRef params schema tables
186 -> TableRef params schema tables
177 -> TableRef params schema (table ': tables)
187 -> TableRef params schema (table ': tables)
178−innerJoin table on tables = UnsafeTableRef $
188+innerJoin tab on tabs = UnsafeTableRef $
179− renderTableRef tables
189+ renderTableRef tabs
180 <> " INNER JOIN " <>
190 <> " INNER JOIN " <>
181− renderTableRef table
191+ renderTableRef tab
182 <> " ON " <>
192 <> " ON " <>
183 renderExpression on
193 renderExpression on
184
194
185−newtype Projection
195+data Clauses params tables = Clauses
186− (params :: [PGType])
196+ { whereClause :: Maybe (Expression params tables 'PGBool)
187− (tables :: [(Symbol,[(Symbol,PGType)])])
197+ , limitClause :: Maybe (Expression params '[] 'PGInt8)
188− (columns :: [(Symbol,PGType)]) =
198+ , offsetClause :: Maybe (Expression params '[] 'PGInt8)
189− UnsafeProjection { renderProjection :: ByteString }
199+ }
190−
191−star :: Projection params '[table ::: columns] columns
192−star = UnsafeProjection "*"
193−
194−tableStar
195− :: HasTable table tables columns
196− => Alias table -> Projection params tables columns
197−tableStar (Alias table) = UnsafeProjection $
198− fromString (symbolVal' table) <> ".*"
199
200
200−project
201+instance Monoid (Clauses params tables) where
201− :: Rec (Aliased (Expression params tables)) columns
202+ mempty = Clauses Nothing Nothing Nothing
202− -> Projection params tables columns
203+ Clauses wh1 lim1 off1 `mappend` Clauses wh2 lim2 off2 = Clauses
203−project
204+ { whereClause = case (wh1,wh2) of
204− = UnsafeProjection
205+ (Nothing,Nothing) -> Nothing
205− . ByteString.intercalate ", "
206+ (Just w1,Nothing) -> Just w1
206− . recordToList
207+ (Nothing,Just w2) -> Just w2
207− . rmap (Const . renderAliased renderExpression)
208+ (Just w1,Just w2) -> Just (w1 &&* w2)
208−
209+ , limitClause = case (lim1,lim2) of
209−data Tabulation
210+ (Nothing,Nothing) -> Nothing
211+ (Just l1,Nothing) -> Just l1
212+ (Nothing,Just l2) -> Just l2
213+ (Just l1,Just l2) -> Just (l1 `minB` l2)
214+ , offsetClause = case (off1,off2) of
215+ (Nothing,Nothing) -> Nothing
216+ (Just o1,Nothing) -> Just o1
217+ (Nothing,Just o2) -> Just o2
218+ (Just o1,Just o2) -> Just (o1 + o2)
219+ }
220+
221+data TableExpression
210 (params :: [PGType])
222 (params :: [PGType])
211 (schema :: [(Symbol,[(Symbol,PGType)])])
223 (schema :: [(Symbol,[(Symbol,PGType)])])
212 (tables :: [(Symbol,[(Symbol,PGType)])])
224 (tables :: [(Symbol,[(Symbol,PGType)])])
213− = Tabulation
225+ = TableExpression
214− { fromClause :: TableRef params schema tables
226+ { tableRef :: TableRef params schema tables
215− , whereClause :: Maybe (Expression params tables 'PGBool)
227+ , clauses :: Clauses params tables
216− , limitClause :: Maybe (Expression params '[] 'PGInt8)
217− , offsetClause :: Maybe (Expression params '[] 'PGInt8)
218 }
228 }
219
229
230+tables
220−tabulation :: TableRef params schema tables -> Tabulation params schema tables
231+ :: TableRef params schema tables
221−tabulation tab = Tabulation tab Nothing Nothing Nothing
232+ -> TableExpression params schema tables
233+tables tref = TableExpression tref mempty
222
234
223−renderTabulation :: Tabulation params schema tables -> ByteString
235+renderTabulation :: TableExpression params schema tables -> ByteString
224−renderTabulation (Tabulation fr wh lim off)= mconcat
236+renderTabulation (TableExpression tref (Clauses wh lim off))= mconcat
225− [ renderTableRef fr
237+ [ renderTableRef tref
226 , maybe "" ((" WHERE " <>) . renderExpression) wh
238 , maybe "" ((" WHERE " <>) . renderExpression) wh
227 , maybe "" ((" LIMIT " <>) . renderExpression) lim
239 , maybe "" ((" LIMIT " <>) . renderExpression) lim
228 , maybe "" ((" OFFSET " <>) . renderExpression) off
240 , maybe "" ((" OFFSET " <>) . renderExpression) off
229 ]
241 ]
230
242
231−instance HasTable table schema columns
243+instance (HasTable table schema columns, table ~ table')
232− => IsLabel table (TableRef params schema '[table ::: columns]) where
244+ => IsLabel table (TableRef params schema '[table' ::: columns]) where
233 fromLabel = getTable
245 fromLabel = getTable
234
246
235−instance HasTable table schema columns
247+instance (HasTable table schema columns, table ~ table')
236− => IsLabel table (Tabulation params schema '[table ::: columns]) where
248+ => IsLabel table (TableExpression params schema '[table' ::: columns]) where
237− fromLabel p = Tabulation (getTable p) Nothing Nothing Nothing
249+ fromLabel p = TableExpression (getTable p) mempty
238
250
239where_
251where_
240 :: Expression params tables 'PGBool
252 :: Expression params tables 'PGBool
241− -> Tabulation params schema tables
253+ -> TableExpression params schema tables
242− -> Tabulation params schema tables
254+ -> TableExpression params schema tables
243−where_ condition tables = tables
255+where_ wh (TableExpression tabs clauses1) = TableExpression tabs
244− { whereClause = case whereClause tables of
256+ (clauses1 <> Clauses (Just wh) Nothing Nothing)
245− Nothing -> Just condition
246− Just conditions -> Just (conditions &&* condition)
247− }
248
257
249limit
258limit
250 :: Expression params '[] 'PGInt8
259 :: Expression params '[] 'PGInt8
251− -> Tabulation params schema tables
260+ -> TableExpression params schema tables
252− -> Tabulation params schema tables
261+ -> TableExpression params schema tables
253−limit n tables = tables
262+limit lim (TableExpression tabs clauses1) = TableExpression tabs
254− { limitClause = case limitClause tables of
263+ (clauses1 <> Clauses Nothing (Just lim) Nothing)
255− Nothing -> Just n
256− Just n' -> Just (n' `minB` n)
257− }
258
264
259offset
265offset
260 :: Expression params '[] 'PGInt8
266 :: Expression params '[] 'PGInt8
261− -> Tabulation params schema tables
267+ -> TableExpression params schema tables
262− -> Tabulation params schema tables
268+ -> TableExpression params schema tables
263−offset n tables = tables
269+offset off (TableExpression tabs clauses1) = TableExpression tabs
264− { offsetClause = case offsetClause tables of
270+ (clauses1 <> Clauses Nothing Nothing (Just off))
265− Nothing -> Just n
271+
266− Just n' -> Just (n' + n)
272+newtype Selection
267− }
273+ (params :: [PGType])
274+ (schema :: [(Symbol,[(Symbol,PGType)])])
275+ (columns :: [(Symbol,PGType)])
276+ = UnsafeSelection
277+ { renderSelection :: ByteString }
268
278
279+starFrom
280+ :: tables ~ '[table ::: columns]
281+ => TableExpression params schema tables
282+ -> Selection params schema columns
283+starFrom tabs = UnsafeSelection $ "* FROM " <> renderTabulation tabs
284+
285+tableStarFrom
286+ :: HasTable table tables columns
287+ => Alias table
288+ -> TableExpression params schema tables
269−newtype Selection params schema columns = UnsafeSelection
289+ -> Selection params schema columns
270− { renderSelection :: ByteString }
290+Alias tab `tableStarFrom` tabs = UnsafeSelection $
291+ fromString (symbolVal' tab) <> ".* FROM" <> renderTabulation tabs
271
292
272from
293from
273− :: Projection params tables columns
294+ :: Rec (Aliased (Expression params tables)) columns
274− -> Tabulation params schema tables
295+ -> TableExpression params schema tables
275 -> Selection params schema columns
296 -> Selection params schema columns
276−from projection tables = UnsafeSelection $
297+list `from` tabs = UnsafeSelection $
277− renderProjection projection <> " FROM " <> renderTabulation tables
298+ renderList list <> " FROM " <> renderTabulation tabs
299+ where
300+ renderList
301+ = ByteString.intercalate ", "
302+ . recordToList
303+ . rmap (Const . renderAliased renderExpression)
278
304
279−newtype Query params schema0 schema1 columns = UnsafeQuery
305+newtype Query
306+ (params :: [PGType])
307+ (schema0 :: [(Symbol,[(Symbol,PGType)])])
308+ (schema1 :: [(Symbol,[(Symbol,PGType)])])
309+ (columns :: [(Symbol,PGType)])
280− { renderQuery :: ByteString }
310+ = UnsafeQuery { renderQuery :: ByteString }
281
311
282−newtype PreparedQuery params schema0 schema1 columns = UnsafePreparedQuery
312+newtype PreparedQuery
313+ (params :: [PGType])
314+ (schema0 :: [(Symbol,[(Symbol,PGType)])])
315+ (schema1 :: [(Symbol,[(Symbol,PGType)])])
316+ (columns :: [(Symbol,PGType)])
283− { renderPreparedQuery :: ByteString }
317+ = UnsafePreparedQuery { renderPreparedQuery :: ByteString }
284
318
285select
319select
286 :: Selection params schema columns
320 :: Selection params schema columns
@@ -289,18 +323,15 @@ select = UnsafeQuery . ("SELECT " <>) . (<> ";") . renderSelection
289
323
290subselect
324subselect
291 :: Aliased (Selection params schema) table
325 :: Aliased (Selection params schema) table
292− -> Tabulation params schema '[table]
326+ -> TableExpression params schema '[table]
293−subselect selection = Tabulation
327+subselect selection = TableExpression
294− { fromClause = UnsafeTableRef . ("SELECT " <>) $
328+ { tableRef = UnsafeTableRef . ("SELECT " <>) $
295 renderAliased renderSelection selection
329 renderAliased renderSelection selection
296− , whereClause = Nothing
330+ , clauses = mempty
297− , limitClause = Nothing
298− , offsetClause = Nothing
299 }
331 }
300
332
301insertInto
333insertInto
302− :: forall schema columns table params
303− . HasTable table schema columns
334+ :: HasTable table schema columns
304 => Alias table
335 => Alias table
305 -> Rec (Aliased (Expression params '[])) columns
336 -> Rec (Aliased (Expression params '[])) columns
306 -> Query params schema schema '[]
337 -> Query params schema schema '[]
squeel-postgresql/test/Squeel/PostgreSQL/QuerySpec.hs+80−80
@@ -3,14 +3,12 @@
3 , OverloadedLabels
3 , OverloadedLabels
4 , OverloadedStrings
4 , OverloadedStrings
5 , PolyKinds
5 , PolyKinds
6− , TypeApplications
7 , TypeOperators
6 , TypeOperators
8#-}
7#-}
9
8
10module Squeel.PostgreSQL.QuerySpec where
9module Squeel.PostgreSQL.QuerySpec where
11
10
12import Data.Boolean
11import Data.Boolean
13−import Data.ByteString
14import Data.Function
12import Data.Function
15import Data.Vinyl
13import Data.Vinyl
16import Test.Hspec
14import Test.Hspec
@@ -20,53 +18,82 @@ import Squeel.PostgreSQL.Schema
20
18
21spec :: Spec
19spec :: Spec
22spec = do
20spec = do
21+ let
22+ query `shouldRenderAs` str = renderQuery query `shouldBe` str
23 it "correctly renders a simple SELECT query" $ do
23 it "correctly renders a simple SELECT query" $ do
24+ let
25+ statement :: Query '[] Tables Tables SumAndCol1
26+ statement = select $
27+ ((#col1 + #col2) `As` #sum :& #col1 :& RNil)
24− select (sumAndCol1 `from` (table1 & where_ true))
28+ `from` (#table1 & where_ true)
25− `shouldRenderAs`
29+ statement `shouldRenderAs`
26− "SELECT (col1 + col2) AS sum, col1 AS col1 FROM table1 WHERE TRUE;"
30+ "SELECT (col1 + col2) AS sum, col1 AS col1 FROM table1 WHERE TRUE;"
27 it "combines WHEREs using AND" $ do
31 it "combines WHEREs using AND" $ do
32+ let
33+ statement :: Query '[] Tables Tables SumAndCol1
34+ statement = select $
35+ ((#col1 + #col2) `As` #sum :& #col1 :& RNil)
28− select (sumAndCol1 `from` (table1 & where_ true & where_ false))
36+ `from` (#table1 & where_ true & where_ false)
29− `shouldRenderAs`
37+ statement `shouldRenderAs`
30− "SELECT (col1 + col2) AS sum, col1 AS col1 FROM table1 WHERE (TRUE AND FALSE);"
38+ "SELECT (col1 + col2) AS sum, col1 AS col1 FROM table1 WHERE (TRUE AND FALSE);"
31 it "performs sub SELECTs" $ do
39 it "performs sub SELECTs" $ do
32− select (star `from` subselect ((sumAndCol1 `from` table1) `As` (#sub :: Alias "sub")))
40+ let
41+ selection = ((#col1 + #col2) `As` #sum :& #col1 :& RNil) `from` #table1
42+ statement :: Query '[] Tables Tables SumAndCol1
43+ statement = select $ starFrom (subselect (selection `As` #sub))
33− `shouldRenderAs`
44+ statement `shouldRenderAs`
34− "SELECT * FROM SELECT (col1 + col2) AS sum, col1 AS col1 FROM table1 AS sub;"
45+ "SELECT * FROM SELECT (col1 + col2) AS sum, col1 AS col1 FROM table1 AS sub;"
35 it "does LIMIT clauses" $ do
46 it "does LIMIT clauses" $ do
47+ let
48+ statement :: Query '[] Tables Tables Columns
36− select (star `from` (table1 & limit 1))
49+ statement = select $ starFrom (#table1 & limit 1)
37− `shouldRenderAs`
38− "SELECT * FROM table1 LIMIT 1;"
50+ statement `shouldRenderAs` "SELECT * FROM table1 LIMIT 1;"
39 it "should use the minimum of given LIMITs" $ do
51 it "should use the minimum of given LIMITs" $ do
52+ let
53+ statement :: Query '[] Tables Tables Columns
40− select (star `from` (table1 & limit 1 & limit 2))
54+ statement = select $ starFrom (#table1 & limit 1 & limit 2)
41− `shouldRenderAs`
55+ statement `shouldRenderAs`
42− "SELECT * FROM table1 LIMIT CASE WHEN (1 <= 2) THEN 1 ELSE 2 END;"
56+ "SELECT * FROM table1 LIMIT CASE WHEN (1 <= 2) THEN 1 ELSE 2 END;"
43 it "should render parameters using $ signs" $ do
57 it "should render parameters using $ signs" $ do
58+ let
59+ statement :: Query '[ 'PGInt8] Tables Tables Columns
44− select (star `from` (parameterizedTable1 & limit param1))
60+ statement = select $ starFrom (#table1 & limit param1)
45− `shouldRenderAs`
46− "SELECT * FROM table1 LIMIT $1;"
61+ statement `shouldRenderAs` "SELECT * FROM table1 LIMIT $1;"
47 it "does OFFSET clauses" $ do
62 it "does OFFSET clauses" $ do
63+ let
64+ statement :: Query '[] Tables Tables Columns
48− select (star `from` (table1 & offset 1))
65+ statement = select $ starFrom (#table1 & offset 1)
49− `shouldRenderAs`
50− "SELECT * FROM table1 OFFSET 1;"
66+ statement `shouldRenderAs` "SELECT * FROM table1 OFFSET 1;"
51 it "should use the sum of given OFFSETs" $ do
67 it "should use the sum of given OFFSETs" $ do
68+ let
69+ statement :: Query '[] Tables Tables Columns
52− select (star `from` (table1 & offset 1 & offset 2))
70+ statement = select $ starFrom (#table1 & offset 1 & offset 2)
53− `shouldRenderAs`
54− "SELECT * FROM table1 OFFSET (1 + 2);"
71+ statement `shouldRenderAs` "SELECT * FROM table1 OFFSET (1 + 2);"
55 it "correctly render simple INSERTs" $ do
72 it "correctly render simple INSERTs" $ do
56− insertInto @Tables @Columns
73+ let
57− (#table1 :: Alias "table1")
74+ statement :: Query '[] Tables Tables '[]
58− (2 `As` #col1 :& 4 `As` #col2 :& RNil)
75+ statement = insertInto #table1 $ 2 `As` #col1 :& 4 `As` #col2 :& RNil
59− `shouldRenderAs`
76+ statement `shouldRenderAs`
60− "INSERT INTO table1 (col1, col2) VALUES (2, 4);"
77+ "INSERT INTO table1 (col1, col2) VALUES (2, 4);"
61 it "should be safe against SQL injection in literal text" $ do
78 it "should be safe against SQL injection in literal text" $ do
62− insertInto @StudentsTable @StudentsColumns
79+ let
63− (#students :: Alias "students")
80+ statement :: Query '[] StudentsTable StudentsTable '[]
81+ statement = insertInto #students $
64− ("Robert'); DROP TABLE students;" `As` #name :& RNil)
82+ "Robert'); DROP TABLE students;" `As` #name :& RNil
65− `shouldRenderAs`
83+ statement `shouldRenderAs`
66− "INSERT INTO students (name) VALUES (E'Robert''); DROP TABLE students;');"
84+ "INSERT INTO students (name) VALUES (E'Robert''); DROP TABLE students;');"
67 describe "JOINs" $ do
85 describe "JOINs" $ do
86+ let
87+ vals =
88+ #orders .&. #orderVal `As` #orderVal
89+ :& #customers .&. #customerVal `As` #customerVal
90+ :& #shippers .&. #shipperVal `As` #shipperVal :& RNil
68 it "should render CROSS JOINs" $ do
91 it "should render CROSS JOINs" $ do
92+ let
93+ statement :: Query '[] JoinTables JoinTables ValueColumns
69− select (vals `from` crossJoins) `shouldRenderAs`
94+ statement = select $ vals `from`
95+ (tables (#orders & crossJoin #customers & crossJoin #shippers))
96+ statement `shouldRenderAs`
70 "SELECT\
97 "SELECT\
71 \ orders.orderVal AS orderVal,\
98 \ orders.orderVal AS orderVal,\
72 \ customers.customerVal AS customerVal,\
99 \ customers.customerVal AS customerVal,\
@@ -75,7 +102,17 @@ spec = do
75 \ CROSS JOIN customers\
102 \ CROSS JOIN customers\
76 \ CROSS JOIN shippers;"
103 \ CROSS JOIN shippers;"
77 it "should render INNER JOINs" $ do
104 it "should render INNER JOINs" $ do
105+ let
106+ innerJoins :: TableExpression '[] JoinTables JoinTables
107+ innerJoins = tables $
108+ #orders
109+ & innerJoin #customers
110+ (#orders .&. #customerID ==* #customers .&. #customerID)
111+ & innerJoin #shippers
112+ (#orders .&. #shipperID ==* #shippers .&. #shipperID)
113+ selection :: Query '[] JoinTables JoinTables ValueColumns
78− select (vals `from` innerJoins) `shouldRenderAs`
114+ selection = select $ vals `from` innerJoins
115+ selection `shouldRenderAs`
79 "SELECT\
116 "SELECT\
80 \ orders.orderVal AS orderVal,\
117 \ orders.orderVal AS orderVal,\
81 \ customers.customerVal AS customerVal,\
118 \ customers.customerVal AS customerVal,\
@@ -88,31 +125,9 @@ spec = do
88
125
89type Columns = '[ "col1" ::: 'PGInt4, "col2" ::: 'PGInt4]
126type Columns = '[ "col1" ::: 'PGInt4, "col2" ::: 'PGInt4]
90type Tables = '[ "table1" ::: Columns ]
127type Tables = '[ "table1" ::: Columns ]
91−
92−sumAndCol1 :: Projection '[] Tables
93− '["sum" ::: 'PGInt4, "col1" ::: 'PGInt4]
128+type SumAndCol1 = '[ "sum" ::: 'PGInt4, "col1" ::: 'PGInt4]
94−sumAndCol1 = project $
95− (#col1 + #col2) `As` #sum
96− :& #col1 :& RNil
97−
98−literalText :: Projection '[] Tables '["literal" ::: 'PGText]
99−literalText = project $ "\';DROP TABLE table1;" `As` #literal :& RNil
100−
101−table1 :: Tabulation '[] Tables Tables
102−table1 = #table1
103−
104−parameterizedTable1 :: Tabulation '[ 'PGInt8] Tables Tables
105−parameterizedTable1 = #table1
106−
107−shouldRenderAs
108− :: Query params schema1 schema2 columns
109− -> ByteString
110− -> Expectation
111−shouldRenderAs query str = renderQuery query `shouldBe` str
112−
113type StudentsColumns = '["name" ::: 'PGText]
129type StudentsColumns = '["name" ::: 'PGText]
114type StudentsTable = '["students" ::: StudentsColumns]
130type StudentsTable = '["students" ::: StudentsColumns]
115−
116type OrderColumns =
131type OrderColumns =
117 [ "orderID" ::: 'PGInt4
132 [ "orderID" ::: 'PGInt4
118 , "orderVal" ::: 'PGText
133 , "orderVal" ::: 'PGText
@@ -124,27 +139,12 @@ type CustomerColumns =
124type ShipperColumns =
139type ShipperColumns =
125 [ "shipperID" ::: 'PGInt4, "shipperVal" ::: 'PGBool ]
140 [ "shipperID" ::: 'PGInt4, "shipperVal" ::: 'PGBool ]
126type JoinTables =
141type JoinTables =
127− [ "shippers" ::: ShipperColumns
142+ [ "shippers" ::: ShipperColumns
128 , "customers" ::: CustomerColumns
143 , "customers" ::: CustomerColumns
129− , "orders" ::: OrderColumns
144+ , "orders" ::: OrderColumns
130 ]
145 ]
131type ValueColumns =
146type ValueColumns =
132− [ "orderVal" ::: 'PGText
147+ [ "orderVal" ::: 'PGText
133 , "customerVal" ::: 'PGFloat4
148 , "customerVal" ::: 'PGFloat4
134− , "shipperVal" ::: 'PGBool
149+ , "shipperVal" ::: 'PGBool
135 ]
150 ]
136−vals :: Projection '[] JoinTables ValueColumns
137−vals = project $
138− #orders .&. #orderVal `As` #orderVal
139− :& #customers .&. #customerVal `As` #customerVal
140− :& #shippers .&. #shipperVal `As` #shipperVal :& RNil
141−crossJoins :: Tabulation '[] JoinTables JoinTables
142−crossJoins = tabulation $
143− #orders & crossJoin #customers & crossJoin #shippers
144−innerJoins :: Tabulation '[] JoinTables JoinTables
145−innerJoins = tabulation $
146− #orders
147− & innerJoin #customers
148− (#orders .&. #customerID ==* #customers .&. #customerID)
149− & innerJoin #shippers
150− (#orders .&. #shipperID ==* #shippers .&. #shipperID)