I'm working on a very simple toy API to improve my Haskell skills.
The relevant database table is called ingredients
and has some fields (id, name, category)
.
I'm now trying to get a selection query working that shows possible duplicates. It does this in a naive way. If two ingredients have the same name, it might be a duplicate. It is however allowed to have ingredients with the same name, it's just that they might be duplicates. It doesn't really matter if this restraint doesn't make sense since it's just a toy project.
Basically I would like to get the following query in esqueleto:
SELECT name FROM ingredients
GROUP BY name
HAVING count(*) > 1;
I succeeded in creating the following esqueleto code
getDuplicateIngredientsStmt :: SqlPersistT (LoggingT IO) [E.Value Text]
getDuplicateIngredientsStmt = E.select
$ E.from
$ \ingredients -> do
E.groupBy $ ingredients E.^. IngredientName
E.having $ (E.countRows :: SqlExpr (E.Value Int)) E.>. E.val 1
return $ ingredients E.^. IngredientName
This all works and compiles, great. But is this really as simple as it gets?
I'm mainly frustrated with me having to cast the countRows
to an SqlExpr
is this really necessary?
If I leave out the cast I get the following error (telling me I need the cast)
Ambiguous type variable ‘typ0’ arising from a use of ‘countRows’
prevents the constraint ‘(Num typ0)’ from being solved.
Probable fix: use a type annotation to specify what ‘typ0’ should be.