Skip to content

Commit 99ecf76

Browse files
committed
Support primary key when testing the existence of an association to a view
1 parent f499127 commit 99ecf76

File tree

2 files changed

+47
-7
lines changed

2 files changed

+47
-7
lines changed

GRDB/Core/Database+Schema.swift

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,6 @@ extension Database {
580580

581581
/// Returns whether the column identifies the rowid column
582582
func columnIsRowID(_ column: String, of tableName: String) throws -> Bool {
583-
#warning("TODO: test with database views")
584583
let pk = try primaryKey(tableName)
585584
return pk.rowIDColumn == column || (pk.tableHasRowID && column.uppercased() == "ROWID")
586585
}
@@ -1153,8 +1152,8 @@ extension Database {
11531152
///
11541153
/// The returned array is never empty.
11551154
func existenceCheckColumns(in tableName: String) throws -> [String] {
1156-
if try tableExists(tableName) {
1157-
// Table: only check the primary key columns for existence
1155+
do {
1156+
// Check the primary key columns for existence
11581157
let primaryKey = try self.primaryKey(tableName)
11591158
if let rowIDColumn = primaryKey.rowIDColumn {
11601159
// Prefer the user-provided name of the rowid
@@ -1175,10 +1174,15 @@ extension Database {
11751174
// try db.existenceCheckColumns(in: "player") // ["uuid"]
11761175
return primaryKey.columns
11771176
}
1178-
} else {
1179-
#warning("TODO: use the primary key if available")
1180-
// View: check all columns for existence
1181-
return try columns(in: tableName).map(\.name)
1177+
} catch let error as DatabaseError {
1178+
if case .SQLITE_ERROR = error.resultCode,
1179+
(try? viewExists(tableName)) == true
1180+
{
1181+
// View without primary key: check all columns for existence
1182+
return try columns(in: tableName).map(\.name)
1183+
} else {
1184+
throw error
1185+
}
11821186
}
11831187
}
11841188
}

Tests/GRDBTests/AssociationBelongsToSQLTests.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2359,5 +2359,41 @@ class AssociationBelongsToSQLTests: GRDBTestCase {
23592359
""")
23602360
}
23612361
}
2362+
2363+
do {
2364+
// View with custom primary key.
2365+
// Existence check is performed on the primary key.
2366+
struct SchemaSource: DatabaseSchemaSource {
2367+
func columnsForPrimaryKey(_ db: Database, inView view: DatabaseObjectID) throws -> [String]? {
2368+
["id"]
2369+
}
2370+
}
2371+
dbConfiguration.schemaSource = SchemaSource()
2372+
let dbQueue = try makeDatabaseQueue()
2373+
try dbQueue.write { db in
2374+
try db.create(table: "author") { t in
2375+
t.autoIncrementedPrimaryKey("id")
2376+
t.column("name", .text)
2377+
}
2378+
try db.create(table: "book") { t in
2379+
t.autoIncrementedPrimaryKey("id")
2380+
t.column("authorID", .integer)
2381+
}
2382+
try db.execute(sql: """
2383+
CREATE VIEW authorView AS SELECT * FROM author
2384+
""")
2385+
2386+
let association = Book.belongsTo(Table("authorView"), using: ForeignKey(["authorId"], to: ["id"]))
2387+
let authorAlias = TableAlias()
2388+
let request = Book
2389+
.joining(optional: association.aliased(authorAlias))
2390+
.filter(!authorAlias.exists)
2391+
try assertEqualSQL(db, request, """
2392+
SELECT "book".* FROM "book" \
2393+
LEFT JOIN "authorView" ON "authorView"."id" = "book"."authorId" \
2394+
WHERE "authorView"."id" IS NULL
2395+
""")
2396+
}
2397+
}
23622398
}
23632399
}

0 commit comments

Comments
 (0)