Skip to content

Commit b00608c

Browse files
committed
fix: address CodeRabbit review feedback
- Remove force-unwrap in SQLFormatterService majorKeywordRegex match - Add explicit internal access control on TableReference - Cap DDL highlight regex to 10k characters for large DDL safety - Fix CRLF double-counting in CellOverlayEditor newline counter - Invalidate queryBuildingDriverCache on plugin register/uninstall - Use DispatchQueue.main.async for isUpdatingColumnLayout flag reset
1 parent e24b15e commit b00608c

6 files changed

Lines changed: 24 additions & 10 deletions

File tree

TablePro/Core/Autocomplete/SQLContextAnalyzer.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ enum SQLClauseType {
4141
}
4242

4343
/// Represents a table reference with optional alias
44-
struct TableReference: Hashable, Sendable {
44+
internal struct TableReference: Hashable, Sendable {
4545
let tableName: String
4646
let alias: String?
4747

TablePro/Core/Plugins/PluginManager.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ final class PluginManager {
209209

210210
Self.logger.info("Loaded plugin '\(entry.name)' v\(entry.version) [\(item.source == .builtIn ? "built-in" : "user")]")
211211
}
212+
213+
queryBuildingDriverCache.removeAll()
212214
}
213215

214216
private func discoverAllPlugins() {
@@ -249,6 +251,7 @@ final class PluginManager {
249251
}
250252
}
251253

254+
queryBuildingDriverCache.removeAll()
252255
hasFinishedInitialLoad = true
253256
validateDependencies()
254257
Self.logger.info("Loaded \(self.plugins.count) plugin(s): \(self.driverPlugins.count) driver(s), \(self.exportPlugins.count) export format(s), \(self.importPlugins.count) import format(s)")
@@ -627,15 +630,19 @@ final class PluginManager {
627630
let typeId = databaseType.pluginTypeId
628631
if let cached = queryBuildingDriverCache[typeId] { return cached }
629632
guard let plugin = driverPlugin(for: databaseType) else {
630-
queryBuildingDriverCache[typeId] = .some(nil)
633+
if hasFinishedInitialLoad {
634+
queryBuildingDriverCache[typeId] = .some(nil)
635+
}
631636
return nil
632637
}
633638
let config = DriverConnectionConfig(host: "", port: 0, username: "", password: "", database: "")
634639
let driver = plugin.createDriver(config: config)
635640
let result: (any PluginDatabaseDriver)? =
636641
driver.buildBrowseQuery(table: "_probe", sortColumns: [], columns: [], limit: 1, offset: 0) != nil
637642
? driver : nil
638-
queryBuildingDriverCache[typeId] = .some(result)
643+
if hasFinishedInitialLoad {
644+
queryBuildingDriverCache[typeId] = .some(result)
645+
}
639646
return result
640647
}
641648

@@ -1013,6 +1020,8 @@ final class PluginManager {
10131020
disabled.remove(id)
10141021
disabledPluginIds = disabled
10151022

1023+
queryBuildingDriverCache.removeAll()
1024+
10161025
Self.logger.info("Uninstalled plugin '\(id)'")
10171026
_needsRestart = true
10181027
}

TablePro/Core/Services/Formatting/SQLFormatterService.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -480,8 +480,9 @@ struct SQLFormatterService: SQLFormatterProtocol {
480480
let searchNSRange = NSRange(searchStart..<sql.endIndex, in: sql)
481481
var endIndex = sql.endIndex
482482

483-
if let match = Self.majorKeywordRegex.firstMatch(in: sql, range: searchNSRange) {
484-
endIndex = Range(match.range, in: sql)!.lowerBound
483+
if let match = Self.majorKeywordRegex.firstMatch(in: sql, range: searchNSRange),
484+
let matchRange = Range(match.range, in: sql) {
485+
endIndex = matchRange.lowerBound
485486
}
486487

487488
// Fix #3: Work with immutable substring

TablePro/Views/Main/Child/MainEditorContentView.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,10 +454,12 @@ struct MainEditorContentView: View {
454454
get: { tab.columnLayout },
455455
set: { newValue in
456456
coordinator.isUpdatingColumnLayout = true
457-
defer { coordinator.isUpdatingColumnLayout = false }
458457
if let index = tabManager.selectedTabIndex {
459458
tabManager.tabs[index].columnLayout = newValue
460459
}
460+
DispatchQueue.main.async {
461+
coordinator.isUpdatingColumnLayout = false
462+
}
461463
}
462464
)
463465
}

TablePro/Views/Results/CellOverlayEditor.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ final class CellOverlayEditor: NSObject, NSTextViewDelegate {
5858
// Determine overlay height — at least the cell height, up to 120pt
5959
let lineHeight: CGFloat = ThemeEngine.shared.dataGridFonts.regular.boundingRectForFont.height + 4
6060
var newlineCount = 0
61-
for scalar in value.unicodeScalars {
62-
if CharacterSet.newlines.contains(scalar) { newlineCount += 1 }
61+
for scalar in value.unicodeScalars where scalar == "\n" {
62+
newlineCount += 1
6363
}
6464
let lineCount = CGFloat(newlineCount + 1)
6565
let contentHeight = max(lineCount * lineHeight + 8, cellRect.height)

TablePro/Views/Structure/DDLTextView.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,12 @@ struct DDLTextView: NSViewRepresentable {
105105
textStorage.addAttribute(.font, value: font, range: fullRange)
106106
textStorage.addAttribute(.foregroundColor, value: NSColor.labelColor, range: fullRange)
107107

108-
// Apply pre-compiled patterns
108+
// Apply pre-compiled patterns (cap to 10k chars for large DDL safety)
109109
let text = textStorage.string
110+
let highlightLength = min(textStorage.length, 10_000)
111+
let highlightRange = NSRange(location: 0, length: highlightLength)
110112
for (regex, color) in Self.syntaxPatterns {
111-
let matches = regex.matches(in: text, options: [], range: fullRange)
113+
let matches = regex.matches(in: text, options: [], range: highlightRange)
112114
for match in matches {
113115
textStorage.addAttribute(.foregroundColor, value: color, range: match.range)
114116
}

0 commit comments

Comments
 (0)