Skip to content

Commit 2dbcdcc

Browse files
committed
feat(import): include redisDatabase in dedup key for Redis connections
1 parent bc5079f commit 2dbcdcc

2 files changed

Lines changed: 107 additions & 2 deletions

File tree

TablePro/Core/Services/Export/ConnectionExportService.swift

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -886,7 +886,7 @@ enum ConnectionExportService {
886886
components: [
887887
normalizedLookupKey(connection.host),
888888
String(connection.port),
889-
normalizedLookupKey(connection.database),
889+
effectiveDatabaseKey(database: connection.database, redisDatabase: connection.redisDatabase),
890890
normalizedLookupKey(connection.username)
891891
]
892892
)
@@ -897,12 +897,23 @@ enum ConnectionExportService {
897897
components: [
898898
normalizedLookupKey(connection.host),
899899
String(connection.port),
900-
normalizedLookupKey(connection.database),
900+
effectiveDatabaseKey(database: connection.database, redisDatabase: connection.redisDatabase),
901901
normalizedLookupKey(connection.username)
902902
]
903903
)
904904
}
905905

906+
private static func effectiveDatabaseKey(database: String?, redisDatabase: Int?) -> String {
907+
let normalized = normalizedLookupKey(database)
908+
if !normalized.isEmpty {
909+
return normalized
910+
}
911+
if let redisDatabase {
912+
return String(redisDatabase)
913+
}
914+
return ""
915+
}
916+
906917
private static func tagIdsByName() -> [String: UUID] {
907918
var idsByName: [String: UUID] = [:]
908919
for tag in TagStorage.shared.loadTags() {

TableProTests/Core/Services/ConnectionImportServiceTests.swift

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,100 @@ struct ConnectionImportServiceTests {
100100
}
101101
}
102102

103+
@Test("redis connections with different database indices are not duplicates")
104+
func redisConnectionsWithDifferentDatabaseIndicesAreNotDuplicates() {
105+
let existing = DatabaseConnection(
106+
name: "Redis DB 0",
107+
host: "redis.example.com",
108+
port: 6_379,
109+
username: "cache",
110+
type: .redis,
111+
redisDatabase: 0
112+
)
113+
let imported = ExportableConnection(
114+
name: "Redis DB 1",
115+
host: "redis.example.com",
116+
port: 6_379,
117+
database: "",
118+
username: "cache",
119+
type: "Redis",
120+
sshConfig: nil,
121+
sslConfig: nil,
122+
color: nil,
123+
tagName: nil,
124+
groupName: nil,
125+
sshProfileId: nil,
126+
safeModeLevel: nil,
127+
aiPolicy: nil,
128+
additionalFields: nil,
129+
redisDatabase: 1,
130+
startupCommands: nil,
131+
localOnly: nil
132+
)
133+
134+
let preview = ConnectionExportService.analyzeImport(
135+
makeEnvelope(with: [imported]),
136+
existingConnections: [existing],
137+
registeredTypeIds: Set(["Redis"]),
138+
fileExists: { _ in true }
139+
)
140+
141+
guard let item = preview.items.first else {
142+
Issue.record("Expected preview item")
143+
return
144+
}
145+
146+
if case .duplicate = item.status {
147+
Issue.record("Expected non-duplicate status for different Redis database indices")
148+
}
149+
}
150+
151+
@Test("redis connections with matching database indices are duplicates")
152+
func redisConnectionsWithMatchingDatabaseIndicesAreDuplicates() {
153+
let existing = DatabaseConnection(
154+
name: "Redis DB 0",
155+
host: "redis.example.com",
156+
port: 6_379,
157+
username: "cache",
158+
type: .redis,
159+
redisDatabase: 0
160+
)
161+
let imported = ExportableConnection(
162+
name: "Redis DB 0 Copy",
163+
host: "redis.example.com",
164+
port: 6_379,
165+
database: "",
166+
username: "cache",
167+
type: "Redis",
168+
sshConfig: nil,
169+
sslConfig: nil,
170+
color: nil,
171+
tagName: nil,
172+
groupName: nil,
173+
sshProfileId: nil,
174+
safeModeLevel: nil,
175+
aiPolicy: nil,
176+
additionalFields: nil,
177+
redisDatabase: 0,
178+
startupCommands: nil,
179+
localOnly: nil
180+
)
181+
182+
let preview = ConnectionExportService.analyzeImport(
183+
makeEnvelope(with: [imported]),
184+
existingConnections: [existing],
185+
registeredTypeIds: Set(["Redis"]),
186+
fileExists: { _ in true }
187+
)
188+
189+
guard case .duplicate(let matched) = preview.items.first?.status else {
190+
Issue.record("Expected duplicate status for matching Redis database indices")
191+
return
192+
}
193+
194+
#expect(matched.id == existing.id)
195+
}
196+
103197
@Test("replace updates the existing connection")
104198
func replaceUpdatesTheExistingConnection() {
105199
let storage = makeStorage()

0 commit comments

Comments
 (0)