@@ -6,8 +6,6 @@
66 , LambdaCase
77 , MagicHash
88 , OverloadedStrings
9− , PolyKinds
10− , ScopedTypeVariables
119 , TypeFamilies
1210 , TypeOperators
1311 , UndecidableInstances
@@ -62,8 +60,8 @@ instance {-# OVERLAPPING #-} KnownSymbol column
6260instance {-# OVERLAPPABLE #-} (KnownSymbol column, HasColumn column table ty)
6361 => HasColumn column (ty' ': table) ty
6462
65−instance HasColumn column columns ty
66− => IsLabel column (Expression params '[table ::: columns] ty) where
63+instance (HasColumn column columns ty, tables ~ '[table ::: columns])
64+ => IsLabel column (Expression params tables ty) where
6765 fromLabel = getColumn
6866
6967(.&.)
@@ -167,18 +165,18 @@ crossJoin
167165 :: TableRef params schema '[table]
168166 -> TableRef params schema tables
169167 -> TableRef params schema (table ': tables)
170−crossJoin table tables = UnsafeTableRef $
171− renderTableRef tables <> " CROSS JOIN " <> renderTableRef table
168+crossJoin tab tabs = UnsafeTableRef $
169+ renderTableRef tabs <> " CROSS JOIN " <> renderTableRef tab
172170
173171innerJoin
174172 :: TableRef params schema '[table]
175173 -> Expression params (table ': tables) 'PGBool
176174 -> TableRef params schema tables
177175 -> TableRef params schema (table ': tables)
178−innerJoin table on tables = UnsafeTableRef $
179− renderTableRef tables
176+innerJoin tab on tabs = UnsafeTableRef $
177+ renderTableRef tabs
180178 <> " INNER JOIN " <>
181− renderTableRef table
179+ renderTableRef tab
182180 <> " ON " <>
183181 renderExpression on
184182
@@ -206,81 +204,110 @@ project
206204 . recordToList
207205 . rmap (Const . renderAliased renderExpression)
208206
209−data Tabulation
207+data Clauses params tables = Clauses
208+ { whereClause :: Maybe (Expression params tables 'PGBool)
209+ , limitClause :: Maybe (Expression params '[] 'PGInt8)
210+ , offsetClause :: Maybe (Expression params '[] 'PGInt8)
211+ }
212+
213+instance Monoid (Clauses params tables) where
214+ mempty = Clauses Nothing Nothing Nothing
215+ Clauses wh1 lim1 off1 `mappend` Clauses wh2 lim2 off2 = Clauses
216+ { whereClause = case (wh1,wh2) of
217+ (Nothing,Nothing) -> Nothing
218+ (Just w1,Nothing) -> Just w1
219+ (Nothing,Just w2) -> Just w2
220+ (Just w1,Just w2) -> Just (w1 &&* w2)
221+ , limitClause = case (lim1,lim2) of
222+ (Nothing,Nothing) -> Nothing
223+ (Just l1,Nothing) -> Just l1
224+ (Nothing,Just l2) -> Just l2
225+ (Just l1,Just l2) -> Just (l1 `minB` l2)
226+ , offsetClause = case (off1,off2) of
227+ (Nothing,Nothing) -> Nothing
228+ (Just o1,Nothing) -> Just o1
229+ (Nothing,Just o2) -> Just o2
230+ (Just o1,Just o2) -> Just (o1 + o2)
231+ }
232+
233+data TableExpression
210234 (params :: [PGType])
211235 (schema :: [(Symbol,[(Symbol,PGType)])])
212236 (tables :: [(Symbol,[(Symbol,PGType)])])
213− = Tabulation
214− { fromClause :: TableRef params schema tables
215− , whereClause :: Maybe (Expression params tables 'PGBool)
216− , limitClause :: Maybe (Expression params '[] 'PGInt8)
217− , offsetClause :: Maybe (Expression params '[] 'PGInt8)
237+ = TableExpression
238+ { tableRef :: TableRef params schema tables
239+ , clauses :: Clauses params tables
218240 }
219241
220−tabulation :: TableRef params schema tables -> Tabulation params schema tables
221−tabulation tab = Tabulation tab Nothing Nothing Nothing
242+tables
243+ :: TableRef params schema tables
244+ -> TableExpression params schema tables
245+tables tref = TableExpression tref mempty
222246
223−renderTabulation :: Tabulation params schema tables -> ByteString
224−renderTabulation (Tabulation fr wh lim off)= mconcat
225− [ renderTableRef fr
247+renderTabulation :: TableExpression params schema tables -> ByteString
248+renderTabulation (TableExpression tref (Clauses wh lim off))= mconcat
249+ [ renderTableRef tref
226250 , maybe "" ((" WHERE " <>) . renderExpression) wh
227251 , maybe "" ((" LIMIT " <>) . renderExpression) lim
228252 , maybe "" ((" OFFSET " <>) . renderExpression) off
229253 ]
230254
231−instance HasTable table schema columns
232− => IsLabel table (TableRef params schema '[table ::: columns]) where
255+instance (HasTable table schema columns, table ~ table')
256+ => IsLabel table (TableRef params schema '[table' ::: columns]) where
233257 fromLabel = getTable
234258
235−instance HasTable table schema columns
236− => IsLabel table (Tabulation params schema '[table ::: columns]) where
237− fromLabel p = Tabulation (getTable p) Nothing Nothing Nothing
259+instance (HasTable table schema columns, table ~ table')
260+ => IsLabel table (TableExpression params schema '[table' ::: columns]) where
261+ fromLabel p = TableExpression (getTable p) mempty
238262
239263where_
240264 :: Expression params tables 'PGBool
241− -> Tabulation params schema tables
242− -> Tabulation params schema tables
243−where_ condition tables = tables
244− { whereClause = case whereClause tables of
245− Nothing -> Just condition
246− Just conditions -> Just (conditions &&* condition)
247− }
265+ -> TableExpression params schema tables
266+ -> TableExpression params schema tables
267+where_ wh (TableExpression tabs clauses1) = TableExpression tabs
268+ (clauses1 <> Clauses (Just wh) Nothing Nothing)
248269
249270limit
250271 :: Expression params '[] 'PGInt8
251− -> Tabulation params schema tables
252− -> Tabulation params schema tables
253−limit n tables = tables
254− { limitClause = case limitClause tables of
255− Nothing -> Just n
256− Just n' -> Just (n' `minB` n)
257− }
272+ -> TableExpression params schema tables
273+ -> TableExpression params schema tables
274+limit lim (TableExpression tabs clauses1) = TableExpression tabs
275+ (clauses1 <> Clauses Nothing (Just lim) Nothing)
258276
259277offset
260278 :: Expression params '[] 'PGInt8
261− -> Tabulation params schema tables
262− -> Tabulation params schema tables
263−offset n tables = tables
264− { offsetClause = case offsetClause tables of
265− Nothing -> Just n
266− Just n' -> Just (n' + n)
267− }
279+ -> TableExpression params schema tables
280+ -> TableExpression params schema tables
281+offset off (TableExpression tabs clauses1) = TableExpression tabs
282+ (clauses1 <> Clauses Nothing Nothing (Just off))
268283
269−newtype Selection params schema columns = UnsafeSelection
270− { renderSelection :: ByteString }
284+newtype Selection
285+ (params :: [PGType])
286+ (schema :: [(Symbol,[(Symbol,PGType)])])
287+ (columns :: [(Symbol,PGType)])
288+ = UnsafeSelection
289+ { renderSelection :: ByteString }
271290
272291from
273− :: Projection params tables columns
274− -> Tabulation params schema tables
292+ :: TableExpression params schema tables
293+ -> Projection params tables columns
275294 -> Selection params schema columns
276−from projection tables = UnsafeSelection $
277− renderProjection projection <> " FROM " <> renderTabulation tables
295+from tabs projection = UnsafeSelection $
296+ renderProjection projection <> " FROM " <> renderTabulation tabs
278297
279−newtype Query params schema0 schema1 columns = UnsafeQuery
280− { renderQuery :: ByteString }
298+newtype Query
299+ (params :: [PGType])
300+ (schema0 :: [(Symbol,[(Symbol,PGType)])])
301+ (schema1 :: [(Symbol,[(Symbol,PGType)])])
302+ (columns :: [(Symbol,PGType)])
303+ = UnsafeQuery { renderQuery :: ByteString }
281304
282−newtype PreparedQuery params schema0 schema1 columns = UnsafePreparedQuery
283− { renderPreparedQuery :: ByteString }
305+newtype PreparedQuery
306+ (params :: [PGType])
307+ (schema0 :: [(Symbol,[(Symbol,PGType)])])
308+ (schema1 :: [(Symbol,[(Symbol,PGType)])])
309+ (columns :: [(Symbol,PGType)])
310+ = UnsafePreparedQuery { renderPreparedQuery :: ByteString }
284311
285312select
286313 :: Selection params schema columns
@@ -289,18 +316,15 @@ select = UnsafeQuery . ("SELECT " <>) . (<> ";") . renderSelection
289316
290317subselect
291318 :: Aliased (Selection params schema) table
292− -> Tabulation params schema '[table]
293−subselect selection = Tabulation
294− { fromClause = UnsafeTableRef . ("SELECT " <>) $
319+ -> TableExpression params schema '[table]
320+subselect selection = TableExpression
321+ { tableRef = UnsafeTableRef . ("SELECT " <>) $
295322 renderAliased renderSelection selection
296− , whereClause = Nothing
297− , limitClause = Nothing
298− , offsetClause = Nothing
323+ , clauses = mempty
299324 }
300325
301326insertInto
302− :: forall schema columns table params
303− . HasTable table schema columns
327+ :: HasTable table schema columns
304328 => Alias table
305329 -> Rec (Aliased (Expression params '[])) columns
306330 -> Query params schema schema '[]