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

271 lines
13 KiB
Swift

import XCTest
import GRDB
private struct Team: Codable, FetchableRecord, PersistableRecord {
static let databaseTableName = "teams"
var id: Int64
var name: String
}
private struct Player: Codable, FetchableRecord, PersistableRecord {
static let databaseTableName = "players"
static let defaultTeam = belongsTo(Team.self)
static let customTeam = belongsTo(Team.self, key: "customTeam")
var id: Int64
var teamId: Int64?
var name: String
}
/// Test row scopes
class AssociationBelongsToRowScopeTests: GRDBTestCase {
override func setup(_ dbWriter: some DatabaseWriter) throws {
try dbWriter.write { db in
try db.create(table: "teams") { t in
t.primaryKey("id", .integer)
t.column("name", .text)
}
try db.create(table: "players") { t in
t.primaryKey("id", .integer)
t.belongsTo("team")
t.column("name", .text)
}
try Team(id: 1, name: "Reds").insert(db)
try Player(id: 1, teamId: 1, name: "Arthur").insert(db)
try Player(id: 2, teamId: nil, name: "Barbara").insert(db)
}
}
func testJoiningDoesNotUseAnyRowAdapter() throws {
let dbQueue = try makeDatabaseQueue()
try dbQueue.inDatabase { db in
let request = Player.joining(required: Player.defaultTeam)
let adapter = try request.makePreparedRequest(db, forSingleResult: false).adapter
XCTAssertNil(adapter)
}
}
func testDefaultScopeIncludingRequired() throws {
let dbQueue = try makeDatabaseQueue()
let request = Player.including(required: Player.defaultTeam)
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 1)
XCTAssertEqual(rows[0].unscoped, ["id":1, "teamId":1, "name":"Arthur"])
XCTAssertEqual(Set(rows[0].scopes.names), ["team"])
XCTAssertEqual(rows[0].scopes["team"]!, ["id":1, "name":"Reds"])
}
func testDefaultScopeIncludingRequiredEmptySelection() throws {
let dbQueue = try makeDatabaseQueue()
let request = Player.select([]).including(required: Player.defaultTeam)
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 1)
XCTAssertEqual(rows[0].unscoped, [:])
XCTAssertEqual(Set(rows[0].scopes.names), ["team"])
XCTAssertEqual(rows[0].scopes["team"]!, ["id":1, "name":"Reds"])
}
func testDefaultScopeAnnotatedWithRequired() throws {
let dbQueue = try makeDatabaseQueue()
let request = Player.annotated(withRequired: Player.defaultTeam)
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 1)
XCTAssertEqual(rows[0], ["id":1, "teamId":1, "name":"Arthur", "id":1, "name":"Reds"])
}
func testDefaultScopeAnnotatedWithRequiredCustomSelection() throws {
let dbQueue = try makeDatabaseQueue()
let request = Player.annotated(withRequired: Player.defaultTeam.select(Column("name").forKey("teamName")))
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 1)
XCTAssertEqual(rows[0], ["id":1, "teamId":1, "name":"Arthur", "teamName":"Reds"])
}
func testDefaultScopeIncludingOptional() throws {
let dbQueue = try makeDatabaseQueue()
let request = Player.including(optional: Player.defaultTeam)
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 2)
XCTAssertEqual(rows[0].unscoped, ["id":1, "teamId":1, "name":"Arthur"])
XCTAssertEqual(Set(rows[0].scopes.names), ["team"])
XCTAssertEqual(rows[0].scopes["team"]!, ["id":1, "name":"Reds"])
XCTAssertEqual(rows[1].unscoped, ["id":2, "teamId":nil, "name":"Barbara"])
XCTAssertEqual(Set(rows[1].scopes.names), ["team"])
XCTAssertEqual(rows[1].scopes["team"]!, ["id":nil, "name":nil])
}
func testDefaultScopeAnnotatedWithOptional() throws {
let dbQueue = try makeDatabaseQueue()
let request = Player.annotated(withOptional: Player.defaultTeam)
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 2)
XCTAssertEqual(rows[0], ["id":1, "teamId":1, "name":"Arthur", "id":1, "name":"Reds"])
XCTAssertEqual(rows[1], ["id":2, "teamId":nil, "name":"Barbara", "id":nil, "name":nil])
}
func testDefaultScopeAnnotatedWithOptionalCustomSelection() throws {
let dbQueue = try makeDatabaseQueue()
let request = Player.annotated(withOptional: Player.defaultTeam.select(Column("name").forKey("teamName")))
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 2)
XCTAssertEqual(rows[0], ["id":1, "teamId":1, "name":"Arthur", "teamName":"Reds"])
XCTAssertEqual(rows[1], ["id":2, "teamId":nil, "name":"Barbara", "teamName":nil])
}
func testDefaultScopeJoiningRequired() throws {
let dbQueue = try makeDatabaseQueue()
let request = Player.joining(required: Player.defaultTeam)
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 1)
XCTAssertEqual(rows[0].unscoped, ["id":1, "teamId":1, "name":"Arthur"])
XCTAssertTrue(rows[0].scopes.names.isEmpty)
}
func testDefaultScopeJoiningOptional() throws {
let dbQueue = try makeDatabaseQueue()
let request = Player.joining(optional: Player.defaultTeam)
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 2)
XCTAssertEqual(rows[0].unscoped, ["id":1, "teamId":1, "name":"Arthur"])
XCTAssertTrue(rows[0].scopes.names.isEmpty)
XCTAssertEqual(rows[1].unscoped, ["id":2, "teamId":nil, "name":"Barbara"])
XCTAssertTrue(rows[0].scopes.names.isEmpty)
}
func testCustomScopeIncludingRequired() throws {
let dbQueue = try makeDatabaseQueue()
let request = Player.including(required: Player.customTeam)
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 1)
XCTAssertEqual(rows[0].unscoped, ["id":1, "teamId":1, "name":"Arthur"])
XCTAssertEqual(Set(rows[0].scopes.names), ["customTeam"])
XCTAssertEqual(rows[0].scopes["customTeam"]!, ["id":1, "name":"Reds"])
}
func testCustomScopeIncludingRequiredEmptySelection() throws {
let dbQueue = try makeDatabaseQueue()
let request = Player.select([]).including(required: Player.customTeam)
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 1)
XCTAssertEqual(rows[0].unscoped, [:])
XCTAssertEqual(Set(rows[0].scopes.names), ["customTeam"])
XCTAssertEqual(rows[0].scopes["customTeam"]!, ["id":1, "name":"Reds"])
}
func testCustomScopeAnnotatedWithRequired() throws {
let dbQueue = try makeDatabaseQueue()
let request = Player.annotated(withRequired: Player.customTeam)
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 1)
XCTAssertEqual(rows[0], ["id":1, "teamId":1, "name":"Arthur", "id":1, "name":"Reds"])
}
func testCustomScopeAnnotatedWithRequiredCustomSelection() throws {
let dbQueue = try makeDatabaseQueue()
let request = Player.annotated(withRequired: Player.customTeam.select(Column("name").forKey("teamName")))
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 1)
XCTAssertEqual(rows[0], ["id":1, "teamId":1, "name":"Arthur", "teamName":"Reds"])
}
func testCustomScopeIncludingOptional() throws {
let dbQueue = try makeDatabaseQueue()
let request = Player.including(optional: Player.customTeam)
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 2)
XCTAssertEqual(rows[0].unscoped, ["id":1, "teamId":1, "name":"Arthur"])
XCTAssertEqual(Set(rows[0].scopes.names), ["customTeam"])
XCTAssertEqual(rows[0].scopes["customTeam"]!, ["id":1, "name":"Reds"])
XCTAssertEqual(rows[1].unscoped, ["id":2, "teamId":nil, "name":"Barbara"])
XCTAssertEqual(Set(rows[1].scopes.names), ["customTeam"])
XCTAssertEqual(rows[1].scopes["customTeam"]!, ["id":nil, "name":nil])
}
func testCustomScopeAnnotatedWithOptional() throws {
let dbQueue = try makeDatabaseQueue()
let request = Player.annotated(withOptional: Player.customTeam)
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 2)
XCTAssertEqual(rows[0], ["id":1, "teamId":1, "name":"Arthur", "id":1, "name":"Reds"])
XCTAssertEqual(rows[1], ["id":2, "teamId":nil, "name":"Barbara", "id":nil, "name":nil])
}
func testCustomScopeAnnotatedWithOptionalCustomSelection() throws {
let dbQueue = try makeDatabaseQueue()
let request = Player.annotated(withOptional: Player.customTeam.select(Column("name").forKey("teamName")))
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 2)
XCTAssertEqual(rows[0], ["id":1, "teamId":1, "name":"Arthur", "teamName":"Reds"])
XCTAssertEqual(rows[1], ["id":2, "teamId":nil, "name":"Barbara", "teamName":nil])
}
func testCustomPluralScopeIncludingRequired() throws {
// Make sure explicit plural keys are preserved
let dbQueue = try makeDatabaseQueue()
do {
let request = Player.including(required: Player.belongsTo(Team.self, key: "teams"))
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 1)
XCTAssertEqual(rows[0].unscoped, ["id":1, "teamId":1, "name":"Arthur"])
XCTAssertEqual(Set(rows[0].scopes.names), ["teams"])
XCTAssertEqual(rows[0].scopes["teams"]!, ["id":1, "name":"Reds"])
}
do {
let request = Player.including(required: Player.defaultTeam.forKey("teams"))
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 1)
XCTAssertEqual(rows[0].unscoped, ["id":1, "teamId":1, "name":"Arthur"])
XCTAssertEqual(Set(rows[0].scopes.names), ["teams"])
XCTAssertEqual(rows[0].scopes["teams"]!, ["id":1, "name":"Reds"])
}
}
func testCustomPluralScopeIncludingOptional() throws {
// Make sure explicit plural keys are preserved
let dbQueue = try makeDatabaseQueue()
do {
let request = Player.including(optional: Player.belongsTo(Team.self, key: "teams"))
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 2)
XCTAssertEqual(rows[0].unscoped, ["id":1, "teamId":1, "name":"Arthur"])
XCTAssertEqual(Set(rows[0].scopes.names), ["teams"])
XCTAssertEqual(rows[0].scopes["teams"]!, ["id":1, "name":"Reds"])
XCTAssertEqual(rows[1].unscoped, ["id":2, "teamId":nil, "name":"Barbara"])
XCTAssertEqual(Set(rows[1].scopes.names), ["teams"])
XCTAssertEqual(rows[1].scopes["teams"]!, ["id":nil, "name":nil])
}
do {
let request = Player.including(optional: Player.defaultTeam.forKey("teams"))
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 2)
XCTAssertEqual(rows[0].unscoped, ["id":1, "teamId":1, "name":"Arthur"])
XCTAssertEqual(Set(rows[0].scopes.names), ["teams"])
XCTAssertEqual(rows[0].scopes["teams"]!, ["id":1, "name":"Reds"])
XCTAssertEqual(rows[1].unscoped, ["id":2, "teamId":nil, "name":"Barbara"])
XCTAssertEqual(Set(rows[1].scopes.names), ["teams"])
XCTAssertEqual(rows[1].scopes["teams"]!, ["id":nil, "name":nil])
}
}
func testCustomScopeJoiningRequired() throws {
let dbQueue = try makeDatabaseQueue()
let request = Player.joining(required: Player.customTeam)
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 1)
XCTAssertEqual(rows[0].unscoped, ["id":1, "teamId":1, "name":"Arthur"])
XCTAssertTrue(rows[0].scopes.names.isEmpty)
}
func testCustomScopeJoiningOptional() throws {
let dbQueue = try makeDatabaseQueue()
let request = Player.joining(optional: Player.customTeam)
let rows = try dbQueue.inDatabase { try Row.fetchAll($0, request) }
XCTAssertEqual(rows.count, 2)
XCTAssertEqual(rows[0].unscoped, ["id":1, "teamId":1, "name":"Arthur"])
XCTAssertTrue(rows[0].scopes.names.isEmpty)
XCTAssertEqual(rows[1].unscoped, ["id":2, "teamId":nil, "name":"Barbara"])
XCTAssertTrue(rows[0].scopes.names.isEmpty)
}
}