Skip to content

Commit ff93ebc

Browse files
committed
Handle FK definitions w/o key references
Closes #1199
1 parent f1bee07 commit ff93ebc

File tree

4 files changed

+49
-3
lines changed

4 files changed

+49
-3
lines changed

SQLite.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,9 @@
211211
DB7C5DA728D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
212212
DB7C5DA828D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
213213
DB7C5DA928D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
214+
DBB93D5A2A22A373009BB96E /* SchemaReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */; };
215+
DBB93D5B2A22A373009BB96E /* SchemaReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */; };
216+
DBB93D5C2A22A373009BB96E /* SchemaReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */; };
214217
EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
215218
EE247ADE1C3F04ED00AE3E12 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE247AD31C3F04ED00AE3E12 /* SQLite.framework */; };
216219
EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
@@ -340,6 +343,7 @@
340343
DB58B21028FB864300F8EEA4 /* SchemaReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaReader.swift; sourceTree = "<group>"; };
341344
DB58B21528FC7C4600F8EEA4 /* SQLiteFeature.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteFeature.swift; sourceTree = "<group>"; };
342345
DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteVersion.swift; sourceTree = "<group>"; };
346+
DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaReaderTests.swift; sourceTree = "<group>"; };
343347
EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
344348
EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = "<group>"; };
345349
EE247AD81C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -483,6 +487,7 @@
483487
19A17B56FBA20E7245BC8AC0 /* Schema */ = {
484488
isa = PBXGroup;
485489
children = (
490+
DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */,
486491
19A176174862D0F0139B3987 /* SchemaDefinitionsTests.swift */,
487492
19A17FDB0B0CFB8987906FD0 /* SchemaChangerTests.swift */,
488493
19A17CA1DF7D0F7C9A94C51C /* Connection+SchemaTests.swift */,
@@ -998,6 +1003,7 @@
9981003
19A17FACE8E4D54A50BA934E /* FTS5Tests.swift in Sources */,
9991004
19A177909023B7B940C5805E /* FTSIntegrationTests.swift in Sources */,
10001005
19A17E1DD976D5CE80018749 /* FTS4Tests.swift in Sources */,
1006+
DBB93D5C2A22A373009BB96E /* SchemaReaderTests.swift in Sources */,
10011007
19A17411403D60640467209E /* ExpressionTests.swift in Sources */,
10021008
19A17CA4D7B63D845428A9C5 /* StatementTests.swift in Sources */,
10031009
19A17885B646CB0201BE4BD5 /* QueryTests.swift in Sources */,
@@ -1119,6 +1125,7 @@
11191125
19A178DA2BB5970778CCAF13 /* FTS5Tests.swift in Sources */,
11201126
19A1755C49154C87304C9146 /* FTSIntegrationTests.swift in Sources */,
11211127
19A17444861E1443143DEB44 /* FTS4Tests.swift in Sources */,
1128+
DBB93D5A2A22A373009BB96E /* SchemaReaderTests.swift in Sources */,
11221129
19A17DD33C2E43DD6EE05A60 /* ExpressionTests.swift in Sources */,
11231130
19A17D6EC40BC35A5DC81BA8 /* StatementTests.swift in Sources */,
11241131
19A17E3F47DA087E2B76D087 /* QueryTests.swift in Sources */,
@@ -1199,6 +1206,7 @@
11991206
19A1776BD5127DFDF847FF1F /* FTS5Tests.swift in Sources */,
12001207
19A173088B85A7E18E8582A7 /* FTSIntegrationTests.swift in Sources */,
12011208
19A178767223229E61C5066F /* FTS4Tests.swift in Sources */,
1209+
DBB93D5B2A22A373009BB96E /* SchemaReaderTests.swift in Sources */,
12021210
19A1781CBA8968ABD3E00877 /* ExpressionTests.swift in Sources */,
12031211
19A17923494236793893BF72 /* StatementTests.swift in Sources */,
12041212
19A17A52BF29D27C9AA229E7 /* QueryTests.swift in Sources */,

Sources/SQLite/Schema/SchemaDefinitions.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public struct ColumnDefinition: Equatable {
107107
public struct ForeignKey: Equatable {
108108
let table: String
109109
let column: String
110-
let primaryKey: String
110+
let primaryKey: String?
111111
let onUpdate: String?
112112
let onDelete: String?
113113
}
@@ -365,7 +365,7 @@ extension ColumnDefinition.ForeignKey {
365365
([
366366
"REFERENCES",
367367
table.quote(),
368-
"(\(primaryKey.quote()))",
368+
primaryKey.map { "(\($0.quote()))" },
369369
onUpdate.map { "ON UPDATE \($0)" },
370370
onDelete.map { "ON DELETE \($0)" }
371371
] as [String?]).compactMap { $0 }

Sources/SQLite/Schema/SchemaReader.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ private enum ForeignKeyListTable {
187187
static let seqColumn = Expression<Int64>("seq")
188188
static let tableColumn = Expression<String>("table")
189189
static let fromColumn = Expression<String>("from")
190-
static let toColumn = Expression<String>("to")
190+
static let toColumn = Expression<String?>("to") // when null, use primary key
191191
static let onUpdateColumn = Expression<String>("on_update")
192192
static let onDeleteColumn = Expression<String>("on_delete")
193193
static let matchColumn = Expression<String>("match")

Tests/SQLiteTests/Schema/SchemaReaderTests.swift

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,44 @@ class SchemaReaderTests: SQLiteTestCase {
135135
])
136136
}
137137

138+
func test_foreignKeys_references_column() throws {
139+
let sql = """
140+
CREATE TABLE artist(
141+
artistid INTEGER PRIMARY KEY,
142+
artistname TEXT
143+
);
144+
CREATE TABLE track(
145+
trackid INTEGER,
146+
trackname TEXT,
147+
trackartist INTEGER REFERENCES artist(artistid)
148+
);
149+
"""
150+
try db.execute(sql)
151+
let trackColumns = try db.schema.foreignKeys(table: "track")
152+
XCTAssertEqual(trackColumns.map { $0.toSQL() }.joined(separator: "\n"), """
153+
REFERENCES "artist" ("artistid")
154+
""")
155+
}
156+
157+
func test_foreignKeys_references_null_column() throws {
158+
let sql = """
159+
CREATE TABLE artist(
160+
artistid INTEGER PRIMARY KEY,
161+
artistname TEXT
162+
);
163+
CREATE TABLE track(
164+
trackid INTEGER,
165+
trackname TEXT,
166+
trackartist INTEGER REFERENCES artist
167+
);
168+
"""
169+
try db.execute(sql)
170+
let trackColumns = try db.schema.foreignKeys(table: "track")
171+
XCTAssertEqual(trackColumns.map { $0.toSQL() }.joined(separator: "\n"), """
172+
REFERENCES "artist"
173+
""")
174+
}
175+
138176
func test_tableDefinitions() throws {
139177
let tables = try schemaReader.tableDefinitions()
140178
XCTAssertEqual(tables.count, 1)

0 commit comments

Comments
 (0)