I have a database schema with teachers, schools, and districts. The TEACHERS
table has a nullable SCHOOL_ID
column (a teacher may or may not belong to a school) and the SCHOOLS
table has a nullable DISTRICT_ID
column (a school may or may not belong to a district).
Using Esqueleto, I want a list of teachers, each with a school (if they belong to one) and a district (if they belong to a school that belongs to a district). It took a little while to figure out the right expression just for the teacher->school left join, but I eventually got it right:
select $
from $ \(teacher `LeftOuterJoin` school) -> do
on (teacher ^. TeacherSchoolId ==. school ?. SchoolId)
return (teacher, school)
I tried adding another left join on DISTRICTS
using an analogous expression:
select $
from $ \(teacher `LeftOuterJoin` school `LeftOuterJoin` district) -> do
on (school ^. SchoolDistrictId ==. district ?. DistrictId)
on (teacher ^. TeacherSchoolId ==. school ?. SchoolId)
return (teacher, school, district)
But I get an error:
Couldn't match type ‘Entity School’ with ‘Maybe (Entity School)’
Expected type: SqlExpr (Maybe (Entity School))
Actual type: SqlExpr (Entity School)
In the first argument of ‘(?.)’, namely ‘school’
In the second argument of ‘(==.)’, namely ‘school ?. SchoolId’
Can this double join be expressed using Esqueleto? If so, how?
Try changing
on (teacher ^. TeacherSchoolId ==. school ?. SchoolId)
To
on (teacher ^. TeacherSchoolId ==. just (school ?. SchoolId))
If that doesn't work, slap 'just' on other components of the query expression until it works.
Reference: used Esqueleto recently on a commercial project
Update, 2016/10/26:
I recently encountered this problem. I think it's a Persistent serialization problem interacting with Esqueleto's willingness to pretend the join doesn't produce nullable results.
I recently changed a fragment of a query from:
person `LeftOuterJoin`
personExtra
) -> do
on ((personExtra ^. PersonExtraPerson) ==. (person ^. PersonId))
to:
person `LeftOuterJoin`
personExtra
) -> do
on ((personExtra ?. PersonExtraPerson) ==. just (person ^. PersonId))
I also changed the return type of my query from Entity PersonExtra
to Maybe (Entity PersonExtra)
.
Now Persistent expects the possibility of a PersistNull
and the query works fine for me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With