Skip to content

Commit 1095d21

Browse files
committed
Default implementation for schema source chaining.
When GRDB eventually adds methods to the DatabaseSchemaSource protocol, our chained schema source will implement chaining on those new methods. When users write their own custom chaining schema source, the compiler will not tell them that they have to chain the new methods when they upgrade GRDB. The built-in (and correct) implementation of chaining helps avoiding this scenario.
1 parent eb2378a commit 1095d21

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

GRDB/Core/DatabaseSchemaSource.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@
4242
/// ### Customizing the Database Schema
4343
///
4444
/// - ``columnsForPrimaryKey(_:inView:)``
45+
///
46+
/// ### Chaining Schema Sources
47+
///
48+
/// - ``then(_:)``
4549
public protocol DatabaseSchemaSource: Sendable {
4650
/// Returns the names of the columns for the primary key in the
4751
/// provided database view.
@@ -118,3 +122,33 @@ extension DatabaseSchemaSource {
118122
nil
119123
}
120124
}
125+
126+
// MARK: - Combined2SchemaSource
127+
128+
extension DatabaseSchemaSource {
129+
/// Returns a schema source that queries `other` when this source does
130+
/// not perform customization.
131+
public func then(_ other: some DatabaseSchemaSource) -> some DatabaseSchemaSource {
132+
Chained2SchemaSource(first: self, second: other)
133+
}
134+
}
135+
136+
// TODO: move to parameter packs eventually. Parameter packs in generic types
137+
// are only available in macOS 14.0.0 or newer.
138+
// This schema source is designed to tame bad citizens that customize tables
139+
// and views they do not own (such as insufficienly robust schema sources
140+
// exposed by external libraries). We should NEVER MERGE the results of the
141+
// schema sources.
142+
struct Chained2SchemaSource<Source1, Source2>: DatabaseSchemaSource
143+
where Source1: DatabaseSchemaSource,
144+
Source2: DatabaseSchemaSource
145+
{
146+
var first: Source1
147+
var second: Source2
148+
149+
func columnsForPrimaryKey(_ db: Database, inView view: DatabaseObjectID) throws -> [String]? {
150+
if let result = try first.columnsForPrimaryKey(db, inView: view) { return result }
151+
if let result = try second.columnsForPrimaryKey(db, inView: view) { return result }
152+
return nil
153+
}
154+
}

0 commit comments

Comments
 (0)