@@ -554,9 +554,9 @@ select_ = select . List
554554-- be subject to the elimination of duplicate rows using `selectDistinct`.
555555selectDistinct
556556 :: (SListI columns, columns ~ (col ': cols))
557− => Selection outer commons 'Ungrouped schemas params from columns
557+ => Selection outer commons grp schemas params from columns
558558 -- ^ selection
559− -> TableExpression outer commons 'Ungrouped schemas params from
559+ -> TableExpression outer commons grp schemas params from
560560 -- ^ intermediate virtual table
561561 -> Query outer commons schemas params columns
562562selectDistinct selection tabexpr = UnsafeQuery $
@@ -568,9 +568,9 @@ selectDistinct selection tabexpr = UnsafeQuery $
568568-- of a general `Selection`.
569569selectDistinct_
570570 :: (SListI columns, columns ~ (col ': cols))
571− => NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns
571+ => NP (Aliased (Expression outer commons grp schemas params from)) columns
572572 -- ^ select list
573− -> TableExpression outer commons 'Ungrouped schemas params from
573+ -> TableExpression outer commons grp schemas params from
574574 -- ^ intermediate virtual table
575575 -> Query outer commons schemas params columns
576576selectDistinct_ = selectDistinct . List
@@ -580,14 +580,21 @@ selectDistinct_ = selectDistinct . List
580580the given expressions evaluate to equal. The DISTINCT ON expressions are
581581interpreted using the same rules as for ORDER BY. ORDER BY is used to
582582ensure that the desired row appears first.
583+
584+The DISTINCT ON expression(s) must match the leftmost ORDER BY expression(s).
585+The ORDER BY clause will normally contain additional expression(s) that
586+determine the desired precedence of rows within each DISTINCT ON group.
587+
588+In order to guarantee they match and reduce redundancy, this function
589+will prepend the The DISTINCT ON expressions to the ORDER BY clause.
583590-}
584591selectDistinctOn
585592 :: (SListI columns, columns ~ (col ': cols))
586− => [SortExpression outer commons 'Ungrouped schemas params from]
587− -- ^ distinct on and return the first row in ordering
588− -> Selection outer commons 'Ungrouped schemas params from columns
593+ => [SortExpression outer commons grp schemas params from]
594+ -- ^ DISTINCT ON expression(s) and prepended to ORDER BY clause
595+ -> Selection outer commons grp schemas params from columns
589596 -- ^ selection
590− -> TableExpression outer commons 'Ungrouped schemas params from
597+ -> TableExpression outer commons grp schemas params from
591598 -- ^ intermediate virtual table
592599 -> Query outer commons schemas params columns
593600selectDistinctOn distincts selection tab = UnsafeQuery $
@@ -608,11 +615,11 @@ selectDistinctOn distincts selection tab = UnsafeQuery $
608615-- of a general `Selection`.
609616selectDistinctOn_
610617 :: (SListI columns, columns ~ (col ': cols))
611− => [SortExpression outer commons 'Ungrouped schemas params from]
618+ => [SortExpression outer commons grp schemas params from]
612619 -- ^ distinct on and return the first row in ordering
613− -> NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns
620+ -> NP (Aliased (Expression outer commons grp schemas params from)) columns
614621 -- ^ selection
615− -> TableExpression outer commons 'Ungrouped schemas params from
622+ -> TableExpression outer commons grp schemas params from
616623 -- ^ intermediate virtual table
617624 -> Query outer commons schemas params columns
618625selectDistinctOn_ distincts = selectDistinctOn distincts . List
@@ -750,7 +757,7 @@ instance RenderSQL (TableExpression outer commons grp schemas params from) where
750757from
751758 :: FromClause outer commons schemas params from -- ^ table reference
752759 -> TableExpression outer commons 'Ungrouped schemas params from
753−from tab = TableExpression tab [] NoGroups NoHaving [] [] []
760+from tab = TableExpression tab [] noGroups NoHaving [] [] []
754761
755762-- | A `where_` is an endomorphism of `TableExpression`s which adds a
756763-- search condition to the `whereClause`.
@@ -771,7 +778,7 @@ groupBy
771778groupBy bys rels = TableExpression
772779 { fromClause = fromClause rels
773780 , whereClause = whereClause rels
774− , groupByClause = Group bys
781+ , groupByClause = group bys
775782 , havingClause = Having []
776783 , orderByClause = []
777784 , limitClause = limitClause rels
@@ -985,19 +992,20 @@ instance (Has rel rels cols, Has col cols ty, bys ~ '[ '(rel, col)])
985992-- done on @NoGroups@ while all output `Expression`s must be aggregated
986993-- in @Group Nil@. In general, all output `Expression`s in the
987994-- complement of @bys@ must be aggregated in @Group bys@.
988−data GroupByClause grp from where
989− NoGroups :: GroupByClause 'Ungrouped from
990− Group
991− :: SListI bys
992− => NP (By from) bys
993− -> GroupByClause ('Grouped bys) from
994−
995−-- | Renders a `GroupByClause`.
995+newtype GroupByClause grp from = UnsafeGroupByClause
996+ { renderGroupByClause :: ByteString }
997+ deriving (GHC.Generic,Show,Eq,Ord,NFData)
996998instance RenderSQL (GroupByClause grp from) where
997− renderSQL = \case
998− NoGroups -> ""
999− Group Nil -> ""
1000− Group bys -> " GROUP BY" <+> renderCommaSeparated renderSQL bys
999+ renderSQL = renderGroupByClause
1000+noGroups :: GroupByClause 'Ungrouped from
1001+noGroups = UnsafeGroupByClause ""
1002+group
1003+ :: SListI bys
1004+ => NP (By from) bys
1005+ -> GroupByClause ('Grouped bys) from
1006+group bys = UnsafeGroupByClause $ case bys of
1007+ Nil -> ""
1008+ bys' -> " GROUP BY" <+> renderCommaSeparated renderSQL bys'
10011009
10021010-- | A `HavingClause` is used to eliminate groups that are not of interest.
10031011-- An `Ungrouped` `TableExpression` may only use `NoHaving` while a `Grouped`