@@ -376,18 +376,56 @@ renderSortExpression = \case
376376 Asc expression -> renderExpression expression <> " ASC"
377377 Desc expression -> renderExpression expression <> " DESC"
378378
379−unsafeAggregate
380− :: ByteString
381− -> Expression params tables 'Ungrouped xty
382− -> Expression params tables ('Grouped distincts) yty
383−unsafeAggregate fun x = UnsafeExpression $ mconcat
384− [fun, "(", renderExpression x, ")"]
379+{-----------------------------------------
380+aggregation
381+-----------------------------------------}
385382
386−sum_
387− :: PGNum ty
388− => Expression params tables 'Ungrouped ('Required (nullity ty))
389− -> Expression params tables ('Grouped distincts) ('Required (nullity ty))
390−sum_ = unsafeAggregate "sum"
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+by
392+ :: ( KnownSymbol table
393+ , tables ~ '[table ::: columns]
394+ , HasColumn column columns ty
395+ )
396+ => Alias column
397+ -> By tables '(table, column)
398+by column = By (Alias (proxy# :: Proxy# (table :: Symbol)), column)
399+
400+renderBy :: By tables tabcolty -> ByteString
401+renderBy (By (table, column)) = renderAlias table <> "." <> renderAlias column
402+
403+data GroupByClause tables grouping where
404+ NoGroups :: GroupByClause tables 'Ungrouped
405+ Distinct
406+ :: SListI distincts
407+ => NP (By tables) distincts
408+ -> GroupByClause tables ('Grouped distincts)
409+
410+renderGroupByClause :: GroupByClause tables grouping -> ByteString
411+renderGroupByClause = \case
412+ NoGroups -> ""
413+ Distinct Nil -> ""
414+ Distinct distincts -> " GROUP BY " <> ByteString.intercalate ", "
415+ (hcollapse (hmap (K . renderBy) distincts))
416+
417+data HavingClause params tables grouping where
418+ NoHaving :: HavingClause params tables 'Ungrouped
419+ Having
420+ :: [Condition params tables ('Grouped distincts)]
421+ -> HavingClause params tables ('Grouped distincts)
422+
423+renderHavingClause :: HavingClause params tables grouping -> ByteString
424+renderHavingClause = \case
425+ NoHaving -> ""
426+ Having [] -> ""
427+ Having conditions -> " HAVING " <> ByteString.intercalate ", "
428+ (renderExpression <$> conditions)
391429
392430class (KnownSymbol table, KnownSymbol column)
393431 => GroupedBy table column distincts where
@@ -422,6 +460,19 @@ instance
422460 (Expression params tables ('Grouped distincts) ty) where
423461 (&.) = getGroup
424462
463+unsafeAggregate
464+ :: ByteString
465+ -> Expression params tables 'Ungrouped xty
466+ -> Expression params tables ('Grouped distincts) yty
467+unsafeAggregate fun x = UnsafeExpression $ mconcat
468+ [fun, "(", renderExpression x, ")"]
469+
470+sum_
471+ :: PGNum ty
472+ => Expression params tables 'Ungrouped ('Required (nullity ty))
473+ -> Expression params tables ('Grouped distincts) ('Required (nullity ty))
474+sum_ = unsafeAggregate "sum"
475+
425476{-----------------------------------------
426477tables
427478-----------------------------------------}
@@ -517,53 +568,6 @@ renderTableReference = \case
517568 , renderExpression on
518569 ]
519570
520−data By
521− (tables :: [(Symbol,[(Symbol,ColumnType)])])
522− (tabcol :: (Symbol,Symbol)) where
523− By
524− :: (HasTable table tables columns, HasColumn column columns ty)
525− => (Alias table, Alias column)
526− -> By tables '(table, column)
527−
528−by
529− :: ( KnownSymbol table
530− , tables ~ '[table ::: columns]
531− , HasColumn column columns ty
532− )
533− => Alias column
534− -> By tables '(table, column)
535−by column = By (Alias (proxy# :: Proxy# (table :: Symbol)), column)
536−
537−renderBy :: By tables tabcolty -> ByteString
538−renderBy (By (table, column)) = renderAlias table <> "." <> renderAlias column
539−
540−data GroupByClause tables grouping where
541− NoGroups :: GroupByClause tables 'Ungrouped
542− Distinct
543− :: SListI distincts
544− => NP (By tables) distincts
545− -> GroupByClause tables ('Grouped distincts)
546−
547−renderGroupByClause :: GroupByClause tables grouping -> ByteString
548−renderGroupByClause = \case
549− NoGroups -> ""
550− Distinct Nil -> ""
551− Distinct distincts -> " GROUP BY " <> ByteString.intercalate ", "
552− (hcollapse (hmap (K . renderBy) distincts))
553−
554−data HavingClause params tables grouping where
555− NoHaving :: HavingClause params tables 'Ungrouped
556− Having
557− :: [Condition params tables ('Grouped distincts)]
558− -> HavingClause params tables ('Grouped distincts)
559−
560−renderHavingClause :: HavingClause params tables grouping -> ByteString
561−renderHavingClause = \case
562− NoHaving -> ""
563− Having [] -> ""
564− Having conditions -> " HAVING " <> ByteString.intercalate ", "
565− (renderExpression <$> conditions)
566−
567571data TableExpression
568572 (params :: [ColumnType])
569573 (schema :: [(Symbol,[(Symbol,ColumnType)])])