Files
UUVPN/iOS-SwiftUI-Code/GRDB.swift-6.29.3/Tests/GRDBTests/AssociationHasOneThroughFetchableRecordTests.swift

262 lines
8.3 KiB
Swift

import XCTest
import GRDB
private struct A: Codable, FetchableRecord, PersistableRecord {
static let b = belongsTo(B.self)
static let c = hasOne(C.self, through: b, using: B.c)
var id: Int64
var bId: Int64?
var name: String
}
private struct B: Codable, FetchableRecord, PersistableRecord {
static let c = belongsTo(C.self)
var id: Int64
var cId: Int64?
var name: String
}
private struct C: Codable, FetchableRecord, PersistableRecord {
var id: Int64
var name: String
}
private struct AWithRequiredC: FetchableRecord {
var a: A
var c: C
init(row: Row) throws {
a = try A(row: row)
c = row["c"]
}
}
private struct AWithOptionalC: FetchableRecord {
var a: A
var c: C?
init(row: Row) throws {
a = try A(row: row)
c = row["c"]
}
}
private struct AWithRequiredBAndOptionalC: FetchableRecord {
var a: A
var b: B
var c: C?
init(row: Row) throws {
a = try A(row: row)
b = row["b"]
c = row["c"]
}
}
private struct AWithCName: FetchableRecord {
var a: A
var cName: String?
init(row: Row) throws {
a = try A(row: row)
cName = row["cName"]
}
}
private struct AWithRequiredBNameAndOptionalCName: FetchableRecord {
var a: A
var bName: String
var cName: String?
init(row: Row) throws {
a = try A(row: row)
bName = row["bName"]
cName = row["cName"]
}
}
/// Test support for FetchableRecord records
class AssociationHasOneThroughFetchableRecordTests: GRDBTestCase {
override func setup(_ dbWriter: some DatabaseWriter) throws {
try dbWriter.write { db in
try db.create(table: "c") { t in
t.autoIncrementedPrimaryKey("id")
t.column("name", .text)
}
try db.create(table: "b") { t in
t.autoIncrementedPrimaryKey("id")
t.belongsTo("c")
t.column("name", .text)
}
try db.create(table: "a") { t in
t.autoIncrementedPrimaryKey("id")
t.belongsTo("b")
t.column("name", .text)
}
try C(id: 1, name: "c1").insert(db)
try B(id: 1, cId: 1, name: "b1").insert(db)
try B(id: 2, cId: nil, name: "b2").insert(db)
try A(id: 1, bId: 1, name: "a1").insert(db)
try A(id: 2, bId: 2, name: "a2").insert(db)
try A(id: 3, bId: nil, name: "a3").insert(db)
}
}
func testIncludingRequired() throws {
let dbQueue = try makeDatabaseQueue()
let request = A.including(required: A.c).order(sql: "a.id")
let records = try dbQueue.inDatabase { try AWithRequiredC.fetchAll($0, request) }
XCTAssertEqual(records.count, 1)
XCTAssertEqual(records[0].a.id, 1)
XCTAssertEqual(records[0].a.bId, 1)
XCTAssertEqual(records[0].a.name, "a1")
XCTAssertEqual(records[0].c.id, 1)
XCTAssertEqual(records[0].c.name, "c1")
}
func testAnnotatedWithRequired() throws {
let dbQueue = try makeDatabaseQueue()
let request = A.annotated(withRequired: A.c.select(Column("name").forKey("cName"))).order(sql: "a.id")
let records = try dbQueue.inDatabase { try AWithCName.fetchAll($0, request) }
XCTAssertEqual(records.count, 1)
XCTAssertEqual(records[0].a.id, 1)
XCTAssertEqual(records[0].a.bId, 1)
XCTAssertEqual(records[0].a.name, "a1")
XCTAssertEqual(records[0].cName, "c1")
}
func testIncludingOptional() throws {
let dbQueue = try makeDatabaseQueue()
let request = A.including(optional: A.c).order(sql: "a.id")
let records = try dbQueue.inDatabase { try AWithOptionalC.fetchAll($0, request) }
XCTAssertEqual(records.count, 3)
XCTAssertEqual(records[0].a.id, 1)
XCTAssertEqual(records[0].a.bId, 1)
XCTAssertEqual(records[0].a.name, "a1")
XCTAssertEqual(records[0].c!.id, 1)
XCTAssertEqual(records[0].c!.name, "c1")
XCTAssertEqual(records[1].a.id, 2)
XCTAssertEqual(records[1].a.bId, 2)
XCTAssertEqual(records[1].a.name, "a2")
XCTAssertNil(records[1].c)
XCTAssertEqual(records[2].a.id, 3)
XCTAssertNil(records[2].a.bId)
XCTAssertEqual(records[2].a.name, "a3")
XCTAssertNil(records[2].c)
}
func testAnnotatedWithOptional() throws {
let dbQueue = try makeDatabaseQueue()
let request = A.annotated(withOptional: A.c.select(Column("name").forKey("cName"))).order(sql: "a.id")
let records = try dbQueue.inDatabase { try AWithCName.fetchAll($0, request) }
XCTAssertEqual(records.count, 3)
XCTAssertEqual(records[0].a.id, 1)
XCTAssertEqual(records[0].a.bId, 1)
XCTAssertEqual(records[0].a.name, "a1")
XCTAssertEqual(records[0].cName, "c1")
XCTAssertEqual(records[1].a.id, 2)
XCTAssertEqual(records[1].a.bId, 2)
XCTAssertEqual(records[1].a.name, "a2")
XCTAssertNil(records[1].cName)
XCTAssertEqual(records[2].a.id, 3)
XCTAssertNil(records[2].a.bId)
XCTAssertEqual(records[2].a.name, "a3")
XCTAssertNil(records[2].cName)
}
func testJoiningRequired() throws {
let dbQueue = try makeDatabaseQueue()
let request = A.joining(required: A.c).order(sql: "a.id")
let records = try dbQueue.inDatabase { try A.fetchAll($0, request) }
XCTAssertEqual(records.count, 1)
XCTAssertEqual(records[0].id, 1)
XCTAssertEqual(records[0].bId, 1)
XCTAssertEqual(records[0].name, "a1")
}
func testJoiningOptional() throws {
let dbQueue = try makeDatabaseQueue()
let request = A.joining(optional: A.c).order(sql: "a.id")
let records = try dbQueue.inDatabase { try A.fetchAll($0, request) }
XCTAssertEqual(records.count, 3)
XCTAssertEqual(records[0].id, 1)
XCTAssertEqual(records[0].bId, 1)
XCTAssertEqual(records[0].name, "a1")
XCTAssertEqual(records[1].id, 2)
XCTAssertEqual(records[1].bId, 2)
XCTAssertEqual(records[1].name, "a2")
XCTAssertEqual(records[2].id, 3)
XCTAssertNil(records[2].bId)
XCTAssertEqual(records[2].name, "a3")
}
func testIncludingOptionalIncludingRequiredPivot() throws {
let dbQueue = try makeDatabaseQueue()
let request = A
.including(optional: A.c)
.including(required: A.b)
.order(sql: "a.id")
let records = try dbQueue.inDatabase { try AWithRequiredBAndOptionalC.fetchAll($0, request) }
XCTAssertEqual(records.count, 2)
XCTAssertEqual(records[0].a.id, 1)
XCTAssertEqual(records[0].a.bId, 1)
XCTAssertEqual(records[0].a.name, "a1")
XCTAssertEqual(records[0].b.id, 1)
XCTAssertEqual(records[0].b.name, "b1")
XCTAssertEqual(records[0].c!.id, 1)
XCTAssertEqual(records[0].c!.name, "c1")
XCTAssertEqual(records[1].a.id, 2)
XCTAssertEqual(records[1].a.bId, 2)
XCTAssertEqual(records[1].a.name, "a2")
XCTAssertEqual(records[1].b.id, 2)
XCTAssertEqual(records[1].b.name, "b2")
XCTAssertNil(records[1].c)
}
func testAnnotatedWithOptionalAnnotatedWithRequiredPivot() throws {
let dbQueue = try makeDatabaseQueue()
let request = A
.annotated(withOptional: A.c.select(Column("name").forKey("cName")))
.annotated(withRequired: A.b.select(Column("name").forKey("bName")))
.order(sql: "a.id")
let records = try dbQueue.inDatabase { try AWithRequiredBNameAndOptionalCName.fetchAll($0, request) }
XCTAssertEqual(records.count, 2)
XCTAssertEqual(records[0].a.id, 1)
XCTAssertEqual(records[0].a.bId, 1)
XCTAssertEqual(records[0].a.name, "a1")
XCTAssertEqual(records[0].bName, "b1")
XCTAssertEqual(records[0].cName, "c1")
XCTAssertEqual(records[1].a.id, 2)
XCTAssertEqual(records[1].a.bId, 2)
XCTAssertEqual(records[1].a.name, "a2")
XCTAssertEqual(records[1].bName, "b2")
XCTAssertNil(records[1].cName)
}
}