14
votes

Doing an outer join between two tables is easy:

tblA.leftJoin(tblB).on(_.aId === _.bId)

But when doing joins between 5 tables it quickly becomes unwieldy:

tblA.leftJoin(tblB).on(_.aId === _.bId).
    leftJoin(tblC).on(_._1.aId === _.cId).
    leftJoin(tblD).on(_._1._1.aId === _.dId).
    leftJoin(tblE).on(_._1._1._1.aId === _.eId)

The tuple accessors become a little confusing, especially if they do not all access the first table.

Is there a better way?

The fact that inner joins are semantically equivalent to flatMap with filter solves this problem for inner joins:

for {
    a <- tblA
    b <- tblB if a.aId === b.bId
    c <- tblC if a.aId === c.cId
    d <- tblD if a.aId === d.dId
    e <- tblE if a.aId === e.eId
} yield ???

Is there a similairly elegant syntax for outer joins?

1

1 Answers

7
votes

How about this?

tblA.leftJoin(tblB).leftJoin(tblC).leftJoin(tblD).leftJoin(tblE).on{
  case ((((a,b),c),d),e) =>
    a.aId === b.bId &&
    a.aId === c.cId &&
    a.aId === d.dId &&
    a.aId === e.eId
}

Doesn't produce the best SQL at the moment, but we hope to improve that soon.

A left join producing HLists should allow to even make the pattern match nicer, but is probably blocked by: https://github.com/slick/slick/issues/728