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

737 lines
49 KiB
Swift

import XCTest
@testable import GRDB
class AssociationPrefetchingRelationTests: GRDBTestCase {
func testAssociationKeyInflections() {
do {
let key = SQLAssociationKey.inflected("player")
XCTAssertEqual(key.baseName, "player")
XCTAssertEqual(key.singularizedName, "player")
XCTAssertEqual(key.pluralizedName, "players")
XCTAssertEqual(key.name(singular: true), "player")
XCTAssertEqual(key.name(singular: false), "players")
}
do {
let key = SQLAssociationKey.fixedSingular("player")
XCTAssertEqual(key.baseName, "player")
XCTAssertEqual(key.singularizedName, "player")
XCTAssertEqual(key.pluralizedName, "players")
XCTAssertEqual(key.name(singular: true), "player")
XCTAssertEqual(key.name(singular: false), "players")
}
do {
let key = SQLAssociationKey.fixedSingular("players")
XCTAssertEqual(key.baseName, "players")
XCTAssertEqual(key.singularizedName, "players")
XCTAssertEqual(key.pluralizedName, "players")
XCTAssertEqual(key.name(singular: true), "players")
XCTAssertEqual(key.name(singular: false), "players")
}
do {
let key = SQLAssociationKey.fixedPlural("player")
XCTAssertEqual(key.baseName, "player")
XCTAssertEqual(key.singularizedName, "player")
XCTAssertEqual(key.pluralizedName, "player")
XCTAssertEqual(key.name(singular: true), "player")
XCTAssertEqual(key.name(singular: false), "player")
}
do {
let key = SQLAssociationKey.fixedPlural("players")
XCTAssertEqual(key.baseName, "players")
XCTAssertEqual(key.singularizedName, "player")
XCTAssertEqual(key.pluralizedName, "players")
XCTAssertEqual(key.name(singular: true), "player")
XCTAssertEqual(key.name(singular: false), "players")
}
do {
let key = SQLAssociationKey.fixed("player")
XCTAssertEqual(key.baseName, "player")
XCTAssertEqual(key.singularizedName, "player")
XCTAssertEqual(key.pluralizedName, "player")
XCTAssertEqual(key.name(singular: true), "player")
XCTAssertEqual(key.name(singular: false), "player")
}
do {
let key = SQLAssociationKey.fixed("players")
XCTAssertEqual(key.baseName, "players")
XCTAssertEqual(key.singularizedName, "players")
XCTAssertEqual(key.pluralizedName, "players")
XCTAssertEqual(key.name(singular: true), "players")
XCTAssertEqual(key.name(singular: false), "players")
}
}
func testOneStep() {
let cardinalities: [SQLAssociationCardinality] = [
.toOne,
.toMany,
]
let keys: [SQLAssociationKey] = [
.inflected("player"),
.fixedSingular("player"),
.fixedSingular("players"),
.fixedPlural("player"),
.fixedPlural("players"),
.fixed("player"),
]
for cardinality in cardinalities {
for key in keys {
let relation = SQLRelation.all(fromTable: "ignored")
let association = _SQLAssociation(
key: key,
condition: .none,
relation: .all(fromTable: "ignored"),
cardinality: cardinality)
for relation in [
relation._joining(optional: association),
relation._including(optional: association),
] {
do {
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneOptional)
}
do {
let relation = relation._joining(optional: association)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneOptional)
}
do {
let relation = relation._joining(required: association)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
}
do {
let relation = relation._including(optional: association)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneOptional)
}
do {
let relation = relation._including(required: association)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
}
if key.name(singular: true) != key.name(singular: false) {
let relation = relation._including(all: association)
XCTAssertEqual(relation.children.count, 2)
XCTAssertEqual(relation.children[0].key, key.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneOptional)
XCTAssertEqual(relation.children[1].key, key.name(singular: false))
XCTAssertEqual(relation.children[1].value.kind, .all)
}
}
for relation in [
relation._joining(required: association),
relation._including(required: association),
] {
do {
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
}
do {
let relation = relation._joining(optional: association)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
}
do {
let relation = relation._joining(required: association)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
}
do {
let relation = relation._including(optional: association)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
}
do {
let relation = relation._including(required: association)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
}
if key.name(singular: true) != key.name(singular: false) {
let relation = relation._including(all: association)
XCTAssertEqual(relation.children.count, 2)
XCTAssertEqual(relation.children[0].key, key.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[1].key, key.name(singular: false))
XCTAssertEqual(relation.children[1].value.kind, .all)
}
}
do {
let relation = relation._including(all: association)
do {
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key.name(singular: false))
XCTAssertEqual(relation.children[0].value.kind, .all)
}
if key.name(singular: true) != key.name(singular: false) {
let relation = relation._joining(optional: association)
XCTAssertEqual(relation.children.count, 2)
XCTAssertEqual(relation.children[0].key, key.name(singular: false))
XCTAssertEqual(relation.children[0].value.kind, .all)
XCTAssertEqual(relation.children[1].key, key.name(singular: true))
XCTAssertEqual(relation.children[1].value.kind, .oneOptional)
}
if key.name(singular: true) != key.name(singular: false) {
let relation = relation._joining(required: association)
XCTAssertEqual(relation.children.count, 2)
XCTAssertEqual(relation.children[0].key, key.name(singular: false))
XCTAssertEqual(relation.children[0].value.kind, .all)
XCTAssertEqual(relation.children[1].key, key.name(singular: true))
XCTAssertEqual(relation.children[1].value.kind, .oneRequired)
}
if key.name(singular: true) != key.name(singular: false) {
let relation = relation._including(optional: association)
XCTAssertEqual(relation.children.count, 2)
XCTAssertEqual(relation.children[0].key, key.name(singular: false))
XCTAssertEqual(relation.children[0].value.kind, .all)
XCTAssertEqual(relation.children[1].key, key.name(singular: true))
XCTAssertEqual(relation.children[1].value.kind, .oneOptional)
}
if key.name(singular: true) != key.name(singular: false) {
let relation = relation._including(required: association)
XCTAssertEqual(relation.children.count, 2)
XCTAssertEqual(relation.children[0].key, key.name(singular: false))
XCTAssertEqual(relation.children[0].value.kind, .all)
XCTAssertEqual(relation.children[1].key, key.name(singular: true))
XCTAssertEqual(relation.children[1].value.kind, .oneRequired)
}
do {
let relation = relation._including(all: association)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key.name(singular: false))
XCTAssertEqual(relation.children[0].value.kind, .all)
}
}
}
}
}
func testTwoSteps() {
let cardinalities: [SQLAssociationCardinality] = [
.toOne,
.toMany,
]
let keys1: [SQLAssociationKey] = [
.inflected("player"),
.fixedSingular("player"),
.fixedSingular("players"),
.fixedPlural("player"),
.fixedPlural("players"),
.fixed("player"),
]
let keys2: [SQLAssociationKey] = [
.inflected("award"),
.fixedSingular("award"),
.fixedSingular("awards"),
.fixedPlural("award"),
.fixedPlural("awards"),
.fixed("award"),
]
for cardinality1 in cardinalities {
for key1 in keys1 {
for cardinality2 in cardinalities {
for key2 in keys2 {
let relation = SQLRelation.all(fromTable: "ignored")
let association1 = _SQLAssociation(
key: key1,
condition: .none,
relation: .all(fromTable: "ignored"),
cardinality: cardinality1)
let association2 = _SQLAssociation(
key: key2,
condition: .none,
relation: .all(fromTable: "ignored"),
cardinality: cardinality2)
let association = association2.through(association1)
for relation in [
relation._joining(optional: association),
relation._including(optional: association),
] {
do {
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneOptional)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneOptional)
}
do {
do {
let relation = relation._joining(optional: association1)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneOptional)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneOptional)
}
do {
let relation = relation._joining(required: association1)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneOptional)
}
do {
let relation = relation._including(optional: association1)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneOptional)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneOptional)
}
do {
let relation = relation._including(required: association1)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneOptional)
}
if !cardinality1.isSingular && key1.name(singular: true) != key1.name(singular: false) {
let relation = relation._including(all: association1)
XCTAssertEqual(relation.children.count, 2)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneOptional)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneOptional)
XCTAssertEqual(relation.children[1].key, key1.name(singular: false))
XCTAssertEqual(relation.children[1].value.kind, .all)
XCTAssertEqual(relation.children[1].value.relation.children.count, 0)
}
}
do {
do {
let relation = relation._joining(optional: association)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneOptional)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneOptional)
}
do {
let relation = relation._joining(required: association)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneRequired)
}
do {
let relation = relation._including(optional: association)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneOptional)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneOptional)
}
do {
let relation = relation._including(required: association)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneRequired)
}
if !cardinality1.isSingular && key1.name(singular: true) != key1.name(singular: false) {
let relation = relation._including(all: association)
XCTAssertEqual(relation.children.count, 2)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneOptional)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneOptional)
XCTAssertEqual(relation.children[1].key, key1.name(singular: cardinality1.isSingular))
XCTAssertEqual(relation.children[1].value.kind, .bridge)
XCTAssertEqual(relation.children[1].value.relation.children.count, 1)
XCTAssertEqual(relation.children[1].value.relation.children[0].key, key2.name(singular: false))
XCTAssertEqual(relation.children[1].value.relation.children[0].value.kind, .all)
}
}
}
for relation in [
relation._joining(required: association),
relation._including(required: association),
] {
do {
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneRequired)
}
do {
do {
let relation = relation._joining(optional: association1)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneRequired)
}
do {
let relation = relation._joining(required: association1)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneRequired)
}
do {
let relation = relation._including(optional: association1)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneRequired)
}
do {
let relation = relation._including(required: association1)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneRequired)
}
if !cardinality1.isSingular && key1.name(singular: true) != key1.name(singular: false) {
let relation = relation._including(all: association1)
XCTAssertEqual(relation.children.count, 2)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[1].key, key1.name(singular: false))
XCTAssertEqual(relation.children[1].value.kind, .all)
XCTAssertEqual(relation.children[1].value.relation.children.count, 0)
}
}
do {
do {
let relation = relation._joining(optional: association)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneRequired)
}
do {
let relation = relation._joining(required: association)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneRequired)
}
do {
let relation = relation._including(optional: association)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneRequired)
}
do {
let relation = relation._including(required: association)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneRequired)
}
if !cardinality1.isSingular && key1.name(singular: true) != key1.name(singular: false) {
let relation = relation._including(all: association)
XCTAssertEqual(relation.children.count, 2)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[1].key, key1.name(singular: cardinality1.isSingular))
XCTAssertEqual(relation.children[1].value.kind, .bridge)
XCTAssertEqual(relation.children[1].value.relation.children.count, 1)
XCTAssertEqual(relation.children[1].value.relation.children[0].key, key2.name(singular: false))
XCTAssertEqual(relation.children[1].value.relation.children[0].value.kind, .all)
}
}
}
do {
let relation = relation._including(all: association)
do {
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: cardinality1.isSingular))
XCTAssertEqual(relation.children[0].value.kind, .bridge)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: false))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .all)
}
// TODO: here we see the problem: it should be possible to merge association1 when it is singular.
if !cardinality1.isSingular && key1.name(singular: true) != key1.name(singular: false) {
let relation = relation._joining(optional: association1)
XCTAssertEqual(relation.children.count, 2)
XCTAssertEqual(relation.children[0].key, key1.name(singular: cardinality1.isSingular))
XCTAssertEqual(relation.children[0].value.kind, .bridge)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: false))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .all)
XCTAssertEqual(relation.children[1].key, key1.name(singular: true))
XCTAssertEqual(relation.children[1].value.kind, .oneOptional)
XCTAssertEqual(relation.children[1].value.relation.children.count, 0)
}
}
}
}
}
}
}
func testThreeSteps() {
let cardinalities: [SQLAssociationCardinality] = [
.toOne,
.toMany,
]
let keys1: [SQLAssociationKey] = [
.inflected("player"),
.fixedSingular("player"),
.fixedSingular("players"),
.fixedPlural("player"),
.fixedPlural("players"),
.fixed("player"),
]
let keys2: [SQLAssociationKey] = [
.inflected("award"),
.fixedSingular("award"),
.fixedSingular("awards"),
.fixedPlural("award"),
.fixedPlural("awards"),
.fixed("award"),
]
let keys3: [SQLAssociationKey] = [
.inflected("sponsor"),
.fixedSingular("sponsor"),
.fixedSingular("sponsors"),
.fixedPlural("sponsor"),
.fixedPlural("sponsors"),
.fixed("sponsor"),
]
for cardinality1 in cardinalities {
for key1 in keys1 {
for cardinality2 in cardinalities {
for key2 in keys2 {
for cardinality3 in cardinalities {
for key3 in keys3 {
let relation = SQLRelation.all(fromTable: "ignored")
let association1 = _SQLAssociation(
key: key1,
condition: .none,
relation: .all(fromTable: "ignored"),
cardinality: cardinality1)
let association2 = _SQLAssociation(
key: key2,
condition: .none,
relation: .all(fromTable: "ignored"),
cardinality: cardinality2)
let association3 = _SQLAssociation(
key: key3,
condition: .none,
relation: .all(fromTable: "ignored"),
cardinality: cardinality3)
for association in [
association3.through(association2.through(association1)),
association3.through(association2).through(association1),
] {
for relation in [
relation._joining(optional: association),
relation._including(optional: association),
] {
do {
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneOptional)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneOptional)
XCTAssertEqual(relation.children[0].value.relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].value.relation.children[0].key, key3.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.relation.children[0].value.kind, .oneOptional)
}
do {
let relation = relation._joining(optional: association1)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneOptional)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneOptional)
XCTAssertEqual(relation.children[0].value.relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].value.relation.children[0].key, key3.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.relation.children[0].value.kind, .oneOptional)
}
}
for relation in [
relation._joining(required: association),
relation._including(required: association),
] {
do {
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[0].value.relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].value.relation.children[0].key, key3.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.relation.children[0].value.kind, .oneRequired)
}
do {
let relation = relation._joining(optional: association1)
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: true))
XCTAssertEqual(relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .oneRequired)
XCTAssertEqual(relation.children[0].value.relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].value.relation.children[0].key, key3.name(singular: true))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.relation.children[0].value.kind, .oneRequired)
}
}
do {
let relation = relation._including(all: association)
do {
XCTAssertEqual(relation.children.count, 1)
XCTAssertEqual(relation.children[0].key, key1.name(singular: cardinality1.isSingular))
XCTAssertEqual(relation.children[0].value.kind, .bridge)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: cardinality2.isSingular))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .bridge)
XCTAssertEqual(relation.children[0].value.relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].value.relation.children[0].key, key3.name(singular: false))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.relation.children[0].value.kind, .all)
}
// TODO: here we see the problem: it should be possible to merge association1 when it is singular.
if !cardinality1.isSingular && key1.name(singular: true) != key1.name(singular: false) {
let relation = relation._joining(optional: association1)
XCTAssertEqual(relation.children.count, 2)
XCTAssertEqual(relation.children[0].key, key1.name(singular: cardinality1.isSingular))
XCTAssertEqual(relation.children[0].value.kind, .bridge)
XCTAssertEqual(relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].key, key2.name(singular: cardinality2.isSingular))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.kind, .bridge)
XCTAssertEqual(relation.children[0].value.relation.children[0].value.relation.children.count, 1)
XCTAssertEqual(relation.children[0].value.relation.children[0].value.relation.children[0].key, key3.name(singular: false))
XCTAssertEqual(relation.children[0].value.relation.children[0].value.relation.children[0].value.kind, .all)
XCTAssertEqual(relation.children[1].key, key1.name(singular: true))
XCTAssertEqual(relation.children[1].value.kind, .oneOptional)
XCTAssertEqual(relation.children[1].value.relation.children.count, 0)
}
}
}
}
}
}
}
}
}
}
// Regression test for <https://github.com/groue/GRDB.swift/issues/1315>
func testIssue1315() throws {
struct A: TableRecord {
static let b = belongsTo(B.self)
}
struct B: TableRecord {
static let c = hasOne(C.self)
static let e = hasOne(E.self)
}
struct C: TableRecord {
static let ds = hasMany(D.self)
}
struct D: TableRecord { }
struct E: TableRecord {
static let fs = hasMany(F.self)
}
struct F: TableRecord { }
try DatabaseQueue().write { db in
try db.execute(sql: """
CREATE TABLE b (id INTEGER PRIMARY KEY);
CREATE TABLE a (id INTEGER PRIMARY KEY, bId INTEGER REFERENCES b(id));
CREATE TABLE c (id INTEGER PRIMARY KEY, bId INTEGER REFERENCES b(id));
CREATE TABLE d (id INTEGER PRIMARY KEY, cId INTEGER REFERENCES c(id));
CREATE TABLE e (id INTEGER PRIMARY KEY, bId INTEGER REFERENCES b(id));
CREATE TABLE f (id INTEGER PRIMARY KEY, eId INTEGER REFERENCES e(id));
""")
let region = try A
.including(required: A.b
.including(optional: B.c.including(all: C.ds))
.including(optional: B.e.including(all: E.fs)))
.databaseRegion(db)
XCTAssertTrue(region.isModified(byEventsOfKind: .insert(tableName: "a")))
XCTAssertTrue(region.isModified(byEventsOfKind: .insert(tableName: "b")))
XCTAssertTrue(region.isModified(byEventsOfKind: .insert(tableName: "c")))
XCTAssertTrue(region.isModified(byEventsOfKind: .insert(tableName: "d")))
XCTAssertTrue(region.isModified(byEventsOfKind: .insert(tableName: "e")))
XCTAssertTrue(region.isModified(byEventsOfKind: .insert(tableName: "f")))
}
}
}