Skip to content

Commit c3ee476

Browse files
committed
fix: handle NULL primary key value with IS NULL in WHERE clause
1 parent 51909d6 commit c3ee476

2 files changed

Lines changed: 22 additions & 2 deletions

File tree

TablePro/Core/Utilities/SQL/SQLRowToStatementConverter.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ struct SQLRowToStatementConverter {
4949
return "\(quoteColumn(col)) = \(formatValue(value))"
5050
}
5151
setClause = setClauses.joined(separator: ", ")
52-
whereClause = "\(quoteColumn(pkColumn)) = \(formatValue(pkValue))"
52+
if pkValue == nil {
53+
whereClause = "\(quoteColumn(pkColumn)) IS NULL"
54+
} else {
55+
whereClause = "\(quoteColumn(pkColumn)) = \(formatValue(pkValue))"
56+
}
5357
} else {
5458
let allClauses = columns.enumerated().map { index, col -> String in
5559
let value = row.indices.contains(index) ? row[index] : nil

TableProTests/Core/Utilities/SQLRowToStatementConverterTests.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
//
55

66
import Foundation
7-
import Testing
87
@testable import TablePro
8+
import Testing
99

1010
@Suite("SQL Row To Statement Converter")
1111
struct SQLRowToStatementConverterTests {
@@ -92,6 +92,13 @@ struct SQLRowToStatementConverterTests {
9292
#expect(result == "UPDATE `users` SET `id` = '1', `name` = NULL, `email` = 'alice@example.com' WHERE `id` = '1' AND `name` IS NULL AND `email` = 'alice@example.com';")
9393
}
9494

95+
@Test("UPDATE with PK uses IS NULL in WHERE when PK value is NULL")
96+
func updateNullPrimaryKeyValue() {
97+
let converter = makeConverter()
98+
let result = converter.generateUpdates(rows: [[nil, "Alice", "alice@example.com"]])
99+
#expect(result == "UPDATE `users` SET `name` = 'Alice', `email` = 'alice@example.com' WHERE `id` IS NULL;")
100+
}
101+
95102
// MARK: - Database-Specific Quoting
96103

97104
@Test("ClickHouse uses ALTER TABLE ... UPDATE syntax")
@@ -122,6 +129,15 @@ struct SQLRowToStatementConverterTests {
122129
#expect(result == "INSERT INTO `users` (`id`, `name`, `email`) VALUES ('1', 'Alice', 'alice@example.com');")
123130
}
124131

132+
@Test("DuckDB uses double-quote quoting and standard UPDATE syntax")
133+
func duckdbUsesDoubleQuoteAndStandardUpdate() {
134+
let converter = makeConverter(databaseType: .duckdb)
135+
let insert = converter.generateInserts(rows: [["1", "Alice", "alice@example.com"]])
136+
#expect(insert == "INSERT INTO \"users\" (\"id\", \"name\", \"email\") VALUES ('1', 'Alice', 'alice@example.com');")
137+
let update = converter.generateUpdates(rows: [["1", "Alice", "alice@example.com"]])
138+
#expect(update == "UPDATE \"users\" SET \"name\" = 'Alice', \"email\" = 'alice@example.com' WHERE \"id\" = '1';")
139+
}
140+
125141
// MARK: - Edge Cases
126142

127143
@Test("Empty rows input returns empty string")

0 commit comments

Comments
 (0)