The semantics of HaskellDB's aggregation operators is very unclear. Let me propose the following example to demonstrate my confusion. It concerns a table whose rows represent people. A person has a family and an age.
import Database.HaskellDB.PrimQuery
import Database.HaskellDB.Query
import Database.HaskellDB.HDBRec
import Database.HaskellDB.DBLayout
data Person = Person
instance FieldTag Person where
fieldName _ = "person"
data Family = Family
instance FieldTag Family where
fieldName _ = "family"
data Age = Age
instance FieldTag Age where
fieldName _ = "age"
family :: Attr Family String
family = mkAttr Family
person :: Attr Person String
person = mkAttr Person
age :: Attr Age Int
age = mkAttr Age
personTable :: Table (RecCons Person String
(RecCons Family String
(RecCons Age Int RecNil)))
personTable = Table "mytable" [ ("person", AttrExpr "personcol")
, ("family", AttrExpr "familycol")
, ("age", AttrExpr "agecol") ]
I might want to calculate the total age of everyone in a family. This I do with agesOfFamilies. It returns a query whose rows (ostensibly) pair the family with the total age of everyone in that family.
agesOfFamilies :: Query (Rel
(RecCons Family (Expr String)
(RecCons Age (Expr Int) RecNil)))
agesOfFamilies = do
my <- table personTable
project (family << my!family # age << _sum (my!age))
I can test it with showSql thus:
*Main> putStrLn $ showSql agesOfFamilies
SELECT familycol as family,
SUM(agecol) as age
FROM mytable as T1
GROUP BY familycol
which is exactly what I wanted. What happens if I want to project just the age column from this query?
justAgesOfFamilies :: Query (Rel (RecCons Age (Expr Int) RecNil))
justAgesOfFamilies = do
agesOfFamilies <- agesOfFamilies
project (age << agesOfFamilies!age)
It seems that justAgesOfFamilies should return a single-column query with one row for each family containing their total age, i.e. the result of the query agesOfFamilies without the family column. However, what I get is completely different
*Main> putStrLn $ showSql justAgesOfFamilies
SELECT SUM(agecol) as age
FROM mytable as T1
This kind of behaviour seems to be an enormous impediment to composability of queries in HaskellDB.
The semantics of HaskellDB's aggregation operators is very unclear. Let me propose the following example to demonstrate my confusion. It concerns a table whose rows represent people. A person has a family and an age.
I might want to calculate the total age of everyone in a family. This I do with
agesOfFamilies. It returns a query whose rows (ostensibly) pair the family with the total age of everyone in that family.I can test it with
showSqlthus:which is exactly what I wanted. What happens if I want to project just the age column from this query?
It seems that
justAgesOfFamiliesshould return a single-column query with one row for each family containing their total age, i.e. the result of the queryagesOfFamilieswithout thefamilycolumn. However, what I get is completely differentThis kind of behaviour seems to be an enormous impediment to composability of queries in HaskellDB.