Skip to content

Commit

Permalink
Merge pull request #49 from valeriomazzeo/feature/outer-join-fix
Browse files Browse the repository at this point in the history
Outer join fix
  • Loading branch information
Joannis authored Oct 17, 2017
2 parents 4f605bf + 8b2db4d commit a16f5d7
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Sources/MongoDriver/MongoDriver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ extension MongoKitten.Database : Fluent.Driver, Connection {
let collectionName = lookup.joined.name

pipeline.append(.lookup(from: self[lookup.joined.entity], localField: lookup.baseKey, foreignField: lookup.joinedKey, as: collectionName))
pipeline.append(.unwind("$" + collectionName))
pipeline.append(.unwind("$" + collectionName, preserveNullAndEmptyArrays: lookup.kind == .outer))
}

pipeline.append(.match(filter))
Expand Down
44 changes: 44 additions & 0 deletions Tests/MongoDriverTests/DriverTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class DriverTests: XCTestCase {
return [
("testInsertAndFind", testInsertAndFind),
("testArray", testArray),
("testOuterJoin", testOuterJoin),
("testSiblingsCount", testSiblingsCount),
("testMax", testMax),
("testSiblingsMax", testSiblingsMax),
Expand Down Expand Up @@ -61,6 +62,49 @@ class DriverTests: XCTestCase {
XCTAssert(foundStore.vinyls.filter({ return $0.name == "Thriller" }).count == 1)
}

func testOuterJoin() throws {
try driver.drop()
let db = Fluent.Database(driver)

Pet.database = db
Toy.database = db

let ball = Toy(name: "ball")
let bone = Toy(name: "bone")
let puppet = Toy(name: "puppet")

try ball.save()
try bone.save()
try puppet.save()

let molly = Pet(name: "Molly", age: 2)
molly.favoriteToyId = ball.id

let rex = Pet(name: "Rex", age: 1)

try molly.save()
try rex.save()

XCTAssertNotNil(try molly.favoriteToy.get())
XCTAssertNil(try rex.favoriteToy.get())

let toysFavoritedByPets = try Toy.makeQuery()
.join(kind: .inner, Pet.self, baseKey: Toy.idKey, joinedKey: "favoriteToyId")
.all()

XCTAssertEqual(toysFavoritedByPets.count, 1)
XCTAssertEqual(toysFavoritedByPets.first?.id, ball.id)

let toysNotFavoritedByPets = try Toy.makeQuery()
.join(kind: .outer, Pet.self, baseKey: Toy.idKey, joinedKey: "favoriteToyId")
.filter(Pet.self, Pet.idKey, .equals, nil)
.all()

XCTAssertEqual(toysNotFavoritedByPets.count, 2)
XCTAssertTrue(toysNotFavoritedByPets.contains(where: { $0.id == bone.id }))
XCTAssertTrue(toysNotFavoritedByPets.contains(where: { $0.id == puppet.id }))
}

func testSiblingsCount() throws {
try driver.drop()
let db = Fluent.Database(driver)
Expand Down
16 changes: 14 additions & 2 deletions Tests/MongoDriverTests/Pet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ final class Pet: Entity {

public let age: Int

public init(name: String, age: Int) {
public var favoriteToyId: Identifier?

public init(name: String, age: Int, favoriteToyId: Identifier? = nil) {
self.name = name
self.age = age
self.favoriteToyId = favoriteToyId
}

// MARK: Storable
Expand All @@ -27,7 +30,11 @@ final class Pet: Entity {

public convenience init(row: Row) throws {

self.init(name: try row.get("name"), age: try row.get("age"))
self.init(
name: try row.get("name"),
age: try row.get("age"),
favoriteToyId: try row.get("favoriteToyId")
)
}

public func makeRow() throws -> Row {
Expand All @@ -37,6 +44,7 @@ final class Pet: Entity {
try row.set(Pet.idKey, self.id)
try row.set("name", self.name)
try row.set("age", self.age)
try row.set("favoriteToyId", self.favoriteToyId)

return row
}
Expand All @@ -46,6 +54,10 @@ final class Pet: Entity {

extension Pet {

public var favoriteToy: Parent<Pet, Toy> {
return self.parent(id: self.favoriteToyId)
}

public var toys: Siblings<Pet, Toy, Pivot<Pet, Toy>> {
return self.siblings()
}
Expand Down

0 comments on commit a16f5d7

Please sign in to comment.