bitemyapp / esqueleto

New home of Esqueleto, please file issues so we can get things caught up!
BSD 3-Clause "New" or "Revised" License
372 stars 107 forks source link

Feature Request: `autoOnClause` #227

Open parsonsmatt opened 3 years ago

parsonsmatt commented 3 years ago

A lot of the time, the on clause is obvious.

User
  name Text

UserOrganization
  user UserId
  organization OrganizationId

Organization
  name Text
joinOrganizationUsers = do
    u :& _ :& o <-
        from $
            Table @User
            `InnerJoin`
            Table @UserOrganization
            `on` do
                \(u :& uo) ->
                    u ^. UserId ==. uo ^. UserOrganizationUser
            `InnerJoin`
            Table @Organization
            `on` do
                \(_ :& uo :& o) ->
                    uo ^. UserOrganizationOrganization ==. o ^. OrganizationId
    pure (u :& o)

It would be great to just write:

joinOrganizationUsers = do
    u :& _ :& o <-
        from $
            Table @User
            `InnerJoin`
            Table @UserOrganization
            `on` autoOnClause
            `InnerJoin`
            Table @Organization
            `on` autoOnClause
    pure (u :& o)

This should be feasible.

class AutoOnClause a where
    autoOnClause :: a -> SqlExpr (Value Bool)

instance
    (HasOneForeignRef (Entity a) b) 
  => 
    AutoOnClause (SqlExpr (Entity a) :& SqlExpr (Entity b)) 
  where
    autoOnClause (a :& b) =
        a ^. singularForeignRefTo ==. b ^. persistIdField

instance ??? => AutoOnClause (a :& SqlEpxr (Entity b)) where
    autoOnClause (a :& b) =
       getMatchingEntity a ^. singularForeignRefTo ==. b ^. persistIdField