Example table definitions & query:
case class House(id: Long, address: String)
case class Metro(id: Long, houseId: Long, name: String)
case class Room(id: Long, houseId: Long, area: Int)
object Houses extends Table[House]("Houses") {
def id = column[Long]("id", O.AutoInc, O.PrimaryKey)
def address = column[String]("address")
def * = id ~ address <> (House.apply _, House.unapply _)
}
object Metros extends Table[Metro]("Metros") {
def id = column[Long]("id", O.AutoInc, O.PrimaryKey)
def houseId = column[Long]("houseId")
def name = column[String]("name")
def * = id ~ houseId ~ name <> (Metro.apply _, Metro.unapply _)
}
object Rooms extends Table[Room]("Rooms") {
def id = column[Long]("id", O.AutoInc, O.PrimaryKey)
def houseId = column[Long]("houseId")
def area = column[Int]("area")
def * = id ~ houseId ~ area <> (Room.apply _, Room.unapply _)
}
val query = for {
((h,m),r) <- Houses
.leftJoin(Rooms).on(_.id === _.houseId)
.leftJoin(Metros).on(_._1.id === _.houseId)
} yield (h, m, r)
Previously generated sql:
SELECT s5.s24, s5.s25, s5.s26, s5.s27, s5.s28, s6.s29, s6.s30, s6.s31
FROM
(SELECT s7.s19 AS s24, s7.s20 AS s25, s8.s21 AS s26, s8.s22 AS s27, s8.s23 AS s28
FROM
(SELECT s11.`id` AS s19, s11.`address` AS s20
FROM `Houses` s11) s7
LEFT OUTER JOIN
(SELECT s12.`id` AS s21, s12.`houseId` AS s22, s12.`area` AS s23
FROM `Rooms` s12) s8 ON s7.s19 = s8.s22) s5
LEFT OUTER JOIN
(SELECT s13.`id` AS s29, s13.`houseId` AS s30, s13.`name` AS s31
FROM `Metros` s13) s6 ON s5.s24 = s6.s30
After applying unboxing phase:
SELECT s5.s24, s5.s25, s5.s26, s5.s27, s5.s28, s6.`id`, s6.`houseId`, s6.`name`
FROM
(SELECT s7.`id` AS s24, s7.`address` AS s25, s8.`id` AS s26, s8.`houseId` AS s27, s8.`area` AS s28
FROM `Houses` s7
LEFT OUTER JOIN `Rooms` s8 ON s7.`id` = s8.`houseId`) s5
LEFT OUTER JOIN `Metros` s6 ON s5.s24 = s6.`houseId`