From 8a9ed73a3af22fa6b18b9c954bcac07a34d8ced8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Fri, 11 Sep 2026 21:57:38 +0700 Subject: [PATCH 01/54] feat(datagrid): highlight rules that color rows or cells by value (#2738) Claude-Session: https://claude.ai/code/session_01WA4qjtY9TiRD6QuqhhW5Yr --- CHANGELOG.md | 2 + .../Core/DataGrid/DataGridDisplayState.swift | 1 + TablePro/Core/DataGrid/RowDisplayBox.swift | 22 ++ TablePro/Core/Menu/ViewMenuBuilder.swift | 4 + .../Highlight/HighlightCondition.swift | 275 ++++++++++++++++++ .../Services/Highlight/HighlightRuleSet.swift | 93 ++++++ ...inSplitViewController+MenuValidation.swift | 4 + ...nSplitViewController+ViewMenuActions.swift | 4 + .../Core/Storage/ConnectionLocalState.swift | 1 + .../Core/Storage/HighlightRuleStorage.swift | 179 ++++++++++++ TablePro/Models/Highlight/HighlightRule.swift | 139 +++++++++ .../Highlight/HighlightRuleDescription.swift | 67 +++++ TablePro/Models/Query/QueryTab.swift | 2 + TablePro/Models/Query/QueryTabState.swift | 2 + TablePro/Models/Query/ResultStatusModel.swift | 2 + .../Views/Components/ClosureMenuTarget.swift | 31 ++ .../Highlight/HighlightColor+AppKit.swift | 42 +++ .../Highlight/HighlightColumnOption.swift | 31 ++ .../Highlight/HighlightMenuBuilder.swift | 144 +++++++++ .../Views/Highlight/HighlightRuleRow.swift | 224 ++++++++++++++ .../Highlight/HighlightRulesPopover.swift | 144 +++++++++ .../Main/Child/DataTabGridDelegate.swift | 42 +++ .../Main/Child/MainEditorContentView.swift | 13 + .../Main/EditorTabContextMenuBuilder.swift | 23 +- ...ainContentCoordinator+HighlightRules.swift | 66 +++++ ...ainContentCoordinator+RenameAdoption.swift | 9 + .../Main/MainContentCommandActions.swift | 9 + .../Cells/DataGridCellAccessibilityView.swift | 15 +- .../Cells/DataGridCellAppearance.swift | 15 +- .../Views/Results/DataGridCoordinator.swift | 26 +- TablePro/Views/Results/DataGridRowView.swift | 34 +-- .../Results/DataGridUpdateSnapshot.swift | 1 + TablePro/Views/Results/DataGridView.swift | 38 ++- .../Views/Results/DataGridViewDelegate.swift | 4 + .../Extensions/DataGridView+CellCommit.swift | 1 + .../Extensions/DataGridView+Columns.swift | 10 +- .../DataGridView+RowDecoration.swift | 77 +++++ .../Extensions/DataGridView+Sort.swift | 5 + TablePro/Views/Results/ResultStatusBar.swift | 51 ++++ .../Views/Results/ResultStatusInputs.swift | 18 ++ .../Structure/StructureGridDelegate.swift | 7 - .../Structure/StructureRowViewWithMenu.swift | 4 +- .../Core/DataGrid/RowDisplayCacheTests.swift | 21 ++ .../Core/Menu/MainMenuBuilderTests.swift | 16 +- .../Highlight/HighlightConditionTests.swift | 147 ++++++++++ .../Highlight/HighlightRuleSetTests.swift | 176 +++++++++++ .../Storage/HighlightRuleStorageTests.swift | 132 +++++++++ .../Models/ResultStatusModelTests.swift | 15 + .../Main/ResultStatusBarLayoutTests.swift | 8 + .../Results/DataGridCellAppearanceTests.swift | 66 +++++ .../Results/DataGridRowTintThemeTests.swift | 98 ++++++- .../Results/DataGridUpdateSnapshotTests.swift | 16 + .../TableViewCoordinatorHighlightTests.swift | 145 +++++++++ TableProUITests/HighlightRulesUITests.swift | 106 +++++++ docs/features/data-grid.mdx | 21 +- docs/images/highlight-rules-dark.png | Bin 0 -> 1884022 bytes docs/images/highlight-rules.png | Bin 0 -> 1873775 bytes 57 files changed, 2747 insertions(+), 101 deletions(-) create mode 100644 TablePro/Core/Services/Highlight/HighlightCondition.swift create mode 100644 TablePro/Core/Services/Highlight/HighlightRuleSet.swift create mode 100644 TablePro/Core/Storage/HighlightRuleStorage.swift create mode 100644 TablePro/Models/Highlight/HighlightRule.swift create mode 100644 TablePro/Models/Highlight/HighlightRuleDescription.swift create mode 100644 TablePro/Views/Components/ClosureMenuTarget.swift create mode 100644 TablePro/Views/Highlight/HighlightColor+AppKit.swift create mode 100644 TablePro/Views/Highlight/HighlightColumnOption.swift create mode 100644 TablePro/Views/Highlight/HighlightMenuBuilder.swift create mode 100644 TablePro/Views/Highlight/HighlightRuleRow.swift create mode 100644 TablePro/Views/Highlight/HighlightRulesPopover.swift create mode 100644 TablePro/Views/Main/Extensions/MainContentCoordinator+HighlightRules.swift create mode 100644 TablePro/Views/Results/Extensions/DataGridView+RowDecoration.swift create mode 100644 TableProTests/Core/Services/Highlight/HighlightConditionTests.swift create mode 100644 TableProTests/Core/Services/Highlight/HighlightRuleSetTests.swift create mode 100644 TableProTests/Core/Storage/HighlightRuleStorageTests.swift create mode 100644 TableProTests/Views/Results/TableViewCoordinatorHighlightTests.swift create mode 100644 TableProUITests/HighlightRulesUITests.swift create mode 100644 docs/images/highlight-rules-dark.png create mode 100644 docs/images/highlight-rules.png diff --git a/CHANGELOG.md b/CHANGELOG.md index c1e1e9b898..9e4f662a82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **Remove Invisible Characters** in the Query menu. (#2717) - **Show invisible characters** in Settings > Editor. (#2717) - Warnings in the SQL editor for full-width punctuation, curly quotes and non-ASCII spaces. (#2717) +- Highlight rules that color data grid rows or cells by value. (#2723) ### Changed @@ -42,6 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Blank welcome window list when a search matched nothing and a favorite existed. - Welcome window reading No Connections while a tag filter hid every connection. - Favorited connection inside a group listed twice on the welcome window. +- Missing red wash on a row deleted together with a new, unsaved row. - Welcome window tag filter stuck on a tag no connection carries any more, hiding every connection. - Collapsing every group on the welcome window undone at the next launch. - Linked Folders and Team Library connections ignoring the welcome window search, with no context menu. diff --git a/TablePro/Core/DataGrid/DataGridDisplayState.swift b/TablePro/Core/DataGrid/DataGridDisplayState.swift index ddb718ca36..b4f23d2920 100644 --- a/TablePro/Core/DataGrid/DataGridDisplayState.swift +++ b/TablePro/Core/DataGrid/DataGridDisplayState.swift @@ -50,4 +50,5 @@ final class DataGridDisplayState { /// reports a schema and a format change and clears the text it was just handed. var identitySchema: ColumnIdentitySchema? var displayFormats: [ValueDisplayFormat?]? + var highlightRuleSetKey: HighlightRuleSet.Key? } diff --git a/TablePro/Core/DataGrid/RowDisplayBox.swift b/TablePro/Core/DataGrid/RowDisplayBox.swift index b4f475587c..99f39e1bd2 100644 --- a/TablePro/Core/DataGrid/RowDisplayBox.swift +++ b/TablePro/Core/DataGrid/RowDisplayBox.swift @@ -25,6 +25,7 @@ final class RowDisplayCache { } private var storage: [RowID: Entry] = [:] + private var highlights: [RowID: RowHighlight] = [:] private var insertionOrder: [RowID] = [] private var insertionHead: Int = 0 private var totalCost: Int = 0 @@ -52,8 +53,28 @@ final class RowDisplayCache { evictIfNeeded() } + func highlight(forID id: RowID) -> RowHighlight? { + highlights[id] + } + + func setHighlight(_ highlight: RowHighlight, forID id: RowID) { + if highlights.count >= countLimit { + highlights.removeAll(keepingCapacity: true) + } + highlights[id] = highlight + } + + func clearHighlight(forID id: RowID) { + highlights.removeValue(forKey: id) + } + + func clearHighlights() { + highlights.removeAll(keepingCapacity: true) + } + func removeAll() { storage.removeAll(keepingCapacity: true) + highlights.removeAll(keepingCapacity: true) insertionOrder.removeAll(keepingCapacity: true) insertionHead = 0 totalCost = 0 @@ -64,6 +85,7 @@ final class RowDisplayCache { /// whose content changed in place keeps its id and would otherwise be served /// its pre-edit text. func clearValues(forID id: RowID) { + highlights.removeValue(forKey: id) guard let existing = storage[id] else { return } totalCost -= existing.cost for index in existing.box.values.indices { diff --git a/TablePro/Core/Menu/ViewMenuBuilder.swift b/TablePro/Core/Menu/ViewMenuBuilder.swift index b6545cdf8c..16a2d8d11a 100644 --- a/TablePro/Core/Menu/ViewMenuBuilder.swift +++ b/TablePro/Core/Menu/ViewMenuBuilder.swift @@ -71,6 +71,10 @@ enum ViewMenuBuilder { shortcut: .toggleFilters, keyboard: keyboard ), + MenuItemFactory.item( + String(localized: "Highlight Rules…"), + action: #selector(MainSplitViewController.showHighlightRules(_:)) + ), MenuItemFactory.item( String(localized: "Show Query History"), action: #selector(MainSplitViewController.toggleQueryHistory(_:)), diff --git a/TablePro/Core/Services/Highlight/HighlightCondition.swift b/TablePro/Core/Services/Highlight/HighlightCondition.swift new file mode 100644 index 0000000000..2f16f6e85c --- /dev/null +++ b/TablePro/Core/Services/Highlight/HighlightCondition.swift @@ -0,0 +1,275 @@ +// +// HighlightCondition.swift +// TablePro +// + +import Foundation +import TableProPluginKit + +struct HighlightCondition { + static let searchLimit = 10_000 + + private enum ValueKind { + case numeric + case boolean + case text + } + + private struct Operand { + let text: String + let number: Decimal? + let boolean: Bool? + let isNullLiteral: Bool + + init(_ raw: String, allowsNullLiteral: Bool) { + let trimmed = raw.trimmingCharacters(in: .whitespaces) + text = raw + number = HighlightCondition.number(from: trimmed) + boolean = HighlightCondition.boolean(from: trimmed) + isNullLiteral = allowsNullLiteral && HighlightCondition.isNullKeyword(trimmed) + } + } + + private let filterOperator: FilterOperator + private let valueKind: ValueKind + private let comparesCaseInsensitively: Bool + private let supportsEmptyString: Bool + private let operand: Operand + private let secondOperand: Operand + private let listOperands: [Operand] + private let regex: NSRegularExpression? + + init(rule: HighlightRule, columnType: ColumnType?) { + filterOperator = rule.filterOperator + valueKind = Self.valueKind(for: columnType) + comparesCaseInsensitively = rule.filterOperator.supportsCaseSensitivity && !rule.isCaseSensitive + supportsEmptyString = ColumnTypeSQLQuoting.supportsEmptyStringComparison(columnType) + + let allowsNullLiteral = Self.allowsNullLiteral(for: columnType) + operand = Operand(rule.value, allowsNullLiteral: allowsNullLiteral) + secondOperand = Operand(rule.secondValue ?? "", allowsNullLiteral: allowsNullLiteral) + listOperands = rule.filterOperator == .inList || rule.filterOperator == .notInList + ? Self.listItems(rule.value).map { Operand($0, allowsNullLiteral: allowsNullLiteral) } + : [] + regex = rule.filterOperator == .regex + ? Self.regularExpression(rule.value, ignoresCase: comparesCaseInsensitively) + : nil + } + + func matches(_ value: PluginCellValue) -> Bool { + switch value { + case .null: + return matchesNull() + case .bytes: + return matchesBinary() + case .text(let text): + return matches(text: text) + } + } + + private func matchesNull() -> Bool { + switch filterOperator { + case .isNull, .isEmpty: + return true + case .equal: + return operand.isNullLiteral + case .inList: + return listOperands.contains { $0.isNullLiteral } + case .notEqual, .contains, .notContains, .startsWith, .endsWith, .greaterThan, .greaterOrEqual, + .lessThan, .lessOrEqual, .isNotNull, .isNotEmpty, .notInList, .between, .regex: + return false + } + } + + private func matchesBinary() -> Bool { + switch filterOperator { + case .isNotNull, .isNotEmpty: + return true + case .isNull, .isEmpty, .equal, .notEqual, .contains, .notContains, .startsWith, .endsWith, + .greaterThan, .greaterOrEqual, .lessThan, .lessOrEqual, .inList, .notInList, .between, .regex: + return false + } + } + + private func matches(text: String) -> Bool { + switch filterOperator { + case .equal: + return !operand.isNullLiteral && order(text, against: operand) == .orderedSame + case .notEqual: + return operand.isNullLiteral || order(text, against: operand) != .orderedSame + case .contains: + return contains(text) + case .notContains: + return !contains(text) + case .startsWith: + return hasAffix(text, anchoredAtEnd: false) + case .endsWith: + return hasAffix(text, anchoredAtEnd: true) + case .greaterThan: + return !operand.isNullLiteral && order(text, against: operand) == .orderedDescending + case .greaterOrEqual: + return !operand.isNullLiteral && order(text, against: operand) != .orderedAscending + case .lessThan: + return !operand.isNullLiteral && order(text, against: operand) == .orderedAscending + case .lessOrEqual: + return !operand.isNullLiteral && order(text, against: operand) != .orderedDescending + case .isNull: + return false + case .isNotNull: + return true + case .isEmpty: + return supportsEmptyString && text.isEmpty + case .isNotEmpty: + return !supportsEmptyString || !text.isEmpty + case .inList: + return listOperands.contains { !$0.isNullLiteral && order(text, against: $0) == .orderedSame } + case .notInList: + let values = listOperands.filter { !$0.isNullLiteral } + return !values.isEmpty && !values.contains { order(text, against: $0) == .orderedSame } + case .between: + return order(text, against: operand) != .orderedAscending + && order(text, against: secondOperand) != .orderedDescending + case .regex: + return matchesRegex(text) + } + } + + private func order(_ text: String, against operand: Operand) -> ComparisonResult { + if prefersNumbers, let lhs = Self.number(from: text), let rhs = operand.number { + return Self.compare(lhs, rhs) + } + if prefersBooleans, let lhs = Self.boolean(from: text), let rhs = operand.boolean { + return Self.compare(lhs ? 1 : 0, rhs ? 1 : 0) + } + return text.compare(operand.text, options: comparesCaseInsensitively ? [.caseInsensitive] : [.literal]) + } + + private var prefersNumbers: Bool { + switch valueKind { + case .numeric: + return true + case .boolean: + return false + case .text: + return isOrderingOperator + } + } + + private var prefersBooleans: Bool { + switch valueKind { + case .numeric, .boolean: + return true + case .text: + return false + } + } + + private var isOrderingOperator: Bool { + switch filterOperator { + case .greaterThan, .greaterOrEqual, .lessThan, .lessOrEqual, .between: + return true + case .equal, .notEqual, .contains, .notContains, .startsWith, .endsWith, .isNull, .isNotNull, + .isEmpty, .isNotEmpty, .inList, .notInList, .regex: + return false + } + } + + private var searchOptions: String.CompareOptions { + comparesCaseInsensitively ? [.caseInsensitive] : [.literal] + } + + private func contains(_ text: String) -> Bool { + guard !operand.text.isEmpty else { return true } + return Self.searchable(text).range(of: operand.text, options: searchOptions) != nil + } + + private func hasAffix(_ text: String, anchoredAtEnd: Bool) -> Bool { + guard !operand.text.isEmpty else { return true } + let options = searchOptions.union(anchoredAtEnd ? [.anchored, .backwards] : [.anchored]) + return text.range(of: operand.text, options: options) != nil + } + + private func matchesRegex(_ text: String) -> Bool { + guard let regex else { return false } + let searchable = Self.searchable(text) as NSString + return regex.firstMatch( + in: searchable as String, + options: [], + range: NSRange(location: 0, length: searchable.length) + ) != nil + } + + private static func searchable(_ text: String) -> String { + let source = text as NSString + guard source.length > searchLimit else { return text } + let cut = source.rangeOfComposedCharacterSequence(at: searchLimit).location + return source.substring(to: cut) + } + + private static func regularExpression(_ pattern: String, ignoresCase: Bool) -> NSRegularExpression? { + guard !pattern.isEmpty, (pattern as NSString).length <= searchLimit else { return nil } + return try? NSRegularExpression(pattern: pattern, options: ignoresCase ? [.caseInsensitive] : []) + } + + private static func valueKind(for columnType: ColumnType?) -> ValueKind { + switch columnType { + case .integer, .decimal: + return .numeric + case .boolean: + return .boolean + case .text, .date, .timestamp, .datetime, .blob, .json, .enumType, .set, .spatial, .array, .none: + return .text + } + } + + private static func listItems(_ input: String) -> [String] { + input.split(separator: ",", omittingEmptySubsequences: true).compactMap { + let trimmed = $0.trimmingCharacters(in: .whitespaces) + return trimmed.isEmpty ? nil : trimmed + } + } + + static func readsAsNullLiteral(_ text: String, columnType: ColumnType?) -> Bool { + allowsNullLiteral(for: columnType) && isNullKeyword(text.trimmingCharacters(in: .whitespaces)) + } + + private static func allowsNullLiteral(for columnType: ColumnType?) -> Bool { + !ColumnTypeSQLQuoting.isKnownTextLike(columnType) + } + + private static func isNullKeyword(_ text: String) -> Bool { + text.caseInsensitiveCompare("NULL") == .orderedSame + } + + static func number(from text: String) -> Decimal? { + let trimmed = text.trimmingCharacters(in: .whitespaces) + guard PluginNumericLiteral.isValid(trimmed) else { return nil } + return Decimal(string: trimmed, locale: Locale(identifier: "en_US_POSIX")) + } + + static func boolean(from text: String) -> Bool? { + let trimmed = text.trimmingCharacters(in: .whitespaces) + switch PluginSQLLiteral.booleanSynonym(for: trimmed) { + case .isTrue: + return true + case .isFalse: + return false + default: + break + } + switch trimmed.lowercased() { + case "t": + return true + case "f": + return false + default: + return nil + } + } + + private static func compare(_ lhs: Value, _ rhs: Value) -> ComparisonResult { + if lhs < rhs { return .orderedAscending } + if lhs > rhs { return .orderedDescending } + return .orderedSame + } +} diff --git a/TablePro/Core/Services/Highlight/HighlightRuleSet.swift b/TablePro/Core/Services/Highlight/HighlightRuleSet.swift new file mode 100644 index 0000000000..15cb302910 --- /dev/null +++ b/TablePro/Core/Services/Highlight/HighlightRuleSet.swift @@ -0,0 +1,93 @@ +// +// HighlightRuleSet.swift +// TablePro +// + +import Foundation +import TableProPluginKit + +struct HighlightRuleSet { + struct Key: Equatable { + let rules: [HighlightRule] + let columns: [String] + let columnTypes: [ColumnType] + } + + private struct CompiledRule { + let rule: HighlightRule + let column: Int + let condition: HighlightCondition + } + + let key: Key + let unresolvedRuleIDs: Set + private let rowRules: [CompiledRule] + private let cellRules: [CompiledRule] + + static let empty = HighlightRuleSet(rules: [], columns: [], columnTypes: []) + + init(rules: [HighlightRule], columns: [String], columnTypes: [ColumnType]) { + key = Key(rules: rules, columns: columns, columnTypes: columnTypes) + + var rowRules: [CompiledRule] = [] + var cellRules: [CompiledRule] = [] + var unresolved = Set() + for rule in rules where rule.isEnabled && rule.isValid { + guard let column = Self.columnIndex( + named: rule.columnName, + occurrence: rule.columnOccurrence, + in: columns + ) else { + unresolved.insert(rule.id) + continue + } + let columnType = column < columnTypes.count ? columnTypes[column] : nil + let compiled = CompiledRule( + rule: rule, + column: column, + condition: HighlightCondition(rule: rule, columnType: columnType) + ) + switch rule.target { + case .row: + rowRules.append(compiled) + case .cell: + cellRules.append(compiled) + } + } + self.rowRules = rowRules + self.cellRules = cellRules + self.unresolvedRuleIDs = unresolved + } + + var isEmpty: Bool { rowRules.isEmpty && cellRules.isEmpty } + + func highlight(for values: ContiguousArray) -> RowHighlight { + guard !isEmpty else { return .none } + let rowRule = rowRules.first { Self.matches($0, in: values) }?.rule + var matchedCells: [Int: HighlightRule] = [:] + for compiled in cellRules where matchedCells[compiled.column] == nil && Self.matches(compiled, in: values) { + matchedCells[compiled.column] = compiled.rule + } + return RowHighlight(rowRule: rowRule, cellRules: matchedCells) + } + + static func columnIndex(named name: String, occurrence: Int, in columns: [String]) -> Int? { + var seen = 0 + for (index, column) in columns.enumerated() where column == name { + if seen == occurrence { return index } + seen += 1 + } + return nil + } + + static func occurrence(ofColumnAt index: Int, in columns: [String]) -> Int { + guard index >= 0, index < columns.count else { return 0 } + let name = columns[index] + return columns[..) -> Bool { + guard compiled.column < values.count else { return false } + return compiled.condition.matches(values[compiled.column]) + } +} diff --git a/TablePro/Core/Services/Infrastructure/MainSplitViewController+MenuValidation.swift b/TablePro/Core/Services/Infrastructure/MainSplitViewController+MenuValidation.swift index 2a11ff404c..997bf4727f 100644 --- a/TablePro/Core/Services/Infrastructure/MainSplitViewController+MenuValidation.swift +++ b/TablePro/Core/Services/Infrastructure/MainSplitViewController+MenuValidation.swift @@ -21,6 +21,7 @@ struct MenuValidationContext: Equatable { var canUseGridFindCommands = false /// Jump to Column reads the mounted data grid, so it needs one on screen with columns to list. var canJumpToColumn = false + var canPresentHighlightRules = false /// Save As writes the selected tab's SQL, so it needs a query tab and not merely a connection. var isQueryTab = false /// Export Results exports the selected tab's rows, so an empty grid has nothing to offer. @@ -261,6 +262,8 @@ extension MainSplitViewController: NSMenuItemValidation { case #selector(toggleFilterBar(_:)): return context.isConnected && context.canUseTableResultCommands + case #selector(showHighlightRules(_:)): + return context.isConnected && context.canPresentHighlightRules case #selector(pinResult(_:)): return context.canPinResultTab case #selector(navigateBack(_:)): @@ -298,6 +301,7 @@ extension MainSplitViewController: NSMenuItemValidation { canUseTableResultCommands: actions.canUseTableResultCommands, canUseGridFindCommands: actions.canUseGridFindCommands, canJumpToColumn: actions.canJumpToColumn, + canPresentHighlightRules: actions.canPresentHighlightRules, isQueryTab: actions.isQueryTab, hasResultRows: actions.hasResultRows, isCurrentTabEditable: actions.isCurrentTabEditable, diff --git a/TablePro/Core/Services/Infrastructure/MainSplitViewController+ViewMenuActions.swift b/TablePro/Core/Services/Infrastructure/MainSplitViewController+ViewMenuActions.swift index 39f1496233..882d26cfbb 100644 --- a/TablePro/Core/Services/Infrastructure/MainSplitViewController+ViewMenuActions.swift +++ b/TablePro/Core/Services/Infrastructure/MainSplitViewController+ViewMenuActions.swift @@ -63,6 +63,10 @@ extension MainSplitViewController { commandActions?.toggleFilterPanel() } + @objc func showHighlightRules(_ sender: Any?) { + commandActions?.showHighlightRules() + } + @objc func toggleQueryHistory(_ sender: Any?) { commandActions?.toggleHistoryPanel() } diff --git a/TablePro/Core/Storage/ConnectionLocalState.swift b/TablePro/Core/Storage/ConnectionLocalState.swift index 35a481283c..0891c8ab73 100644 --- a/TablePro/Core/Storage/ConnectionLocalState.swift +++ b/TablePro/Core/Storage/ConnectionLocalState.swift @@ -38,6 +38,7 @@ internal enum ConnectionLocalState { } FilterSettingsStorage.shared.removeFilters(for: connectionIds) + HighlightRuleStorage.shared.removeRules(for: connectionIds) DatabaseTreeFilterStorage.shared.removeFilters(for: connectionIds) RecentlyClosedTabStore.shared.removeEntries(for: connectionIds) WorkspaceRailOrderStore.shared.removeEntries(for: connectionIds) diff --git a/TablePro/Core/Storage/HighlightRuleStorage.swift b/TablePro/Core/Storage/HighlightRuleStorage.swift new file mode 100644 index 0000000000..ae2ba5bad7 --- /dev/null +++ b/TablePro/Core/Storage/HighlightRuleStorage.swift @@ -0,0 +1,179 @@ +// +// HighlightRuleStorage.swift +// TablePro +// + +import Foundation +import Observation +import os + +@MainActor +@Observable +final class HighlightRuleStorage { + static let shared = HighlightRuleStorage() + + nonisolated private static let logger = Logger( + subsystem: "com.TablePro", + category: "HighlightRuleStorage" + ) + + private(set) var revision = 0 + + @ObservationIgnored private let storageDirectory: URL + @ObservationIgnored private var cache: [UUID: [String: [HighlightRule]]] = [:] + @ObservationIgnored private let encoder: JSONEncoder = { + let encoder = JSONEncoder() + encoder.outputFormatting = [.sortedKeys] + return encoder + }() + @ObservationIgnored private let decoder = JSONDecoder() + + init(storageDirectory: URL? = nil) { + self.storageDirectory = storageDirectory ?? Self.resolvedStorageDirectory() + do { + try FileManager.default.createDirectory(at: self.storageDirectory, withIntermediateDirectories: true) + } catch { + Self.logger.error("Failed to create storage directory: \(error.localizedDescription)") + } + } + + func rules(for scope: TableScope) -> [HighlightRule] { + _ = revision + return loadEntries(for: scope.connectionId)[scope.storageComponent] ?? [] + } + + func setRules(_ rules: [HighlightRule], for scope: TableScope) { + var entries = loadEntries(for: scope.connectionId) + guard entries[scope.storageComponent, default: []] != rules else { return } + if rules.isEmpty { + entries.removeValue(forKey: scope.storageComponent) + } else { + entries[scope.storageComponent] = rules + } + commit(entries, for: scope.connectionId) + } + + func rename(from oldScope: TableScope, to newScope: TableScope) { + guard oldScope.storageComponent != newScope.storageComponent else { return } + var entries = loadEntries(for: oldScope.connectionId) + guard let moving = entries.removeValue(forKey: oldScope.storageComponent) else { return } + entries[newScope.storageComponent] = moving + commit(entries, for: oldScope.connectionId) + } + + func renameScope( + connectionId: UUID, + fromDatabase: String, + fromSchema: String?, + toDatabase: String, + toSchema: String? + ) { + let oldPrefix = TableScope.storagePrefix(connectionId: connectionId, database: fromDatabase, schema: fromSchema) + let newPrefix = TableScope.storagePrefix(connectionId: connectionId, database: toDatabase, schema: toSchema) + guard oldPrefix != newPrefix else { return } + + var entries = loadEntries(for: connectionId) + let moving = entries.keys.filter { $0.hasPrefix(oldPrefix) } + guard !moving.isEmpty else { return } + for key in moving { + entries[newPrefix + key.dropFirst(oldPrefix.count)] = entries.removeValue(forKey: key) + } + commit(entries, for: connectionId) + } + + func removeRules(for connectionIds: Set) { + guard !connectionIds.isEmpty else { return } + for connectionId in connectionIds { + cache[connectionId] = [:] + removeFile(at: fileURL(for: connectionId)) + } + revision &+= 1 + } + + private func commit(_ entries: [String: [HighlightRule]], for connectionId: UUID) { + cache[connectionId] = entries + if entries.isEmpty { + removeFile(at: fileURL(for: connectionId)) + } else { + write(entries, for: connectionId) + } + revision &+= 1 + } + + private func loadEntries(for connectionId: UUID) -> [String: [HighlightRule]] { + if let cached = cache[connectionId] { return cached } + + let url = fileURL(for: connectionId) + guard FileManager.default.fileExists(atPath: url.path) else { + cache[connectionId] = [:] + return [:] + } + + do { + let data = try Data(contentsOf: url) + let decoded = try decoder.decode([String: [LossyHighlightRule]].self, from: data) + let entries = decoded.compactMapValues { lossy -> [HighlightRule]? in + let rules = lossy.compactMap(\.rule) + return rules.isEmpty ? nil : rules + } + cache[connectionId] = entries + return entries + } catch { + Self.logger.error( + "Unreadable highlight rules for \(connectionId, privacy: .public): \(error.localizedDescription, privacy: .public)" + ) + preserveUnreadableFile(at: url) + cache[connectionId] = [:] + return [:] + } + } + + private func write(_ entries: [String: [HighlightRule]], for connectionId: UUID) { + do { + let data = try encoder.encode(entries) + try data.write(to: fileURL(for: connectionId), options: .atomic) + } catch { + Self.logger.error( + "Failed to write highlight rules for \(connectionId, privacy: .public): \(error.localizedDescription, privacy: .public)" + ) + } + } + + private func preserveUnreadableFile(at url: URL) { + let preserved = url.deletingPathExtension().appendingPathExtension("unreadable.json") + let fileManager = FileManager.default + try? fileManager.removeItem(at: preserved) + do { + try fileManager.moveItem(at: url, to: preserved) + } catch { + Self.logger.error("Failed to set aside unreadable highlight rules: \(error.localizedDescription, privacy: .public)") + } + } + + private func removeFile(at url: URL) { + guard FileManager.default.fileExists(atPath: url.path) else { return } + do { + try FileManager.default.removeItem(at: url) + } catch { + Self.logger.error("Failed to remove highlight rules file: \(error.localizedDescription, privacy: .public)") + } + } + + private func fileURL(for connectionId: UUID) -> URL { + storageDirectory.appendingPathComponent("\(connectionId.uuidString).json") + } + + private static func resolvedStorageDirectory() -> URL { + AppStorageEnvironment.shared.applicationSupportRoot + .appendingPathComponent("TablePro", isDirectory: true) + .appendingPathComponent("HighlightRules", isDirectory: true) + } +} + +private struct LossyHighlightRule: Decodable { + let rule: HighlightRule? + + init(from decoder: Decoder) throws { + rule = try? HighlightRule(from: decoder) + } +} diff --git a/TablePro/Models/Highlight/HighlightRule.swift b/TablePro/Models/Highlight/HighlightRule.swift new file mode 100644 index 0000000000..9dcec164c7 --- /dev/null +++ b/TablePro/Models/Highlight/HighlightRule.swift @@ -0,0 +1,139 @@ +// +// HighlightRule.swift +// TablePro +// + +import Foundation + +enum HighlightColor: String, CaseIterable, Identifiable, Codable, Sendable { + case red + case orange + case yellow + case green + case blue + case purple + case gray + + var id: String { rawValue } + + var displayName: String { + switch self { + case .red: return String(localized: "Red") + case .orange: return String(localized: "Orange") + case .yellow: return String(localized: "Yellow") + case .green: return String(localized: "Green") + case .blue: return String(localized: "Blue") + case .purple: return String(localized: "Purple") + case .gray: return String(localized: "Gray") + } + } +} + +enum HighlightTarget: String, CaseIterable, Identifiable, Codable, Sendable { + case row + case cell + + var id: String { rawValue } + + var displayName: String { + switch self { + case .row: return String(localized: "Row") + case .cell: return String(localized: "Cell") + } + } +} + +struct HighlightRule: Identifiable, Equatable, Hashable, Codable, Sendable { + let id: UUID + var isEnabled: Bool + var columnName: String + var columnOccurrence: Int + var filterOperator: FilterOperator + var value: String + var secondValue: String? + var isCaseSensitive: Bool + var color: HighlightColor + var target: HighlightTarget + + init( + id: UUID = UUID(), + isEnabled: Bool = true, + columnName: String, + columnOccurrence: Int = 0, + filterOperator: FilterOperator = .equal, + value: String = "", + secondValue: String? = nil, + isCaseSensitive: Bool? = nil, + color: HighlightColor = .yellow, + target: HighlightTarget = .row + ) { + self.id = id + self.isEnabled = isEnabled + self.columnName = columnName + self.columnOccurrence = max(0, columnOccurrence) + self.filterOperator = filterOperator + self.value = value + self.secondValue = secondValue + self.isCaseSensitive = isCaseSensitive ?? filterOperator.defaultIsCaseSensitive + self.color = color + self.target = target + } + + private enum CodingKeys: String, CodingKey { + case id, isEnabled, columnName, columnOccurrence, filterOperator, value, secondValue + case isCaseSensitive, color, target + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let decodedOperator = try container.decode(FilterOperator.self, forKey: .filterOperator) + self.id = try container.decodeIfPresent(UUID.self, forKey: .id) ?? UUID() + self.isEnabled = try container.decodeIfPresent(Bool.self, forKey: .isEnabled) ?? true + self.columnName = try container.decode(String.self, forKey: .columnName) + self.columnOccurrence = max(0, try container.decodeIfPresent(Int.self, forKey: .columnOccurrence) ?? 0) + self.filterOperator = decodedOperator + self.value = try container.decodeIfPresent(String.self, forKey: .value) ?? "" + self.secondValue = try container.decodeIfPresent(String.self, forKey: .secondValue) + self.isCaseSensitive = try container.decodeIfPresent(Bool.self, forKey: .isCaseSensitive) + ?? decodedOperator.defaultIsCaseSensitive + self.color = try container.decode(HighlightColor.self, forKey: .color) + self.target = try container.decodeIfPresent(HighlightTarget.self, forKey: .target) ?? .row + } + + var isValid: Bool { + guard !columnName.isEmpty else { return false } + guard filterOperator.requiresValue else { return true } + guard !value.isEmpty else { return false } + guard filterOperator.requiresSecondValue else { return true } + return !(secondValue?.isEmpty ?? true) + } + + func hasSameCondition(as other: HighlightRule) -> Bool { + columnName == other.columnName + && columnOccurrence == other.columnOccurrence + && filterOperator == other.filterOperator + && value == other.value + && (filterOperator.requiresSecondValue ? secondValue == other.secondValue : true) + && isCaseSensitive == other.isCaseSensitive + && target == other.target + } +} + +struct RowHighlight: Equatable, Sendable { + let rowRule: HighlightRule? + let cellRules: [Int: HighlightRule] + + static let none = RowHighlight(rowRule: nil, cellRules: [:]) + + var isEmpty: Bool { rowRule == nil && cellRules.isEmpty } + + var rowColor: HighlightColor? { rowRule?.color } + + func cellRule(forColumn column: Int) -> HighlightRule? { + cellRules[column] + } + + func describingRule(forColumn column: Int) -> HighlightRule? { + cellRules[column] ?? rowRule + } +} diff --git a/TablePro/Models/Highlight/HighlightRuleDescription.swift b/TablePro/Models/Highlight/HighlightRuleDescription.swift new file mode 100644 index 0000000000..18c1ab6a20 --- /dev/null +++ b/TablePro/Models/Highlight/HighlightRuleDescription.swift @@ -0,0 +1,67 @@ +// +// HighlightRuleDescription.swift +// TablePro +// + +import Foundation + +enum HighlightRuleDescription { + static let menuValueLimit = 32 + + static func condition(of rule: HighlightRule, valueLimit: Int? = nil) -> String { + condition( + columnName: rule.columnName, + filterOperator: rule.filterOperator, + value: rule.value, + secondValue: rule.secondValue, + valueLimit: valueLimit + ) + } + + static func condition( + columnName: String, + filterOperator: FilterOperator, + value: String, + secondValue: String?, + valueLimit: Int? = nil + ) -> String { + guard filterOperator.requiresValue else { + return String(format: String(localized: "%1$@ %2$@"), columnName, filterOperator.displayName) + } + + let first = truncated(value, to: valueLimit) + if filterOperator.requiresSecondValue { + return String( + format: String(localized: "%1$@ between “%2$@” and “%3$@”"), + columnName, + first, + truncated(secondValue ?? "", to: valueLimit) + ) + } + + return String( + format: String(localized: "%1$@ %2$@ “%3$@”"), + columnName, + operatorText(filterOperator), + first + ) + } + + static func truncated(_ value: String, to limit: Int?) -> String { + guard let limit, limit > 0 else { return value } + let source = value as NSString + guard source.length > limit else { return value } + let cut = source.rangeOfComposedCharacterSequence(at: limit).location + return source.substring(to: cut) + "\u{2026}" + } + + private static func operatorText(_ filterOperator: FilterOperator) -> String { + switch filterOperator { + case .equal, .notEqual, .greaterThan, .greaterOrEqual, .lessThan, .lessOrEqual: + return filterOperator.symbol + case .contains, .notContains, .startsWith, .endsWith, .isNull, .isNotNull, .isEmpty, + .isNotEmpty, .inList, .notInList, .between, .regex: + return filterOperator.displayName + } + } +} diff --git a/TablePro/Models/Query/QueryTab.swift b/TablePro/Models/Query/QueryTab.swift index ece3ac2985..e94279226c 100644 --- a/TablePro/Models/Query/QueryTab.swift +++ b/TablePro/Models/Query/QueryTab.swift @@ -74,6 +74,7 @@ struct QueryTab: Identifiable, Equatable { /// run with no `DataGridView` in the view tree. Living on the grid's SwiftUI coordinator meant /// switching result mode did not hide the order, it deleted it. (#2251) var valueFilter: GridValueFilterState + var sessionHighlightRules: [HighlightRule] = [] var pagination: PaginationState var chartConfiguration: ResultChartConfiguration var hasUserInteraction: Bool @@ -407,6 +408,7 @@ struct QueryTab: Identifiable, Equatable { && lhs.pagination == rhs.pagination && lhs.sortState == rhs.sortState && lhs.valueFilter == rhs.valueFilter + && lhs.sessionHighlightRules == rhs.sessionHighlightRules && lhs.chartConfiguration == rhs.chartConfiguration && lhs.display == rhs.display && lhs.tableContext.isEditable == rhs.tableContext.isEditable diff --git a/TablePro/Models/Query/QueryTabState.swift b/TablePro/Models/Query/QueryTabState.swift index e4480deabf..48e920e70f 100644 --- a/TablePro/Models/Query/QueryTabState.swift +++ b/TablePro/Models/Query/QueryTabState.swift @@ -657,6 +657,7 @@ struct TabDisplayState: Equatable { var isResultsCollapsed: Bool = false var resultSets: [ResultSet] = [] var activeResultSetId: UUID? + var highlightRulesPresentationRequest: Int = 0 var activeResultSet: ResultSet? { guard let id = activeResultSetId else { return resultSets.last } @@ -698,5 +699,6 @@ struct TabDisplayState: Equatable { && lhs.isResultsCollapsed == rhs.isResultsCollapsed && lhs.resultSets.map(\.id) == rhs.resultSets.map(\.id) && lhs.activeResultSetId == rhs.activeResultSetId + && lhs.highlightRulesPresentationRequest == rhs.highlightRulesPresentationRequest } } diff --git a/TablePro/Models/Query/ResultStatusModel.swift b/TablePro/Models/Query/ResultStatusModel.swift index f58e2c1ad3..ccb0032825 100644 --- a/TablePro/Models/Query/ResultStatusModel.swift +++ b/TablePro/Models/Query/ResultStatusModel.swift @@ -41,6 +41,7 @@ struct ResultStatusControls: Equatable { var showsCountInProgress = false var showsFetchAll = false var showsColumns = false + var showsHighlightRules = false var showsFilters = false var showsPagination = false /// First, Previous, Next, Last and the page number, which an engine that cannot skip rows has @@ -115,6 +116,7 @@ struct ResultStatusModel: Equatable { && !pagination.isLoadingMore controls.showsColumns = viewMode.showsColumnControls && describesAResult + controls.showsHighlightRules = viewMode == .data && describesAResult controls.showsFilters = viewMode.showsRowFilters && isTable && snapshot.hasTableName controls.showsPagination = viewMode.showsResultScope && isTable && snapshot.hasTableName controls.showsPageNavigation = controls.showsPagination && snapshot.paginationCapability.allowsSeeking diff --git a/TablePro/Views/Components/ClosureMenuTarget.swift b/TablePro/Views/Components/ClosureMenuTarget.swift new file mode 100644 index 0000000000..0e85c2f969 --- /dev/null +++ b/TablePro/Views/Components/ClosureMenuTarget.swift @@ -0,0 +1,31 @@ +// +// ClosureMenuTarget.swift +// TablePro +// + +import AppKit + +/// `NSMenuItem` holds its target weakly, so the closure needs an owner that outlives the menu. +/// `representedObject` is that owner: it is strong, it belongs to the item, and it goes when the +/// item does. +@MainActor +final class ClosureMenuTarget: NSObject { + private let action: () -> Void + + init(action: @escaping () -> Void) { + self.action = action + } + + @objc func fire() { + action() + } + + static func item(title: String, isEnabled: Bool = true, action: @escaping () -> Void) -> NSMenuItem { + let item = NSMenuItem(title: title, action: #selector(fire), keyEquivalent: "") + let target = ClosureMenuTarget(action: action) + item.target = target + item.representedObject = target + item.isEnabled = isEnabled + return item + } +} diff --git a/TablePro/Views/Highlight/HighlightColor+AppKit.swift b/TablePro/Views/Highlight/HighlightColor+AppKit.swift new file mode 100644 index 0000000000..fb3bc5b7d6 --- /dev/null +++ b/TablePro/Views/Highlight/HighlightColor+AppKit.swift @@ -0,0 +1,42 @@ +// +// HighlightColor+AppKit.swift +// TablePro +// + +import AppKit + +extension HighlightColor { + static let washAlpha: CGFloat = 0.2 + + var systemColor: NSColor { + switch self { + case .red: return .systemRed + case .orange: return .systemOrange + case .yellow: return .systemYellow + case .green: return .systemGreen + case .blue: return .systemBlue + case .purple: return .systemPurple + case .gray: return .systemGray + } + } + + var washColor: NSColor { + systemColor.withAlphaComponent(Self.washAlpha) + } + + func swatchImage(diameter: CGFloat = 12) -> NSImage { + let color = systemColor + let image = NSImage(size: NSSize(width: diameter, height: diameter), flipped: false) { rect in + color.setFill() + NSBezierPath(ovalIn: rect.insetBy(dx: 0.5, dy: 0.5)).fill() + NSColor.separatorColor.setStroke() + let outline = NSBezierPath(ovalIn: rect.insetBy(dx: 0.5, dy: 0.5)) + outline.lineWidth = 0.5 + outline.stroke() + return true + } + image.isTemplate = false + image.accessibilityDescription = displayName + return image + } +} diff --git a/TablePro/Views/Highlight/HighlightColumnOption.swift b/TablePro/Views/Highlight/HighlightColumnOption.swift new file mode 100644 index 0000000000..945e8fb854 --- /dev/null +++ b/TablePro/Views/Highlight/HighlightColumnOption.swift @@ -0,0 +1,31 @@ +// +// HighlightColumnOption.swift +// TablePro +// + +import Foundation + +struct HighlightColumnOption: Identifiable, Hashable { + let name: String + let occurrence: Int + let label: String + + var id: String { Self.identifier(name: name, occurrence: occurrence) } + + static func identifier(name: String, occurrence: Int) -> String { + "\(occurrence)#\(name)" + } + + static func options(for columns: [String]) -> [HighlightColumnOption] { + var seen: [String: Int] = [:] + let totals = columns.reduce(into: [String: Int]()) { $0[$1, default: 0] += 1 } + return columns.map { name in + let occurrence = seen[name, default: 0] + seen[name] = occurrence + 1 + let label = totals[name, default: 0] > 1 + ? String(format: String(localized: "%1$@ (%2$d)"), name, occurrence + 1) + : name + return HighlightColumnOption(name: name, occurrence: occurrence, label: label) + } + } +} diff --git a/TablePro/Views/Highlight/HighlightMenuBuilder.swift b/TablePro/Views/Highlight/HighlightMenuBuilder.swift new file mode 100644 index 0000000000..537505cbba --- /dev/null +++ b/TablePro/Views/Highlight/HighlightMenuBuilder.swift @@ -0,0 +1,144 @@ +// +// HighlightMenuBuilder.swift +// TablePro +// + +import AppKit +import TableProPluginKit + +@MainActor +enum HighlightMenuBuilder { + struct CellContext { + let columnName: String + let columnOccurrence: Int + let columnType: ColumnType? + let value: PluginCellValue + let existingRules: [HighlightRule] + } + + struct Actions { + let apply: (HighlightRule) -> Void + let remove: (HighlightRule) -> Void + let showRules: () -> Void + } + + static func quickRule( + columnName: String, + columnOccurrence: Int, + columnType: ColumnType?, + value: PluginCellValue, + target: HighlightTarget, + color: HighlightColor + ) -> HighlightRule? { + switch value { + case .null: + return HighlightRule( + columnName: columnName, + columnOccurrence: columnOccurrence, + filterOperator: .isNull, + color: color, + target: target + ) + case .text(let text) where text.isEmpty: + return HighlightRule( + columnName: columnName, + columnOccurrence: columnOccurrence, + filterOperator: .isEmpty, + color: color, + target: target + ) + case .text(let text) where HighlightCondition.readsAsNullLiteral(text, columnType: columnType): + return nil + case .text(let text): + return HighlightRule( + columnName: columnName, + columnOccurrence: columnOccurrence, + filterOperator: .equal, + value: text, + color: color, + target: target + ) + case .bytes: + return nil + } + } + + static func sectionTitle(for rule: HighlightRule) -> String { + let condition = HighlightRuleDescription.condition( + of: rule, + valueLimit: HighlightRuleDescription.menuValueLimit + ) + switch rule.target { + case .row: + return String(format: String(localized: "Rows Where %@"), condition) + case .cell: + return String(format: String(localized: "Cells Where %@"), condition) + } + } + + static func menuItem(for context: CellContext, actions: Actions) -> NSMenuItem? { + let templates = HighlightTarget.allCases.compactMap { target in + quickRule( + columnName: context.columnName, + columnOccurrence: context.columnOccurrence, + columnType: context.columnType, + value: context.value, + target: target, + color: .yellow + ) + } + guard !templates.isEmpty else { return nil } + + let submenu = NSMenu() + var existingMatches: [HighlightRule] = [] + for template in templates { + let existing = context.existingRules.first { $0.hasSameCondition(as: template) } + if let existing { existingMatches.append(existing) } + submenu.addItem(.sectionHeader(title: sectionTitle(for: template))) + submenu.addItem(paletteItem(for: template, existing: existing, actions: actions)) + } + + submenu.addItem(.separator()) + if !existingMatches.isEmpty { + submenu.addItem(ClosureMenuTarget.item(title: String(localized: "Remove Highlight")) { + existingMatches.forEach(actions.remove) + }) + } + submenu.addItem(ClosureMenuTarget.item(title: String(localized: "Highlight Rules…"), action: actions.showRules)) + + let item = NSMenuItem(title: String(localized: "Highlight"), action: nil, keyEquivalent: "") + item.image = NSImage(systemSymbolName: "highlighter", accessibilityDescription: nil) + item.submenu = submenu + return item + } + + private static func paletteItem( + for template: HighlightRule, + existing: HighlightRule?, + actions: Actions + ) -> NSMenuItem { + let colors = HighlightColor.allCases + let palette = NSMenu.palette( + colors: colors.map(\.systemColor), + titles: colors.map(\.displayName) + ) { menu in + let selected = menu.selectedItems.compactMap { menu.items.firstIndex(of: $0) } + guard let index = selected.first, colors.indices.contains(index) else { + if let existing { actions.remove(existing) } + return + } + var rule = existing ?? template + rule.color = colors[index] + rule.isEnabled = true + actions.apply(rule) + } + palette.selectionMode = .selectOne + if let existing, let index = colors.firstIndex(of: existing.color), index < palette.items.count { + palette.selectedItems = [palette.items[index]] + } + + let item = NSMenuItem(title: sectionTitle(for: template), action: nil, keyEquivalent: "") + item.submenu = palette + return item + } +} diff --git a/TablePro/Views/Highlight/HighlightRuleRow.swift b/TablePro/Views/Highlight/HighlightRuleRow.swift new file mode 100644 index 0000000000..7e07625e35 --- /dev/null +++ b/TablePro/Views/Highlight/HighlightRuleRow.swift @@ -0,0 +1,224 @@ +// +// HighlightRuleRow.swift +// TablePro +// + +import SwiftUI + +struct HighlightRuleRow: View { + @Binding var rule: HighlightRule + let columnOptions: [HighlightColumnOption] + @Binding var focusedRuleID: UUID? + let canMoveUp: Bool + let canMoveDown: Bool + let onMoveUp: () -> Void + let onMoveDown: () -> Void + let onRemove: () -> Void + let onCancel: () -> Void + + private var isColumnMissing: Bool { + !columnOptions.contains { $0.name == rule.columnName && $0.occurrence == rule.columnOccurrence } + } + + var body: some View { + VStack(alignment: .leading, spacing: 6) { + HStack(spacing: 6) { + Toggle("", isOn: $rule.isEnabled) + .toggleStyle(.checkbox) + .labelsHidden() + .accessibilityLabel(String(localized: "Enable rule")) + .accessibilityIdentifier("highlight-rule-enabled") + .help(String(localized: "Apply this rule")) + conditionEditor + .opacity(rule.isEnabled ? 1 : 0.5) + } + HStack(spacing: 8) { + colorPicker + targetPicker + if isColumnMissing { + Label(String(localized: "Not in this result"), systemImage: "exclamationmark.triangle") + .font(.caption) + .foregroundStyle(.secondary) + .help(String(format: String(localized: "This result has no column named %@"), rule.columnName)) + } + Spacer(minLength: 0) + removeButton + } + .padding(.leading, 22) + .opacity(rule.isEnabled ? 1 : 0.5) + } + .padding(.vertical, 4) + .accessibilityElement(children: .contain) + .accessibilityLabel(HighlightRuleDescription.condition(of: rule)) + .accessibilityActions { + if canMoveUp { + Button(String(localized: "Move Rule Up"), action: onMoveUp) + } + if canMoveDown { + Button(String(localized: "Move Rule Down"), action: onMoveDown) + } + } + } + + private var conditionEditor: some View { + HStack(spacing: 6) { + columnPicker + operatorMenu + valueFields + } + } + + private var columnSelection: Binding { + Binding( + get: { HighlightColumnOption.identifier(name: rule.columnName, occurrence: rule.columnOccurrence) }, + set: { identifier in + guard let option = columnOptions.first(where: { $0.id == identifier }) else { return } + rule.columnName = option.name + rule.columnOccurrence = option.occurrence + } + ) + } + + private var columnPicker: some View { + Picker("", selection: columnSelection) { + ForEach(columnOptions) { option in + Text(option.label).tag(option.id) + } + if isColumnMissing { + Divider() + Text(rule.columnName) + .tag(HighlightColumnOption.identifier(name: rule.columnName, occurrence: rule.columnOccurrence)) + } + } + .pickerStyle(.menu) + .controlSize(.small) + .fixedSize() + .labelsHidden() + .accessibilityLabel(String(localized: "Rule column")) + .accessibilityValue(rule.columnName) + } + + private var operatorSelection: Binding { + Binding( + get: { rule.filterOperator }, + set: { newOperator in + guard newOperator != rule.filterOperator else { return } + rule.filterOperator = newOperator + rule.isCaseSensitive = newOperator.defaultIsCaseSensitive + } + ) + } + + private var operatorMenu: some View { + Menu { + Picker("", selection: operatorSelection) { + ForEach(FilterOperator.allCases) { filterOperator in + Text(Self.operatorLabel(filterOperator)) + .accessibilityLabel(filterOperator.displayName) + .tag(filterOperator) + } + } + .pickerStyle(.inline) + .labelsHidden() + + if rule.filterOperator.supportsCaseSensitivity { + Divider() + Toggle(String(localized: "Match Case"), isOn: $rule.isCaseSensitive) + } + } label: { + HStack(spacing: 3) { + Text(Self.operatorLabel(rule.filterOperator)) + if rule.filterOperator.supportsCaseSensitivity, + rule.isCaseSensitive != rule.filterOperator.defaultIsCaseSensitive { + Image(systemName: "textformat") + .imageScale(.small) + .foregroundStyle(.secondary) + } + } + } + .menuStyle(.button) + .controlSize(.small) + .fixedSize() + .accessibilityLabel(String(localized: "Rule operator")) + .accessibilityValue(rule.filterOperator.displayName) + } + + @ViewBuilder + private var valueFields: some View { + if rule.filterOperator.requiresValue { + FilterValueTextField( + text: $rule.value, + focusedId: $focusedRuleID, + identity: rule.id, + placeholder: String(localized: "Value"), + onCancel: onCancel + ) + .frame(minWidth: 90) + .accessibilityLabel(String(localized: "Rule value")) + + if rule.filterOperator.requiresSecondValue { + Text("and") + .font(.subheadline) + .foregroundStyle(.secondary) + TextField("Value", text: Binding( + get: { rule.secondValue ?? "" }, + set: { rule.secondValue = $0 } + )) + .textFieldStyle(.roundedBorder) + .controlSize(.small) + .autocorrectionDisabled(true) + .frame(minWidth: 70) + .accessibilityLabel(String(localized: "Second rule value")) + } + } else { + Spacer(minLength: 0) + } + } + + private var colorPicker: some View { + Picker("", selection: $rule.color) { + ForEach(HighlightColor.allCases) { color in + Label { + Text(color.displayName) + } icon: { + Image(nsImage: color.swatchImage()) + } + .tag(color) + } + } + .pickerStyle(.menu) + .controlSize(.small) + .fixedSize() + .labelsHidden() + .accessibilityLabel(String(localized: "Highlight color")) + .accessibilityValue(rule.color.displayName) + } + + private var targetPicker: some View { + Picker("", selection: $rule.target) { + ForEach(HighlightTarget.allCases) { target in + Text(target.displayName).tag(target) + } + } + .pickerStyle(.segmented) + .controlSize(.small) + .fixedSize() + .labelsHidden() + .accessibilityLabel(String(localized: "Apply To")) + .help(String(localized: "Color the whole row, or only the matching cell")) + } + + private var removeButton: some View { + Button(String(localized: "Remove Rule"), systemImage: "minus", action: onRemove) + .labelStyle(.iconOnly) + .buttonStyle(.bordered) + .controlSize(.small) + .help(String(localized: "Remove this rule")) + } + + private static func operatorLabel(_ filterOperator: FilterOperator) -> String { + filterOperator.symbol.isEmpty + ? filterOperator.displayName + : "\(filterOperator.symbol) \(filterOperator.displayName)" + } +} diff --git a/TablePro/Views/Highlight/HighlightRulesPopover.swift b/TablePro/Views/Highlight/HighlightRulesPopover.swift new file mode 100644 index 0000000000..642004f9c0 --- /dev/null +++ b/TablePro/Views/Highlight/HighlightRulesPopover.swift @@ -0,0 +1,144 @@ +// +// HighlightRulesPopover.swift +// TablePro +// + +import SwiftUI + +struct HighlightRulesPopover: View { + let columns: [String] + let rules: [HighlightRule] + let isPersisted: Bool + let onChange: ([HighlightRule]) -> Void + + @State private var focusedRuleID: UUID? + @Environment(\.dismiss) private var dismiss + + private static let rowHeight: CGFloat = 64 + private static let maximumListHeight: CGFloat = 420 + + private var columnOptions: [HighlightColumnOption] { + HighlightColumnOption.options(for: columns) + } + + var body: some View { + VStack(alignment: .leading, spacing: 0) { + header + Divider() + if rules.isEmpty { + emptyState + } else { + ruleList + } + Divider() + footer + } + .frame(width: 540) + } + + private var header: some View { + VStack(alignment: .leading, spacing: 2) { + Text("Highlight Rules") + .font(.headline) + Text("Rules are checked in order. The first match sets the color.") + .font(.caption) + .foregroundStyle(.secondary) + } + .padding(.horizontal, 12) + .padding(.vertical, 10) + } + + private var emptyState: some View { + ContentUnavailableView { + Label(String(localized: "No Highlight Rules"), systemImage: "highlighter") + } description: { + Text("Right-click a cell and choose Highlight to color rows by value.") + } + .frame(maxWidth: .infinity) + .padding(.vertical, 8) + } + + private var ruleList: some View { + List { + ForEach(rules) { rule in + HighlightRuleRow( + rule: binding(for: rule), + columnOptions: columnOptions, + focusedRuleID: $focusedRuleID, + canMoveUp: rules.first?.id != rule.id, + canMoveDown: rules.last?.id != rule.id, + onMoveUp: { move(rule, by: -1) }, + onMoveDown: { move(rule, by: 1) }, + onRemove: { remove(rule) }, + onCancel: close + ) + } + .onMove(perform: move) + } + .listStyle(.plain) + .scrollContentBackground(.hidden) + .frame(height: min(CGFloat(rules.count) * Self.rowHeight + 8, Self.maximumListHeight)) + } + + private var footer: some View { + HStack(spacing: 8) { + Button(String(localized: "Add Rule"), systemImage: "plus", action: addRule) + .controlSize(.small) + .disabled(columns.isEmpty) + .accessibilityIdentifier("highlight-rules-add") + + Spacer(minLength: 8) + + if !isPersisted { + Text("Rules for this query result are not saved.") + .font(.caption) + .foregroundStyle(.secondary) + .lineLimit(1) + } + } + .padding(.horizontal, 12) + .padding(.vertical, 8) + } + + private func binding(for rule: HighlightRule) -> Binding { + Binding( + get: { rules.first { $0.id == rule.id } ?? rule }, + set: { updated in + var next = rules + guard let index = next.firstIndex(where: { $0.id == updated.id }) else { return } + next[index] = updated + onChange(next) + } + ) + } + + private func addRule() { + guard let first = columnOptions.first else { return } + let rule = HighlightRule(columnName: first.name, columnOccurrence: first.occurrence) + onChange(rules + [rule]) + focusedRuleID = rule.id + } + + private func close() { + dismiss() + } + + private func remove(_ rule: HighlightRule) { + onChange(rules.filter { $0.id != rule.id }) + } + + private func move(from source: IndexSet, to destination: Int) { + var next = rules + next.move(fromOffsets: source, toOffset: destination) + onChange(next) + } + + private func move(_ rule: HighlightRule, by offset: Int) { + guard let index = rules.firstIndex(where: { $0.id == rule.id }) else { return } + let target = index + offset + guard rules.indices.contains(target) else { return } + var next = rules + next.swapAt(index, target) + onChange(next) + } +} diff --git a/TablePro/Views/Main/Child/DataTabGridDelegate.swift b/TablePro/Views/Main/Child/DataTabGridDelegate.swift index 4de563328c..2de98910ef 100644 --- a/TablePro/Views/Main/Child/DataTabGridDelegate.swift +++ b/TablePro/Views/Main/Child/DataTabGridDelegate.swift @@ -134,6 +134,48 @@ final class DataTabGridDelegate: DataGridViewDelegate { return menu } + func dataGridHighlightMenuItem(forRow displayRow: Int, dataColumn: Int) -> NSMenuItem? { + guard let coordinator, + let grid = tableViewCoordinator, + let tab = coordinator.tabManager.selectedTab, + let row = grid.displayRow(at: displayRow) else { return nil } + let tableRows = grid.tableRowsProvider() + let columns = tableRows.columns + guard columns.indices.contains(dataColumn), dataColumn < row.values.count else { return nil } + + let tabId = tab.id + let context = HighlightMenuBuilder.CellContext( + columnName: columns[dataColumn], + columnOccurrence: HighlightRuleSet.occurrence(ofColumnAt: dataColumn, in: columns), + columnType: dataColumn < tableRows.columnTypes.count ? tableRows.columnTypes[dataColumn] : nil, + value: row.values[dataColumn], + existingRules: coordinator.highlightRules(for: tab) + ) + let actions = HighlightMenuBuilder.Actions( + apply: { [weak coordinator] rule in + coordinator?.applyQuickHighlight(rule, forTab: tabId) + }, + remove: { [weak coordinator] rule in + coordinator?.removeHighlightRules(sharingConditionWith: rule, forTab: tabId) + }, + showRules: { [weak coordinator] in + coordinator?.presentHighlightRules() + } + ) + return HighlightMenuBuilder.menuItem(for: context, actions: actions) + } + + func dataGridHighlightValuesMenuItem(forColumn dataColumnIndex: Int) -> NSMenuItem? { + guard coordinator != nil, let grid = tableViewCoordinator else { return nil } + let columns = grid.tableRowsProvider().columns + guard columns.indices.contains(dataColumnIndex) else { return nil } + let columnName = columns[dataColumnIndex] + let occurrence = HighlightRuleSet.occurrence(ofColumnAt: dataColumnIndex, in: columns) + return ClosureMenuTarget.item(title: String(localized: "Highlight Values…")) { [weak coordinator] in + coordinator?.presentHighlightRules(addingRuleForColumn: columnName, occurrence: occurrence) + } + } + weak var tableViewCoordinator: TableViewCoordinator? func dataGridAttach(tableViewCoordinator: TableViewCoordinator) { diff --git a/TablePro/Views/Main/Child/MainEditorContentView.swift b/TablePro/Views/Main/Child/MainEditorContentView.swift index bfe980b42f..07b6b67c9c 100644 --- a/TablePro/Views/Main/Child/MainEditorContentView.swift +++ b/TablePro/Views/Main/Child/MainEditorContentView.swift @@ -916,6 +916,7 @@ struct MainEditorContentView: View { editRefusalMessage: refusal?.message ), displayFormats: coordinator.displayFormats(for: tab), + highlightRules: coordinator.highlightRules(for: tab), delegate: dataTabDelegate, selectedRowIndices: Binding( get: { selectionState.indices }, @@ -1019,6 +1020,18 @@ struct MainEditorContentView: View { ? { coordinator.showColumnJump(seededWith: $0) } : nil ), + highlightState: StatusBarHighlightState( + rules: coordinator.highlightRules(for: tab), + columns: resolvedRows.columns, + isPersisted: coordinator.highlightRuleScope(for: tab) != nil, + presentationRequest: tab.display.highlightRulesPresentationRequest, + onChange: { [coordinator, tabId = tab.id] rules in + coordinator.setHighlightRules(rules, forTab: tabId) + }, + onDismiss: { [coordinator, tabId = tab.id] in + coordinator.discardIncompleteHighlightRules(forTab: tabId) + } + ), paginationCallbacks: PaginationCallbacks( onFirst: onFirstPage, onPrevious: onPreviousPage, diff --git a/TablePro/Views/Main/EditorTabContextMenuBuilder.swift b/TablePro/Views/Main/EditorTabContextMenuBuilder.swift index f06ad43bb6..214b893374 100644 --- a/TablePro/Views/Main/EditorTabContextMenuBuilder.swift +++ b/TablePro/Views/Main/EditorTabContextMenuBuilder.swift @@ -58,27 +58,6 @@ internal enum EditorTabContextMenuBuilder { isEnabled: Bool = true, action: @escaping () -> Void ) { - let item = NSMenuItem(title: title, action: #selector(ClosureMenuTarget.fire), keyEquivalent: "") - let target = ClosureMenuTarget(action: action) - item.target = target - item.representedObject = target - item.isEnabled = isEnabled - menu.addItem(item) - } -} - -/// `NSMenuItem` holds its target weakly, so the closure needs an owner that outlives the menu. -/// `representedObject` is that owner: it is strong, it belongs to the item, and it goes when the -/// item does. -@MainActor -private final class ClosureMenuTarget: NSObject { - private let action: () -> Void - - init(action: @escaping () -> Void) { - self.action = action - } - - @objc func fire() { - action() + menu.addItem(ClosureMenuTarget.item(title: title, isEnabled: isEnabled, action: action)) } } diff --git a/TablePro/Views/Main/Extensions/MainContentCoordinator+HighlightRules.swift b/TablePro/Views/Main/Extensions/MainContentCoordinator+HighlightRules.swift new file mode 100644 index 0000000000..ab684bfd84 --- /dev/null +++ b/TablePro/Views/Main/Extensions/MainContentCoordinator+HighlightRules.swift @@ -0,0 +1,66 @@ +// +// MainContentCoordinator+HighlightRules.swift +// TablePro +// + +import Foundation + +extension MainContentCoordinator { + func highlightRuleScope(for tab: QueryTab) -> TableScope? { + tab.tableContext.scope(connectionId: connectionId) + } + + func highlightRules(for tab: QueryTab) -> [HighlightRule] { + guard let scope = highlightRuleScope(for: tab) else { return tab.sessionHighlightRules } + return HighlightRuleStorage.shared.rules(for: scope) + } + + func setHighlightRules(_ rules: [HighlightRule], forTab tabId: UUID) { + guard let index = tabManager.tabs.firstIndex(where: { $0.id == tabId }) else { return } + if let scope = highlightRuleScope(for: tabManager.tabs[index]) { + HighlightRuleStorage.shared.setRules(rules, for: scope) + return + } + guard tabManager.tabs[index].sessionHighlightRules != rules else { return } + tabManager.mutate(at: index) { $0.sessionHighlightRules = rules } + } + + func applyQuickHighlight(_ rule: HighlightRule, forTab tabId: UUID) { + guard let tab = tabManager.tabs.first(where: { $0.id == tabId }) else { return } + var rules = highlightRules(for: tab) + rules.removeAll { $0.hasSameCondition(as: rule) } + rules.insert(rule, at: 0) + setHighlightRules(rules, forTab: tabId) + } + + func removeHighlightRules(sharingConditionWith rule: HighlightRule, forTab tabId: UUID) { + guard let tab = tabManager.tabs.first(where: { $0.id == tabId }) else { return } + let rules = highlightRules(for: tab).filter { !$0.hasSameCondition(as: rule) } + setHighlightRules(rules, forTab: tabId) + } + + func discardIncompleteHighlightRules(forTab tabId: UUID) { + guard let tab = tabManager.tabs.first(where: { $0.id == tabId }) else { return } + let rules = highlightRules(for: tab) + let complete = rules.filter(\.isValid) + guard complete.count != rules.count else { return } + setHighlightRules(complete, forTab: tabId) + } + + func presentHighlightRules(addingRuleForColumn columnName: String? = nil, occurrence: Int = 0) { + guard let index = tabManager.selectedTabIndex else { return } + let tabId = tabManager.tabs[index].id + if let columnName { + let newRule = HighlightRule(columnName: columnName, columnOccurrence: occurrence) + setHighlightRules(highlightRules(for: tabManager.tabs[index]) + [newRule], forTab: tabId) + } + tabManager.mutate(at: index) { $0.display.highlightRulesPresentationRequest &+= 1 } + } + + var canPresentHighlightRules: Bool { + guard hasMountedDataGrid, + let tab = tabManager.selectedTab, + tab.display.resultsViewMode == .data else { return false } + return !(tabSessionRegistry.existingTableRows(for: tab.id)?.columns.isEmpty ?? true) + } +} diff --git a/TablePro/Views/Main/Extensions/MainContentCoordinator+RenameAdoption.swift b/TablePro/Views/Main/Extensions/MainContentCoordinator+RenameAdoption.swift index 3bcfabbfb6..dd32e6b913 100644 --- a/TablePro/Views/Main/Extensions/MainContentCoordinator+RenameAdoption.swift +++ b/TablePro/Views/Main/Extensions/MainContentCoordinator+RenameAdoption.swift @@ -98,6 +98,11 @@ extension MainContentCoordinator { connectionId: connectionId, databaseName: database, schemaName: schema, tableName: newName ) ) + let scopedDatabase = database.isEmpty ? nil : database + HighlightRuleStorage.shared.rename( + from: TableScope(connectionId: connectionId, database: scopedDatabase, schema: schema, table: oldName), + to: TableScope(connectionId: connectionId, database: scopedDatabase, schema: schema, table: newName) + ) } private func moveFavorite(_ ref: DatabaseTreeTableRef, to newName: String, database: String?) { @@ -139,6 +144,10 @@ extension MainContentCoordinator { connectionId: connectionId, fromDatabase: database, fromSchema: schema, toDatabase: toDatabase, toSchema: toSchema ) + HighlightRuleStorage.shared.renameScope( + connectionId: connectionId, fromDatabase: database, fromSchema: schema, + toDatabase: toDatabase, toSchema: toSchema + ) retargetFavoriteTables( database: database, schema: schema, toDatabase: toDatabase, toSchema: toSchema ) diff --git a/TablePro/Views/Main/MainContentCommandActions.swift b/TablePro/Views/Main/MainContentCommandActions.swift index 8ff2fda18c..b2b3ae6211 100644 --- a/TablePro/Views/Main/MainContentCommandActions.swift +++ b/TablePro/Views/Main/MainContentCommandActions.swift @@ -936,6 +936,15 @@ final class MainContentCommandActions { coordinator.toggleFilterPanel() } + var canPresentHighlightRules: Bool { + coordinator?.canPresentHighlightRules ?? false + } + + func showHighlightRules() { + guard canPresentHighlightRules, let coordinator else { return } + coordinator.presentHighlightRules() + } + func showFindBar() { guard canUseGridFindCommands, let coordinator else { return } coordinator.findCoordinator.show() diff --git a/TablePro/Views/Results/Cells/DataGridCellAccessibilityView.swift b/TablePro/Views/Results/Cells/DataGridCellAccessibilityView.swift index 3978dc9a0c..1d5ba6d736 100644 --- a/TablePro/Views/Results/Cells/DataGridCellAccessibilityView.swift +++ b/TablePro/Views/Results/Cells/DataGridCellAccessibilityView.swift @@ -88,11 +88,20 @@ internal final class DataGridCellAccessibilityView: NSView { override internal func accessibilityValue() -> Any? { text } override internal func accessibilityLabel() -> String? { - String( - format: String(localized: "Row %d, column %d: %@"), + guard let highlight = coordinator?.highlightDescription(row: row, columnIndex: dataColumn) else { + return String( + format: String(localized: "Row %d, column %d: %@"), + row + 1, + dataColumn + 1, + text + ) + } + return String( + format: String(localized: "Row %d, column %d: %@, highlighted where %@"), row + 1, dataColumn + 1, - text + text, + highlight ) } diff --git a/TablePro/Views/Results/Cells/DataGridCellAppearance.swift b/TablePro/Views/Results/Cells/DataGridCellAppearance.swift index 9a0d23f2d9..01b03621fe 100644 --- a/TablePro/Views/Results/Cells/DataGridCellAppearance.swift +++ b/TablePro/Views/Results/Cells/DataGridCellAppearance.swift @@ -15,7 +15,7 @@ struct DataGridCellAppearance: Equatable { let text: String let font: NSFont let textColor: NSColor - /// Painted behind the text, for a find match or a modified value. + /// Painted behind the text, for a find match, a modified value or a highlight rule. let backgroundTint: NSColor? let accessory: DataGridCellAccessory /// Which symbol the accessory draws, resolved here because it follows the row's state rather @@ -52,18 +52,19 @@ struct DataGridCellAppearance: Equatable { } let findTint: NSColor? = state.isCurrentFindMatch ? palette.findMatchTint : nil - let modifiedTint: NSColor? + let highlightColor = state.visualState.cellHighlightColor(forColumn: state.columnIndex) + let stateTint: NSColor? if state.visualState.isDeleted || state.visualState.isInserted { - modifiedTint = nil + stateTint = nil } else if state.visualState.isModified(columnIndex: state.columnIndex) { - modifiedTint = palette.modifiedColumnTint + stateTint = palette.modifiedColumnTint } else { - modifiedTint = nil + stateTint = highlightColor?.washColor } // A find match keeps its own highlight whatever else is true, and the text turns black // against it. Otherwise a selected row's text takes the selection's own colour, and the - // modified tint stands down so the selection fill is not painted over. + // modified or highlight tint stands down so the selection fill is not painted over. let backgroundTint: NSColor? let textColor: NSColor if let findTint { @@ -73,7 +74,7 @@ struct DataGridCellAppearance: Equatable { backgroundTint = nil textColor = .alternateSelectedControlTextColor } else { - backgroundTint = modifiedTint + backgroundTint = stateTint textColor = baseColor } diff --git a/TablePro/Views/Results/DataGridCoordinator.swift b/TablePro/Views/Results/DataGridCoordinator.swift index 88ca3cb1d4..28e2f55309 100644 --- a/TablePro/Views/Results/DataGridCoordinator.swift +++ b/TablePro/Views/Results/DataGridCoordinator.swift @@ -550,6 +550,7 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData static let rowViewIdentifier = NSUserInterfaceItemIdentifier("TableRowView") let visualIndex = RowVisualIndex() + var highlightRuleSet: HighlightRuleSet = .empty private let largeDatasetThreshold = 5_000 var isLargeDataset: Bool { cachedRowCount > largeDatasetThreshold } @@ -693,6 +694,7 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData systemTimeZoneCancellable = nil detachAccessibilityActivationObserver() visualIndex.clear() + highlightRuleSet = .empty displayCache.removeAll() columnDisplayFormats = [] cachedRowCount = 0 @@ -747,6 +749,7 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData visualIndex.rebuild(from: changeManager, displayIDs: displayIDs) updateCache() tableView.insertRows(at: indices, withAnimation: Self.rowAnimation(.slideDown)) + repaintVisibleRowDecorations() } /// Accessibility > Display > Reduce Motion asks for no sliding rows, and the app @@ -764,6 +767,7 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData visualIndex.rebuild(from: changeManager, displayIDs: displayIDs) updateCache() tableView.removeRows(at: indices, withAnimation: Self.rowAnimation(.slideUp)) + repaintVisibleRowDecorations() } private func bumpDisplayRevision() { @@ -1046,6 +1050,7 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData private func invalidateDisplayCache(forDisplayRow displayIndex: Int, column: Int) { guard let row = displayRow(at: displayIndex) else { return } + displayCache.clearHighlight(forID: row.id) guard let box = displayCache.box(forID: row.id), column >= 0, column < box.values.count else { return } box.values[column] = nil @@ -1062,6 +1067,7 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData invalidateDisplayCache(forDisplayRow: row, column: column) visualIndex.updateRow(row, from: changeManager, displayIDs: displayIDs) redrawCells(rows: IndexSet(integer: row), tableColumnIndexes: IndexSet(integer: tableColumn)) + invalidateRowDecoration(displayRow: row) case .cellsChanged(let positions): guard !positions.isEmpty, let tableView else { return } var rowSet = IndexSet() @@ -1080,6 +1086,9 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData visualIndex.updateRow(row, from: changeManager, displayIDs: displayIDs) } redrawCells(rows: rowSet, tableColumnIndexes: colSet) + for row in rowSet { + invalidateRowDecoration(displayRow: row) + } case .rowsInserted(let indices): guard !indices.isEmpty else { return } overlayEditor?.dismiss(commit: false) @@ -1130,21 +1139,6 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData refreshRowVisualState(at: row) } - func refreshVisibleRowVisualStates() { - guard let tableView else { return } - tableView.enumerateAvailableRowViews { [weak self] rowView, row in - guard let self, let dataRowView = rowView as? DataGridRowView else { return } - dataRowView.applyVisualState(self.visualState(for: row)) - } - } - - func refreshRowVisualState(at row: Int) { - guard let tableView, - let dataRowView = tableView.rowView(atRow: row, makeIfNecessary: false) as? DataGridRowView - else { return } - dataRowView.applyVisualState(visualState(for: row)) - } - func commitActiveCellEdit() { overlayEditor?.dismiss(commit: true) overlayViewer?.dismiss() @@ -1419,7 +1413,7 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData if let delegateState = delegate?.dataGridVisualState(forRow: row) { return delegateState } - return visualIndex.visualState(for: row) + return visualIndex.visualState(for: row).highlighted(highlight(forDisplayRow: row)) } // MARK: - NSTableViewDataSource diff --git a/TablePro/Views/Results/DataGridRowView.swift b/TablePro/Views/Results/DataGridRowView.swift index df68344e02..53faf4f8f1 100644 --- a/TablePro/Views/Results/DataGridRowView.swift +++ b/TablePro/Views/Results/DataGridRowView.swift @@ -37,8 +37,9 @@ class DataGridRowView: NSTableRowView { private var seededRowIndex: Int = 0 - private(set) var visualState: RowVisualState = .empty - private var rowTint: NSColor? + var visualState: RowVisualState { + coordinator?.visualState(for: rowIndex) ?? .empty + } /// Draws the row's data cells. /// @@ -201,14 +202,7 @@ class DataGridRowView: NSTableRowView { "hidden": NSNull(), ] - /// The tint derives from the row state and the active theme, so it is recomputed on every call - /// and the colour comparison below decides whether anything needs redrawing. Returning early on - /// an unchanged state would ignore the theme, which is the input a theme change moves. - func applyVisualState(_ state: RowVisualState) { - visualState = state - let nextTint = state.tint - guard !colorsEqual(rowTint, nextTint) else { return } - rowTint = nextTint + func invalidateVisualState() { needsDisplay = true } @@ -236,8 +230,8 @@ class DataGridRowView: NSTableRowView { override func drawBackground(in dirtyRect: NSRect) { super.drawBackground(in: dirtyRect) - if let rowTint, !isSelected { - rowTint.setFill() + if !isSelected, let tint = visualState.tint { + tint.setFill() bounds.fill() } drawCellSelectionFill(in: dirtyRect) @@ -277,14 +271,6 @@ class DataGridRowView: NSTableRowView { private static let emphasizedCellSelectionAlpha: CGFloat = 0.28 - private func colorsEqual(_ lhs: NSColor?, _ rhs: NSColor?) -> Bool { - switch (lhs, rhs) { - case (nil, nil): return true - case let (l?, r?): return l == r - default: return false - } - } - private func addForeignKeyMenuItems(to menu: NSMenu, dataColumnIndex: Int, tableRows: TableRows) { guard let coordinator, dataColumnIndex >= 0, dataColumnIndex < tableRows.columns.count else { return } let columnName = tableRows.columns[dataColumnIndex] @@ -510,6 +496,14 @@ class DataGridRowView: NSTableRowView { jsonViewItem.target = self menu.addItem(jsonViewItem) + if dataColumnIndex >= 0, + let highlightItem = coordinator.delegate?.dataGridHighlightMenuItem( + forRow: rowIndex, + dataColumn: dataColumnIndex + ) { + menu.addItem(highlightItem) + } + let tableRows = coordinator.tableRowsProvider() addForeignKeyMenuItems(to: menu, dataColumnIndex: dataColumnIndex, tableRows: tableRows) diff --git a/TablePro/Views/Results/DataGridUpdateSnapshot.swift b/TablePro/Views/Results/DataGridUpdateSnapshot.swift index 51c3667cfa..c5a1359b4c 100644 --- a/TablePro/Views/Results/DataGridUpdateSnapshot.swift +++ b/TablePro/Views/Results/DataGridUpdateSnapshot.swift @@ -13,6 +13,7 @@ struct DataGridUpdateSnapshot: Equatable { let columns: [String] let valueFilteredIDsCount: Int? let displayFormats: [ValueDisplayFormat?] + let highlightRules: [HighlightRule] let configuration: DataGridConfiguration let isEditable: Bool let rowReorder: DataGridRowReorder diff --git a/TablePro/Views/Results/DataGridView.swift b/TablePro/Views/Results/DataGridView.swift index a01aebcd71..baabbbbcca 100644 --- a/TablePro/Views/Results/DataGridView.swift +++ b/TablePro/Views/Results/DataGridView.swift @@ -19,11 +19,28 @@ struct RowVisualState: Equatable { let isDeleted: Bool let isInserted: Bool let modifiedColumns: Set + let highlight: RowHighlight + + init(isDeleted: Bool, isInserted: Bool, modifiedColumns: Set, highlight: RowHighlight = .none) { + self.isDeleted = isDeleted + self.isInserted = isInserted + self.modifiedColumns = modifiedColumns + self.highlight = highlight + } func isModified(columnIndex: Int) -> Bool { modifiedColumns.contains(columnIndex) } + func highlighted(_ highlight: RowHighlight) -> RowVisualState { + RowVisualState( + isDeleted: isDeleted, + isInserted: isInserted, + modifiedColumns: modifiedColumns, + highlight: highlight + ) + } + static let empty = RowVisualState(isDeleted: false, isInserted: false, modifiedColumns: []) } @@ -33,7 +50,20 @@ extension RowVisualState { @MainActor var tint: NSColor? { if isDeleted { return ThemeEngine.shared.colors.dataGrid.deleted } if isInserted { return ThemeEngine.shared.colors.dataGrid.inserted } - return nil + return highlight.rowColor?.washColor + } + + func cellHighlightColor(forColumn column: Int) -> HighlightColor? { + guard !isDeleted, !isInserted else { return nil } + return highlight.cellRule(forColumn: column)?.color + } + + func drawnHighlightRule(forColumn column: Int) -> HighlightRule? { + guard !isDeleted, !isInserted else { return nil } + if !isModified(columnIndex: column), let cellRule = highlight.cellRule(forColumn: column) { + return cellRule + } + return highlight.rowRule } } @@ -45,6 +75,7 @@ struct DataGridView: NSViewRepresentable { let isEditable: Bool var configuration: DataGridConfiguration = .init() var displayFormats: [ValueDisplayFormat?] = [] + var highlightRules: [HighlightRule] = [] var delegate: (any DataGridViewDelegate)? var layoutPersister: (any ColumnLayoutPersisting)? /// Whether a row may be dragged to a new position, and why not when it may not. @@ -145,6 +176,7 @@ struct DataGridView: NSViewRepresentable { let initialRows = tableRowsProvider() coordinator.rebuildColumnMetadataCache(from: initialRows) + coordinator.syncHighlightRules(highlightRules, tableRows: initialRows) coordinator.isRebuildingColumns = true let storedInitialLayout = coordinator.layoutDiscardingUnownedWidths( @@ -223,6 +255,7 @@ struct DataGridView: NSViewRepresentable { columns: latestRows.columns, valueFilteredIDsCount: coordinator.valueFilteredIDs?.count, displayFormats: displayFormats, + highlightRules: highlightRules, configuration: configuration, isEditable: isEditable, rowReorder: rowReorder, @@ -320,6 +353,7 @@ struct DataGridView: NSViewRepresentable { let liveColumnWidths = latestRows.columns.isEmpty ? [:] : coordinator.currentColumnWidths() coordinator.apply(configuration: configuration, isEditable: isEditable) let schemaChanged = coordinator.rebuildColumnMetadataCache(from: latestRows) + let highlightsChanged = coordinator.syncHighlightRules(highlightRules, tableRows: latestRows) let presentationChanges = coordinator.updateColumnPresentations(from: latestRows) let needsFullReload = structureChanged || schemaChanged @@ -385,6 +419,8 @@ struct DataGridView: NSViewRepresentable { coordinator.startBackgroundPrewarm() } else if displayFormatsChanged { coordinator.reloadAfterDisplayFormatChange() + } else if highlightsChanged { + coordinator.repaintVisibleRowDecorations() } } diff --git a/TablePro/Views/Results/DataGridViewDelegate.swift b/TablePro/Views/Results/DataGridViewDelegate.swift index f21ea8e748..68b40dc12f 100644 --- a/TablePro/Views/Results/DataGridViewDelegate.swift +++ b/TablePro/Views/Results/DataGridViewDelegate.swift @@ -38,6 +38,8 @@ protocol DataGridViewDelegate: AnyObject { func dataGridShowAllColumns() func dataGridColumnStructureMenuItems(forColumn dataColumnIndex: Int) -> [NSMenuItem] func dataGridRowStructureMenuItems(forRow displayRow: Int) -> [NSMenuItem] + func dataGridHighlightMenuItem(forRow displayRow: Int, dataColumn: Int) -> NSMenuItem? + func dataGridHighlightValuesMenuItem(forColumn dataColumnIndex: Int) -> NSMenuItem? func dataGridVisualState(forRow row: Int) -> RowVisualState? func dataGridRowView(for tableView: NSTableView, row: Int, coordinator: TableViewCoordinator) -> NSTableRowView? func dataGridEmptySpaceMenu() -> NSMenu? @@ -83,6 +85,8 @@ extension DataGridViewDelegate { func dataGridShowAllColumns() {} func dataGridColumnStructureMenuItems(forColumn dataColumnIndex: Int) -> [NSMenuItem] { [] } func dataGridRowStructureMenuItems(forRow displayRow: Int) -> [NSMenuItem] { [] } + func dataGridHighlightMenuItem(forRow displayRow: Int, dataColumn: Int) -> NSMenuItem? { nil } + func dataGridHighlightValuesMenuItem(forColumn dataColumnIndex: Int) -> NSMenuItem? { nil } func dataGridVisualState(forRow row: Int) -> RowVisualState? { nil } func dataGridRowView(for tableView: NSTableView, row: Int, coordinator: TableViewCoordinator) -> NSTableRowView? { nil } func dataGridEmptySpaceMenu() -> NSMenu? { nil } diff --git a/TablePro/Views/Results/Extensions/DataGridView+CellCommit.swift b/TablePro/Views/Results/Extensions/DataGridView+CellCommit.swift index ddb83f651c..285570a131 100644 --- a/TablePro/Views/Results/Extensions/DataGridView+CellCommit.swift +++ b/TablePro/Views/Results/Extensions/DataGridView+CellCommit.swift @@ -20,6 +20,7 @@ extension TableViewCoordinator { invalidateDisplayCache() visualIndex.updateRow(row, from: changeManager, displayIDs: displayIDs) + invalidateRowDecoration(displayRow: row) guard let tableColumnIndex = tableColumnIndex(for: columnIndex) else { return } redrawCells(rows: IndexSet(integer: row), tableColumnIndexes: IndexSet(integer: tableColumnIndex)) } diff --git a/TablePro/Views/Results/Extensions/DataGridView+Columns.swift b/TablePro/Views/Results/Extensions/DataGridView+Columns.swift index d454f915cd..a21e7c2109 100644 --- a/TablePro/Views/Results/Extensions/DataGridView+Columns.swift +++ b/TablePro/Views/Results/Extensions/DataGridView+Columns.swift @@ -142,13 +142,7 @@ extension TableViewCoordinator { func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? { if let delegateRowView = delegate?.dataGridRowView(for: tableView, row: row, coordinator: self) { - // Delegate-provided row views (e.g. StructureRowViewWithMenu) must still - // pick up the deleted/inserted/modified tint. Apply the visual state if - // the row view subclasses DataGridRowView; otherwise the delegate is - // responsible for its own visual state. - if let dataGridRow = delegateRowView as? DataGridRowView { - dataGridRow.applyVisualState(visualState(for: row)) - } + (delegateRowView as? DataGridRowView)?.invalidateVisualState() return delegateRowView } let rowView = (tableView.makeView(withIdentifier: Self.rowViewIdentifier, owner: nil) as? DataGridRowView) @@ -156,7 +150,7 @@ extension TableViewCoordinator { rowView.identifier = Self.rowViewIdentifier rowView.coordinator = self rowView.rowIndex = row - rowView.applyVisualState(visualState(for: row)) + rowView.invalidateVisualState() return rowView } } diff --git a/TablePro/Views/Results/Extensions/DataGridView+RowDecoration.swift b/TablePro/Views/Results/Extensions/DataGridView+RowDecoration.swift new file mode 100644 index 0000000000..b3c8e9538d --- /dev/null +++ b/TablePro/Views/Results/Extensions/DataGridView+RowDecoration.swift @@ -0,0 +1,77 @@ +// +// DataGridView+RowDecoration.swift +// TablePro +// + +import AppKit + +extension TableViewCoordinator { + func refreshVisibleRowVisualStates() { + guard let tableView else { return } + tableView.enumerateAvailableRowViews { rowView, _ in + (rowView as? DataGridRowView)?.invalidateVisualState() + } + } + + func refreshRowVisualState(at row: Int) { + guard let tableView, + let dataRowView = tableView.rowView(atRow: row, makeIfNecessary: false) as? DataGridRowView + else { return } + dataRowView.invalidateVisualState() + } + + @discardableResult + func syncHighlightRules(_ rules: [HighlightRule], tableRows: TableRows) -> Bool { + let key = HighlightRuleSet.Key(rules: rules, columns: tableRows.columns, columnTypes: tableRows.columnTypes) + let compiledChanged = highlightRuleSet.key != key + if compiledChanged { + highlightRuleSet = HighlightRuleSet( + rules: rules, + columns: tableRows.columns, + columnTypes: tableRows.columnTypes + ) + } + guard displayState.highlightRuleSetKey != key else { return compiledChanged } + displayState.highlightRuleSetKey = key + displayCache.clearHighlights() + return true + } + + func highlight(forDisplayRow displayIndex: Int) -> RowHighlight { + guard !highlightRuleSet.isEmpty, let row = displayRow(at: displayIndex) else { return .none } + if let cached = displayCache.highlight(forID: row.id) { return cached } + let resolved = highlightRuleSet.highlight(for: row.values) + displayCache.setHighlight(resolved, forID: row.id) + return resolved + } + + func highlightDescription(row: Int, columnIndex: Int) -> String? { + guard let rule = visualState(for: row).drawnHighlightRule(forColumn: columnIndex) else { return nil } + return HighlightRuleDescription.condition(of: rule, valueLimit: HighlightRuleDescription.menuValueLimit) + } + + func invalidateRowDecoration(displayRow row: Int) { + guard let tableView, row >= 0, row < tableView.numberOfRows else { return } + if let rowView = tableView.rowView(atRow: row, makeIfNecessary: false) as? DataGridRowView { + rowView.invalidateVisualState() + rowView.redrawCells() + } + repaintRowGutter(forRow: row) + } + + func repaintVisibleRowDecorations() { + guard let tableView else { return } + tableView.enumerateAvailableRowViews { rowView, _ in + guard let dataRowView = rowView as? DataGridRowView else { return } + dataRowView.invalidateVisualState() + dataRowView.redrawCells() + } + repaintRowGutter() + } + + private func repaintRowGutter(forRow row: Int) { + guard let rowGutter, let tableView else { return } + let band = rowGutter.convert(tableView.rect(ofRow: row), from: tableView) + rowGutter.setNeedsDisplay(NSRect(x: 0, y: band.minY, width: rowGutter.bounds.width, height: band.height)) + } +} diff --git a/TablePro/Views/Results/Extensions/DataGridView+Sort.swift b/TablePro/Views/Results/Extensions/DataGridView+Sort.swift index 2fd249928c..e0b9ea45f2 100644 --- a/TablePro/Views/Results/Extensions/DataGridView+Sort.swift +++ b/TablePro/Views/Results/Extensions/DataGridView+Sort.swift @@ -170,6 +170,11 @@ extension TableViewCoordinator { menu.addItem(clearAllItem) } + if let dataColumnIndex = dataColumnIndex(from: column.identifier), + let highlightItem = delegate?.dataGridHighlightValuesMenuItem(forColumn: dataColumnIndex) { + menu.addItem(highlightItem) + } + if let dataColumnIndex = dataColumnIndex(from: column.identifier) { addDisplayFormatMenu(to: menu, dataColumnIndex: dataColumnIndex, tableRows: tableRows) } diff --git a/TablePro/Views/Results/ResultStatusBar.swift b/TablePro/Views/Results/ResultStatusBar.swift index 35d02b1ad1..c2fa3a6478 100644 --- a/TablePro/Views/Results/ResultStatusBar.swift +++ b/TablePro/Views/Results/ResultStatusBar.swift @@ -24,6 +24,7 @@ struct ResultStatusBar: View { let snapshot: StatusBarSnapshot let filterState: TabFilterState let columnState: StatusBarColumnState + let highlightState: StatusBarHighlightState let paginationCallbacks: PaginationCallbacks let structureFooter: StructureFooterCapability let execution: ExecutionReadout @@ -37,6 +38,7 @@ struct ResultStatusBar: View { let onStructureRemove: () -> Void @State private var showColumnPopover = false + @State private var showHighlightPopover = false var body: some View { HStack(spacing: StatusBarChrome.clusterSpacing) { @@ -50,6 +52,15 @@ struct ResultStatusBar: View { .statusBarChrome() .onChange(of: snapshot.tabId) { _, _ in showColumnPopover = false + showHighlightPopover = false + } + .onChange(of: showHighlightPopover) { _, isShown in + guard !isShown else { return } + highlightState.onDismiss() + } + .onChange(of: highlightPresentation) { previous, current in + guard previous.tabId == current.tabId, model.controls.showsHighlightRules else { return } + showHighlightPopover = true } } @@ -159,6 +170,9 @@ struct ResultStatusBar: View { if model.controls.showsColumns { columnsButton } + if model.controls.showsHighlightRules { + highlightButton + } if model.controls.showsFilters { filtersToggle } @@ -240,6 +254,43 @@ struct ResultStatusBar: View { } } + private var highlightButton: some View { + Button { + showHighlightPopover.toggle() + } label: { + Label { + Text("Highlight Rules") + } icon: { + Image(systemName: "highlighter") + } + } + .labelStyle(.iconOnly) + .controlSize(.small) + .disabled(highlightState.columns.isEmpty) + .help(String(localized: "Highlight Rules")) + .accessibilityLabel(String(localized: "Highlight Rules")) + .accessibilityValue(highlightAccessibilityValue) + .accessibilityIdentifier("result-status-highlight") + .popover(isPresented: $showHighlightPopover, arrowEdge: .top) { + HighlightRulesPopover( + columns: highlightState.columns, + rules: highlightState.rules, + isPersisted: highlightState.isPersisted, + onChange: highlightState.onChange + ) + } + } + + private var highlightPresentation: HighlightPresentationRequest { + HighlightPresentationRequest(tabId: snapshot.tabId, count: highlightState.presentationRequest) + } + + private var highlightAccessibilityValue: String { + let count = highlightState.activeRuleCount + guard count > 0 else { return String(localized: "No highlight rules") } + return String(format: String(localized: "%d rules"), count) + } + private var filtersToggle: some View { Toggle(isOn: Binding(get: { filterState.isVisible }, set: { _ in onToggleFilters() })) { Label { diff --git a/TablePro/Views/Results/ResultStatusInputs.swift b/TablePro/Views/Results/ResultStatusInputs.swift index 5473a9d500..3c060b58d1 100644 --- a/TablePro/Views/Results/ResultStatusInputs.swift +++ b/TablePro/Views/Results/ResultStatusInputs.swift @@ -16,6 +16,24 @@ struct PaginationCallbacks { let onRequestExactCount: () -> Void } +struct HighlightPresentationRequest: Equatable { + let tabId: UUID? + let count: Int +} + +struct StatusBarHighlightState { + let rules: [HighlightRule] + let columns: [String] + let isPersisted: Bool + let presentationRequest: Int + let onChange: ([HighlightRule]) -> Void + let onDismiss: () -> Void + + var activeRuleCount: Int { + rules.filter { $0.isEnabled && $0.isValid }.count + } +} + struct StatusBarColumnState { let hidden: Set let columns: [GridColumnEntry] diff --git a/TablePro/Views/Structure/StructureGridDelegate.swift b/TablePro/Views/Structure/StructureGridDelegate.swift index abc9f5bd9f..319a9d5f5c 100644 --- a/TablePro/Views/Structure/StructureGridDelegate.swift +++ b/TablePro/Views/Structure/StructureGridDelegate.swift @@ -474,13 +474,6 @@ final class StructureGridDelegate: DataGridViewDelegate { rowView.isStructureEditable = connection.type.supportsSchemaEditing let src = sourceRow(for: row) - // Don't set `isDeleted` / visual state here. `DataGridView+Columns` - // calls `applyVisualState(visualState(for: row))` on every row view it - // returns from `tableView(_:rowViewForRow:)`. Setting it twice is a - // smell that previously hid the bug: when `applyVisualState` was a - // tint-only setter, this line was the only place the menu's - // `isDeleted` flag was assigned, and it was assigned only on row-view - // creation. Single source of truth now is `DataGridRowView.visualState`. if selectedTab == .foreignKeys, src < structureChangeManager.workingForeignKeys.count { rowView.referencedTableName = structureChangeManager.workingForeignKeys[src].referencedTable diff --git a/TablePro/Views/Structure/StructureRowViewWithMenu.swift b/TablePro/Views/Structure/StructureRowViewWithMenu.swift index 7cabb81da2..6cd092ac5c 100644 --- a/TablePro/Views/Structure/StructureRowViewWithMenu.swift +++ b/TablePro/Views/Structure/StructureRowViewWithMenu.swift @@ -11,8 +11,8 @@ import AppKit /// Row view providing a context menu tailored to the Structure tab. Inherits /// selection/emphasis cell invalidation, deleted/inserted-row tint, and the /// `RowVisualState` source-of-truth from `DataGridRowView`. The context menu -/// reads `visualState.isDeleted` directly, so a single `applyVisualState` call -/// updates both the tint and the menu without a shadow flag to keep in sync. +/// reads the same live `visualState` the tint is drawn from, so the two cannot +/// disagree. final class StructureRowViewWithMenu: DataGridRowView { var structureTab: StructureTab = .columns var isStructureEditable: Bool = true diff --git a/TableProTests/Core/DataGrid/RowDisplayCacheTests.swift b/TableProTests/Core/DataGrid/RowDisplayCacheTests.swift index fdf38700ae..ae2b3a0286 100644 --- a/TableProTests/Core/DataGrid/RowDisplayCacheTests.swift +++ b/TableProTests/Core/DataGrid/RowDisplayCacheTests.swift @@ -191,6 +191,27 @@ struct RowDisplayCacheTests { #expect(cache.box(forID: .existing(1)) == nil) } + @Test("A row's highlight lives and dies with its formatted text") + func highlightSharesTheTextLifetime() { + let cache = RowDisplayCache() + let highlight = RowHighlight(rowRule: HighlightRule(columnName: "c", value: "x"), cellRules: [:]) + cache.setBox(makeBox(["x"]), forID: .existing(1)) + cache.setHighlight(highlight, forID: .existing(1)) + cache.setHighlight(highlight, forID: .existing(2)) + + cache.clearValues(forID: .existing(1)) + #expect(cache.highlight(forID: .existing(1)) == nil) + #expect(cache.highlight(forID: .existing(2)) == highlight) + + cache.clearHighlights() + #expect(cache.highlight(forID: .existing(2)) == nil) + #expect(cache.box(forID: .existing(1)) != nil) + + cache.setHighlight(highlight, forID: .existing(3)) + cache.removeAll() + #expect(cache.highlight(forID: .existing(3)) == nil) + } + @Test("Inserted row IDs of both kinds round-trip") func mixedRowIDKinds() { let cache = RowDisplayCache() diff --git a/TableProTests/Core/Menu/MainMenuBuilderTests.swift b/TableProTests/Core/Menu/MainMenuBuilderTests.swift index 03d66c10d8..d088d362d4 100644 --- a/TableProTests/Core/Menu/MainMenuBuilderTests.swift +++ b/TableProTests/Core/Menu/MainMenuBuilderTests.swift @@ -419,6 +419,17 @@ struct MainMenuValidationTests { #expect(enabled(#selector(MainSplitViewController.toggleFilterBar(_:)), context)) } + @Test("Highlight Rules needs a connected data grid with columns") + func highlightRulesNeedsDataGrid() { + var context = MenuValidationContext() + context.canPresentHighlightRules = true + #expect(!enabled(#selector(MainSplitViewController.showHighlightRules(_:)), context)) + context.isConnected = true + #expect(enabled(#selector(MainSplitViewController.showHighlightRules(_:)), context)) + context.canPresentHighlightRules = false + #expect(!enabled(#selector(MainSplitViewController.showHighlightRules(_:)), context)) + } + @Test("Capability flags gate driver-specific commands") func capabilitiesGateCommands() { var context = MenuValidationContext() @@ -445,6 +456,8 @@ struct MainMenuValidationTests { private func capableContext() -> MenuValidationContext { var context = MenuValidationContext() context.canUseTableResultCommands = true + context.canPresentHighlightRules = true + context.canNavigatePages = true context.isQueryTab = true context.hasResultRows = true context.hasQueryText = true @@ -489,7 +502,8 @@ struct MainMenuValidationTests { #selector(MainSplitViewController.openContainerSwitcher(_:)), #selector(MainSplitViewController.showServerDashboard(_:)), #selector(MainSplitViewController.showUsersAndRoles(_:)), - #selector(MainSplitViewController.toggleFilterBar(_:)) + #selector(MainSplitViewController.toggleFilterBar(_:)), + #selector(MainSplitViewController.showHighlightRules(_:)) ] } diff --git a/TableProTests/Core/Services/Highlight/HighlightConditionTests.swift b/TableProTests/Core/Services/Highlight/HighlightConditionTests.swift new file mode 100644 index 0000000000..c18f9d2f9f --- /dev/null +++ b/TableProTests/Core/Services/Highlight/HighlightConditionTests.swift @@ -0,0 +1,147 @@ +// +// HighlightConditionTests.swift +// TableProTests +// + +import Foundation +@testable import TablePro +import TableProPluginKit +import Testing + +@Suite("Highlight condition matching") +struct HighlightConditionTests { + private func matches( + _ value: PluginCellValue, + _ filterOperator: FilterOperator, + _ operand: String = "", + second: String? = nil, + caseSensitive: Bool? = nil, + type: ColumnType? = .text(rawType: "VARCHAR") + ) -> Bool { + let rule = HighlightRule( + columnName: "c", + filterOperator: filterOperator, + value: operand, + secondValue: second, + isCaseSensitive: caseSensitive + ) + return HighlightCondition(rule: rule, columnType: type).matches(value) + } + + @Test("Equality on text is exact and case-sensitive by default") + func textEquality() { + #expect(matches("paid", .equal, "paid")) + #expect(!matches("Paid", .equal, "paid")) + #expect(matches("Paid", .equal, "paid", caseSensitive: false)) + #expect(matches("pending", .notEqual, "paid")) + #expect(!matches("007", .equal, "7")) + } + + @Test("A padded value matches exactly as stored, so a quick rule matches its own cell") + func paddedValuesMatchAsStored() { + #expect(matches("abc ", .equal, "abc ", type: .text(rawType: "CHAR(10)"))) + #expect(!matches("abc", .equal, "abc ", type: .text(rawType: "CHAR(10)"))) + #expect(matches(" ", .equal, " ")) + #expect(matches("42", .equal, " 42 ", type: .integer(rawType: "INT"))) + } + + @Test("NULL fails every comparison and matches only IS NULL and IS EMPTY") + func nullSemantics() { + #expect(matches(.null, .isNull)) + #expect(matches(.null, .isEmpty)) + #expect(!matches(.null, .isNotNull)) + #expect(!matches(.null, .notEqual, "paid")) + #expect(!matches(.null, .greaterThan, "1", type: .integer(rawType: "INT"))) + #expect(!matches(.null, .notContains, "x")) + #expect(!matches(.null, .notInList, "a, b")) + } + + @Test("The literal NULL means IS NULL on a column that is not text") + func nullLiteral() { + #expect(matches(.null, .equal, "NULL", type: .integer(rawType: "INT"))) + #expect(!matches("5", .equal, "NULL", type: .integer(rawType: "INT"))) + #expect(matches("5", .notEqual, "null", type: .integer(rawType: "INT"))) + #expect(!matches(.null, .equal, "NULL")) + #expect(matches("NULL", .equal, "NULL")) + } + + @Test("Numbers compare numerically on a numeric column") + func numericColumns() { + let integer = ColumnType.integer(rawType: "INT") + #expect(matches("1000", .greaterThan, "999", type: integer)) + #expect(matches("1.0", .equal, "1", type: .decimal(rawType: "DECIMAL"))) + #expect(matches("5", .between, "1", second: "10", type: integer)) + #expect(!matches("11", .between, "1", second: "10", type: integer)) + #expect(matches("10", .lessOrEqual, "10", type: integer)) + } + + @Test("Ordering on text compares numerically only when both sides are numbers") + func orderingOnText() { + #expect(matches("1000", .greaterThan, "999")) + #expect(matches("banana", .greaterThan, "apple")) + #expect(!matches("apple", .greaterThan, "banana")) + } + + @Test("Boolean columns accept every spelling of true and false") + func booleans() { + let boolean = ColumnType.boolean(rawType: "BOOLEAN") + #expect(matches("t", .equal, "true", type: boolean)) + #expect(matches("1", .equal, "yes", type: boolean)) + #expect(matches("false", .equal, "0", type: boolean)) + #expect(!matches("f", .equal, "true", type: boolean)) + #expect(matches("1", .equal, "true", type: .integer(rawType: "TINYINT(1)"))) + } + + @Test("Pattern operators ignore case by default and honour Match Case") + func patterns() { + #expect(matches("Hello World", .contains, "world")) + #expect(!matches("Hello World", .contains, "world", caseSensitive: true)) + #expect(matches("Hello", .startsWith, "he")) + #expect(matches("Hello", .endsWith, "LLO")) + #expect(!matches("Hello", .endsWith, "hel")) + #expect(matches("Hello", .notContains, "xyz")) + } + + @Test("Empty means NULL or an empty string on text, and only NULL elsewhere") + func emptiness() { + #expect(matches("", .isEmpty)) + #expect(!matches("x", .isEmpty)) + #expect(matches("x", .isNotEmpty)) + #expect(!matches("", .isNotEmpty)) + #expect(!matches("", .isEmpty, type: .integer(rawType: "INT"))) + #expect(matches("", .isNotEmpty, type: .integer(rawType: "INT"))) + } + + @Test("IN and NOT IN split on commas and trim each item") + func lists() { + #expect(matches("b", .inList, "a, b ,c")) + #expect(!matches("d", .inList, "a, b, c")) + #expect(matches("d", .notInList, "a, b, c")) + #expect(!matches("a", .notInList, "a, b")) + #expect(matches(.null, .inList, "a, NULL", type: .integer(rawType: "INT"))) + } + + @Test("A regular expression searches the value, and an invalid one matches nothing") + func regex() { + #expect(matches("order-42", .regex, "\\d+$")) + #expect(!matches("order", .regex, "\\d+$")) + #expect(matches("ABC", .regex, "abc", caseSensitive: false)) + #expect(!matches("anything", .regex, "(unclosed")) + } + + @Test("A binary value matches only IS NULL and IS NOT NULL") + func binary() { + let bytes = PluginCellValue.bytes(Data([0x01, 0x02])) + #expect(matches(bytes, .isNotNull)) + #expect(!matches(bytes, .isNull)) + #expect(!matches(bytes, .equal, "0x0102")) + #expect(!matches(bytes, .contains, "01")) + } + + @Test("A search past the cap only looks at the leading part of a very long value") + func searchIsCapped() { + let long = String(repeating: "a", count: HighlightCondition.searchLimit + 50) + "needle" + #expect(!matches(.text(long), .contains, "needle")) + #expect(matches(.text("needle" + long), .contains, "needle")) + } +} diff --git a/TableProTests/Core/Services/Highlight/HighlightRuleSetTests.swift b/TableProTests/Core/Services/Highlight/HighlightRuleSetTests.swift new file mode 100644 index 0000000000..b8f5d9713e --- /dev/null +++ b/TableProTests/Core/Services/Highlight/HighlightRuleSetTests.swift @@ -0,0 +1,176 @@ +// +// HighlightRuleSetTests.swift +// TableProTests +// + +import Foundation +@testable import TablePro +import TableProPluginKit +import Testing + +@Suite("Highlight rule set") +struct HighlightRuleSetTests { + private let columns = ["id", "status", "total"] + private let types: [ColumnType] = [.integer(rawType: "INT"), .text(rawType: "VARCHAR"), .decimal(rawType: "DECIMAL")] + + private func row(_ values: PluginCellValue...) -> ContiguousArray { + ContiguousArray(values) + } + + @Test("The first matching row rule sets the row's color, and reordering flips it") + func firstRowRuleWins() { + let paid = HighlightRule(columnName: "status", value: "paid", color: .green) + let big = HighlightRule(columnName: "total", filterOperator: .greaterThan, value: "100", color: .red) + let values = row("1", "paid", "500") + + let paidFirst = HighlightRuleSet(rules: [paid, big], columns: columns, columnTypes: types) + let bigFirst = HighlightRuleSet(rules: [big, paid], columns: columns, columnTypes: types) + + #expect(paidFirst.highlight(for: values).rowColor == .green) + #expect(bigFirst.highlight(for: values).rowColor == .red) + } + + @Test("A cell rule colours its own column and leaves the row rule in place") + func cellRulesColourTheirColumn() { + let rowRule = HighlightRule(columnName: "status", value: "paid", color: .green) + let cellRule = HighlightRule( + columnName: "total", filterOperator: .greaterThan, value: "100", color: .red, target: .cell + ) + let highlight = HighlightRuleSet(rules: [rowRule, cellRule], columns: columns, columnTypes: types) + .highlight(for: row("1", "paid", "500")) + + #expect(highlight.rowColor == .green) + #expect(highlight.cellRule(forColumn: 2)?.color == .red) + #expect(highlight.cellRule(forColumn: 1) == nil) + #expect(highlight.describingRule(forColumn: 2) == cellRule) + #expect(highlight.describingRule(forColumn: 0) == rowRule) + } + + @Test("Disabled and incomplete rules never match") + func disabledAndIncompleteRules() { + let disabled = HighlightRule(isEnabled: false, columnName: "status", value: "paid", color: .green) + let incomplete = HighlightRule(columnName: "status", value: "", color: .red) + let set = HighlightRuleSet(rules: [disabled, incomplete], columns: columns, columnTypes: types) + + #expect(set.isEmpty) + #expect(set.highlight(for: row("1", "paid", "5")) == .none) + } + + @Test("A rule whose column is not in the result is reported, not dropped") + func missingColumnIsUnresolved() { + let rule = HighlightRule(columnName: "archived", filterOperator: .isNotNull, color: .gray) + let set = HighlightRuleSet(rules: [rule], columns: columns, columnTypes: types) + + #expect(set.unresolvedRuleIDs == [rule.id]) + #expect(set.highlight(for: row("1", "paid", "5")) == .none) + } + + @Test("A duplicated column name resolves by occurrence") + func duplicateColumnsResolveByOccurrence() { + let duplicated = ["status", "status"] + let textTypes: [ColumnType] = [.text(rawType: nil), .text(rawType: nil)] + let second = HighlightRule( + columnName: "status", columnOccurrence: 1, value: "paid", color: .blue, target: .cell + ) + let highlight = HighlightRuleSet(rules: [second], columns: duplicated, columnTypes: textTypes) + .highlight(for: row("paid", "paid")) + + #expect(highlight.cellRule(forColumn: 0) == nil) + #expect(highlight.cellRule(forColumn: 1)?.color == .blue) + #expect(HighlightRuleSet.occurrence(ofColumnAt: 1, in: duplicated) == 1) + #expect(HighlightRuleSet.columnIndex(named: "status", occurrence: 2, in: duplicated) == nil) + } +} + +@Suite("Highlight rule descriptions and quick rules") +@MainActor +struct HighlightRuleDescriptionTests { + @Test("A comparison reads as column, symbol and quoted value") + func comparisonTitle() { + let rule = HighlightRule(columnName: "status", value: "paid") + #expect(HighlightRuleDescription.condition(of: rule) == "status = “paid”") + } + + @Test("An operator without a value reads as its name") + func valuelessTitle() { + let rule = HighlightRule(columnName: "notes", filterOperator: .isNull) + #expect(HighlightRuleDescription.condition(of: rule) == "notes is NULL") + } + + @Test("A long value is truncated in menu titles only") + func longValuesTruncate() { + let value = String(repeating: "x", count: 50) + let rule = HighlightRule(columnName: "notes", value: value) + let title = HighlightRuleDescription.condition(of: rule, valueLimit: HighlightRuleDescription.menuValueLimit) + + #expect(title == "notes = “\(String(repeating: "x", count: 32))…”") + #expect(HighlightRuleDescription.condition(of: rule).contains(value)) + } + + @Test("The quick rule follows the clicked cell's raw value") + func quickRuleFromCell() { + let text = HighlightMenuBuilder.quickRule( + columnName: "status", columnOccurrence: 0, columnType: .text(rawType: "VARCHAR"), value: "paid", target: .row, color: .green + ) + let null = HighlightMenuBuilder.quickRule( + columnName: "status", columnOccurrence: 0, columnType: .text(rawType: "VARCHAR"), value: .null, target: .cell, color: .red + ) + let empty = HighlightMenuBuilder.quickRule( + columnName: "status", columnOccurrence: 0, columnType: .text(rawType: "VARCHAR"), value: "", target: .row, color: .red + ) + let binary = HighlightMenuBuilder.quickRule( + columnName: "blob", columnOccurrence: 0, columnType: .text(rawType: "VARCHAR"), value: .bytes(Data([1])), target: .row, color: .red + ) + + #expect(text?.filterOperator == .equal) + #expect(text?.value == "paid") + #expect(null?.filterOperator == .isNull) + #expect(null?.target == .cell) + #expect(empty?.filterOperator == .isEmpty) + #expect(binary == nil) + } + + @Test("A quick rule cannot be built from a value the rule would read as NULL") + func quickRuleRefusesTheNullKeyword() { + let json = HighlightMenuBuilder.quickRule( + columnName: "payload", columnOccurrence: 0, columnType: .json(rawType: "JSONB"), + value: "null", target: .row, color: .red + ) + let text = HighlightMenuBuilder.quickRule( + columnName: "note", columnOccurrence: 0, columnType: .text(rawType: "VARCHAR"), + value: "null", target: .row, color: .red + ) + + #expect(json == nil) + #expect(text?.value == "null") + } + + @Test("Menu sections name the target and the condition") + func sectionTitles() { + let row = HighlightRule(columnName: "status", value: "paid", target: .row) + let cell = HighlightRule(columnName: "status", value: "paid", target: .cell) + + #expect(HighlightMenuBuilder.sectionTitle(for: row) == "Rows Where status = “paid”") + #expect(HighlightMenuBuilder.sectionTitle(for: cell) == "Cells Where status = “paid”") + } + + @Test("Two rules share a condition regardless of their color") + func sameCondition() { + let green = HighlightRule(columnName: "status", value: "paid", color: .green) + var red = green + red.color = .red + let cell = HighlightRule(columnName: "status", value: "paid", color: .green, target: .cell) + + #expect(HighlightRule(columnName: "status", value: "paid", color: .red).hasSameCondition(as: green)) + #expect(red.hasSameCondition(as: green)) + #expect(!cell.hasSameCondition(as: green)) + } + + @Test("Duplicated columns get a numbered label") + func columnOptions() { + let options = HighlightColumnOption.options(for: ["id", "status", "status"]) + + #expect(options.map(\.label) == ["id", "status (1)", "status (2)"]) + #expect(options.map(\.occurrence) == [0, 0, 1]) + } +} diff --git a/TableProTests/Core/Storage/HighlightRuleStorageTests.swift b/TableProTests/Core/Storage/HighlightRuleStorageTests.swift new file mode 100644 index 0000000000..f970093cb6 --- /dev/null +++ b/TableProTests/Core/Storage/HighlightRuleStorageTests.swift @@ -0,0 +1,132 @@ +// +// HighlightRuleStorageTests.swift +// TableProTests +// + +import Foundation +@testable import TablePro +import Testing + +@Suite("Highlight rule storage") +@MainActor +struct HighlightRuleStorageTests { + private let directory: URL + private let connectionId = UUID() + + init() { + directory = FileManager.default.temporaryDirectory + .appendingPathComponent("HighlightRuleStorageTests-\(UUID().uuidString)", isDirectory: true) + } + + private func scope(table: String, database: String? = "shop", schema: String? = "public") -> TableScope { + TableScope(connectionId: connectionId, database: database, schema: schema, table: table) + } + + private var fileURL: URL { + directory.appendingPathComponent("\(connectionId.uuidString).json") + } + + @Test("Rules round-trip through a fresh store") + func roundTrip() { + let rules = [ + HighlightRule(columnName: "status", value: "paid", color: .green), + HighlightRule(columnName: "total", filterOperator: .greaterThan, value: "10", color: .red, target: .cell) + ] + HighlightRuleStorage(storageDirectory: directory).setRules(rules, for: scope(table: "orders")) + + let reloaded = HighlightRuleStorage(storageDirectory: directory) + #expect(reloaded.rules(for: scope(table: "orders")) == rules) + #expect(reloaded.rules(for: scope(table: "customers")).isEmpty) + } + + @Test("Clearing the last rule removes the connection's file") + func clearingRemovesFile() { + let storage = HighlightRuleStorage(storageDirectory: directory) + storage.setRules([HighlightRule(columnName: "status", value: "paid")], for: scope(table: "orders")) + #expect(FileManager.default.fileExists(atPath: fileURL.path)) + + storage.setRules([], for: scope(table: "orders")) + #expect(!FileManager.default.fileExists(atPath: fileURL.path)) + } + + @Test("A table rename moves its rules to the new name") + func renameMovesRules() { + let storage = HighlightRuleStorage(storageDirectory: directory) + let rules = [HighlightRule(columnName: "status", value: "paid")] + storage.setRules(rules, for: scope(table: "orders")) + + storage.rename(from: scope(table: "orders"), to: scope(table: "purchases")) + + let reloaded = HighlightRuleStorage(storageDirectory: directory) + #expect(reloaded.rules(for: scope(table: "orders")).isEmpty) + #expect(reloaded.rules(for: scope(table: "purchases")) == rules) + } + + @Test("A schema rename moves every table's rules in it") + func renameScopeMovesEveryTable() { + let storage = HighlightRuleStorage(storageDirectory: directory) + let rules = [HighlightRule(columnName: "status", value: "paid")] + storage.setRules(rules, for: scope(table: "orders")) + storage.setRules(rules, for: scope(table: "items")) + + storage.renameScope( + connectionId: connectionId, fromDatabase: "shop", fromSchema: "public", + toDatabase: "shop", toSchema: "sales" + ) + + #expect(storage.rules(for: scope(table: "orders", schema: "sales")) == rules) + #expect(storage.rules(for: scope(table: "items", schema: "sales")) == rules) + #expect(storage.rules(for: scope(table: "orders")).isEmpty) + } + + @Test("Deleting a connection removes its rules") + func removingConnectionPurges() { + let storage = HighlightRuleStorage(storageDirectory: directory) + storage.setRules([HighlightRule(columnName: "status", value: "paid")], for: scope(table: "orders")) + + storage.removeRules(for: [connectionId]) + + #expect(storage.rules(for: scope(table: "orders")).isEmpty) + #expect(!FileManager.default.fileExists(atPath: fileURL.path)) + } + + @Test("Every change moves the observed revision") + func revisionMoves() { + let storage = HighlightRuleStorage(storageDirectory: directory) + let before = storage.revision + storage.setRules([HighlightRule(columnName: "status", value: "paid")], for: scope(table: "orders")) + #expect(storage.revision != before) + } + + @Test("An unreadable file is set aside rather than overwritten") + func unreadableFileIsPreserved() throws { + try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) + try Data("{ not json".utf8).write(to: fileURL) + + let storage = HighlightRuleStorage(storageDirectory: directory) + #expect(storage.rules(for: scope(table: "orders")).isEmpty) + + let preserved = directory.appendingPathComponent("\(connectionId.uuidString).unreadable.json") + #expect(FileManager.default.fileExists(atPath: preserved.path)) + #expect(try String(contentsOf: preserved, encoding: .utf8) == "{ not json") + } + + @Test("A rule the app cannot decode is skipped and the rest survive") + func undecodableRuleIsSkipped() throws { + try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) + let key = scope(table: "orders").storageComponent + let json = """ + {"\(key)": [ + {"columnName": "status", "filterOperator": "=", "value": "paid", "color": "green"}, + {"columnName": "status", "filterOperator": "SOUNDS LIKE", "value": "x", "color": "green"}, + {"columnName": "status", "filterOperator": "=", "value": "late", "color": "chartreuse"} + ]} + """ + try Data(json.utf8).write(to: fileURL) + + let rules = HighlightRuleStorage(storageDirectory: directory).rules(for: scope(table: "orders")) + #expect(rules.count == 1) + #expect(rules.first?.value == "paid") + #expect(rules.first?.color == .green) + } +} diff --git a/TableProTests/Models/ResultStatusModelTests.swift b/TableProTests/Models/ResultStatusModelTests.swift index b5d378e0d9..00d7005949 100644 --- a/TableProTests/Models/ResultStatusModelTests.swift +++ b/TableProTests/Models/ResultStatusModelTests.swift @@ -199,6 +199,21 @@ struct ResultStatusModelTests { #expect(!structure.controls.showsPagination) } + @Test("Highlight rules are offered only where the data grid draws the result") + func highlightRulesFollowTheDataGrid() { + let table = makeSnapshot(rowCount: 10) + #expect(model(table, viewMode: .data).controls.showsHighlightRules) + #expect(!model(table, viewMode: .json).controls.showsHighlightRules) + #expect(!model(table, viewMode: .chart).controls.showsHighlightRules) + #expect(!model(table, viewMode: .structure).controls.showsHighlightRules) + + let query = makeSnapshot(tabType: .query, rowCount: 3, hasTableName: false) + #expect(model(query, viewMode: .data).controls.showsHighlightRules) + + let noResult = makeSnapshot(tabType: .query, rowCount: 0, hasColumns: false, hasTableName: false) + #expect(!model(noResult, viewMode: .data).controls.showsHighlightRules) + } + @Test("A query tab never offers table-only controls") func queryTabHasNoTableControls() { var pagination = PaginationState(pageSize: 1_000) diff --git a/TableProTests/Views/Main/ResultStatusBarLayoutTests.swift b/TableProTests/Views/Main/ResultStatusBarLayoutTests.swift index 577126b481..eb163d7508 100644 --- a/TableProTests/Views/Main/ResultStatusBarLayoutTests.swift +++ b/TableProTests/Views/Main/ResultStatusBarLayoutTests.swift @@ -51,6 +51,14 @@ struct ResultStatusBarLayoutTests { onReset: {}, onJumpToColumn: nil ), + highlightState: StatusBarHighlightState( + rules: [], + columns: hasColumns ? ["id", "name"] : [], + isPersisted: tabType == .table, + presentationRequest: 0, + onChange: { _ in }, + onDismiss: {} + ), paginationCallbacks: PaginationCallbacks( onFirst: {}, onPrevious: {}, diff --git a/TableProTests/Views/Results/DataGridCellAppearanceTests.swift b/TableProTests/Views/Results/DataGridCellAppearanceTests.swift index 731f8fbc37..56a47edb1b 100644 --- a/TableProTests/Views/Results/DataGridCellAppearanceTests.swift +++ b/TableProTests/Views/Results/DataGridCellAppearanceTests.swift @@ -179,4 +179,70 @@ struct DataGridCellAppearanceTests { func noAccessoryNoRole() { #expect(resolve().accessoryRole == nil) } + + // MARK: - Highlight rules + + private func highlighted( + column: Int, + color: HighlightColor = .green, + isDeleted: Bool = false, + isInserted: Bool = false, + modifiedColumns: Set = [] + ) -> RowVisualState { + let rule = HighlightRule(columnName: "status", value: "paid", color: color, target: .cell) + return RowVisualState( + isDeleted: isDeleted, + isInserted: isInserted, + modifiedColumns: modifiedColumns, + highlight: RowHighlight(rowRule: nil, cellRules: [column: rule]) + ) + } + + @Test("A cell a highlight rule matches takes the rule's wash") + func highlightedCellTakesTheWash() { + let appearance = resolve(visualState: highlighted(column: 1), columnIndex: 1) + + #expect(appearance.backgroundTint == HighlightColor.green.washColor) + #expect(resolve(visualState: highlighted(column: 1), columnIndex: 2).backgroundTint == nil) + } + + @Test("A modified cell keeps the modified tint over a highlight") + func modifiedTintOutranksHighlight() { + let appearance = resolve(visualState: highlighted(column: 0, modifiedColumns: [0]), columnIndex: 0) + + #expect(appearance.backgroundTint == palette.modifiedColumnTint) + } + + @Test("A find match and a selection both outrank a highlight") + func findAndSelectionOutrankHighlight() { + let found = resolve(visualState: highlighted(column: 0), isCurrentFindMatch: true, columnIndex: 0) + let selected = resolve(visualState: highlighted(column: 0), columnIndex: 0, onEmphasizedSelection: true) + + #expect(found.backgroundTint == palette.findMatchTint) + #expect(selected.backgroundTint == nil) + } + + @Test("A pending insert or delete shows no cell highlight, so it cannot pass for one") + func pendingRowsShowNoCellHighlight() { + let inserted = resolve(visualState: highlighted(column: 0, isInserted: true), columnIndex: 0) + let deleted = resolve(visualState: highlighted(column: 0, isDeleted: true), columnIndex: 0) + + #expect(inserted.backgroundTint == nil) + #expect(deleted.backgroundTint == nil) + } + + @Test("Only a highlight that is drawn is named to VoiceOver") + func drawnHighlightRule() { + let rowRule = HighlightRule(columnName: "status", value: "paid", color: .green) + let cellRule = HighlightRule(columnName: "total", value: "9", color: .red, target: .cell) + let highlight = RowHighlight(rowRule: rowRule, cellRules: [1: cellRule]) + let plain = RowVisualState(isDeleted: false, isInserted: false, modifiedColumns: [], highlight: highlight) + let modified = RowVisualState(isDeleted: false, isInserted: false, modifiedColumns: [1], highlight: highlight) + let deleted = RowVisualState(isDeleted: true, isInserted: false, modifiedColumns: [], highlight: highlight) + + #expect(plain.drawnHighlightRule(forColumn: 1) == cellRule) + #expect(plain.drawnHighlightRule(forColumn: 0) == rowRule) + #expect(modified.drawnHighlightRule(forColumn: 1) == rowRule) + #expect(deleted.drawnHighlightRule(forColumn: 1) == nil) + } } diff --git a/TableProTests/Views/Results/DataGridRowTintThemeTests.swift b/TableProTests/Views/Results/DataGridRowTintThemeTests.swift index 059bc25999..9997f2c42d 100644 --- a/TableProTests/Views/Results/DataGridRowTintThemeTests.swift +++ b/TableProTests/Views/Results/DataGridRowTintThemeTests.swift @@ -4,9 +4,28 @@ // import AppKit +import SwiftUI @testable import TablePro import Testing +@MainActor +private final class FixedVisualStateDelegate: DataGridViewDelegate { + var state: RowVisualState + + init(state: RowVisualState) { + self.state = state + } + + func dataGridVisualState(forRow row: Int) -> RowVisualState? { state } +} + +@MainActor +private final class NoopColumnLayoutPersister: ColumnLayoutPersisting { + func load(for key: ColumnLayoutTableKey) -> ColumnLayoutState? { nil } + func save(_ layout: ColumnLayoutState, for key: ColumnLayoutTableKey) {} + func clear(for key: ColumnLayoutTableKey) {} +} + /// These tests activate a theme on the shared `ThemeEngine`. What keeps that from reaching a suite /// running in parallel is that both bodies are synchronous and `@MainActor`, so nothing else on the /// main actor can interleave between activating the test theme and restoring the original one. @@ -17,8 +36,29 @@ import Testing struct DataGridRowTintThemeTests { private static let deleted = RowVisualState(isDeleted: true, isInserted: false, modifiedColumns: []) - private func makeRowView() -> DataGridRowView { - DataGridRowView(frame: NSRect(x: 0, y: 0, width: 120, height: 24)) + private final class Harness { + let delegate: FixedVisualStateDelegate + let coordinator: TableViewCoordinator + let rowView: DataGridRowView + + @MainActor + init(state: RowVisualState) { + delegate = FixedVisualStateDelegate(state: state) + coordinator = TableViewCoordinator( + changeManager: AnyChangeManager(DataChangeManager()), + isEditable: false, + selectedRowIndices: .constant([]), + delegate: delegate, + layoutPersister: NoopColumnLayoutPersister() + ) + rowView = DataGridRowView(frame: NSRect(x: 0, y: 0, width: 120, height: 24)) + rowView.coordinator = coordinator + rowView.rowIndex = 0 + } + } + + private func makeRowView(state: RowVisualState) -> Harness { + Harness(state: state) } private func renderedTint(of rowView: DataGridRowView) throws -> NSColor { @@ -42,18 +82,53 @@ struct DataGridRowTintThemeTests { defer { engine.activateTheme(original) } engine.activateTheme(theme(original, id: "test.tint.red", deletedHex: "#FF0000")) - let rowView = makeRowView() - rowView.applyVisualState(Self.deleted) - let firstTint = try renderedTint(of: rowView) + let harness = makeRowView(state: Self.deleted) + let firstTint = try renderedTint(of: harness.rowView) engine.activateTheme(theme(original, id: "test.tint.blue", deletedHex: "#0000FF")) - rowView.applyVisualState(Self.deleted) - let secondTint = try renderedTint(of: rowView) + harness.rowView.invalidateVisualState() + let secondTint = try renderedTint(of: harness.rowView) #expect(firstTint.redComponent > secondTint.redComponent) #expect(secondTint.blueComponent > firstTint.blueComponent) } + @Test("A row paints the state its coordinator reports now, not one pushed into it earlier") + func rowPaintsTheLiveState() throws { + let engine = ThemeEngine.shared + let original = engine.activeTheme + defer { engine.activateTheme(original) } + engine.activateTheme(theme(original, id: "test.tint.red", deletedHex: "#FF0000")) + + let harness = makeRowView(state: .empty) + let before = try renderedTint(of: harness.rowView) + harness.delegate.state = Self.deleted + let after = try renderedTint(of: harness.rowView) + + #expect(before.alphaComponent == 0) + #expect(after.redComponent > 0.5) + #expect(harness.rowView.visualState == Self.deleted) + } + + @Test("A pending delete keeps its wash over a matching highlight rule") + func pendingDeleteOutranksHighlightWash() throws { + let engine = ThemeEngine.shared + let original = engine.activeTheme + defer { engine.activateTheme(original) } + engine.activateTheme(theme(original, id: "test.tint.red", deletedHex: "#FF0000")) + + let highlight = RowHighlight( + rowRule: HighlightRule(columnName: "status", value: "paid", color: .blue), + cellRules: [:] + ) + let harness = makeRowView(state: Self.deleted.highlighted(highlight)) + let tint = try renderedTint(of: harness.rowView) + + #expect(tint.redComponent > tint.blueComponent) + #expect(Self.deleted.highlighted(highlight).tint == engine.colors.dataGrid.deleted) + #expect(RowVisualState.empty.highlighted(highlight).tint == HighlightColor.blue.washColor) + } + @Test("A row with no deleted or inserted state stays untinted across a theme change") func plainRowStaysUntinted() throws { let engine = ThemeEngine.shared @@ -61,13 +136,12 @@ struct DataGridRowTintThemeTests { defer { engine.activateTheme(original) } engine.activateTheme(theme(original, id: "test.tint.red", deletedHex: "#FF0000")) - let rowView = makeRowView() - rowView.applyVisualState(.empty) - let firstTint = try renderedTint(of: rowView) + let harness = makeRowView(state: .empty) + let firstTint = try renderedTint(of: harness.rowView) engine.activateTheme(theme(original, id: "test.tint.blue", deletedHex: "#0000FF")) - rowView.applyVisualState(.empty) - let secondTint = try renderedTint(of: rowView) + harness.rowView.invalidateVisualState() + let secondTint = try renderedTint(of: harness.rowView) #expect(firstTint.redComponent == secondTint.redComponent) #expect(firstTint.blueComponent == secondTint.blueComponent) diff --git a/TableProTests/Views/Results/DataGridUpdateSnapshotTests.swift b/TableProTests/Views/Results/DataGridUpdateSnapshotTests.swift index e37360eff5..d8a139b418 100644 --- a/TableProTests/Views/Results/DataGridUpdateSnapshotTests.swift +++ b/TableProTests/Views/Results/DataGridUpdateSnapshotTests.swift @@ -16,6 +16,7 @@ struct DataGridUpdateSnapshotTests { reloadVersion: Int = 0, contentRevision: Int = 0, displayFormats: [ValueDisplayFormat?] = [], + highlightRules: [HighlightRule] = [], columnComments: [String: String] = [:] ) -> DataGridUpdateSnapshot { DataGridUpdateSnapshot( @@ -24,6 +25,7 @@ struct DataGridUpdateSnapshotTests { columns: columns, valueFilteredIDsCount: nil, displayFormats: displayFormats, + highlightRules: highlightRules, configuration: DataGridConfiguration(), isEditable: true, rowReorder: .disabled, @@ -79,6 +81,20 @@ struct DataGridUpdateSnapshotTests { #expect(raw != uuid) } + @Test("A highlight rule change invalidates the update snapshot") + func highlightRuleChangesSnapshot() { + let rule = HighlightRule(columnName: "type", value: "admin", color: .green) + var recolored = rule + recolored.color = .red + + let highlighted = makeSnapshot(highlightRules: [rule]) + let rebuilt = makeSnapshot(highlightRules: [rule]) + + #expect(makeSnapshot() != highlighted) + #expect(highlighted != makeSnapshot(highlightRules: [recolored])) + #expect(highlighted == rebuilt) + } + @Test("Display format cache entries are scoped to a pinned result set") func displayFormatCacheUsesResultSetIdentity() { let firstResult = UUID() diff --git a/TableProTests/Views/Results/TableViewCoordinatorHighlightTests.swift b/TableProTests/Views/Results/TableViewCoordinatorHighlightTests.swift new file mode 100644 index 0000000000..0d644c8514 --- /dev/null +++ b/TableProTests/Views/Results/TableViewCoordinatorHighlightTests.swift @@ -0,0 +1,145 @@ +// +// TableViewCoordinatorHighlightTests.swift +// TableProTests +// + +import AppKit +import SwiftUI +@testable import TablePro +import TableProPluginKit +import Testing + +@MainActor +private final class HighlightTestPersister: ColumnLayoutPersisting { + func load(for key: ColumnLayoutTableKey) -> ColumnLayoutState? { nil } + func save(_ layout: ColumnLayoutState, for key: ColumnLayoutTableKey) {} + func clear(for key: ColumnLayoutTableKey) {} +} + +@MainActor +private final class StructureStateDelegate: DataGridViewDelegate { + func dataGridVisualState(forRow row: Int) -> RowVisualState? { .empty } +} + +@MainActor +private final class HighlightGrid { + var tableRows: TableRows + let coordinator: TableViewCoordinator + + init(statuses: [String], delegate: (any DataGridViewDelegate)? = nil) { + let rows = ContiguousArray(statuses.enumerated().map { index, status in + Row(id: .existing(index), values: [.text("\(index)"), .text(status)]) + }) + tableRows = TableRows( + rows: rows, + columns: ["id", "status"], + columnTypes: [.integer(rawType: "INT"), .text(rawType: "VARCHAR")] + ) + coordinator = TableViewCoordinator( + changeManager: AnyChangeManager(DataChangeManager()), + isEditable: true, + selectedRowIndices: .constant([]), + delegate: delegate, + layoutPersister: HighlightTestPersister() + ) + coordinator.tableRowsProvider = { [weak self] in self?.tableRows ?? TableRows() } + coordinator.tableRowsMutator = { [weak self] mutation in + guard let self else { return } + mutation(&self.tableRows) + } + coordinator.rebuildColumnMetadataCache(from: tableRows) + coordinator.updateCache() + } + + @discardableResult + func apply(_ rules: [HighlightRule]) -> Bool { + coordinator.syncHighlightRules(rules, tableRows: tableRows) + } + + func rowColor(_ row: Int) -> HighlightColor? { + coordinator.visualState(for: row).highlight.rowColor + } +} + +@Suite("Grid coordinator highlight rules") +@MainActor +struct TableViewCoordinatorHighlightTests { + private let paid = HighlightRule(columnName: "status", value: "paid", color: .green) + + @Test("Only the rows a rule matches carry its highlight") + func matchingRowsCarryTheHighlight() { + let grid = HighlightGrid(statuses: ["paid", "pending", "paid"]) + grid.apply([paid]) + + #expect(grid.rowColor(0) == .green) + #expect(grid.rowColor(1) == nil) + #expect(grid.rowColor(2) == .green) + } + + @Test("Changing the rules reports a change and recolours rows already evaluated") + func changingRulesRecolours() { + let grid = HighlightGrid(statuses: ["paid"]) + #expect(grid.apply([paid])) + #expect(grid.rowColor(0) == .green) + + var recolored = paid + recolored.color = .red + #expect(grid.apply([recolored])) + #expect(grid.rowColor(0) == .red) + #expect(!grid.apply([recolored])) + } + + @Test("An edit that flips a rule is reflected once the edit commits") + func editFlipsTheHighlight() { + let grid = HighlightGrid(statuses: ["pending"]) + grid.apply([paid]) + #expect(grid.rowColor(0) == nil) + + grid.coordinator.commitTypedCellEdit(row: 0, columnIndex: 1, newValue: .text("paid")) + + #expect(grid.tableRows.rows[0].values[1] == .text("paid")) + #expect(grid.rowColor(0) == .green) + } + + @Test("New rows under the same positional ids are evaluated afresh once the cache is dropped") + func positionalIdsAreNotServedStaleHighlights() { + let grid = HighlightGrid(statuses: ["paid"]) + grid.apply([paid]) + #expect(grid.rowColor(0) == .green) + + grid.tableRows.rows[0].values[1] = .text("pending") + grid.coordinator.invalidateDisplayCache() + + #expect(grid.rowColor(0) == nil) + } + + @Test("A fresh display state for a new page carries no highlights from the old one") + func freshDisplayStateStartsClean() { + let grid = HighlightGrid(statuses: ["paid"]) + grid.apply([paid]) + #expect(grid.rowColor(0) == .green) + + grid.tableRows.rows[0].values[1] = .text("pending") + grid.coordinator.adoptDisplayState(DataGridDisplayState()) + grid.apply([paid]) + + #expect(grid.rowColor(0) == nil) + } + + @Test("A grid whose owner supplies its own row state is never highlighted") + func delegateStateSuppressesHighlights() { + let delegate = StructureStateDelegate() + let grid = HighlightGrid(statuses: ["paid"], delegate: delegate) + grid.apply([paid]) + + #expect(grid.rowColor(0) == nil) + } + + @Test("The accessibility description names the rule that coloured the cell") + func accessibilityDescription() { + let grid = HighlightGrid(statuses: ["paid"]) + grid.apply([paid]) + + #expect(grid.coordinator.highlightDescription(row: 0, columnIndex: 0) == "status = “paid”") + } +} diff --git a/TableProUITests/HighlightRulesUITests.swift b/TableProUITests/HighlightRulesUITests.swift new file mode 100644 index 0000000000..5cb6e155c4 --- /dev/null +++ b/TableProUITests/HighlightRulesUITests.swift @@ -0,0 +1,106 @@ +// +// HighlightRulesUITests.swift +// TableProUITests +// + +import AppKit +import XCTest + +final class HighlightRulesUITests: UITestCase { + func testAddingARuleFromTheStatusBarKeepsItForTheTable() throws { + let app = try launchWithSampleDatabase() + let window = try readyWindow(of: app) + _ = try albumGrid(in: window) + + openRulesFromStatusBar(in: window) + let add = window.buttons["highlight-rules-add"].firstMatch + XCTAssertTrue(waitUntilHittable(add, timeout: 10), "The popover must offer Add Rule") + XCTAssertFalse(ruleCheckbox(in: window).exists, "A table nobody highlighted starts with no rules") + add.click() + XCTAssertTrue(ruleCheckbox(in: window).waitToExist(timeout: 10), "Add Rule must list a new rule") + app.typeText("1") + + app.typeKey(.escape, modifierFlags: []) + XCTAssertTrue(add.waitForNonExistence(timeout: 5), "Escape in the value field must close the popover") + + openRulesFromStatusBar(in: window) + XCTAssertTrue( + ruleCheckbox(in: window).waitToExist(timeout: 10), + "A rule belongs to the table, so reopening the popover lists it again" + ) + + let reopenedAdd = window.buttons["highlight-rules-add"].firstMatch + XCTAssertTrue(waitUntilHittable(reopenedAdd, timeout: 10)) + reopenedAdd.click() + XCTAssertTrue(waitForPredicate(timeout: 10) { self.ruleCheckboxes(in: window).count == 2 }) + app.typeKey(.escape, modifierFlags: []) + XCTAssertTrue(reopenedAdd.waitForNonExistence(timeout: 5)) + + openRulesFromStatusBar(in: window) + XCTAssertTrue(ruleCheckbox(in: window).waitToExist(timeout: 10)) + XCTAssertEqual(ruleCheckboxes(in: window).count, 1, "A rule closed without a value is not kept") + } + + func testTheCellMenuOffersHighlightAndOpensTheRules() throws { + let app = try launchWithSampleDatabase() + let window = try readyWindow(of: app) + let grid = try albumGrid(in: window) + + let cell = gridPoint(in: grid, of: window, dy: 70) + cell.click() + Thread.sleep(forTimeInterval: NSEvent.doubleClickInterval) + cell.rightClick() + + let highlight = window.menus.menuItems["Highlight"].firstMatch + XCTAssertTrue(highlight.waitToExist(timeout: 15), "A cell's context menu must offer Highlight") + highlight.hover() + + let showRules = contextMenuItem("Highlight Rules…", in: app) + XCTAssertTrue(waitUntilHittable(showRules, timeout: 10), "The Highlight submenu must offer Highlight Rules…") + showRules.click() + + XCTAssertTrue( + window.buttons["highlight-rules-add"].firstMatch.waitToExist(timeout: 10), + "Highlight Rules… must open the rules popover" + ) + } + + // MARK: - Helpers + + private func readyWindow(of app: XCUIApplication) throws -> XCUIElement { + let window = app.windows.matching(NSPredicate(format: "identifier != %@", "welcome")).firstMatch + XCTAssertTrue(window.waitToExist(timeout: 60), "The sample database produced no window") + XCTAssertTrue( + waitForPredicate(timeout: 30) { window.outlines.firstMatch.outlineRows.count > 1 }, + "The object browser must list the sample database's tables" + ) + return window + } + + private func albumGrid(in window: XCUIElement) throws -> XCUIElement { + let row = window.outlines.firstMatch.staticTexts + .matching(NSPredicate(format: "value == %@", "Table: Album")) + .firstMatch + XCTAssertTrue(row.waitToExist(timeout: 20), "The object browser must list Album") + clickAtCenter(row) + + let grid = window.tables.matching(identifier: "data-grid").firstMatch + XCTAssertTrue(grid.waitToExist(timeout: 30), "Album produced no data grid") + XCTAssertTrue(waitForClickableRows(in: grid), "Album must load rows before a cell can be highlighted") + return grid + } + + private func openRulesFromStatusBar(in window: XCUIElement) { + let button = window.buttons["result-status-highlight"] + XCTAssertTrue(waitUntilHittable(button, timeout: 15), "The status bar must offer Highlight") + button.click() + } + + private func ruleCheckbox(in window: XCUIElement) -> XCUIElement { + ruleCheckboxes(in: window).firstMatch + } + + private func ruleCheckboxes(in window: XCUIElement) -> XCUIElementQuery { + window.checkBoxes.matching(identifier: "highlight-rule-enabled") + } +} diff --git a/docs/features/data-grid.mdx b/docs/features/data-grid.mdx index dd8110ceae..9fc8d6c10c 100644 --- a/docs/features/data-grid.mdx +++ b/docs/features/data-grid.mdx @@ -1,9 +1,9 @@ --- title: Data Grid -description: Sort, size, hide, chart and copy the rows a table or a query puts in the grid +description: Sort, size, hide, highlight, chart and copy the rows a table or a query puts in the grid --- -Most of the grid's controls sit in the status bar beneath it. The view switcher is at the leading edge, the row count in the middle, then the columns, filter and page buttons at the trailing edge. +Most of the grid's controls sit in the status bar beneath it. The view switcher is at the leading edge, the row count in the middle, then the columns, highlight, filter and page buttons at the trailing edge. Data grid @@ -40,6 +40,23 @@ The header menu carries two filters that answer different questions. A value filter lives as long as the result does: switching view mode or tab keeps it, replacing the result clears it. **Fetch All** keeps it and applies it to the rows it loads. +## Highlighting + +Right-click a cell and open **Highlight**. A color under **Rows Where status = “paid”** tints every row holding that value; a color under **Cells Where status = “paid”** tints only that cell. The palette marks the color a matching rule already uses, and **Remove Highlight** takes the rule away. + +For anything other than an exact match, click the highlighter button in the status bar or choose **View > Highlight Rules**. A rule is a column, an operator from the [filter bar](/features/filtering), a value, a color, and **Row** or **Cell**. **Highlight Values…** in the header menu starts a rule on that column. A rule left without a value is dropped when the popover closes. + + + Highlight Rules popover listing three rules over an Invoice grid with tinted rows and cells + Highlight Rules popover listing three rules over an Invoice grid with tinted rows and cells + + +Rules run top to bottom and the first match colors the row, so drag the rule that should win to the top. A rule picked from the cell menu goes in first. A cell rule tints its own cell over the row's color. Rules read the stored value rather than the text a **Display As** format shows: a numeric column compares as numbers, a boolean column accepts `true`, `1`, `t` and `yes` alike, and `NULL` never satisfies a comparison: match it with **is NULL** or **is empty**. + +A row waiting to be inserted or deleted keeps its [change tracking](/features/change-tracking) tint over any rule, and a selected row shows the selection. On a table you edit, give row rules a color other than the green and red those tints use, so a highlight never reads as a pending change. + +Rules belong to the table, scoped to the connection, database, and schema, and follow the table through a rename. A query result that comes from one table uses that table's rules. Rules on any other query result are not saved, and go when the tab closes or the app quits. Saved rules stay on this Mac and do not sync. + ## Columns Drag a border to resize a column, or double-click it to fit the content; **Size to Fit** and **Size All Columns to Fit** on the header menu do the same. A fitted column stops at half the visible grid width. diff --git a/docs/images/highlight-rules-dark.png b/docs/images/highlight-rules-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..7f5c21fc9b42747c190d1ae14796594fa0f3a940 GIT binary patch literal 1884022 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

UG|l#})6ftprh?0u=$C*{&FC!=tu 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

P)UxDJW1-#58{ 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

mBvO;9Sb*OJO(nyh>GS-zBEo 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

  • IkJxZobb9yruI+{&FK81!3Ryr&I4N)A zv!Oi;XbKhOYk!vcMzW{*bt+JfW?dxOrO(AnIrgCvlnRp2OP>S{ASbI&L%K&ItVnF3 zUlSk;K7c1hNZ@9~{ZP*S!I`KJLb+bQ`a

    |Wj&H4NGfD=D|>@;Mv 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¬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

    &!?_t;*;sw@K|4( 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

    1XXAyeV7ffj*!>^R^567x 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 LerUVgNq7v%(wy0dPnK$za9W!D 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%0ADAl<&0 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 na;IBpoY^D13!6+f;!9t?sz}p>P;l9VZN?zLJ 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

      `OW{d-NJrm~s0;xJx1@49EK%Ir2Dh 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

      FL6bOX(!%ZsVm5@wA^38m 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
      T9@vP+l;t^coGnidzR(C`)Zc3 zRPe(EWb%`Vv2V%#f(Z`&{f!&&KA~KguQ5DC$;AOy>;%1v{=ZHi46CL427|iU)n^>vGN-6jEEZ6+NH2i%XodQVc z1DW-hx}YE5zwVPS5unM_fVHw`flD#n(UZD>EjIp;%0;;V*Tm>o#mxV0iusWb3erhaRp_O=oBo*N@ao2HVnN!^K7J->3er(3d=97l2_o z)bi?kVClFn@Lz9_$HKi4fbEUG^?Tl5kO!^U`F!iA{M=T;m?Cs@cYJgpm1^grxuuo&G|8e6QoPWm6u{{Q&)6M3zRe$w^ooit2` zMnwDAf4zUpE4)ivba33@wotzbZGqT+Mod4SfO4W#-+itizCYE-bEgnTtsSVA=zpCP z0Wn@Uhcz-y{koRK$7@OYuM3pMnxA)3V(YLLn>QTJFPN~&j&V(EwuXO%vO;enjPgQQRlR-i*j#oGP~#{Hm1tn}$@%fA0V=;k#C z`pqynz8cA$Q?&HKp`D2zu^y~YUWyn00OM$!F_a!*e=a6znYIJlye|8L%9O@w4oFJ& z)lr6)umECqIoXs0)?OI!2wu1}kq(0;Lk}GB!X-sAl$0ZQ&mV*BsK?;kSKC`E%$lkX zmRlN@yvn{Uug9?QM}fSG-*D*2FYIX|9!pg1@vi?rzz*QJ0qm!MntNu0$AN80uDLZy zaln9Ny!rGqR{GCJ^y|OkZlK>0Sv$qmcQlDF>u8}O-T=Fm(v;s#ZIX=F4SXcMx?TZ{ zkq3>K#{M(q2;LX=r@z4ngNg>idMxyJ;Lpnk!)1t{_EQ$_Tecz=h>i?gWTYEJ*s`E}{F56WtK1dJm3f*x1r zY6YV?29Px`QD#Hn7*r8{9icjN4iy$i^N*9Ag((PGQs^VT*EoY2(e=EAAP+Rn^ot>7 z%|~58kV}-+sedhVT;lkOSoHAqKUa3&(M<>rcYe6dTn^M>>`Ig8xqTwLAL3SCD@= zEG@ieg8LLECw5x*m!OyE(Zh~YS&==lT$t$hog-LLT}8Mq z-0x=mA;Gi6)lI11GE=Wh+gzx*%NMtNt47C^Amot13ib+q+=+r-R^xXK+ur1@lqe~b z5Z*RZB>xKwAMZJuEi1H^Z@X9sUlEz5z4*a6POtp0Sof3okOgyOi6jmN|Kf3ky*yf3 zX$z7%>Ifpb43+R3%lZ1{$rJrD4V)0Mev{j;jMa{y5%;!3et~bkGzlNVz8B3j$n=KU z<_uJ69)y1X1xdqwl$D(@QfC@?|dA_|YGlspl6k6DJ z7!~{bG-b$Yt(ZK;7RjK;t8^#|-%|lpfQxV-o^x~gbL|`+KM+g03Ec$HT|h~hYyyx7 zXyLwKq)=AINGm=I=Fo5dj|JfAn;*ULUAY!lb^)mZC?4W5758GaQ>^mHA12lROoS|6 z^X#B=TG&#L-$H4bemFu?{2Kxl1Bk{UKH`Fgr!{oF$?Nccc?L~T-v?53wzXCvG z6|T^9^=Vuiny~&>=GvIq!sNd9L=W_$=+)q#T?TaqE$WUlb+3!lK!y$~y-k|sD4y0} z=epo3rAF_cmYwvD+p35d|DW@?XsC7m)Oid~?J(J!?`xu8-S&~N57brPBZl`x9hJ?+ z%yDH(HxB|g2GX3AJ)Sv>pj!;sZ>TPa4)Uq5N#{zQp*1I-^^ zVEsy2&cWxB27re@jMMZquGxkSL9977SmTlmK0%iq6%bFpZBf+?Xb?kn8^2;=H@H7N zYbNx+uMSOFWWqlE5=M0H#^@w#H0``~^QSnGo_S{RkQ?y6)%fS@ zL%6Z5spNt6c2GMbuBcIAL%EBu`3|kdNut$sHRH(_tpcx@MxrSug7+XcA<%;GvjwDMl~mt~R20s}WJaj+=3eIs4S z?8eur;^VzAFk}+1RO)098ZhG>5(#<9Mg&#pYW~ZBuCcwT*qV5rBsk3NkLUvoBduPz zWLa@{rM;U{!!cndGww7wkexy*wpEBekUc{VlVe@ZGm+=Udkro08d?&PnLGae_uj=9Sc@-{ zCv%>C_St9e97yeoge$1%5VIDt)ewB=9%78KAb&j?=bEKK@* zgrI{);(%wr)_@^s?slJzJ`N*%a9TZwKGRkC$OcG#z#z8pb`QOWy1R==F#Pc6SvsUA z_~u+R7z4tj`&ckp`vQ$0qqiJttk8&`LOP6kQ?ke~)s4VFH?)zI3KRFv>+VEcYPYWT zz3UPXNjFw;T`i{SrFDaeN6*~^N%(UXr5mQEe)9QYrOvlxi+_JHP#?$$UAelZ{l_z; zB7{k=wS7cT;}Snd0MDITe|IYW_l9`Oc>Z!%1bJoL+3-p7PT$FY(}k{qAz0~eO)gug z3nT$;TWf!YxRQq1?^hvCN?n@-sBHwU@P;l*9;fM$#t40cI5tsYVi~@jNf6KkFVS{( zpnA8|o_l6paS>vt&@4S9zq|jKc4#&3$Kx>YO68Mx44sdF)1jY0F^bAFQR3oRm0btC zbTq>d@=w?rqV=tGc+1&u$7Z>Hvya#ITsDBZBMAyxjD+d9AgDc2-FEA6wR}Z?0|=)7 zcO)WR9Jg41GkDxDOW8vFRIjG4Gzn_F%;zl$aG3=uSFVd-n7xud#DYwxr{D zN#U#P*<#}=ts7eDf|_Yk$<8yi$s{vwFQMeT-|%5xq^{4ollRRb`<2ii(Re1dT?IWR z(TKJJK{URhoX$2loKfBV<~N1ym-9w0RGk4C#M8$WFG7rGxEL7kh#1_D z|JoL_w1y;#n`rsmf0XwusN{w0vsMx{h9=#q+kBV#0--?Q00pB+MpoY|3C?_jy#MJQ z+yfNch=w=+Kn>0fk&hr{e_|WG&ox~fz)^wWvD$bPlN2oe1j;!LUR`?xF;%`gSn>S) zxukw%4y^%YCsR;Uc$%Y!Qr&v)7X~6H5V0|T!81H(($vLX9;L3K&eN77`5Y~dXwIpG zMPo*Of%<sZmKcO;1G_;tD!1+f7IUsj{zJy(w8YWYZ+S8HB-E^_<6W&So* zP!?%?p03Z2IdUWG-BO%7&!vnBs0}!M^CS71ZS`L6*_jb;p^<}~YdaN%o=n6`X9KZ? z0kuz9^_1VHn)%(lyqMvQO@>8nym&7EmMq`x>P3c$tiDXrT7oK1f^DX6&I3ugdaUnC z1|D|XQCGI`Y`@{`=R51W(h1vr^U-r8IW|PysZ|3{)*S{5?U;#&W2n2cB^E7KTeWZ1 zW&@9>4E7!2U4DUKBC& zv&y)Ev$f0ZwCtf;Ee>E*+xy{izgXfN_+zL(WW<8+><_pGAXFgd)ut)jS`Um#_9puX z*iK~uW?f~_A@F|BOH%vLPfYDE{8q}Hqwr3&&lW46XF2jO_`Vc*CNG+H?LQvMcYBDR zla_G+q3g4or5|SiG~+@Jk1!HTMvqJje+aGA2C^x#@bMh-Z54>@$yw2MB$0mMYZZE_ptYjO=;~XMMig;$7Y;A>fYZRC^+dp8C9oXX z14^DG`U#tEX%~lRLZ89Al!ECwqh_OQ5~nAhYu}}qr^N>dwm+RDzl*^48Tz1hnz=~H zJ>(PH6U=v-U+n?hrg58wys|nZkt&u@cwi*mrw@IM`Npt-yV2Z!Hq=FwDwOJq_qg_gqJ19s`4`%A`~ zn)>T3Y2o)csq+z3TT$j5dXeQ74)&9*4 zKUW+l+RXC7ALXS-DAk4Vvb`F@L4ygPnTn?*pbxJGVS}iVqL;3nbi{nSp16j&wbj>a z_sckvI{}foL%C~8z}(su(mDHVIQQ7~q@W4m8ncErAG@M@_rJ9F3QaM&2nq+2d_vl* zX0n{7oEX?=SxC552V}g4RXE`V}cK&_dpgq}^oV)o9P7+*up#2W* zx=3tqJ#@U93+SvR$|!_LzjC#X*Qklft%3J@{ieZ$BFp?8m^S3=9W!PR|D4M-bt2 zO%I4rSZLeV4opUJL0-LtMx_UvkDRaEW(rtKgxp;2f%VgS28qbiqZ;5x@&$=Y+x&3G zAUVtAszqIgW;UVtJsq8&r6@>S;s`$htA&jCqnX-oE5i3r%nAZm@P0C8`ujPE3D(w!>>-^H;JKfUWEV0b{;l|VI~AARkTfd- z#_wKdV0OMwAcr0+dr-{p>3iSKi%1VS^b^ieyVM^YTvKNGC_Py0-B$% zMEruqYpUBqwQGaf>eGUZiUjjNz711S#@**wO?c(EDiWhPrL}ncH^n}Qdws4aj!u=~ zQjEJ`XBDGcjB*o0zTg|mN!KUa%$qZH-l?cLQQ#k-nD(tHd)4`@N5Jewm$_Wu@#cW3 zmLkzAB2-|aHaWi#zI)z@USe|m>b>T{X(+m;Yf+GA!Mi0kXB}3RN*Os#ok?dFFJChu z*UlQq(RKk_=fW{`y}j7~;w*9Y@sfk&Z;>&S>6P#5^LWdqJeS?_n01d6PO`ouaEadc zdNi`{7+i12k%GcE`urDxK^5K&Q!1MZvUd29_liP^=B1ZcSEnoKE!!kEap*(EneWh>Xnk#>ss~V#ErFZ zHF1h1sr?{s4PBxqN#Xo(!3H?RZV|(jeFd6C^?*-fIGR%NOhJVZYc~5!K@CkC;1VJS zXx6hJ2|QrFSp<0A^#AzPiA)=_a_J==@k5l7Dn&wZpY)sG0ESe-{Cn2;)K}-v{1{s* zUikLtknt6Rt-rnOD70VEUN8WIzMcu-CQb=)D3RISZe;q!f((;VmV;`wH$0UmBWF*eUFs0e%eK)eo)f7wC<`cj)?{ z0mx1J?ix*5H1VoiAQ4w+W;>s>_Oa+ zv`*UJ18u**kdK*J&ER42^x5Pd;O6y~iV7k!4bn&@V)fbhziP(!)fkmSJz$>_M706= zY#{9&_B5@xipj~a5w>MyTHGV*cvg(p&Y9dYk420t?XP>!c%`Nf0B;&d z#1*vlN{06lntx2FsG4s zugKFcIGq=A{PJ~Xi2B+;g;`saUb3n2lOF1q_fH9aGmtOXD&VoO{VY4-6I0+fwn(*5 z9O`Px!zx*C7?AxkrjZFqov4RafZzEj*0qpIPCv?O zzeA~2r>Dl8gxy5!1Nk>k`nXnqr$1hp{N*&IwvOvgRfP|v7z5S{o3cPt)J`wjy}taL zm(n2=71Cp7MP5`0;+;3gOWn9vyC*LIi!stHa{X{%F*ZTrr3m{Opr@mHzt{M#Q3x&Cnz>uj#vG<0I-@;-;Qt&GPJA`ANds*)K2#b-kP<5Fuu z26q2RaCx7_A2)8nQ>D>VTrcz>;2sYxv4(-w!<^@#;bD}JS&jqoVlGv_S@Zv176BU9 ziqm6H_K@<~OTc#xOR(yw*#5*e>|fQhrCoEEnzs53YSNHx%P5uvX`;bhiVGh331lP| zjgwHl+l3z}b_c0+6e9>r=v#`50X|V|k5GYC5ZT8E*M|8Eik|ROR*>SFpgd2TZ0EYb zc3Y+0h8%nD?;`WMs=T`6V%XnAZjxc}G#7NO;C@P@XCo|LDT#s}VWFtLJ5TKNv+ZYrG>wJ(sJJ(KOLS z!o7_3f4Q)-*Yuz1XGb|kmM|A$y**t6>J(!GPkvr$+!Ntiy|mNvMxqa2Wo;&)@$u=p zaY(wO-S7{cyyJj@YPZGe9g2F+NQM_Bs=rchou#YSnV#yp=p`dbgN2{>{#CKCU;=mEsqse^>JBi3uKO`DA6NZui}ZbEkls9K5uvPE-ER?v+9I6HPN2&|Uo1WpZc zLTO|P;!Y)c@cun6K#~Agtu}DJqlVT?w;_CX6}#(lR6K!UpMmb4U?coDpi_*)b!Nwx zZ(qk@IJbMrMBDq@_a74^+{xVp?A^*eIT{e5SMfb*~gE zF)m1;49*7rl9}xul%%=M*V84ScL)C5H~e7)u=!m=F9zh^`7Qz(p9qYBYj>cbEJ_WP z_Lsay`%mA2Au4D(_=dz5q6O25u{ywX0xy)3O94;o@*KA$+XLGJRgV166eqIkw0;;g zT}?g21|{tO!*bUcKaq7J8kIG>!u-TRJ96K1fx|@5t@22kBn@gC6IHcrN{Axi7oJFO z&pGV_N@qN4djLPp+))PE>vJFVenDh{v=8T#$u`V@qoeGX77`SBA)Jx?q4tn|?X2_- zXg!MT{kq=4tD>$FGXMj>m~Kpx`xoq2Yo_OE|FKlN!EPkZ(peetcLqvWgc^g)I={YM zr-jozBCL+c`+eQ?($l64_zvJ!O{HigdD{w7)@mbRD zGV%GCbe>67ZCgw-YK+Y_%yPtG{%=oyZk(pk46$|Dr4McaPRY~BO@#1J(Xg1b2Z!)2 zA<6TA6lNY#*>G}wHozdUitx=X-6OoMO&&SEl-^E&SBA|*ryS9`q*PR4)}=S}szA*h zX;srotxxRYRBUrsGHQWtNJ2QhNVE z>5ppMLA@U$na_$Xi}a;9WjZCgk{|FbFD-SfQM3}9M1BizT)Y@s*MssJ(Z}5ggs%oZ zEPNHfNLqJ^^6mn&6@1UfD2yFy-WvN^1?cdi(7fSNc`4ZtG>c(@mHWg!C=P$Lnb2J*Wx9q}}WUTtfr zER0?*(q+mzhw|?gFxWp5@uug8WbA2Wx=5(tEyI06ZjU_$C7p4<+!Qu&>su9xSNl#A zOP#2 zYpufoDN`8Lpn&he(s4>@)Ou~?0I*+Z5n#GFrdMPfL*;UAScZCf?jiZ*nW5WYI|q=a zwifXxZ!hx2>9FAc#Ny37(;s4egnzfn$4>4_rj1jVhsdh1;A6m~sDk6lG$#taB% zf6UHfR$~W6zk9yq4td=1C_HJ`)bgzLUQ?GhL7XhKHdp;rTeC500KF)%h)hJ@0Fqhj zd%r%~J2rdy5p??~N{Kqn^QC!{Q99Y~h&B5hO-m1`cfsPQNL^qRimdS_fEW+bcjim3Hv5ddnPo(p zG@yh?gFA;@R*G2PnfX!I15A;lvd(S*IVectlFKr1s;15SC~g9%w17TS{Vp@cBmae) zP5ZPQCPd%)z3DEy7%j2%`*=37#$%-m-n6?Rf+3e3Y>a6;*Ai3I>T}USFD5G@w%=oG zJZxomracZ${u-6z8mSnQnnGy0;ida)%mP|Tu-Lu}sV%FIUl!@d1RhNYd@#_&es`a- z=Xl+XITBUEt*mr76zd6fikh>j$y`vENycn62!u~(-NNcC&`|AGy zqz$0M(XR#bIbmfJ*roTRY3LLo^7P9l5^D3w3uuUh)e@g1gv4Necn*tQ@1W)co|!i7 z$#B13Y-90Ty!3teTa^@OwTPAi9Tu@tpvyjD_=}dsa67!efI`npld9nRpcn&l1=#=n zpsA=22S5p;K^?yMbX37ciABguBg6RX>UfXuDnbmoVGHR;vcV=bt@8`I5 zxiACmGxrwri|0y$IcGh-DPN}^x?!Z)FoLy}MI zOce#V*Coh@zbW)!{s1PC|H?O*#Ty0n9UzSaC=Uzfdvscz|C9^pBA`!B5E}?j6)DEX z6tq$#4eJJA1Pv_}|C?r2UI(1W-G@`kZq;J{*F*Qd-yl?#J-EjS{W_99;ZNL*`{Izj zua}Q=1Zk`LjpW&o|3-$1clI#~vKd^Ci^X3iqB8*Lla|f6r7gy-?)(Z-iZ)%f@BMP% zJ?%PUIbh!gb^9hVW4zd28)2D9{HVLBvg#iH0Zy;a00S2VSdhjxcbs|SfGHE^*C^!2 zgg6`B+ukeb9`^I`oy_muX4+cjz!1l5@UjkR zyQ(-~|IlEt$_0CQ$HU$IphnsC_MVu}t{ZuzeXkFfZ9Sbo+LLN&@DK9mh|Mk8X{Np; za#F8zP)Ra)3@2w$sZ6Z@U7w!(J^%jrw0w1wM18vllN_frhU2(YroUX_hAyS^Zo<%S z=iCRW=&dwh5pW{wLU?%yL+-EyVezULwtL;O1qpk(Q z_QE17QJfKtP|X?qNv`*;nXKiO^VH+aZfM$JH5eW{k|rc)2=zd|H8ow(mi%iqhkw1- zi<1J5j#ET5!xlPKUR&QK{AjL{ZV0pX2Ds{J#ax-CfT>>btODquhI=)<72pI0?trI2 z-+g?)e)oqX?kUw;&BEXbY#Z($|#kh`?T016WHp>ChLvktSXbS^Rjt-s4 zQ>*Y*#MY4ns+yT);$2l^lP&7omN9RrxvR>E$lM)GC^w3dD9yMy`w`fNP0g4GrNAf3 zKb1uqY3wGeY~^|}X_Wb?p*GA1cBrc-EjO|V-dSCS&V2e3VEylA_!9cL3>vppgQtm+ zPvr&}dB*hGM7lmqpV5!gDto@@5>DNU2b^eee=`i!(YMF+EPGRuExrW3d?OX;749>Q z3X;VEnuS4oPYz-0Jzp%lh#B{-CyV>V+YZ%ty!6A@!#eQ=40P{q@&^SehUIc9?$2W4 z(D_BP`BZ^VeX3Ko&B7n@2cb+nw&&-#kpu=GH>n0{UcB)&u%16qOwo1WG0m5^SxX-k zq#k%2v#C??E4TqBwnPEW%Hq`Bv19mvnp&0aTN9C~38he|zg6g??;dD7j^TU1X;j(Qlw1wG3( zu3xSqiGxn~R8MoV!NeZQ{HLDUIidvP;$R_7d$ue#H065QhI|?n`Rme7JsBoTK<$Sh z8u3@mtvpyG1CXMq%UY3BBgv^+AR;|3N6P{6S5;oq_8*Z^4%v5sIGen@(qvgS=*@P) zA!8NGzt&c=@r`#%UQxb%u9TL|h^baO--m!?(p`}T_3JV+@N|c< zYUYx6J_DlWOhPeRw|Asxsvq3>%5+$QN<$kG+wK8D(JkU1nJkAsW!e!s%yFFXthtf# zFbd+@|6hYj(H$bC_U`Ld*ZO~3LzN>1U;jQOb<({lQVvsVAl}h|BC@3^XXH%L-T+j- z>f}xksP@bkMWnzh(E{-Tj^v&;#K>IL-q>e0z$TLmviT85vhA&xb?@$x?mSqNSQ^&V zN+|D@ooa)WFPwh-k*p~}(JkCZ6&(^B_EGT;mmH-a+kNz!Bvf$mlbmeNQk-~N55{5t z6I|zXIZ3I1ayZaP_?!LTM<^~gV)6@yvF$cHy72rJWIOoGW1{l1}v_9c~a1Q)3B%kN3|^(tHyBSA{#-f zy49ebwp8QmYsKlg(l(FM?DHv?Y3A4n8-G2fU(H^Vh>Wcm*qi9+B8RiRegd=>qE}cvPz|I!NaA$RP4_KTrcbd) zC}kbxX9osjyS77j-eef+lUeVNU41E8U9`Dl)ve7Ev;jOgL4Bv9=e@B3!PhPmRZtIj z?y@)r(noKiE_<0yVV*a{K%Xc~l}HWnEQd7JX7ROR%pJ?N=w$2ely2q_>P~X~xykna zpvaA%AIX)(xQdU^z?x7w^yYLLR8G`>;+h6k5?!QiT=t>fApN=Gnz!*iJ|8APN^ zL7br2Nt}$U;g1*)xl&H+X;NhmN^87`mOaA>mF;0B%b;gAG=3LdXyJbIjRmiSs8UPI zTMJ%pv3SLbw1)-kBe&ab1+H9un22;O3rg@u!1IlYo#W=~yjLlGYoyEQ+<@>=g+_H+wO&(?{EnudGsu&lPQYY&wxG%$YHZ5|H+CChg5-3* zetV0&LX||X<^10*03>f{vy&I1=8O_l816lIJ?qQb!QOMlWlmC=Jxkr|8$S2E)<5q2 zb2QJrXE!tmkBJzAVkhf%Zto96q{GCv7*2j`n{H$lRGSM;4g-Go={z&HAHecAd7vqP zowWCq9chssjgVG`gK>DLoTt=bM)A5Tw^vey^AJaX$uAH^6TUHq3eYq4F zF6H5S>vmq9Ku1%>Wsg(ul(ig9b;Bx~JMu@frPD{p1Y07S5pfM0aB_Ret&}TZx2bHy zxeotp`ly)U#I`G`6Ay@5iyfg@iG+bH%s7DB4Ke z$e3Az4!>%*Hd6Bxuz(3v2#dUVLByQ?L;67%H;u`EsGe=S%pqo|KVA? zqb{{xk>FTsXE1RHy-sGiZM^FgdW15qz!b15^S0;}LGnu@W7g{xc7vrVsd60-0A;2-=n%0ZuL2iU$&=$?Sk( zRM64x*A}HiqrvQr8**{XJka?Kw20!#eZ0Yny7U1?3hU@`^^}Jg>)qGWGRfxxNt@Sx zzNot60ormchy^9)Xnu#yAOs~Mp?^mEvK}^;=>-v+bx6#>wL5!zh}ej}PZHhPsUklVQ=vtvmG<}c6@|%m-FST-G8;V^c` zXGd-+Vij0^nzjhN;}-@B16ttqpfaaMY(0&EfDG6f`VIDyee)#5v5UIrBDqgNvbsU( z!PB{!0ac#cQ#&R6U9Lyi&-z67zM11!jycaJzH1W({B}>Hcme8kStY57YN3U9Z<(c^ zy#w1EiW~U&#oCXU;VN{|+W4>SaU0iEUb>~OalIobLbpuwD8_xCHuPf_Y;!8G%=)nb zEeZ3+(_njZD6Lnl>t=PSxP`*hmC+ zjUGLs#VfBsPLGN$Pvr3cK>?WZ)5$ zrwm!IA-6>-O*DunQ?H$@t4zHMScvGfv;y%eZkEXFlVG{n1@GR86}9d9npgw9SN`<> z4PK4)(^fc4a;(r1=otd`$W^arUJ#Efp_D$wlfTKGSo4yEs3Ski(r*4Z1wNP=jp>Fu zQ+BrE;uJ}S+rM|rj2b-iQm_?vxqJtH$iHm)Qh=Z)EygVFQncjt)@)C;sFW`UDeXJ1htq zf#ao?OE1Tbh(sa%$?&ye<(5b8Rigk}dn);BOIv0c1F&W;oMm%8+u%O2`W*mM5v@kiZA0klVkT^JrH0g|R zywfRp-1uT#YESL!pJn8)!nqWTΠ%3Eh&6w)JWC`HU50&?m*fS`+tyhacntMP?<| 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�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ⅅ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 =(ge2H|(OL9KRM50z-1#?^O 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
      MAWM$F}k3Si@hA`bJ>su=5 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⩔0g>o~oLP%yD}_-%Xz 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�}a5;AZ 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

      r3{1ReB(@ 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

      fi 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 _!fvINIKx%GszGvuSSct7^Mg3(cs2E8pO|JiAiM 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

      G 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 z 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 XkxnN+fB6yz_ Date: Fri, 11 Sep 2026 22:20:18 +0700 Subject: [PATCH 02/54] fix(plugin-postgresql): read SQLSTATE from the right libpq field (#2739) Claude-Session: https://claude.ai/code/session_01X1ejXbmyPqUziRWVxJ5cu8 --- CHANGELOG.md | 2 + .../LibPQPluginConnection.swift | 37 +---------- .../LibPQPluginError.swift | 34 ++++++++++ .../Plugins/LibPQPluginErrorTests.swift | 65 +++++++++++++++++++ project.yml | 1 + 5 files changed, 104 insertions(+), 35 deletions(-) create mode 100644 Plugins/PostgreSQLDriverPlugin/LibPQPluginError.swift create mode 100644 TableProTests/Plugins/LibPQPluginErrorTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e4f662a82..7a071753ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Wrong SQLSTATE code in PostgreSQL, Redshift, CockroachDB and PGlite error messages. +- Read-only write explanation never shown on PostgreSQL servers. - Safe Mode minimum from a configuration profile missing from the toolbar, the Database menu and the connection form. (#2030) - Stop not ending queries on MySQL and MariaDB servers without TLS. - Users & Roles failing, Stop not ending queries and sequences listed as tables on TiDB servers opened as MySQL. diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift b/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift index c979af827a..3326feda18 100644 --- a/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift +++ b/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift @@ -14,21 +14,6 @@ import TableProPluginKit private let logger = Logger(subsystem: "com.TablePro.PostgreSQLDriver", category: "LibPQPluginConnection") -// MARK: - Error Types - -struct LibPQPluginError: Error { - let message: String - let sqlState: String? - let detail: String? - - static let notConnected = LibPQPluginError( - message: String(localized: "Not connected to database"), sqlState: nil, detail: nil) - static let connectionFailed = LibPQPluginError( - message: String(localized: "Failed to establish connection"), sqlState: nil, detail: nil) - static let connectionTimedOut = LibPQPluginError( - message: String(localized: "Timed out while connecting to the server"), sqlState: nil, detail: nil) -} - // MARK: - Query Result struct LibPQPluginQueryResult { @@ -1243,22 +1228,12 @@ final class LibPQPluginConnection: @unchecked Sendable { private func getResultError(from result: OpaquePointer) -> LibPQPluginError { var message = "Unknown error" - var sqlState: String? - var detail: String? - if let msgPtr = PQresultErrorMessage(result) { message = String(cString: msgPtr).trimmingCharacters(in: .whitespacesAndNewlines) } - - if let statePtr = PQresultErrorField(result, Int32(80)) { - sqlState = String(cString: statePtr) - } - - if let detailPtr = PQresultErrorField(result, Int32(68)) { - detail = String(cString: detailPtr) + return LibPQPluginError(message: message) { field in + PQresultErrorField(result, field).map { String(cString: $0) } } - - return LibPQPluginError(message: message, sqlState: sqlState, detail: detail) } private func getAffectedRows(from result: OpaquePointer) -> Int { @@ -1275,11 +1250,3 @@ final class LibPQPluginConnection: @unchecked Sendable { return nil } } - -// MARK: - PluginDriverError Conformance - -extension LibPQPluginError: PluginDriverError { - var pluginErrorMessage: String { message } - var pluginSqlState: String? { sqlState } - var pluginErrorDetail: String? { detail } -} diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQPluginError.swift b/Plugins/PostgreSQLDriverPlugin/LibPQPluginError.swift new file mode 100644 index 0000000000..e2ad6aa6c1 --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/LibPQPluginError.swift @@ -0,0 +1,34 @@ +import Foundation +import TableProPluginKit + +struct LibPQPluginError: Error { + let message: String + let sqlState: String? + let detail: String? + + static let notConnected = LibPQPluginError( + message: String(localized: "Not connected to database"), sqlState: nil, detail: nil) + static let connectionFailed = LibPQPluginError( + message: String(localized: "Failed to establish connection"), sqlState: nil, detail: nil) + static let connectionTimedOut = LibPQPluginError( + message: String(localized: "Timed out while connecting to the server"), sqlState: nil, detail: nil) +} + +internal extension LibPQPluginError { + private static let sqlStateField = Int32(UInt8(ascii: "C")) + private static let detailField = Int32(UInt8(ascii: "D")) + + init(message: String, readingResultField readField: (Int32) -> String?) { + self.init( + message: message, + sqlState: readField(Self.sqlStateField), + detail: readField(Self.detailField) + ) + } +} + +extension LibPQPluginError: PluginDriverError { + var pluginErrorMessage: String { message } + var pluginSqlState: String? { sqlState } + var pluginErrorDetail: String? { detail } +} diff --git a/TableProTests/Plugins/LibPQPluginErrorTests.swift b/TableProTests/Plugins/LibPQPluginErrorTests.swift new file mode 100644 index 0000000000..3bab0016e4 --- /dev/null +++ b/TableProTests/Plugins/LibPQPluginErrorTests.swift @@ -0,0 +1,65 @@ +import Foundation +@testable import TablePro +import TableProPluginKit +import Testing + +@Suite("LibPQPluginError result fields") +struct LibPQPluginErrorTests { + private static let undefinedFunctionFields: [Int32: String] = [ + Int32(UInt8(ascii: "C")): "42883", + Int32(UInt8(ascii: "P")): "134", + Int32(UInt8(ascii: "D")): "no function matches" + ] + + private static func decoded(_ fields: [Int32: String], message: String = "ERROR: failed") -> LibPQPluginError { + LibPQPluginError(message: message) { fields[$0] } + } + + @Test("SQLSTATE comes from the C field, never the statement position") + func sqlStateReadsTheSQLStateField() { + let error = Self.decoded(Self.undefinedFunctionFields) + #expect(error.sqlState == "42883") + #expect(error.pluginSqlState == "42883") + } + + @Test("Detail comes from the D field") + func detailReadsTheDetailField() { + let error = Self.decoded(Self.undefinedFunctionFields) + #expect(error.detail == "no function matches") + } + + @Test("Only the SQLSTATE and detail fields are read") + func readsNoOtherField() { + var requested: [Int32] = [] + _ = LibPQPluginError(message: "ERROR: failed") { field in + requested.append(field) + return nil + } + #expect(Set(requested) == [Int32(UInt8(ascii: "C")), Int32(UInt8(ascii: "D"))]) + } + + @Test("A result with no diagnostic fields carries no SQLSTATE") + func missingFieldsStayNil() { + let error = Self.decoded([:]) + #expect(error.sqlState == nil) + #expect(error.detail == nil) + } + + @Test("The error description names the SQLSTATE") + func descriptionNamesTheSQLState() { + let error = Self.decoded( + Self.undefinedFunctionFields, + message: "ERROR: function to_regclass(text) does not exist" + ) + #expect(error.errorDescription?.contains("(SQLSTATE: 42883)") == true) + } + + @Test("A decoded read-only transaction error is diagnosed as server-enforced read-only") + func readOnlyTransactionIsDiagnosed() { + let error = Self.decoded( + [Int32(UInt8(ascii: "C")): "25006"], + message: "ERROR: cannot execute INSERT in a read-only transaction" + ) + #expect(DatabaseWriteRejectionDiagnosis.classify(error) != nil) + } +} diff --git a/project.yml b/project.yml index c8a381d0bc..7906d573d2 100644 --- a/project.yml +++ b/project.yml @@ -501,6 +501,7 @@ targets: - Plugins/MSSQLDriverPlugin/MSSQLCheckConstraintDefinition.swift - Plugins/PostgreSQLDriverPlugin/ColumnQueryShape.swift - Plugins/PostgreSQLDriverPlugin/LibPQByteaDecoder.swift + - Plugins/PostgreSQLDriverPlugin/LibPQPluginError.swift - Plugins/PostgreSQLDriverPlugin/LibPQSSLMapping.swift - Plugins/PostgreSQLDriverPlugin/PostGISSpatialRewrite.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift From 3b9a51a94484fbf3aee76259bc05ce3f42801328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Fri, 11 Sep 2026 22:41:19 +0700 Subject: [PATCH 03/54] fix(plugin-mysql): set the session character set on connect and decode MySQL text by its declared charset (#2725) (#2740) * fix(plugin-mysql): set the session character set on connect and decode MySQL text by its declared charset (#2725) Claude-Session: https://claude.ai/code/session_01U7kkDGsR4M4v9NWiycc97U * fix(plugin-mysql): rebind prepared-statement results after growing a truncated column buffer Claude-Session: https://claude.ai/code/session_01U7kkDGsR4M4v9NWiycc97U --- CHANGELOG.md | 8 + CLAUDE.md | 2 + .../MariaDBFieldMetadata.swift | 74 +++ .../MariaDBPluginConnection.swift | 449 +++++------------- .../MySQLDriverPlugin/MySQLCharacterSet.swift | 111 +++++ .../MySQLColumnDecoding.swift | 102 ++++ .../MySQLConnectionEncoding.swift | 50 ++ Plugins/MySQLDriverPlugin/MySQLLatin1.swift | 64 +++ Plugins/MySQLDriverPlugin/MySQLPlugin.swift | 3 +- .../MySQLDriverPlugin/MySQLPluginDriver.swift | 5 +- .../SQLExportEncodingDeclaration.swift | 42 ++ .../SQLExportPlugin/SQLExportFileWriter.swift | 30 +- Plugins/SQLExportPlugin/SQLExportPlugin.swift | 16 +- ...uginMetadataRegistry+CuratedDefaults.swift | 14 +- .../Database/GeometryWKBParserTests.swift | 244 ---------- .../Plugins/MariaDBFieldClassifierTests.swift | 5 - .../Plugins/MariaDBTypeNameTests.swift | 4 - .../Plugins/MySQLCharacterSetTests.swift | 73 +++ .../Plugins/MySQLColumnDecodingTests.swift | 107 +++++ .../MySQLConnectionEncodingTests.swift | 82 ++++ TableProTests/Plugins/MySQLLatin1Tests.swift | 101 ++++ .../Plugins/SQLExportEncodingTests.swift | 117 +++++ docs/databases/mysql.mdx | 36 +- docs/features/import-export.mdx | 2 + project.yml | 8 + scripts/check-mysql-charset-decoding.sh | 151 ++++++ 26 files changed, 1308 insertions(+), 592 deletions(-) create mode 100644 Plugins/MySQLDriverPlugin/MariaDBFieldMetadata.swift create mode 100644 Plugins/MySQLDriverPlugin/MySQLCharacterSet.swift create mode 100644 Plugins/MySQLDriverPlugin/MySQLColumnDecoding.swift create mode 100644 Plugins/MySQLDriverPlugin/MySQLConnectionEncoding.swift create mode 100644 Plugins/MySQLDriverPlugin/MySQLLatin1.swift create mode 100644 Plugins/SQLExportPlugin/SQLExportEncodingDeclaration.swift create mode 100644 TableProTests/Plugins/MySQLCharacterSetTests.swift create mode 100644 TableProTests/Plugins/MySQLColumnDecodingTests.swift create mode 100644 TableProTests/Plugins/MySQLConnectionEncodingTests.swift create mode 100644 TableProTests/Plugins/MySQLLatin1Tests.swift create mode 100644 TableProTests/Plugins/SQLExportEncodingTests.swift create mode 100755 scripts/check-mysql-charset-decoding.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a071753ba..2447a90ef5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **Show invisible characters** in Settings > Editor. (#2717) - Warnings in the SQL editor for full-width punctuation, curly quotes and non-ASCII spaces. (#2717) - Highlight rules that color data grid rows or cells by value. (#2723) +- **Encoding** option for MySQL and MariaDB connections, with **UTF-8 via Latin 1** for databases written through a Latin 1 client. (#2725) ### Changed @@ -33,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Open Project Folder… in File > Import. - First-launch tour replaced by a one-page welcome sheet, shown again from Help > Getting Started. - Beancount connections held at Safe Mode Read-Only. (#2030) +- MySQL sessions on the server's default `utf8mb4` collation. ### Fixed @@ -125,6 +127,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Line and paragraph separators (U+2028, U+2029) shown as line breaks the database does not see. (#2717) - Stop on Cloudflare D1, libSQL and Trino cancelling a sidebar read instead of the running query. - Numeric-looking filter values sent unquoted to text columns when a table first opens or after a foreign key jump. +- Garbled non-Latin text saved to MySQL and MariaDB servers that force a Latin 1 session. (#2725) +- Garbled non-Latin text when restoring a MySQL or MariaDB SQL export through a Latin 1 client. (#2725) +- Curly quotes, € and other Windows-1252 symbols shown as invisible characters after `SET NAMES latin1`. +- `Illegal mix of collations` comparing a column with a user variable on MySQL 8. +- GEOMETRY values from a parameterized MySQL query shown as raw bytes. +- Earlier row's text repeated in later rows of a parameterized MySQL query once a value passed 64 KB. ### Security diff --git a/CLAUDE.md b/CLAUDE.md index 171a618c95..4dab1c7726 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -225,6 +225,8 @@ To ship one: add the record type or field in CloudKit Console (or `xcrun cktool **A pooled metadata read assumes a second connection reaches the same database, and an embedded engine breaks that assumption**: `MetadataConnectionPool` builds a whole new driver, so it is only correct when the database lives on a server the driver reconnects to. When the database lives *inside* the driver instance, the pool gets a different database: a second `duckdb_open(":memory:")` is a fresh empty database, and a second `duckdb_open` on the same *file* is a second independent read-write instance that the first never sees (DuckDB's file lock does not conflict within one process). The failure is silent, because an empty catalog is indistinguishable from "no tables", which is why #2108 survived a manual refresh. `supportsConnectionPooling` is the opt-out, and it is read only by `DatabaseManager.canPool`; DuckDB and PGlite set it `false`. SQLite-family engines keep pooling, because multi-connection access to one file is what they are built for. Two rules follow. First, every metadata read goes through `DatabaseManager.withMetadataDriver` so `metadataRoute` can apply the rule; reaching for `MetadataConnectionPool.shared.withDriver` directly bypasses it, which is how routines kept pooling after the sidebar stopped. Second, a capability with no `DriverPlugin` static is curated per type and `buildMetadataSnapshot` must carry it over from the built-in snapshot, or `register(snapshot:forTypeId:)` resets it to the struct default the moment the plugin loads. That is not hypothetical: it silently disabled MongoDB's `authenticationIsDatabaseScoped` (#1970) for every build that had the plugin installed. `registerVariant` already treats the curated entry as authoritative, which is the only reason PGlite's flag ever worked. +**A MySQL session's character set is server state, and the driver sets it rather than asking for it**: `MYSQL_SET_CHARSET_NAME` only puts a collation byte in the handshake, and the server is free to ignore it. `init_connect='SET NAMES latin1'` for any user without `CONNECTION_ADMIN`, MariaDB's `skip-character-set-client-handshake`, and a server with no `utf8mb4` all leave the session latin1 while libmariadb still reports `utf8mb4`. The driver sends UTF-8 either way, so every comment and value it wrote there was stored double-encoded, which is the `メール` of #2725, and a user-variable comparison on MySQL 8 failed with `ERROR 1267` under the handshake's `utf8mb4_general_ci`. So `MariaDBPluginConnection.establishSessionCharacterSet` calls `mysql_set_character_set` on every connect path, falls back to a plain `SET NAMES utf8` (libmariadb itself rewrites `utf8` to `utf8mb3`, which a pre-5.5.3 server does not know), and keeps the server's own session when it refuses both rather than failing the connect: a MySQL-protocol engine that rejects `SET NAMES` must still connect. Two rules follow. Outgoing SQL stays the UTF-8 bytes of the Swift string and never follows a mid-session `SET NAMES`: a legacy dump that declares `SET NAMES latin1` over UTF-8 bytes restores byte-for-byte only because nothing re-encodes it, which is also what the `mysql` client does. And every result cell decodes through `MySQLColumnDecoding` by its field's own `charsetnr`, never as "UTF-8 and hope": a latin1 field reads UTF-8 first and then MySQL's latin1, which is cp1252 plus five C1 pass-through bytes and not Foundation's `.isoLatin1` or `.windowsCP1252`. The Foundation encodings in `MySQLCharacterSet` are a hand transcription of the server's tables; `scripts/check-mysql-charset-decoding.sh` diffs them against a live server, and a charset that disagrees stays out of the table. **UTF-8 via Latin 1** (`mysqlConnectionEncoding`) sets only `character_set_client` to latin1 and repairs the text client-side, so correctly stored text is never read back as `?`, which a latin1 results charset would do and a structure edit would then write back. + **A MongoDB update or delete is anchored on `_id` or it does not run**: `generateDelete` used to fall back to a filter built from the remaining columns, which silently dropped every value it could not stringify (all binary) and then `deleteOne`d the first partial match, so a document with a binary `_id` could delete a different document. Both paths now skip with a logged warning instead, matching what `generateUpdate` already did. **Redis Cluster routing follows the server's own answer, and the curated table is only a fallback**: `RedisCommandRouting` fetches `COMMAND` once at connect, which supplies key positions on every Redis and, from Redis 7, the `request_policy` / `response_policy` tips that say which commands fan out and how their replies combine. A policy lives on the *subcommand* entry, not the container (`COMMAND INFO config` carries no tips at all; `config|set` is what says `all_nodes`), so the table is keyed `container|sub`. Redis 6 reports no tips, so a parsed reply is merged *over* the curated table rather than replacing it, or `DBSIZE`, `KEYS` and `FLUSHDB` would each go to one shard of a cluster and report success. The curated table is a hand-written list that has to agree with Redis and that nothing at runtime checks, so `scripts/check-redis-command-routing.sh [host] [port]` diffs it against a live Redis 7+; it found 32 disagreements the first time it ran, including a container command hashed on its literal subcommand name and `MSETNX` marked splittable when splitting it breaks the guarantee it exists for. Two rules follow. A container command takes no key of its own, so `OBJECT`, `MEMORY` and `CONFIG` declare no key positions and their keyed subcommands are listed separately, at the index the key sits in the *full* argument list (`OBJECT ENCODING k` puts it at 2, not 1). And an unknown command is routed as keyless rather than by hashing `argv[1]`: a keyless container like `SCRIPT LOAD` answers `+OK` from one node and never sends a `MOVED` to correct the guess. diff --git a/Plugins/MySQLDriverPlugin/MariaDBFieldMetadata.swift b/Plugins/MySQLDriverPlugin/MariaDBFieldMetadata.swift new file mode 100644 index 0000000000..fe98664288 --- /dev/null +++ b/Plugins/MySQLDriverPlugin/MariaDBFieldMetadata.swift @@ -0,0 +1,74 @@ +// +// MariaDBFieldMetadata.swift +// MySQLDriverPlugin +// + +import Foundation +import TableProPluginKit + +internal let mysqlNotNullFlag: UInt = 0x0001 +internal let mysqlPriKeyFlag: UInt = 0x0002 +internal let mysqlBinaryFlag: UInt = 0x0080 +internal let mysqlEnumFlag: UInt = 0x0100 +internal let mysqlAutoIncrementFlag: UInt = 0x0200 +internal let mysqlSetFlag: UInt = 0x0800 +internal let mysqlBinaryCharset: UInt32 = 63 + +internal func makeColumnMeta(name: String, typeName: String, flags: UInt) -> PluginColumnInfo { + PluginColumnInfo( + name: name, + dataType: typeName, + isNullable: (flags & mysqlNotNullFlag) == 0, + isPrimaryKey: (flags & mysqlPriKeyFlag) != 0, + identityKind: (flags & mysqlAutoIncrementFlag) != 0 ? .byDefault : nil + ) +} + +internal func mariaDBTypeName( + typeRaw: UInt32, + flags: UInt, + charsetnr: UInt32, + length: UInt +) -> String { + let isBinary = (flags & mysqlBinaryFlag) != 0 && charsetnr == mysqlBinaryCharset + + switch typeRaw { + case 0: return "DECIMAL" + case 1: return "TINYINT" + case 2: return "SMALLINT" + case 3: return "INT" + case 4: return "FLOAT" + case 5: return "DOUBLE" + case 6: return "NULL" + case 7: return "TIMESTAMP" + case 8: return "BIGINT" + case 9: return "MEDIUMINT" + case 10: return "DATE" + case 11: return "TIME" + case 12: return "DATETIME" + case 13: return "YEAR" + case 14: return "NEWDATE" + case 15: return "VARCHAR" + case 16: return "BIT" + case 245: return "JSON" + case 246: return "NEWDECIMAL" + case 247: return "ENUM" + case 248: return "SET" + case 249: + return isBinary ? "TINYBLOB" : "TINYTEXT" + case 250: + return isBinary ? "MEDIUMBLOB" : "MEDIUMTEXT" + case 251: + return isBinary ? "LONGBLOB" : "LONGTEXT" + case 252: + if isBinary { + return length > 65_535 ? "LONGBLOB" : "BLOB" + } else { + return length > 65_535 ? "LONGTEXT" : "TEXT" + } + case 253: return isBinary ? "VARBINARY" : "VARCHAR" + case 254: return isBinary ? "BINARY" : "CHAR" + case 255: return "GEOMETRY" + default: return "UNKNOWN" + } +} diff --git a/Plugins/MySQLDriverPlugin/MariaDBPluginConnection.swift b/Plugins/MySQLDriverPlugin/MariaDBPluginConnection.swift index 819ef2572e..6e29301542 100644 --- a/Plugins/MySQLDriverPlugin/MariaDBPluginConnection.swift +++ b/Plugins/MySQLDriverPlugin/MariaDBPluginConnection.swift @@ -11,27 +11,8 @@ import Foundation import OSLog import TableProPluginKit -// MySQL/MariaDB field flag and charset constants -internal let mysqlNotNullFlag: UInt = 0x0001 -internal let mysqlPriKeyFlag: UInt = 0x0002 -internal let mysqlBinaryFlag: UInt = 0x0080 -internal let mysqlEnumFlag: UInt = 0x0100 -internal let mysqlAutoIncrementFlag: UInt = 0x0200 -internal let mysqlSetFlag: UInt = 0x0800 -internal let mysqlBinaryCharset: UInt32 = 63 - private let logger = Logger(subsystem: "com.TablePro", category: "MariaDBPluginConnection") -internal func makeColumnMeta(name: String, typeName: String, flags: UInt) -> PluginColumnInfo { - PluginColumnInfo( - name: name, - dataType: typeName, - isNullable: (flags & mysqlNotNullFlag) == 0, - isPrimaryKey: (flags & mysqlPriKeyFlag) != 0, - identityKind: (flags & mysqlAutoIncrementFlag) != 0 ? .byDefault : nil - ) -} - // MARK: - Error Types struct MariaDBPluginError: Error { @@ -96,60 +77,6 @@ func mysqlTypeToString(_ fieldPtr: UnsafePointer) -> String { ) } -/// Pure mapping from raw MySQL/MariaDB field type code + flags to TablePro's -/// column-type-name string. Separated from `mysqlTypeToString` so it can be -/// unit-tested without an actual `MYSQL_FIELD` struct. -internal func mariaDBTypeName( - typeRaw: UInt32, - flags: UInt, - charsetnr: UInt32, - length: UInt -) -> String { - // Binary flag alone is insufficient — MariaDB sets it on text columns with - // binary collation (e.g. utf8mb4_bin for JSON). Only charset 63 is truly binary. - let isBinary = (flags & mysqlBinaryFlag) != 0 && charsetnr == mysqlBinaryCharset - - switch typeRaw { - case 0: return "DECIMAL" - case 1: return "TINYINT" - case 2: return "SMALLINT" - case 3: return "INT" - case 4: return "FLOAT" - case 5: return "DOUBLE" - case 6: return "NULL" - case 7: return "TIMESTAMP" - case 8: return "BIGINT" - case 9: return "MEDIUMINT" - case 10: return "DATE" - case 11: return "TIME" - case 12: return "DATETIME" - case 13: return "YEAR" - case 14: return "NEWDATE" - case 15: return "VARCHAR" - case 16: return "BIT" - case 245: return "JSON" - case 246: return "NEWDECIMAL" - case 247: return "ENUM" - case 248: return "SET" - case 249: - return isBinary ? "TINYBLOB" : "TINYTEXT" - case 250: - return isBinary ? "MEDIUMBLOB" : "MEDIUMTEXT" - case 251: - return isBinary ? "LONGBLOB" : "LONGTEXT" - case 252: - if isBinary { - return length > 65_535 ? "LONGBLOB" : "BLOB" - } else { - return length > 65_535 ? "LONGTEXT" : "TEXT" - } - case 253: return isBinary ? "VARBINARY" : "VARCHAR" - case 254: return isBinary ? "BINARY" : "CHAR" - case 255: return "GEOMETRY" - default: return "UNKNOWN" - } -} - // MARK: - Connection Class final class MariaDBPluginConnection: @unchecked Sendable { @@ -168,6 +95,7 @@ final class MariaDBPluginConnection: @unchecked Sendable { private let sslConfig: SSLConfiguration private let enableCleartextPlugin: Bool private let queryTimeoutSeconds: Int + private let connectionEncoding: MySQLConnectionEncoding private let stateLock = NSLock() private let cancellationGate = PluginQueryCancellationGate() @@ -240,7 +168,8 @@ final class MariaDBPluginConnection: @unchecked Sendable { database: String, sslConfig: SSLConfiguration, enableCleartextPlugin: Bool = false, - queryTimeoutSeconds: Int = 0 + queryTimeoutSeconds: Int = 0, + connectionEncoding: MySQLConnectionEncoding = .utf8 ) { self.host = host self.port = UInt32(port) @@ -250,6 +179,7 @@ final class MariaDBPluginConnection: @unchecked Sendable { self.sslConfig = sslConfig self.enableCleartextPlugin = enableCleartextPlugin self.queryTimeoutSeconds = queryTimeoutSeconds + self.connectionEncoding = connectionEncoding } deinit { @@ -393,22 +323,43 @@ final class MariaDBPluginConnection: @unchecked Sendable { mysql_close(mysql) throw error } + do { + try establishSessionCharacterSet(on: mysql) + } catch { + mysql_close(mysql) + throw error + } return mysql } - private func readError(from mysql: UnsafeMutablePointer) -> MariaDBPluginError { - let code = mysql_errno(mysql) - let message: String - if let msgPtr = mysql_error(mysql) { - message = String(cString: msgPtr) - } else { - message = "Unknown error" + private func establishSessionCharacterSet(on mysql: UnsafeMutablePointer) throws { + if mysql_set_character_set(mysql, MySQLConnectionEncoding.sessionCharacterSetName) != 0 { + let refusal = errorMessage(from: mysql) + if runSessionStatement(MySQLConnectionEncoding.sessionFallbackStatement, on: mysql) { + logger.notice("Server refused utf8mb4 (\(refusal, privacy: .public)), so the session uses utf8") + } else { + logger.warning("Server refused a UTF-8 session (\(refusal, privacy: .public)); keeping its own") + } } - var sqlState: String? - if let statePtr = mysql_sqlstate(mysql), statePtr[0] != 0 { - sqlState = String(cString: statePtr) + for statement in connectionEncoding.sessionStatements where !runSessionStatement(statement, on: mysql) { + throw readError(from: mysql) + } + } + + private func runSessionStatement(_ statement: String, on mysql: UnsafeMutablePointer) -> Bool { + let status = statement.withCString { mysql_real_query(mysql, $0, UInt(strlen($0))) } + if let discarded = mysql_store_result(mysql) { + mysql_free_result(discarded) } - return MariaDBPluginError(code: code, message: message, sqlState: sqlState) + return status == 0 + } + + private func readError(from mysql: UnsafeMutablePointer) -> MariaDBPluginError { + MariaDBPluginError( + code: mysql_errno(mysql), + message: mysql_error(mysql).map(decodedMessage) ?? "Unknown error", + sqlState: sqlState(mysql_sqlstate(mysql)) + ) } func disconnect() { @@ -670,45 +621,8 @@ final class MariaDBPluginConnection: @unchecked Sendable { } } - let numFields = Int(mysql_num_fields(resultPtr)) - var columns: [String] = [] - var columnTypes: [UInt32] = [] - var columnTypeNames: [String] = [] - var columnIsBinary: [Bool] = [] - var columnIsBoolean: [Bool] = [] - var columnMeta: [PluginColumnInfo] = [] - columns.reserveCapacity(numFields) - columnTypes.reserveCapacity(numFields) - columnTypeNames.reserveCapacity(numFields) - columnIsBinary.reserveCapacity(numFields) - columnIsBoolean.reserveCapacity(numFields) - columnMeta.reserveCapacity(numFields) let sessionFlavor = flavor - - if let fields = mysql_fetch_fields(resultPtr) { - for i in 0.., metadata: UnsafeMutablePointer, - columns: [String], - columnTypes: [UInt32], - columnTypeNames: [String], - columnIsBinary: [Bool], + columns: MySQLResultColumns, rowCap: Int? = nil, generation: Int, sentAt: Date @@ -950,8 +842,8 @@ final class MariaDBPluginConnection: @unchecked Sendable { break } - // Re-fetch truncated columns with correctly sized buffers if fetchStatus == MYSQL_DATA_TRUNCATED { + var grewBuffer = false for i in 0.. Int(resultBinds[i].buffer_length) { @@ -962,33 +854,22 @@ final class MariaDBPluginConnection: @unchecked Sendable { resultBuffers[i] = newBuffer resultBinds[i].buffer = newBuffer resultBinds[i].buffer_length = UInt(actualLength) + grewBuffer = true if mysql_stmt_fetch_column(stmt, &resultBinds[i], UInt32(i), 0) != 0 { logger.warning("mysql_stmt_fetch_column failed for column \(i)") } } } - } - - var row: [PluginCellValue] = [] - for i in 0..= batchSize { continuation.yield(.rows(batch)) batch.removeAll(keepingCapacity: true) @@ -1296,77 +1093,83 @@ final class MariaDBPluginConnection: @unchecked Sendable { _cachedServerVersion } - private static func cellValue( - _ buffer: UnsafeRawBufferPointer, - typeRaw: UInt32, - isBinary: Bool, - isBoolean: Bool, - flavor: MySQLServerFlavor - ) -> PluginCellValue { - if flavor.isDatabend { - if isBoolean { - return .text(DatabendResultShape.booleanText(fromWireText: String(bytes: buffer, encoding: .utf8) ?? "")) - } - if isBinary { - return .bytes(DatabendResultShape.binaryValue(fromWireText: Data(buffer))) - } - if typeRaw == 255 { - return .text(String(bytes: buffer, encoding: .utf8) ?? "") - } - } - if typeRaw == 255 { - return .text(GeometryWKBParser.parse(buffer)) - } - if MariaDBFieldClassifier.isBit(typeRaw: typeRaw) { - return .text(MariaDBFieldClassifier.bitFieldToString(buffer)) - } - if isBinary { - return .bytes(Data(buffer)) - } - if let text = String(bytes: buffer, encoding: .utf8) { - return .text(text) - } - return .text(String(bytes: buffer, encoding: .isoLatin1) ?? "") - } - // MARK: - Private Helpers private func getError() -> MariaDBPluginError { guard let mysql = mysql else { return MariaDBPluginError.notConnected } + return readError(from: mysql) + } - let code = mysql_errno(mysql) - let message: String - if let msgPtr = mysql_error(mysql) { - message = String(cString: msgPtr) - } else { - message = "Unknown error" - } + private func getStmtError(_ stmt: UnsafeMutablePointer) -> MariaDBPluginError { + MariaDBPluginError( + code: mysql_stmt_errno(stmt), + message: mysql_stmt_error(stmt).map(decodedMessage) ?? "Unknown statement error", + sqlState: sqlState(mysql_stmt_sqlstate(stmt)) + ) + } - var sqlState: String? - if let statePtr = mysql_sqlstate(mysql), statePtr[0] != 0 { - sqlState = String(cString: statePtr) - } + private func decodedMessage(_ message: UnsafePointer) -> String { + mysqlSessionText(cString: message, encoding: connectionEncoding) + } - return MariaDBPluginError(code: code, message: message, sqlState: sqlState) + private func sqlState(_ state: UnsafePointer?) -> String? { + guard let state, state[0] != 0 else { return nil } + return String(cString: state) } - private func getStmtError(_ stmt: UnsafeMutablePointer) -> MariaDBPluginError { - let code = mysql_stmt_errno(stmt) - let message: String - if let msgPtr = mysql_stmt_error(stmt) { - message = String(cString: msgPtr) - } else { - message = "Unknown statement error" + private func describeColumns(_ fields: UnsafeMutablePointer?, count: Int) -> MySQLResultColumns { + var columns = MySQLResultColumns() + guard let fields else { return columns } + let sessionFlavor = flavor + for index in 0.. String { + guard let name = field.name else { return "column_\(index)" } + let bytes = UnsafeRawBufferPointer(start: name, count: strnlen(name, Int(field.name_length))) + return mysqlSessionText(bytes, encoding: connectionEncoding) + } - return MariaDBPluginError(code: code, message: message, sqlState: sqlState) + private static func typeCode(of field: MYSQL_FIELD, flags: UInt) -> UInt32 { + if (flags & mysqlSetFlag) != 0 { return 248 } + if (flags & mysqlEnumFlag) != 0 { return 247 } + return field.type.rawValue + } + + private static func characterSetName(forCollation collation: UInt32) -> String? { + guard let info = mariadb_get_charset_by_nr(collation), let name = info.pointee.csname else { return nil } + return String(cString: name) + } + + private func textProtocolRow( + _ row: MYSQL_ROW, + lengths: UnsafeMutablePointer?, + columns: MySQLResultColumns + ) -> [PluginCellValue] { + columns.row(encoding: connectionEncoding) { index in + guard let value = row[index] else { return nil } + return UnsafeRawBufferPointer(start: value, count: Int(clamping: lengths?[index] ?? 0)) + } } } diff --git a/Plugins/MySQLDriverPlugin/MySQLCharacterSet.swift b/Plugins/MySQLDriverPlugin/MySQLCharacterSet.swift new file mode 100644 index 0000000000..92ffcb0bc4 --- /dev/null +++ b/Plugins/MySQLDriverPlugin/MySQLCharacterSet.swift @@ -0,0 +1,111 @@ +// +// MySQLCharacterSet.swift +// MySQLDriverPlugin +// + +import CoreFoundation +import Foundation + +internal struct MySQLCharacterSet: Hashable, Sendable { + static let utf8mb4 = MySQLCharacterSet(serverName: "utf8mb4") + static let latin1 = MySQLCharacterSet(serverName: "latin1") + + let name: String + private let decoding: Decoding + + init(serverName: String) { + let normalized = serverName.trimmingCharacters(in: .whitespaces).lowercased() + name = normalized == "utf8" ? "utf8mb3" : normalized + decoding = Self.decoding(forName: name) + } + + func decode(_ bytes: UnsafeRawBufferPointer) -> String { + switch decoding { + case .utf8: + return Self.decodeUTF8ReplacingInvalid(bytes) + case .utf8OrMySQLLatin1: + return Self.decodeUTF8OrMySQLLatin1(bytes) + case .foundation(let encoding, let isSingleByte): + return Self.decode(bytes, encoding: encoding, isSingleByte: isSingleByte) + } + } + + static func decodeUTF8OrMySQLLatin1(_ bytes: UnsafeRawBufferPointer) -> String { + if let text = String(bytes: bytes, encoding: .utf8) { + return text + } + return MySQLLatin1.decode(bytes) + } + + static func decodeUTF8ReplacingInvalid(_ bytes: UnsafeRawBufferPointer) -> String { + String(decoding: bytes, as: UTF8.self) // swiftlint:disable:this optional_data_string_conversion + } + + static var singleByteDecodedNames: [String] { + Array(singleByteEncodings.keys).sorted() + } + + static var multiByteDecodedNames: [String] { + Array(multiByteEncodings.keys).sorted() + } + + private enum Decoding: Hashable, Sendable { + case utf8 + case utf8OrMySQLLatin1 + case foundation(String.Encoding, isSingleByte: Bool) + } + + private static let utf8Names: Set = ["utf8mb4", "utf8mb3", "ascii", "binary"] + + private static func decoding(forName name: String) -> Decoding { + if utf8Names.contains(name) { return .utf8 } + if name == "latin1" { return .utf8OrMySQLLatin1 } + if let encoding = singleByteEncodings[name] { return .foundation(encoding, isSingleByte: true) } + if let encoding = multiByteEncodings[name] { return .foundation(encoding, isSingleByte: false) } + return .utf8 + } + + private static let singleByteEncodings: [String: String.Encoding] = [ + "latin2": .isoLatin2, + "cp1250": .windowsCP1250, + "cp1251": .windowsCP1251, + "cp1256": encoding(.windowsArabic), + "cp1257": encoding(.windowsBalticRim), + "cp850": encoding(.dosLatin1), + "cp852": encoding(.dosLatin2), + "latin5": encoding(.isoLatin5), + "macce": encoding(.macCentralEurRoman), + "macroman": .macOSRoman + ] + + private static let multiByteEncodings: [String: String.Encoding] = [ + "cp932": .shiftJIS, + "gbk": encoding(.GBK_95), + "gb2312": encoding(.EUC_CN), + "gb18030": encoding(.GB_18030_2000), + "ucs2": .utf16BigEndian, + "utf16": .utf16BigEndian, + "utf16le": .utf16LittleEndian, + "utf32": .utf32BigEndian + ] + + private static func encoding(_ encoding: CFStringEncodings) -> String.Encoding { + String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(encoding.rawValue))) + } + + private static func decode( + _ bytes: UnsafeRawBufferPointer, + encoding: String.Encoding, + isSingleByte: Bool + ) -> String { + if let text = String(bytes: bytes, encoding: encoding) { + return text + } + guard isSingleByte else { + return decodeUTF8ReplacingInvalid(bytes) + } + return bytes.reduce(into: "") { text, byte in + text += String(bytes: [byte], encoding: encoding) ?? "\u{FFFD}" + } + } +} diff --git a/Plugins/MySQLDriverPlugin/MySQLColumnDecoding.swift b/Plugins/MySQLDriverPlugin/MySQLColumnDecoding.swift new file mode 100644 index 0000000000..9b7b76d97b --- /dev/null +++ b/Plugins/MySQLDriverPlugin/MySQLColumnDecoding.swift @@ -0,0 +1,102 @@ +// +// MySQLColumnDecoding.swift +// MySQLDriverPlugin +// + +import Foundation +import TableProPluginKit + +internal enum MySQLColumnDecoding: Equatable, Sendable { + case geometry + case bit + case bytes + case text(MySQLCharacterSet) + case databendBoolean + case databendHexBytes + + private static let geometryType: UInt32 = 255 + + init( + typeRaw: UInt32, + length: UInt = 0, + charsetnr: UInt32, + characterSetName: String?, + flavor: MySQLServerFlavor = .mysql + ) { + let isBinary = MariaDBFieldClassifier.isBinary(typeRaw: typeRaw, charset: charsetnr) + if flavor.isDatabend, DatabendResultShape.isBoolean(typeRaw: typeRaw, length: length) { + self = .databendBoolean + } else if flavor.isDatabend, isBinary { + self = .databendHexBytes + } else if typeRaw == Self.geometryType { + self = flavor.isDatabend ? .text(.utf8mb4) : .geometry + } else if MariaDBFieldClassifier.isBit(typeRaw: typeRaw) { + self = .bit + } else if isBinary { + self = .bytes + } else if charsetnr == mysqlBinaryCharset { + self = .text(.utf8mb4) + } else { + self = .text(characterSetName.map(MySQLCharacterSet.init(serverName:)) ?? .utf8mb4) + } + } + + func decode(_ bytes: UnsafeRawBufferPointer, encoding: MySQLConnectionEncoding) -> PluginCellValue { + switch self { + case .geometry: + return .text(GeometryWKBParser.parse(bytes)) + case .bit: + return .text(MariaDBFieldClassifier.bitFieldToString(bytes)) + case .bytes: + return .bytes(Data(bytes)) + case .text(let characterSet): + return .text(encoding.presentedText(characterSet.decode(bytes))) + case .databendBoolean: + return .text(DatabendResultShape.booleanText(fromWireText: MySQLCharacterSet.utf8mb4.decode(bytes))) + case .databendHexBytes: + return .bytes(DatabendResultShape.binaryValue(fromWireText: Data(bytes))) + } + } +} + +internal struct MySQLResultColumns { + private(set) var names: [String] = [] + private(set) var typeCodes: [UInt32] = [] + private(set) var typeNames: [String] = [] + private(set) var decodings: [MySQLColumnDecoding] = [] + private(set) var metadata: [PluginColumnInfo] = [] + + var count: Int { names.count } + + mutating func append( + name: String, + typeCode: UInt32, + typeName: String, + decoding: MySQLColumnDecoding, + flags: UInt + ) { + names.append(name) + typeCodes.append(typeCode) + typeNames.append(typeName) + decodings.append(decoding) + metadata.append(makeColumnMeta(name: name, typeName: typeName, flags: flags)) + } + + func row( + encoding: MySQLConnectionEncoding, + value: (Int) -> UnsafeRawBufferPointer? + ) -> [PluginCellValue] { + decodings.indices.map { index in + guard let bytes = value(index) else { return .null } + return decodings[index].decode(bytes, encoding: encoding) + } + } +} + +internal func mysqlSessionText(_ bytes: UnsafeRawBufferPointer, encoding: MySQLConnectionEncoding) -> String { + encoding.presentedText(MySQLCharacterSet.decodeUTF8OrMySQLLatin1(bytes)) +} + +internal func mysqlSessionText(cString: UnsafePointer, encoding: MySQLConnectionEncoding) -> String { + mysqlSessionText(UnsafeRawBufferPointer(start: cString, count: strlen(cString)), encoding: encoding) +} diff --git a/Plugins/MySQLDriverPlugin/MySQLConnectionEncoding.swift b/Plugins/MySQLDriverPlugin/MySQLConnectionEncoding.swift new file mode 100644 index 0000000000..34457c1a42 --- /dev/null +++ b/Plugins/MySQLDriverPlugin/MySQLConnectionEncoding.swift @@ -0,0 +1,50 @@ +// +// MySQLConnectionEncoding.swift +// MySQLDriverPlugin +// + +import Foundation +import TableProPluginKit + +internal enum MySQLConnectionEncoding: String, CaseIterable, Sendable { + case utf8 = "" + case utf8ViaLatin1 + + static let fieldId = "mysqlConnectionEncoding" + static let sessionCharacterSetName = "utf8mb4" + static let sessionFallbackStatement = "SET NAMES utf8" + + static var connectionField: ConnectionField { + ConnectionField( + id: fieldId, + label: String(localized: "Encoding"), + fieldType: .dropdown(options: allCases.map { .init(value: $0.rawValue, label: $0.displayName) }), + section: .advanced + ) + } + + init(fieldValue: String?) { + self = fieldValue.flatMap(Self.init(rawValue:)) ?? .utf8 + } + + var displayName: String { + switch self { + case .utf8: return "UTF-8" + case .utf8ViaLatin1: return String(localized: "UTF-8 via Latin 1") + } + } + + var sessionStatements: [String] { + switch self { + case .utf8: return [] + case .utf8ViaLatin1: return ["SET character_set_client = latin1"] + } + } + + func presentedText(_ text: String) -> String { + switch self { + case .utf8: return text + case .utf8ViaLatin1: return MySQLLatin1.repairingDoubleEncodedUTF8(text) + } + } +} diff --git a/Plugins/MySQLDriverPlugin/MySQLLatin1.swift b/Plugins/MySQLDriverPlugin/MySQLLatin1.swift new file mode 100644 index 0000000000..5fd582f285 --- /dev/null +++ b/Plugins/MySQLDriverPlugin/MySQLLatin1.swift @@ -0,0 +1,64 @@ +// +// MySQLLatin1.swift +// MySQLDriverPlugin +// + +import Foundation + +internal enum MySQLLatin1 { + private static let windowsRangeScalars: [UInt32] = [ + 0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008D, 0x017D, 0x008F, + 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x017E, 0x0178 + ] + + private static let windowsRange = 0x80...0x9F + + static let scalarsByByte: [Unicode.Scalar] = (0...255).map { byte in + guard windowsRange.contains(byte), + let scalar = Unicode.Scalar(windowsRangeScalars[byte - windowsRange.lowerBound]) else { + return Unicode.Scalar(UInt8(byte)) + } + return scalar + } + + private static let bytesByScalar: [UInt32: UInt8] = Dictionary( + uniqueKeysWithValues: scalarsByByte.enumerated().map { ($0.element.value, UInt8($0.offset)) } + ) + + static func decode(_ bytes: UnsafeRawBufferPointer) -> String { + guard bytes.contains(where: { $0 >= 0x80 }) else { + return MySQLCharacterSet.decodeUTF8ReplacingInvalid(bytes) + } + var scalars = String.UnicodeScalarView() + scalars.reserveCapacity(bytes.count) + for byte in bytes { + scalars.append(scalarsByByte[Int(byte)]) + } + return String(scalars) + } + + static func decode(_ bytes: [UInt8]) -> String { + bytes.withUnsafeBytes { decode($0) } + } + + static func bytes(representing text: String) -> [UInt8]? { + var bytes: [UInt8] = [] + bytes.reserveCapacity(text.utf8.count) + for scalar in text.unicodeScalars { + guard let byte = bytesByScalar[scalar.value] else { return nil } + bytes.append(byte) + } + return bytes + } + + static func repairingDoubleEncodedUTF8(_ text: String) -> String { + guard text.utf8.contains(where: { $0 >= 0x80 }) else { return text } + guard let original = bytes(representing: text), + let repaired = String(bytes: original, encoding: .utf8) else { + return text + } + return repaired + } +} diff --git a/Plugins/MySQLDriverPlugin/MySQLPlugin.swift b/Plugins/MySQLDriverPlugin/MySQLPlugin.swift index 33f95710de..bdba8d1fca 100644 --- a/Plugins/MySQLDriverPlugin/MySQLPlugin.swift +++ b/Plugins/MySQLDriverPlugin/MySQLPlugin.swift @@ -30,7 +30,8 @@ final class MySQLPlugin: NSObject, TableProPlugin, DriverPlugin { defaultValue: "0", fieldType: .stepper(range: ConnectionField.IntRange(0...240)), section: .advanced - ) + ), + MySQLConnectionEncoding.connectionField ] static let additionalDatabaseTypeIds: [String] = ["MariaDB", "TiDB", "Databend"] diff --git a/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift b/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift index 97eaf4ba58..2d15ac1406 100644 --- a/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift +++ b/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift @@ -124,7 +124,10 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { database: _activeDatabase, sslConfig: sslConfig, enableCleartextPlugin: config.additionalFields["enableCleartextPlugin"] == "true", - queryTimeoutSeconds: config.additionalFields["queryTimeoutSeconds"].flatMap { Int($0) } ?? 0 + queryTimeoutSeconds: config.additionalFields["queryTimeoutSeconds"].flatMap { Int($0) } ?? 0, + connectionEncoding: MySQLConnectionEncoding( + fieldValue: config.additionalFields[MySQLConnectionEncoding.fieldId] + ) ) try await conn.connect() diff --git a/Plugins/SQLExportPlugin/SQLExportEncodingDeclaration.swift b/Plugins/SQLExportPlugin/SQLExportEncodingDeclaration.swift new file mode 100644 index 0000000000..2f5dc785fa --- /dev/null +++ b/Plugins/SQLExportPlugin/SQLExportEncodingDeclaration.swift @@ -0,0 +1,42 @@ +// +// SQLExportEncodingDeclaration.swift +// SQLExportPlugin +// + +import Foundation +import TableProPluginKit + +internal struct SQLExportEncodingDeclaration: Equatable { + static let empty = SQLExportEncodingDeclaration(prologue: "", epilogue: "") + + let prologue: String + let epilogue: String + + static func forDialect(_ dialect: SqlDialect) -> SQLExportEncodingDeclaration { + switch dialect { + case .mysql: + return mysql + default: + return .empty + } + } + + private static let mysql = SQLExportEncodingDeclaration( + prologue: """ + /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; + /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; + /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; + /*!40101 SET NAMES utf8 */; + /*!50503 SET NAMES utf8mb4 */; + + + """, + epilogue: """ + + /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; + /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; + /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; + + """ + ) +} diff --git a/Plugins/SQLExportPlugin/SQLExportFileWriter.swift b/Plugins/SQLExportPlugin/SQLExportFileWriter.swift index a0673e562a..2afa774923 100644 --- a/Plugins/SQLExportPlugin/SQLExportFileWriter.swift +++ b/Plugins/SQLExportPlugin/SQLExportFileWriter.swift @@ -27,20 +27,33 @@ internal final class SQLExportFileWriter { private let destination: URL private let splitSizeBytes: Int + private let encodingDeclaration: SQLExportEncodingDeclaration private var handle: FileHandle private var tempURL: URL private var bytesInCurrentPart = 0 + private var currentPartHasStatements = false private var partIndex = 1 private var pending: [(temp: URL, final: URL)] = [] private var isCommitted = false - internal init(destination: URL, splitSizeMegabytes: Int) throws { + internal init( + destination: URL, + splitSizeMegabytes: Int, + encodingDeclaration: SQLExportEncodingDeclaration = .empty + ) throws { self.destination = destination self.splitSizeBytes = max(0, splitSizeMegabytes) * 1_024 * 1_024 + self.encodingDeclaration = encodingDeclaration let (handle, tempURL) = try PluginExportUtilities.beginAtomicWrite(for: destination) self.handle = handle self.tempURL = tempURL + do { + try writeRaw(encodingDeclaration.prologue) + } catch { + rollback() + throw error + } } /// True once a second part exists, so the caller can report the split rather than leaving the @@ -51,17 +64,20 @@ internal final class SQLExportFileWriter { internal func write(_ text: String) throws { let data = try text.toUTF8Data() - if splitSizeBytes > 0, bytesInCurrentPart > 0, bytesInCurrentPart + data.count > splitSizeBytes { + let partSize = bytesInCurrentPart + data.count + encodingDeclaration.epilogue.utf8.count + if splitSizeBytes > 0, currentPartHasStatements, partSize > splitSizeBytes { try rotate() } try handle.write(contentsOf: data) bytesInCurrentPart += data.count + currentPartHasStatements = true } /// Publishes every part and returns where they landed. An unsplit export keeps the name the /// user chose; a split one numbers all of its parts, so no part silently claims that name. @discardableResult internal func commit() throws -> [URL] { + try writeRaw(encodingDeclaration.epilogue) try handle.close() let finalURL = didSplit ? Self.partURL(for: destination, part: partIndex) : destination pending.append((tempURL, finalURL)) @@ -88,6 +104,7 @@ internal final class SQLExportFileWriter { internal var currentFileURL: URL { tempURL } private func rotate() throws { + try writeRaw(encodingDeclaration.epilogue) try handle.close() pending.append((tempURL, Self.partURL(for: destination, part: partIndex))) partIndex += 1 @@ -95,5 +112,14 @@ internal final class SQLExportFileWriter { handle = nextHandle tempURL = nextTemp bytesInCurrentPart = 0 + currentPartHasStatements = false + try writeRaw(encodingDeclaration.prologue) + } + + private func writeRaw(_ text: String) throws { + guard !text.isEmpty else { return } + let data = try text.toUTF8Data() + try handle.write(contentsOf: data) + bytesInCurrentPart += data.count } } diff --git a/Plugins/SQLExportPlugin/SQLExportPlugin.swift b/Plugins/SQLExportPlugin/SQLExportPlugin.swift index 9feba46ef5..ab5b969155 100644 --- a/Plugins/SQLExportPlugin/SQLExportPlugin.swift +++ b/Plugins/SQLExportPlugin/SQLExportPlugin.swift @@ -139,7 +139,11 @@ final class SQLExportPlugin: ExportFormatPlugin, SettablePlugin, @unchecked Send metadataWarnings.append(String(localized: "A compressed export is written as one file, so the split size was not applied.")) } - let writer = try SQLExportFileWriter(destination: actualDestination, splitSizeMegabytes: splitSize) + let writer = try SQLExportFileWriter( + destination: actualDestination, + splitSizeMegabytes: splitSize, + encodingDeclaration: .forDialect(SqlDialect.from(databaseTypeId: dataSource.databaseTypeId)) + ) var committed = false defer { if !committed { writer.rollback() } @@ -478,10 +482,7 @@ final class SQLExportPlugin: ExportFormatPlugin, SettablePlugin, @unchecked Send guard !ddl.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { throw SQLExportObjectError.emptyDefinition } - try writer.write(ddl) - if !ddl.hasSuffix(";") { - try writer.write(";") - } + try writer.write(ddl.hasSuffix(";") ? ddl : ddl + ";") try writer.write("\n\n") } catch { ddlFailures.append(sanitizedName) @@ -524,10 +525,7 @@ final class SQLExportPlugin: ExportFormatPlugin, SettablePlugin, @unchecked Send guard !ddl.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { throw SQLExportObjectError.emptyDefinition } - try writer.write(ddl) - if !ddl.hasSuffix(";") { - try writer.write(";") - } + try writer.write(ddl.hasSuffix(";") ? ddl : ddl + ";") try writer.write("\n\n") } catch { ddlFailures.append(sanitizedName) diff --git a/TablePro/Core/Plugins/PluginMetadataRegistry+CuratedDefaults.swift b/TablePro/Core/Plugins/PluginMetadataRegistry+CuratedDefaults.swift index 2373cc1bbd..558d6ea777 100644 --- a/TablePro/Core/Plugins/PluginMetadataRegistry+CuratedDefaults.swift +++ b/TablePro/Core/Plugins/PluginMetadataRegistry+CuratedDefaults.swift @@ -223,6 +223,16 @@ extension PluginMetadataRegistry { section: .advanced ) + let mysqlEncodingField = ConnectionField( + id: "mysqlConnectionEncoding", + label: String(localized: "Encoding"), + fieldType: .dropdown(options: [ + .init(value: "", label: "UTF-8"), + .init(value: "utf8ViaLatin1", label: String(localized: "UTF-8 via Latin 1")) + ]), + section: .advanced + ) + let defaults: [(typeId: String, snapshot: PluginMetadataSnapshot)] = [ ("MySQL", PluginMetadataSnapshot( displayName: "MySQL", iconName: "mysql-icon", defaultPort: 3_306, @@ -282,7 +292,7 @@ extension PluginMetadataRegistry { columnTypesByCategory: mysqlColumnTypes ), connection: PluginMetadataSnapshot.ConnectionConfig( - additionalConnectionFields: awsIAMFields + [mysqlIdleReleaseField], + additionalConnectionFields: awsIAMFields + [mysqlIdleReleaseField, mysqlEncodingField], category: .relational, tagline: String(localized: "Most popular open-source SQL database"), defaultUnixSocketPath: "/var/run/mysqld/mysqld.sock" @@ -346,7 +356,7 @@ extension PluginMetadataRegistry { columnTypesByCategory: mysqlColumnTypes ), connection: PluginMetadataSnapshot.ConnectionConfig( - additionalConnectionFields: awsIAMFields + [mysqlIdleReleaseField], + additionalConnectionFields: awsIAMFields + [mysqlIdleReleaseField, mysqlEncodingField], category: .relational, tagline: String(localized: "Open-source fork of MySQL"), defaultUnixSocketPath: "/var/run/mysqld/mysqld.sock" diff --git a/TableProTests/Core/Database/GeometryWKBParserTests.swift b/TableProTests/Core/Database/GeometryWKBParserTests.swift index 42061f9650..ba80e74719 100644 --- a/TableProTests/Core/Database/GeometryWKBParserTests.swift +++ b/TableProTests/Core/Database/GeometryWKBParserTests.swift @@ -77,7 +77,6 @@ private func wkbPolygon(_ rings: [[(Double, Double)]]) -> [UInt8] { @Suite("GeometryWKBParser") struct GeometryWKBParserTests { - @Test("Point: little-endian binary produces WKT") func testPoint() { let data = mysqlGeometry(wkb: wkbPoint(1.0, 2.0)) @@ -177,246 +176,3 @@ struct GeometryWKBParserTests { #expect(result == "POINT(100.0 200.0)") } } - -// MARK: - Local Copy of GeometryWKBParser - -// Copied from Plugins/MySQLDriverPlugin/GeometryWKBParser.swift -// because the plugin is a bundle target and cannot be imported with @testable import. - -private enum GeometryWKBParser { - static func parse(_ data: Data) -> String { - guard data.count >= 9 else { - return hexString(data) - } - - let wkbData = data.dropFirst(4) - var offset = wkbData.startIndex - return parseWKBGeometry(wkbData, offset: &offset) ?? hexString(data) - } - - static func parse(_ buffer: UnsafeRawBufferPointer) -> String { - let data = Data(buffer) - return parse(data) - } - - private static func parseWKBGeometry(_ data: Data.SubSequence, offset: inout Data.Index) -> String? { - guard offset < data.endIndex else { return nil } - - let byteOrder = data[offset] - let littleEndian = byteOrder == 0x01 - offset = data.index(after: offset) - - guard let typeCode = readUInt32(data, offset: &offset, littleEndian: littleEndian) else { - return nil - } - - switch typeCode { - case 1: - return parsePoint(data, offset: &offset, littleEndian: littleEndian) - case 2: - return parseLineString(data, offset: &offset, littleEndian: littleEndian) - case 3: - return parsePolygon(data, offset: &offset, littleEndian: littleEndian) - case 4: - return parseMultiPoint(data, offset: &offset, littleEndian: littleEndian) - case 5: - return parseMultiLineString(data, offset: &offset, littleEndian: littleEndian) - case 6: - return parseMultiPolygon(data, offset: &offset, littleEndian: littleEndian) - case 7: - return parseGeometryCollection(data, offset: &offset, littleEndian: littleEndian) - default: - return nil - } - } - - private static func parsePoint( - _ data: Data.SubSequence, - offset: inout Data.Index, - littleEndian: Bool - ) -> String? { - guard let x = readFloat64(data, offset: &offset, littleEndian: littleEndian), - let y = readFloat64(data, offset: &offset, littleEndian: littleEndian) else { - return nil - } - return "POINT(\(formatCoord(x)) \(formatCoord(y)))" - } - - private static func parseLineString( - _ data: Data.SubSequence, - offset: inout Data.Index, - littleEndian: Bool - ) -> String? { - guard let points = readPointList(data, offset: &offset, littleEndian: littleEndian) else { - return nil - } - return "LINESTRING(\(points))" - } - - private static func parsePolygon( - _ data: Data.SubSequence, - offset: inout Data.Index, - littleEndian: Bool - ) -> String? { - guard let numRings = readUInt32(data, offset: &offset, littleEndian: littleEndian) else { - return nil - } - var rings: [String] = [] - for _ in 0 ..< numRings { - guard let points = readPointList(data, offset: &offset, littleEndian: littleEndian) else { - return nil - } - rings.append("(\(points))") - } - return "POLYGON(\(rings.joined(separator: ", ")))" - } - - private static func parseMultiPoint( - _ data: Data.SubSequence, - offset: inout Data.Index, - littleEndian: Bool - ) -> String? { - guard let numGeoms = readUInt32(data, offset: &offset, littleEndian: littleEndian) else { - return nil - } - var points: [String] = [] - for _ in 0 ..< numGeoms { - guard let geom = parseWKBGeometry(data, offset: &offset) else { return nil } - if geom.hasPrefix("POINT("), geom.hasSuffix(")") { - let ns = geom as NSString - points.append(ns.substring(with: NSRange(location: 6, length: ns.length - 7))) - } else { - points.append(geom) - } - } - return "MULTIPOINT(\(points.joined(separator: ", ")))" - } - - private static func parseMultiLineString( - _ data: Data.SubSequence, - offset: inout Data.Index, - littleEndian: Bool - ) -> String? { - guard let numGeoms = readUInt32(data, offset: &offset, littleEndian: littleEndian) else { - return nil - } - var lineStrings: [String] = [] - for _ in 0 ..< numGeoms { - guard let geom = parseWKBGeometry(data, offset: &offset) else { return nil } - if geom.hasPrefix("LINESTRING("), geom.hasSuffix(")") { - let ns = geom as NSString - lineStrings.append("(\(ns.substring(with: NSRange(location: 11, length: ns.length - 12))))") - } else { - lineStrings.append(geom) - } - } - return "MULTILINESTRING(\(lineStrings.joined(separator: ", ")))" - } - - private static func parseMultiPolygon( - _ data: Data.SubSequence, - offset: inout Data.Index, - littleEndian: Bool - ) -> String? { - guard let numGeoms = readUInt32(data, offset: &offset, littleEndian: littleEndian) else { - return nil - } - var polygons: [String] = [] - for _ in 0 ..< numGeoms { - guard let geom = parseWKBGeometry(data, offset: &offset) else { return nil } - if geom.hasPrefix("POLYGON("), geom.hasSuffix(")") { - let ns = geom as NSString - polygons.append("(\(ns.substring(with: NSRange(location: 8, length: ns.length - 9))))") - } else { - polygons.append(geom) - } - } - return "MULTIPOLYGON(\(polygons.joined(separator: ", ")))" - } - - private static func parseGeometryCollection( - _ data: Data.SubSequence, - offset: inout Data.Index, - littleEndian: Bool - ) -> String? { - guard let numGeoms = readUInt32(data, offset: &offset, littleEndian: littleEndian) else { - return nil - } - var geoms: [String] = [] - for _ in 0 ..< numGeoms { - guard let geom = parseWKBGeometry(data, offset: &offset) else { return nil } - geoms.append(geom) - } - return "GEOMETRYCOLLECTION(\(geoms.joined(separator: ", ")))" - } - - private static func readUInt32( - _ data: Data.SubSequence, - offset: inout Data.Index, - littleEndian: Bool - ) -> UInt32? { - let endOffset = data.index(offset, offsetBy: 4, limitedBy: data.endIndex) ?? data.endIndex - guard data.distance(from: offset, to: endOffset) == 4 else { return nil } - - let bytes = data[offset ..< endOffset] - offset = endOffset - - if littleEndian { - return bytes.withUnsafeBytes { $0.loadUnaligned(as: UInt32.self).littleEndian } - } else { - return bytes.withUnsafeBytes { $0.loadUnaligned(as: UInt32.self).bigEndian } - } - } - - private static func readFloat64( - _ data: Data.SubSequence, - offset: inout Data.Index, - littleEndian: Bool - ) -> Double? { - let endOffset = data.index(offset, offsetBy: 8, limitedBy: data.endIndex) ?? data.endIndex - guard data.distance(from: offset, to: endOffset) == 8 else { return nil } - - let bytes = data[offset ..< endOffset] - offset = endOffset - - let bits: UInt64 - if littleEndian { - bits = bytes.withUnsafeBytes { $0.loadUnaligned(as: UInt64.self).littleEndian } - } else { - bits = bytes.withUnsafeBytes { $0.loadUnaligned(as: UInt64.self).bigEndian } - } - return Double(bitPattern: bits) - } - - private static func readPointList( - _ data: Data.SubSequence, - offset: inout Data.Index, - littleEndian: Bool - ) -> String? { - guard let numPoints = readUInt32(data, offset: &offset, littleEndian: littleEndian) else { - return nil - } - var coords: [String] = [] - for _ in 0 ..< numPoints { - guard let x = readFloat64(data, offset: &offset, littleEndian: littleEndian), - let y = readFloat64(data, offset: &offset, littleEndian: littleEndian) else { - return nil - } - coords.append("\(formatCoord(x)) \(formatCoord(y))") - } - return coords.joined(separator: ", ") - } - - private static func formatCoord(_ value: Double) -> String { - if value == value.rounded() && abs(value) < 1e15 { - return String(format: "%.1f", value) - } - let formatted = String(format: "%.15g", value) - return formatted - } - - static func hexString(_ data: Data) -> String { - if data.isEmpty { return "" } - return "0x" + data.map { String(format: "%02X", $0) }.joined() - } -} diff --git a/TableProTests/Plugins/MariaDBFieldClassifierTests.swift b/TableProTests/Plugins/MariaDBFieldClassifierTests.swift index 883dbc64fd..f570a3fd43 100644 --- a/TableProTests/Plugins/MariaDBFieldClassifierTests.swift +++ b/TableProTests/Plugins/MariaDBFieldClassifierTests.swift @@ -3,13 +3,10 @@ // TableProTests // -#if canImport(MySQLDriverPlugin) import Foundation import TableProPluginKit import Testing -@testable import MySQLDriverPlugin - @Suite("MariaDBFieldClassifier") struct MariaDBFieldClassifierTests { @Test("makeColumnMeta reads PRIMARY KEY, NOT NULL, and AUTO_INCREMENT flags") @@ -82,7 +79,6 @@ struct MariaDBFieldClassifierTests { bytes.withUnsafeBytes { MariaDBFieldClassifier.bitFieldToString($0) } } - @Test("BLOB family with binary charset routes to binary") func blobFamilyBinary() { for typeRaw: UInt32 in [249, 250, 251, 252] { @@ -147,4 +143,3 @@ struct MariaDBFieldClassifierTests { #expect(!MariaDBFieldClassifier.isBinary(typeRaw: 255, charset: 63)) // GEOMETRY (handled upstream) } } -#endif diff --git a/TableProTests/Plugins/MariaDBTypeNameTests.swift b/TableProTests/Plugins/MariaDBTypeNameTests.swift index 2fb80741ae..af00cc4630 100644 --- a/TableProTests/Plugins/MariaDBTypeNameTests.swift +++ b/TableProTests/Plugins/MariaDBTypeNameTests.swift @@ -3,11 +3,8 @@ // TableProTests // -#if canImport(MySQLDriverPlugin) import Testing -@testable import MySQLDriverPlugin - @Suite("MariaDB type name resolution") struct MariaDBTypeNameTests { private func resolve(typeRaw: UInt32, charsetnr: UInt32 = 33, flags: UInt = 0, length: UInt = 0) -> String { @@ -117,4 +114,3 @@ struct MariaDBTypeNameTests { #expect(resolve(typeRaw: 252, charsetnr: 33, flags: 0, length: 100_000) == "LONGTEXT") } } -#endif diff --git a/TableProTests/Plugins/MySQLCharacterSetTests.swift b/TableProTests/Plugins/MySQLCharacterSetTests.swift new file mode 100644 index 0000000000..c6717f1f09 --- /dev/null +++ b/TableProTests/Plugins/MySQLCharacterSetTests.swift @@ -0,0 +1,73 @@ +// +// MySQLCharacterSetTests.swift +// TableProTests +// + +import Foundation +import Testing + +@Suite("MySQL character set decoding") +struct MySQLCharacterSetTests { + private func decode(_ bytes: [UInt8], as name: String) -> String { + bytes.withUnsafeBytes { MySQLCharacterSet(serverName: name).decode($0) } + } + + @Test("Server names are normalized, and utf8 means utf8mb3") + func namesAreNormalized() { + #expect(MySQLCharacterSet(serverName: "UTF8").name == "utf8mb3") + #expect(MySQLCharacterSet(serverName: " latin1 ") == .latin1) + #expect(MySQLCharacterSet(serverName: "utf8mb4") == .utf8mb4) + } + + @Test("UTF-8 text decodes as UTF-8") + func utf8Decodes() { + #expect(decode(Array("メール・記事紐付け".utf8), as: "utf8mb4") == "メール・記事紐付け") + #expect(decode(Array("😀".utf8), as: "utf8mb4") == "😀") + } + + @Test("Invalid UTF-8 is marked with a replacement character, not reinvented as Latin 1") + func invalidUTF8IsNotFabricated() { + #expect(decode([0x61, 0xFF, 0x62], as: "utf8mb4") == "a\u{FFFD}b") + #expect(decode([0x63, 0x61, 0x66, 0xE9], as: "utf8mb3") == "caf\u{FFFD}") + } + + @Test("A latin1 column holding UTF-8 bytes reads as that UTF-8") + func latin1HoldingUTF8() { + #expect(decode([0xE3, 0x83, 0xA1], as: "latin1") == "メ") + } + + @Test("A latin1 column holding Latin 1 text uses MySQL's own latin1, which is cp1252") + func latin1IsWindows1252() { + #expect(decode([0x69, 0x74, 0x92, 0x73, 0x20, 0x35, 0x80], as: "latin1") == "it’s 5€") + #expect(decode([0x63, 0x61, 0x66, 0xE9], as: "latin1") == "café") + } + + @Test("Charsets Foundation decodes byte-for-byte like the server use Foundation") + func foundationCharsets() { + #expect(decode([0xCF, 0xF0, 0xE8, 0xE2, 0xE5, 0xF2], as: "cp1251") == "Привет") + #expect(decode([0xB1, 0xE6], as: "latin2") == "ąć") + #expect(decode([0x83, 0x81, 0x81, 0x5B, 0x83, 0x8B, 0x5C], as: "cp932") == "メール\\") + #expect(decode([0xD6, 0xD0, 0xCE, 0xC4], as: "gbk") == "中文") + #expect(decode([0x30, 0xE1, 0x30, 0xFC], as: "utf16") == "メー") + #expect(decode([0xE1, 0x30, 0xFC, 0x30], as: "utf16le") == "メー") + } + + @Test("A byte a single-byte charset leaves undefined becomes one replacement character") + func undefinedSingleByteKeepsTheRest() { + #expect(decode([0x61, 0x81, 0x62], as: "cp1250") == "a\u{FFFD}b") + } + + @Test("Charsets whose Foundation mapping disagrees with the server are not in the table") + func mismatchedCharsetsAreExcluded() { + let decodable = Set(MySQLCharacterSet.singleByteDecodedNames + MySQLCharacterSet.multiByteDecodedNames) + for name in ["sjis", "ujis", "eucjpms", "big5", "euckr", "greek", "hebrew", "koi8r", "koi8u", "cp866", "latin7", "tis620"] { + #expect(!decodable.contains(name), "\(name)") + } + } + + @Test("A charset without a verified decoder reads valid UTF-8 as UTF-8") + func unknownCharsetFallsBackToUTF8() { + #expect(decode(Array("abc".utf8), as: "armscii8") == "abc") + #expect(decode([0x61, 0xFF], as: "armscii8") == "a\u{FFFD}") + } +} diff --git a/TableProTests/Plugins/MySQLColumnDecodingTests.swift b/TableProTests/Plugins/MySQLColumnDecodingTests.swift new file mode 100644 index 0000000000..37be254ad9 --- /dev/null +++ b/TableProTests/Plugins/MySQLColumnDecodingTests.swift @@ -0,0 +1,107 @@ +// +// MySQLColumnDecodingTests.swift +// TableProTests +// + +import Foundation +import TableProPluginKit +import Testing + +@Suite("MySQL column decoding") +struct MySQLColumnDecodingTests { + private static let doubleEncodedMail = String(bytes: [0xC3, 0xA3, 0xC6, 0x92, 0xC2, 0xA1], encoding: .utf8) ?? "" + + private func decoding(type: UInt32, charset: UInt32, name: String? = "utf8mb4") -> MySQLColumnDecoding { + MySQLColumnDecoding(typeRaw: type, charsetnr: charset, characterSetName: name) + } + + private func decode( + _ bytes: [UInt8], + with decoding: MySQLColumnDecoding, + encoding: MySQLConnectionEncoding = .utf8 + ) -> PluginCellValue { + bytes.withUnsafeBytes { decoding.decode($0, encoding: encoding) } + } + + @Test("Each column kind gets its own decoding") + func columnKinds() { + #expect(decoding(type: 255, charset: 63) == .geometry) + #expect(decoding(type: 16, charset: 63) == .bit) + #expect(decoding(type: 252, charset: 63) == .bytes) + #expect(decoding(type: 253, charset: 63) == .bytes) + #expect(decoding(type: 253, charset: 8, name: "latin1") == .text(.latin1)) + #expect(decoding(type: 252, charset: 255, name: "utf8mb4") == .text(.utf8mb4)) + } + + @Test("Numbers, dates and JSON carry the binary charset and decode as text") + func binaryCharsetScalarsAreText() { + for type: UInt32 in [3, 8, 12, 245, 246] { + #expect(decoding(type: type, charset: 63, name: "binary") == .text(.utf8mb4)) + } + } + + @Test("Databend's booleans, hex-encoded binary and text geometry keep their own decoding") + func databendShapes() { + let boolean = MySQLColumnDecoding(typeRaw: 2, length: 1, charsetnr: 63, characterSetName: "binary", flavor: .databend) + #expect(boolean == .databendBoolean) + #expect(decode(Array("1".utf8), with: boolean) == .text("true")) + + let binary = MySQLColumnDecoding(typeRaw: 252, charsetnr: 63, characterSetName: "binary", flavor: .databend) + #expect(binary == .databendHexBytes) + #expect(decode(Array("CAFE".utf8), with: binary) == .bytes(Data([0xCA, 0xFE]))) + + let geometry = MySQLColumnDecoding(typeRaw: 255, charsetnr: 63, characterSetName: "binary", flavor: .databend) + #expect(geometry == .text(.utf8mb4)) + #expect(MySQLColumnDecoding(typeRaw: 2, length: 1, charsetnr: 63, characterSetName: "binary") == .text(.utf8mb4)) + } + + @Test("A collation id libmariadb does not know decodes as the session's UTF-8") + func unknownCollationIsUTF8() { + #expect(decoding(type: 253, charset: 309, name: nil) == .text(.utf8mb4)) + } + + @Test("The default encoding shows exactly what the server stored") + func defaultShowsStoredText() { + let stored = Array(Self.doubleEncodedMail.utf8) + #expect(decode(stored, with: .text(.utf8mb4)) == .text(Self.doubleEncodedMail)) + } + + @Test("UTF-8 via Latin 1 repairs text columns only") + func legacyModeRepairsText() { + let stored = Array(Self.doubleEncodedMail.utf8) + #expect(decode(stored, with: .text(.utf8mb4), encoding: .utf8ViaLatin1) == .text("メ")) + #expect(decode(stored, with: .bytes, encoding: .utf8ViaLatin1) == .bytes(Data(stored))) + } + + @Test("A result row keeps NULLs and decodes every other cell by its column") + func resultRow() { + var columns = MySQLResultColumns() + columns.append(name: "id", typeCode: 3, typeName: "INT", decoding: .text(.utf8mb4), flags: mysqlPriKeyFlag) + columns.append(name: "note", typeCode: 253, typeName: "VARCHAR", decoding: .text(.latin1), flags: 0) + columns.append(name: "missing", typeCode: 253, typeName: "VARCHAR", decoding: .text(.utf8mb4), flags: 0) + let cells: [[UInt8]?] = [Array("7".utf8), [0x63, 0x61, 0x66, 0xE9], nil] + let buffers = cells.map { cell in + cell.map { bytes in + let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: bytes.count, alignment: 1) + buffer.copyBytes(from: bytes) + return buffer + } + } + defer { buffers.forEach { $0?.deallocate() } } + + let row = columns.row(encoding: .utf8) { index in + buffers[index].map { UnsafeRawBufferPointer($0) } + } + + #expect(row == [.text("7"), .text("café"), .null]) + #expect(columns.metadata.first?.isPrimaryKey == true) + } + + @Test("Names and messages read as UTF-8, or as MySQL latin1 when a latin1 session sent them") + func sessionText() { + let utf8 = Array("列名".utf8) + let latin1: [UInt8] = [0x63, 0x61, 0x66, 0xE9] + #expect(utf8.withUnsafeBytes { mysqlSessionText($0, encoding: .utf8) } == "列名") + #expect(latin1.withUnsafeBytes { mysqlSessionText($0, encoding: .utf8) } == "café") + } +} diff --git a/TableProTests/Plugins/MySQLConnectionEncodingTests.swift b/TableProTests/Plugins/MySQLConnectionEncodingTests.swift new file mode 100644 index 0000000000..52218ceecd --- /dev/null +++ b/TableProTests/Plugins/MySQLConnectionEncodingTests.swift @@ -0,0 +1,82 @@ +// +// MySQLConnectionEncodingTests.swift +// TableProTests +// + +import Foundation +@testable import TablePro +import TableProPluginKit +import Testing + +@Suite("MySQL connection encoding") +struct MySQLConnectionEncodingTests { + @Test("A missing, empty or unknown field value is plain UTF-8") + func fieldValueParsing() { + #expect(MySQLConnectionEncoding(fieldValue: nil) == .utf8) + #expect(MySQLConnectionEncoding(fieldValue: "") == .utf8) + #expect(MySQLConnectionEncoding(fieldValue: "sjis") == .utf8) + #expect(MySQLConnectionEncoding(fieldValue: "utf8ViaLatin1") == .utf8ViaLatin1) + } + + @Test("Only UTF-8 via Latin 1 changes the client character set, and only the client's") + func sessionStatements() { + #expect(MySQLConnectionEncoding.utf8.sessionStatements.isEmpty) + #expect(MySQLConnectionEncoding.utf8ViaLatin1.sessionStatements == ["SET character_set_client = latin1"]) + #expect(MySQLConnectionEncoding.sessionCharacterSetName == "utf8mb4") + #expect(MySQLConnectionEncoding.sessionFallbackStatement == "SET NAMES utf8") + } + + @Test("The field is an advanced dropdown whose values the driver reads back") + func fieldShape() throws { + let field = MySQLConnectionEncoding.connectionField + #expect(field.id == MySQLConnectionEncoding.fieldId) + #expect(field.section == .advanced) + guard case .dropdown(let options) = field.fieldType else { + Issue.record("expected a dropdown") + return + } + #expect(options.map(\.value) == MySQLConnectionEncoding.allCases.map(\.rawValue)) + for option in options { + #expect(MySQLConnectionEncoding(fieldValue: option.value).rawValue == option.value) + } + } + + @Test("MySQL and MariaDB curate the same encoding field the plugin declares") + func curatedFieldsMatchThePlugin() throws { + let expected = try Self.encoded(MySQLConnectionEncoding.connectionField) + let curated = PluginMetadataRegistry.curatedDefaults() + for typeId in ["MySQL", "MariaDB"] { + let snapshot = try #require(curated.first { $0.typeId == typeId }?.snapshot) + let field = try #require( + snapshot.connection.additionalConnectionFields.first { $0.id == MySQLConnectionEncoding.fieldId }, + "\(typeId) curates no encoding field" + ) + #expect(try Self.encoded(field) == expected, "\(typeId)") + } + } + + @Test("The MySQL plugin declares the shared encoding field") + func pluginDeclaresTheField() throws { + let source = try String(contentsOf: Self.repositoryRoot().appendingPathComponent( + "Plugins/MySQLDriverPlugin/MySQLPlugin.swift" + ), encoding: .utf8) + #expect(source.contains("MySQLConnectionEncoding.connectionField")) + } + + private static func encoded(_ field: ConnectionField) throws -> Data { + let encoder = JSONEncoder() + encoder.outputFormatting = [.sortedKeys] + return try encoder.encode(field) + } + + private static func repositoryRoot(file: StaticString = #filePath) throws -> URL { + var directory = URL(fileURLWithPath: "\(file)").deletingLastPathComponent() + while directory.path != "/" { + if FileManager.default.fileExists(atPath: directory.appendingPathComponent("project.yml").path) { + return directory + } + directory = directory.deletingLastPathComponent() + } + throw CocoaError(.fileNoSuchFile) + } +} diff --git a/TableProTests/Plugins/MySQLLatin1Tests.swift b/TableProTests/Plugins/MySQLLatin1Tests.swift new file mode 100644 index 0000000000..e6e15332eb --- /dev/null +++ b/TableProTests/Plugins/MySQLLatin1Tests.swift @@ -0,0 +1,101 @@ +// +// MySQLLatin1Tests.swift +// TableProTests +// + +import Foundation +import Testing + +@Suite("MySQL latin1") +struct MySQLLatin1Tests { + private static let serverUTF8ForUpperHalf: [String] = [ + "E282AC", "C281", "E2809A", "C692", "E2809E", "E280A6", "E280A0", "E280A1", + "CB86", "E280B0", "C5A0", "E280B9", "C592", "C28D", "C5BD", "C28F", + "C290", "E28098", "E28099", "E2809C", "E2809D", "E280A2", "E28093", "E28094", + "CB9C", "E284A2", "C5A1", "E280BA", "C593", "C29D", "C5BE", "C5B8", + "C2A0", "C2A1", "C2A2", "C2A3", "C2A4", "C2A5", "C2A6", "C2A7", + "C2A8", "C2A9", "C2AA", "C2AB", "C2AC", "C2AD", "C2AE", "C2AF", + "C2B0", "C2B1", "C2B2", "C2B3", "C2B4", "C2B5", "C2B6", "C2B7", + "C2B8", "C2B9", "C2BA", "C2BB", "C2BC", "C2BD", "C2BE", "C2BF", + "C380", "C381", "C382", "C383", "C384", "C385", "C386", "C387", + "C388", "C389", "C38A", "C38B", "C38C", "C38D", "C38E", "C38F", + "C390", "C391", "C392", "C393", "C394", "C395", "C396", "C397", + "C398", "C399", "C39A", "C39B", "C39C", "C39D", "C39E", "C39F", + "C3A0", "C3A1", "C3A2", "C3A3", "C3A4", "C3A5", "C3A6", "C3A7", + "C3A8", "C3A9", "C3AA", "C3AB", "C3AC", "C3AD", "C3AE", "C3AF", + "C3B0", "C3B1", "C3B2", "C3B3", "C3B4", "C3B5", "C3B6", "C3B7", + "C3B8", "C3B9", "C3BA", "C3BB", "C3BC", "C3BD", "C3BE", "C3BF" + ] + + private static let reporterMojibakeUTF8 = + "C3A3C692C2A1C3A3C692C2BCC3A3C692C2ABC3A3C692C2BBC3A8C2A8CB9CC3A4C2BAE280B9C3A7C2B4C290C3A4C2BBCB9CC3A3C281E28098" + + private func hex(_ text: String) -> String { + text.utf8.map { String(format: "%02X", $0) }.joined() + } + + private func text(fromHex hex: String) -> String { + var bytes: [UInt8] = [] + var index = hex.startIndex + while index < hex.endIndex { + let next = hex.index(index, offsetBy: 2) + bytes.append(UInt8(hex[index.. URL { + let directory = FileManager.default.temporaryDirectory + .appendingPathComponent(UUID().uuidString, isDirectory: true) + try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) + return directory + } + + @Test("A MySQL dump declares utf8mb4 the way mysqldump does, and puts the session back") + func mysqlDeclaresUTF8MB4() { + let declaration = SQLExportEncodingDeclaration.forDialect(.mysql) + #expect(declaration.prologue.contains("/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;")) + #expect(declaration.prologue.contains("/*!40101 SET NAMES utf8 */;")) + #expect(declaration.prologue.contains("/*!50503 SET NAMES utf8mb4 */;")) + #expect(declaration.epilogue.contains("/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;")) + #expect(declaration.epilogue.contains("/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;")) + #expect(declaration.epilogue.contains("/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;")) + } + + @Test("Other dialects write no declaration") + func otherDialectsDeclareNothing() { + for dialect: SqlDialect in [.sqlite, .generic, .postgres] { + #expect(SQLExportEncodingDeclaration.forDialect(dialect) == .empty) + } + } + + @Test("An unsplit dump opens with the declaration and closes by restoring the session") + func unsplitDumpIsWrapped() throws { + let directory = try temporaryDirectory() + defer { try? FileManager.default.removeItem(at: directory) } + let declaration = SQLExportEncodingDeclaration.forDialect(.mysql) + + let destination = directory.appendingPathComponent("dump.sql") + let writer = try SQLExportFileWriter( + destination: destination, splitSizeMegabytes: 0, encodingDeclaration: declaration + ) + try writer.write("INSERT INTO `t` VALUES ('メール');\n") + try writer.commit() + + let dump = try String(contentsOf: destination, encoding: .utf8) + #expect(dump == declaration.prologue + "INSERT INTO `t` VALUES ('メール');\n" + declaration.epilogue) + } + + @Test("Every part of a split dump carries its own declaration, so each restores on its own") + func everyPartIsWrapped() throws { + let directory = try temporaryDirectory() + defer { try? FileManager.default.removeItem(at: directory) } + let declaration = SQLExportEncodingDeclaration.forDialect(.mysql) + + let destination = directory.appendingPathComponent("dump.sql") + let writer = try SQLExportFileWriter( + destination: destination, splitSizeMegabytes: 1, encodingDeclaration: declaration + ) + let chunk = String(repeating: "x", count: 700 * 1_024) + try writer.write("A\(chunk);\n") + try writer.write("B\(chunk);\n") + let parts = try writer.commit() + + #expect(parts.count == 2) + for (index, part) in parts.enumerated() { + let text = try String(contentsOf: part, encoding: .utf8) + #expect(text.hasPrefix(declaration.prologue), "part \(index + 1)") + #expect(text.hasSuffix(declaration.epilogue), "part \(index + 1)") + #expect(text.contains(index == 0 ? "A" : "B")) + } + } + + @Test("No part grows past the cap once its closing declaration is added") + func epilogueCountsTowardTheCap() throws { + let directory = try temporaryDirectory() + defer { try? FileManager.default.removeItem(at: directory) } + let declaration = SQLExportEncodingDeclaration.forDialect(.mysql) + let cap = 1_024 * 1_024 + + let destination = directory.appendingPathComponent("dump.sql") + let writer = try SQLExportFileWriter( + destination: destination, splitSizeMegabytes: 1, encodingDeclaration: declaration + ) + let firstLength = cap - declaration.prologue.utf8.count - declaration.epilogue.utf8.count - 5 + try writer.write(String(repeating: "a", count: firstLength - 2) + ";\n") + try writer.write("SELECT 1;\n") + let parts = try writer.commit() + + #expect(parts.count == 2) + for part in parts { + let size = try FileManager.default.attributesOfItem(atPath: part.path)[.size] as? Int ?? 0 + #expect(size <= cap, "\(part.lastPathComponent) is \(size) bytes") + } + } + + @Test("A statement larger than the cap still lands in a part of its own, not after an empty one") + func oversizedStatementDoesNotLeaveAnEmptyPart() throws { + let directory = try temporaryDirectory() + defer { try? FileManager.default.removeItem(at: directory) } + + let destination = directory.appendingPathComponent("dump.sql") + let writer = try SQLExportFileWriter( + destination: destination, splitSizeMegabytes: 1, + encodingDeclaration: .forDialect(.mysql) + ) + try writer.write(String(repeating: "y", count: 2 * 1_024 * 1_024) + ";\n") + let parts = try writer.commit() + + #expect(parts.count == 1) + #expect(!writer.didSplit) + } +} diff --git a/docs/databases/mysql.mdx b/docs/databases/mysql.mdx index 40e694b46d..a930f51cef 100644 --- a/docs/databases/mysql.mdx +++ b/docs/databases/mysql.mdx @@ -26,7 +26,7 @@ MySQL 8 accounts on `caching_sha2_password` connect on the first try, with no au | **Password** | empty | Stored in the macOS Keychain | | **Database** | empty | Optional. Leave it empty to browse every database | -The session character set is `utf8mb4`, so emoji and non-Latin text round-trip untouched. A connect attempt gives up after 10 seconds. +Every connection sets its session character set to `utf8mb4` once it logs in, over any `init_connect` the server runs, so emoji and non-Latin text round-trip untouched. A connect attempt gives up after 10 seconds. ## Connection URL @@ -76,6 +76,40 @@ Reconnecting costs a TCP connect, the TLS handshake and authentication: measured A release is refused, with the reason, while the session holds anything a reconnect would destroy: an open transaction, a temporary table, a prepared statement, a `GET_LOCK`, `LOCK TABLES`, a user variable, a changed session setting, or a stored routine call, whose body is opaque. +## Garbled non-Latin text + +A comment or value that reads `メール` where `メール` belongs was written by a client that sent UTF-8 while telling the server it was sending Latin 1. A `mysql` command-line client without a UTF-8 locale does that, and so does a MySQL 5.7 container loading its `docker-entrypoint-initdb.d` scripts, and so does any client on a server whose `init_connect` runs `SET NAMES latin1`. The server stored the garbled form, so every UTF-8 client shows the same thing. + +To work with such a database the way that client did, set **Encoding** to **UTF-8 via Latin 1** in **Options** and reconnect. Text written through Latin 1 then reads correctly, text stored correctly still reads correctly, and whatever you save is stored the way the old client stored it, so the application that wrote the data keeps reading it. + + +With **UTF-8 via Latin 1**, a correctly stored value you edit is saved in the garbled form, and a table or column whose non-Latin name was stored correctly cannot be opened. Use it on a database written through Latin 1, never on one where applications write UTF-8. + + +An SQL export taken with **UTF-8 via Latin 1** holds the text as it reads, in UTF-8. Restoring it gives a database with the text fixed, which the old client then reads as `?`. Restore it where you are moving off that client, not as a backup of the database it still writes to. + +To fix the stored text instead, convert it in place. The `WHERE` clause skips values that were stored correctly: + +```sql +UPDATE orders +SET note = CONVERT(CAST(CONVERT(note USING latin1) AS BINARY) USING utf8mb4) +WHERE note = CONVERT(CONVERT(note USING latin1) USING utf8mb4) + AND CONVERT(CAST(CONVERT(note USING latin1) AS BINARY) USING utf8mb4) IS NOT NULL; +``` + +Table comments take one `ALTER TABLE` each. This query writes them for the current database; run the statements it returns: + +```sql +SELECT CONCAT('ALTER TABLE `', TABLE_NAME, '` COMMENT = ', + QUOTE(CONVERT(CAST(CONVERT(TABLE_COMMENT USING latin1) AS BINARY) USING utf8mb4)), ';') +FROM information_schema.TABLES +WHERE TABLE_SCHEMA = DATABASE() AND TABLE_COMMENT <> '' + AND TABLE_COMMENT = CONVERT(CONVERT(TABLE_COMMENT USING latin1) USING utf8mb4) + AND CONVERT(CAST(CONVERT(TABLE_COMMENT USING latin1) AS BINARY) USING utf8mb4) IS NOT NULL; +``` + +A column comment is part of the column's definition. Copy it from the **Structure** tab while **UTF-8 via Latin 1** is on, then switch back to **UTF-8**, reconnect, and paste it into the same column. + ## SSL/TLS New connections default to **Preferred**: TLS first, dropping to plain text only after an SSL handshake error. Pick **Verify CA** with the provider's certificate for strict validation. See [SSL/TLS](/connections/ssl). diff --git a/docs/features/import-export.mdx b/docs/features/import-export.mdx index 0bfb69afd4..cc3664e5dc 100644 --- a/docs/features/import-export.mdx +++ b/docs/features/import-export.mdx @@ -133,6 +133,8 @@ As SQL, a results export writes `INSERT` statements only. A result set is the ou Splitting writes `dump.part1.sql`, `dump.part2.sql` and so on, rotating between statements so no part ends mid-`INSERT`. Restore the parts in order. A gzipped export is one file, so the two settings do not combine and the summary says so. + A MySQL or MariaDB dump is UTF-8 and says so: every part opens with `SET NAMES utf8mb4` and ends by putting the session's character set back, as `mysqldump` does. `mysql < dump.sql` then restores Japanese, emoji and other non-Latin text intact, even from a client whose default is Latin 1. + One snapshot opens `START TRANSACTION WITH CONSISTENT SNAPSHOT` on MySQL, `BEGIN ISOLATION LEVEL REPEATABLE READ` on PostgreSQL, and a deferred transaction on SQLite. It holds that transaction open for the whole export. Excluding the counter drops `AUTO_INCREMENT=` from the table options and leaves the column's own `AUTO_INCREMENT` attribute alone. Restoring rows sets the counter one past the highest key in the data, so a source counter that had run ahead of its rows, after deletes or a reset, does not carry over. diff --git a/project.yml b/project.yml index 7906d573d2..e08d09fabc 100644 --- a/project.yml +++ b/project.yml @@ -476,6 +476,13 @@ targets: - Plugins/MongoDBDriverPlugin/MongoScriptText.swift - Plugins/MongoDBDriverPlugin/MongoStreamProjection.swift - Plugins/OracleDriverPlugin/OracleObjectQueries.swift + - Plugins/MySQLDriverPlugin/GeometryWKBParser.swift + - Plugins/MySQLDriverPlugin/MariaDBFieldClassifier.swift + - Plugins/MySQLDriverPlugin/MariaDBFieldMetadata.swift + - Plugins/MySQLDriverPlugin/MySQLCharacterSet.swift + - Plugins/MySQLDriverPlugin/MySQLColumnDecoding.swift + - Plugins/MySQLDriverPlugin/MySQLConnectionEncoding.swift + - Plugins/MySQLDriverPlugin/MySQLLatin1.swift - Plugins/MySQLDriverPlugin/MySQLColumnDefinitionSQL.swift - Plugins/MySQLDriverPlugin/MySQLCreateTableSQL.swift - Plugins/MySQLDriverPlugin/MySQLIdleRelease.swift @@ -564,6 +571,7 @@ targets: - Plugins/RedisDriverPlugin/RedisStatementGenerator.swift - Plugins/RedisDriverPlugin/RedisTopologyDiagnostics.swift - Plugins/SQLExportPlugin/SQLExportDDLRewriter.swift + - Plugins/SQLExportPlugin/SQLExportEncodingDeclaration.swift - Plugins/SQLExportPlugin/SQLExportFileWriter.swift - Plugins/SQLExportPlugin/SQLExportInsertMode.swift - Plugins/SQLExportPlugin/SQLExportModels.swift diff --git a/scripts/check-mysql-charset-decoding.sh b/scripts/check-mysql-charset-decoding.sh new file mode 100755 index 0000000000..3ee16221ad --- /dev/null +++ b/scripts/check-mysql-charset-decoding.sh @@ -0,0 +1,151 @@ +#!/usr/bin/env bash +# +# Compare the MySQL driver's character-set decoders against a real server. +# +# MySQLCharacterSet maps a server charset name to a Foundation encoding by hand, and MySQLLatin1 +# carries MySQL's own latin1 table, which is cp1252 with five bytes passed through as C1 +# controls. Both are transcriptions of what the server does, and Foundation's idea of a charset +# disagrees with MySQL's for several names that look identical (latin1, greek, hebrew, sjis). This +# asks the server how it converts every byte of every single-byte charset in the table, and a set +# of sample strings for the multibyte ones, and fails if the Swift decoders disagree. +# +# Usage: +# scripts/check-mysql-charset-decoding.sh [host] [port] [user] +# +# Needs the mysql client, xcrun swiftc, and a MySQL 8 or MariaDB 10.5+ server. The password, if +# any, comes from MYSQL_PWD. A byte the server leaves undefined may decode to a replacement +# character or pass through as its own code point, as MySQL's latin1 does. Exits non-zero on a +# disagreement. + +set -uo pipefail + +HOST="${1:-127.0.0.1}" +PORT="${2:-3306}" +USER_NAME="${3:-root}" +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +PLUGIN="$ROOT/Plugins/MySQLDriverPlugin" + +command -v mysql > /dev/null || { + echo "mysql client not found" >&2 + exit 3 +} + +MYSQL=(mysql --no-defaults -h "$HOST" -P "$PORT" -u "$USER_NAME" -N -B -r --default-character-set=utf8mb4) +if ! "${MYSQL[@]}" -e "SELECT 1" > /dev/null 2>&1; then + echo "no MySQL at $HOST:$PORT for $USER_NAME" >&2 + exit 3 +fi + +WORK="$(mktemp -d)" +trap 'rm -rf "$WORK"' EXIT + +cat > "$WORK/main.swift" <<'SWIFT' +import Foundation + +func bytes(fromHex hex: Substring) -> [UInt8]? { + guard hex.count % 2 == 0 else { return nil } + var result: [UInt8] = [] + var index = hex.startIndex + while index < hex.endIndex { + let next = hex.index(index, offsetBy: 2) + guard let byte = UInt8(hex[index.. String { + input.withUnsafeBytes { MySQLCharacterSet(serverName: name).decode($0) } +} + +let arguments = CommandLine.arguments +if arguments.count == 2, arguments[1] == "names" { + for name in ["latin1"] + MySQLCharacterSet.singleByteDecodedNames { + print("\(name) single") + } + for name in MySQLCharacterSet.multiByteDecodedNames { + print("\(name) multi") + } + exit(0) +} + +var failures = 0 +for line in (try String(contentsOfFile: arguments[1], encoding: .utf8)).split(separator: "\n") { + let fields = line.split(separator: "\t", omittingEmptySubsequences: false) + guard fields.count >= 3 else { continue } + let name = String(fields[0]) + switch fields[1] { + case "byte": + guard let byte = UInt8(fields[2], radix: 16), fields.count == 4, + fields[3] != "NULL", let server = bytes(fromHex: fields[3]) else { continue } + let undefined = server == [0x3F] && byte != 0x3F + let local = decode([byte], name) + let passThrough = String(Unicode.Scalar(byte)) + let acceptable = undefined ? ["\u{FFFD}", "?", passThrough] : [String(decoding: server, as: UTF8.self)] + if !acceptable.contains(local) { + print("\(name) byte \(fields[2]): server \(fields[3]) local \(local.unicodeScalars.map { String($0.value, radix: 16) })") + failures += 1 + } + case "sample": + guard fields.count == 5, let encoded = bytes(fromHex: fields[3]), let back = bytes(fromHex: fields[4]) else { + continue + } + let sample = String(fields[2]) + guard String(decoding: back, as: UTF8.self) == sample else { continue } + let local = decode(encoded, name) + if local != sample { + print("\(name) sample \(sample): local \(local)") + failures += 1 + } + default: + continue + } +} +print(failures == 0 ? "OK" : "\(failures) disagreements") +exit(failures == 0 ? 0 : 1) +SWIFT + +xcrun swiftc -O -o "$WORK/check" "$WORK/main.swift" \ + "$PLUGIN/MySQLCharacterSet.swift" "$PLUGIN/MySQLLatin1.swift" > "$WORK/build.log" 2>&1 || { + cat "$WORK/build.log" >&2 + exit 3 +} + +SAMPLES=("メール・記事紐付け" "~" "〜" "①" "髙" "¥" "\\" "‖" "¬" "㈱" '“' "€" "中文简体" "繁體中文" + "한국어" "Привет" "ґєії" "ąčęėįšųūž" "ğışİ" "łóźżćńśŁ" "àéüß" "😀" "アイウ" "∑" "×" $'\xe2\x80\x94' "£") + +NAMES="$("$WORK/check" names)" && [ -n "$NAMES" ] || { + echo "the decoder listed no character sets" >&2 + exit 3 +} + +: > "$WORK/server.tsv" +: > "$WORK/mysql.err" +while read -r NAME KIND; do + KNOWN="$("${MYSQL[@]}" -e "SELECT COUNT(*) FROM information_schema.CHARACTER_SETS WHERE CHARACTER_SET_NAME = '$NAME'" 2>> "$WORK/mysql.err")" + if [ "$KNOWN" != "1" ]; then + echo "skipped $NAME: this server has no such character set" + continue + fi + if [ "$KIND" = "single" ]; then + COLUMNS="" + for BYTE in $(seq 0 255); do + HEX="$(printf '%02X' "$BYTE")" + COLUMNS="$COLUMNS${COLUMNS:+,}CONCAT('$NAME\tbyte\t$HEX\t', IFNULL(HEX(CONVERT(CONVERT(UNHEX('$HEX') USING $NAME) USING utf8mb4)), 'NULL'))" + done + "${MYSQL[@]}" -e "SELECT $COLUMNS" 2>> "$WORK/mysql.err" | tr '\t' '\n' | paste - - - - >> "$WORK/server.tsv" + fi + for SAMPLE in "${SAMPLES[@]}"; do + LITERAL="${SAMPLE//\\/\\\\}" + "${MYSQL[@]}" -e "SELECT '$NAME', 'sample', _utf8mb4'$LITERAL', HEX(CONVERT(_utf8mb4'$LITERAL' USING $NAME)), HEX(CONVERT(CONVERT(_utf8mb4'$LITERAL' USING $NAME) USING utf8mb4))" \ + >> "$WORK/server.tsv" 2>> "$WORK/mysql.err" + done +done <<< "$NAMES" + +if grep -v -e '^WARNING' -e '^$' "$WORK/mysql.err" > /dev/null; then + grep -v -e '^WARNING' "$WORK/mysql.err" >&2 + exit 3 +fi + +"$WORK/check" "$WORK/server.tsv" From e16391618bcdfb747cec448a2cd99424ada78ad3 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 11 Sep 2026 15:15:30 +0000 Subject: [PATCH 04/54] feat(plugin-mysql): add OceanBase MySQL-mode connection type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nguyễn Nam Long --- CHANGELOG.md | 1 + .../TableProCoreTypes/DatabaseType.swift | 6 +- .../DatabaseTypeTests.swift | 5 +- Plugins/MySQLDriverPlugin/Info.plist | 1 + Plugins/MySQLDriverPlugin/MySQLPlugin.swift | 6 +- .../MySQLPluginDriver+Flavor.swift | 26 +++- .../MySQLPluginDriver+OceanBase.swift | 86 +++++++++++ .../MySQLDriverPlugin/MySQLPluginDriver.swift | 22 ++- .../MySQLDriverPlugin/MySQLServerFlavor.swift | 44 +++++- .../MySQLServerVersion.swift | 6 + .../OceanBaseHiddenPrimaryKey.swift | 33 ++++ Plugins/MySQLDriverPlugin/OceanBaseSQL.swift | 141 ++++++++++++++++++ Plugins/TableProPluginKit/SqlDialect.swift | 2 +- .../oceanbase-icon.imageset/Contents.json | 16 ++ .../oceanbase-icon.imageset/oceanbase.svg | 1 + TablePro/Core/CrossEngine/SQLTypeFamily.swift | 1 + TablePro/Core/Plugins/ImportTypeMapper.swift | 2 +- ...uginMetadataRegistry+CuratedDefaults.swift | 2 +- ...etadataRegistry+MySQLVariantDefaults.swift | 68 +++++++++ ...ginMetadataRegistry+SnapshotAdoption.swift | 2 +- .../Core/Plugins/PluginMetadataRegistry.swift | 4 +- .../DockerComposeExtractor.swift | 7 + TablePro/Info.plist | 1 + TablePro/Models/Connection/DatabaseType.swift | 1 + .../Schema/ColumnDefaultVocabulary.swift | 2 +- .../Models/Schema/ForeignKeyDialect.swift | 2 +- .../oceanbase-icon.imageset/Contents.json | 16 ++ .../oceanbase-icon.imageset/oceanbase.svg | 1 + .../Coordinators/ConnectionCoordinator.swift | 2 +- .../Helpers/DatabaseType+Mobile.swift | 3 + .../Intents/IntentDatabaseSession.swift | 2 +- .../Platform/IOSDriverFactory.swift | 4 +- .../Views/Components/DatabaseIconView.swift | 1 + .../SQLBuilderDefaultValuesTests.swift | 3 + .../MySQLVariantSupportTests.swift | 13 ++ .../SQLDialectParityTests.swift | 1 + .../oceanbase-icon.imageset/Contents.json | 16 ++ .../oceanbase-icon.imageset/oceanbase.svg | 1 + .../Helpers/DatabaseTypeStyle.swift | 2 + .../CloudSQL/CloudSQLProxyModelTests.swift | 1 + ...ementGeneratorOceanBaseHiddenPKTests.swift | 61 ++++++++ .../Core/Compare/CompareSQLLiteralTests.swift | 2 +- .../SchemaSyncScriptBuilderTests.swift | 2 + .../Plugins/MySQLVariantSupportTests.swift | 42 +++++- .../PluginManagerVariantAccessorTests.swift | 1 + ...PluginMetadataRegistryTypeCountTests.swift | 11 +- .../PluginMetadataRegistryVariantTests.swift | 3 +- .../Plugins/SocketPathPlaceholderTests.swift | 1 + .../ProjectYamlExtractorTests.swift | 16 ++ .../ConnectionURLParserOceanBaseTests.swift | 44 ++++++ .../Utilities/DatabaseURLSchemeTests.swift | 21 +++ .../Models/DatabaseTypeOceanBaseTests.swift | 50 +++++++ TableProTests/Models/DatabaseTypeTests.swift | 10 +- .../Plugins/MySQLServerFlavorTests.swift | 51 ++++++- .../OceanBaseHiddenPrimaryKeyTests.swift | 53 +++++++ TableProTests/Plugins/OceanBaseSQLTests.swift | 94 ++++++++++++ ...tructureColumnFieldRegistrationTests.swift | 4 +- docs/connections/connection-form.mdx | 1 + docs/connections/urls.mdx | 1 + docs/databases/index.mdx | 9 +- docs/databases/mysql.mdx | 2 +- docs/databases/oceanbase.mdx | 59 ++++++++ docs/docs.json | 1 + docs/index.mdx | 2 +- docs/snippets/driver-counts.mdx | 2 +- project.yml | 2 + 66 files changed, 1057 insertions(+), 42 deletions(-) create mode 100644 Plugins/MySQLDriverPlugin/MySQLPluginDriver+OceanBase.swift create mode 100644 Plugins/MySQLDriverPlugin/OceanBaseHiddenPrimaryKey.swift create mode 100644 Plugins/MySQLDriverPlugin/OceanBaseSQL.swift create mode 100644 TablePro/Assets.xcassets/oceanbase-icon.imageset/Contents.json create mode 100644 TablePro/Assets.xcassets/oceanbase-icon.imageset/oceanbase.svg create mode 100644 TableProMobile/TableProMobile/Assets.xcassets/oceanbase-icon.imageset/Contents.json create mode 100644 TableProMobile/TableProMobile/Assets.xcassets/oceanbase-icon.imageset/oceanbase.svg create mode 100644 TableProMobile/TableProWidget/Assets.xcassets/oceanbase-icon.imageset/Contents.json create mode 100644 TableProMobile/TableProWidget/Assets.xcassets/oceanbase-icon.imageset/oceanbase.svg create mode 100644 TableProTests/Core/ChangeTracking/SQLStatementGeneratorOceanBaseHiddenPKTests.swift create mode 100644 TableProTests/Core/Utilities/ConnectionURLParserOceanBaseTests.swift create mode 100644 TableProTests/Models/DatabaseTypeOceanBaseTests.swift create mode 100644 TableProTests/Plugins/OceanBaseHiddenPrimaryKeyTests.swift create mode 100644 TableProTests/Plugins/OceanBaseSQLTests.swift create mode 100644 docs/databases/oceanbase.mdx diff --git a/CHANGELOG.md b/CHANGELOG.md index 2447a90ef5..f561ecf84a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- OceanBase MySQL-mode connection type, including grid saves on servers opened as MySQL. (#1748) - Google Cloud Spanner as a registry plugin over the REST API. (#1226, #2480) - TiDB and Databend connection types on the MySQL driver. (#1066, #2514) - Empty state in the inspector and the assistant for a connection that is not up. diff --git a/Packages/TableProCore/Sources/TableProCoreTypes/DatabaseType.swift b/Packages/TableProCore/Sources/TableProCoreTypes/DatabaseType.swift index 211eda5ad6..de3feef5c5 100644 --- a/Packages/TableProCore/Sources/TableProCoreTypes/DatabaseType.swift +++ b/Packages/TableProCore/Sources/TableProCoreTypes/DatabaseType.swift @@ -13,6 +13,7 @@ public struct DatabaseType: Hashable, Codable, Sendable, RawRepresentable { public static let mariadb = DatabaseType(rawValue: "MariaDB") public static let tidb = DatabaseType(rawValue: "TiDB") public static let databend = DatabaseType(rawValue: "Databend") + public static let oceanbase = DatabaseType(rawValue: "OceanBase") public static let postgresql = DatabaseType(rawValue: "PostgreSQL") public static let sqlite = DatabaseType(rawValue: "SQLite") public static let redis = DatabaseType(rawValue: "Redis") @@ -42,7 +43,7 @@ public struct DatabaseType: Hashable, Codable, Sendable, RawRepresentable { public static let cloudflareR2SQL = DatabaseType(rawValue: "Cloudflare R2 SQL") public static let allKnownTypes: [DatabaseType] = [ - .mysql, .mariadb, .tidb, .databend, .postgresql, .sqlite, .redis, .mongodb, + .mysql, .mariadb, .tidb, .databend, .oceanbase, .postgresql, .sqlite, .redis, .mongodb, .clickhouse, .mssql, .oracle, .dameng, .duckdb, .cassandra, .redshift, .etcd, .cloudflareD1, .dynamodb, .bigquery, .spanner, .snowflake, .libsql, .beancount, .surrealdb, .teradata, .trino, .kafka, .cloudflareR2SQL @@ -55,6 +56,7 @@ public struct DatabaseType: Hashable, Codable, Sendable, RawRepresentable { case .mariadb: return "mariadb-icon" case .tidb: return "tidb-icon" case .databend: return "databend-icon" + case .oceanbase: return "oceanbase-icon" case .postgresql: return "postgresql-icon" case .redshift: return "redshift-icon" case .sqlite: return "sqlite-icon" @@ -85,7 +87,7 @@ public struct DatabaseType: Hashable, Codable, Sendable, RawRepresentable { public var pluginTypeId: String { switch self { - case .mariadb, .tidb, .databend: return DatabaseType.mysql.rawValue + case .mariadb, .tidb, .databend, .oceanbase: return DatabaseType.mysql.rawValue case .redshift: return DatabaseType.postgresql.rawValue default: return rawValue } diff --git a/Packages/TableProCore/Tests/TableProModelsTests/DatabaseTypeTests.swift b/Packages/TableProCore/Tests/TableProModelsTests/DatabaseTypeTests.swift index f0d7b2e80f..dc7522fc13 100644 --- a/Packages/TableProCore/Tests/TableProModelsTests/DatabaseTypeTests.swift +++ b/Packages/TableProCore/Tests/TableProModelsTests/DatabaseTypeTests.swift @@ -10,6 +10,7 @@ struct DatabaseTypeTests { #expect(DatabaseType.mariadb.rawValue == "MariaDB") #expect(DatabaseType.tidb.rawValue == "TiDB") #expect(DatabaseType.databend.rawValue == "Databend") + #expect(DatabaseType.oceanbase.rawValue == "OceanBase") #expect(DatabaseType.postgresql.rawValue == "PostgreSQL") #expect(DatabaseType.sqlite.rawValue == "SQLite") #expect(DatabaseType.redis.rawValue == "Redis") @@ -29,6 +30,7 @@ struct DatabaseTypeTests { #expect(DatabaseType.mariadb.pluginTypeId == "MySQL") #expect(DatabaseType.tidb.pluginTypeId == "MySQL") #expect(DatabaseType.databend.pluginTypeId == "MySQL") + #expect(DatabaseType.oceanbase.pluginTypeId == "MySQL") #expect(DatabaseType.postgresql.pluginTypeId == "PostgreSQL") #expect(DatabaseType.redshift.pluginTypeId == "PostgreSQL") #expect(DatabaseType.sqlite.pluginTypeId == "SQLite") @@ -59,10 +61,11 @@ struct DatabaseTypeTests { @Test("allKnownTypes contains all expected types") func allKnownTypesComplete() { - #expect(DatabaseType.allKnownTypes.count == 28) + #expect(DatabaseType.allKnownTypes.count == 29) #expect(DatabaseType.allKnownTypes.contains(.mysql)) #expect(DatabaseType.allKnownTypes.contains(.tidb)) #expect(DatabaseType.allKnownTypes.contains(.databend)) + #expect(DatabaseType.allKnownTypes.contains(.oceanbase)) #expect(DatabaseType.allKnownTypes.contains(.bigquery)) #expect(DatabaseType.allKnownTypes.contains(.spanner)) #expect(DatabaseType.allKnownTypes.contains(.snowflake)) diff --git a/Plugins/MySQLDriverPlugin/Info.plist b/Plugins/MySQLDriverPlugin/Info.plist index 7f89d51299..7e6f0a44f2 100644 --- a/Plugins/MySQLDriverPlugin/Info.plist +++ b/Plugins/MySQLDriverPlugin/Info.plist @@ -10,6 +10,7 @@ MariaDB TiDB Databend + OceanBase diff --git a/Plugins/MySQLDriverPlugin/MySQLPlugin.swift b/Plugins/MySQLDriverPlugin/MySQLPlugin.swift index bdba8d1fca..aab80c5f16 100644 --- a/Plugins/MySQLDriverPlugin/MySQLPlugin.swift +++ b/Plugins/MySQLDriverPlugin/MySQLPlugin.swift @@ -15,7 +15,7 @@ import TableProPluginKit final class MySQLPlugin: NSObject, TableProPlugin, DriverPlugin { static let pluginName = "MySQL Driver" static let pluginVersion = "1.0.0" - static let pluginDescription = "MySQL, MariaDB, TiDB, and Databend support via libmariadb" + static let pluginDescription = "MySQL, MariaDB, TiDB, Databend, and OceanBase support via libmariadb" static let capabilities: [PluginCapability] = [.databaseDriver] static let databaseTypeId = "MySQL" @@ -33,7 +33,7 @@ final class MySQLPlugin: NSObject, TableProPlugin, DriverPlugin { ), MySQLConnectionEncoding.connectionField ] - static let additionalDatabaseTypeIds: [String] = ["MariaDB", "TiDB", "Databend"] + static let additionalDatabaseTypeIds: [String] = ["MariaDB", "TiDB", "Databend", "OceanBase"] // MARK: - UI/Capability Metadata @@ -123,7 +123,7 @@ final class MySQLPlugin: NSObject, TableProPlugin, DriverPlugin { static func driverVariant(for databaseTypeId: String) -> String? { switch databaseTypeId { - case MySQLServerFlavor.tidbVariant, MySQLServerFlavor.databendVariant: + case MySQLServerFlavor.tidbVariant, MySQLServerFlavor.databendVariant, MySQLServerFlavor.oceanbaseVariant: return databaseTypeId default: return nil diff --git a/Plugins/MySQLDriverPlugin/MySQLPluginDriver+Flavor.swift b/Plugins/MySQLDriverPlugin/MySQLPluginDriver+Flavor.swift index 02d63b71cd..1d177e64ee 100644 --- a/Plugins/MySQLDriverPlugin/MySQLPluginDriver+Flavor.swift +++ b/Plugins/MySQLDriverPlugin/MySQLPluginDriver+Flavor.swift @@ -28,7 +28,14 @@ extension MySQLFlavorMismatchError: PluginDriverError { extension MySQLPluginDriver { static func initialFlavor(for config: DriverConnectionConfig) -> MySQLServerFlavor { - config.additionalFields["driverVariant"] == MySQLServerFlavor.databendVariant ? .databend : .mysql + switch config.additionalFields["driverVariant"] { + case MySQLServerFlavor.databendVariant: + return .databend + case MySQLServerFlavor.oceanbaseVariant: + return .oceanbase(version: nil) + default: + return .mysql + } } func resolveFlavor(on connection: MariaDBPluginConnection, variant: String?) async throws -> MySQLServerFlavor { @@ -48,6 +55,21 @@ extension MySQLPluginDriver { throw MySQLFlavorMismatchError(kind: .databendNeedsItsOwnType) } + if variant == MySQLServerFlavor.oceanbaseVariant { + if MySQLFlavorResolution.needsOceanBaseProbe(banner: banner, variant: variant) { + if let comment = await firstValue(of: MySQLFlavorResolution.oceanbaseProbe, on: connection), + let version = MySQLServerFlavor.oceanbaseVersion(fromBanner: comment) { + return .oceanbase(version: version) + } + return .oceanbase(version: nil) + } + return bannerFlavor.isOceanBase ? bannerFlavor : .oceanbase(version: nil) + } + + if bannerFlavor.isOceanBase { + return bannerFlavor + } + guard MySQLFlavorResolution.needsTiDBVersionProbe(banner: banner, variant: variant) else { return bannerFlavor } @@ -59,7 +81,7 @@ extension MySQLPluginDriver { } func killTarget(for flavor: MySQLServerFlavor, on connection: MariaDBPluginConnection) async -> MySQLKillTarget { - guard flavor.isTiDB || flavor.isDatabend else { return .threadId } + guard flavor.isTiDB || flavor.isDatabend || flavor.isOceanBase else { return .threadId } let identifier = await firstValue(of: MySQLFlavorResolution.connectionIdentifierProbe, on: connection) return flavor.killTarget(connectionIdentifier: identifier) } diff --git a/Plugins/MySQLDriverPlugin/MySQLPluginDriver+OceanBase.swift b/Plugins/MySQLDriverPlugin/MySQLPluginDriver+OceanBase.swift new file mode 100644 index 0000000000..c7db8b9e55 --- /dev/null +++ b/Plugins/MySQLDriverPlugin/MySQLPluginDriver+OceanBase.swift @@ -0,0 +1,86 @@ +import Foundation +import TableProPluginKit + +extension MySQLPluginDriver { + func rewriteOceanBaseQueryIfNeeded(_ query: String) async -> String { + guard flavor.isOceanBase else { return query } + if let table = OceanBaseSQL.simpleSelectStarTable(from: query) { + let hidden = await oceanbaseHiddenPrimaryKeyColumns(for: table) + return OceanBaseSQL.projectingHiddenPrimaryKeys( + sql: query, + hiddenColumns: hidden, + quote: quoteIdentifier + ) + } + return OceanBaseSQL.withHiddenColumnVisibilityHint(query) + } + + func attachingOceanBaseHiddenPrimaryKeys( + to columns: [PluginColumnInfo], + table: String + ) async throws -> [PluginColumnInfo] { + let indexes = try await fetchIndexes(table: table, schema: nil) + let primaryColumns = indexes.first(where: \.isPrimary)?.columns ?? [] + var attached = OceanBaseHiddenPrimaryKey.attaching( + to: columns, + primaryIndexColumns: primaryColumns + ) + let visibleNames = Set(columns.map(\.name)) + if attached.count == columns.count, !columns.contains(where: \.isPrimaryKey) { + for name in OceanBaseSQL.documentedHiddenNames where !visibleNames.contains(name) { + if await oceanbaseColumnExists(name, table: table) { + attached.append(OceanBaseHiddenPrimaryKey.synthesizedColumn(named: name)) + } + } + } + let hiddenNames = attached.compactMap { column in + visibleNames.contains(column.name) ? nil : column.name + } + rememberOceanBaseHiddenPrimaryKeys(hiddenNames, for: table) + return attached + } + + func attachingOceanBaseHiddenPrimaryKeys( + to allColumns: [String: [PluginColumnInfo]], + primaryColumnsByTable: [String: [String]] + ) -> [String: [PluginColumnInfo]] { + var merged = allColumns + for (table, columns) in allColumns { + let attached = OceanBaseHiddenPrimaryKey.attaching( + to: columns, + primaryIndexColumns: primaryColumnsByTable[table] ?? [] + ) + merged[table] = attached + let hiddenNames = attached.compactMap { column in + columns.contains(where: { $0.name == column.name }) ? nil : column.name + } + rememberOceanBaseHiddenPrimaryKeys(hiddenNames, for: table) + } + return merged + } + + private func oceanbaseHiddenPrimaryKeyColumns(for table: String) async -> [String] { + if let cached = cachedOceanBaseHiddenPrimaryKeys(for: table) { + return cached + } + do { + _ = try await fetchColumns(table: table, schema: nil) + } catch { + return [] + } + return cachedOceanBaseHiddenPrimaryKeys(for: table) ?? [] + } + + private func oceanbaseColumnExists(_ column: String, table: String) async -> Bool { + do { + _ = try await execute(query: OceanBaseSQL.documentedHiddenColumnProbe( + table: table, + column: column, + quote: quoteIdentifier + )) + return true + } catch { + return false + } + } +} diff --git a/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift b/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift index 2d15ac1406..ba47dc2e9b 100644 --- a/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift +++ b/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift @@ -60,6 +60,8 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { /// connection between `requireConnection` returning and the query reaching the server. private var activeOperations = 0 + private var oceanbaseHiddenPrimaryKeys: [String: [String]] = [:] + internal static let logger = Logger(subsystem: "com.TablePro", category: "MySQLPluginDriver") var currentSchema: String? { nil } @@ -216,6 +218,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { guard let parameters else { return try await executeWithReconnect(query: query, isRetry: false, rowCap: cap) } + let query = await rewriteOceanBaseQueryIfNeeded(query) let conn = try await requireConnection() defer { endOperation() } noteActivity(query) @@ -242,6 +245,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { } func executeParameterized(query: String, parameters: [PluginCellValue]) async throws -> PluginQueryResult { + let query = await rewriteOceanBaseQueryIfNeeded(query) let conn = try await requireConnection() defer { endOperation() } noteActivity(query) @@ -279,6 +283,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { countsAsActivity: Bool = true ) async throws -> PluginQueryResult { let startTime = Date() + let query = await rewriteOceanBaseQueryIfNeeded(query) let conn = try await requireConnection() defer { endOperation() } @@ -507,7 +512,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { let result = try await execute(query: "SHOW FULL COLUMNS FROM \(quoteIdentifier(table))") let generationExpressions = try await fetchGenerationExpressions(table: table) - return result.rows.compactMap { row in + let columns = result.rows.compactMap { row -> PluginColumnInfo? in guard let name = row[safe: 0]?.asText, let dataType = row[safe: 1]?.asText else { return nil } @@ -549,6 +554,8 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { generationKind: mysqlGenerationKind(extra: extra) ) } + guard flavor.isOceanBase else { return columns } + return try await attachingOceanBaseHiddenPrimaryKeys(to: columns, table: table) } private func fetchGenerationExpressions(table: String) async throws -> [String: String] { @@ -685,7 +692,10 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { allColumns[tableName, default: []].append(column) } - return allColumns + guard flavor.isOceanBase else { return allColumns } + let indexes = try await fetchAllIndexes(schema: schema) + let primaryByTable = indexes.mapValues { $0.first(where: \.isPrimary)?.columns ?? [] } + return attachingOceanBaseHiddenPrimaryKeys(to: allColumns, primaryColumnsByTable: primaryByTable) } func fetchIndexes(table: String, schema: String?) async throws -> [PluginIndexInfo] { @@ -1250,6 +1260,14 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { // MARK: - Private Helpers + func cachedOceanBaseHiddenPrimaryKeys(for table: String) -> [String]? { + sessionLock.withLock { oceanbaseHiddenPrimaryKeys[table] } + } + + func rememberOceanBaseHiddenPrimaryKeys(_ columns: [String], for table: String) { + sessionLock.withLock { oceanbaseHiddenPrimaryKeys[table] = columns } + } + private func extractTableName(from query: String) -> String? { guard let regex = Self.tableNameRegex, let match = regex.firstMatch(in: query, range: NSRange(query.startIndex..., in: query)), diff --git a/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift b/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift index de8c018da8..a67a5ce0a6 100644 --- a/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift +++ b/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift @@ -33,15 +33,20 @@ internal enum MySQLServerFlavor: Equatable, Sendable { case mariadb case tidb(version: MySQLEngineVersion?) case databend + case oceanbase(version: MySQLEngineVersion?) static let tidbVariant = "TiDB" static let databendVariant = "Databend" + static let oceanbaseVariant = "OceanBase" static func fromBanner(_ banner: String?) -> MySQLServerFlavor { guard let banner else { return .mysql } if let version = tidbVersion(fromBanner: banner) { return .tidb(version: version) } + if banner.range(of: "oceanbase", options: .caseInsensitive) != nil { + return .oceanbase(version: oceanbaseVersion(fromBanner: banner)) + } if isDatabendBanner(banner) { return .databend } @@ -63,6 +68,18 @@ internal enum MySQLServerFlavor: Equatable, Sendable { banner.range(of: #"^\d+\.\d+\.\d+-v\d+\.\d+\.\d+-"#, options: .regularExpression) != nil } + static func oceanbaseVersion(fromBanner banner: String) -> MySQLEngineVersion? { + guard banner.range(of: "oceanbase", options: .caseInsensitive) != nil else { return nil } + if let marker = banner.range(of: "OceanBase_CE-v", options: .caseInsensitive) + ?? banner.range(of: "OceanBase-v", options: .caseInsensitive) { + return MySQLEngineVersion(parsing: banner[marker.upperBound...]) + } + guard let name = banner.range(of: "OceanBase", options: .caseInsensitive) else { return nil } + var rest = banner[name.upperBound...] + rest = rest.drop(while: { $0.isLetter || $0 == "_" || $0 == "-" || $0.isWhitespace }) + return MySQLEngineVersion(parsing: rest) + } + var isMariaDB: Bool { self == .mariadb } var isTiDB: Bool { @@ -72,11 +89,21 @@ internal enum MySQLServerFlavor: Equatable, Sendable { var isDatabend: Bool { self == .databend } + var isOceanBase: Bool { + guard case .oceanbase = self else { return false } + return true + } + var tidbVersion: MySQLEngineVersion? { guard case .tidb(let version) = self else { return nil } return version } + var oceanbaseVersion: MySQLEngineVersion? { + guard case .oceanbase(let version) = self else { return nil } + return version + } + var systemDatabaseNames: [String] { switch self { case .mysql, .mariadb: @@ -85,6 +112,8 @@ internal enum MySQLServerFlavor: Equatable, Sendable { return ["INFORMATION_SCHEMA", "METRICS_SCHEMA", "PERFORMANCE_SCHEMA", "mysql", "sys"] case .databend: return ["information_schema", "system"] + case .oceanbase: + return ["information_schema", "mysql", "oceanbase"] } } @@ -92,7 +121,7 @@ internal enum MySQLServerFlavor: Equatable, Sendable { switch self { case .mysql, .mariadb: return ["OPTIMIZE TABLE", "ANALYZE TABLE", "CHECK TABLE", "REPAIR TABLE"] - case .tidb, .databend: + case .tidb, .databend, .oceanbase: return ["ANALYZE TABLE"] } } @@ -114,7 +143,7 @@ internal enum MySQLServerFlavor: Equatable, Sendable { return "SET SESSION max_statement_time = \(seconds)" case .databend: return "SET max_execute_time_in_seconds = \(seconds)" - case .mysql, .tidb: + case .mysql, .tidb, .oceanbase: return "SET SESSION max_execution_time = \(seconds * 1_000)" } } @@ -146,6 +175,9 @@ internal enum MySQLServerFlavor: Equatable, Sendable { case .databend: guard let session = connectionIdentifier, !session.isEmpty else { return .threadId } return .databendSession(session) + case .oceanbase: + guard let id = connectionIdentifier.flatMap(UInt64.init) else { return .threadId } + return .oceanbaseConnection(id) case .mysql, .mariadb: return .threadId } @@ -156,6 +188,7 @@ internal enum MySQLKillTarget: Equatable, Sendable { case threadId case tidbConnection(UInt64) case databendSession(String) + case oceanbaseConnection(UInt64) func statement(threadId: UInt) -> String? { switch self { @@ -165,6 +198,8 @@ internal enum MySQLKillTarget: Equatable, Sendable { return "KILL TIDB QUERY \(id)" case .databendSession(let session): return "KILL QUERY '\(mysqlEscapeStringLiteral(session))'" + case .oceanbaseConnection(let id): + return "KILL QUERY \(id)" } } } @@ -178,7 +213,12 @@ internal enum MySQLFlavorResolution { variant == MySQLServerFlavor.databendVariant && !MySQLServerFlavor.fromBanner(banner).isDatabend } + static func needsOceanBaseProbe(banner: String?, variant: String?) -> Bool { + variant == MySQLServerFlavor.oceanbaseVariant && !MySQLServerFlavor.fromBanner(banner).isOceanBase + } + static let tidbVersionProbe = "SELECT tidb_version()" static let databendProbe = "SELECT value FROM system.settings WHERE name = 'max_result_rows'" + static let oceanbaseProbe = "SELECT @@version_comment" static let connectionIdentifierProbe = "SELECT CONNECTION_ID()" } diff --git a/Plugins/MySQLDriverPlugin/MySQLServerVersion.swift b/Plugins/MySQLDriverPlugin/MySQLServerVersion.swift index 514dd1f9f0..e65763fc57 100644 --- a/Plugins/MySQLDriverPlugin/MySQLServerVersion.swift +++ b/Plugins/MySQLDriverPlugin/MySQLServerVersion.swift @@ -38,6 +38,9 @@ enum MySQLServerVersion { case .tidb(let version): guard let version else { return false } return version >= MySQLEngineVersion(major: 7, minor: 2, patch: 0) + case .oceanbase(let version): + guard let version else { return false } + return version >= MySQLEngineVersion(major: 4, minor: 0, patch: 0) case .databend: return false } @@ -53,6 +56,9 @@ enum MySQLServerVersion { return isAtLeast((10, 2, 0), banner: banner) case .tidb: return true + case .oceanbase(let version): + guard let version else { return false } + return version >= MySQLEngineVersion(major: 4, minor: 0, patch: 0) case .databend: return false } diff --git a/Plugins/MySQLDriverPlugin/OceanBaseHiddenPrimaryKey.swift b/Plugins/MySQLDriverPlugin/OceanBaseHiddenPrimaryKey.swift new file mode 100644 index 0000000000..49b3d6ce72 --- /dev/null +++ b/Plugins/MySQLDriverPlugin/OceanBaseHiddenPrimaryKey.swift @@ -0,0 +1,33 @@ +import Foundation +import TableProPluginKit + +internal enum OceanBaseHiddenPrimaryKey { + static func synthesizedColumn(named name: String) -> PluginColumnInfo { + PluginColumnInfo( + name: name, + dataType: "BIGINT", + isNullable: false, + isPrimaryKey: true, + defaultValue: nil, + extra: "auto_increment", + identityKind: .always, + isGenerated: false, + allowedValues: nil, + generationExpression: nil, + generationKind: nil + ) + } + + static func attaching( + to columns: [PluginColumnInfo], + primaryIndexColumns: [String] + ) -> [PluginColumnInfo] { + let visible = Set(columns.map(\.name)) + let hidden = OceanBaseSQL.hiddenPrimaryKeyColumns( + primaryIndexColumns: primaryIndexColumns, + visibleColumnNames: visible + ) + guard !hidden.isEmpty else { return columns } + return columns + hidden.map(synthesizedColumn(named:)) + } +} diff --git a/Plugins/MySQLDriverPlugin/OceanBaseSQL.swift b/Plugins/MySQLDriverPlugin/OceanBaseSQL.swift new file mode 100644 index 0000000000..321dd6531b --- /dev/null +++ b/Plugins/MySQLDriverPlugin/OceanBaseSQL.swift @@ -0,0 +1,141 @@ +import Foundation + +internal enum OceanBaseSQL { + static let visibilityHint = "/*+ opt_param('hidden_column_visible','true') */" + static let incrementColumn = "__pk_increment" + static let clusterColumn = "__pk_cluster_column" + static let documentedHiddenNames = [incrementColumn, clusterColumn] + + private static let hintedVerbs: Set = [ + "SELECT", "UPDATE", "DELETE", "INSERT", "REPLACE" + ] + + static func isDocumentedHiddenName(_ name: String) -> Bool { + documentedHiddenNames.contains(name) + } + + static func hiddenPrimaryKeyColumns( + primaryIndexColumns: [String], + visibleColumnNames: Set + ) -> [String] { + var seen = Set() + var hidden: [String] = [] + for column in primaryIndexColumns where !visibleColumnNames.contains(column) { + guard seen.insert(column).inserted else { continue } + hidden.append(column) + } + return hidden + } + + static func withHiddenColumnVisibilityHint(_ sql: String) -> String { + let trimmed = sql.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { return sql } + if trimmed.contains("hidden_column_visible") { return sql } + guard let verbEnd = firstKeywordEnd(in: trimmed) else { return sql } + let verb = String(trimmed[trimmed.startIndex.. String + ) -> String { + let hinted = withHiddenColumnVisibilityHint(sql) + guard !hiddenColumns.isEmpty else { return hinted } + guard simpleSelectStarTable(from: hinted) != nil else { return hinted } + let extras = hiddenColumns.map(quote).joined(separator: ", ") + guard let regex = try? NSRegularExpression( + pattern: #"(?is)^(SELECT(?:\s+/\*\+[^*]*\*/)?)\s+\*\s+FROM\b"# + ) else { + return hinted + } + let nsSQL = hinted as NSString + guard let match = regex.firstMatch(in: hinted, range: NSRange(location: 0, length: nsSQL.length)), + match.numberOfRanges > 1 + else { + return hinted + } + let prefix = nsSQL.substring(with: match.range(at: 1)) + let afterFrom = nsSQL.substring(from: match.range.upperBound) + return "\(prefix) *, \(extras) FROM\(afterFrom)" + } + + static func simpleSelectStarTable(from sql: String) -> String? { + let trimmed = sql.trimmingCharacters(in: .whitespacesAndNewlines) + guard let regex = try? NSRegularExpression( + pattern: #"(?is)^SELECT(?:\s+/\*\+[^*]*\*/)?\s+\*\s+FROM\s+"# + ) else { + return nil + } + let nsSQL = trimmed as NSString + guard let match = regex.firstMatch(in: trimmed, range: NSRange(location: 0, length: nsSQL.length)) else { + return nil + } + var rest = nsSQL.substring(from: match.range.upperBound) + .trimmingCharacters(in: .whitespacesAndNewlines) + guard !rest.hasPrefix("(") else { return nil } + return trailingQualifiedIdentifier(from: &rest) + } + + static func documentedHiddenColumnProbe(table: String, column: String, quote: (String) -> String) -> String { + "SELECT \(visibilityHint) \(quote(column)) FROM \(quote(table)) LIMIT 0" + } + + private static func firstKeywordEnd(in sql: String) -> String.Index? { + var index = sql.startIndex + while index < sql.endIndex, sql[index].isWhitespace { + sql.formIndex(after: &index) + } + guard index < sql.endIndex, sql[index].isLetter else { return nil } + while index < sql.endIndex, sql[index].isLetter { + sql.formIndex(after: &index) + } + return index + } + + private static func trailingQualifiedIdentifier(from rest: inout String) -> String? { + var parts: [String] = [] + while let ident = parseLeadingIdentifier(from: &rest) { + parts.append(ident) + rest = rest.trimmingCharacters(in: .whitespacesAndNewlines) + guard rest.hasPrefix(".") else { break } + rest.removeFirst() + rest = rest.trimmingCharacters(in: .whitespacesAndNewlines) + } + return parts.last + } + + private static func parseLeadingIdentifier(from rest: inout String) -> String? { + rest = rest.trimmingCharacters(in: .whitespacesAndNewlines) + guard let first = rest.first else { return nil } + if first == "`" { + rest.removeFirst() + guard let end = rest.firstIndex(of: "`") else { return nil } + let value = String(rest[.. rest.startIndex else { return nil } + let value = String(rest[.. diff --git a/TablePro/Core/CrossEngine/SQLTypeFamily.swift b/TablePro/Core/CrossEngine/SQLTypeFamily.swift index cae295d6cd..d2c9ed8cdf 100644 --- a/TablePro/Core/CrossEngine/SQLTypeFamily.swift +++ b/TablePro/Core/CrossEngine/SQLTypeFamily.swift @@ -43,6 +43,7 @@ internal enum SQLTypeFamily: String, Hashable, Sendable, CaseIterable { "MySQL": .mysql, "MariaDB": .mysql, "TiDB": .mysql, + "OceanBase": .mysql, "PostgreSQL": .postgres, "Redshift": .postgres, "CockroachDB": .postgres, diff --git a/TablePro/Core/Plugins/ImportTypeMapper.swift b/TablePro/Core/Plugins/ImportTypeMapper.swift index 14e5f3455a..3de3cfaf02 100644 --- a/TablePro/Core/Plugins/ImportTypeMapper.swift +++ b/TablePro/Core/Plugins/ImportTypeMapper.swift @@ -11,7 +11,7 @@ enum ImportTypeMapper { switch databaseType { case .postgresql, .redshift, .cockroachdb: return postgresType(type) - case .mysql, .mariadb, .tidb: + case .mysql, .mariadb, .tidb, .oceanbase: return mysqlType(type) case .sqlite: return sqliteType(type) diff --git a/TablePro/Core/Plugins/PluginMetadataRegistry+CuratedDefaults.swift b/TablePro/Core/Plugins/PluginMetadataRegistry+CuratedDefaults.swift index 558d6ea777..db1eddaeda 100644 --- a/TablePro/Core/Plugins/PluginMetadataRegistry+CuratedDefaults.swift +++ b/TablePro/Core/Plugins/PluginMetadataRegistry+CuratedDefaults.swift @@ -11,7 +11,7 @@ import TableProPluginKit /// The primary type ids here are overwritten by `buildMetadataSnapshot` the moment the plugin /// registers, so these are the pre-load answer for those. For a variant id they are the whole /// answer: `registerVariant` keeps the curated entry and ignores the plugin's own statics, which -/// is the only reason MariaDB, TiDB, Databend, Redshift, CockroachDB and PGlite can differ from +/// is the only reason MariaDB, TiDB, Databend, OceanBase, Redshift, CockroachDB and PGlite can differ from /// the plugin that drives them. extension PluginMetadataRegistry { // swiftlint:disable:next function_body_length diff --git a/TablePro/Core/Plugins/PluginMetadataRegistry+MySQLVariantDefaults.swift b/TablePro/Core/Plugins/PluginMetadataRegistry+MySQLVariantDefaults.swift index ac98728d42..0f4d331b9d 100644 --- a/TablePro/Core/Plugins/PluginMetadataRegistry+MySQLVariantDefaults.swift +++ b/TablePro/Core/Plugins/PluginMetadataRegistry+MySQLVariantDefaults.swift @@ -34,6 +34,10 @@ extension PluginMetadataRegistry { mysqlColumnTypes.filter { $0.key != "Spatial" } } + static func oceanbaseColumnTypes(from mysqlColumnTypes: [String: [String]]) -> [String: [String]] { + mysqlColumnTypes.filter { $0.key != "Spatial" } + } + static func mysqlVariantDefaults( dialect: SQLDialectDescriptor, mysqlColumnTypes: [String: [String]], @@ -163,6 +167,70 @@ extension PluginMetadataRegistry { category: .analytical, tagline: String(localized: "Cloud data warehouse, built in Rust") ) + )), + ("OceanBase", PluginMetadataSnapshot( + displayName: "OceanBase", iconName: "oceanbase-icon", defaultPort: 2_881, + requiresAuthentication: true, supportsForeignKeys: true, supportsSchemaEditing: true, + isDownloadable: false, primaryUrlScheme: "oceanbase", parameterStyle: .questionMark, + navigationModel: .standard, explainVariants: [ + ExplainVariant(id: "explain", label: "EXPLAIN", sqlPrefix: "EXPLAIN", format: .plainText) + ], pathFieldRole: .database, + supportsHealthMonitor: true, urlSchemes: ["oceanbase"], postConnectActions: [.selectDatabaseFromLastSession], + brandColorHex: "#006AFF", + queryLanguageName: "SQL", editorLanguage: .sql, + connectionMode: .network, supportsDatabaseSwitching: true, + structureEditing: SchemaEditingSupport(columnReorder: .alter, foreignKeyEdit: .alter), + capabilities: PluginMetadataSnapshot.CapabilityFlags( + supportsSchemaSwitching: false, + supportsImport: true, + supportsExport: true, + supportsSSH: true, + supportsSSL: true, + supportsCascadeDrop: false, + supportsForeignKeyDisable: false, + supportsReadOnlyMode: true, + supportsQueryProgress: false, + requiresReconnectForDatabaseSwitch: false, + supportsDropDatabase: true, + supportsRenameTable: true, + supportsRenameView: true, + supportsRenameColumn: true, + supportsTriggers: true, + supportsTriggerEditing: false, + supportsCheckConstraints: true, + supportsCheckConstraintEditing: false, + supportsGeneratedColumns: true, + supportsRoutines: true, + supportsDatabaseTriggerBrowse: true, + defaultSSLMode: .preferred, + supportsPrincipalConnectionLimit: false + ), + schema: PluginMetadataSnapshot.SchemaInfo( + defaultSchemaName: "public", + defaultGroupName: "main", + tableEntityName: "Tables", + containerEntityName: "Database", + defaultPrimaryKeyColumn: nil, + immutableColumns: ["__pk_increment", "__pk_cluster_column"], + systemDatabaseNames: ["information_schema", "mysql", "oceanbase"], + systemSchemaNames: [], + fileExtensions: [], + databaseGroupingStrategy: .byDatabase, + structureColumnFields: [ + .name, .type, .nullable, .defaultValue, .generated, .generationExpression, + .onUpdate, .autoIncrement, .comment, .charset, .collation + ] + ), + editor: PluginMetadataSnapshot.EditorConfig( + sqlDialect: dialect, + statementCompletions: [], + columnTypesByCategory: oceanbaseColumnTypes(from: mysqlColumnTypes) + ), + connection: PluginMetadataSnapshot.ConnectionConfig( + additionalConnectionFields: [idleReleaseField], + category: .relational, + tagline: String(localized: "Distributed HTAP, MySQL-compatible") + ) )) ] } diff --git a/TablePro/Core/Plugins/PluginMetadataRegistry+SnapshotAdoption.swift b/TablePro/Core/Plugins/PluginMetadataRegistry+SnapshotAdoption.swift index c3045a6b2e..bc2a81bef6 100644 --- a/TablePro/Core/Plugins/PluginMetadataRegistry+SnapshotAdoption.swift +++ b/TablePro/Core/Plugins/PluginMetadataRegistry+SnapshotAdoption.swift @@ -21,7 +21,7 @@ extension PluginMetadataRegistry { /// /// Two facts qualify: case-insensitive matching, which is why Redshift is spelled /// `postgresqlDialect.withCaseSensitivityStyle(.caseFoldFunction)`, and the column type list, - /// which TiDB narrows (no spatial types) and Databend replaces with its own. Each has its own + /// which TiDB and OceanBase narrow (no spatial types) and Databend replaces with its own. Each has its own /// named adoption here rather than a value comparison: `SQLDialectDescriptor` is not /// `Equatable`, and a whole-descriptor diff would report "differs" for Redshift and hand it /// the stub back. diff --git a/TablePro/Core/Plugins/PluginMetadataRegistry.swift b/TablePro/Core/Plugins/PluginMetadataRegistry.swift index d6c246abaa..798bc35bde 100644 --- a/TablePro/Core/Plugins/PluginMetadataRegistry.swift +++ b/TablePro/Core/Plugins/PluginMetadataRegistry.swift @@ -383,6 +383,7 @@ final class PluginMetadataRegistry: @unchecked Sendable { reverseTypeIndex["MariaDB"] = "MySQL" reverseTypeIndex["TiDB"] = "MySQL" reverseTypeIndex["Databend"] = "MySQL" + reverseTypeIndex["OceanBase"] = "MySQL" reverseTypeIndex["Redshift"] = "PostgreSQL" reverseTypeIndex["CockroachDB"] = "PostgreSQL" reverseTypeIndex["PGlite"] = "PostgreSQL" @@ -680,7 +681,7 @@ final class PluginMetadataRegistry: @unchecked Sendable { /// Keyed by `databaseTypeId`. Stale plugins from the registry inherit these on registration. static func fallbackCategory(forTypeId typeId: String) -> DatabaseCategory { switch typeId { - case "MySQL", "MariaDB", "PostgreSQL", "SQLite", "Oracle", "MSSQL": + case "MySQL", "MariaDB", "PostgreSQL", "SQLite", "Oracle", "MSSQL", "OceanBase": return .relational case "Redshift", "ClickHouse", "DuckDB", "BigQuery": return .analytical @@ -707,6 +708,7 @@ final class PluginMetadataRegistry: @unchecked Sendable { switch typeId { case "MySQL": return String(localized: "Most popular open-source SQL database") case "MariaDB": return String(localized: "Open-source fork of MySQL") + case "OceanBase": return String(localized: "Distributed HTAP, MySQL-compatible") case "PostgreSQL": return String(localized: "Advanced object-relational SQL") case "Redshift": return String(localized: "Amazon's columnar warehouse on Postgres") case "SQLite": return String(localized: "Embedded zero-config SQL database") diff --git a/TablePro/Core/Services/ProjectImport/DockerComposeExtractor.swift b/TablePro/Core/Services/ProjectImport/DockerComposeExtractor.swift index 4e4c56d551..faccd4b180 100644 --- a/TablePro/Core/Services/ProjectImport/DockerComposeExtractor.swift +++ b/TablePro/Core/Services/ProjectImport/DockerComposeExtractor.swift @@ -79,6 +79,9 @@ enum DockerComposeExtractor { if databendRepositories.contains(repositoryPath.suffix(2).joined(separator: "/")) { return ServiceDatabase(type: .databend, defaultPort: 3_307) } + if name.contains("oceanbase") { + return ServiceDatabase(type: .oceanbase, defaultPort: 2_881) + } if name.contains("postgres"), !name.contains("postgrest") { return ServiceDatabase(type: .postgresql, defaultPort: 5_432) } @@ -179,6 +182,10 @@ enum DockerComposeExtractor { fields.username = variables["QUERY_DEFAULT_USER"] ?? "root" fields.password = variables["QUERY_DEFAULT_PASSWORD"] ?? "" fields.database = "default" + case .oceanbase: + fields.username = "root@sys" + fields.password = "" + fields.database = "" case .mariadb, .mysql: let prefix = variables["MARIADB_PASSWORD"] != nil || variables["MARIADB_DATABASE"] != nil ? "MARIADB" diff --git a/TablePro/Info.plist b/TablePro/Info.plist index cf67a7aafc..40bd760bdc 100644 --- a/TablePro/Info.plist +++ b/TablePro/Info.plist @@ -415,6 +415,7 @@ mysql mariadb tidb + oceanbase sqlite mongodb redis diff --git a/TablePro/Models/Connection/DatabaseType.swift b/TablePro/Models/Connection/DatabaseType.swift index db70ba1768..571114d0be 100644 --- a/TablePro/Models/Connection/DatabaseType.swift +++ b/TablePro/Models/Connection/DatabaseType.swift @@ -18,6 +18,7 @@ extension DatabaseType { static let mariadb = DatabaseType(rawValue: "MariaDB") static let tidb = DatabaseType(rawValue: "TiDB") static let databend = DatabaseType(rawValue: "Databend") + static let oceanbase = DatabaseType(rawValue: "OceanBase") static let postgresql = DatabaseType(rawValue: "PostgreSQL") static let sqlite = DatabaseType(rawValue: "SQLite") static let redshift = DatabaseType(rawValue: "Redshift") diff --git a/TablePro/Models/Schema/ColumnDefaultVocabulary.swift b/TablePro/Models/Schema/ColumnDefaultVocabulary.swift index 4583449a6d..5266829b67 100644 --- a/TablePro/Models/Schema/ColumnDefaultVocabulary.swift +++ b/TablePro/Models/Schema/ColumnDefaultVocabulary.swift @@ -54,7 +54,7 @@ internal enum ColumnDefaultVocabulary { private static func expressionSQL(for databaseType: DatabaseType) -> [String] { switch databaseType { - case .mysql, .tidb: + case .mysql, .tidb, .oceanbase: return ["CURRENT_TIMESTAMP", "(UUID())", "(CURRENT_DATE)"] case .mariadb: return ["CURRENT_TIMESTAMP", "uuid()", "curdate()"] diff --git a/TablePro/Models/Schema/ForeignKeyDialect.swift b/TablePro/Models/Schema/ForeignKeyDialect.swift index 7253c6a0df..fe1f2d3fce 100644 --- a/TablePro/Models/Schema/ForeignKeyDialect.swift +++ b/TablePro/Models/Schema/ForeignKeyDialect.swift @@ -44,7 +44,7 @@ struct ForeignKeyDialect: Equatable, Sendable { allowsQualifiedReferencedTable: false, allowsOmittedReferencedColumns: true ) - case .mysql, .mariadb, .tidb: + case .mysql, .mariadb, .tidb, .oceanbase: return ForeignKeyDialect( deleteActions: [.noAction, .restrict, .cascade, .setNull], updateActions: [.noAction, .restrict, .cascade, .setNull], diff --git a/TableProMobile/TableProMobile/Assets.xcassets/oceanbase-icon.imageset/Contents.json b/TableProMobile/TableProMobile/Assets.xcassets/oceanbase-icon.imageset/Contents.json new file mode 100644 index 0000000000..eb0b7fe6e2 --- /dev/null +++ b/TableProMobile/TableProMobile/Assets.xcassets/oceanbase-icon.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "oceanbase.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/TableProMobile/TableProMobile/Assets.xcassets/oceanbase-icon.imageset/oceanbase.svg b/TableProMobile/TableProMobile/Assets.xcassets/oceanbase-icon.imageset/oceanbase.svg new file mode 100644 index 0000000000..a423b01f5c --- /dev/null +++ b/TableProMobile/TableProMobile/Assets.xcassets/oceanbase-icon.imageset/oceanbase.svg @@ -0,0 +1 @@ + diff --git a/TableProMobile/TableProMobile/Coordinators/ConnectionCoordinator.swift b/TableProMobile/TableProMobile/Coordinators/ConnectionCoordinator.swift index a52072da93..14cffc8d25 100644 --- a/TableProMobile/TableProMobile/Coordinators/ConnectionCoordinator.swift +++ b/TableProMobile/TableProMobile/Coordinators/ConnectionCoordinator.swift @@ -51,7 +51,7 @@ final class ConnectionCoordinator { var supportsDatabaseSwitching: Bool { connection.type == .mysql || connection.type == .mariadb || - connection.type == .tidb || + connection.type == .tidb || connection.type == .oceanbase || connection.type == .postgresql || connection.type == .redshift || connection.type == .mssql } diff --git a/TableProMobile/TableProMobile/Helpers/DatabaseType+Mobile.swift b/TableProMobile/TableProMobile/Helpers/DatabaseType+Mobile.swift index 3b1badeebf..bfce9ab524 100644 --- a/TableProMobile/TableProMobile/Helpers/DatabaseType+Mobile.swift +++ b/TableProMobile/TableProMobile/Helpers/DatabaseType+Mobile.swift @@ -7,6 +7,7 @@ extension DatabaseType { case .mysql, .mariadb: return "3306" case .tidb: return "4000" case .databend: return "3307" + case .oceanbase: return "2881" case .postgresql: return "5432" case .redshift: return "5439" case .redis: return "6379" @@ -23,6 +24,7 @@ extension DatabaseType { case .mariadb: "MariaDB" case .tidb: "TiDB" case .databend: "Databend" + case .oceanbase: "OceanBase" case .postgresql: "PostgreSQL" case .redshift: "Redshift" case .sqlite: "SQLite" @@ -38,6 +40,7 @@ extension DatabaseType { .mysql, .mariadb, .tidb, + .oceanbase, .postgresql, .sqlite, .duckdb, diff --git a/TableProMobile/TableProMobile/Intents/IntentDatabaseSession.swift b/TableProMobile/TableProMobile/Intents/IntentDatabaseSession.swift index a2991128a1..32cebec073 100644 --- a/TableProMobile/TableProMobile/Intents/IntentDatabaseSession.swift +++ b/TableProMobile/TableProMobile/Intents/IntentDatabaseSession.swift @@ -9,7 +9,7 @@ struct IntentDatabaseSession { static func supportsTabularInsert(_ type: DatabaseType) -> Bool { switch type { - case .mysql, .mariadb, .tidb, .postgresql, .redshift, .mssql, .sqlite, .duckdb, .oracle: + case .mysql, .mariadb, .tidb, .oceanbase, .postgresql, .redshift, .mssql, .sqlite, .duckdb, .oracle: return true default: return false diff --git a/TableProMobile/TableProMobile/Platform/IOSDriverFactory.swift b/TableProMobile/TableProMobile/Platform/IOSDriverFactory.swift index 1752290732..fa3007c9a1 100644 --- a/TableProMobile/TableProMobile/Platform/IOSDriverFactory.swift +++ b/TableProMobile/TableProMobile/Platform/IOSDriverFactory.swift @@ -33,7 +33,7 @@ nonisolated final class IOSDriverFactory: DriverFactory { ? nil : bookmarkStore.bookmark(for: connection.id) return DuckDBDriver(path: connection.database, bookmark: bookmark) - case .mysql, .mariadb, .tidb: + case .mysql, .mariadb, .tidb, .oceanbase: return MySQLDriver( host: connection.host, port: connection.port, @@ -75,6 +75,6 @@ nonisolated final class IOSDriverFactory: DriverFactory { } func supportedTypes() -> [DatabaseType] { - [.sqlite, .duckdb, .mysql, .mariadb, .tidb, .postgresql, .redshift, .redis, .mssql, .oracle] + [.sqlite, .duckdb, .mysql, .mariadb, .tidb, .oceanbase, .postgresql, .redshift, .redis, .mssql, .oracle] } } diff --git a/TableProMobile/TableProMobile/Views/Components/DatabaseIconView.swift b/TableProMobile/TableProMobile/Views/Components/DatabaseIconView.swift index 458e4c3fdd..917b33d668 100644 --- a/TableProMobile/TableProMobile/Views/Components/DatabaseIconView.swift +++ b/TableProMobile/TableProMobile/Views/Components/DatabaseIconView.swift @@ -30,6 +30,7 @@ struct DatabaseIconView: View { case .mysql, .mariadb: return .orange case .tidb: return .red case .databend: return .blue + case .oceanbase: return .blue case .postgresql, .redshift: return .blue case .sqlite: return .green case .redis: return .red diff --git a/TableProMobile/TableProMobileTests/Helpers/SQLBuilderDefaultValuesTests.swift b/TableProMobile/TableProMobileTests/Helpers/SQLBuilderDefaultValuesTests.swift index 22e6543edc..7d72893bff 100644 --- a/TableProMobile/TableProMobileTests/Helpers/SQLBuilderDefaultValuesTests.swift +++ b/TableProMobile/TableProMobileTests/Helpers/SQLBuilderDefaultValuesTests.swift @@ -18,6 +18,9 @@ struct SQLBuilderDefaultValuesTests { #expect(SQLBuilder.buildAllDefaultsInsert(qualifiedTable: "`t`", for: .tidb) == "INSERT INTO `t` () VALUES ()") #expect(SQLBuilder.quoteIdentifier("a`b", for: .tidb) == "`a``b`") + #expect(SQLBuilder.buildAllDefaultsInsert(qualifiedTable: "`t`", for: .oceanbase) + == "INSERT INTO `t` () VALUES ()") + #expect(SQLBuilder.speaksMySQLDialect(.oceanbase)) } @Test("Databend is not a MySQL dialect on iOS") diff --git a/TableProMobile/TableProMobileTests/MySQLVariantSupportTests.swift b/TableProMobile/TableProMobileTests/MySQLVariantSupportTests.swift index 390e9c2428..7f5caf1e58 100644 --- a/TableProMobile/TableProMobileTests/MySQLVariantSupportTests.swift +++ b/TableProMobile/TableProMobileTests/MySQLVariantSupportTests.swift @@ -9,9 +9,11 @@ struct MySQLVariantSupportTests { @Test("TiDB is offered and supported, Databend is neither") func offeredTypes() { #expect(DatabaseType.mobileSupportedTypes.contains(.tidb)) + #expect(DatabaseType.mobileSupportedTypes.contains(.oceanbase)) #expect(!DatabaseType.mobileSupportedTypes.contains(.databend)) let supported = IOSDriverFactory().supportedTypes() #expect(supported.contains(.tidb)) + #expect(supported.contains(.oceanbase)) #expect(!supported.contains(.databend)) } @@ -21,11 +23,14 @@ struct MySQLVariantSupportTests { #expect(DatabaseType.tidb.mobileDisplayName == "TiDB") #expect(DatabaseType.databend.defaultPort == "3307") #expect(DatabaseType.databend.mobileDisplayName == "Databend") + #expect(DatabaseType.oceanbase.defaultPort == "2881") + #expect(DatabaseType.oceanbase.mobileDisplayName == "OceanBase") } @Test("TiDB takes tabular inserts from Shortcuts, Databend does not") func tabularInsert() { #expect(IntentDatabaseSession.supportsTabularInsert(.tidb)) + #expect(IntentDatabaseSession.supportsTabularInsert(.oceanbase)) #expect(!IntentDatabaseSession.supportsTabularInsert(.databend)) } @@ -36,4 +41,12 @@ struct MySQLVariantSupportTests { let mysql = try #require(driver as? MySQLDriver) #expect(mysql.databaseType == .tidb) } + + @Test("OceanBase routes to the MySQL driver with its own type") + func oceanBaseRoutesToMySQLDriver() throws { + let connection = DatabaseConnection(name: "o", type: .oceanbase, host: "127.0.0.1", port: 2_881) + let driver = try IOSDriverFactory().createDriver(for: connection, password: nil) + let mysql = try #require(driver as? MySQLDriver) + #expect(mysql.databaseType == .oceanbase) + } } diff --git a/TableProMobile/TableProMobileTests/SQLDialectParityTests.swift b/TableProMobile/TableProMobileTests/SQLDialectParityTests.swift index f7d65f1ec6..12206f2c12 100644 --- a/TableProMobile/TableProMobileTests/SQLDialectParityTests.swift +++ b/TableProMobile/TableProMobileTests/SQLDialectParityTests.swift @@ -42,6 +42,7 @@ struct SQLDialectParityTests { (.mysql, .collationDefined), (.mariadb, .collationDefined), (.tidb, .collationDefined), + (.oceanbase, .collationDefined), (.mssql, .collationDefined), (.postgresql, .ilikeOperator), (.duckdb, .ilikeOperator), diff --git a/TableProMobile/TableProWidget/Assets.xcassets/oceanbase-icon.imageset/Contents.json b/TableProMobile/TableProWidget/Assets.xcassets/oceanbase-icon.imageset/Contents.json new file mode 100644 index 0000000000..eb0b7fe6e2 --- /dev/null +++ b/TableProMobile/TableProWidget/Assets.xcassets/oceanbase-icon.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "oceanbase.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/TableProMobile/TableProWidget/Assets.xcassets/oceanbase-icon.imageset/oceanbase.svg b/TableProMobile/TableProWidget/Assets.xcassets/oceanbase-icon.imageset/oceanbase.svg new file mode 100644 index 0000000000..a423b01f5c --- /dev/null +++ b/TableProMobile/TableProWidget/Assets.xcassets/oceanbase-icon.imageset/oceanbase.svg @@ -0,0 +1 @@ + diff --git a/TableProMobile/TableProWidget/Helpers/DatabaseTypeStyle.swift b/TableProMobile/TableProWidget/Helpers/DatabaseTypeStyle.swift index c5e91110f7..c54702effb 100644 --- a/TableProMobile/TableProWidget/Helpers/DatabaseTypeStyle.swift +++ b/TableProMobile/TableProWidget/Helpers/DatabaseTypeStyle.swift @@ -7,6 +7,7 @@ enum DatabaseTypeStyle { case "MariaDB": return "mariadb-icon" case "TiDB": return "tidb-icon" case "Databend": return "databend-icon" + case "OceanBase": return "oceanbase-icon" case "PostgreSQL": return "postgresql-icon" case "Redshift": return "redshift-icon" case "SQLite": return "sqlite-icon" @@ -46,6 +47,7 @@ enum DatabaseTypeStyle { case "MySQL", "MariaDB": return .orange case "TiDB": return .red case "Databend": return .blue + case "OceanBase": return .blue case "PostgreSQL", "Redshift": return .blue case "SQLite": return .green case "Redis": return .red diff --git a/TableProTests/CloudSQL/CloudSQLProxyModelTests.swift b/TableProTests/CloudSQL/CloudSQLProxyModelTests.swift index 68bf261328..9464ec8a9f 100644 --- a/TableProTests/CloudSQL/CloudSQLProxyModelTests.swift +++ b/TableProTests/CloudSQL/CloudSQLProxyModelTests.swift @@ -108,6 +108,7 @@ struct CloudSQLProxyModelTests { #expect(!DatabaseType.mariadb.supportsCloudSQLProxy) #expect(!DatabaseType.tidb.supportsCloudSQLProxy) #expect(!DatabaseType.databend.supportsCloudSQLProxy) + #expect(!DatabaseType.oceanbase.supportsCloudSQLProxy) #expect(!DatabaseType.sqlite.supportsCloudSQLProxy) #expect(!DatabaseType.mongodb.supportsCloudSQLProxy) } diff --git a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorOceanBaseHiddenPKTests.swift b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorOceanBaseHiddenPKTests.swift new file mode 100644 index 0000000000..2f11a7ee96 --- /dev/null +++ b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorOceanBaseHiddenPKTests.swift @@ -0,0 +1,61 @@ +import TableProPluginKit +@testable import TablePro +import Testing + +@Suite("SQL Statement Generator OceanBase hidden PK") +struct SQLStatementGeneratorOceanBaseHiddenPKTests { + private func makeGenerator( + columns: [String], + primaryKeyColumns: [String], + generatedColumns: Set = [] + ) throws -> SQLStatementGenerator { + try SQLStatementGenerator( + tableName: "orders", + columns: columns, + primaryKeyColumns: primaryKeyColumns, + databaseType: .oceanbase, + generatedColumns: generatedColumns, + dialect: nil + ) + } + + @Test("An UPDATE is skipped when the hidden PK is named but not in the result columns") + func missingHiddenKeySkipsUpdate() throws { + let generator = try makeGenerator( + columns: ["name", "amount"], + primaryKeyColumns: ["__pk_increment"] + ) + let change = RowChange( + rowIndex: 0, + type: .update, + cellChanges: [ + CellChange(columnIndex: 0, columnName: "name", oldValue: "old", newValue: "new") + ], + originalRow: ["old", "1"].map(PluginCellValue.fromOptional) + ) + #expect(generator.generateUpdateSQL(for: change) == nil) + } + + @Test("An UPDATE matches on the hidden PK once it is a result column") + func hiddenKeyAnchorsUpdate() throws { + let generator = try makeGenerator( + columns: ["name", "amount", "__pk_increment"], + primaryKeyColumns: ["__pk_increment"], + generatedColumns: ["__pk_increment"] + ) + let change = RowChange( + rowIndex: 0, + type: .update, + cellChanges: [ + CellChange(columnIndex: 0, columnName: "name", oldValue: "old", newValue: "new") + ], + originalRow: ["old", "1", "42"].map(PluginCellValue.fromOptional) + ) + let statement = try #require(generator.generateUpdateSQL(for: change)) + #expect(statement.sql == "UPDATE `orders` SET `name` = ? WHERE `__pk_increment` = ?") + #expect(statement.parameters.count == 2) + #expect(statement.parameters[0] as? String == "new") + #expect(statement.parameters[1] as? String == "42") + #expect(!statement.sql.contains("SET `__pk_increment`")) + } +} diff --git a/TableProTests/Core/Compare/CompareSQLLiteralTests.swift b/TableProTests/Core/Compare/CompareSQLLiteralTests.swift index 0cb4a9d813..665ce4ad24 100644 --- a/TableProTests/Core/Compare/CompareSQLLiteralTests.swift +++ b/TableProTests/Core/Compare/CompareSQLLiteralTests.swift @@ -15,7 +15,7 @@ final class CompareSQLLiteralTests: XCTestCase { private let png = Data([0x89, 0x50, 0x4E, 0x47]) func testBitStringEnginesKeepTheDefaultSpelling() throws { - for type in [DatabaseType.mysql, .mariadb, .tidb, .databend, .sqlite, .clickhouse, .duckdb, .libsql, .turso, .cloudflareD1] { + for type in [DatabaseType.mysql, .mariadb, .tidb, .databend, .oceanbase, .sqlite, .clickhouse, .duckdb, .libsql, .turso, .cloudflareD1] { let literal = try XCTUnwrap(CompareSQLLiteral.binaryLiteral(for: png, databaseType: type)) XCTAssertEqual(literal, "X'89504E47'", "\(type.rawValue) uses a bit-string literal") } diff --git a/TableProTests/Core/Compare/SchemaSyncScriptBuilderTests.swift b/TableProTests/Core/Compare/SchemaSyncScriptBuilderTests.swift index 7e56a6c1a4..450a69ccbe 100644 --- a/TableProTests/Core/Compare/SchemaSyncScriptBuilderTests.swift +++ b/TableProTests/Core/Compare/SchemaSyncScriptBuilderTests.swift @@ -351,6 +351,8 @@ final class CompareSyncEngineFamilyTests: XCTestCase { XCTAssertFalse(CompareSyncEngineFamily.canGenerateStructureScript(from: .mysql, to: .tidb)) XCTAssertFalse(CompareSyncEngineFamily.canGenerateStructureScript(from: .tidb, to: .mariadb)) XCTAssertFalse(CompareSyncEngineFamily.canGenerateStructureScript(from: .mysql, to: .databend)) + XCTAssertTrue(CompareSyncEngineFamily.canGenerateStructureScript(from: .oceanbase, to: .oceanbase)) + XCTAssertFalse(CompareSyncEngineFamily.canGenerateStructureScript(from: .mysql, to: .oceanbase)) } func testUnrelatedEnginesAreRefused() { diff --git a/TableProTests/Core/Plugins/MySQLVariantSupportTests.swift b/TableProTests/Core/Plugins/MySQLVariantSupportTests.swift index 1b6e1540fb..cf4228ea12 100644 --- a/TableProTests/Core/Plugins/MySQLVariantSupportTests.swift +++ b/TableProTests/Core/Plugins/MySQLVariantSupportTests.swift @@ -29,6 +29,15 @@ struct MySQLVariantSupportTests { #expect(ExplainFormatResolver.resolve(declared: .plainText, databaseType: DatabaseType(rawValue: typeId)) == .plainText) } + @Test("OceanBase keeps a plain EXPLAIN and does not take FORMAT=JSON") + func oceanbaseExplainStaysPlain() throws { + let registry = PluginMetadataRegistry.shared + registry.registerVariant(pluginSnapshot: try Self.mysqlPluginSnapshot(), forTypeId: "OceanBase", primaryTypeId: "MySQL") + let variants = try #require(registry.snapshot(forRegisteredTypeId: "OceanBase")).explainVariants + #expect(variants.map(\.sqlPrefix) == ["EXPLAIN"]) + #expect(variants.allSatisfy { $0.format == .plainText }) + } + @Test("TiDB keeps its type list without the spatial group once the MySQL plugin registers") func tidbColumnTypesSurviveRegistration() throws { let registry = PluginMetadataRegistry.shared @@ -38,6 +47,15 @@ struct MySQLVariantSupportTests { #expect(types["JSON"] == ["JSON"]) } + @Test("OceanBase keeps its type list without the spatial group once the MySQL plugin registers") + func oceanbaseColumnTypesSurviveRegistration() throws { + let registry = PluginMetadataRegistry.shared + registry.registerVariant(pluginSnapshot: try Self.mysqlPluginSnapshot(), forTypeId: "OceanBase", primaryTypeId: "MySQL") + let types = try #require(registry.snapshot(forRegisteredTypeId: "OceanBase")).editor.columnTypesByCategory + #expect(types["Spatial"] == nil) + #expect(types["JSON"] == ["JSON"]) + } + @Test("Databend keeps its own types and case folding once the MySQL plugin registers") func databendEditorSurvivesRegistration() throws { let registry = PluginMetadataRegistry.shared @@ -66,6 +84,7 @@ struct MySQLVariantSupportTests { @Test("TiDB hides the connection limit it ignores; the others keep it") func principalConnectionLimit() { #expect(!PluginManager.shared.supportsPrincipalConnectionLimit(for: .tidb)) + #expect(!PluginManager.shared.supportsPrincipalConnectionLimit(for: .oceanbase)) #expect(PluginManager.shared.supportsPrincipalConnectionLimit(for: .mysql)) #expect(PluginManager.shared.supportsPrincipalConnectionLimit(for: .mariadb)) } @@ -75,6 +94,7 @@ struct MySQLVariantSupportTests { #expect(PluginManager.shared.rowMatchExcludedTypePrefixes(for: .databend).contains("VARIANT")) #expect(PluginManager.shared.rowMatchExcludedTypePrefixes(for: .mysql).isEmpty) #expect(PluginManager.shared.rowMatchExcludedTypePrefixes(for: .tidb).isEmpty) + #expect(PluginManager.shared.rowMatchExcludedTypePrefixes(for: .oceanbase).isEmpty) } @Test("The inspector's function menu offers only what each engine has") @@ -82,6 +102,8 @@ struct MySQLVariantSupportTests { let tidb = SQLFunctionProvider.functions(for: .tidb).map(\.expression) #expect(tidb.contains("CURDATE()")) #expect(tidb.contains("UTC_TIMESTAMP()")) + let oceanbase = SQLFunctionProvider.functions(for: .oceanbase).map(\.expression) + #expect(oceanbase.contains("CURDATE()")) let databend = SQLFunctionProvider.functions(for: .databend).map(\.expression) #expect(databend == ["NOW()", "CURRENT_TIMESTAMP()", "UUID()"]) } @@ -97,6 +119,7 @@ struct MySQLVariantSupportTests { @Test("Databend lexes as the generic dialect, TiDB as MySQL") func lexicalDialects() { #expect(SqlDialect.from(databaseTypeId: "TiDB") == .mysql) + #expect(SqlDialect.from(databaseTypeId: "OceanBase") == .mysql) #expect(SqlDialect.from(databaseTypeId: "Databend") == .generic) } @@ -109,7 +132,9 @@ struct MySQLVariantSupportTests { @Test("TiDB copies as the MySQL type family; Databend does not") func typeFamilies() { #expect(SQLTypeFamily.of(.tidb) == .mysql) + #expect(SQLTypeFamily.of(.oceanbase) == .mysql) #expect(!SQLTypeFamily.needsTranslation(from: .mysql, to: .tidb)) + #expect(!SQLTypeFamily.needsTranslation(from: .mysql, to: .oceanbase)) #expect(SQLTypeFamily.of(.databend) != .mysql) } @@ -118,12 +143,20 @@ struct MySQLVariantSupportTests { #expect(ColumnDefaultVocabulary.options(for: .tidb) == ColumnDefaultVocabulary.options(for: .mysql)) } + @Test("OceanBase treats the hidden primary key columns as immutable") + func oceanbaseImmutableHiddenKeys() { + #expect(PluginManager.shared.immutableColumns(for: .oceanbase) == ["__pk_increment", "__pk_cluster_column"]) + #expect(PluginManager.shared.immutableColumns(for: .mysql).isEmpty) + } + @Test("Neither variant gets a Server Dashboard or a native backup") func dashboardAndBackup() { #expect(ServerDashboardQueryProviderFactory.provider(for: .tidb) == nil) #expect(ServerDashboardQueryProviderFactory.provider(for: .databend) == nil) + #expect(ServerDashboardQueryProviderFactory.provider(for: .oceanbase) == nil) #expect(!NativeDumpRegistry.supports(.tidb)) #expect(!NativeDumpRegistry.supports(.databend)) + #expect(!NativeDumpRegistry.supports(.oceanbase)) } @Test("TiDB compares with TiDB, not with MySQL or MariaDB") @@ -132,14 +165,21 @@ struct MySQLVariantSupportTests { #expect(!CompareSyncEngineFamily.canGenerateStructureScript(from: .mysql, to: .tidb)) #expect(!CompareSyncEngineFamily.canGenerateStructureScript(from: .tidb, to: .mariadb)) #expect(!CompareSyncEngineFamily.canGenerateStructureScript(from: .mysql, to: .databend)) + #expect(CompareSyncEngineFamily.canGenerateStructureScript(from: .oceanbase, to: .oceanbase)) + #expect(!CompareSyncEngineFamily.canGenerateStructureScript(from: .mysql, to: .oceanbase)) + #expect(!CompareSyncEngineFamily.canGenerateStructureScript(from: .oceanbase, to: .mariadb)) } - @Test("URLs: tidb:// opens TiDB, databend:// is refused") + @Test("URLs: tidb:// opens TiDB, oceanbase:// opens OceanBase, databend:// is refused") func urlSchemes() { guard case .success(let tidb) = ConnectionURLParser.parse("tidb://root@host:4000/test") else { Issue.record("Expected tidb:// to parse"); return } #expect(tidb.type == .tidb) + guard case .success(let oceanbase) = ConnectionURLParser.parse("oceanbase://root%40sys@host:2881/test") else { + Issue.record("Expected oceanbase:// to parse"); return + } + #expect(oceanbase.type == .oceanbase) guard case .failure = ConnectionURLParser.parse("databend://root:pw@host:8000/default") else { Issue.record("Expected databend:// to be refused"); return } diff --git a/TableProTests/Core/Plugins/PluginManagerVariantAccessorTests.swift b/TableProTests/Core/Plugins/PluginManagerVariantAccessorTests.swift index 315d0818d9..4cce008edb 100644 --- a/TableProTests/Core/Plugins/PluginManagerVariantAccessorTests.swift +++ b/TableProTests/Core/Plugins/PluginManagerVariantAccessorTests.swift @@ -49,6 +49,7 @@ struct PluginManagerVariantAccessorTests { "INFORMATION_SCHEMA", "METRICS_SCHEMA", "PERFORMANCE_SCHEMA", "mysql", "sys" ]) #expect(manager.systemDatabaseNames(for: .databend) == ["information_schema", "system"]) + #expect(manager.systemDatabaseNames(for: .oceanbase) == ["information_schema", "mysql", "oceanbase"]) } /// The reason the editor half of this was reported: Redshift has no non-ASCII ILIKE, so it diff --git a/TableProTests/Core/Plugins/PluginMetadataRegistryTypeCountTests.swift b/TableProTests/Core/Plugins/PluginMetadataRegistryTypeCountTests.swift index ef6d5a6e67..5cf47c6b72 100644 --- a/TableProTests/Core/Plugins/PluginMetadataRegistryTypeCountTests.swift +++ b/TableProTests/Core/Plugins/PluginMetadataRegistryTypeCountTests.swift @@ -11,7 +11,7 @@ import Testing /// this registry, `docs/snippets/driver-counts.mdx`, and the marketing site. Nothing at runtime /// reconciles them, and by August 2026 they read 28, 27 and 25 at once. /// -/// The answer is 34, and the reason it once read 28 is worth keeping. Turso is served by +/// The answer is 35, and the reason it once read 28 is worth keeping. Turso is served by /// the libSQL plugin and was the only alias in `reverseTypeIndex` with no curated entry of its /// own, so it was the only type the picker could not offer before its plugin was installed. /// ScyllaDB is the shape every other alias already had: an alias of Cassandra with a curated @@ -24,7 +24,7 @@ import Testing /// `docs/scripts/check-docs-against-source.py` reads the registry and holds the docs half. /// /// The count is taken from the built-in defaults rather than from `allRegisteredTypeIds()`. -/// Both answer 34 under XCTest, where no plugin bundle ever loads, but the registry is a +/// Both answer 35 under XCTest, where no plugin bundle ever loads, but the registry is a /// process-global singleton and suites that register a synthetic type run alongside this one. @MainActor @Suite("PluginMetadataRegistry engine count") @@ -34,7 +34,7 @@ struct PluginMetadataRegistryTypeCountTests { "CockroachDB", "Dameng", "Databend", "DuckDB", "DynamoDB", "Elasticsearch", "etcd", "Kafka", "libSQL", "MariaDB", "MongoDB", "MySQL", "Oracle", "PGlite", "PostgreSQL", "Redis", "Redshift", "ScyllaDB", "Snowflake", "Spanner", "SQL Server", "SQLite", "SurrealDB", "Teradata", "TiDB", "Trino", - "Turso", "Typesense" + "Turso", "Typesense", "OceanBase" ] private static func builtInTypeIds() -> Set { @@ -43,10 +43,10 @@ struct PluginMetadataRegistryTypeCountTests { return Set(curated + registry) } - @Test("The app ships 34 database types before any plugin loads") + @Test("The app ships 35 database types before any plugin loads") func builtInDefaultsCoverTwentyNineTypes() { let ids = Self.builtInTypeIds() - #expect(ids.count == 34) + #expect(ids.count == 35) #expect(ids == Self.expectedTypeIds) } @@ -64,6 +64,7 @@ struct PluginMetadataRegistryTypeCountTests { "MariaDB": "MySQL", "TiDB": "MySQL", "Databend": "MySQL", + "OceanBase": "MySQL", "Redshift": "PostgreSQL", "CockroachDB": "PostgreSQL", "PGlite": "PostgreSQL", diff --git a/TableProTests/Core/Plugins/PluginMetadataRegistryVariantTests.swift b/TableProTests/Core/Plugins/PluginMetadataRegistryVariantTests.swift index 38e92eee94..2314d8d2d4 100644 --- a/TableProTests/Core/Plugins/PluginMetadataRegistryVariantTests.swift +++ b/TableProTests/Core/Plugins/PluginMetadataRegistryVariantTests.swift @@ -104,6 +104,7 @@ struct PluginMetadataRegistryVariantTests { #expect(registry.snapshot(for: .cockroachdb)?.defaultPort == 26_257) #expect(registry.snapshot(for: .tidb)?.defaultPort == 4_000) #expect(registry.snapshot(for: .databend)?.defaultPort == 3_307) + #expect(registry.snapshot(for: .oceanbase)?.defaultPort == 2_881) } /// One connection, one dialect. The filter preview reads PluginManager.sqlDialect while the @@ -112,7 +113,7 @@ struct PluginMetadataRegistryVariantTests { @MainActor @Test("every reader of the editor dialect agrees for a variant type") func dialectReadersAgreeForAVariant() throws { - for databaseType in [DatabaseType.redshift, .cockroachdb, .pglite, .mariadb, .tidb, .databend] { + for databaseType in [DatabaseType.redshift, .cockroachdb, .pglite, .mariadb, .tidb, .databend, .oceanbase] { let viaManager = try #require(PluginManager.shared.sqlDialect(for: databaseType)) let viaHelper = try resolveSQLDialect(for: databaseType) #expect(viaManager.caseSensitivityStyle == viaHelper.caseSensitivityStyle) diff --git a/TableProTests/Core/Plugins/SocketPathPlaceholderTests.swift b/TableProTests/Core/Plugins/SocketPathPlaceholderTests.swift index f6e774a486..676094c2aa 100644 --- a/TableProTests/Core/Plugins/SocketPathPlaceholderTests.swift +++ b/TableProTests/Core/Plugins/SocketPathPlaceholderTests.swift @@ -21,6 +21,7 @@ struct SocketPathPlaceholderTests { func mysqlProtocolVariantsHaveNoSocket() { #expect(PluginManager.shared.defaultUnixSocketPath(for: .tidb) == nil) #expect(PluginManager.shared.defaultUnixSocketPath(for: .databend) == nil) + #expect(PluginManager.shared.defaultUnixSocketPath(for: .oceanbase) == nil) } @Test("PostgreSQL uses the PGSQL socket") diff --git a/TableProTests/Core/Services/ProjectImport/ProjectYamlExtractorTests.swift b/TableProTests/Core/Services/ProjectImport/ProjectYamlExtractorTests.swift index 61f26be14d..8b4817e737 100644 --- a/TableProTests/Core/Services/ProjectImport/ProjectYamlExtractorTests.swift +++ b/TableProTests/Core/Services/ProjectImport/ProjectYamlExtractorTests.swift @@ -262,6 +262,22 @@ struct DockerComposeExtractorTests { #expect(databend?.parsedURL.database == "default") } + @Test("OceanBase images map to OceanBase on 2881 as root@sys") + func testOceanBaseImageAndCredentials() { + let oceanbase = extract(""" + services: + ob: + image: oceanbase/oceanbase-ce:latest + ports: + - "2881:2881" + """).first + #expect(oceanbase?.parsedURL.type == .oceanbase) + #expect(oceanbase?.parsedURL.port == nil) + #expect(oceanbase?.parsedURL.username == "root@sys") + #expect(oceanbase?.parsedURL.password.isEmpty == true) + #expect(oceanbase?.parsedURL.database.isEmpty == true) + } + @Test("Interpolation uses the adjacent dotenv file") func testInterpolationFromDotenv() { let contents = """ diff --git a/TableProTests/Core/Utilities/ConnectionURLParserOceanBaseTests.swift b/TableProTests/Core/Utilities/ConnectionURLParserOceanBaseTests.swift new file mode 100644 index 0000000000..f05642df9b --- /dev/null +++ b/TableProTests/Core/Utilities/ConnectionURLParserOceanBaseTests.swift @@ -0,0 +1,44 @@ +import Foundation +@testable import TablePro +import TableProPluginKit +import Testing + +@Suite("Connection URL Parser - OceanBase") +struct ConnectionURLParserOceanBaseTests { + @Test("Full oceanbase URL with default port") + func testFullURLDefaultPort() { + let result = ConnectionURLParser.parse("oceanbase://root%40sys:pass@host:2881/test") + guard case .success(let parsed) = result else { + Issue.record("Expected success"); return + } + #expect(parsed.type == .oceanbase) + #expect(parsed.host == "host") + #expect(parsed.port == nil) + #expect(parsed.database == "test") + #expect(parsed.username == "root@sys") + #expect(parsed.password == "pass") + } + + @Test("Case-insensitive OceanBase scheme") + func testCaseInsensitiveScheme() { + let result = ConnectionURLParser.parse("OceanBase://root%40sys@host/db") + guard case .success(let parsed) = result else { + Issue.record("Expected success"); return + } + #expect(parsed.type == .oceanbase) + #expect(parsed.host == "host") + #expect(parsed.username == "root@sys") + } + + @Test("OceanBase non-default port preserved") + func testNonDefaultPortPreserved() { + let result = ConnectionURLParser.parse("oceanbase://root%40sys:pass@host:2883/db") + guard case .success(let parsed) = result else { + Issue.record("Expected success"); return + } + #expect(parsed.type == .oceanbase) + #expect(parsed.port == 2_883) + #expect(parsed.host == "host") + #expect(parsed.database == "db") + } +} diff --git a/TableProTests/Core/Utilities/DatabaseURLSchemeTests.swift b/TableProTests/Core/Utilities/DatabaseURLSchemeTests.swift index 6003e96c7b..d087d77d2c 100644 --- a/TableProTests/Core/Utilities/DatabaseURLSchemeTests.swift +++ b/TableProTests/Core/Utilities/DatabaseURLSchemeTests.swift @@ -61,6 +61,16 @@ struct DatabaseURLSchemeTests { #expect(parsed.type == .tidb) } + @Test("OceanBase scheme parses successfully") + func oceanbaseScheme() { + let result = ConnectionURLParser.parse("oceanbase://root%40sys:pass@localhost:2881/test") + guard case .success(let parsed) = result else { + Issue.record("Expected success"); return + } + #expect(parsed.type == .oceanbase) + #expect(parsed.username == "root@sys") + } + @Test("SQLite scheme parses successfully") func sqliteScheme() { let result = ConnectionURLParser.parse("sqlite:///path/to/database.db") @@ -196,6 +206,17 @@ struct DatabaseURLSchemeTests { #expect(parsed.sshHost == "sshhost") } + @Test("OceanBase+SSH scheme parses successfully") + func oceanbaseSshScheme() { + let result = ConnectionURLParser.parse("oceanbase+ssh://sshuser@sshhost:22/root%40sys:dbpass@dbhost/dbname") + guard case .success(let parsed) = result else { + Issue.record("Expected success"); return + } + #expect(parsed.type == .oceanbase) + #expect(parsed.sshHost == "sshhost") + #expect(parsed.username == "root@sys") + } + // MARK: - Unsupported Schemes @Test("FTP scheme returns unsupported error") diff --git a/TableProTests/Models/DatabaseTypeOceanBaseTests.swift b/TableProTests/Models/DatabaseTypeOceanBaseTests.swift new file mode 100644 index 0000000000..dcee5681ee --- /dev/null +++ b/TableProTests/Models/DatabaseTypeOceanBaseTests.swift @@ -0,0 +1,50 @@ +import Foundation +@testable import TablePro +import TableProPluginKit +import Testing + +@Suite("DatabaseType OceanBase") +struct DatabaseTypeOceanBaseTests { + @Test("rawValue is OceanBase") + func rawValue() { + #expect(DatabaseType.oceanbase.rawValue == "OceanBase") + } + + @Test("defaultPort is 2881") + func defaultPort() { + #expect(DatabaseType.oceanbase.defaultPort == 2_881) + } + + @Test("iconName is oceanbase-icon") + func iconName() { + #expect(DatabaseType.oceanbase.iconName == "oceanbase-icon") + } + + @Test("pluginTypeId resolves to MySQL") + func pluginTypeIdResolvesToMySQL() { + #expect(DatabaseType.oceanbase.pluginTypeId == "MySQL") + } + + @Test("triggers browse without trigger editing") + func triggerFlags() { + #expect(DatabaseType.oceanbase.supportsTriggers == true) + #expect(DatabaseType.oceanbase.supportsTriggerEditing == false) + } + + @Test("routines are offered") + func routines() { + #expect(DatabaseType.oceanbase.supportsRoutines == true) + } + + @Test("allKnownTypes contains oceanbase") + func allKnownTypesContainsOceanBase() { + #expect(DatabaseType.allKnownTypes.contains(.oceanbase)) + } + + @Test("Codable round-trips through rawValue") + func codableRoundTrip() throws { + let encoded = try JSONEncoder().encode(DatabaseType.oceanbase) + let decoded = try JSONDecoder().decode(DatabaseType.self, from: encoded) + #expect(decoded == DatabaseType.oceanbase) + } +} diff --git a/TableProTests/Models/DatabaseTypeTests.swift b/TableProTests/Models/DatabaseTypeTests.swift index 1e7a3a1e42..ba749d08d6 100644 --- a/TableProTests/Models/DatabaseTypeTests.swift +++ b/TableProTests/Models/DatabaseTypeTests.swift @@ -57,6 +57,7 @@ struct DatabaseTypeTests { (DatabaseType.mariadb, "MariaDB"), (DatabaseType.tidb, "TiDB"), (DatabaseType.databend, "Databend"), + (DatabaseType.oceanbase, "OceanBase"), (DatabaseType.postgresql, "PostgreSQL"), (DatabaseType.sqlite, "SQLite"), (DatabaseType.mongodb, "MongoDB"), @@ -119,6 +120,11 @@ struct DatabaseTypeTests { #expect(DatabaseType.databend.pluginTypeId == "MySQL") } + @Test("OceanBase pluginTypeId maps to MySQL plugin") + func testOceanBasePluginTypeId() { + #expect(DatabaseType.oceanbase.pluginTypeId == "MySQL") + } + @Test("Redshift pluginTypeId maps to PostgreSQL plugin") func testRedshiftPluginTypeId() { #expect(DatabaseType.redshift.pluginTypeId == "PostgreSQL") @@ -156,7 +162,8 @@ struct DatabaseTypeTests { DatabaseType.mysql, DatabaseType.mariadb, DatabaseType.tidb, - DatabaseType.databend + DatabaseType.databend, + DatabaseType.oceanbase ]) func testMariaDBClientEnginesDefaultSSLPreferred(type: DatabaseType) { #expect(type.defaultSSLMode == .preferred) @@ -194,6 +201,7 @@ struct DatabaseTypeTests { DatabaseType.mariadb, DatabaseType.tidb, DatabaseType.databend, + DatabaseType.oceanbase, DatabaseType.mssql ]) func testOpportunisticTLSSupported(type: DatabaseType) { diff --git a/TableProTests/Plugins/MySQLServerFlavorTests.swift b/TableProTests/Plugins/MySQLServerFlavorTests.swift index efcb1d0f6c..7781acfebf 100644 --- a/TableProTests/Plugins/MySQLServerFlavorTests.swift +++ b/TableProTests/Plugins/MySQLServerFlavorTests.swift @@ -17,6 +17,9 @@ struct MySQLServerFlavorTests { ("11.4.2-MariaDB-log", .mariadb), ("8.0.11-TiDB-v7.5.1", .tidb(version: MySQLEngineVersion(major: 7, minor: 5, patch: 1))), ("8.0.11-TiDB-v8.5.1", .tidb(version: MySQLEngineVersion(major: 8, minor: 5, patch: 1))), + ("5.7.25-OceanBase-v4.2.1", .oceanbase(version: MySQLEngineVersion(major: 4, minor: 2, patch: 1))), + ("5.7.25 OceanBase 3.1.3", .oceanbase(version: MySQLEngineVersion(major: 3, minor: 1, patch: 3))), + ("5.7.25-OceanBase_CE-v4.3.5", .oceanbase(version: MySQLEngineVersion(major: 4, minor: 3, patch: 5))), (databendBanner, .databend) ]) func bannerNamesTheEngine(banner: String, expected: MySQLServerFlavor) { @@ -35,13 +38,24 @@ struct MySQLServerFlavorTests { #expect(MySQLServerFlavor.tidbVersion(fromReleaseInfo: "8.0.36") == nil) } - @Test("A TiDB or Databend connection whose banner does not say so is confirmed with a query") + @Test("A TiDB, Databend or OceanBase connection whose banner does not say so is confirmed with a query") func probesOnlyWhenTheBannerIsSilent() { #expect(MySQLFlavorResolution.needsTiDBVersionProbe(banner: "8.0.35", variant: "TiDB")) #expect(!MySQLFlavorResolution.needsTiDBVersionProbe(banner: "8.0.11-TiDB-v7.5.1", variant: "TiDB")) #expect(!MySQLFlavorResolution.needsTiDBVersionProbe(banner: "8.0.35", variant: nil)) #expect(MySQLFlavorResolution.needsDatabendProbe(banner: "8.0.36", variant: "Databend")) #expect(!MySQLFlavorResolution.needsDatabendProbe(banner: Self.databendBanner, variant: "Databend")) + #expect(MySQLFlavorResolution.needsOceanBaseProbe(banner: "5.7.25", variant: "OceanBase")) + #expect(!MySQLFlavorResolution.needsOceanBaseProbe(banner: "5.7.25-OceanBase-v4.2.1", variant: "OceanBase")) + #expect(!MySQLFlavorResolution.needsOceanBaseProbe(banner: "5.7.25-OceanBase-v4.2.1", variant: nil)) + } + + @Test("A MySQL connection whose banner names OceanBase is OceanBase") + func mysqlOpenedOceanBaseIsOceanBase() { + let flavor = MySQLServerFlavor.fromBanner("5.7.25-OceanBase-v4.2.1") + #expect(flavor.isOceanBase) + #expect(flavor.oceanbaseVersion == MySQLEngineVersion(major: 4, minor: 2, patch: 1)) + #expect(!MySQLServerFlavor.fromBanner("5.7.25").isOceanBase) } @Test("System databases are the exact spellings each engine reports") @@ -51,6 +65,11 @@ struct MySQLServerFlavorTests { "INFORMATION_SCHEMA", "METRICS_SCHEMA", "PERFORMANCE_SCHEMA", "mysql", "sys" ]) #expect(MySQLServerFlavor.databend.systemDatabaseNames == ["information_schema", "system"]) + #expect(MySQLServerFlavor.oceanbase(version: nil).systemDatabaseNames == [ + "information_schema", "mysql", "oceanbase" + ]) + #expect(!MySQLServerFlavor.oceanbase(version: nil).systemDatabaseNames.contains("test")) + #expect(!MySQLServerFlavor.oceanbase(version: nil).systemDatabaseNames.contains("performance_schema")) } @Test("TiDB and Databend offer only the maintenance they support") @@ -58,6 +77,7 @@ struct MySQLServerFlavorTests { #expect(MySQLServerFlavor.mysql.maintenanceOperations.count == 4) #expect(MySQLServerFlavor.tidb(version: nil).maintenanceOperations == ["ANALYZE TABLE"]) #expect(MySQLServerFlavor.databend.maintenanceOperations == ["ANALYZE TABLE"]) + #expect(MySQLServerFlavor.oceanbase(version: nil).maintenanceOperations == ["ANALYZE TABLE"]) } @Test("TiDB sequences cannot be browsed, so they are not listed as tables") @@ -72,6 +92,7 @@ struct MySQLServerFlavorTests { #expect(!MySQLServerFlavor.mysql.dropsIdleSessionOnKillQuery) #expect(!MySQLServerFlavor.mariadb.dropsIdleSessionOnKillQuery) #expect(!MySQLServerFlavor.databend.dropsIdleSessionOnKillQuery) + #expect(!MySQLServerFlavor.oceanbase(version: nil).dropsIdleSessionOnKillQuery) } @Test("Only Databend refuses server-side prepare") @@ -79,6 +100,7 @@ struct MySQLServerFlavorTests { #expect(!MySQLServerFlavor.databend.preparesOnServer) #expect(MySQLServerFlavor.tidb(version: nil).preparesOnServer) #expect(MySQLServerFlavor.mysql.preparesOnServer) + #expect(MySQLServerFlavor.oceanbase(version: nil).preparesOnServer) } @Test("A read-write transaction declares the access mode so a read-only session default is overridden") @@ -104,6 +126,7 @@ struct MySQLServerFlavorTests { (.mysql, 0, "SET SESSION max_execution_time = 0"), (.mysql, 30, "SET SESSION max_execution_time = 30000"), (.tidb(version: nil), 30, "SET SESSION max_execution_time = 30000"), + (.oceanbase(version: nil), 30, "SET SESSION max_execution_time = 30000"), (.databend, 30, "SET max_execute_time_in_seconds = 30") ]) func queryTimeout(flavor: MySQLServerFlavor, seconds: Int, expected: String) { @@ -120,11 +143,14 @@ struct MySQLServerFlavorTests { #expect(!MySQLServerFlavor.databend.isInterruptedByKill(errno: 1_105, message: "SyntaxException. Code: 1005")) } - @Test("TiDB kills by its 64-bit connection id and Databend by its session id") + @Test("TiDB kills by its 64-bit connection id, OceanBase by CONNECTION_ID, Databend by its session id") func killStatements() { let tidb = MySQLServerFlavor.tidb(version: nil).killTarget(connectionIdentifier: "2199023255571") #expect(tidb.statement(threadId: 19) == "KILL TIDB QUERY 2199023255571") + let oceanbase = MySQLServerFlavor.oceanbase(version: nil).killTarget(connectionIdentifier: "3221490143") + #expect(oceanbase.statement(threadId: 19) == "KILL QUERY 3221490143") + let databend = MySQLServerFlavor.databend.killTarget(connectionIdentifier: "1f7e5199-119f-484a-aaff-e8d5143a7979") #expect(databend.statement(threadId: 89) == "KILL QUERY '1f7e5199-119f-484a-aaff-e8d5143a7979'") @@ -137,6 +163,7 @@ struct MySQLServerFlavorTests { func killFallsBackToThreadId() { #expect(MySQLServerFlavor.tidb(version: nil).killTarget(connectionIdentifier: nil) == .threadId) #expect(MySQLServerFlavor.tidb(version: nil).killTarget(connectionIdentifier: "not-a-number") == .threadId) + #expect(MySQLServerFlavor.oceanbase(version: nil).killTarget(connectionIdentifier: nil) == .threadId) #expect(MySQLServerFlavor.databend.killTarget(connectionIdentifier: "") == .threadId) } @@ -157,5 +184,25 @@ struct MySQLServerFlavorTests { func databendGenerationExpression() { #expect(!MySQLServerVersion.hasGenerationExpression(banner: Self.databendBanner, flavor: .databend)) #expect(MySQLServerVersion.hasGenerationExpression(banner: "8.0.11-TiDB-v7.5.1", flavor: .tidb(version: nil))) + #expect(MySQLServerVersion.hasGenerationExpression( + banner: "5.7.25-OceanBase-v4.2.1", + flavor: .oceanbase(version: MySQLEngineVersion(major: 4, minor: 2, patch: 1)) + )) + #expect(!MySQLServerVersion.hasGenerationExpression( + banner: "5.7.25 OceanBase 3.1.3", + flavor: .oceanbase(version: MySQLEngineVersion(major: 3, minor: 1, patch: 3)) + )) + #expect(!MySQLServerVersion.hasGenerationExpression( + banner: "5.7.25", + flavor: .oceanbase(version: nil) + )) + #expect(MySQLServerVersion.hasCheckConstraints( + banner: "5.7.25-OceanBase-v4.2.1", + flavor: .oceanbase(version: MySQLEngineVersion(major: 4, minor: 0, patch: 0)) + )) + #expect(!MySQLServerVersion.hasCheckConstraints( + banner: "5.7.25 OceanBase 3.1.3", + flavor: .oceanbase(version: MySQLEngineVersion(major: 3, minor: 1, patch: 3)) + )) } } diff --git a/TableProTests/Plugins/OceanBaseHiddenPrimaryKeyTests.swift b/TableProTests/Plugins/OceanBaseHiddenPrimaryKeyTests.swift new file mode 100644 index 0000000000..5a2c2fb78b --- /dev/null +++ b/TableProTests/Plugins/OceanBaseHiddenPrimaryKeyTests.swift @@ -0,0 +1,53 @@ +import Foundation +import TableProPluginKit +import Testing + +@Suite("OceanBase hidden primary key") +struct OceanBaseHiddenPrimaryKeyTests { + @Test("A SHOW INDEX PRIMARY column missing from SHOW COLUMNS is attached as BIGINT PK") + func attachesHiddenPrimary() { + let visible = [ + PluginColumnInfo(name: "name", dataType: "VARCHAR(32)", isNullable: true, isPrimaryKey: false) + ] + let attached = OceanBaseHiddenPrimaryKey.attaching( + to: visible, + primaryIndexColumns: ["__pk_increment"] + ) + #expect(attached.map(\.name) == ["name", "__pk_increment"]) + let hidden = attached[1] + #expect(hidden.isPrimaryKey) + #expect(hidden.dataType == "BIGINT") + #expect(hidden.identityKind == .always) + #expect(!hidden.isNullable) + } + + @Test("A visible primary key is left alone") + func visiblePrimaryIsUnchanged() { + let visible = [ + PluginColumnInfo(name: "id", dataType: "INT", isNullable: false, isPrimaryKey: true), + PluginColumnInfo(name: "name", dataType: "VARCHAR(32)", isNullable: true, isPrimaryKey: false) + ] + let attached = OceanBaseHiddenPrimaryKey.attaching( + to: visible, + primaryIndexColumns: ["id"] + ) + #expect(attached.map(\.name) == ["id", "name"]) + } + + @Test("An already-visible hidden name is not duplicated") + func doesNotDuplicate() { + let visible = [ + PluginColumnInfo( + name: "__pk_increment", + dataType: "BIGINT", + isNullable: false, + isPrimaryKey: true + ) + ] + let attached = OceanBaseHiddenPrimaryKey.attaching( + to: visible, + primaryIndexColumns: ["__pk_increment"] + ) + #expect(attached.count == 1) + } +} diff --git a/TableProTests/Plugins/OceanBaseSQLTests.swift b/TableProTests/Plugins/OceanBaseSQLTests.swift new file mode 100644 index 0000000000..ce91f19c16 --- /dev/null +++ b/TableProTests/Plugins/OceanBaseSQLTests.swift @@ -0,0 +1,94 @@ +import Foundation +import Testing + +@Suite("OceanBase SQL rewrite") +struct OceanBaseSQLTests { + private func quote(_ name: String) -> String { + "`\(name.replacingOccurrences(of: "`", with: "``"))`" + } + + @Test("The visibility hint sits after the first verb") + func hintFollowsTheVerb() { + #expect( + OceanBaseSQL.withHiddenColumnVisibilityHint("SELECT * FROM t") + == "SELECT \(OceanBaseSQL.visibilityHint) * FROM t" + ) + #expect( + OceanBaseSQL.withHiddenColumnVisibilityHint("UPDATE t SET a = 1 WHERE b = 2") + == "UPDATE \(OceanBaseSQL.visibilityHint) t SET a = 1 WHERE b = 2" + ) + #expect( + OceanBaseSQL.withHiddenColumnVisibilityHint("DELETE FROM t WHERE id = 1") + == "DELETE \(OceanBaseSQL.visibilityHint) FROM t WHERE id = 1" + ) + } + + @Test("SHOW, SET and KILL are left alone") + func sessionCommandsAreNotHinted() { + for sql in ["SHOW FULL COLUMNS FROM t", "SET SESSION max_execution_time = 1000", "KILL QUERY 42"] { + #expect(OceanBaseSQL.withHiddenColumnVisibilityHint(sql) == sql) + } + } + + @Test("A statement that already carries the hint is not hinted again") + func existingHintIsKept() { + let sql = "SELECT \(OceanBaseSQL.visibilityHint) `__pk_increment` FROM t LIMIT 0" + #expect(OceanBaseSQL.withHiddenColumnVisibilityHint(sql) == sql) + } + + @Test("SELECT * from a table expands with hidden primary key columns") + func selectStarProjectsHiddenKeys() { + let rewritten = OceanBaseSQL.projectingHiddenPrimaryKeys( + sql: "SELECT * FROM orders", + hiddenColumns: ["__pk_increment"], + quote: quote + ) + #expect(rewritten == "SELECT \(OceanBaseSQL.visibilityHint) *, `__pk_increment` FROM orders") + } + + @Test("SELECT * from a subquery is not expanded") + func subquerySelectStarIsNotExpanded() { + let sql = "SELECT * FROM (SELECT 1) AS x" + #expect(OceanBaseSQL.simpleSelectStarTable(from: sql) == nil) + #expect( + OceanBaseSQL.projectingHiddenPrimaryKeys(sql: sql, hiddenColumns: ["__pk_increment"], quote: quote) + == "SELECT \(OceanBaseSQL.visibilityHint) * FROM (SELECT 1) AS x" + ) + } + + @Test("A qualified identifier keeps the table name, not the schema") + func qualifiedTableName() { + #expect(OceanBaseSQL.simpleSelectStarTable(from: "SELECT * FROM `test`.`orders`") == "orders") + #expect(OceanBaseSQL.simpleSelectStarTable(from: "select * from orders WHERE 1") == "orders") + } + + @Test("Hidden primary key names are the ones SHOW INDEX lists that SHOW COLUMNS omits") + func hiddenNamesComeFromThePrimaryIndex() { + #expect( + OceanBaseSQL.hiddenPrimaryKeyColumns( + primaryIndexColumns: ["__pk_increment"], + visibleColumnNames: ["id", "name"] + ) == ["__pk_increment"] + ) + #expect( + OceanBaseSQL.hiddenPrimaryKeyColumns( + primaryIndexColumns: ["id"], + visibleColumnNames: ["id", "name"] + ).isEmpty + ) + #expect( + OceanBaseSQL.hiddenPrimaryKeyColumns( + primaryIndexColumns: ["__pk_increment", "__pk_cluster_column"], + visibleColumnNames: ["name"] + ) == ["__pk_increment", "__pk_cluster_column"] + ) + } + + @Test("The documented probe names a hidden column under the visibility hint") + func documentedProbe() { + #expect( + OceanBaseSQL.documentedHiddenColumnProbe(table: "orders", column: "__pk_increment", quote: quote) + == "SELECT \(OceanBaseSQL.visibilityHint) `__pk_increment` FROM `orders` LIMIT 0" + ) + } +} diff --git a/TableProTests/Views/Structure/StructureColumnFieldRegistrationTests.swift b/TableProTests/Views/Structure/StructureColumnFieldRegistrationTests.swift index f530ce4ade..1dbb346296 100644 --- a/TableProTests/Views/Structure/StructureColumnFieldRegistrationTests.swift +++ b/TableProTests/Views/Structure/StructureColumnFieldRegistrationTests.swift @@ -20,11 +20,13 @@ struct StructureColumnFieldRegistrationTests { let mysql = PluginManager.shared.structureColumnFields(for: .mysql) let mariadb = PluginManager.shared.structureColumnFields(for: .mariadb) let tidb = PluginManager.shared.structureColumnFields(for: .tidb) + let oceanbase = PluginManager.shared.structureColumnFields(for: .oceanbase) #expect(Set(mysql) == Set(mariadb)) #expect(Set(mysql) == Set(tidb)) + #expect(Set(mysql) == Set(oceanbase)) } - @Test("MySQL-protocol engines with on update offer it", arguments: [DatabaseType.mysql, .mariadb, .tidb]) + @Test("MySQL-protocol engines with on update offer it", arguments: [DatabaseType.mysql, .mariadb, .tidb, .oceanbase]) func onUpdateIsOffered(databaseType: DatabaseType) { #expect(PluginManager.shared.structureColumnFields(for: databaseType).contains(.onUpdate)) } diff --git a/docs/connections/connection-form.mdx b/docs/connections/connection-form.mdx index adf4952cea..82deff0965 100644 --- a/docs/connections/connection-form.mdx +++ b/docs/connections/connection-form.mdx @@ -111,6 +111,7 @@ Metadata connections, the extra ones TablePro opens to read a database's object | [MariaDB](/databases/mariadb) | 3306 | Yes | Yes | Yes | No | Yes | Yes | | [TiDB](/databases/tidb) | 4000 | Yes | Yes | Yes | No | Yes | Yes | | [Databend](/databases/databend) | 3307 | Yes | Yes | Yes | No | Yes | Yes | +| [OceanBase](/databases/oceanbase) | 2881 | Yes | Yes | Yes | No | Yes | Yes | | [PostgreSQL](/databases/postgresql) | 5432 | Yes | Yes | Yes | Yes | Yes | Yes | | [Amazon Redshift](/databases/redshift) | 5439 | Yes | Yes | Yes | No | Yes | Yes | | [CockroachDB](/databases/cockroachdb) | 26257 | Yes | Yes | Yes | No | Yes | Yes | diff --git a/docs/connections/urls.mdx b/docs/connections/urls.mdx index b2cc1cc16a..8ec370e575 100644 --- a/docs/connections/urls.mdx +++ b/docs/connections/urls.mdx @@ -19,6 +19,7 @@ Two readers take these URLs, and not the same set. The **Import from URL…** sh | `mysql://` | MySQL | Yes | | `mariadb://` | MariaDB | Yes | | `tidb://` | TiDB | Yes | +| `oceanbase://` | OceanBase | Yes | | `sqlite://` | SQLite | Yes | | `mongodb://` | MongoDB | Yes | | `mongodb+srv://` | MongoDB (SRV) | Yes | diff --git a/docs/databases/index.mdx b/docs/databases/index.mdx index c0d2e822b9..4d8db69d1a 100644 --- a/docs/databases/index.mdx +++ b/docs/databases/index.mdx @@ -1,11 +1,11 @@ --- title: Supported Databases -description: All 34 engines TablePro connects to, their default ports, and which ones need a plugin +description: All 35 engines TablePro connects to, their default ports, and which ones need a plugin --- import DriverCounts from "/snippets/driver-counts.mdx"; -Thirty-four engines, and every one of them is free to use. What differs between them is where the +Thirty-five engines, and every one of them is free to use. What differs between them is where the driver comes from, not what the license covers. @@ -34,6 +34,7 @@ driver comes from, not what the license covers. | [Microsoft SQL Server](/databases/mssql) | 1433 | Plugin | | [MongoDB](/databases/mongodb) | 27017 | Plugin | | [MySQL](/databases/mysql) | 3306 | Built-in | +| [OceanBase](/databases/oceanbase) | 2881 | Built-in | | [Oracle Database](/databases/oracle) | 1521 | Plugin | | [PGlite](/databases/pglite) | 5432 | Built-in | | [PostgreSQL](/databases/postgresql) | 5432 | Built-in | @@ -50,8 +51,8 @@ driver comes from, not what the license covers. | [Turso](/databases/libsql) | API-based | Plugin | Rows sharing a page share a driver. MariaDB reads as MySQL, ScyllaDB as Cassandra, Turso as libSQL, -and Redshift, CockroachDB and PGlite all speak the PostgreSQL wire protocol. TiDB and Databend -also run on the bundled MySQL driver. +and Redshift, CockroachDB and PGlite all speak the PostgreSQL wire protocol. TiDB, Databend and +OceanBase also run on the bundled MySQL driver. ## Built-in against plugin diff --git a/docs/databases/mysql.mdx b/docs/databases/mysql.mdx index a930f51cef..78842a350f 100644 --- a/docs/databases/mysql.mdx +++ b/docs/databases/mysql.mdx @@ -3,7 +3,7 @@ title: MySQL description: Connect to MySQL 5.7 and later with the bundled MariaDB Connector/C driver --- -MySQL 8 accounts on `caching_sha2_password` connect on the first try, with no auth plugin to switch over. The same bundled driver covers 5.7 and later, plus [MariaDB](/databases/mariadb), [TiDB](/databases/tidb), and [Databend](/databases/databend). +MySQL 8 accounts on `caching_sha2_password` connect on the first try, with no auth plugin to switch over. The same bundled driver covers 5.7 and later, plus [MariaDB](/databases/mariadb), [TiDB](/databases/tidb), [Databend](/databases/databend), and [OceanBase](/databases/oceanbase). ## Quick setup diff --git a/docs/databases/oceanbase.mdx b/docs/databases/oceanbase.mdx new file mode 100644 index 0000000000..be783601ef --- /dev/null +++ b/docs/databases/oceanbase.mdx @@ -0,0 +1,59 @@ +--- +title: OceanBase +description: Connect to OceanBase MySQL mode through the bundled MySQL driver on port 2881 +--- + +Sign in as `user@tenant`. The sys tenant's root is `root@sys`. Oracle compatibility mode is a different protocol and does not connect. + +No minimum OceanBase version is enforced. Host, password, SSH tunnels, SSL/TLS and `Cmd+K` database switching work as on [MySQL](/databases/mysql). + +## Connection settings + +| Field | Default | Notes | +|-------|---------|-------| +| **Port** | `2881` | The SQL port for MySQL mode. Do not point at an OBProxy extras port unless that is the SQL listener | +| **Database** | empty | Optional. Leave it empty to browse every database in the tenant | +| **SSL Mode** | Preferred | TLS first, plain text if the server refuses | +| **Username** | empty | `user@tenant`. In a URL, write the `@` as `%40`: `root%40sys` | + +**Release the Server Connection After** is available under Advanced. AWS IAM, Cloud SQL Auth Proxy and Unix socket are not offered; reach a private cluster through an [SSH tunnel](/connections/ssh-tunneling). + +## Connection URL + +```text +oceanbase://root%40sys:password@host:2881/database +``` + +`oceanbase+ssh://` opens it through an SSH tunnel. See [Connection URL Reference](/connections/urls). + +## Hidden primary keys + +A table with no explicit primary key still has one: `__pk_increment`, and on some clusters `__pk_cluster_column`. `SHOW FULL COLUMNS` and a plain `SELECT *` omit those names, so a grid save that matches on visible columns cannot find the row. + +Opening the table projects the hidden key into the result. Stop and parameterized `UPDATE` / `DELETE` then match on it. The column is not editable. + +A connection saved as **MySQL** that reaches an OceanBase server takes the same path. The sidebar, type picker and EXPLAIN follow the connection type, so choose **OceanBase** for those. + +## What the MySQL driver does not copy + +- The sidebar hides `information_schema`, `mysql` and `oceanbase`. User databases such as `test` stay listed. +- **Stop** sends `KILL QUERY` for `CONNECTION_ID()`, which is wider than the 32-bit handshake thread id. +- `EXPLAIN` is plain text. `EXPLAIN FORMAT=JSON` is not offered. +- The type picker has MySQL's types without the Spatial group. +- [Users & Roles](/features/users-roles) has no connection limit field. +- Table Maintenance offers `ANALYZE TABLE` only. +- Foreign keys can be created. `SET FOREIGN_KEY_CHECKS` is not sent. Triggers appear in the Structure tab; adding one from there is not offered. + +## Limitations + +- Oracle compatibility mode does not connect. Use a MySQL-mode tenant and the MySQL protocol port. +- No Server Dashboard, and **File > Backup Dump…** stays dimmed. +- [Compare & Sync](/features/compare-sync) writes no structure script between OceanBase and MySQL or MariaDB. OceanBase against OceanBase works. +- Cluster tenant administration is out of scope. + +## Related + +- [MySQL](/databases/mysql), for connection fields, SSL/TLS, and troubleshooting +- [MariaDB](/databases/mariadb) +- [TiDB](/databases/tidb) +- [SSH Tunneling](/connections/ssh-tunneling) diff --git a/docs/docs.json b/docs/docs.json index 43abd690e3..a10fea0e07 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -164,6 +164,7 @@ "databases/mssql", "databases/mongodb", "databases/mysql", + "databases/oceanbase", "databases/oracle", "databases/pglite", "databases/postgresql", diff --git a/docs/index.mdx b/docs/index.mdx index 4f67682ea0..062214abf9 100644 --- a/docs/index.mdx +++ b/docs/index.mdx @@ -1,6 +1,6 @@ --- title: Introduction -description: Native macOS database client for MySQL, PostgreSQL, SQLite, MongoDB, Redis, and 29 more +description: Native macOS database client for MySQL, PostgreSQL, SQLite, MongoDB, Redis, and 30 more --- import DriverCounts from "/snippets/driver-counts.mdx"; diff --git a/docs/snippets/driver-counts.mdx b/docs/snippets/driver-counts.mdx index 36442e09d9..a6c7ae26f2 100644 --- a/docs/snippets/driver-counts.mdx +++ b/docs/snippets/driver-counts.mdx @@ -1,3 +1,3 @@ -Five drivers ship inside the app and cover eleven databases. Twenty-one registry plugins cover the +Five drivers ship inside the app and cover twelve databases. Twenty-one registry plugins cover the other twenty-three and install on the first connection that needs one. See [Plugins & Themes](/features/plugins). diff --git a/project.yml b/project.yml index e08d09fabc..35c34f4d56 100644 --- a/project.yml +++ b/project.yml @@ -498,6 +498,8 @@ targets: - Plugins/MySQLDriverPlugin/DatabendLiteral.swift - Plugins/MySQLDriverPlugin/DatabendResultShape.swift - Plugins/MySQLDriverPlugin/TiDBCheckConstraints.swift + - Plugins/MySQLDriverPlugin/OceanBaseSQL.swift + - Plugins/MySQLDriverPlugin/OceanBaseHiddenPrimaryKey.swift - Plugins/SQLiteDriverPlugin/SQLiteCheckConstraintParser.swift - Plugins/SQLiteDriverPlugin/SQLiteCreateTableDDL.swift - Plugins/SQLiteDriverPlugin/SQLiteDefaultValue.swift From 432ea6080822701864d106af467b596e91802ec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Fri, 11 Sep 2026 23:32:00 +0700 Subject: [PATCH 05/54] fix(plugin-postgresql): pin client_encoding to UTF8 in the startup packet on macOS and iOS, and declare it in SQL exports (#2743) * fix(plugin-postgresql): pin client_encoding to UTF8 in the startup packet and stop reading invalid UTF-8 as Latin 1 Claude-Session: https://claude.ai/code/session_01U7kkDGsR4M4v9NWiycc97U * fix(ios): pin client_encoding to UTF8 in the PostgreSQL connection string Claude-Session: https://claude.ai/code/session_01U7kkDGsR4M4v9NWiycc97U * fix(plugin-postgresql): open every PostgreSQL SQL export part with SET client_encoding = 'UTF8' Claude-Session: https://claude.ai/code/session_01U7kkDGsR4M4v9NWiycc97U --- CHANGELOG.md | 3 + .../LibPQCellDecoding.swift | 29 +++++ .../LibPQConnectionString.swift | 66 +++++++++++ .../LibPQPluginConnection.swift | 74 ++++-------- .../SQLExportEncodingDeclaration.swift | 19 ++- Plugins/SQLExportPlugin/SQLExportPlugin.swift | 2 +- .../Drivers/PostgreSQLConnectionString.swift | 2 + .../PostgreSQLConnectionStringTests.swift | 5 + .../Plugins/LibPQCellDecodingTests.swift | 61 ++++++++++ .../Plugins/LibPQConnectionStringTests.swift | 111 ++++++++++++++++++ .../Plugins/SQLExportEncodingTests.swift | 71 ++++++++--- docs/databases/postgresql.mdx | 6 + docs/features/import-export.mdx | 10 +- project.yml | 2 + scripts/check-postgres-client-encoding.sh | 103 ++++++++++++++++ 15 files changed, 490 insertions(+), 74 deletions(-) create mode 100644 Plugins/PostgreSQLDriverPlugin/LibPQCellDecoding.swift create mode 100644 Plugins/PostgreSQLDriverPlugin/LibPQConnectionString.swift create mode 100644 TableProTests/Plugins/LibPQCellDecodingTests.swift create mode 100644 TableProTests/Plugins/LibPQConnectionStringTests.swift create mode 100755 scripts/check-postgres-client-encoding.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 2447a90ef5..e76c7939f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -133,6 +133,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `Illegal mix of collations` comparing a column with a user variable on MySQL 8. - GEOMETRY values from a parameterized MySQL query shown as raw bytes. - Earlier row's text repeated in later rows of a parameterized MySQL query once a value passed 64 KB. +- Garbled non-ASCII text on PostgreSQL databases not encoded in UTF-8 after `RESET ALL` or `DISCARD ALL`. +- Garbled or double-encoded non-ASCII text on iOS with PostgreSQL databases not encoded in UTF-8. +- Garbled non-ASCII text when restoring a PostgreSQL SQL export into a database not encoded in UTF-8. ### Security diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQCellDecoding.swift b/Plugins/PostgreSQLDriverPlugin/LibPQCellDecoding.swift new file mode 100644 index 0000000000..efe2ae6e44 --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/LibPQCellDecoding.swift @@ -0,0 +1,29 @@ +// +// LibPQCellDecoding.swift +// PostgreSQLDriverPlugin +// + +import Foundation +import TableProPluginKit + +internal enum LibPQCellDecoding { + private static let booleanOid: UInt32 = 16 + private static let byteaOid: UInt32 = 17 + + static func value(from bytes: UnsafeRawBufferPointer, oid: UInt32) -> PluginCellValue { + let text = text(from: bytes) + switch oid { + case byteaOid: + guard let data = LibPQByteaDecoder.decode(text) else { return .text(text) } + return .bytes(data) + case booleanOid: + return .text(text == "t" ? "true" : "false") + default: + return .text(text) + } + } + + static func text(from bytes: UnsafeRawBufferPointer) -> String { + String(decoding: bytes, as: UTF8.self) // swiftlint:disable:this optional_data_string_conversion + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQConnectionString.swift b/Plugins/PostgreSQLDriverPlugin/LibPQConnectionString.swift new file mode 100644 index 0000000000..a06fc2514b --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/LibPQConnectionString.swift @@ -0,0 +1,66 @@ +// +// LibPQConnectionString.swift +// PostgreSQLDriverPlugin +// + +import Foundation +import TableProPluginKit + +internal enum LibPQConnectionString { + static let clientEncoding = "UTF8" + + private static let clientEncodingNames: Set = ["UTF8", "UNICODE"] + + static func build( + host: String, + port: Int, + user: String, + password: String?, + database: String, + sslConfig: SSLConfiguration, + options: String? + ) -> String { + var parameters: [(String, String)] = [ + ("host", host), + ("port", String(port)), + ("dbname", database) + ] + + if !user.isEmpty { + parameters.append(("user", user)) + } + if let password, !password.isEmpty { + parameters.append(("password", password)) + } + + parameters.append(("sslmode", LibPQSSLMapping.sslmode(for: sslConfig.mode))) + if sslConfig.verifiesCertificate, !sslConfig.caCertificatePath.isEmpty { + parameters.append(("sslrootcert", sslConfig.caCertificatePath)) + } + if !sslConfig.clientCertificatePath.isEmpty { + parameters.append(("sslcert", sslConfig.clientCertificatePath)) + } + if !sslConfig.clientKeyPath.isEmpty { + parameters.append(("sslkey", sslConfig.clientKeyPath)) + } + + parameters.append(("client_encoding", clientEncoding)) + if let options, !options.isEmpty { + parameters.append(("options", options)) + } + + return parameters + .map { "\($0.0)='\(escape($0.1))'" } + .joined(separator: " ") + } + + static func isClientEncoding(reportedByServer reported: String?) -> Bool { + guard let reported else { return false } + return clientEncodingNames.contains(reported.uppercased()) + } + + static func escape(_ value: String) -> String { + value.replacingOccurrences(of: "\\", with: "\\\\") + .replacingOccurrences(of: "'", with: "\\'") + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift b/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift index 3326feda18..df6e9dc16c 100644 --- a/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift +++ b/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift @@ -200,7 +200,7 @@ final class LibPQPluginConnection: @unchecked Sendable { } private func performConnect(reportingStage report: @escaping ConnectionStageReporter) throws { - guard let connection = buildConnectionString().withCString({ PQconnectStart($0) }) else { + guard let connection = connectionString.withCString({ PQconnectStart($0) }) else { throw LibPQPluginError.connectionFailed } @@ -299,10 +299,7 @@ final class LibPQPluginConnection: @unchecked Sendable { } private func configureEstablishedConnection(_ connection: OpaquePointer) { - "SET client_encoding TO 'UTF8'".withCString { cStr in - let result = PQexec(connection, cStr) - PQclear(result) - } + logUnexpectedClientEncoding(of: connection) let version = PQserverVersion(connection) guard version > 0 else { return } @@ -319,39 +316,24 @@ final class LibPQPluginConnection: @unchecked Sendable { } } - private func buildConnectionString() -> String { - func escapeConnParam(_ value: String) -> String { - value.replacingOccurrences(of: "\\", with: "\\\\") - .replacingOccurrences(of: "'", with: "\\'") - } - - var connStr = "host='\(escapeConnParam(host))' port='\(port)' dbname='\(escapeConnParam(database))'" - - if !user.isEmpty { - connStr += " user='\(escapeConnParam(user))'" - } - - if let password, !password.isEmpty { - connStr += " password='\(escapeConnParam(password))'" - } - - connStr += " sslmode='\(LibPQSSLMapping.sslmode(for: sslConfig.mode))'" - - if sslConfig.verifiesCertificate, !sslConfig.caCertificatePath.isEmpty { - connStr += " sslrootcert='\(escapeConnParam(sslConfig.caCertificatePath))'" - } - if !sslConfig.clientCertificatePath.isEmpty { - connStr += " sslcert='\(escapeConnParam(sslConfig.clientCertificatePath))'" - } - if !sslConfig.clientKeyPath.isEmpty { - connStr += " sslkey='\(escapeConnParam(sslConfig.clientKeyPath))'" - } - - if let options, !options.isEmpty { - connStr += " options='\(escapeConnParam(options))'" - } + private func logUnexpectedClientEncoding(of connection: OpaquePointer) { + let reported = PQparameterStatus(connection, "client_encoding").map { String(cString: $0) } + guard !LibPQConnectionString.isClientEncoding(reportedByServer: reported) else { return } + logger.warning( + "Server reports client_encoding \(reported ?? "none", privacy: .public) instead of UTF8" + ) + } - return connStr + private var connectionString: String { + LibPQConnectionString.build( + host: host, + port: port, + user: user, + password: password, + database: database, + sslConfig: sslConfig, + options: options + ) } func disconnect() { @@ -1128,7 +1110,7 @@ final class LibPQPluginConnection: @unchecked Sendable { } else if let valuePtr = PQgetvalue(result, Int32(rowIndex), 0) { let length = Int(PQgetlength(result, Int32(rowIndex), 0)) let bufferPtr = UnsafeRawBufferPointer(start: valuePtr, count: length) - converted.append(.text(String(bytes: bufferPtr, encoding: .utf8) ?? "")) + converted.append(.text(LibPQCellDecoding.text(from: bufferPtr))) } else { converted.append(.null) } @@ -1148,21 +1130,7 @@ final class LibPQPluginConnection: @unchecked Sendable { } let length = Int(PQgetlength(result, row, column)) - let bufferPtr = UnsafeRawBufferPointer(start: valuePtr, count: length) - - if oid == 17 { - let text = String(bytes: bufferPtr, encoding: .utf8) ?? "" - guard let data = LibPQByteaDecoder.decode(text) else { return .text(text) } - return .bytes(data) - } - - if oid == 16 { - let str = String(bytes: bufferPtr, encoding: .utf8) ?? "" - return .text(str == "t" ? "true" : "false") - } - - if let str = String(bytes: bufferPtr, encoding: .utf8) { return .text(str) } - return .text(String(bytes: bufferPtr, encoding: .isoLatin1) ?? "") + return LibPQCellDecoding.value(from: UnsafeRawBufferPointer(start: valuePtr, count: length), oid: oid) } private func parseRows( diff --git a/Plugins/SQLExportPlugin/SQLExportEncodingDeclaration.swift b/Plugins/SQLExportPlugin/SQLExportEncodingDeclaration.swift index 2f5dc785fa..ec0e4acaa9 100644 --- a/Plugins/SQLExportPlugin/SQLExportEncodingDeclaration.swift +++ b/Plugins/SQLExportPlugin/SQLExportEncodingDeclaration.swift @@ -12,10 +12,16 @@ internal struct SQLExportEncodingDeclaration: Equatable { let prologue: String let epilogue: String - static func forDialect(_ dialect: SqlDialect) -> SQLExportEncodingDeclaration { - switch dialect { + private static let typesAcceptingSetClientEncoding: Set = [ + "PostgreSQL", "Greenplum", "AlloyDB", "Citus", "CockroachDB", "PGlite" + ] + + static func forDatabaseType(_ databaseTypeId: String) -> SQLExportEncodingDeclaration { + switch SqlDialect.from(databaseTypeId: databaseTypeId) { case .mysql: return mysql + case .postgres where typesAcceptingSetClientEncoding.contains(databaseTypeId): + return postgres default: return .empty } @@ -39,4 +45,13 @@ internal struct SQLExportEncodingDeclaration: Equatable { """ ) + + private static let postgres = SQLExportEncodingDeclaration( + prologue: """ + SET client_encoding = 'UTF8'; + + + """, + epilogue: "" + ) } diff --git a/Plugins/SQLExportPlugin/SQLExportPlugin.swift b/Plugins/SQLExportPlugin/SQLExportPlugin.swift index ab5b969155..0d89712688 100644 --- a/Plugins/SQLExportPlugin/SQLExportPlugin.swift +++ b/Plugins/SQLExportPlugin/SQLExportPlugin.swift @@ -142,7 +142,7 @@ final class SQLExportPlugin: ExportFormatPlugin, SettablePlugin, @unchecked Send let writer = try SQLExportFileWriter( destination: actualDestination, splitSizeMegabytes: splitSize, - encodingDeclaration: .forDialect(SqlDialect.from(databaseTypeId: dataSource.databaseTypeId)) + encodingDeclaration: .forDatabaseType(dataSource.databaseTypeId) ) var committed = false defer { diff --git a/TableProMobile/TableProMobile/Drivers/PostgreSQLConnectionString.swift b/TableProMobile/TableProMobile/Drivers/PostgreSQLConnectionString.swift index fb6d97b91e..38101239c5 100644 --- a/TableProMobile/TableProMobile/Drivers/PostgreSQLConnectionString.swift +++ b/TableProMobile/TableProMobile/Drivers/PostgreSQLConnectionString.swift @@ -2,6 +2,7 @@ import Foundation nonisolated enum PostgreSQLConnectionString { static let connectTimeoutSeconds = 10 + static let clientEncoding = "UTF8" static func build( host: String, @@ -19,6 +20,7 @@ nonisolated enum PostgreSQLConnectionString { ("password", password), ("connect_timeout", String(connectTimeoutSeconds)), ("sslmode", ssl.postgresSSLMode), + ("client_encoding", clientEncoding), ] if let caPath = ssl.existingCACertificatePath { diff --git a/TableProMobile/TableProMobileTests/Drivers/PostgreSQLConnectionStringTests.swift b/TableProMobile/TableProMobileTests/Drivers/PostgreSQLConnectionStringTests.swift index c447a9d329..a82e087ba7 100644 --- a/TableProMobile/TableProMobileTests/Drivers/PostgreSQLConnectionStringTests.swift +++ b/TableProMobile/TableProMobileTests/Drivers/PostgreSQLConnectionStringTests.swift @@ -34,6 +34,11 @@ struct PostgreSQLConnectionStringTests { #expect(connStr.contains("sslmode='disable'")) } + @Test("the session is pinned to UTF8 in the startup packet, whatever the database's encoding") + func pinsClientEncoding() { + #expect(build(ssl: .disabled).contains("client_encoding='UTF8'")) + } + @Test("a client certificate and key reach libpq as sslcert and sslkey") func clientCertificateIsSent() { let certPath = temporaryFile() diff --git a/TableProTests/Plugins/LibPQCellDecodingTests.swift b/TableProTests/Plugins/LibPQCellDecodingTests.swift new file mode 100644 index 0000000000..11a9ea7337 --- /dev/null +++ b/TableProTests/Plugins/LibPQCellDecodingTests.swift @@ -0,0 +1,61 @@ +// +// LibPQCellDecodingTests.swift +// TableProTests +// + +import Foundation +import TableProPluginKit +import Testing + +@Suite("LibPQCellDecoding") +struct LibPQCellDecodingTests { + private static let textOid: UInt32 = 25 + private static let booleanOid: UInt32 = 16 + private static let byteaOid: UInt32 = 17 + + private func decode(_ bytes: [UInt8], oid: UInt32 = textOid) -> PluginCellValue { + bytes.withUnsafeBytes { LibPQCellDecoding.value(from: $0, oid: oid) } + } + + @Test("UTF-8 text decodes as written") + func utf8Text() { + #expect(decode(Array("メール café".utf8)) == .text("メール café")) + } + + @Test("Bytes that are not UTF-8 become replacement characters, never Latin 1 guesses") + func invalidUTF8IsNotFabricated() { + let eucJPMail: [UInt8] = [0xA5, 0xE1, 0xA1, 0xBC, 0xA5, 0xEB] + guard case .text(let text) = decode(eucJPMail) else { + Issue.record("expected text") + return + } + #expect(text.contains("\u{FFFD}")) + #expect(text != "¥á¡¼¥ë") + } + + @Test("A Latin 1 byte on its own is a replacement character, not é") + func latin1ByteIsReplaced() { + #expect(decode([0x63, 0x61, 0x66, 0xE9]) == .text("caf\u{FFFD}")) + } + + @Test("Empty text stays empty") + func emptyText() { + #expect(decode([]) == .text("")) + } + + @Test("Boolean t and f read as true and false") + func booleans() { + #expect(decode(Array("t".utf8), oid: Self.booleanOid) == .text("true")) + #expect(decode(Array("f".utf8), oid: Self.booleanOid) == .text("false")) + } + + @Test("bytea hex decodes to its bytes") + func byteaHex() { + #expect(decode(Array("\\xdeadbeef".utf8), oid: Self.byteaOid) == .bytes(Data([0xDE, 0xAD, 0xBE, 0xEF]))) + } + + @Test("A bytea value that is not in a bytea format stays text") + func byteaFallsBackToText() { + #expect(decode(Array("\\xzz".utf8), oid: Self.byteaOid) == .text("\\xzz")) + } +} diff --git a/TableProTests/Plugins/LibPQConnectionStringTests.swift b/TableProTests/Plugins/LibPQConnectionStringTests.swift new file mode 100644 index 0000000000..63b3f0f1b3 --- /dev/null +++ b/TableProTests/Plugins/LibPQConnectionStringTests.swift @@ -0,0 +1,111 @@ +// +// LibPQConnectionStringTests.swift +// TableProTests +// + +import Foundation +import TableProPluginKit +import Testing + +@Suite("LibPQConnectionString") +struct LibPQConnectionStringTests { + private func build( + user: String = "postgres", + password: String? = "hunter2", + sslConfig: SSLConfiguration = SSLConfiguration(), + options: String? = nil + ) -> String { + LibPQConnectionString.build( + host: "db.example.com", + port: 5_432, + user: user, + password: password, + database: "app", + sslConfig: sslConfig, + options: options + ) + } + + @Test("The base parameters are always present") + func baseParameters() { + let conninfo = build() + + #expect(conninfo.contains("host='db.example.com'")) + #expect(conninfo.contains("port='5432'")) + #expect(conninfo.contains("dbname='app'")) + #expect(conninfo.contains("user='postgres'")) + #expect(conninfo.contains("password='hunter2'")) + #expect(conninfo.contains("sslmode='disable'")) + } + + @Test("The session is pinned to UTF8 in the startup packet, so RESET ALL and DISCARD ALL keep it") + func pinsClientEncoding() { + #expect(build().contains("client_encoding='UTF8'")) + } + + @Test("Connection options still reach the server, after the pinned encoding") + func optionsFollowTheEncoding() { + let conninfo = build(options: "--cluster=my-cluster -c search_path=app") + + #expect(conninfo.hasSuffix("client_encoding='UTF8' options='--cluster=my-cluster -c search_path=app'")) + } + + @Test("A client_encoding in the connection options rides along in options, where the server applies it first") + func clientEncodingInOptionsStaysInOptions() { + let conninfo = build(options: "-c client_encoding=LATIN1") + + #expect(conninfo.contains("client_encoding='UTF8'")) + #expect(conninfo.contains("options='-c client_encoding=LATIN1'")) + } + + @Test("An empty user, password or options is left out") + func emptyValuesAreOmitted() { + let conninfo = build(user: "", password: "", options: "") + + #expect(!conninfo.contains("user=")) + #expect(!conninfo.contains("password=")) + #expect(!conninfo.contains("options=")) + #expect(conninfo.contains("client_encoding='UTF8'")) + } + + @Test("A CA certificate is sent only when the mode verifies it") + func caOnlyWhenVerifying() { + let requiring = build(sslConfig: SSLConfiguration(mode: .required, caCertificatePath: "/ca.pem")) + #expect(!requiring.contains("sslrootcert")) + + let verifying = build(sslConfig: SSLConfiguration(mode: .verifyCa, caCertificatePath: "/ca.pem")) + #expect(verifying.contains("sslmode='verify-ca'")) + #expect(verifying.contains("sslrootcert='/ca.pem'")) + } + + @Test("A client certificate and key reach libpq as sslcert and sslkey") + func clientCertificateIsSent() { + let conninfo = build(sslConfig: SSLConfiguration( + mode: .required, + clientCertificatePath: "/client.pem", + clientKeyPath: "/client.key" + )) + + #expect(conninfo.contains("sslcert='/client.pem'")) + #expect(conninfo.contains("sslkey='/client.key'")) + } + + @Test("Quotes and backslashes in values are escaped") + func escapesValues() { + let conninfo = build(user: "o'brien", password: "back\\slash", options: "-c application_name='x'") + + #expect(conninfo.contains("user='o\\'brien'")) + #expect(conninfo.contains("password='back\\\\slash'")) + #expect(conninfo.contains("options='-c application_name=\\'x\\''")) + } + + @Test("UTF8 and its PostgreSQL 8.0 name UNICODE both count as the pinned encoding") + func recognizesReportedEncoding() { + #expect(LibPQConnectionString.isClientEncoding(reportedByServer: "UTF8")) + #expect(LibPQConnectionString.isClientEncoding(reportedByServer: "UNICODE")) + #expect(LibPQConnectionString.isClientEncoding(reportedByServer: "utf8")) + #expect(!LibPQConnectionString.isClientEncoding(reportedByServer: "EUC_JP")) + #expect(!LibPQConnectionString.isClientEncoding(reportedByServer: "SQL_ASCII")) + #expect(!LibPQConnectionString.isClientEncoding(reportedByServer: nil)) + } +} diff --git a/TableProTests/Plugins/SQLExportEncodingTests.swift b/TableProTests/Plugins/SQLExportEncodingTests.swift index 0b38016efd..e3096004d3 100644 --- a/TableProTests/Plugins/SQLExportEncodingTests.swift +++ b/TableProTests/Plugins/SQLExportEncodingTests.swift @@ -18,27 +18,60 @@ struct SQLExportEncodingTests { @Test("A MySQL dump declares utf8mb4 the way mysqldump does, and puts the session back") func mysqlDeclaresUTF8MB4() { - let declaration = SQLExportEncodingDeclaration.forDialect(.mysql) - #expect(declaration.prologue.contains("/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;")) - #expect(declaration.prologue.contains("/*!40101 SET NAMES utf8 */;")) - #expect(declaration.prologue.contains("/*!50503 SET NAMES utf8mb4 */;")) - #expect(declaration.epilogue.contains("/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;")) - #expect(declaration.epilogue.contains("/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;")) - #expect(declaration.epilogue.contains("/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;")) + for typeId in ["MySQL", "MariaDB", "TiDB"] { + let declaration = SQLExportEncodingDeclaration.forDatabaseType(typeId) + #expect(declaration.prologue.contains("/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;")) + #expect(declaration.prologue.contains("/*!40101 SET NAMES utf8 */;")) + #expect(declaration.prologue.contains("/*!50503 SET NAMES utf8mb4 */;")) + #expect(declaration.epilogue.contains("/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;")) + #expect(declaration.epilogue.contains("/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;")) + #expect(declaration.epilogue.contains("/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;")) + } } - @Test("Other dialects write no declaration") - func otherDialectsDeclareNothing() { - for dialect: SqlDialect in [.sqlite, .generic, .postgres] { - #expect(SQLExportEncodingDeclaration.forDialect(dialect) == .empty) + @Test("A PostgreSQL dump declares UTF8 the way pg_dump does, on every engine that accepts the statement") + func postgresDeclaresUTF8() { + for typeId in ["PostgreSQL", "Greenplum", "AlloyDB", "Citus", "CockroachDB", "PGlite"] { + let declaration = SQLExportEncodingDeclaration.forDatabaseType(typeId) + #expect(declaration.prologue == "SET client_encoding = 'UTF8';\n\n", "\(typeId)") + #expect(declaration.epilogue.isEmpty, "\(typeId)") } } + @Test("Redshift gets no declaration, because it does not document client_encoding as settable") + func redshiftDeclaresNothing() { + #expect(SQLExportEncodingDeclaration.forDatabaseType("Redshift") == .empty) + } + + @Test("Other engines write no declaration") + func otherEnginesDeclareNothing() { + for typeId in ["SQLite", "DuckDB", "Oracle", "MSSQL", "SomeFuturePlugin"] { + #expect(SQLExportEncodingDeclaration.forDatabaseType(typeId) == .empty, "\(typeId)") + } + } + + @Test("A PostgreSQL dump opens with the declaration and ends with the last statement") + func postgresDumpIsPrefixed() throws { + let directory = try temporaryDirectory() + defer { try? FileManager.default.removeItem(at: directory) } + let declaration = SQLExportEncodingDeclaration.forDatabaseType("PostgreSQL") + + let destination = directory.appendingPathComponent("dump.sql") + let writer = try SQLExportFileWriter( + destination: destination, splitSizeMegabytes: 0, encodingDeclaration: declaration + ) + try writer.write("INSERT INTO \"t\" VALUES ('メール');\n") + try writer.commit() + + let dump = try String(contentsOf: destination, encoding: .utf8) + #expect(dump == "SET client_encoding = 'UTF8';\n\nINSERT INTO \"t\" VALUES ('メール');\n") + } + @Test("An unsplit dump opens with the declaration and closes by restoring the session") func unsplitDumpIsWrapped() throws { let directory = try temporaryDirectory() defer { try? FileManager.default.removeItem(at: directory) } - let declaration = SQLExportEncodingDeclaration.forDialect(.mysql) + let declaration = SQLExportEncodingDeclaration.forDatabaseType("MySQL") let destination = directory.appendingPathComponent("dump.sql") let writer = try SQLExportFileWriter( @@ -51,11 +84,15 @@ struct SQLExportEncodingTests { #expect(dump == declaration.prologue + "INSERT INTO `t` VALUES ('メール');\n" + declaration.epilogue) } - @Test("Every part of a split dump carries its own declaration, so each restores on its own") - func everyPartIsWrapped() throws { + @Test( + "Every part of a split dump carries its own declaration, so each restores on its own", + arguments: ["MySQL", "PostgreSQL"] + ) + func everyPartIsWrapped(databaseTypeId: String) throws { let directory = try temporaryDirectory() defer { try? FileManager.default.removeItem(at: directory) } - let declaration = SQLExportEncodingDeclaration.forDialect(.mysql) + let declaration = SQLExportEncodingDeclaration.forDatabaseType(databaseTypeId) + #expect(declaration != .empty) let destination = directory.appendingPathComponent("dump.sql") let writer = try SQLExportFileWriter( @@ -79,7 +116,7 @@ struct SQLExportEncodingTests { func epilogueCountsTowardTheCap() throws { let directory = try temporaryDirectory() defer { try? FileManager.default.removeItem(at: directory) } - let declaration = SQLExportEncodingDeclaration.forDialect(.mysql) + let declaration = SQLExportEncodingDeclaration.forDatabaseType("MySQL") let cap = 1_024 * 1_024 let destination = directory.appendingPathComponent("dump.sql") @@ -106,7 +143,7 @@ struct SQLExportEncodingTests { let destination = directory.appendingPathComponent("dump.sql") let writer = try SQLExportFileWriter( destination: destination, splitSizeMegabytes: 1, - encodingDeclaration: .forDialect(.mysql) + encodingDeclaration: .forDatabaseType("MySQL") ) try writer.write(String(repeating: "y", count: 2 * 1_024 * 1_024) + ";\n") let parts = try writer.commit() diff --git a/docs/databases/postgresql.mdx b/docs/databases/postgresql.mdx index d98bbd3dff..aa65eea563 100644 --- a/docs/databases/postgresql.mdx +++ b/docs/databases/postgresql.mdx @@ -70,6 +70,10 @@ Enums, composites, domains and ranges are listed under **Types** in each schema, PostgreSQL has no in-place `USE`, so a tab bound to a database other than the connection's active one runs on a second connection opened for that database. It shares no temp tables, session variables, or open transaction with the query editor on the main connection: keep a multi-statement transaction or a `CREATE TEMP TABLE` on tabs bound to one database. Binding itself is on [Tabs](/features/tabs#where-a-tab-points). +## Text encoding + +Sessions run in `UTF8` whatever encoding the database was created with, and the server converts text both ways. Japanese in an `EUC_JP` database or accented names in a `LATIN1` one read and save intact, and stay that way after `RESET ALL` or `DISCARD ALL` in a query tab. A `-c client_encoding=…` in **Connection Options** is overridden; other settings there still apply. + ## Tools `EXPLAIN` and `EXPLAIN ANALYZE` run with `FORMAT JSON` and render as a plan diagram or tree. See [EXPLAIN Visualization](/features/explain-visualization). **Database > Users & Roles** shows where each privilege comes from before you grant or revoke it. **Backup Dump** and **Restore Dump** shell out to your local `pg_dump` and `pg_restore`; see [Backup & Restore](/features/backup-restore). @@ -90,4 +94,6 @@ New connections default to **Preferred** (libpq `sslmode=prefer`): TLS first, pl **FATAL: password authentication failed for user "…"**: the role and password are checked against `pg_hba.conf`. Confirm the method on the matching line (`scram-sha-256` or `md5` for passwords, `trust` for local dev), and that the line matches the host you are connecting from. +**ERROR: invalid byte sequence for encoding "UTF8": 0x…**: the database's encoding is `SQL_ASCII`, which stores bytes without checking them, and a value in the result is not UTF-8. Run `SHOW server_encoding` to confirm. Move the data to a `UTF8` database: dump it with `pg_dump --encoding=` and the encoding the text was written in, such as `EUC_JP` or `WIN1252`, then restore that dump into a database created with `ENCODING 'UTF8'`. + **A Postgres-compatible engine loads no tables**: wire-compatible engines connect under the PostgreSQL type, and the catalogs they omit are probed for rather than assumed. An engine without `pg_matviews` still lists its tables; object kinds it does not expose will not appear at all. diff --git a/docs/features/import-export.mdx b/docs/features/import-export.mdx index cc3664e5dc..b65c0f9448 100644 --- a/docs/features/import-export.mdx +++ b/docs/features/import-export.mdx @@ -133,7 +133,15 @@ As SQL, a results export writes `INSERT` statements only. A result set is the ou Splitting writes `dump.part1.sql`, `dump.part2.sql` and so on, rotating between statements so no part ends mid-`INSERT`. Restore the parts in order. A gzipped export is one file, so the two settings do not combine and the summary says so. - A MySQL or MariaDB dump is UTF-8 and says so: every part opens with `SET NAMES utf8mb4` and ends by putting the session's character set back, as `mysqldump` does. `mysql < dump.sql` then restores Japanese, emoji and other non-Latin text intact, even from a client whose default is Latin 1. + A dump is UTF-8 and says so in every part, the way the engine's own dump tool does: + + | Engine | Each part opens with | + |---|---| + | MySQL, MariaDB | `SET NAMES utf8mb4`, and ends by putting the session's character set back | + | PostgreSQL, CockroachDB, PGlite | `SET client_encoding = 'UTF8';` | + | Amazon Redshift | Nothing. Set `PGCLIENTENCODING=UTF8` before restoring it into a database that is not UTF-8 | + + `mysql < dump.sql` and `psql < dump.sql` then restore Japanese, emoji and other non-Latin text intact, even into a `LATIN1` or `EUC_JP` database or from a client whose default is Latin 1. One snapshot opens `START TRANSACTION WITH CONSISTENT SNAPSHOT` on MySQL, `BEGIN ISOLATION LEVEL REPEATABLE READ` on PostgreSQL, and a deferred transaction on SQLite. It holds that transaction open for the whole export. diff --git a/project.yml b/project.yml index e08d09fabc..f632d56e17 100644 --- a/project.yml +++ b/project.yml @@ -508,6 +508,8 @@ targets: - Plugins/MSSQLDriverPlugin/MSSQLCheckConstraintDefinition.swift - Plugins/PostgreSQLDriverPlugin/ColumnQueryShape.swift - Plugins/PostgreSQLDriverPlugin/LibPQByteaDecoder.swift + - Plugins/PostgreSQLDriverPlugin/LibPQCellDecoding.swift + - Plugins/PostgreSQLDriverPlugin/LibPQConnectionString.swift - Plugins/PostgreSQLDriverPlugin/LibPQPluginError.swift - Plugins/PostgreSQLDriverPlugin/LibPQSSLMapping.swift - Plugins/PostgreSQLDriverPlugin/PostGISSpatialRewrite.swift diff --git a/scripts/check-postgres-client-encoding.sh b/scripts/check-postgres-client-encoding.sh new file mode 100755 index 0000000000..c812e153c7 --- /dev/null +++ b/scripts/check-postgres-client-encoding.sh @@ -0,0 +1,103 @@ +#!/usr/bin/env bash +# +# Check the server facts the PostgreSQL driver and SQL export rely on for text encoding. +# +# The macOS and iOS drivers put client_encoding=UTF8 in the libpq connection string instead of +# running SET client_encoding after connect, because a value from the startup packet is the +# session's reset value and survives RESET ALL and DISCARD ALL, while a SET does not. SQL export +# opens a PostgreSQL-family dump with SET client_encoding = 'UTF8', which only helps if the engine +# accepts that statement. This asks a real server both questions, then restores a UTF-8 dump into +# LATIN1 and EUC_JP databases through psql reading stdin, where psql leaves the client encoding at +# the database's own, and checks the bytes that were stored. +# +# Usage: +# scripts/check-postgres-client-encoding.sh [host] [port] [user] [database] +# +# Needs psql. The password, if any, comes from PGPASSWORD. Point it at CockroachDB, PGlite or any +# other PostgreSQL-compatible engine to check the first two facts there; the restore check is +# skipped on an engine that cannot create and connect to a LATIN1 or EUC_JP database, which +# includes both of those. Exits non-zero on a failure. + +set -uo pipefail + +HOST="${1:-127.0.0.1}" +PORT="${2:-5432}" +USER_NAME="${3:-postgres}" +DATABASE="${4:-postgres}" + +command -v psql > /dev/null || { + echo "psql not found" >&2 + exit 3 +} + +unset PGCLIENTENCODING +BASE="host=$HOST port=$PORT user=$USER_NAME sslmode=prefer connect_timeout=10" +PSQL=(psql -X -A -t -v ON_ERROR_STOP=1) + +if ! "${PSQL[@]}" "$BASE dbname=$DATABASE" -c "SELECT 1" > /dev/null 2>&1; then + echo "no PostgreSQL at $HOST:$PORT for $USER_NAME" >&2 + exit 3 +fi + +WORK="$(mktemp -d)" +trap 'rm -rf "$WORK"' EXIT +failures=0 + +check() { + local label=$1 expected=$2 actual=$3 + if [ "$expected" = "$actual" ]; then + echo "ok $label" + else + echo "FAIL $label: expected '$expected', got '$actual'" + failures=$((failures + 1)) + fi +} + +pinned="$BASE dbname=$DATABASE client_encoding=UTF8" +check "startup client_encoding=UTF8" "UTF8" "$("${PSQL[@]}" "$pinned" -c "SHOW client_encoding" 2>&1)" +check "UTF8 after RESET ALL" "UTF8" "$("${PSQL[@]}" "$pinned" -c "RESET ALL" -c "SHOW client_encoding" 2>&1 | tail -1)" +check "UTF8 after DISCARD ALL" "UTF8" "$("${PSQL[@]}" "$pinned" -c "DISCARD ALL" -c "SHOW client_encoding" 2>&1 | tail -1)" +check "SET client_encoding = 'UTF8' accepted" "SET" \ + "$(psql -X -v ON_ERROR_STOP=1 "$BASE dbname=$DATABASE" -c "SET client_encoding = 'UTF8'" 2>&1)" + +restore_check() { + local encoding=$1 text=$2 expected_hex=$3 db + db="tablepro_encoding_probe_$(echo "$encoding" | tr '[:upper:]' '[:lower:]')" + "${PSQL[@]}" "$BASE dbname=$DATABASE" -c "DROP DATABASE IF EXISTS $db" > /dev/null 2>&1 + if ! "${PSQL[@]}" "$BASE dbname=$DATABASE" \ + -c "CREATE DATABASE $db ENCODING '$encoding' LC_COLLATE 'C' LC_CTYPE 'C' TEMPLATE template0" \ + > /dev/null 2>&1; then + echo "skip $encoding restore: the server cannot create a $encoding database" + return + fi + local reached + reached=$("${PSQL[@]}" "$BASE dbname=$db" -c "SHOW server_encoding" 2>&1) + if [ "$reached" != "$encoding" ]; then + echo "skip $encoding restore: connecting to $db reached a $reached database" + "${PSQL[@]}" "$BASE dbname=$DATABASE" -c "DROP DATABASE IF EXISTS $db" > /dev/null 2>&1 + return + fi + + printf "SET client_encoding = 'UTF8';\n\nCREATE TABLE t (v text);\nINSERT INTO t VALUES ('%s');\n" "$text" \ + > "$WORK/dump.sql" + local output + output=$("${PSQL[@]}" "$BASE dbname=$db" < "$WORK/dump.sql" 2>&1) + local stored + stored=$("${PSQL[@]}" "$BASE dbname=$db" -c "SELECT encode(convert_to(v, '$encoding'), 'hex') FROM t" 2>&1) + check "$encoding restore of a UTF-8 dump through stdin" "$expected_hex" "${stored:-$output}" + + local session + session=$("${PSQL[@]}" "$BASE dbname=$db client_encoding=UTF8" -c "RESET ALL" -c "SELECT v FROM t" 2>&1 | tail -1) + check "$encoding read through a UTF8-pinned session after RESET ALL" "$text" "$session" + + "${PSQL[@]}" "$BASE dbname=$DATABASE" -c "DROP DATABASE IF EXISTS $db" > /dev/null 2>&1 +} + +restore_check LATIN1 "café" "636166e9" +restore_check EUC_JP "メール" "a5e1a1bca5eb" + +if [ "$failures" -gt 0 ]; then + echo "$failures check(s) failed" + exit 1 +fi +echo "all checks passed" From 5327a068c90c0983c7a655754129b80b86cd2ae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Nam=20Long?= Date: Fri, 11 Sep 2026 16:48:58 +0000 Subject: [PATCH 06/54] fix(plugin-mysql): spell OceanBase binary literals as MySQL bit-strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nguyễn Nam Long --- TablePro/Core/Compare/CompareSQLLiteral.swift | 4 ++-- .../Services/ProjectImport/ProjectYamlExtractorTests.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/TablePro/Core/Compare/CompareSQLLiteral.swift b/TablePro/Core/Compare/CompareSQLLiteral.swift index 5d5118e68c..e6b8d7d6e8 100644 --- a/TablePro/Core/Compare/CompareSQLLiteral.swift +++ b/TablePro/Core/Compare/CompareSQLLiteral.swift @@ -56,8 +56,8 @@ internal enum CompareSQLLiteral { /// name falls back to the driver's own spelling rather than guessing at one. internal static func binaryStyle(for databaseType: DatabaseType) -> BinaryStyle { switch databaseType { - case .mysql, .mariadb, .tidb, .databend, .sqlite, .clickhouse, .duckdb, .libsql, .turso, - .cloudflareD1: + case .mysql, .mariadb, .tidb, .databend, .oceanbase, .sqlite, .clickhouse, .duckdb, .libsql, + .turso, .cloudflareD1: return .bitString case .postgresql, .cockroachdb, .redshift, .pglite: return .postgresBytea diff --git a/TableProTests/Core/Services/ProjectImport/ProjectYamlExtractorTests.swift b/TableProTests/Core/Services/ProjectImport/ProjectYamlExtractorTests.swift index 8b4817e737..c3bbc97428 100644 --- a/TableProTests/Core/Services/ProjectImport/ProjectYamlExtractorTests.swift +++ b/TableProTests/Core/Services/ProjectImport/ProjectYamlExtractorTests.swift @@ -272,7 +272,7 @@ struct DockerComposeExtractorTests { - "2881:2881" """).first #expect(oceanbase?.parsedURL.type == .oceanbase) - #expect(oceanbase?.parsedURL.port == nil) + #expect(oceanbase?.parsedURL.port == 2_881) #expect(oceanbase?.parsedURL.username == "root@sys") #expect(oceanbase?.parsedURL.password.isEmpty == true) #expect(oceanbase?.parsedURL.database.isEmpty == true) From b2f02e3402c93ce2bd8e5df520b047c5e1a0f907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Fri, 11 Sep 2026 23:49:06 +0700 Subject: [PATCH 07/54] fix(ios): set the MySQL session character set on iPhone and decode results by their declared charset (#2725) (#2744) --- CHANGELOG.md | 4 + CLAUDE.md | 2 +- .../DatabendResultShape.swift | 2 +- .../MySQLDriverPlugin/GeometryWKBParser.swift | 2 +- .../MariaDBCharacterSet.swift | 117 ++++++++++ .../MariaDBFieldClassifier.swift | 2 +- .../MariaDBFieldMetadata.swift | 18 +- .../MariaDBPluginConnection.swift | 126 ++--------- .../MySQLDriverPlugin/MySQLCharacterSet.swift | 2 +- .../MySQLColumnDecoding.swift | 8 +- .../MySQLConnectionEncoding.swift | 6 +- .../MySQLDriverPlugin/MySQLKillTarget.swift | 33 +++ Plugins/MySQLDriverPlugin/MySQLLatin1.swift | 2 +- .../MySQLDriverPlugin/MySQLPluginDriver.swift | 4 +- .../MySQLDriverPlugin/MySQLServerFlavor.swift | 36 +--- .../TableProMobile/Drivers/MySQLDriver.swift | 200 +++++++++--------- .../Platform/IOSDriverFactory.swift | 3 +- .../Drivers/MySQLSharedDecodingTests.swift | 43 ++++ TableProMobile/project.yml | 11 + .../MySQLConnectionEncodingTests.swift | 7 + project.yml | 1 + 21 files changed, 366 insertions(+), 263 deletions(-) create mode 100644 Plugins/MySQLDriverPlugin/MariaDBCharacterSet.swift create mode 100644 Plugins/MySQLDriverPlugin/MySQLKillTarget.swift create mode 100644 TableProMobile/TableProMobileTests/Drivers/MySQLSharedDecodingTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index e76c7939f9..1e9021fec4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Garbled non-Latin text saved from iPhone and iPad to MySQL servers that force a Latin 1 session. (#2725) +- **Encoding** ignored on iPhone and iPad by a MySQL connection synced from the Mac. (#2725) +- Binary MySQL columns shown as text on iPhone and iPad, and searched with `LIKE`. +- Crash opening a MySQL result whose column has no name on iPhone and iPad. - Wrong SQLSTATE code in PostgreSQL, Redshift, CockroachDB and PGlite error messages. - Read-only write explanation never shown on PostgreSQL servers. - Safe Mode minimum from a configuration profile missing from the toolbar, the Database menu and the connection form. (#2030) diff --git a/CLAUDE.md b/CLAUDE.md index 4dab1c7726..568c0efb8d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -225,7 +225,7 @@ To ship one: add the record type or field in CloudKit Console (or `xcrun cktool **A pooled metadata read assumes a second connection reaches the same database, and an embedded engine breaks that assumption**: `MetadataConnectionPool` builds a whole new driver, so it is only correct when the database lives on a server the driver reconnects to. When the database lives *inside* the driver instance, the pool gets a different database: a second `duckdb_open(":memory:")` is a fresh empty database, and a second `duckdb_open` on the same *file* is a second independent read-write instance that the first never sees (DuckDB's file lock does not conflict within one process). The failure is silent, because an empty catalog is indistinguishable from "no tables", which is why #2108 survived a manual refresh. `supportsConnectionPooling` is the opt-out, and it is read only by `DatabaseManager.canPool`; DuckDB and PGlite set it `false`. SQLite-family engines keep pooling, because multi-connection access to one file is what they are built for. Two rules follow. First, every metadata read goes through `DatabaseManager.withMetadataDriver` so `metadataRoute` can apply the rule; reaching for `MetadataConnectionPool.shared.withDriver` directly bypasses it, which is how routines kept pooling after the sidebar stopped. Second, a capability with no `DriverPlugin` static is curated per type and `buildMetadataSnapshot` must carry it over from the built-in snapshot, or `register(snapshot:forTypeId:)` resets it to the struct default the moment the plugin loads. That is not hypothetical: it silently disabled MongoDB's `authenticationIsDatabaseScoped` (#1970) for every build that had the plugin installed. `registerVariant` already treats the curated entry as authoritative, which is the only reason PGlite's flag ever worked. -**A MySQL session's character set is server state, and the driver sets it rather than asking for it**: `MYSQL_SET_CHARSET_NAME` only puts a collation byte in the handshake, and the server is free to ignore it. `init_connect='SET NAMES latin1'` for any user without `CONNECTION_ADMIN`, MariaDB's `skip-character-set-client-handshake`, and a server with no `utf8mb4` all leave the session latin1 while libmariadb still reports `utf8mb4`. The driver sends UTF-8 either way, so every comment and value it wrote there was stored double-encoded, which is the `メール` of #2725, and a user-variable comparison on MySQL 8 failed with `ERROR 1267` under the handshake's `utf8mb4_general_ci`. So `MariaDBPluginConnection.establishSessionCharacterSet` calls `mysql_set_character_set` on every connect path, falls back to a plain `SET NAMES utf8` (libmariadb itself rewrites `utf8` to `utf8mb3`, which a pre-5.5.3 server does not know), and keeps the server's own session when it refuses both rather than failing the connect: a MySQL-protocol engine that rejects `SET NAMES` must still connect. Two rules follow. Outgoing SQL stays the UTF-8 bytes of the Swift string and never follows a mid-session `SET NAMES`: a legacy dump that declares `SET NAMES latin1` over UTF-8 bytes restores byte-for-byte only because nothing re-encodes it, which is also what the `mysql` client does. And every result cell decodes through `MySQLColumnDecoding` by its field's own `charsetnr`, never as "UTF-8 and hope": a latin1 field reads UTF-8 first and then MySQL's latin1, which is cp1252 plus five C1 pass-through bytes and not Foundation's `.isoLatin1` or `.windowsCP1252`. The Foundation encodings in `MySQLCharacterSet` are a hand transcription of the server's tables; `scripts/check-mysql-charset-decoding.sh` diffs them against a live server, and a charset that disagrees stays out of the table. **UTF-8 via Latin 1** (`mysqlConnectionEncoding`) sets only `character_set_client` to latin1 and repairs the text client-side, so correctly stored text is never read back as `?`, which a latin1 results charset would do and a structure edit would then write back. +**A MySQL session's character set is server state, and the driver sets it rather than asking for it**: `MYSQL_SET_CHARSET_NAME` only puts a collation byte in the handshake, and the server is free to ignore it. `init_connect='SET NAMES latin1'` for any user without `CONNECTION_ADMIN`, MariaDB's `skip-character-set-client-handshake`, and a server with no `utf8mb4` all leave the session latin1 while libmariadb still reports `utf8mb4`. The driver sends UTF-8 either way, so every comment and value it wrote there was stored double-encoded, which is the `メール` of #2725, and a user-variable comparison on MySQL 8 failed with `ERROR 1267` under the handshake's `utf8mb4_general_ci`. So `MariaDBCharacterSet.establishSession`, which the macOS plugin and the iOS driver share, calls `mysql_set_character_set` on every connect path, falls back to a plain `SET NAMES utf8` (libmariadb itself rewrites `utf8` to `utf8mb3`, which a pre-5.5.3 server does not know), and keeps the server's own session when it refuses both rather than failing the connect: a MySQL-protocol engine that rejects `SET NAMES` must still connect. Two rules follow. Outgoing SQL stays the UTF-8 bytes of the Swift string and never follows a mid-session `SET NAMES`: a legacy dump that declares `SET NAMES latin1` over UTF-8 bytes restores byte-for-byte only because nothing re-encodes it, which is also what the `mysql` client does. And every result cell decodes through `MySQLColumnDecoding` by its field's own `charsetnr`, never as "UTF-8 and hope": a latin1 field reads UTF-8 first and then MySQL's latin1, which is cp1252 plus five C1 pass-through bytes and not Foundation's `.isoLatin1` or `.windowsCP1252`. The Foundation encodings in `MySQLCharacterSet` are a hand transcription of the server's tables; `scripts/check-mysql-charset-decoding.sh` diffs them against a live server, and a charset that disagrees stays out of the table. **UTF-8 via Latin 1** (`mysqlConnectionEncoding`) sets only `character_set_client` to latin1 and repairs the text client-side, so correctly stored text is never read back as `?`, which a latin1 results charset would do and a structure edit would then write back. **A MongoDB update or delete is anchored on `_id` or it does not run**: `generateDelete` used to fall back to a filter built from the remaining columns, which silently dropped every value it could not stringify (all binary) and then `deleteOne`d the first partial match, so a document with a binary `_id` could delete a different document. Both paths now skip with a logged warning instead, matching what `generateUpdate` already did. diff --git a/Plugins/MySQLDriverPlugin/DatabendResultShape.swift b/Plugins/MySQLDriverPlugin/DatabendResultShape.swift index d67489e730..aab081616a 100644 --- a/Plugins/MySQLDriverPlugin/DatabendResultShape.swift +++ b/Plugins/MySQLDriverPlugin/DatabendResultShape.swift @@ -6,7 +6,7 @@ import Foundation import TableProPluginKit -internal enum DatabendResultShape { +nonisolated internal enum DatabendResultShape { static let booleanTypeName = "BOOLEAN" private static let shortFieldType: UInt32 = 2 diff --git a/Plugins/MySQLDriverPlugin/GeometryWKBParser.swift b/Plugins/MySQLDriverPlugin/GeometryWKBParser.swift index 060b1f1051..ecc82573c6 100644 --- a/Plugins/MySQLDriverPlugin/GeometryWKBParser.swift +++ b/Plugins/MySQLDriverPlugin/GeometryWKBParser.swift @@ -8,7 +8,7 @@ import Foundation -enum GeometryWKBParser { +nonisolated enum GeometryWKBParser { /// Parses MySQL's internal geometry binary format to WKT string. /// /// MySQL internal binary format: diff --git a/Plugins/MySQLDriverPlugin/MariaDBCharacterSet.swift b/Plugins/MySQLDriverPlugin/MariaDBCharacterSet.swift new file mode 100644 index 0000000000..2b5d3fcbaf --- /dev/null +++ b/Plugins/MySQLDriverPlugin/MariaDBCharacterSet.swift @@ -0,0 +1,117 @@ +import CMariaDB +import Foundation +import OSLog + +nonisolated internal enum MariaDBCharacterSet { + private static let logger = Logger(subsystem: "com.TablePro", category: "MariaDBCharacterSet") + + static func establishSession(on mysql: UnsafeMutablePointer, encoding: MySQLConnectionEncoding) -> Bool { + if mysql_set_character_set(mysql, MySQLConnectionEncoding.sessionCharacterSetName) != 0 { + let refusal = errorSummary(of: mysql, encoding: encoding) + if run(MySQLConnectionEncoding.sessionFallbackStatement, on: mysql) { + logger.notice("Server refused utf8mb4 (\(refusal, privacy: .public)), so the session uses utf8") + } else { + logger.warning("Server refused a UTF-8 session (\(refusal, privacy: .public)); keeping its own") + } + } + for statement in encoding.sessionStatements where !run(statement, on: mysql) { + return false + } + return true + } + + static func name(forCollation collation: UInt32) -> String? { + guard let info = mariadb_get_charset_by_nr(collation), let name = info.pointee.csname else { return nil } + return String(cString: name) + } + + static func describeColumns( + of fields: UnsafeMutablePointer?, + count: Int, + encoding: MySQLConnectionEncoding, + flavor: MySQLServerFlavor = .mysql + ) -> MySQLResultColumns { + var columns = MySQLResultColumns() + guard let fields else { return columns } + for index in 0.., + decoding: MySQLColumnDecoding + ) -> String { + guard decoding != .databendBoolean else { return DatabendResultShape.booleanTypeName } + return mysqlTypeToString(field) + } + + private static func typeCode(of field: MYSQL_FIELD, flags: UInt) -> UInt32 { + if (flags & mysqlSetFlag) != 0 { return 248 } + if (flags & mysqlEnumFlag) != 0 { return 247 } + return field.type.rawValue + } + + static func decodedName(of field: MYSQL_FIELD, encoding: MySQLConnectionEncoding) -> String? { + guard let name = field.name else { return nil } + let bytes = UnsafeRawBufferPointer(start: name, count: strnlen(name, Int(field.name_length))) + return mysqlSessionText(bytes, encoding: encoding) + } + + private static func run(_ statement: String, on mysql: UnsafeMutablePointer) -> Bool { + let status = statement.withCString { mysql_real_query(mysql, $0, UInt(strlen($0))) } + if let discarded = mysql_store_result(mysql) { + mysql_free_result(discarded) + } + return status == 0 + } + + private static func errorSummary(of mysql: UnsafeMutablePointer, encoding: MySQLConnectionEncoding) -> String { + let code = mysql_errno(mysql) + guard let message = mysql_error(mysql) else { return "error \(code)" } + return "\(code) \(mysqlSessionText(cString: message, encoding: encoding))" + } +} + +nonisolated func mysqlTypeToString(_ fieldPtr: UnsafePointer) -> String { + let field = fieldPtr.pointee + let flags = UInt(field.flags) + + // MariaDB extended metadata: detect JSON stored as LONGTEXT. + // `MARIADB_CONST_STRING` is length-prefixed (not null-terminated), so we must read + // exactly `attr.length` bytes. `String(cString:)` would scan past the buffer into + // adjacent memory and intermittently fail the comparison when that memory is non-zero. + var attr = MARIADB_CONST_STRING() + if mariadb_field_attr(&attr, fieldPtr, MARIADB_FIELD_ATTR_FORMAT_NAME) == 0, + let str = attr.str, attr.length > 0, + let value = String(data: Data(bytes: str, count: Int(attr.length)), encoding: .utf8), + value == "json" { + return "JSON" + } + + if (flags & mysqlEnumFlag) != 0 { return "ENUM" } + if (flags & mysqlSetFlag) != 0 { return "SET" } + + return mariaDBTypeName( + typeRaw: field.type.rawValue, + flags: flags, + charsetnr: field.charsetnr, + length: field.length + ) +} diff --git a/Plugins/MySQLDriverPlugin/MariaDBFieldClassifier.swift b/Plugins/MySQLDriverPlugin/MariaDBFieldClassifier.swift index f49a05151e..c6fc918677 100644 --- a/Plugins/MySQLDriverPlugin/MariaDBFieldClassifier.swift +++ b/Plugins/MySQLDriverPlugin/MariaDBFieldClassifier.swift @@ -5,7 +5,7 @@ import Foundation -internal enum MariaDBFieldClassifier { +nonisolated internal enum MariaDBFieldClassifier { private static let bitType: UInt32 = 16 private static let binaryCharset: UInt32 = 63 private static let blobOrStringTypes: Set = [249, 250, 251, 252, 253, 254] diff --git a/Plugins/MySQLDriverPlugin/MariaDBFieldMetadata.swift b/Plugins/MySQLDriverPlugin/MariaDBFieldMetadata.swift index fe98664288..e918564ec7 100644 --- a/Plugins/MySQLDriverPlugin/MariaDBFieldMetadata.swift +++ b/Plugins/MySQLDriverPlugin/MariaDBFieldMetadata.swift @@ -6,15 +6,15 @@ import Foundation import TableProPluginKit -internal let mysqlNotNullFlag: UInt = 0x0001 -internal let mysqlPriKeyFlag: UInt = 0x0002 -internal let mysqlBinaryFlag: UInt = 0x0080 -internal let mysqlEnumFlag: UInt = 0x0100 -internal let mysqlAutoIncrementFlag: UInt = 0x0200 -internal let mysqlSetFlag: UInt = 0x0800 -internal let mysqlBinaryCharset: UInt32 = 63 +nonisolated internal let mysqlNotNullFlag: UInt = 0x0001 +nonisolated internal let mysqlPriKeyFlag: UInt = 0x0002 +nonisolated internal let mysqlBinaryFlag: UInt = 0x0080 +nonisolated internal let mysqlEnumFlag: UInt = 0x0100 +nonisolated internal let mysqlAutoIncrementFlag: UInt = 0x0200 +nonisolated internal let mysqlSetFlag: UInt = 0x0800 +nonisolated internal let mysqlBinaryCharset: UInt32 = 63 -internal func makeColumnMeta(name: String, typeName: String, flags: UInt) -> PluginColumnInfo { +nonisolated internal func makeColumnMeta(name: String, typeName: String, flags: UInt) -> PluginColumnInfo { PluginColumnInfo( name: name, dataType: typeName, @@ -24,7 +24,7 @@ internal func makeColumnMeta(name: String, typeName: String, flags: UInt) -> Plu ) } -internal func mariaDBTypeName( +nonisolated internal func mariaDBTypeName( typeRaw: UInt32, flags: UInt, charsetnr: UInt32, diff --git a/Plugins/MySQLDriverPlugin/MariaDBPluginConnection.swift b/Plugins/MySQLDriverPlugin/MariaDBPluginConnection.swift index 6e29301542..024749bb08 100644 --- a/Plugins/MySQLDriverPlugin/MariaDBPluginConnection.swift +++ b/Plugins/MySQLDriverPlugin/MariaDBPluginConnection.swift @@ -45,38 +45,6 @@ struct MariaDBPluginQueryResult { var firstRowTime: TimeInterval? } -// MARK: - SSL Configuration - -// MARK: - Type Mapping - -func mysqlTypeToString(_ fieldPtr: UnsafePointer) -> String { - let field = fieldPtr.pointee - let flags = UInt(field.flags) - let length = field.length - - // MariaDB extended metadata: detect JSON stored as LONGTEXT. - // `MARIADB_CONST_STRING` is length-prefixed (not null-terminated), so we must read - // exactly `attr.length` bytes. `String(cString:)` would scan past the buffer into - // adjacent memory and intermittently fail the comparison when that memory is non-zero. - var attr = MARIADB_CONST_STRING() - if mariadb_field_attr(&attr, fieldPtr, MARIADB_FIELD_ATTR_FORMAT_NAME) == 0, - let str = attr.str, attr.length > 0, - let value = String(data: Data(bytes: str, count: Int(attr.length)), encoding: .utf8), - value == "json" { - return "JSON" - } - - if (flags & mysqlEnumFlag) != 0 { return "ENUM" } - if (flags & mysqlSetFlag) != 0 { return "SET" } - - return mariaDBTypeName( - typeRaw: field.type.rawValue, - flags: flags, - charsetnr: field.charsetnr, - length: field.length - ) -} - // MARK: - Connection Class final class MariaDBPluginConnection: @unchecked Sendable { @@ -318,42 +286,14 @@ final class MariaDBPluginConnection: @unchecked Sendable { } } - if result == nil { + guard result != nil, MariaDBCharacterSet.establishSession(on: mysql, encoding: connectionEncoding) else { let error = readError(from: mysql) mysql_close(mysql) throw error } - do { - try establishSessionCharacterSet(on: mysql) - } catch { - mysql_close(mysql) - throw error - } return mysql } - private func establishSessionCharacterSet(on mysql: UnsafeMutablePointer) throws { - if mysql_set_character_set(mysql, MySQLConnectionEncoding.sessionCharacterSetName) != 0 { - let refusal = errorMessage(from: mysql) - if runSessionStatement(MySQLConnectionEncoding.sessionFallbackStatement, on: mysql) { - logger.notice("Server refused utf8mb4 (\(refusal, privacy: .public)), so the session uses utf8") - } else { - logger.warning("Server refused a UTF-8 session (\(refusal, privacy: .public)); keeping its own") - } - } - for statement in connectionEncoding.sessionStatements where !runSessionStatement(statement, on: mysql) { - throw readError(from: mysql) - } - } - - private func runSessionStatement(_ statement: String, on mysql: UnsafeMutablePointer) -> Bool { - let status = statement.withCString { mysql_real_query(mysql, $0, UInt(strlen($0))) } - if let discarded = mysql_store_result(mysql) { - mysql_free_result(discarded) - } - return status == 0 - } - private func readError(from mysql: UnsafeMutablePointer) -> MariaDBPluginError { MariaDBPluginError( code: mysql_errno(mysql), @@ -622,7 +562,12 @@ final class MariaDBPluginConnection: @unchecked Sendable { } let sessionFlavor = flavor - let columns = describeColumns(mysql_fetch_fields(resultPtr), count: Int(mysql_num_fields(resultPtr))) + let columns = MariaDBCharacterSet.describeColumns( + of: mysql_fetch_fields(resultPtr), + count: Int(mysql_num_fields(resultPtr)), + encoding: connectionEncoding, + flavor: sessionFlavor + ) var rows: [[PluginCellValue]] = [] rows.reserveCapacity(min(1_000, PluginRowLimits.emergencyMax)) @@ -970,7 +915,12 @@ final class MariaDBPluginConnection: @unchecked Sendable { mysql_free_result(metadata) } - let columns = describeColumns(mysql_fetch_fields(metadata), count: Int(mysql_num_fields(metadata))) + let columns = MariaDBCharacterSet.describeColumns( + of: mysql_fetch_fields(metadata), + count: Int(mysql_num_fields(metadata)), + encoding: connectionEncoding, + flavor: flavor + ) let fetchResult = try fetchResultSet( from: stmt, metadata: metadata, @@ -1037,9 +987,11 @@ final class MariaDBPluginConnection: @unchecked Sendable { return } - let columns = describeColumns( - mysql_fetch_fields(resultPtr), - count: Int(mysql_num_fields(resultPtr)) + let columns = MariaDBCharacterSet.describeColumns( + of: mysql_fetch_fields(resultPtr), + count: Int(mysql_num_fields(resultPtr)), + encoding: connectionEncoding, + flavor: flavor ) continuation.yield(.header(PluginStreamHeader( @@ -1119,48 +1071,6 @@ final class MariaDBPluginConnection: @unchecked Sendable { return String(cString: state) } - private func describeColumns(_ fields: UnsafeMutablePointer?, count: Int) -> MySQLResultColumns { - var columns = MySQLResultColumns() - guard let fields else { return columns } - let sessionFlavor = flavor - for index in 0.. String { - guard let name = field.name else { return "column_\(index)" } - let bytes = UnsafeRawBufferPointer(start: name, count: strnlen(name, Int(field.name_length))) - return mysqlSessionText(bytes, encoding: connectionEncoding) - } - - private static func typeCode(of field: MYSQL_FIELD, flags: UInt) -> UInt32 { - if (flags & mysqlSetFlag) != 0 { return 248 } - if (flags & mysqlEnumFlag) != 0 { return 247 } - return field.type.rawValue - } - - private static func characterSetName(forCollation collation: UInt32) -> String? { - guard let info = mariadb_get_charset_by_nr(collation), let name = info.pointee.csname else { return nil } - return String(cString: name) - } - private func textProtocolRow( _ row: MYSQL_ROW, lengths: UnsafeMutablePointer?, diff --git a/Plugins/MySQLDriverPlugin/MySQLCharacterSet.swift b/Plugins/MySQLDriverPlugin/MySQLCharacterSet.swift index 92ffcb0bc4..96fa8f7834 100644 --- a/Plugins/MySQLDriverPlugin/MySQLCharacterSet.swift +++ b/Plugins/MySQLDriverPlugin/MySQLCharacterSet.swift @@ -6,7 +6,7 @@ import CoreFoundation import Foundation -internal struct MySQLCharacterSet: Hashable, Sendable { +nonisolated internal struct MySQLCharacterSet: Hashable, Sendable { static let utf8mb4 = MySQLCharacterSet(serverName: "utf8mb4") static let latin1 = MySQLCharacterSet(serverName: "latin1") diff --git a/Plugins/MySQLDriverPlugin/MySQLColumnDecoding.swift b/Plugins/MySQLDriverPlugin/MySQLColumnDecoding.swift index 9b7b76d97b..694924873f 100644 --- a/Plugins/MySQLDriverPlugin/MySQLColumnDecoding.swift +++ b/Plugins/MySQLDriverPlugin/MySQLColumnDecoding.swift @@ -6,7 +6,7 @@ import Foundation import TableProPluginKit -internal enum MySQLColumnDecoding: Equatable, Sendable { +nonisolated internal enum MySQLColumnDecoding: Equatable, Sendable { case geometry case bit case bytes @@ -59,7 +59,7 @@ internal enum MySQLColumnDecoding: Equatable, Sendable { } } -internal struct MySQLResultColumns { +nonisolated internal struct MySQLResultColumns { private(set) var names: [String] = [] private(set) var typeCodes: [UInt32] = [] private(set) var typeNames: [String] = [] @@ -93,10 +93,10 @@ internal struct MySQLResultColumns { } } -internal func mysqlSessionText(_ bytes: UnsafeRawBufferPointer, encoding: MySQLConnectionEncoding) -> String { +nonisolated internal func mysqlSessionText(_ bytes: UnsafeRawBufferPointer, encoding: MySQLConnectionEncoding) -> String { encoding.presentedText(MySQLCharacterSet.decodeUTF8OrMySQLLatin1(bytes)) } -internal func mysqlSessionText(cString: UnsafePointer, encoding: MySQLConnectionEncoding) -> String { +nonisolated internal func mysqlSessionText(cString: UnsafePointer, encoding: MySQLConnectionEncoding) -> String { mysqlSessionText(UnsafeRawBufferPointer(start: cString, count: strlen(cString)), encoding: encoding) } diff --git a/Plugins/MySQLDriverPlugin/MySQLConnectionEncoding.swift b/Plugins/MySQLDriverPlugin/MySQLConnectionEncoding.swift index 34457c1a42..6702122977 100644 --- a/Plugins/MySQLDriverPlugin/MySQLConnectionEncoding.swift +++ b/Plugins/MySQLDriverPlugin/MySQLConnectionEncoding.swift @@ -6,7 +6,7 @@ import Foundation import TableProPluginKit -internal enum MySQLConnectionEncoding: String, CaseIterable, Sendable { +nonisolated internal enum MySQLConnectionEncoding: String, CaseIterable, Sendable { case utf8 = "" case utf8ViaLatin1 @@ -27,6 +27,10 @@ internal enum MySQLConnectionEncoding: String, CaseIterable, Sendable { self = fieldValue.flatMap(Self.init(rawValue:)) ?? .utf8 } + init(additionalFields: [String: String]) { + self.init(fieldValue: additionalFields[Self.fieldId]) + } + var displayName: String { switch self { case .utf8: return "UTF-8" diff --git a/Plugins/MySQLDriverPlugin/MySQLKillTarget.swift b/Plugins/MySQLDriverPlugin/MySQLKillTarget.swift new file mode 100644 index 0000000000..0c333f085d --- /dev/null +++ b/Plugins/MySQLDriverPlugin/MySQLKillTarget.swift @@ -0,0 +1,33 @@ +import Foundation + +internal enum MySQLKillTarget: Equatable, Sendable { + case threadId + case tidbConnection(UInt64) + case databendSession(String) + + func statement(threadId: UInt) -> String? { + switch self { + case .threadId: + return threadId > 0 ? "KILL QUERY \(threadId)" : nil + case .tidbConnection(let id): + return "KILL TIDB QUERY \(id)" + case .databendSession(let session): + return "KILL QUERY '\(mysqlEscapeStringLiteral(session))'" + } + } +} + +internal extension MySQLServerFlavor { + func killTarget(connectionIdentifier: String?) -> MySQLKillTarget { + switch self { + case .tidb: + guard let id = connectionIdentifier.flatMap(UInt64.init) else { return .threadId } + return .tidbConnection(id) + case .databend: + guard let session = connectionIdentifier, !session.isEmpty else { return .threadId } + return .databendSession(session) + case .mysql, .mariadb: + return .threadId + } + } +} diff --git a/Plugins/MySQLDriverPlugin/MySQLLatin1.swift b/Plugins/MySQLDriverPlugin/MySQLLatin1.swift index 5fd582f285..becef4793c 100644 --- a/Plugins/MySQLDriverPlugin/MySQLLatin1.swift +++ b/Plugins/MySQLDriverPlugin/MySQLLatin1.swift @@ -5,7 +5,7 @@ import Foundation -internal enum MySQLLatin1 { +nonisolated internal enum MySQLLatin1 { private static let windowsRangeScalars: [UInt32] = [ 0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008D, 0x017D, 0x008F, diff --git a/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift b/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift index 2d15ac1406..c982bce1ce 100644 --- a/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift +++ b/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift @@ -125,9 +125,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { sslConfig: sslConfig, enableCleartextPlugin: config.additionalFields["enableCleartextPlugin"] == "true", queryTimeoutSeconds: config.additionalFields["queryTimeoutSeconds"].flatMap { Int($0) } ?? 0, - connectionEncoding: MySQLConnectionEncoding( - fieldValue: config.additionalFields[MySQLConnectionEncoding.fieldId] - ) + connectionEncoding: MySQLConnectionEncoding(additionalFields: config.additionalFields) ) try await conn.connect() diff --git a/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift b/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift index de8c018da8..9cb8554964 100644 --- a/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift +++ b/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift @@ -6,7 +6,7 @@ import Foundation import TableProPluginKit -internal struct MySQLEngineVersion: Comparable, Sendable { +nonisolated internal struct MySQLEngineVersion: Comparable, Sendable { let major: Int let minor: Int let patch: Int @@ -28,7 +28,7 @@ internal struct MySQLEngineVersion: Comparable, Sendable { } } -internal enum MySQLServerFlavor: Equatable, Sendable { +nonisolated internal enum MySQLServerFlavor: Equatable, Sendable { case mysql case mariadb case tidb(version: MySQLEngineVersion?) @@ -137,39 +137,9 @@ internal enum MySQLServerFlavor: Equatable, Sendable { guard isDatabend else { return errno == 1_317 } return errno == 1_105 && message.contains("AbortedQuery") } - - func killTarget(connectionIdentifier: String?) -> MySQLKillTarget { - switch self { - case .tidb: - guard let id = connectionIdentifier.flatMap(UInt64.init) else { return .threadId } - return .tidbConnection(id) - case .databend: - guard let session = connectionIdentifier, !session.isEmpty else { return .threadId } - return .databendSession(session) - case .mysql, .mariadb: - return .threadId - } - } -} - -internal enum MySQLKillTarget: Equatable, Sendable { - case threadId - case tidbConnection(UInt64) - case databendSession(String) - - func statement(threadId: UInt) -> String? { - switch self { - case .threadId: - return threadId > 0 ? "KILL QUERY \(threadId)" : nil - case .tidbConnection(let id): - return "KILL TIDB QUERY \(id)" - case .databendSession(let session): - return "KILL QUERY '\(mysqlEscapeStringLiteral(session))'" - } - } } -internal enum MySQLFlavorResolution { +nonisolated internal enum MySQLFlavorResolution { static func needsTiDBVersionProbe(banner: String?, variant: String?) -> Bool { variant == MySQLServerFlavor.tidbVariant && !MySQLServerFlavor.fromBanner(banner).isTiDB } diff --git a/TableProMobile/TableProMobile/Drivers/MySQLDriver.swift b/TableProMobile/TableProMobile/Drivers/MySQLDriver.swift index 2f89f9de0d..a53b40ac8b 100644 --- a/TableProMobile/TableProMobile/Drivers/MySQLDriver.swift +++ b/TableProMobile/TableProMobile/Drivers/MySQLDriver.swift @@ -3,6 +3,7 @@ import Foundation import TableProDatabase import TableProModels import TableProMSSQLCore +import TableProPluginKit nonisolated final class MySQLDriver: DatabaseDriver, @unchecked Sendable { private let actor = MySQLActor() @@ -13,6 +14,7 @@ nonisolated final class MySQLDriver: DatabaseDriver, @unchecked Sendable { private let database: String let ssl: DriverSSLConfiguration let databaseType: DatabaseType + private let connectionEncoding: MySQLConnectionEncoding var supportsSchemas: Bool { false } var currentSchema: String? { nil } @@ -32,7 +34,8 @@ nonisolated final class MySQLDriver: DatabaseDriver, @unchecked Sendable { password: String, database: String, ssl: DriverSSLConfiguration = .disabled, - databaseType: DatabaseType = .mysql + databaseType: DatabaseType = .mysql, + connectionEncoding: MySQLConnectionEncoding = .utf8 ) { self.host = host self.port = port @@ -41,13 +44,17 @@ nonisolated final class MySQLDriver: DatabaseDriver, @unchecked Sendable { self.database = database self.ssl = ssl self.databaseType = databaseType + self.connectionEncoding = connectionEncoding } // MARK: - Connection func connect() async throws { try await LocalNetworkPermission.shared.ensureAccess(for: host) - try await actor.connect(host: host, port: port, user: user, password: password, database: database, ssl: ssl) + try await actor.connect( + host: host, port: port, user: user, password: password, database: database, + ssl: ssl, encoding: connectionEncoding + ) serverVersion = await actor.serverVersion() } @@ -271,7 +278,13 @@ private actor MySQLActor { private static let connectDeadline: DispatchTimeInterval = .seconds(15) - func connect(host: String, port: Int, user: String, password: String, database: String, ssl: DriverSSLConfiguration) async throws { + private var encoding: MySQLConnectionEncoding = .utf8 + + func connect( + host: String, port: Int, user: String, password: String, database: String, + ssl: DriverSSLConfiguration, encoding: MySQLConnectionEncoding + ) async throws { + self.encoding = encoding // Close existing connection if reconnecting if let mysql { mysql_close(mysql); self.mysql = nil } @@ -279,7 +292,7 @@ private actor MySQLActor { throw MySQLError.connectionFailed("Failed to initialize MySQL client") } - mysql_options(handle, MYSQL_SET_CHARSET_NAME, "utf8mb4") + mysql_options(handle, MYSQL_SET_CHARSET_NAME, MySQLConnectionEncoding.sessionCharacterSetName) var timeout: UInt32 = 10 mysql_options(handle, MYSQL_OPT_CONNECT_TIMEOUT, &timeout) @@ -333,7 +346,13 @@ private actor MySQLActor { ) guard connected else { - let msg = String(cString: mysql_error(handle)) + let msg = message(from: handle) + mysql_close(handle) + throw MySQLError.connectionFailed(msg) + } + + guard MariaDBCharacterSet.establishSession(on: handle, encoding: encoding) else { + let msg = message(from: handle) mysql_close(handle) throw MySQLError.connectionFailed(msg) } @@ -351,11 +370,37 @@ private actor MySQLActor { func ping() throws -> Bool { guard let mysql else { throw MySQLError.notConnected } if mysql_ping(mysql) != 0 { - throw MySQLError.queryFailed(String(cString: mysql_error(mysql))) + throw MySQLError.queryFailed(message(from: mysql)) } return true } + private func legacyText(_ value: PluginCellValue) -> String? { + switch value { + case .null: + return nil + case .text(let text): + return text + case .bytes(let data): + return Self.hexText(data) + @unknown default: + return nil + } + } + + private static func hexText(_ data: Data) -> String { + let shown = data.prefix(hexPreviewBytes) + let hex = shown.map { String(format: "%02X", $0) }.joined() + return data.count > hexPreviewBytes ? "0x\(hex)…" : "0x\(hex)" + } + + private static let hexPreviewBytes = 256 + + private func message(from mysql: UnsafeMutablePointer) -> String { + guard let text = mysql_error(mysql) else { return "" } + return mysqlSessionText(cString: text, encoding: encoding) + } + func serverVersion() -> String? { guard let mysql else { return nil } return String(cString: mysql_get_server_info(mysql)) @@ -367,12 +412,12 @@ private actor MySQLActor { let start = Date() guard mysql_real_query(mysql, query, UInt(query.utf8.count)) == 0 else { - throw MySQLError.queryFailed(String(cString: mysql_error(mysql))) + throw MySQLError.queryFailed(message(from: mysql)) } guard let result = mysql_store_result(mysql) else { if mysql_field_count(mysql) != 0 { - throw MySQLError.queryFailed(String(cString: mysql_error(mysql))) + throw MySQLError.queryFailed(message(from: mysql)) } let raw = mysql_affected_rows(mysql) let affected = raw == .max ? 0 : Int(clamping: raw) @@ -384,16 +429,11 @@ private actor MySQLActor { defer { mysql_free_result(result) } let fieldCount = Int(mysql_num_fields(result)) - var columns: [String] = [] - var columnTypes: [String] = [] - - if let fields = mysql_fetch_fields(result) { - for i in 0..= maxRows @@ -435,6 +468,7 @@ private actor MySQLActor { private var streamingResult: UnsafeMutablePointer? private var streamingColumns: [ColumnInfo] = [] + private var streamingDecoding = MySQLResultColumns() func beginStream(query: String) throws -> MySQLBeginStreamResult { guard let mysql else { throw MySQLError.notConnected } @@ -443,12 +477,12 @@ private actor MySQLActor { } guard mysql_real_query(mysql, query, UInt(query.utf8.count)) == 0 else { - throw MySQLError.queryFailed(String(cString: mysql_error(mysql))) + throw MySQLError.queryFailed(message(from: mysql)) } guard let result = mysql_use_result(mysql) else { if mysql_field_count(mysql) != 0 { - throw MySQLError.queryFailed(String(cString: mysql_error(mysql))) + throw MySQLError.queryFailed(message(from: mysql)) } let raw = mysql_affected_rows(mysql) let affected = raw == .max ? 0 : Int(clamping: raw) @@ -457,23 +491,21 @@ private actor MySQLActor { streamingResult = result - let fieldCount = Int(mysql_num_fields(result)) - var columns: [ColumnInfo] = [] - if let fields = mysql_fetch_fields(result) { - for i in 0.. CellRef? { @@ -521,7 +557,8 @@ private actor MySQLActor { for pkColumn in lazyContext.primaryKeyColumns { guard let columnIndex = columns.firstIndex(where: { $0.name == pkColumn }) else { return nil } guard let cValue = row[columnIndex] else { return nil } - pkComponents.append(PrimaryKeyComponent(column: pkColumn, value: String(cString: cValue))) + let value = mysqlSessionText(cString: cValue, encoding: encoding) + pkComponents.append(PrimaryKeyComponent(column: pkColumn, value: value)) } return CellRef(table: lazyContext.table, column: column, primaryKey: pkComponents) } @@ -532,39 +569,6 @@ nonisolated enum MySQLBeginStreamResult: Sendable { case noResult(affectedRows: Int) } -// MARK: - MySQL Field Type Names - -nonisolated private func mysqlFieldTypeName(_ typeValue: UInt32) -> String { - switch typeValue { - case 0: return "DECIMAL" - case 1: return "TINYINT" - case 2: return "SMALLINT" - case 3: return "INT" - case 4: return "FLOAT" - case 5: return "DOUBLE" - case 6: return "NULL" - case 7: return "TIMESTAMP" - case 8: return "BIGINT" - case 9: return "MEDIUMINT" - case 10: return "DATE" - case 11: return "TIME" - case 12: return "DATETIME" - case 13: return "YEAR" - case 15: return "VARCHAR" - case 16: return "BIT" - case 245: return "JSON" - case 246: return "NEWDECIMAL" - case 249: return "TINYTEXT" - case 250: return "MEDIUMTEXT" - case 251: return "LONGTEXT" - case 252: return "TEXT" - case 253: return "VARCHAR" - case 254: return "CHAR" - case 255: return "GEOMETRY" - default: return "UNKNOWN" - } -} - nonisolated private struct RawMySQLResult: Sendable { let columns: [String] let columnTypes: [String] diff --git a/TableProMobile/TableProMobile/Platform/IOSDriverFactory.swift b/TableProMobile/TableProMobile/Platform/IOSDriverFactory.swift index 1752290732..e80d89083b 100644 --- a/TableProMobile/TableProMobile/Platform/IOSDriverFactory.swift +++ b/TableProMobile/TableProMobile/Platform/IOSDriverFactory.swift @@ -41,7 +41,8 @@ nonisolated final class IOSDriverFactory: DriverFactory { password: password ?? "", database: connection.database, ssl: try ssl(for: connection), - databaseType: connection.type + databaseType: connection.type, + connectionEncoding: MySQLConnectionEncoding(additionalFields: connection.additionalFields) ) case .postgresql, .redshift: return PostgreSQLDriver( diff --git a/TableProMobile/TableProMobileTests/Drivers/MySQLSharedDecodingTests.swift b/TableProMobile/TableProMobileTests/Drivers/MySQLSharedDecodingTests.swift new file mode 100644 index 0000000000..8bb79194ba --- /dev/null +++ b/TableProMobile/TableProMobileTests/Drivers/MySQLSharedDecodingTests.swift @@ -0,0 +1,43 @@ +import Foundation +@testable import TableProMobile +import Testing + +@Suite("MySQL shared decoding on iOS") +struct MySQLSharedDecodingTests { + @Test("The connection's Encoding field reaches the driver") + func encodingFieldIsRead() { + #expect(MySQLConnectionEncoding(additionalFields: [:]) == .utf8) + #expect(MySQLConnectionEncoding(additionalFields: ["mysqlConnectionEncoding": ""]) == .utf8) + #expect( + MySQLConnectionEncoding(additionalFields: ["mysqlConnectionEncoding": "utf8ViaLatin1"]) == .utf8ViaLatin1 + ) + } + + @Test("Text written through a Latin 1 connection reads as UTF-8 under the legacy encoding") + func legacyTextIsRepaired() { + let stored = String(bytes: [0xC3, 0xA3, 0xC6, 0x92, 0xC2, 0xA1], encoding: .utf8) ?? "" + #expect(MySQLConnectionEncoding.utf8.presentedText(stored) == stored) + #expect(MySQLConnectionEncoding.utf8ViaLatin1.presentedText(stored) == "メ") + } + + @Test("A latin1 column holding Latin 1 text uses MySQL's own latin1 table") + func latin1ColumnsDecode() { + let bytes: [UInt8] = [0x69, 0x74, 0x92, 0x73, 0x20, 0x35, 0x80] + let decoded = bytes.withUnsafeBytes { MySQLCharacterSet(serverName: "latin1").decode($0) } + #expect(decoded == "it’s 5€") + } + + @Test("A binary column stays bytes and a text column stays text") + func columnKindsSurvive() { + #expect(MySQLColumnDecoding(typeRaw: 252, charsetnr: 63, characterSetName: "binary") == .bytes) + #expect(MySQLColumnDecoding(typeRaw: 253, charsetnr: 45, characterSetName: "utf8mb4") == .text(.utf8mb4)) + } + + @Test("A BLOB column reports a binary type name, so the grid does not search it as text") + func blobTypeName() { + let blob = mariaDBTypeName(typeRaw: 252, flags: mysqlBinaryFlag, charsetnr: 63, length: 100) + #expect(blob == "BLOB") + #expect(mariaDBTypeName(typeRaw: 254, flags: mysqlBinaryFlag, charsetnr: 63, length: 16) == "BINARY") + #expect(mariaDBTypeName(typeRaw: 252, flags: 0, charsetnr: 45, length: 100) == "TEXT") + } +} diff --git a/TableProMobile/project.yml b/TableProMobile/project.yml index 64beabbf6d..716475f94f 100644 --- a/TableProMobile/project.yml +++ b/TableProMobile/project.yml @@ -52,6 +52,17 @@ targets: - ../Plugins/RedisDriverPlugin/RedisAuthCommand.swift - ../Plugins/RedisDriverPlugin/RedisConnectProbe.swift - ../Plugins/RedisDriverPlugin/RedisDatabaseIndex.swift + # MySQL session character set and result decoding the iOS driver shares with the macOS plugin. + - ../Plugins/MySQLDriverPlugin/DatabendResultShape.swift + - ../Plugins/MySQLDriverPlugin/GeometryWKBParser.swift + - ../Plugins/MySQLDriverPlugin/MariaDBCharacterSet.swift + - ../Plugins/MySQLDriverPlugin/MariaDBFieldClassifier.swift + - ../Plugins/MySQLDriverPlugin/MariaDBFieldMetadata.swift + - ../Plugins/MySQLDriverPlugin/MySQLCharacterSet.swift + - ../Plugins/MySQLDriverPlugin/MySQLColumnDecoding.swift + - ../Plugins/MySQLDriverPlugin/MySQLConnectionEncoding.swift + - ../Plugins/MySQLDriverPlugin/MySQLLatin1.swift + - ../Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift configFiles: Debug: ../Configs/Version-iOS.xcconfig Release: ../Configs/Version-iOS.xcconfig diff --git a/TableProTests/Plugins/MySQLConnectionEncodingTests.swift b/TableProTests/Plugins/MySQLConnectionEncodingTests.swift index 52218ceecd..c5080506c5 100644 --- a/TableProTests/Plugins/MySQLConnectionEncodingTests.swift +++ b/TableProTests/Plugins/MySQLConnectionEncodingTests.swift @@ -18,6 +18,13 @@ struct MySQLConnectionEncodingTests { #expect(MySQLConnectionEncoding(fieldValue: "utf8ViaLatin1") == .utf8ViaLatin1) } + @Test("The connection's additional fields resolve to an encoding") + func additionalFieldsParsing() { + #expect(MySQLConnectionEncoding(additionalFields: [:]) == .utf8) + #expect(MySQLConnectionEncoding(additionalFields: ["mysqlConnectionEncoding": "utf8ViaLatin1"]) == .utf8ViaLatin1) + #expect(MySQLConnectionEncoding(additionalFields: ["other": "utf8ViaLatin1"]) == .utf8) + } + @Test("Only UTF-8 via Latin 1 changes the client character set, and only the client's") func sessionStatements() { #expect(MySQLConnectionEncoding.utf8.sessionStatements.isEmpty) diff --git a/project.yml b/project.yml index f632d56e17..69d7414378 100644 --- a/project.yml +++ b/project.yml @@ -488,6 +488,7 @@ targets: - Plugins/MySQLDriverPlugin/MySQLIdleRelease.swift - Plugins/MySQLDriverPlugin/MySQLSessionFootprint.swift - Plugins/MySQLDriverPlugin/MySQLGeneratedColumnClassification.swift + - Plugins/MySQLDriverPlugin/MySQLKillTarget.swift - Plugins/MySQLDriverPlugin/MySQLObjectQueries.swift - Plugins/MySQLDriverPlugin/MySQLSelectLimitStatement.swift - Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift From af1c60ec16163fadbda563b8f11a0751f8006d83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Nam=20Long?= Date: Fri, 11 Sep 2026 17:03:45 +0000 Subject: [PATCH 08/54] ci(plugin-mysql): retrigger macOS tests after XcodeGen checksum flake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nguyễn Nam Long From 9aa90bdbbac5e50a7a8e99a6e66e87967d5682a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 00:07:42 +0700 Subject: [PATCH 09/54] fix(datagrid): draw the data grid in the theme's own colors (#2745) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ngô Quốc Đạt --- CHANGELOG.md | 5 + .../Services/Formatting/StoredBoolean.swift | 29 +++ .../Highlight/HighlightCondition.swift | 24 +- .../Themes/tablepro.default-dark.json | 10 +- .../Themes/tablepro.default-light.json | 10 +- .../Resources/Themes/tablepro.dracula.json | 3 +- TablePro/Resources/Themes/tablepro.nord.json | 3 +- TablePro/Theme/ResolvedThemeColors.swift | 40 ++- TablePro/Theme/ThemeColors.swift | 65 +++-- .../Cells/DataGridCellAppearance.swift | 15 +- .../Results/Cells/DataGridCellPalette.swift | 15 ++ .../Results/Cells/DataGridCellRegistry.swift | 7 +- .../Views/Results/DataGridBodyChrome.swift | 32 ++- .../Views/Results/DataGridCoordinator.swift | 3 + .../Views/Results/DataGridRowGutterView.swift | 12 +- TablePro/Views/Results/DataGridRowView.swift | 15 +- TablePro/Views/Results/DataGridView.swift | 1 + .../Appearance/ThemeEditorColorsSection.swift | 42 ++-- .../Views/Settings/ThemePreviewCard.swift | 26 +- .../Theme/DataGridThemeColorsTests.swift | 235 ++++++++++++++++++ .../Results/DataGridCellAppearanceTests.swift | 80 +++++- .../DataGridRowNumberRenderingTests.swift | 38 +++ docs/customization/appearance.mdx | 8 +- 23 files changed, 564 insertions(+), 154 deletions(-) create mode 100644 TablePro/Core/Services/Formatting/StoredBoolean.swift create mode 100644 TableProTests/Theme/DataGridThemeColorsTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e9021fec4..d7f0353f34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,8 +36,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Beancount connections held at Safe Mode Read-Only. (#2030) - MySQL sessions on the server's default `utf8mb4` collation. +### Removed + +- Focus Border color in the theme editor. + ### Fixed +- Data grid ignoring the theme's background, text, alternate row, NULL, boolean and row number colors. - Garbled non-Latin text saved from iPhone and iPad to MySQL servers that force a Latin 1 session. (#2725) - **Encoding** ignored on iPhone and iPad by a MySQL connection synced from the Mac. (#2725) - Binary MySQL columns shown as text on iPhone and iPad, and searched with `LIKE`. diff --git a/TablePro/Core/Services/Formatting/StoredBoolean.swift b/TablePro/Core/Services/Formatting/StoredBoolean.swift new file mode 100644 index 0000000000..c558be3cfa --- /dev/null +++ b/TablePro/Core/Services/Formatting/StoredBoolean.swift @@ -0,0 +1,29 @@ +// +// StoredBoolean.swift +// TablePro +// + +import Foundation +import TableProPluginKit + +enum StoredBoolean { + static func value(of text: String) -> Bool? { + let trimmed = text.trimmingCharacters(in: .whitespaces) + switch PluginSQLLiteral.booleanSynonym(for: trimmed) { + case .isTrue: + return true + case .isFalse: + return false + default: + break + } + switch trimmed.lowercased() { + case "t": + return true + case "f": + return false + default: + return nil + } + } +} diff --git a/TablePro/Core/Services/Highlight/HighlightCondition.swift b/TablePro/Core/Services/Highlight/HighlightCondition.swift index 2f16f6e85c..2f941ab2ad 100644 --- a/TablePro/Core/Services/Highlight/HighlightCondition.swift +++ b/TablePro/Core/Services/Highlight/HighlightCondition.swift @@ -25,7 +25,7 @@ struct HighlightCondition { let trimmed = raw.trimmingCharacters(in: .whitespaces) text = raw number = HighlightCondition.number(from: trimmed) - boolean = HighlightCondition.boolean(from: trimmed) + boolean = StoredBoolean.value(of: trimmed) isNullLiteral = allowsNullLiteral && HighlightCondition.isNullKeyword(trimmed) } } @@ -138,7 +138,7 @@ struct HighlightCondition { if prefersNumbers, let lhs = Self.number(from: text), let rhs = operand.number { return Self.compare(lhs, rhs) } - if prefersBooleans, let lhs = Self.boolean(from: text), let rhs = operand.boolean { + if prefersBooleans, let lhs = StoredBoolean.value(of: text), let rhs = operand.boolean { return Self.compare(lhs ? 1 : 0, rhs ? 1 : 0) } return text.compare(operand.text, options: comparesCaseInsensitively ? [.caseInsensitive] : [.literal]) @@ -247,26 +247,6 @@ struct HighlightCondition { return Decimal(string: trimmed, locale: Locale(identifier: "en_US_POSIX")) } - static func boolean(from text: String) -> Bool? { - let trimmed = text.trimmingCharacters(in: .whitespaces) - switch PluginSQLLiteral.booleanSynonym(for: trimmed) { - case .isTrue: - return true - case .isFalse: - return false - default: - break - } - switch trimmed.lowercased() { - case "t": - return true - case "f": - return false - default: - return nil - } - } - private static func compare(_ lhs: Value, _ rhs: Value) -> ComparisonResult { if lhs < rhs { return .orderedAscending } if lhs > rhs { return .orderedDescending } diff --git a/TablePro/Resources/Themes/tablepro.default-dark.json b/TablePro/Resources/Themes/tablepro.default-dark.json index 48e2450078..d28e2b4149 100644 --- a/TablePro/Resources/Themes/tablepro.default-dark.json +++ b/TablePro/Resources/Themes/tablepro.default-dark.json @@ -25,18 +25,10 @@ } }, "dataGrid": { - "background": "#1E1E1E", - "text": "#D4D4D4", - "alternateRow": "#FFFFFF08", - "nullValue": "#858585", - "boolTrue": "#32D74B", - "boolFalse": "#FF453A", - "rowNumber": "#858585", "modified": "#FFD60A4D", "inserted": "#32D74B26", "deleted": "#FF453A26", - "deletedText": "#FF453A80", - "focusBorder": "#007AFF" + "deletedText": "#FF453A80" }, "ui": { "accentColor": null, diff --git a/TablePro/Resources/Themes/tablepro.default-light.json b/TablePro/Resources/Themes/tablepro.default-light.json index 8d4b7b0115..4de5f91386 100644 --- a/TablePro/Resources/Themes/tablepro.default-light.json +++ b/TablePro/Resources/Themes/tablepro.default-light.json @@ -25,18 +25,10 @@ } }, "dataGrid": { - "background": "#FFFFFF", - "text": "#000000", - "alternateRow": "#F5F5F5", - "nullValue": "#8E8E93", - "boolTrue": "#248A3D", - "boolFalse": "#D70015", - "rowNumber": "#8E8E93", "modified": "#FFD60A4D", "inserted": "#34C7594D", "deleted": "#FF3B304D", - "deletedText": "#FF3B3080", - "focusBorder": "#007AFF" + "deletedText": "#FF3B3080" }, "ui": { "accentColor": null, diff --git a/TablePro/Resources/Themes/tablepro.dracula.json b/TablePro/Resources/Themes/tablepro.dracula.json index 77a1459646..083586caf0 100644 --- a/TablePro/Resources/Themes/tablepro.dracula.json +++ b/TablePro/Resources/Themes/tablepro.dracula.json @@ -35,8 +35,7 @@ "modified": "#FFB86C4D", "inserted": "#50FA7B26", "deleted": "#FF555526", - "deletedText": "#FF555580", - "focusBorder": "#BD93F9" + "deletedText": "#FF555580" }, "ui": { "windowBackground": "#282A36", diff --git a/TablePro/Resources/Themes/tablepro.nord.json b/TablePro/Resources/Themes/tablepro.nord.json index 884cb69034..7b9c17c916 100644 --- a/TablePro/Resources/Themes/tablepro.nord.json +++ b/TablePro/Resources/Themes/tablepro.nord.json @@ -35,8 +35,7 @@ "modified": "#EBCB8B4D", "inserted": "#A3BE8C26", "deleted": "#BF616A26", - "deletedText": "#BF616A80", - "focusBorder": "#88C0D0" + "deletedText": "#BF616A80" }, "ui": { "windowBackground": "#2E3440", diff --git a/TablePro/Theme/ResolvedThemeColors.swift b/TablePro/Theme/ResolvedThemeColors.swift index 1c6dff20a2..8557126d58 100644 --- a/TablePro/Theme/ResolvedThemeColors.swift +++ b/TablePro/Theme/ResolvedThemeColors.swift @@ -79,13 +79,9 @@ struct ResolvedDataGridColors { let alternateRow: NSColor let alternateRowSwiftUI: Color let nullValue: NSColor - let nullValueSwiftUI: Color - let boolTrue: NSColor - let boolTrueSwiftUI: Color - let boolFalse: NSColor - let boolFalseSwiftUI: Color + let boolTrue: NSColor? + let boolFalse: NSColor? let rowNumber: NSColor - let rowNumberSwiftUI: Color let modified: NSColor let modifiedSwiftUI: Color @@ -99,24 +95,17 @@ struct ResolvedDataGridColors { let deletedText: NSColor let deletedTextSwiftUI: Color - let focusBorder: NSColor - let focusBorderCG: CGColor - init(from colors: DataGridThemeColors) { - background = colors.background.nsColor - backgroundSwiftUI = colors.background.swiftUIColor - text = colors.text.nsColor - textSwiftUI = colors.text.swiftUIColor - alternateRow = colors.alternateRow.nsColor - alternateRowSwiftUI = colors.alternateRow.swiftUIColor - nullValue = colors.nullValue.nsColor - nullValueSwiftUI = colors.nullValue.swiftUIColor - boolTrue = colors.boolTrue.nsColor - boolTrueSwiftUI = colors.boolTrue.swiftUIColor - boolFalse = colors.boolFalse.nsColor - boolFalseSwiftUI = colors.boolFalse.swiftUIColor - rowNumber = colors.rowNumber.nsColor - rowNumberSwiftUI = colors.rowNumber.swiftUIColor + background = colors.background?.nsColor ?? .controlBackgroundColor + backgroundSwiftUI = colors.background?.swiftUIColor ?? Color(nsColor: .controlBackgroundColor) + text = colors.text?.nsColor ?? .labelColor + textSwiftUI = colors.text?.swiftUIColor ?? Color(nsColor: .labelColor) + alternateRow = colors.alternateRow?.nsColor ?? Self.systemAlternateRow + alternateRowSwiftUI = colors.alternateRow?.swiftUIColor ?? Color(nsColor: Self.systemAlternateRow) + nullValue = colors.nullValue?.nsColor ?? .secondaryLabelColor + boolTrue = colors.boolTrue?.nsColor + boolFalse = colors.boolFalse?.nsColor + rowNumber = colors.rowNumber?.nsColor ?? .secondaryLabelColor modified = colors.modified.nsColor modifiedSwiftUI = colors.modified.swiftUIColor @@ -129,9 +118,10 @@ struct ResolvedDataGridColors { deletedCG = colors.deleted.cgColor deletedText = colors.deletedText.nsColor deletedTextSwiftUI = colors.deletedText.swiftUIColor + } - focusBorder = colors.focusBorder.nsColor - focusBorderCG = colors.focusBorder.cgColor + private static var systemAlternateRow: NSColor { + NSColor.alternatingContentBackgroundColors.last ?? .controlBackgroundColor } } diff --git a/TablePro/Theme/ThemeColors.swift b/TablePro/Theme/ThemeColors.swift index 7fbb9bddd7..1b4fbd47c1 100644 --- a/TablePro/Theme/ThemeColors.swift +++ b/TablePro/Theme/ThemeColors.swift @@ -131,47 +131,44 @@ internal struct EditorThemeColors: Codable, Equatable, Sendable { // MARK: - Data Grid Theme Colors internal struct DataGridThemeColors: Codable, Equatable, Sendable { - var background: String - var text: String - var alternateRow: String - var nullValue: String - var boolTrue: String - var boolFalse: String - var rowNumber: String + var background: String? + var text: String? + var alternateRow: String? + var nullValue: String? + var boolTrue: String? + var boolFalse: String? + var rowNumber: String? var modified: String var inserted: String var deleted: String var deletedText: String - var focusBorder: String static let defaultLight = DataGridThemeColors( - background: "#FFFFFF", - text: "#000000", - alternateRow: "#F5F5F5", - nullValue: "#8E8E93", - boolTrue: "#248A3D", - boolFalse: "#D70015", - rowNumber: "#8E8E93", + background: nil, + text: nil, + alternateRow: nil, + nullValue: nil, + boolTrue: nil, + boolFalse: nil, + rowNumber: nil, modified: "#FFD60A4D", inserted: "#34C7594D", deleted: "#FF3B304D", - deletedText: "#FF3B3080", - focusBorder: "#007AFF" + deletedText: "#FF3B3080" ) init( - background: String, - text: String, - alternateRow: String, - nullValue: String, - boolTrue: String, - boolFalse: String, - rowNumber: String, + background: String?, + text: String?, + alternateRow: String?, + nullValue: String?, + boolTrue: String?, + boolFalse: String?, + rowNumber: String?, modified: String, inserted: String, deleted: String, - deletedText: String, - focusBorder: String + deletedText: String ) { self.background = background self.text = text @@ -184,25 +181,23 @@ internal struct DataGridThemeColors: Codable, Equatable, Sendable { self.inserted = inserted self.deleted = deleted self.deletedText = deletedText - self.focusBorder = focusBorder } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let fallback = DataGridThemeColors.defaultLight - background = try container.decodeIfPresent(String.self, forKey: .background) ?? fallback.background - text = try container.decodeIfPresent(String.self, forKey: .text) ?? fallback.text - alternateRow = try container.decodeIfPresent(String.self, forKey: .alternateRow) ?? fallback.alternateRow - nullValue = try container.decodeIfPresent(String.self, forKey: .nullValue) ?? fallback.nullValue - boolTrue = try container.decodeIfPresent(String.self, forKey: .boolTrue) ?? fallback.boolTrue - boolFalse = try container.decodeIfPresent(String.self, forKey: .boolFalse) ?? fallback.boolFalse - rowNumber = try container.decodeIfPresent(String.self, forKey: .rowNumber) ?? fallback.rowNumber + background = try container.decodeIfPresent(String.self, forKey: .background) + text = try container.decodeIfPresent(String.self, forKey: .text) + alternateRow = try container.decodeIfPresent(String.self, forKey: .alternateRow) + nullValue = try container.decodeIfPresent(String.self, forKey: .nullValue) + boolTrue = try container.decodeIfPresent(String.self, forKey: .boolTrue) + boolFalse = try container.decodeIfPresent(String.self, forKey: .boolFalse) + rowNumber = try container.decodeIfPresent(String.self, forKey: .rowNumber) modified = try container.decodeIfPresent(String.self, forKey: .modified) ?? fallback.modified inserted = try container.decodeIfPresent(String.self, forKey: .inserted) ?? fallback.inserted deleted = try container.decodeIfPresent(String.self, forKey: .deleted) ?? fallback.deleted deletedText = try container.decodeIfPresent(String.self, forKey: .deletedText) ?? fallback.deletedText - focusBorder = try container.decodeIfPresent(String.self, forKey: .focusBorder) ?? fallback.focusBorder } } diff --git a/TablePro/Views/Results/Cells/DataGridCellAppearance.swift b/TablePro/Views/Results/Cells/DataGridCellAppearance.swift index 01b03621fe..d140ec35f0 100644 --- a/TablePro/Views/Results/Cells/DataGridCellAppearance.swift +++ b/TablePro/Views/Results/Cells/DataGridCellAppearance.swift @@ -42,10 +42,10 @@ struct DataGridCellAppearance: Equatable { switch content.placeholder { case .none: font = palette.regularFont - baseColor = deletedTextColor ?? .labelColor + baseColor = deletedTextColor ?? valueTextColor(kind: kind, rawValue: content.rawValue, palette: palette) case .null, .empty: font = palette.italicFont - baseColor = deletedTextColor ?? .secondaryLabelColor + baseColor = deletedTextColor ?? palette.placeholderText case .defaultMarker: font = palette.mediumFont baseColor = deletedTextColor ?? .systemBlue @@ -104,4 +104,15 @@ struct DataGridCellAppearance: Equatable { drawsFocusRing: isCursorVisible && !onEmphasizedSelection ) } + + private static func valueTextColor( + kind: DataGridCellKind, + rawValue: String?, + palette: DataGridCellPalette + ) -> NSColor { + guard kind == .boolean, let rawValue, let isTrue = StoredBoolean.value(of: rawValue) else { + return palette.text + } + return (isTrue ? palette.booleanTrueText : palette.booleanFalseText) ?? palette.text + } } diff --git a/TablePro/Views/Results/Cells/DataGridCellPalette.swift b/TablePro/Views/Results/Cells/DataGridCellPalette.swift index a0f56df65b..0ddabe24fe 100644 --- a/TablePro/Views/Results/Cells/DataGridCellPalette.swift +++ b/TablePro/Views/Results/Cells/DataGridCellPalette.swift @@ -10,6 +10,11 @@ struct DataGridCellPalette: Equatable { let regularFont: NSFont let italicFont: NSFont let mediumFont: NSFont + let text: NSColor + let placeholderText: NSColor + let booleanTrueText: NSColor? + let booleanFalseText: NSColor? + let rowNumberText: NSColor let deletedRowText: NSColor let modifiedColumnTint: NSColor let findMatchTint: NSColor @@ -18,6 +23,11 @@ struct DataGridCellPalette: Equatable { regularFont: .systemFont(ofSize: NSFont.systemFontSize), italicFont: .systemFont(ofSize: NSFont.systemFontSize), mediumFont: .systemFont(ofSize: NSFont.systemFontSize, weight: .medium), + text: .labelColor, + placeholderText: .secondaryLabelColor, + booleanTrueText: nil, + booleanFalseText: nil, + rowNumberText: .secondaryLabelColor, deletedRowText: .secondaryLabelColor, modifiedColumnTint: .systemYellow, findMatchTint: .findHighlightColor @@ -30,6 +40,11 @@ extension ThemeEngine { regularFont: dataGridFonts.regular, italicFont: dataGridFonts.italic, mediumFont: dataGridFonts.medium, + text: colors.dataGrid.text, + placeholderText: colors.dataGrid.nullValue, + booleanTrueText: colors.dataGrid.boolTrue, + booleanFalseText: colors.dataGrid.boolFalse, + rowNumberText: colors.dataGrid.rowNumber, deletedRowText: colors.dataGrid.deletedText, modifiedColumnTint: colors.dataGrid.modified, findMatchTint: .findHighlightColor diff --git a/TablePro/Views/Results/Cells/DataGridCellRegistry.swift b/TablePro/Views/Results/Cells/DataGridCellRegistry.swift index f7bb521a1f..781084b970 100644 --- a/TablePro/Views/Results/Cells/DataGridCellRegistry.swift +++ b/TablePro/Views/Results/Cells/DataGridCellRegistry.swift @@ -57,7 +57,6 @@ final class DataGridCellRegistry { cell.alignment = .right cell.font = ThemeEngine.shared.dataGridFonts.rowNumber cell.tag = DataGridFontVariant.rowNumber - cell.textColor = .secondaryLabelColor cell.translatesAutoresizingMaskIntoConstraints = false cellView.textField = cell @@ -76,6 +75,7 @@ final class DataGridCellRegistry { ]) } + cell.textColor = rowNumberColor(for: visualState) guard row >= 0 && row < cachedRowCount else { cell.stringValue = "" return cellView @@ -83,10 +83,13 @@ final class DataGridCellRegistry { let displayNumber = row + pageOffset + 1 cell.stringValue = "\(displayNumber)" - cell.textColor = visualState.isDeleted ? ThemeEngine.shared.colors.dataGrid.deletedText : .secondaryLabelColor cellView.setAccessibilityLabel(String(format: String(localized: "Row %d"), displayNumber)) cellView.setAccessibilityRowIndexRange(NSRange(location: row, length: 1)) return cellView } + + func rowNumberColor(for visualState: RowVisualState) -> NSColor { + visualState.isDeleted ? palette.deletedRowText : palette.rowNumberText + } } diff --git a/TablePro/Views/Results/DataGridBodyChrome.swift b/TablePro/Views/Results/DataGridBodyChrome.swift index 4c40ee3f9b..99685798b2 100644 --- a/TablePro/Views/Results/DataGridBodyChrome.swift +++ b/TablePro/Views/Results/DataGridBodyChrome.swift @@ -114,13 +114,35 @@ enum DataGridBodyChrome { return bands } - /// The alternate stripe `NSTableRowView` paints for a row, or nil when the table does not - /// alternate, where a row shows the table's own background. + /// The theme's background, falling back to the system's, for the table to paint itself with. + /// + /// Set on the table rather than read from the theme at each draw, because AppKit reads the + /// table's own `backgroundColor` too, for the area an elastic scroll uncovers. + static func applyBackground(to tableView: NSTableView) { + let background = ThemeEngine.shared.colors.dataGrid.background + guard tableView.backgroundColor != background else { return } + tableView.backgroundColor = background + } + + /// The alternate stripe a row carries, or nil when the table does not alternate, where a row + /// shows the table's own background. + /// + /// The theme's pair when it declares one, otherwise `NSColor.alternatingContentBackgroundColors`, + /// which is the pair `NSTableView` itself hands its row views. static func stripeColor(forRow row: Int, of tableView: NSTableView) -> NSColor? { guard tableView.usesAlternatingRowBackgroundColors else { return nil } - let stripes = NSColor.alternatingContentBackgroundColors - guard !stripes.isEmpty else { return nil } - return stripes[row % stripes.count] + return row.isMultiple(of: 2) + ? ThemeEngine.shared.colors.dataGrid.background + : ThemeEngine.shared.colors.dataGrid.alternateRow + } + + /// What a row view lays down before its tint and selection: its stripe, or the table's own + /// background when the table does not alternate. + /// + /// Painted by `DataGridRowView` itself rather than by `NSTableRowView`, which paints the system + /// stripes whatever the theme declares. + static func rowBackgroundColor(forRow row: Int, of tableView: NSTableView) -> NSColor { + stripeColor(forRow: row, of: tableView) ?? tableView.backgroundColor } /// Lays `background` down and blends `layers` over it bottom to top, which is the colour a row diff --git a/TablePro/Views/Results/DataGridCoordinator.swift b/TablePro/Views/Results/DataGridCoordinator.swift index 28e2f55309..9843474696 100644 --- a/TablePro/Views/Results/DataGridCoordinator.swift +++ b/TablePro/Views/Results/DataGridCoordinator.swift @@ -610,6 +610,9 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData themeCancellable = AppEvents.shared.themeChanged .receive(on: RunLoop.main) .sink { [weak self] _ in + if let tableView = self?.tableView { + DataGridBodyChrome.applyBackground(to: tableView) + } self?.reloadVisibleRowsAndStates() /// The row-number font is a theme value and it decides the column's width, which /// the pinned gutter mirrors. Nothing re-measured it on a theme change before, so diff --git a/TablePro/Views/Results/DataGridRowGutterView.swift b/TablePro/Views/Results/DataGridRowGutterView.swift index 25df1a1085..6d972b54be 100644 --- a/TablePro/Views/Results/DataGridRowGutterView.swift +++ b/TablePro/Views/Results/DataGridRowGutterView.swift @@ -152,7 +152,7 @@ final class DataGridRowGutterView: NSView { band.row + pageOffset + 1, in: NSRect(x: cellFrame.minX, y: stripRect.minY, width: cellFrame.width, height: stripRect.height), font: font, - color: numberColor(isSelected: isSelected, emphasized: emphasized, state: state) + color: numberColor(isSelected: isSelected, emphasized: emphasized, state: state, coordinator: coordinator) ) } @@ -182,10 +182,14 @@ final class DataGridRowGutterView: NSView { return layers } - private func numberColor(isSelected: Bool, emphasized: Bool, state: RowVisualState) -> NSColor { + private func numberColor( + isSelected: Bool, + emphasized: Bool, + state: RowVisualState, + coordinator: TableViewCoordinator + ) -> NSColor { if isSelected, emphasized { return .alternateSelectedControlTextColor } - if state.isDeleted { return ThemeEngine.shared.colors.dataGrid.deletedText } - return .secondaryLabelColor + return coordinator.cellRegistry.rowNumberColor(for: state) } /// Right-aligned inside the cell frame AppKit gives the mounted row-number cell, with the insets diff --git a/TablePro/Views/Results/DataGridRowView.swift b/TablePro/Views/Results/DataGridRowView.swift index 53faf4f8f1..a083518d32 100644 --- a/TablePro/Views/Results/DataGridRowView.swift +++ b/TablePro/Views/Results/DataGridRowView.swift @@ -229,7 +229,7 @@ class DataGridRowView: NSTableRowView { } override func drawBackground(in dirtyRect: NSRect) { - super.drawBackground(in: dirtyRect) + drawRowBackground(in: dirtyRect) if !isSelected, let tint = visualState.tint { tint.setFill() bounds.fill() @@ -237,6 +237,19 @@ class DataGridRowView: NSTableRowView { drawCellSelectionFill(in: dirtyRect) } + /// The row's stripe from `DataGridBodyChrome`, the owner the pinned gutter and the area past the + /// last row read too, rather than the `backgroundColor` the table assigns, which is only ever the + /// system's. A row outside a table has no stripe, and AppKit's own drawing already leaves it clear: + /// its `backgroundColor` is nil there, so it must not be read. + private func drawRowBackground(in dirtyRect: NSRect) { + guard let tableView = coordinator?.tableView else { + super.drawBackground(in: dirtyRect) + return + } + DataGridBodyChrome.rowBackgroundColor(forRow: rowIndex, of: tableView).setFill() + dirtyRect.fill() + } + /// A cell range on a row the table has selected is already covered by `NSTableRowView`'s own /// selection fill, which runs after this, so only the remaining rows are painted here. private func drawCellSelectionFill(in dirtyRect: NSRect) { diff --git a/TablePro/Views/Results/DataGridView.swift b/TablePro/Views/Results/DataGridView.swift index baabbbbcca..98e2c01400 100644 --- a/TablePro/Views/Results/DataGridView.swift +++ b/TablePro/Views/Results/DataGridView.swift @@ -137,6 +137,7 @@ struct DataGridView: NSViewRepresentable { tableView.intercellSpacing = NSSize(width: 1, height: 0) tableView.rowHeight = CGFloat(settings.rowHeight.rawValue) tableView.usesAutomaticRowHeights = false + DataGridBodyChrome.applyBackground(to: tableView) tableView.delegate = context.coordinator tableView.dataSource = context.coordinator diff --git a/TablePro/Views/Settings/Appearance/ThemeEditorColorsSection.swift b/TablePro/Views/Settings/Appearance/ThemeEditorColorsSection.swift index 5eb4690197..5e2c70ab6f 100644 --- a/TablePro/Views/Settings/Appearance/ThemeEditorColorsSection.swift +++ b/TablePro/Views/Settings/Appearance/ThemeEditorColorsSection.swift @@ -108,28 +108,23 @@ internal struct ThemeEditorColorsSection: View { // MARK: - Data Grid private var dataGridSection: some View { - Section(String(localized: "Data Grid")) { - LabeledContent(String(localized: "Background")) { - HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.background)) - } - LabeledContent(String(localized: "Text")) { - HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.text)) - } - LabeledContent(String(localized: "Alternate Row")) { - HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.alternateRow)) - } - LabeledContent(String(localized: "NULL Value")) { - HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.nullValue)) - } - LabeledContent(String(localized: "Bool True")) { - HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.boolTrue)) - } - LabeledContent(String(localized: "Bool False")) { - HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.boolFalse)) - } - LabeledContent(String(localized: "Row Number")) { - HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.rowNumber)) - } + let system = ResolvedDataGridColors(from: .defaultLight) + let resolved = ResolvedDataGridColors(from: theme.dataGrid) + return Section(String(localized: "Data Grid")) { + optionalColorRow(String(localized: "Background"), keyPath: \.dataGrid.background, + fallback: system.background) + optionalColorRow(String(localized: "Text"), keyPath: \.dataGrid.text, + fallback: system.text) + optionalColorRow(String(localized: "Alternate Row"), keyPath: \.dataGrid.alternateRow, + fallback: system.alternateRow) + optionalColorRow(String(localized: "NULL Value"), keyPath: \.dataGrid.nullValue, + fallback: system.nullValue) + optionalColorRow(String(localized: "Bool True"), keyPath: \.dataGrid.boolTrue, + fallback: resolved.text) + optionalColorRow(String(localized: "Bool False"), keyPath: \.dataGrid.boolFalse, + fallback: resolved.text) + optionalColorRow(String(localized: "Row Number"), keyPath: \.dataGrid.rowNumber, + fallback: system.rowNumber) LabeledContent(String(localized: "Modified")) { HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.modified)) } @@ -142,9 +137,6 @@ internal struct ThemeEditorColorsSection: View { LabeledContent(String(localized: "Deleted Text")) { HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.deletedText)) } - LabeledContent(String(localized: "Focus Border")) { - HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.focusBorder)) - } } } diff --git a/TablePro/Views/Settings/ThemePreviewCard.swift b/TablePro/Views/Settings/ThemePreviewCard.swift index 3302f4e1bf..0efd021cf5 100644 --- a/TablePro/Views/Settings/ThemePreviewCard.swift +++ b/TablePro/Views/Settings/ThemePreviewCard.swift @@ -18,6 +18,8 @@ struct ThemePreviewCard: View { let onSelect: () -> Void var size: CardSize = .standard + @Environment(\.colorScheme) private var colorScheme + var body: some View { switch size { case .standard: @@ -99,6 +101,20 @@ struct ThemePreviewCard: View { dataGridArea } } + .environment(\.colorScheme, previewColorScheme) + } + + /// The system colours a theme leaves undeclared resolve in the appearance the theme is used + /// in, not in whichever one Settings happens to be showing. + private var previewColorScheme: ColorScheme { + switch theme.appearance { + case .dark: + return .dark + case .light: + return .light + case .auto: + return colorScheme + } } private var sidebarStrip: some View { @@ -169,22 +185,22 @@ struct ThemePreviewCard: View { } private var dataGridArea: some View { - VStack(spacing: 0) { + let colors = ResolvedDataGridColors(from: theme.dataGrid) + return VStack(spacing: 0) { ForEach(0.. NSColor? { + color?.usingColorSpace(.sRGB) + } + + private func matches(_ lhs: NSColor?, _ hex: String) -> Bool { + guard let lhs = sRGB(lhs), let rhs = sRGB(hex.nsColor) else { return false } + return abs(lhs.redComponent - rhs.redComponent) < 0.01 + && abs(lhs.greenComponent - rhs.greenComponent) < 0.01 + && abs(lhs.blueComponent - rhs.blueComponent) < 0.01 + && abs(lhs.alphaComponent - rhs.alphaComponent) < 0.01 + } + + private func withTheme(_ configure: (inout DataGridThemeColors) -> Void, _ body: () throws -> Void) rethrows { + let engine = ThemeEngine.shared + let original = engine.activeTheme + defer { engine.activateTheme(original) } + var theme = ThemeDefinition.default + theme.id = "test.grid-colors" + configure(&theme.dataGrid) + engine.activateTheme(theme) + try body() + } + + // MARK: - Decoding + + @Test("An undeclared grid color decodes as absent, a state tint as the default") + func emptyGroupDecodes() throws { + let decoded = try JSONDecoder().decode(DataGridThemeColors.self, from: Data("{}".utf8)) + + #expect(decoded == DataGridThemeColors.defaultLight) + #expect(decoded.background == nil) + #expect(decoded.boolTrue == nil) + #expect(decoded.modified == DataGridThemeColors.defaultLight.modified) + } + + @Test("A theme written with focusBorder still decodes, and the key is dropped on save") + func focusBorderIsIgnored() throws { + let json = """ + { "background": "#282A36", "text": "#F8F8F2", "focusBorder": "#BD93F9", "deleted": "#FF555526" } + """ + let decoded = try JSONDecoder().decode(DataGridThemeColors.self, from: Data(json.utf8)) + let encoded = try #require(String(data: JSONEncoder().encode(decoded), encoding: .utf8)) + + #expect(decoded.background == "#282A36") + #expect(decoded.text == "#F8F8F2") + #expect(decoded.deleted == "#FF555526") + #expect(!encoded.contains("focusBorder")) + } + + @Test("An undeclared grid color is left out of the saved file") + func undeclaredColorsAreNotWritten() throws { + let encoded = try #require(String(data: JSONEncoder().encode(DataGridThemeColors.defaultLight), encoding: .utf8)) + + for key in Self.systemDefaultedKeys { + #expect(!encoded.contains("\"\(key)\""), "\(key) was written") + } + } + + // MARK: - Resolution + + @Test("An undeclared grid color resolves to the color the grid draws without a theme") + func undeclaredColorsResolveToSystem() { + let resolved = ResolvedDataGridColors(from: .defaultLight) + + #expect(resolved.background == .controlBackgroundColor) + #expect(resolved.text == .labelColor) + #expect(resolved.alternateRow == NSColor.alternatingContentBackgroundColors.last) + #expect(resolved.nullValue == .secondaryLabelColor) + #expect(resolved.rowNumber == .secondaryLabelColor) + #expect(resolved.boolTrue == nil) + #expect(resolved.boolFalse == nil) + } + + @Test("A declared grid color resolves to its own value") + func declaredColorsResolve() { + var colors = DataGridThemeColors.defaultLight + colors.background = "#102030" + colors.text = "#405060" + colors.alternateRow = "#708090" + colors.nullValue = "#A0B0C0" + colors.boolTrue = "#00FF00" + colors.boolFalse = "#FF0000" + colors.rowNumber = "#123456" + let resolved = ResolvedDataGridColors(from: colors) + + #expect(matches(resolved.background, "#102030")) + #expect(matches(resolved.text, "#405060")) + #expect(matches(resolved.alternateRow, "#708090")) + #expect(matches(resolved.nullValue, "#A0B0C0")) + #expect(matches(resolved.boolTrue, "#00FF00")) + #expect(matches(resolved.boolFalse, "#FF0000")) + #expect(matches(resolved.rowNumber, "#123456")) + } + + // MARK: - The grid reads them + + @Test("The table and its stripes take the theme's background and alternate row") + func stripesFollowTheTheme() { + withTheme({ + $0.background = "#102030" + $0.alternateRow = "#708090" + }) { + let tableView = NSTableView() + tableView.usesAlternatingRowBackgroundColors = true + DataGridBodyChrome.applyBackground(to: tableView) + + #expect(matches(tableView.backgroundColor, "#102030")) + #expect(matches(DataGridBodyChrome.stripeColor(forRow: 0, of: tableView), "#102030")) + #expect(matches(DataGridBodyChrome.stripeColor(forRow: 1, of: tableView), "#708090")) + #expect(matches(DataGridBodyChrome.rowBackgroundColor(forRow: 3, of: tableView), "#708090")) + + tableView.usesAlternatingRowBackgroundColors = false + #expect(DataGridBodyChrome.stripeColor(forRow: 1, of: tableView) == nil) + #expect(matches(DataGridBodyChrome.rowBackgroundColor(forRow: 1, of: tableView), "#102030")) + } + } + + @Test("Without grid colors the stripes are the pair NSTableView hands its rows") + func stripesFallBackToSystem() { + withTheme({ _ in }) { + let tableView = NSTableView() + tableView.usesAlternatingRowBackgroundColors = true + DataGridBodyChrome.applyBackground(to: tableView) + let system = NSColor.alternatingContentBackgroundColors + + #expect(tableView.backgroundColor == .controlBackgroundColor) + #expect(DataGridBodyChrome.stripeColor(forRow: 0, of: tableView) == system.first) + #expect(DataGridBodyChrome.stripeColor(forRow: 1, of: tableView) == system.last) + } + } + + @Test("Row numbers take the theme's color, and a deleted row's the deleted text") + func rowNumberColor() { + withTheme({ + $0.rowNumber = "#123456" + $0.deletedText = "#FF000080" + }) { + let registry = DataGridCellRegistry() + let deleted = RowVisualState(isDeleted: true, isInserted: false, modifiedColumns: []) + + #expect(matches(registry.rowNumberColor(for: .empty), "#123456")) + #expect(matches(registry.rowNumberColor(for: deleted), "#FF000080")) + } + } + + @Test("The cell palette carries the theme's text, NULL and boolean colors") + func paletteFollowsTheTheme() { + withTheme({ + $0.text = "#405060" + $0.nullValue = "#A0B0C0" + $0.boolTrue = "#00FF00" + }) { + let palette = ThemeEngine.shared.dataGridCellPalette + + #expect(matches(palette.text, "#405060")) + #expect(matches(palette.placeholderText, "#A0B0C0")) + #expect(matches(palette.booleanTrueText, "#00FF00")) + #expect(palette.booleanFalseText == nil) + } + } + + /// Eight of these keys were declared, editable and shipped in every theme while the grid drew + /// system colors instead, so a theme could set them and see nothing change. + @Test("Every data grid theme color is read by the grid") + func everyKeyHasAGridReader() throws { + let keys = Mirror(reflecting: DataGridThemeColors.defaultLight).children.compactMap(\.label) + let resultsDirectory = Self.repositoryRoot.appendingPathComponent("TablePro/Views/Results", isDirectory: true) + let enumerator = try #require(FileManager.default.enumerator(at: resultsDirectory, includingPropertiesForKeys: nil)) + var source = "" + for case let url as URL in enumerator where url.pathExtension == "swift" { + source += try String(contentsOf: url, encoding: .utf8) + } + + #expect(!keys.isEmpty) + for key in keys { + #expect(source.contains("dataGrid.\(key)"), "No grid code reads the \(key) theme color") + } + } + + // MARK: - Bundled themes + + private func dataGridGroup(ofTheme id: String) throws -> [String: Any] { + let url = Self.repositoryRoot.appendingPathComponent("TablePro/Resources/Themes/\(id).json") + let json = try JSONSerialization.jsonObject(with: Data(contentsOf: url)) as? [String: Any] + return try #require(json?["dataGrid"] as? [String: Any]) + } + + @Test("The default themes leave the grid on system colors", arguments: [ + "tablepro.default-light", "tablepro.default-dark", + ]) + func defaultThemesDeclareNoGridColors(id: String) throws { + let group = try dataGridGroup(ofTheme: id) + + for key in Self.systemDefaultedKeys + ["focusBorder"] { + #expect(group[key] == nil, "\(id) declares \(key)") + } + } + + @Test("The designed themes declare every grid color", arguments: ["tablepro.dracula", "tablepro.nord"]) + func designedThemesDeclareGridColors(id: String) throws { + let group = try dataGridGroup(ofTheme: id) + + for key in Self.systemDefaultedKeys { + #expect((group[key] as? String)?.isEmpty == false, "\(id) omits \(key)") + } + #expect(group["focusBorder"] == nil) + } +} diff --git a/TableProTests/Views/Results/DataGridCellAppearanceTests.swift b/TableProTests/Views/Results/DataGridCellAppearanceTests.swift index 56a47edb1b..7bfc51a180 100644 --- a/TableProTests/Views/Results/DataGridCellAppearanceTests.swift +++ b/TableProTests/Views/Results/DataGridCellAppearanceTests.swift @@ -19,6 +19,25 @@ struct DataGridCellAppearanceTests { regularFont: .systemFont(ofSize: 13), italicFont: .systemFont(ofSize: 13), mediumFont: .systemFont(ofSize: 13, weight: .medium), + text: .labelColor, + placeholderText: .secondaryLabelColor, + booleanTrueText: nil, + booleanFalseText: nil, + rowNumberText: .secondaryLabelColor, + deletedRowText: .systemRed, + modifiedColumnTint: .systemYellow, + findMatchTint: .systemOrange + ) + + private let themedPalette = DataGridCellPalette( + regularFont: .systemFont(ofSize: 13), + italicFont: .systemFont(ofSize: 13), + mediumFont: .systemFont(ofSize: 13, weight: .medium), + text: .systemPurple, + placeholderText: .systemBrown, + booleanTrueText: .systemGreen, + booleanFalseText: .systemPink, + rowNumberText: .systemTeal, deletedRowText: .systemRed, modifiedColumnTint: .systemYellow, findMatchTint: .systemOrange @@ -36,7 +55,8 @@ struct DataGridCellAppearanceTests { isCurrentFindMatch: Bool = false, columnIndex: Int = 0, onEmphasizedSelection: Bool = false, - hasOverlay: Bool = false + hasOverlay: Bool = false, + palette: DataGridCellPalette? = nil ) -> DataGridCellAppearance { DataGridCellAppearance.resolve( kind: kind, @@ -50,7 +70,7 @@ struct DataGridCellAppearanceTests { row: 0, columnIndex: columnIndex ), - palette: palette, + palette: palette ?? self.palette, nullDisplayString: "NULL", onEmphasizedSelection: onEmphasizedSelection, hasOverlay: hasOverlay @@ -245,4 +265,60 @@ struct DataGridCellAppearanceTests { #expect(modified.drawnHighlightRule(forColumn: 1) == rowRule) #expect(deleted.drawnHighlightRule(forColumn: 1) == nil) } + + // MARK: - Theme colors + + @Test("A value takes the theme's text color, a placeholder its NULL color") + func themeTextAndPlaceholderColors() { + let value = resolve(palette: themedPalette) + let null = resolve(text: "", rawValue: nil, placeholder: .null, palette: themedPalette) + let empty = resolve(text: "", rawValue: "", placeholder: .empty, palette: themedPalette) + + #expect(value.textColor == .systemPurple) + #expect(null.textColor == .systemBrown) + #expect(empty.textColor == .systemBrown) + } + + @Test("A boolean cell takes the theme's true or false color", arguments: [ + ("true", NSColor.systemGreen), ("1", .systemGreen), ("t", .systemGreen), + ("false", .systemPink), ("0", .systemPink), ("f", .systemPink), + ]) + func booleanColors(raw: String, expected: NSColor) { + let appearance = resolve(kind: .boolean, text: raw, rawValue: raw, palette: themedPalette) + + #expect(appearance.textColor == expected) + } + + @Test("A boolean color stays off text columns and unreadable values") + func booleanColorNeedsABooleanValue() { + let textColumn = resolve(kind: .text, text: "true", rawValue: "true", palette: themedPalette) + let unreadable = resolve(kind: .boolean, text: "maybe", rawValue: "maybe", palette: themedPalette) + + #expect(textColumn.textColor == .systemPurple) + #expect(unreadable.textColor == .systemPurple) + } + + @Test("A theme without boolean colors draws booleans as plain text") + func booleanFallsBackToText() { + let appearance = resolve(kind: .boolean, text: "true", rawValue: "true") + + #expect(appearance.textColor == .labelColor) + } + + @Test("Selection, deletion and a find match outrank the boolean color") + func booleanColorYieldsToState() { + let selected = resolve(kind: .boolean, text: "1", rawValue: "1", onEmphasizedSelection: true, palette: themedPalette) + let deleted = resolve( + kind: .boolean, + text: "1", + rawValue: "1", + visualState: RowVisualState(isDeleted: true, isInserted: false, modifiedColumns: []), + palette: themedPalette + ) + let found = resolve(kind: .boolean, text: "1", rawValue: "1", isCurrentFindMatch: true, palette: themedPalette) + + #expect(selected.textColor == .alternateSelectedControlTextColor) + #expect(deleted.textColor == .systemRed) + #expect(found.textColor == .black) + } } diff --git a/TableProTests/Views/Results/DataGridRowNumberRenderingTests.swift b/TableProTests/Views/Results/DataGridRowNumberRenderingTests.swift index 8935e3d234..4c2f02654f 100644 --- a/TableProTests/Views/Results/DataGridRowNumberRenderingTests.swift +++ b/TableProTests/Views/Results/DataGridRowNumberRenderingTests.swift @@ -449,6 +449,44 @@ struct DataGridRowNumberRenderingTests { #expect(grid.header.drawnPinnedHeadingRect == widened) } + /// `NSTableRowView` paints the system stripes whatever the table is told, so a theme's own pair + /// only shows because the row paints the stripe `DataGridBodyChrome` gives it. The strip reads the + /// same owner, so it has to keep matching the row under a theme too. Light mode, where the + /// system stripes are white and light grey, so a dark themed row cannot pass for one. + @Test("Rows paint the theme's stripes, and the strip still matches them") + func rowsPaintTheThemesStripes() throws { + let engine = ThemeEngine.shared + let original = engine.activeTheme + defer { engine.activateTheme(original) } + var theme = ThemeDefinition.default + theme.id = "test.grid-stripes" + theme.dataGrid.background = "#282A36" + theme.dataGrid.alternateRow = "#44475A" + engine.activateTheme(theme) + + let grid = makeGrid(appearance: .aqua) + let rows = grid.rowsUnderTheStrip + #expect(rows.count >= 4, "too few rows under the strip to cover both stripes") + let firstData = try #require(grid.coordinator.firstPresentedColumnIndex()) + let dataRect = grid.tableView.rect(ofColumn: firstData) + let raster = try #require(Raster(of: grid.scrollView, in: grid.scrollView.bounds)) + + var bodies: [Int: NSColor] = [:] + for row in rows { + let midY = grid.tableView.rect(ofRow: row).midY + let strip = try #require(raster.color(at: grid.pointInScrollView(NSPoint(x: 2, y: midY)))) + let body = try #require( + raster.color(at: grid.pointInScrollView(NSPoint(x: dataRect.maxX - 12, y: midY))) + ) + #expect(matches(strip, body), "row \(row): strip \(strip), row \(body)") + #expect(body.redComponent < 0.35, "row \(row) drew \(body), not the theme's dark stripe") + bodies[row] = body + } + let even = try #require(rows.first(where: { $0.isMultiple(of: 2) }).flatMap { bodies[$0] }) + let odd = try #require(rows.first(where: { !$0.isMultiple(of: 2) }).flatMap { bodies[$0] }) + #expect(!matches(even, odd), "both stripes drew \(even)") + } + private func rightClick(at point: NSPoint, in grid: Grid) -> NSEvent? { NSEvent.mouseEvent( with: .rightMouseDown, diff --git a/docs/customization/appearance.mdx b/docs/customization/appearance.mdx index d9b6bf6e73..ec506c18bb 100644 --- a/docs/customization/appearance.mdx +++ b/docs/customization/appearance.mdx @@ -43,18 +43,18 @@ Custom themes get color wells here. A built-in or registry theme shows a lock an |-------|----------| | Editor | Background, text, cursor, current line, selection, line number, invisibles | | Syntax Colors | Keyword, string, number, comment, NULL, operator, function, type | -| Data Grid | Background, text, alternate row, NULL value, bool true/false, row number, modified/inserted/deleted rows, deleted text, focus border | +| Data Grid | Background, text, alternate row, NULL value, bool true/false, row number, modified/inserted/deleted rows, deleted text | | Interface | Window, control, and card backgrounds, border, primary/secondary/tertiary text, selection, hover | | Status Colors | Success, warning, error, info | | Badges | Badge background, primary key, auto increment | | Sidebar | Background, text, selected item, hover, section header | | Toolbar | Secondary and tertiary text | -Interface, Sidebar, and Toolbar colors sit on macOS system colors until you override one, which is why an untouched theme follows your system accent color. An overridden well grows a reset button that puts the system color back. +Interface, Sidebar, and Toolbar colors sit on macOS system colors until you override one, which is why an untouched theme follows your system accent color. So do the grid's background, text, alternate row, NULL value, and row number. Bool true and false show in the grid's text color until you set them. An overridden well grows a reset button that puts the system color back. ## Theme files -A theme is one JSON file. **Export…** in the gear menu writes the active theme with every key filled in, which is the shortest way to start a new one; **Import…** in the **+** menu reads one back into `~/Library/Application Support/TablePro/Themes/`. Community themes install from the [registry](/features/plugins) under **Settings > Plugins > Browse**, Themes category. +A theme is one JSON file. **Export…** in the gear menu writes every color the active theme sets, which is the shortest way to start a new one; **Import…** in the **+** menu reads one back into `~/Library/Application Support/TablePro/Themes/`. Community themes install from the [registry](/features/plugins) under **Settings > Plugins > Browse**, Themes category. | Key | Holds | |-----|-------| @@ -86,7 +86,7 @@ A theme is one JSON file. **Export…** in the gear menu writes the active theme Colors are sRGB hex, `#RRGGBB` or `#RRGGBBAA` for a translucent overlay such as a selection band. A value that is neither renders as the system label color, which is how a typo shows up. -Every key is optional. A group you leave out falls back to Default Light, and a color left out of `ui`, `sidebar`, or `toolbar` is the macOS system color rather than a fixed value. +Every key is optional. A group you leave out falls back to Default Light. A color left out of `ui`, `sidebar`, or `toolbar` is the macOS system color rather than a fixed value, and so is a `dataGrid` `background`, `text`, `alternateRow`, `nullValue`, or `rowNumber`. A missing `boolTrue` or `boolFalse` uses the grid's text color. ## Connection colors From 33b8e8c62ea82a3581fa7a63f027f8fb35ff5b83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 00:08:10 +0700 Subject: [PATCH 10/54] fix(export): report a restore into an older PostgreSQL server as complete (#2747) Claude-Session: https://claude.ai/code/session_01X1ejXbmyPqUziRWVxJ5cu8 --- CHANGELOG.md | 1 + TablePro/Core/Database/NativeDumpBatch.swift | 2 +- .../Core/Database/NativeDumpDescriptor.swift | 12 + .../Core/Database/NativeDumpRegistry.swift | 2 + .../Core/Database/NativeDumpService.swift | 69 ++++- .../Database/PostgresRestoreDiagnostics.swift | 121 ++++++++ TablePro/Resources/Localizable.xcstrings | 68 +++++ TablePro/Views/Backup/BackupResultSheet.swift | 58 +++- .../Views/Backup/RestoreDatabaseFlow.swift | 11 +- .../Database/NativeDumpBatchTests.swift | 2 +- .../Database/NativeDumpServiceTests.swift | 180 ++++++++++- .../PostgresRestoreDiagnosticsTests.swift | 287 ++++++++++++++++++ ...ackupResultSheetSkippedSettingsTests.swift | 30 ++ docs/features/backup-restore.mdx | 2 + 14 files changed, 822 insertions(+), 23 deletions(-) create mode 100644 TablePro/Core/Database/PostgresRestoreDiagnostics.swift create mode 100644 TableProTests/Database/PostgresRestoreDiagnosticsTests.swift create mode 100644 TableProTests/Views/Backup/BackupResultSheetSkippedSettingsTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index d7f0353f34..e93e81ab57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -136,6 +136,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Line and paragraph separators (U+2028, U+2029) shown as line breaks the database does not see. (#2717) - Stop on Cloudflare D1, libSQL and Trino cancelling a sidebar read instead of the running query. - Numeric-looking filter values sent unquoted to text columns when a table first opens or after a foreign key jump. +- Restore reported as failed after a complete restore into a PostgreSQL server older than `pg_restore`. - Garbled non-Latin text saved to MySQL and MariaDB servers that force a Latin 1 session. (#2725) - Garbled non-Latin text when restoring a MySQL or MariaDB SQL export through a Latin 1 client. (#2725) - Curly quotes, € and other Windows-1252 symbols shown as invisible characters after `SET NAMES latin1`. diff --git a/TablePro/Core/Database/NativeDumpBatch.swift b/TablePro/Core/Database/NativeDumpBatch.swift index 6c7fe06cc8..bdd95d309d 100644 --- a/TablePro/Core/Database/NativeDumpBatch.swift +++ b/TablePro/Core/Database/NativeDumpBatch.swift @@ -195,7 +195,7 @@ final class NativeDumpBatch { case .running(_, _, let bytes, let total): state.bytesProcessed = bytes state.totalBytes = total ?? state.totalBytes - case .finished(_, _, let bytes): + case .finished(_, _, let bytes, _): record(item, .succeeded(bytes: bytes)) return case .failed(let message, _): diff --git a/TablePro/Core/Database/NativeDumpDescriptor.swift b/TablePro/Core/Database/NativeDumpDescriptor.swift index 45ac0bc370..1de349bf9f 100644 --- a/TablePro/Core/Database/NativeDumpDescriptor.swift +++ b/TablePro/Core/Database/NativeDumpDescriptor.swift @@ -122,6 +122,10 @@ struct NativeDumpDescriptor: Sendable { /// from the binary's name, which is what `buildCommand` used to do. let needsCredentialsFile: Bool + internal let restoreExitPolicy: NativeDumpExitPolicy + + internal let requiresUntranslatedMessages: Bool + let backupArguments: @Sendable (Request) -> [String] let restoreArguments: @Sendable (Request) -> [String] let environment: @Sendable (Request) -> [String: String] @@ -134,6 +138,8 @@ struct NativeDumpDescriptor: Sendable { restoreDelivery: OutputDelivery, exposesPasswordInArguments: Bool = false, needsCredentialsFile: Bool = false, + restoreExitPolicy: NativeDumpExitPolicy = .zeroExitOnly, + requiresUntranslatedMessages: Bool = false, backupArguments: @escaping @Sendable (Request) -> [String], restoreArguments: @escaping @Sendable (Request) -> [String], environment: @escaping @Sendable (Request) -> [String: String] = { _ in [:] } @@ -145,6 +151,8 @@ struct NativeDumpDescriptor: Sendable { self.restoreDelivery = restoreDelivery self.exposesPasswordInArguments = exposesPasswordInArguments self.needsCredentialsFile = needsCredentialsFile + self.restoreExitPolicy = restoreExitPolicy + self.requiresUntranslatedMessages = requiresUntranslatedMessages self.backupArguments = backupArguments self.restoreArguments = restoreArguments self.environment = environment @@ -161,6 +169,10 @@ struct NativeDumpDescriptor: Sendable { func delivery(for kind: NativeDumpKind) -> OutputDelivery { kind == .backup ? backupDelivery : restoreDelivery } + + internal func exitPolicy(for kind: NativeDumpKind) -> NativeDumpExitPolicy { + kind == .backup ? .zeroExitOnly : restoreExitPolicy + } } /// Statements the engine already in front of the app runs for itself. diff --git a/TablePro/Core/Database/NativeDumpRegistry.swift b/TablePro/Core/Database/NativeDumpRegistry.swift index d69e319f6e..9cfec8cfe6 100644 --- a/TablePro/Core/Database/NativeDumpRegistry.swift +++ b/TablePro/Core/Database/NativeDumpRegistry.swift @@ -79,6 +79,8 @@ enum NativeDumpRegistry { installHint: String(localized: "Install it with `brew install libpq` and link it."), backupDelivery: .toolWritesFile, restoreDelivery: .toolWritesFile, + restoreExitPolicy: .toleratesUnrecognizedSessionSettings, + requiresUntranslatedMessages: true, backupArguments: { request in connectionFlags(request) + ["-Fc", "-d", request.database] diff --git a/TablePro/Core/Database/NativeDumpService.swift b/TablePro/Core/Database/NativeDumpService.swift index de81dee115..fb80e616f6 100644 --- a/TablePro/Core/Database/NativeDumpService.swift +++ b/TablePro/Core/Database/NativeDumpService.swift @@ -26,7 +26,7 @@ enum NativeDumpState: Equatable { case idle case running(database: String, fileURL: URL, bytesProcessed: Int64, totalBytes: Int64?) case cancelling - case finished(database: String, fileURL: URL, bytesProcessed: Int64) + case finished(database: String, fileURL: URL, bytesProcessed: Int64, skippedSettings: [String] = []) /// A restore that fails part way through has already replayed some of the dump, and the /// target is left in whatever state that reached. A backup writes only to its own file, which /// is removed, so nothing of the user's is touched. @@ -64,6 +64,20 @@ enum NativeDumpError: LocalizedError, Equatable { } } +internal enum NativeDumpExitPolicy: Equatable, Sendable { + case zeroExitOnly + case toleratesUnrecognizedSessionSettings + + internal func skippedSettings(exitCode: Int32, stderr: String) -> [String]? { + switch self { + case .zeroExitOnly: + return nil + case .toleratesUnrecognizedSessionSettings: + return PostgresRestoreDiagnostics.skippedSessionSettings(exitCode: exitCode, stderr: stderr) + } + } +} + /// Parameters for a single backup or restore subprocess. struct NativeDumpCommand: Equatable { let executable: URL @@ -87,6 +101,8 @@ struct NativeDumpCommand: Equatable { /// takes standard output and writes it out. let isRestore: Bool + internal let exitPolicy: NativeDumpExitPolicy + init( executable: URL, arguments: [String], @@ -95,7 +111,8 @@ struct NativeDumpCommand: Equatable { delivery: NativeDumpDescriptor.OutputDelivery = .toolWritesFile, redirectedFileURL: URL? = nil, temporaryCredentialsFileURL: URL? = nil, - isRestore: Bool = false + isRestore: Bool = false, + exitPolicy: NativeDumpExitPolicy = .zeroExitOnly ) { self.executable = executable self.arguments = arguments @@ -105,6 +122,7 @@ struct NativeDumpCommand: Equatable { self.redirectedFileURL = redirectedFileURL self.temporaryCredentialsFileURL = temporaryCredentialsFileURL self.isRestore = isRestore + self.exitPolicy = exitPolicy } } @@ -124,6 +142,13 @@ enum NativeDumpJob { case statements(NativeDumpStatementJob) } +internal extension NativeDumpJob { + var exitPolicy: NativeDumpExitPolicy { + guard case .process(let command) = self else { return .zeroExitOnly } + return command.exitPolicy + } +} + /// Captured terminal state of a finished/cancelled run. struct NativeDumpRunResult: Equatable { let exitCode: Int32 @@ -305,6 +330,7 @@ final class NativeDumpService { let runner = runnerFactory(job) try runner.start() self.runner = runner + let exitPolicy = job.exitPolicy setState(.running(database: database, fileURL: fileURL, bytesProcessed: 0, totalBytes: totalBytesEstimate)) if kind == .backup { @@ -313,7 +339,7 @@ final class NativeDumpService { Task { @MainActor [weak self] in guard let result = await self?.runner?.result else { return } - self?.handleTermination(result: result, database: database, fileURL: fileURL) + self?.handleTermination(result: result, database: database, fileURL: fileURL, exitPolicy: exitPolicy) } } @@ -389,6 +415,9 @@ final class NativeDumpService { var arguments = tool.arguments(for: kind, request: request) var environment = minimalEnvironment() environment.merge(tool.environment(request)) { _, new in new } + if tool.requiresUntranslatedMessages { + environment = untranslatedMessagesEnvironment(environment) + } var credentialsFileURL: URL? if tool.needsCredentialsFile, @@ -408,7 +437,8 @@ final class NativeDumpService { delivery: delivery, redirectedFileURL: delivery == .standardOutput ? request.fileURL : nil, temporaryCredentialsFileURL: credentialsFileURL, - isRestore: kind == .restore + isRestore: kind == .restore, + exitPolicy: tool.exitPolicy(for: kind) ) } @@ -440,6 +470,17 @@ final class NativeDumpService { "PATH", "HOME", "USER", "LOGNAME", "SHELL", "TMPDIR", "LANG", "LC_ALL" ] + nonisolated internal static let untranslatedMessagesLocale = "C" + + nonisolated internal static func untranslatedMessagesEnvironment(_ environment: [String: String]) -> [String: String] { + var result = environment + if let everyCategory = result.removeValue(forKey: "LC_ALL"), result["LC_CTYPE"] == nil { + result["LC_CTYPE"] = everyCategory + } + result["LC_MESSAGES"] = untranslatedMessagesLocale + return result + } + nonisolated static func minimalEnvironment() -> [String: String] { let parent = ProcessInfo.processInfo.environment var env: [String: String] = [:] @@ -454,7 +495,8 @@ final class NativeDumpService { private func handleTermination( result: NativeDumpRunResult, database: String, - fileURL: URL + fileURL: URL, + exitPolicy: NativeDumpExitPolicy ) { byteSizeTask?.cancel() byteSizeTask = nil @@ -475,6 +517,23 @@ final class NativeDumpService { return } + if let skipped = exitPolicy.skippedSettings(exitCode: result.exitCode, stderr: result.stderr) { + setState(.finished( + database: database, + fileURL: fileURL, + bytesProcessed: writtenBytes, + skippedSettings: skipped + )) + let settings = skipped.joined(separator: ",") + Self.logger.notice( + """ + \(self.toolName, privacy: .public) finished skipping settings=\(settings, privacy: .public) \ + db=\(database, privacy: .public) + """ + ) + return + } + if kind == .backup { Self.removeDestination(fileURL) } let summary = result.stderr.isEmpty ? String(format: String(localized: "Process exited with code %d"), Int(result.exitCode)) diff --git a/TablePro/Core/Database/PostgresRestoreDiagnostics.swift b/TablePro/Core/Database/PostgresRestoreDiagnostics.swift new file mode 100644 index 0000000000..9f42dc1418 --- /dev/null +++ b/TablePro/Core/Database/PostgresRestoreDiagnostics.swift @@ -0,0 +1,121 @@ +// +// PostgresRestoreDiagnostics.swift +// TablePro +// + +import Foundation + +internal enum PostgresRestoreDiagnostics { + private static let errorsIgnoredExitCode: Int32 = 1 + private static let errorsIgnoredPrefix = "pg_restore: warning: errors ignored on restore: " + private static let phaseContextLines: Set = [ + "pg_restore: while INITIALIZING:", + "pg_restore: while PROCESSING TOC:" + ] + private static let tocEntryContextPrefix = "pg_restore: from TOC entry " + private static let executeQueryPrefix = "pg_restore: error: could not execute query: " + private static let couldNotSetPrefix = "pg_restore: error: could not set " + private static let setCommandPrefix = "Command was: SET " + private static let unrecognizedParameterPrefix = "ERROR: unrecognized configuration parameter \"" + + internal static func skippedSessionSettings(exitCode: Int32, stderr: String) -> [String]? { + guard exitCode == errorsIgnoredExitCode else { return nil } + let lines = stderr + .split(whereSeparator: \.isNewline) + .map(String.init) + .filter { !$0.trimmingCharacters(in: .whitespaces).isEmpty } + guard let summary = lines.last, + let reportedErrorCount = errorsIgnoredCount(summary), + let skipped = rejectedSettings(in: lines.dropLast()), + !skipped.isEmpty, + skipped.count == reportedErrorCount + else { return nil } + return uniqued(skipped) + } + + private static func rejectedSettings(in lines: ArraySlice) -> [String]? { + var settings: [String] = [] + var remaining = lines + while let line = remaining.popFirst() { + if isContext(line) { continue } + if let setting = couldNotSetSetting(line) { + settings.append(setting) + continue + } + guard let command = remaining.popFirst(), + let setting = rejectedSetCommandSetting(error: line, command: command) + else { return nil } + settings.append(setting) + } + return settings + } + + private static func isContext(_ line: String) -> Bool { + phaseContextLines.contains(line) || line.hasPrefix(tocEntryContextPrefix) + } + + private static func errorsIgnoredCount(_ line: String) -> Int? { + guard line.hasPrefix(errorsIgnoredPrefix) else { return nil } + return Int(line.dropFirst(errorsIgnoredPrefix.count)) + } + + private static func couldNotSetSetting(_ line: String) -> String? { + guard line.hasPrefix(couldNotSetPrefix) else { return nil } + let remainder = line.dropFirst(couldNotSetPrefix.count) + let quoted = remainder.first == "\"" + let nameStart = quoted ? remainder.index(after: remainder.startIndex) : remainder.startIndex + let separator = quoted ? "\": " : ": " + guard let separatorRange = remainder[nameStart...].range(of: separator) else { return nil } + let setting = String(remainder[nameStart.. String? { + guard error.hasPrefix(executeQueryPrefix), + let setting = unrecognizedParameter(in: String(error.dropFirst(executeQueryPrefix.count))) + else { return nil } + let assignment = setCommandPrefix + setting + " = " + guard command.hasPrefix(assignment), command.hasSuffix(";") else { return nil } + let value = command.dropFirst(assignment.count).dropLast() + guard isSingleValue(value) else { return nil } + return setting + } + + private static func unrecognizedParameter(in serverMessage: String) -> String? { + guard serverMessage.hasPrefix(unrecognizedParameterPrefix), serverMessage.hasSuffix("\"") else { return nil } + let name = String(serverMessage.dropFirst(unrecognizedParameterPrefix.count).dropLast()) + return isSettingName(name) ? name : nil + } + + private static func isSettingName(_ name: String) -> Bool { + !name.isEmpty && name.allSatisfy { character in + character == "_" || character == "." || (character.isASCII && (character.isLetter || character.isNumber)) + } + } + + private static func isSingleValue(_ value: Substring) -> Bool { + guard value.first == "'" else { + return !value.isEmpty && value.allSatisfy { character in + character.isASCII && (character.isLetter || character.isNumber || "_.+-".contains(character)) + } + } + return isQuotedLiteral(value) + } + + private static func isQuotedLiteral(_ value: Substring) -> Bool { + guard value.count >= 2, value.first == "'", value.last == "'" else { return false } + var inner = value.dropFirst().dropLast() + while let character = inner.popFirst() { + guard character == "'" else { continue } + guard inner.popFirst() == "'" else { return false } + } + return true + } + + private static func uniqued(_ settings: [String]) -> [String] { + var seen: Set = [] + return settings.filter { seen.insert($0).inserted } + } +} diff --git a/TablePro/Resources/Localizable.xcstrings b/TablePro/Resources/Localizable.xcstrings index 5d33321d19..9af84bbc1f 100644 --- a/TablePro/Resources/Localizable.xcstrings +++ b/TablePro/Resources/Localizable.xcstrings @@ -142543,6 +142543,74 @@ } } }, + "Skipped settings this server does not recognize: %@." : { + "localizations" : { + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "이 서버가 인식하지 못하는 설정을 건너뛰었습니다: %@." + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bu sunucunun tanımadığı ayarlar atlandı: %@." + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "Đã bỏ qua các thiết lập mà máy chủ này không nhận ra: %@." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已跳过此服务器无法识别的设置:%@。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "已略過此伺服器無法辨識的設定:%@。" + } + } + } + }, + "Skipped the %@ setting, which this server does not recognize." : { + "localizations" : { + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "이 서버가 인식하지 못하는 %@ 설정을 건너뛰었습니다." + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bu sunucunun tanımadığı %@ ayarı atlandı." + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "Đã bỏ qua thiết lập %@ mà máy chủ này không nhận ra." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已跳过此服务器无法识别的 %@ 设置。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "已略過此伺服器無法辨識的 %@ 設定。" + } + } + } + }, "Skips foreign key constraint checks for this operation" : { "extractionState" : "stale", "localizations" : { diff --git a/TablePro/Views/Backup/BackupResultSheet.swift b/TablePro/Views/Backup/BackupResultSheet.swift index de981e47ef..6f91e71141 100644 --- a/TablePro/Views/Backup/BackupResultSheet.swift +++ b/TablePro/Views/Backup/BackupResultSheet.swift @@ -15,7 +15,7 @@ struct BackupResultSheet: View { enum Outcome { case backupSuccess(database: String, destination: URL, bytes: Int64) - case restoreSuccess(database: String, source: URL) + case restoreSuccess(database: String, source: URL, skippedSettings: [String]) /// A run over several databases, where one failing does not stop the rest, so the sheet /// reports every database rather than one verdict for the batch. case batch(outcomes: [NativeDumpBatchOutcome], directory: URL) @@ -84,16 +84,32 @@ struct BackupResultSheet: View { scrollingDetail(message) case .batch(let outcomes, let directory): scrollingDetail(Self.batchDetail(outcomes, directory: directory)) - default: - if let detail { - Text(detail) + case .restoreSuccess(_, _, let skippedSettings): + summaryDetail + if let note = Self.skippedSettingsNote(skippedSettings) { + Text(note) .font(.callout) .foregroundStyle(.secondary) .multilineTextAlignment(.center) - .lineLimit(6) + .fixedSize(horizontal: false, vertical: true) .frame(maxWidth: .infinity, alignment: .center) .textSelection(.enabled) } + default: + summaryDetail + } + } + + @ViewBuilder + private var summaryDetail: some View { + if let detail { + Text(detail) + .font(.callout) + .foregroundStyle(.secondary) + .multilineTextAlignment(.center) + .lineLimit(6) + .frame(maxWidth: .infinity, alignment: .center) + .textSelection(.enabled) } } @@ -179,7 +195,7 @@ struct BackupResultSheet: View { database, destination.path ) - case .restoreSuccess(let database, let source): + case .restoreSuccess(let database, let source, _): return String( format: String(localized: "Restored \u{201C}%@\u{201D} from %@"), database, @@ -198,6 +214,20 @@ struct BackupResultSheet: View { } } + internal static func skippedSettingsNote(_ settings: [String]) -> String? { + guard let first = settings.first else { return nil } + guard settings.count > 1 else { + return String( + format: String(localized: "Skipped the %@ setting, which this server does not recognize."), + first + ) + } + return String( + format: String(localized: "Skipped settings this server does not recognize: %@."), + settings.formatted(.list(type: .and)) + ) + } + /// One line per database, so a run where the second of three failed says which one and keeps /// the other two visible rather than reporting a single verdict for the batch. private static func batchDetail(_ outcomes: [NativeDumpBatchOutcome], directory: URL) -> String { @@ -242,7 +272,21 @@ struct BackupResultSheet: View { kind: .restore, outcome: .restoreSuccess( database: "production", - source: URL(fileURLWithPath: "/Users/me/Desktop/production.dump") + source: URL(fileURLWithPath: "/Users/me/Desktop/production.dump"), + skippedSettings: [] + ), + onClose: {}, + onShowInFinder: nil + ) +} + +#Preview("Restore Success With Skipped Settings") { + BackupResultSheet( + kind: .restore, + outcome: .restoreSuccess( + database: "production", + source: URL(fileURLWithPath: "/Users/me/Desktop/production.dump"), + skippedSettings: ["idle_in_transaction_session_timeout", "transaction_timeout"] ), onClose: {}, onShowInFinder: nil diff --git a/TablePro/Views/Backup/RestoreDatabaseFlow.swift b/TablePro/Views/Backup/RestoreDatabaseFlow.swift index 19b5c2c2b2..f3266cfbc5 100644 --- a/TablePro/Views/Backup/RestoreDatabaseFlow.swift +++ b/TablePro/Views/Backup/RestoreDatabaseFlow.swift @@ -20,7 +20,7 @@ struct RestoreDatabaseFlow: View { case resolvingTarget case pickDatabase case running(database: String) - case finished(database: String) + case finished(database: String, skippedSettings: [String]) case failed(message: String, targetMayBeModified: Bool) case cancelled } @@ -41,10 +41,11 @@ struct RestoreDatabaseFlow: View { isCancelling: service.state == .cancelling, onCancel: { service.cancel() } ) - case .finished(let database): + case .finished(let database, let skippedSettings): BackupResultSheet( kind: .restore, - outcome: .restoreSuccess(database: database, source: sourceURL), + outcome: .restoreSuccess( + database: database, source: sourceURL, skippedSettings: skippedSettings), onClose: { isPresented = false }, onShowInFinder: nil ) @@ -152,8 +153,8 @@ struct RestoreDatabaseFlow: View { switch state { case .running(let database, _, _, _): phase = .running(database: database) - case .finished(let database, _, _): - phase = .finished(database: database) + case .finished(let database, _, _, let skippedSettings): + phase = .finished(database: database, skippedSettings: skippedSettings) case .failed(let message, let targetMayBeModified): phase = .failed(message: message, targetMayBeModified: targetMayBeModified) case .cancelled: diff --git a/TableProTests/Database/NativeDumpBatchTests.swift b/TableProTests/Database/NativeDumpBatchTests.swift index 5d88671bd5..e024c34c42 100644 --- a/TableProTests/Database/NativeDumpBatchTests.swift +++ b/TableProTests/Database/NativeDumpBatchTests.swift @@ -56,7 +56,7 @@ private final class FakeDumpService: NativeDumpRunning { } private func substituted(_ state: NativeDumpState, database: String, fileURL: URL) -> NativeDumpState { - guard case .finished(_, _, let bytes) = state else { return state } + guard case .finished(_, _, let bytes, _) = state else { return state } return .finished(database: database, fileURL: fileURL, bytesProcessed: bytes) } diff --git a/TableProTests/Database/NativeDumpServiceTests.swift b/TableProTests/Database/NativeDumpServiceTests.swift index 3e7c88f922..ef7b122fa4 100644 --- a/TableProTests/Database/NativeDumpServiceTests.swift +++ b/TableProTests/Database/NativeDumpServiceTests.swift @@ -98,6 +98,92 @@ struct NativeDumpServiceCommandTests { #expect(!command.arguments.contains("-f")) } + @Test("pg_restore tolerates unrecognized session settings; pg_dump does not") + func postgresExitPolicies() throws { + let restore = try NativeDumpService.buildCommand( + kind: .restore, + tool: postgresTool, + executable: URL(fileURLWithPath: "/usr/bin/pg_restore"), + request: request(connection: connection(), fileURL: URL(fileURLWithPath: "/tmp/sales.dump")) + ) + let backup = try NativeDumpService.buildCommand( + kind: .backup, + tool: postgresTool, + executable: URL(fileURLWithPath: "/usr/bin/pg_dump"), + request: request(connection: connection(), fileURL: URL(fileURLWithPath: "/tmp/sales.dump")) + ) + #expect(restore.exitPolicy == .toleratesUnrecognizedSessionSettings) + #expect(backup.exitPolicy == .zeroExitOnly) + } + + @Test("Every other engine's restore keeps the strict exit policy") + func otherEnginesStayStrict() throws { + for type in [DatabaseType.mysql, .mongodb, .sqlite, .mssql] { + let tool = try #require(NativeDumpRegistry.descriptor(for: type)?.commandLineTool) + #expect(tool.exitPolicy(for: .restore) == .zeroExitOnly) + #expect(tool.exitPolicy(for: .backup) == .zeroExitOnly) + } + } + + @Test("A job the engine runs for itself never tolerates a failure") + func statementJobsStayStrict() { + let job = NativeDumpJob.statements( + NativeDumpStatementJob( + statements: ["SELECT 1"], + cleanupStatements: [], + scope: DatabaseScope(connectionId: UUID(), database: "sales", schema: nil) + ) + ) + #expect(job.exitPolicy == .zeroExitOnly) + } + + @Test("pg_dump and pg_restore print untranslated messages") + func postgresToolsPrintUntranslatedMessages() throws { + for kind in [NativeDumpKind.backup, .restore] { + let command = try NativeDumpService.buildCommand( + kind: kind, + tool: postgresTool, + executable: URL(fileURLWithPath: "/usr/bin/pg_restore"), + request: request(connection: connection(), fileURL: URL(fileURLWithPath: "/tmp/sales.dump")) + ) + #expect(command.environment["LC_MESSAGES"] == "C") + #expect(command.environment["LC_ALL"] == nil) + } + } + + @Test("Other engines' tools keep the user's message language") + func otherToolsKeepTheirLanguage() throws { + let tool = try #require(NativeDumpRegistry.descriptor(for: .mysql)?.commandLineTool) + #expect(!tool.requiresUntranslatedMessages) + } + + @Test("LC_ALL moves to LC_CTYPE so character handling survives, and messages become untranslated") + func untranslatedMessagesMovesLcAll() { + let environment = NativeDumpService.untranslatedMessagesEnvironment( + ["LANG": "fr_FR.UTF-8", "LC_ALL": "fr_FR.UTF-8", "PATH": "/usr/bin"] + ) + #expect(environment == [ + "LANG": "fr_FR.UTF-8", + "LC_CTYPE": "fr_FR.UTF-8", + "LC_MESSAGES": "C", + "PATH": "/usr/bin" + ]) + } + + @Test("An LC_CTYPE already present is kept over LC_ALL") + func untranslatedMessagesKeepsLcCtype() { + let environment = NativeDumpService.untranslatedMessagesEnvironment( + ["LC_ALL": "fr_FR.UTF-8", "LC_CTYPE": "de_DE.UTF-8"] + ) + #expect(environment == ["LC_CTYPE": "de_DE.UTF-8", "LC_MESSAGES": "C"]) + } + + @Test("Without LC_ALL only LC_MESSAGES is added") + func untranslatedMessagesWithoutLcAll() { + let environment = NativeDumpService.untranslatedMessagesEnvironment(["LANG": "ko_KR.UTF-8"]) + #expect(environment == ["LANG": "ko_KR.UTF-8", "LC_MESSAGES": "C"]) + } + @Test("empty host falls back to 127.0.0.1") func hostFallback() throws { let command = try NativeDumpService.buildCommand( @@ -191,7 +277,7 @@ struct NativeDumpServiceCommandTests { ) ) let allowed: Set = [ - "PATH", "HOME", "USER", "LOGNAME", "SHELL", "TMPDIR", "LANG", "LC_ALL", + "PATH", "HOME", "USER", "LOGNAME", "SHELL", "TMPDIR", "LANG", "LC_CTYPE", "LC_MESSAGES", "PGPASSWORD", "PGSSLMODE" ] let unexpected = Set(command.environment.keys).subtracting(allowed) @@ -257,17 +343,103 @@ private final class FakeDumpRunner: NativeDumpRunner, @unchecked Sendable { @Suite("NativeDumpService state machine", .serialized) @MainActor struct NativeDumpServiceStateMachineTests { - private func fakeJob() -> NativeDumpJob { + private func fakeJob(exitPolicy: NativeDumpExitPolicy = .zeroExitOnly) -> NativeDumpJob { .process( NativeDumpCommand( executable: URL(fileURLWithPath: "/usr/bin/true"), arguments: [], environment: [:], - stderrByteCap: 64_000 + stderrByteCap: 64_000, + exitPolicy: exitPolicy ) ) } + private static let skippedSettingsStderr = """ + pg_restore: error: could not execute query: ERROR: unrecognized configuration parameter "transaction_timeout" + Command was: SET transaction_timeout = 0; + pg_restore: warning: errors ignored on restore: 1 + """ + + @Test("A restore whose only errors are unrecognized settings finishes and names them") + func restoreFinishesSkippingSettings() async throws { + let runner = FakeDumpRunner() + let service = service(kind: .restore, runner: runner) + let updates = service.stateUpdates() + + try service.run( + job: fakeJob(exitPolicy: .toleratesUnrecognizedSessionSettings), + database: "sales", + fileURL: URL(fileURLWithPath: "/tmp/test-skipped.dump") + ) + runner.finish(.init(exitCode: 1, stderr: Self.skippedSettingsStderr, wasCancelled: false)) + let finalState = try await firstMatching(updates) { + switch $0 { + case .finished, .failed: return true + default: return false + } + } + + guard case .finished(let db, _, _, let skipped) = finalState else { + Issue.record("expected finished, got \(finalState)") + return + } + #expect(db == "sales") + #expect(skipped == ["transaction_timeout"]) + } + + @Test("The same output under the strict policy is still a failure") + func strictPolicyStillFails() async throws { + let runner = FakeDumpRunner() + let service = service(kind: .restore, runner: runner) + let updates = service.stateUpdates() + + try service.run( + job: fakeJob(), + database: "sales", + fileURL: URL(fileURLWithPath: "/tmp/test-strict.dump") + ) + runner.finish(.init(exitCode: 1, stderr: Self.skippedSettingsStderr, wasCancelled: false)) + let finalState = try await firstMatching(updates) { + switch $0 { + case .finished, .failed: return true + default: return false + } + } + + guard case .failed(let message, let targetMayBeModified) = finalState else { + Issue.record("expected failed, got \(finalState)") + return + } + #expect(message == Self.skippedSettingsStderr) + #expect(targetMayBeModified) + } + + @Test("A real error under the tolerant policy is still a failure") + func tolerantPolicyRealError() async throws { + let runner = FakeDumpRunner() + let service = service(kind: .restore, runner: runner) + let updates = service.stateUpdates() + + try service.run( + job: fakeJob(exitPolicy: .toleratesUnrecognizedSessionSettings), + database: "sales", + fileURL: URL(fileURLWithPath: "/tmp/test-real-error.dump") + ) + runner.finish(.init(exitCode: 1, stderr: "FATAL: connection refused", wasCancelled: false)) + let finalState = try await firstMatching(updates) { + switch $0 { + case .finished, .failed: return true + default: return false + } + } + + guard case .failed = finalState else { + Issue.record("expected failed, got \(finalState)") + return + } + } + private func service(kind: NativeDumpKind, runner: FakeDumpRunner) -> NativeDumpService { NativeDumpService(kind: kind, runnerFactory: { job in runner.startedJob = job @@ -299,7 +471,7 @@ struct NativeDumpServiceStateMachineTests { runner.finish(.init(exitCode: 0, stderr: "", wasCancelled: false)) let finalState = try await firstMatching(updates) { if case .finished = $0 { return true }; return false } - if case .finished(let db, _, _) = finalState { + if case .finished(let db, _, _, _) = finalState { #expect(db == "sales") } else { Issue.record("expected finished, got \(finalState)") diff --git a/TableProTests/Database/PostgresRestoreDiagnosticsTests.swift b/TableProTests/Database/PostgresRestoreDiagnosticsTests.swift new file mode 100644 index 0000000000..f3a2bace4b --- /dev/null +++ b/TableProTests/Database/PostgresRestoreDiagnosticsTests.swift @@ -0,0 +1,287 @@ +import Foundation +import Testing + +@testable import TablePro + +@Suite("PostgresRestoreDiagnostics") +struct PostgresRestoreDiagnosticsTests { + private static let pgRestore17IntoServer92 = """ + pg_restore: error: could not execute query: ERROR: unrecognized configuration parameter "lock_timeout" + Command was: SET lock_timeout = 0; + pg_restore: error: could not execute query: ERROR: unrecognized configuration parameter "idle_in_transaction_session_timeout" + Command was: SET idle_in_transaction_session_timeout = 0; + pg_restore: error: could not execute query: ERROR: unrecognized configuration parameter "transaction_timeout" + Command was: SET transaction_timeout = 0; + pg_restore: error: could not execute query: ERROR: unrecognized configuration parameter "row_security" + Command was: SET row_security = off; + pg_restore: warning: errors ignored on restore: 4 + """ + + private static let pgRestore17IntoServer12 = """ + pg_restore: error: could not execute query: ERROR: unrecognized configuration parameter "transaction_timeout" + Command was: SET transaction_timeout = 0; + pg_restore: warning: errors ignored on restore: 1 + """ + + private static let pgRestore17ArchiveFrom17IntoServer96 = """ + pg_restore: error: could not execute query: ERROR: unrecognized configuration parameter "transaction_timeout" + Command was: SET transaction_timeout = 0; + pg_restore: error: could not set "default_table_access_method": ERROR: unrecognized configuration parameter "default_table_access_method" + pg_restore: warning: errors ignored on restore: 2 + """ + + private static let pgRestore17SequenceDumpIntoServer96 = """ + pg_restore: error: could not execute query: ERROR: unrecognized configuration parameter "transaction_timeout" + Command was: SET transaction_timeout = 0; + pg_restore: error: could not set "default_table_access_method": ERROR: unrecognized configuration parameter "default_table_access_method" + pg_restore: error: could not execute query: ERROR: syntax error at or near "AS" + LINE 2: AS integer + ^ + Command was: CREATE SEQUENCE public.t_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + + pg_restore: error: could not execute query: ERROR: relation "public.t_id_seq" does not exist + Command was: ALTER SEQUENCE public.t_id_seq OWNED BY public.t.id; + + + pg_restore: error: could not execute query: ERROR: relation "public.t_id_seq" does not exist + Command was: ALTER TABLE ONLY public.t ALTER COLUMN id SET DEFAULT nextval('public.t_id_seq'::regclass); + + + pg_restore: error: could not execute query: ERROR: relation "public.t_id_seq" does not exist + LINE 1: SELECT pg_catalog.setval('public.t_id_seq', 3, true); + ^ + Command was: SELECT pg_catalog.setval('public.t_id_seq', 3, true); + + + pg_restore: warning: errors ignored on restore: 6 + """ + + private static let pgRestore12InitializingIntoServer93 = """ + pg_restore: while INITIALIZING: + pg_restore: error: could not execute query: ERROR: unrecognized configuration parameter "idle_in_transaction_session_timeout" + Command was: SET idle_in_transaction_session_timeout = 0; + pg_restore: error: could not execute query: ERROR: unrecognized configuration parameter "row_security" + Command was: SET row_security = off; + pg_restore: warning: errors ignored on restore: 2 + """ + + private static let pgRestore12ProcessingTocIntoServer96 = """ + pg_restore: while PROCESSING TOC: + pg_restore: from TOC entry 202; 1259 19993 TABLE t postgres + pg_restore: error: could not set default_table_access_method: ERROR: unrecognized configuration parameter "default_table_access_method" + pg_restore: warning: errors ignored on restore: 1 + """ + + private static let pgRestore12BothPhasesIntoServer93 = """ + pg_restore: while INITIALIZING: + pg_restore: error: could not execute query: ERROR: unrecognized configuration parameter "idle_in_transaction_session_timeout" + Command was: SET idle_in_transaction_session_timeout = 0; + pg_restore: error: could not execute query: ERROR: unrecognized configuration parameter "row_security" + Command was: SET row_security = off; + pg_restore: while PROCESSING TOC: + pg_restore: from TOC entry 202; 1259 19993 TABLE t postgres + pg_restore: error: could not set default_table_access_method: ERROR: unrecognized configuration parameter "default_table_access_method" + pg_restore: warning: errors ignored on restore: 3 + """ + + private static let pgRestore11IntoServer93 = """ + pg_restore: [archiver (db)] Error while INITIALIZING: + pg_restore: [archiver (db)] could not execute query: ERROR: unrecognized configuration parameter "idle_in_transaction_session_timeout" + Command was: SET idle_in_transaction_session_timeout = 0; + + pg_restore: [archiver (db)] could not execute query: ERROR: unrecognized configuration parameter "row_security" + Command was: SET row_security = off; + + WARNING: errors ignored on restore: 2 + """ + + private static let pgRestore17FrenchLocaleIntoServer12 = """ + pg_restore: erreur : could not execute query: ERROR: unrecognized configuration parameter "transaction_timeout" + La commande était : SET transaction_timeout = 0; + pg_restore: attention : erreurs ignorées lors de la restauration : 1 + """ + + private static func skipped(_ stderr: String, exitCode: Int32 = 1) -> [String]? { + PostgresRestoreDiagnostics.skippedSessionSettings(exitCode: exitCode, stderr: stderr) + } + + @Test("A same-server round trip with pg_restore 17 on 9.2 skips four settings") + func roundTripOnServer92() { + #expect(Self.skipped(Self.pgRestore17IntoServer92) == [ + "lock_timeout", "idle_in_transaction_session_timeout", "transaction_timeout", "row_security" + ]) + } + + @Test("pg_restore 17 on a 12 server skips transaction_timeout alone") + func roundTripOnServer12() { + #expect(Self.skipped(Self.pgRestore17IntoServer12) == ["transaction_timeout"]) + } + + @Test("pg_restore 17's quoted could not set form counts as a skipped setting") + func quotedCouldNotSetForm() { + #expect(Self.skipped(Self.pgRestore17ArchiveFrom17IntoServer96) == [ + "transaction_timeout", "default_table_access_method" + ]) + } + + @Test("pg_restore 12 prefixes the preamble with a while INITIALIZING context line") + func pgRestore12InitializingContext() { + #expect(Self.skipped(Self.pgRestore12InitializingIntoServer93) == [ + "idle_in_transaction_session_timeout", "row_security" + ]) + } + + @Test("pg_restore 12 sets the table access method per TOC entry, unquoted") + func pgRestore12ProcessingTocContext() { + #expect(Self.skipped(Self.pgRestore12ProcessingTocIntoServer96) == ["default_table_access_method"]) + } + + @Test("pg_restore 12 with errors in both phases") + func pgRestore12BothPhases() { + #expect(Self.skipped(Self.pgRestore12BothPhasesIntoServer93) == [ + "idle_in_transaction_session_timeout", "row_security", "default_table_access_method" + ]) + } + + @Test("pg_restore 11 and older use another format and are not second-guessed") + func pgRestore11FailsSafe() { + #expect(Self.skipped(Self.pgRestore11IntoServer93) == nil) + } + + @Test("Translated client messages are not second-guessed") + func translatedClientMessages() { + #expect(Self.skipped(Self.pgRestore17FrenchLocaleIntoServer12) == nil) + } + + @Test("A real object error among skipped settings is still a failure") + func realErrorAmongSkippedSettings() { + #expect(Self.skipped(Self.pgRestore17SequenceDumpIntoServer96) == nil) + } + + @Test("Empty output with a failing exit is a failure") + func emptyStderr() { + #expect(Self.skipped("") == nil) + } + + @Test("Only exit code 1, the errors-ignored code, is ever tolerated") + func otherExitCodes() { + #expect(Self.skipped(Self.pgRestore17IntoServer12, exitCode: 0) == nil) + #expect(Self.skipped(Self.pgRestore17IntoServer12, exitCode: 2) == nil) + } + + @Test("A count that disagrees with the errors shown means output was lost") + func truncatedOutput() { + let lines = Self.pgRestore17IntoServer92.split(separator: "\n", omittingEmptySubsequences: false) + #expect(Self.skipped(lines.dropFirst(2).joined(separator: "\n")) == nil) + } + + @Test("A missing errors-ignored summary is a failure") + func missingSummary() { + let lines = Self.pgRestore17IntoServer12.split(separator: "\n", omittingEmptySubsequences: false) + #expect(Self.skipped(lines.dropLast().joined(separator: "\n")) == nil) + } + + @Test("Anything after the summary is a failure, context lines included") + func outputAfterSummary() { + #expect(Self.skipped(Self.pgRestore17IntoServer12 + "\npg_restore: error: could not execute query: ERROR: boom") == nil) + #expect(Self.skipped(Self.pgRestore17IntoServer12 + "\npg_restore: while INITIALIZING:") == nil) + } + + @Test("The same setting rejected twice is named once") + func duplicateSettingNamedOnce() { + let stderr = """ + pg_restore: error: could not execute query: ERROR: unrecognized configuration parameter "transaction_timeout" + Command was: SET transaction_timeout = 0; + pg_restore: error: could not execute query: ERROR: unrecognized configuration parameter "transaction_timeout" + Command was: SET transaction_timeout = 0; + pg_restore: warning: errors ignored on restore: 2 + """ + #expect(Self.skipped(stderr) == ["transaction_timeout"]) + } + + @Test("A rejected SET naming a different parameter than the error is a failure") + func mismatchedSetParameter() { + let stderr = """ + pg_restore: error: could not execute query: ERROR: unrecognized configuration parameter "row_security" + Command was: SET transaction_timeout = 0; + pg_restore: warning: errors ignored on restore: 1 + """ + #expect(Self.skipped(stderr) == nil) + } + + @Test("A could not set line naming a different parameter than the error is a failure") + func mismatchedCouldNotSetParameter() { + let quoted = """ + pg_restore: error: could not set "default_table_access_method": ERROR: unrecognized configuration parameter "row_security" + pg_restore: warning: errors ignored on restore: 1 + """ + let unquoted = """ + pg_restore: error: could not set default_table_access_method: ERROR: unrecognized configuration parameter "row_security" + pg_restore: warning: errors ignored on restore: 1 + """ + #expect(Self.skipped(quoted) == nil) + #expect(Self.skipped(unquoted) == nil) + } + + @Test("A command carrying a second statement is not a skipped setting") + func multiStatementCommand() { + let stderr = """ + pg_restore: error: could not execute query: ERROR: unrecognized configuration parameter "bogus" + Command was: SET bogus = 1; CREATE TABLE t(id int); + pg_restore: warning: errors ignored on restore: 1 + """ + #expect(Self.skipped(stderr) == nil) + } + + @Test("A quoted value is one value, and a quote that ends early is not") + func quotedValues() { + let quoted = """ + pg_restore: error: could not execute query: ERROR: unrecognized configuration parameter "bogus" + Command was: SET bogus = 'it''s fine'; + pg_restore: warning: errors ignored on restore: 1 + """ + let escaping = """ + pg_restore: error: could not execute query: ERROR: unrecognized configuration parameter "bogus" + Command was: SET bogus = 'a'; DROP TABLE t; SELECT 'b'; + pg_restore: warning: errors ignored on restore: 1 + """ + #expect(Self.skipped(quoted) == ["bogus"]) + #expect(Self.skipped(escaping) == nil) + } + + @Test("A SET rejected for a bad value rather than an unknown parameter is a failure") + func invalidValue() { + let stderr = """ + pg_restore: error: could not execute query: ERROR: invalid value for parameter "client_encoding": "LATIN9X" + Command was: SET client_encoding = 'LATIN9X'; + pg_restore: warning: errors ignored on restore: 1 + """ + #expect(Self.skipped(stderr) == nil) + } + + @Test("A connection failure is a failure") + func connectionFailure() { + let stderr = """ + pg_restore: error: connection to server at "127.0.0.1", port 5432 failed: Connection refused + \tIs the server running on that host and accepting TCP/IP connections? + """ + #expect(Self.skipped(stderr) == nil) + } + + @Test("A server that reports errors in another language is not second-guessed") + func localizedServerMessage() { + let stderr = """ + pg_restore: error: could not execute query: ERROR: paramètre de configuration « transaction_timeout » non reconnu + Command was: SET transaction_timeout = 0; + pg_restore: warning: errors ignored on restore: 1 + """ + #expect(Self.skipped(stderr) == nil) + } +} diff --git a/TableProTests/Views/Backup/BackupResultSheetSkippedSettingsTests.swift b/TableProTests/Views/Backup/BackupResultSheetSkippedSettingsTests.swift new file mode 100644 index 0000000000..d41f05e274 --- /dev/null +++ b/TableProTests/Views/Backup/BackupResultSheetSkippedSettingsTests.swift @@ -0,0 +1,30 @@ +import Foundation +import Testing + +@testable import TablePro + +@Suite("BackupResultSheet skipped settings note") +struct BackupResultSheetSkippedSettingsTests { + @Test("No note when nothing was skipped") + func noSettings() { + #expect(BackupResultSheet.skippedSettingsNote([]) == nil) + } + + @Test("One setting is named on its own") + func oneSetting() { + let note = BackupResultSheet.skippedSettingsNote(["transaction_timeout"]) + #expect(note?.contains("transaction_timeout") == true) + } + + @Test("Every setting is named, however many there are") + func severalSettings() { + let settings = [ + "lock_timeout", "idle_in_transaction_session_timeout", "transaction_timeout", + "row_security", "default_table_access_method" + ] + let note = BackupResultSheet.skippedSettingsNote(settings) + for setting in settings { + #expect(note?.contains(setting) == true) + } + } +} diff --git a/docs/features/backup-restore.mdx b/docs/features/backup-restore.mdx index 59eba8abd9..8a4c069236 100644 --- a/docs/features/backup-restore.mdx +++ b/docs/features/backup-restore.mdx @@ -138,3 +138,5 @@ A non-zero exit shows the last 64 KB of the tool's stderr in a scrollable monosp | An authentication failure | The password goes through the environment or a config file rather than a prompt, so this is the account or the database. Check that the role can log in | | Objects that conflict with the dump | Restore into a fresh database, or drop the conflicting objects first | | *"a single transaction can only write to a single attached database"* | A DuckDB query tab has an open transaction that has already written. Commit or roll it back, then run the backup again | + +One non-zero exit is not a failure. A `pg_restore` newer than the server sets parameters the server does not have, such as `transaction_timeout` on anything before PostgreSQL 17, and exits 1 after restoring everything. When those are its only errors, the restore reports complete and names the settings the server skipped. Any other error in the same run still fails it. So does a server whose `lc_messages` is not English, because its errors cannot be read. From dedfe65b6e975ebef78e020035470181be9c5a69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 00:08:43 +0700 Subject: [PATCH 11/54] fix(plugin-mysql): replay a statement across a dropped connection only on a session holding nothing (#2749) --- CHANGELOG.md | 2 + CLAUDE.md | 2 + .../MySQLDriverPlugin/MySQLPluginDriver.swift | 25 +++++---- .../MySQLSessionFootprint.swift | 34 +++++++++++- .../MySQLStatementClassification.swift | 13 +++++ .../SQLStatementSplitting.swift | 12 ++++- .../Plugins/MySQLSessionFootprintTests.swift | 39 ++++++++++++++ .../MySQLStatementClassificationTests.swift | 36 +++++++++++++ .../Plugins/SQLStatementSplittingTests.swift | 54 +++++++++++++++++++ docs/databases/mysql.mdx | 8 ++- 10 files changed, 213 insertions(+), 12 deletions(-) create mode 100644 TableProTests/Plugins/SQLStatementSplittingTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index e93e81ab57..c4b1110375 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Read-only write explanation never shown on PostgreSQL servers. - Safe Mode minimum from a configuration profile missing from the toolbar, the Database menu and the connection form. (#2030) - Stop not ending queries on MySQL and MariaDB servers without TLS. +- Wrong results after MySQL retakes a dropped connection, on a session that had set a variable, a session setting or a database. +- Session state set by the `/*! ... */` statements a MySQL dump writes counting as a comment. - Users & Roles failing, Stop not ending queries and sequences listed as tables on TiDB servers opened as MySQL. - Update release notes show all changes for the offered version, with new features before fixes and properly formatted Markdown. The full changelog is also available from Help and Software Update settings. - Blank welcome window list when a search matched nothing and a favorite existed. diff --git a/CLAUDE.md b/CLAUDE.md index 568c0efb8d..048cd8d80e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -227,6 +227,8 @@ To ship one: add the record type or field in CloudKit Console (or `xcrun cktool **A MySQL session's character set is server state, and the driver sets it rather than asking for it**: `MYSQL_SET_CHARSET_NAME` only puts a collation byte in the handshake, and the server is free to ignore it. `init_connect='SET NAMES latin1'` for any user without `CONNECTION_ADMIN`, MariaDB's `skip-character-set-client-handshake`, and a server with no `utf8mb4` all leave the session latin1 while libmariadb still reports `utf8mb4`. The driver sends UTF-8 either way, so every comment and value it wrote there was stored double-encoded, which is the `メール` of #2725, and a user-variable comparison on MySQL 8 failed with `ERROR 1267` under the handshake's `utf8mb4_general_ci`. So `MariaDBCharacterSet.establishSession`, which the macOS plugin and the iOS driver share, calls `mysql_set_character_set` on every connect path, falls back to a plain `SET NAMES utf8` (libmariadb itself rewrites `utf8` to `utf8mb3`, which a pre-5.5.3 server does not know), and keeps the server's own session when it refuses both rather than failing the connect: a MySQL-protocol engine that rejects `SET NAMES` must still connect. Two rules follow. Outgoing SQL stays the UTF-8 bytes of the Swift string and never follows a mid-session `SET NAMES`: a legacy dump that declares `SET NAMES latin1` over UTF-8 bytes restores byte-for-byte only because nothing re-encodes it, which is also what the `mysql` client does. And every result cell decodes through `MySQLColumnDecoding` by its field's own `charsetnr`, never as "UTF-8 and hope": a latin1 field reads UTF-8 first and then MySQL's latin1, which is cp1252 plus five C1 pass-through bytes and not Foundation's `.isoLatin1` or `.windowsCP1252`. The Foundation encodings in `MySQLCharacterSet` are a hand transcription of the server's tables; `scripts/check-mysql-charset-decoding.sh` diffs them against a live server, and a charset that disagrees stays out of the table. **UTF-8 via Latin 1** (`mysqlConnectionEncoding`) sets only `character_set_client` to latin1 and repairs the text client-side, so correctly stored text is never read back as `?`, which a latin1 results charset would do and a structure edit would then write back. +**A reconnect the user did not ask for hands back a different session, so only a session holding nothing may replay a statement across one**: `MySQLPluginDriver.executeWithReconnect` retakes a connection the server dropped and runs the statement again, and the new session has none of the old one's state. Measured on MySQL 8.4.11 by killing the connection under it: `SELECT @probe` answered `NULL` where it had answered 42, `SELECT DATABASE()` answered the database the driver connects to over the one a `USE` had selected, and `@@SESSION.sql_mode` answered the server default over the session's `ANSI_QUOTES`, all three without raising. `mysqlMayReplay` is the single gate and reads `MySQLSessionFootprint.isClean`, not `hasOpenTransaction` alone; the same footprint gates the idle release, so one flag covers both paths. Only the driver's own statements go in with `countsAsActivity: false`, and only because the driver puts them back itself: the query timeout, and the `USE` behind a database switch, which reconnects through `_activeDatabase`. And `/*!40101 ... */` is not a comment, it is SQL the server runs, so `SQLStatementSplitting` keeps it whole rather than stripping it; a mysqldump preamble run from the editor sets the character set, the time zone and six `@OLD_` variables inside them, and dropping them left the footprint reading clean. + **A MongoDB update or delete is anchored on `_id` or it does not run**: `generateDelete` used to fall back to a filter built from the remaining columns, which silently dropped every value it could not stringify (all binary) and then `deleteOne`d the first partial match, so a document with a binary `_id` could delete a different document. Both paths now skip with a logged warning instead, matching what `generateUpdate` already did. **Redis Cluster routing follows the server's own answer, and the curated table is only a fallback**: `RedisCommandRouting` fetches `COMMAND` once at connect, which supplies key positions on every Redis and, from Redis 7, the `request_policy` / `response_policy` tips that say which commands fan out and how their replies combine. A policy lives on the *subcommand* entry, not the container (`COMMAND INFO config` carries no tips at all; `config|set` is what says `all_nodes`), so the table is keyed `container|sub`. Redis 6 reports no tips, so a parsed reply is merged *over* the curated table rather than replacing it, or `DBSIZE`, `KEYS` and `FLUSHDB` would each go to one shard of a cluster and report success. The curated table is a hand-written list that has to agree with Redis and that nothing at runtime checks, so `scripts/check-redis-command-routing.sh [host] [port]` diffs it against a live Redis 7+; it found 32 disagreements the first time it ran, including a container command hashed on its literal subcommand name and `MSETNX` marked splittable when splitting it breaks the guarantee it exists for. Two rules follow. A container command takes no key of its own, so `OBJECT`, `MEMORY` and `CONFIG` declare no key positions and their keyed subcommands are listed separately, at the index the key sits in the *full* argument list (`OBJECT ENCODING k` puts it at 2, not 1). And an unknown command is routed as keyless rather than by hashing `argv[1]`: a keyless container like `SCRIPT LOAD` answers `+OK` from one node and never sends a `MOVED` to correct the guess. diff --git a/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift b/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift index c982bce1ce..5e07d7746f 100644 --- a/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift +++ b/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift @@ -266,10 +266,9 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { } /// The reconnect this does is not the idle release: it is recovery from a connection the - /// server dropped, where the session state is already gone. `mysqlStatementIsSafeToReplay` - /// decides whether the statement can be run twice, and the footprint decides whether running - /// it again would land it somewhere different. Replaying a statement outside the transaction - /// the user opened for it commits work they meant to be able to roll back. + /// server dropped, where the session state is already gone. `mysqlMayReplay` owns the + /// decision, and takes both halves of it: whether the statement means the same thing run + /// twice, and whether the session that replaces this one can answer it the same way. private func executeWithReconnect( query: String, isRetry: Bool, @@ -319,8 +318,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { columnMeta: result.columnMeta ) } catch let error as MariaDBPluginError - where !isRetry && isConnectionLostError(error) && mysqlStatementIsSafeToReplay(query) - && !hasOpenTransaction { + where !isRetry && isConnectionLostError(error) && mayReplay(query) { try await reconnect() return try await executeWithReconnect( query: query, @@ -344,8 +342,8 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { } } - private var hasOpenTransaction: Bool { - sessionLock.withLock { footprint.hasOpenTransaction } + private func mayReplay(_ query: String) -> Bool { + sessionLock.withLock { mysqlMayReplay(query, on: footprint) } } /// Takes a server connection again if the last one was handed back. A connection that was @@ -1019,8 +1017,17 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { // MARK: - Database Switching + /// The `USE` goes in the way the query timeout does, as the driver's own setup rather than as + /// use. `_activeDatabase` is what every reconnect connects to, so the database the driver + /// switched to is not the session's to lose, and counting it would leave the footprint dirty + /// from the first database switch onward. A `USE` the user types is a different statement: the + /// driver does not know about it, a reconnect silently undoes it, and the footprint says so. func switchDatabase(to database: String) async throws { - _ = try await execute(query: "USE \(quoteIdentifier(database))") + _ = try await executeWithReconnect( + query: "USE \(quoteIdentifier(database))", + isRetry: false, + countsAsActivity: false + ) _activeDatabase = database } diff --git a/Plugins/MySQLDriverPlugin/MySQLSessionFootprint.swift b/Plugins/MySQLDriverPlugin/MySQLSessionFootprint.swift index b819ad1972..38650a4716 100644 --- a/Plugins/MySQLDriverPlugin/MySQLSessionFootprint.swift +++ b/Plugins/MySQLDriverPlugin/MySQLSessionFootprint.swift @@ -38,6 +38,12 @@ struct MySQLSessionFootprint: Equatable { private(set) var hasLockedTables = false private(set) var hasSessionSettings = false + /// A `USE` the user ran themselves. The driver's own database switch does not come through + /// here, because it records the database it moved to and every reconnect connects to that one; + /// a `USE` typed into the editor does not, so a reconnect silently puts the session back on + /// the database the driver still thinks it is on. + private(set) var hasChangedDatabase = false + /// A `CALL` runs a body this driver never sees, and a routine is free to create a temporary /// table, take a lock or open a transaction. Opaque is the only honest reading. private(set) var ranOpaqueRoutine = false @@ -69,6 +75,9 @@ struct MySQLSessionFootprint: Equatable { if hasSessionSettings { return String(localized: "This connection has session settings changed, which reconnecting would reset.") } + if hasChangedDatabase { + return String(localized: "This connection switched database with USE, which reconnecting would undo.") + } if ranOpaqueRoutine { return String(localized: "This connection called a stored routine, so TablePro cannot tell what the session is holding.") } @@ -95,7 +104,7 @@ struct MySQLSessionFootprint: Equatable { } private mutating func observeStatement(_ statement: String) { - let normalized = statement.uppercased() + let normalized = Self.executableBody(of: statement).uppercased() guard !normalized.isEmpty else { return } if normalized.hasPrefix("CREATE TEMPORARY ") || normalized.hasPrefix("CREATE OR REPLACE TEMPORARY ") { @@ -121,6 +130,9 @@ struct MySQLSessionFootprint: Equatable { if normalized.hasPrefix("CALL ") { ranOpaqueRoutine = true } + if normalized.hasPrefix("USE ") { + hasChangedDatabase = true + } if normalized.contains("GET_LOCK(") { hasAdvisoryLocks = true } @@ -138,6 +150,26 @@ struct MySQLSessionFootprint: Equatable { } } + /// What MySQL runs when the statement is one of its version-gated comments, and the statement + /// itself otherwise. + /// + /// `/*!40101 SET NAMES utf8mb4 */` is executed by any server from 4.1.1, and MariaDB spells + /// its own `/*M!100301 ... */`. mysqldump writes its whole preamble this way, so a restore run + /// from the editor sets `character_set_client`, the time zone and half a dozen `@OLD_` + /// variables inside them. `SQLStatementSplitting` leaves them whole rather than reading them + /// as comments, because only the engine that executes the body can say what it is. + private static func executableBody(of statement: String) -> String { + guard statement.hasPrefix("/*!") || statement.hasPrefix("/*M!") else { return statement } + guard let close = statement.range(of: "*/"), + statement[close.upperBound...].allSatisfy({ $0.isWhitespace }) else { return statement } + let marked = statement[statement.index(statement.startIndex, offsetBy: 2).. Bool { + text.hasPrefix("/*!") || text.hasPrefix("/*M!") + } + /// Tracks whether the scan currently sits inside something a `;` cannot end. private struct Scanner { private enum State { diff --git a/TableProTests/Plugins/MySQLSessionFootprintTests.swift b/TableProTests/Plugins/MySQLSessionFootprintTests.swift index a00be78d47..a795298f3b 100644 --- a/TableProTests/Plugins/MySQLSessionFootprintTests.swift +++ b/TableProTests/Plugins/MySQLSessionFootprintTests.swift @@ -110,6 +110,45 @@ struct MySQLSessionFootprintTests { #expect(footprint(after: "SELECT @counter := 1").hasUserVariables) } + /// mysqldump writes its whole preamble as version-gated comments, which MySQL executes. They + /// read as comments, so the statement splitter used to drop them and a restore run from the + /// editor left the session holding six user variables and two session settings that the + /// footprint reported as nothing. + @Test("A version-gated comment sets session state, and is seen") + func versionGatedCommentsAreSeen() { + let preamble = """ + /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; + /*!40103 SET TIME_ZONE='+00:00' */; + INSERT INTO `t` VALUES (1); + """ + let result = footprint(after: preamble) + #expect(result.hasUserVariables) + #expect(result.hasSessionSettings) + #expect(result.blockingReason != nil) + + #expect(footprint(after: "/*M!100301 SET @x = 1 */").hasUserVariables) + #expect(footprint(after: "/*! SET SESSION sql_mode = 'ANSI' */").hasSessionSettings) + } + + /// Only a statement that is entirely one of them. A version-gated comment inside a `CREATE + /// TABLE`, which is how mysqldump writes a partition clause, is part of that statement. + @Test("A version-gated comment inside another statement is left alone") + func versionGatedCommentsInsideAStatementAreLeftAlone() { + #expect(footprint(after: "CREATE TABLE t (a INT) /*!50100 PARTITION BY HASH (a) */").isClean) + #expect(footprint(after: "SELECT '/*!40101 SET NAMES utf8 */'").isClean) + } + + /// `USE` moves the session to another database, and a reconnect puts it back on the one the + /// driver holds without saying so. Measured on MySQL 8.4.11: after the connection was killed, + /// `SELECT DATABASE()` answered the connection's own database, not the one `USE` had selected. + @Test("A database switched with USE is tracked") + func useIsTracked() { + let result = footprint(after: "USE reporting") + #expect(result.hasChangedDatabase) + #expect(result.blockingReason != nil) + #expect(footprint(after: "SELECT * FROM t USE INDEX (i)").isClean) + } + @Test("A reset clears everything, for a session that is genuinely new") func resetClearsEverything() { var result = footprint(after: "BEGIN", "CREATE TEMPORARY TABLE staging (a INT)") diff --git a/TableProTests/Plugins/MySQLStatementClassificationTests.swift b/TableProTests/Plugins/MySQLStatementClassificationTests.swift index b4f2e1bd9f..6903a627a6 100644 --- a/TableProTests/Plugins/MySQLStatementClassificationTests.swift +++ b/TableProTests/Plugins/MySQLStatementClassificationTests.swift @@ -111,4 +111,40 @@ struct MySQLReplaySafetyTests { #expect(mysqlStatementIsSafeToReplay("SELECT *\n FROM users\n FOR UPDATE") == false) #expect(mysqlStatementIsSafeToReplay("SELECT NEXT\n VALUE\tFOR order_seq") == false) } + + private func footprint(after statements: String...) -> MySQLSessionFootprint { + var footprint = MySQLSessionFootprint() + for statement in statements { + footprint.observe(statement) + } + return footprint + } + + /// The session that replaces a dropped one is a new one, and the statement is answered from + /// it. Measured on MySQL 8.4.11: `SELECT @probe` came back `NULL` where it had come back 42, + /// with nothing raised. A replay is therefore only for a session holding nothing. + @Test("A read is replayed only on a session that holds nothing") + func replayNeedsACleanSession() { + #expect(mysqlMayReplay("SELECT * FROM users", on: footprint(after: "SELECT 1"))) + + for statement in [ + "SET @total = 5", + "SET SESSION sql_mode = 'ANSI'", + "CREATE TEMPORARY TABLE staging (a INT)", + "PREPARE stmt FROM 'SELECT 1'", + "LOCK TABLES users WRITE", + "USE reporting", + "BEGIN", + "CALL rebuild_report()", + "/*!40103 SET TIME_ZONE='+00:00' */", + ] { + #expect(!mysqlMayReplay("SELECT * FROM users", on: footprint(after: statement)), "\(statement)") + } + } + + @Test("A statement that is unsafe on its own is not replayed on a clean session either") + func replayStillNeedsASafeStatement() { + #expect(!mysqlMayReplay("UPDATE users SET name = 'a'", on: MySQLSessionFootprint())) + #expect(!mysqlMayReplay("SELECT GET_LOCK('job', 10)", on: MySQLSessionFootprint())) + } } diff --git a/TableProTests/Plugins/SQLStatementSplittingTests.swift b/TableProTests/Plugins/SQLStatementSplittingTests.swift new file mode 100644 index 0000000000..83c678562c --- /dev/null +++ b/TableProTests/Plugins/SQLStatementSplittingTests.swift @@ -0,0 +1,54 @@ +// +// SQLStatementSplittingTests.swift +// TableProTests +// + +import Foundation +import Testing +import TableProPluginKit + +@Suite("SQL statement splitting") +struct SQLStatementSplittingTests { + @Test("A batch splits on the semicolons that are separators") + func splitsOnSeparators() { + #expect(SQLStatementSplitting.statements(in: "SELECT 1; SELECT 2;") == ["SELECT 1", "SELECT 2"]) + #expect(SQLStatementSplitting.statements(in: "SELECT ';'") == ["SELECT ';'"]) + #expect(SQLStatementSplitting.statements(in: " ; ; ").isEmpty) + } + + @Test("A comment in front of a statement is dropped") + func leadingCommentsAreDropped() { + #expect(SQLStatementSplitting.statements(in: "-- note\nSELECT 1") == ["SELECT 1"]) + #expect(SQLStatementSplitting.statements(in: "/* note */ SELECT 1") == ["SELECT 1"]) + #expect(SQLStatementSplitting.statements(in: "# note\nSELECT 1") == ["SELECT 1"]) + #expect(SQLStatementSplitting.statements(in: "/* only a comment */").isEmpty) + } + + /// `/*!40101 ... */` is SQL, not a comment: MySQL runs the body on any server at or above the + /// version, MariaDB spells its own `/*M!100301 ... */`, and mysqldump writes its entire + /// preamble that way. Dropping them as comments left the MySQL driver blind to every `SET` a + /// restore ran, so it read the session as holding nothing. + @Test("A version-gated comment is kept, because the server executes it") + func executableCommentsAreKept() { + #expect( + SQLStatementSplitting.statements(in: "/*!40101 SET NAMES utf8 */;") + == ["/*!40101 SET NAMES utf8 */"] + ) + #expect( + SQLStatementSplitting.statements(in: "/*M!100301 SET @x = 1 */;") + == ["/*M!100301 SET @x = 1 */"] + ) + #expect( + SQLStatementSplitting.statements(in: "/*! SET @x = 1 */; SELECT 1") + == ["/*! SET @x = 1 */", "SELECT 1"] + ) + } + + /// Keeping it must not make it read as a transaction statement. The keyword is no longer the + /// first word of the statement, and closing already requires the whole statement to be one. + @Test("A transaction keyword inside a version-gated comment does not close a transaction") + func executableCommentsNeverClose() { + #expect(SQLTransactionTracking.effect(of: "BEGIN; /*!40101 COMMIT */") == .opens) + #expect(SQLTransactionTracking.effect(of: "/*!40101 COMMIT */") == .unchanged) + } +} diff --git a/docs/databases/mysql.mdx b/docs/databases/mysql.mdx index a930f51cef..35812037f2 100644 --- a/docs/databases/mysql.mdx +++ b/docs/databases/mysql.mdx @@ -74,7 +74,13 @@ To stop the check itself, set **Check connections** to **Only when I use the con Reconnecting costs a TCP connect, the TLS handshake and authentication: measured at 2ms against a server on the same machine and 800ms to 1.9s across the internet. That cost lands on the first query after an idle period, so leave this at `0` for a remote server unless the slot matters more than the wait. -A release is refused, with the reason, while the session holds anything a reconnect would destroy: an open transaction, a temporary table, a prepared statement, a `GET_LOCK`, `LOCK TABLES`, a user variable, a changed session setting, or a stored routine call, whose body is opaque. +A release is refused, with the reason, while the session holds anything a reconnect would destroy: an open transaction, a temporary table, a prepared statement, a `GET_LOCK`, `LOCK TABLES`, a user variable, a changed session setting, a database selected with `USE`, or a stored routine call, whose body is opaque. The statements a dump runs inside `/*!40101 ... */` count, since the server executes them. + +## When the server drops the connection + +A read that fails because the server closed the connection is run once more on a new one, and only from a session holding nothing: the same list as above. Every other statement reports the error, because the second session answers from different state. Measured on MySQL 8.4.11, replaying regardless: `SELECT @total` came back `NULL` where it had come back 42, and `SELECT DATABASE()` came back as the connection's own database rather than the one `USE` had selected, neither of them raising anything. + +**Database > Reconnect** takes a new connection and puts back the database, the schema and the startup commands. ## Garbled non-Latin text From 30eb207f9c3e559f4181044f21621c7fc7ab1c0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 00:09:12 +0700 Subject: [PATCH 12/54] fix(datagrid): carry every per-table setting through a rename and a connection delete (#2746) --- CHANGELOG.md | 1 + .../SyncMetadataStorage.swift | 18 ++- .../Core/Storage/ColumnLayoutPersister.swift | 33 +++-- .../Core/Storage/ConnectionLocalState.swift | 8 +- .../Core/Storage/FilterSettingsStorage.swift | 73 +++++----- .../Storage/ForeignKeyLabelColumnStore.swift | 32 ++++- .../Core/Storage/HighlightRuleStorage.swift | 21 +-- .../Storage/Preferences/KeyValueStore.swift | 26 ++++ .../Storage/Preferences/PreferenceKeys.swift | 7 +- .../Core/Storage/Preferences/TableScope.swift | 4 + .../Storage/TableScopedSettingsStore.swift | 32 +++++ .../Storage/ValueDisplayFormatStorage.swift | 41 +++++- TablePro/Core/Sync/SyncChangeTracker.swift | 8 ++ ...ainContentCoordinator+RenameAdoption.swift | 42 ++---- .../Core/Storage/ColumnLayoutSyncTests.swift | 77 ++++++++++ .../Storage/FilterSettingsStorageTests.swift | 86 ++++++++++- .../Storage/HighlightRuleStorageTests.swift | 20 ++- .../TableScopedSettingsRegistryTests.swift | 134 ++++++++++++++++++ .../ValueDisplayFormatStorageTests.swift | 96 +++++++++++++ .../Core/Sync/SyncChangeTrackerTests.swift | 34 ++++- .../ForeignKeyLabelColumnStoreTests.swift | 75 ++++++++++ 21 files changed, 760 insertions(+), 108 deletions(-) create mode 100644 TablePro/Core/Storage/TableScopedSettingsStore.swift create mode 100644 TableProTests/Core/Storage/TableScopedSettingsRegistryTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index c4b1110375..c6d31e1ad0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -148,6 +148,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Garbled non-ASCII text on PostgreSQL databases not encoded in UTF-8 after `RESET ALL` or `DISCARD ALL`. - Garbled or double-encoded non-ASCII text on iOS with PostgreSQL databases not encoded in UTF-8. - Garbled non-ASCII text when restoring a PostgreSQL SQL export into a database not encoded in UTF-8. +- Display As formats and foreign key labels lost on a rename, and kept with column layouts after deleting a connection. ### Security diff --git a/Packages/TableProCore/Sources/TableProSyncTransport/SyncMetadataStorage.swift b/Packages/TableProCore/Sources/TableProSyncTransport/SyncMetadataStorage.swift index e6abad6f91..860a2148e2 100644 --- a/Packages/TableProCore/Sources/TableProSyncTransport/SyncMetadataStorage.swift +++ b/Packages/TableProCore/Sources/TableProSyncTransport/SyncMetadataStorage.swift @@ -73,9 +73,14 @@ public final class SyncMetadataStorage: @unchecked Sendable { } public func removeDirty(_ id: String, type: SyncRecordType) { - var ids = dirtyIds(for: type) - ids.remove(id) - saveDirtyIds(ids, for: type) + removeDirty([id], type: type) + } + + public func removeDirty(_ ids: [String], type: SyncRecordType) { + guard !ids.isEmpty else { return } + var current = dirtyIds(for: type) + current.subtract(ids) + saveDirtyIds(current, for: type) } public func clearDirty(type: SyncRecordType) { @@ -95,8 +100,13 @@ public final class SyncMetadataStorage: @unchecked Sendable { } public func addTombstone(_ id: String, type: SyncRecordType) { + addTombstones([id], type: type) + } + + public func addTombstones(_ ids: [String], type: SyncRecordType) { + guard !ids.isEmpty else { return } var current = tombstones(for: type) - current.append(Tombstone(id: id)) + current.append(contentsOf: ids.map { Tombstone(id: $0) }) saveTombstones(current, for: type) } diff --git a/TablePro/Core/Storage/ColumnLayoutPersister.swift b/TablePro/Core/Storage/ColumnLayoutPersister.swift index 8e73b13750..4fdb4979e6 100644 --- a/TablePro/Core/Storage/ColumnLayoutPersister.swift +++ b/TablePro/Core/Storage/ColumnLayoutPersister.swift @@ -8,7 +8,7 @@ import os import TableProSyncTransport @MainActor -final class FileColumnLayoutPersister: ColumnLayoutPersisting { +final class FileColumnLayoutPersister: ColumnLayoutPersisting, TableScopedSettingsStore { static let shared: FileColumnLayoutPersister = { let persister = FileColumnLayoutPersister() persister.performScopeMigration() @@ -131,20 +131,23 @@ final class FileColumnLayoutPersister: ColumnLayoutPersisting { /// Persisted before either sync marker is written, because `markDeleted` posts a change /// notification that can start a sync, and a sync reading the old file would put the entry /// back under the name that has gone. - func rename(from oldKey: ColumnLayoutTableKey, to newKey: ColumnLayoutTableKey) { - var entries = loadEntries(for: oldKey.connectionId) - guard let entry = entries.removeValue(forKey: oldKey.storageKey) else { return } - entries[newKey.storageKey] = entry - cache[oldKey.connectionId] = entries - writeEntries(entries, for: oldKey.connectionId) - syncTracker.markDirty(.settings, id: Self.syncCategory(for: newKey.storageKey)) - syncTracker.markDeleted(.settings, id: Self.syncCategory(for: oldKey.storageKey)) + func renameTable(from oldScope: TableScope, to newScope: TableScope) { + let oldKey = oldScope.storageComponent + let newKey = newScope.storageComponent + guard oldKey != newKey else { return } + var entries = loadEntries(for: oldScope.connectionId) + guard let entry = entries.removeValue(forKey: oldKey) else { return } + entries[newKey] = entry + cache[oldScope.connectionId] = entries + writeEntries(entries, for: oldScope.connectionId) + syncTracker.markDirty(.settings, id: Self.syncCategory(for: newKey)) + syncTracker.markDeleted(.settings, id: Self.syncCategory(for: oldKey)) } /// Moves every table's saved layout from one container to another. Same prefix rewrite as the /// filter store, and for the same reason: the tables that have a layout are whatever the user /// has opened over the life of the connection, not what is loaded now. - func renameScope( + func renameContainer( connectionId: UUID, fromDatabase: String, fromSchema: String?, @@ -174,6 +177,16 @@ final class FileColumnLayoutPersister: ColumnLayoutPersisting { } } + func purgeConnections(_ connectionIds: Set) { + var deletedCategories: [String] = [] + for connectionId in connectionIds { + deletedCategories += loadEntries(for: connectionId).keys.map(Self.syncCategory(for:)) + cache[connectionId] = [:] + removeFile(for: connectionId) + } + syncTracker.markDeleted(.settings, ids: deletedCategories) + } + func clear(for key: ColumnLayoutTableKey) { removeLegacyHidden(for: key) diff --git a/TablePro/Core/Storage/ConnectionLocalState.swift b/TablePro/Core/Storage/ConnectionLocalState.swift index 0891c8ab73..66387bf739 100644 --- a/TablePro/Core/Storage/ConnectionLocalState.swift +++ b/TablePro/Core/Storage/ConnectionLocalState.swift @@ -22,7 +22,8 @@ internal enum ConnectionLocalState { internal static func purge( connectionIds: Set, origin: Origin, - appSettings: AppSettingsStorage = .shared + appSettings: AppSettingsStorage = .shared, + tableScopedStores: [any TableScopedSettingsStore] = TableScopedSettingsRegistry.stores ) { guard !connectionIds.isEmpty else { return } @@ -37,8 +38,9 @@ internal enum ConnectionLocalState { QueryInsightsPreferencesStorage.remove(for: connectionId) } - FilterSettingsStorage.shared.removeFilters(for: connectionIds) - HighlightRuleStorage.shared.removeRules(for: connectionIds) + for store in tableScopedStores { + store.purgeConnections(connectionIds) + } DatabaseTreeFilterStorage.shared.removeFilters(for: connectionIds) RecentlyClosedTabStore.shared.removeEntries(for: connectionIds) WorkspaceRailOrderStore.shared.removeEntries(for: connectionIds) diff --git a/TablePro/Core/Storage/FilterSettingsStorage.swift b/TablePro/Core/Storage/FilterSettingsStorage.swift index edb873cff8..7383bc6daf 100644 --- a/TablePro/Core/Storage/FilterSettingsStorage.swift +++ b/TablePro/Core/Storage/FilterSettingsStorage.swift @@ -75,7 +75,7 @@ struct FilterSettings: Codable, Equatable { } @MainActor -final class FilterSettingsStorage { +final class FilterSettingsStorage: TableScopedSettingsStore { static let shared = FilterSettingsStorage() nonisolated private static let logger = Logger(subsystem: "com.TablePro", category: "FilterSettingsStorage") @@ -84,6 +84,7 @@ final class FilterSettingsStorage { private static let migrationCompleteKey = "com.TablePro.filterStateMigrationComplete" private static let compositeKeyMigrationKey = "com.TablePro.filterStateCompositeKeyMigrationComplete" private static let settingsKey = "com.TablePro.filter.settings" + private static let browseKeySuffix = ".browse" private let defaults: UserDefaults @@ -257,38 +258,31 @@ final class FilterSettingsStorage { /// Moves a table's saved filters onto its new name. A rename keeps the columns the filters /// name, so the working set is still valid; leaving it behind would silently drop it. - func renameLastFilters( - from oldTableName: String, - to newTableName: String, - connectionId: UUID, - databaseName: String, - schemaName: String? - ) { - let oldKey = compositeKey( - tableName: oldTableName, connectionId: connectionId, - databaseName: databaseName, schemaName: schemaName - ) - let newKey = compositeKey( - tableName: newTableName, connectionId: connectionId, - databaseName: databaseName, schemaName: schemaName - ) + func renameTable(from oldScope: TableScope, to newScope: TableScope) { + let oldKey = oldScope.storageComponent + let newKey = newScope.storageComponent guard oldKey != newKey else { return } - if let cached = lastFiltersCache.removeValue(forKey: oldKey) { - lastFiltersCache[newKey] = cached + let oldBrowseKey = oldKey + Self.browseKeySuffix + let newBrowseKey = newKey + Self.browseKeySuffix + lastFiltersCache[newKey] = lastFiltersCache.removeValue(forKey: oldKey) + browseSearchCache[newBrowseKey] = browseSearchCache.removeValue(forKey: oldBrowseKey) + + let moves = [(oldKey, newKey), (oldBrowseKey, newBrowseKey)].map { source, destination in + (fileURL(forKey: source), fileURL(forKey: destination)) } - let source = fileURL(forKey: oldKey) - let destination = fileURL(forKey: newKey) ioQueue.async { - guard FileManager.default.fileExists(atPath: source.path) else { return } - try? FileManager.default.removeItem(at: destination) - try? FileManager.default.moveItem(at: source, to: destination) + let fm = FileManager.default + for (source, destination) in moves where fm.fileExists(atPath: source.path) { + try? fm.removeItem(at: destination) + try? fm.moveItem(at: source, to: destination) + } } } /// Moves every table's saved filters from one container to another, by rewriting the part of /// each key that names the container. Keyed by prefix rather than by walking the table list, /// because that list is loaded lazily and a table nobody opened this session still has a file. - func renameScope( + func renameContainer( connectionId: UUID, fromDatabase: String, fromSchema: String?, @@ -303,10 +297,8 @@ final class FilterSettingsStorage { ) guard oldPrefix != newPrefix else { return } - for key in lastFiltersCache.keys where key.hasPrefix(oldPrefix) { - let moved = newPrefix + key.dropFirst(oldPrefix.count) - lastFiltersCache[moved] = lastFiltersCache.removeValue(forKey: key) - } + lastFiltersCache = Self.rekeyed(lastFiltersCache, fromPrefix: oldPrefix, toPrefix: newPrefix) + browseSearchCache = Self.rekeyed(browseSearchCache, fromPrefix: oldPrefix, toPrefix: newPrefix) let directory = filterStateDirectory ioQueue.async { @@ -410,20 +402,13 @@ final class FilterSettingsStorage { connectionId: connectionId, databaseName: databaseName, schemaName: schemaName - ) + ".browse" - } - - func removeFilters(for connectionId: UUID) { - removeFilters(for: [connectionId]) + ) + Self.browseKeySuffix } - func removeFilters(for connectionIds: Set) { + func purgeConnections(_ connectionIds: Set) { guard !connectionIds.isEmpty else { return } - let encodedPrefixes = connectionIds.map { id in - let idString = id.uuidString - return (idString.addingPercentEncoding(withAllowedCharacters: .alphanumerics) ?? idString) + "." - } + let encodedPrefixes = connectionIds.map { TableScope.storagePrefix(connectionId: $0) } let matchesConnection: (String) -> Bool = { name in encodedPrefixes.contains { name.hasPrefix($0) } } @@ -445,6 +430,18 @@ final class FilterSettingsStorage { } } + private static func rekeyed( + _ cache: [String: Value], + fromPrefix oldPrefix: String, + toPrefix newPrefix: String + ) -> [String: Value] { + var rekeyed = cache + for key in cache.keys where key.hasPrefix(oldPrefix) { + rekeyed[newPrefix + key.dropFirst(oldPrefix.count)] = rekeyed.removeValue(forKey: key) + } + return rekeyed + } + private func fileURL(forKey key: String) -> URL { filterStateDirectory.appendingPathComponent("\(key).json") } diff --git a/TablePro/Core/Storage/ForeignKeyLabelColumnStore.swift b/TablePro/Core/Storage/ForeignKeyLabelColumnStore.swift index 90034ea964..3ef31e58d3 100644 --- a/TablePro/Core/Storage/ForeignKeyLabelColumnStore.swift +++ b/TablePro/Core/Storage/ForeignKeyLabelColumnStore.swift @@ -12,9 +12,11 @@ import Foundation /// setting it once for `users` is what a user means by remembering it. Device-local, so this needs /// no CloudKit record type. @MainActor -internal final class ForeignKeyLabelColumnStore { +internal final class ForeignKeyLabelColumnStore: TableScopedSettingsStore { static let shared = ForeignKeyLabelColumnStore() + private static let keyPrefix = PreferenceKeys.foreignKeyLabelColumnPrefix + private let store: KeyValueStore init(defaults: KeyValueStore = AppStorageEnvironment.shared.defaults) { @@ -36,4 +38,32 @@ internal final class ForeignKeyLabelColumnStore { } store.setDataValue(Data(name.utf8), forKey: PreferenceKeys.foreignKeyLabelColumn(scope).name) } + + func renameTable(from oldScope: TableScope, to newScope: TableScope) { + store.moveValue( + fromKey: PreferenceKeys.foreignKeyLabelColumn(oldScope).name, + toKey: PreferenceKeys.foreignKeyLabelColumn(newScope).name + ) + } + + func renameContainer( + connectionId: UUID, + fromDatabase: String, + fromSchema: String?, + toDatabase: String, + toSchema: String? + ) { + store.moveValues( + withPrefix: Self.keyPrefix + + TableScope.storagePrefix(connectionId: connectionId, database: fromDatabase, schema: fromSchema), + toPrefix: Self.keyPrefix + + TableScope.storagePrefix(connectionId: connectionId, database: toDatabase, schema: toSchema) + ) + } + + func purgeConnections(_ connectionIds: Set) { + for connectionId in connectionIds { + store.removeValues(withPrefix: Self.keyPrefix + TableScope.storagePrefix(connectionId: connectionId)) + } + } } diff --git a/TablePro/Core/Storage/HighlightRuleStorage.swift b/TablePro/Core/Storage/HighlightRuleStorage.swift index ae2ba5bad7..363afb9d91 100644 --- a/TablePro/Core/Storage/HighlightRuleStorage.swift +++ b/TablePro/Core/Storage/HighlightRuleStorage.swift @@ -9,7 +9,7 @@ import os @MainActor @Observable -final class HighlightRuleStorage { +final class HighlightRuleStorage: TableScopedSettingsStore { static let shared = HighlightRuleStorage() nonisolated private static let logger = Logger( @@ -53,7 +53,7 @@ final class HighlightRuleStorage { commit(entries, for: scope.connectionId) } - func rename(from oldScope: TableScope, to newScope: TableScope) { + func renameTable(from oldScope: TableScope, to newScope: TableScope) { guard oldScope.storageComponent != newScope.storageComponent else { return } var entries = loadEntries(for: oldScope.connectionId) guard let moving = entries.removeValue(forKey: oldScope.storageComponent) else { return } @@ -61,7 +61,7 @@ final class HighlightRuleStorage { commit(entries, for: oldScope.connectionId) } - func renameScope( + func renameContainer( connectionId: UUID, fromDatabase: String, fromSchema: String?, @@ -81,11 +81,12 @@ final class HighlightRuleStorage { commit(entries, for: connectionId) } - func removeRules(for connectionIds: Set) { + func purgeConnections(_ connectionIds: Set) { guard !connectionIds.isEmpty else { return } for connectionId in connectionIds { cache[connectionId] = [:] removeFile(at: fileURL(for: connectionId)) + removeFile(at: unreadableFileURL(for: connectionId)) } revision &+= 1 } @@ -122,7 +123,7 @@ final class HighlightRuleStorage { Self.logger.error( "Unreadable highlight rules for \(connectionId, privacy: .public): \(error.localizedDescription, privacy: .public)" ) - preserveUnreadableFile(at: url) + preserveUnreadableFile(for: connectionId) cache[connectionId] = [:] return [:] } @@ -139,12 +140,12 @@ final class HighlightRuleStorage { } } - private func preserveUnreadableFile(at url: URL) { - let preserved = url.deletingPathExtension().appendingPathExtension("unreadable.json") + private func preserveUnreadableFile(for connectionId: UUID) { + let preserved = unreadableFileURL(for: connectionId) let fileManager = FileManager.default try? fileManager.removeItem(at: preserved) do { - try fileManager.moveItem(at: url, to: preserved) + try fileManager.moveItem(at: fileURL(for: connectionId), to: preserved) } catch { Self.logger.error("Failed to set aside unreadable highlight rules: \(error.localizedDescription, privacy: .public)") } @@ -159,6 +160,10 @@ final class HighlightRuleStorage { } } + private func unreadableFileURL(for connectionId: UUID) -> URL { + storageDirectory.appendingPathComponent("\(connectionId.uuidString).unreadable.json") + } + private func fileURL(for connectionId: UUID) -> URL { storageDirectory.appendingPathComponent("\(connectionId.uuidString).json") } diff --git a/TablePro/Core/Storage/Preferences/KeyValueStore.swift b/TablePro/Core/Storage/Preferences/KeyValueStore.swift index 3eae1e0000..eae43eea02 100644 --- a/TablePro/Core/Storage/Preferences/KeyValueStore.swift +++ b/TablePro/Core/Storage/Preferences/KeyValueStore.swift @@ -8,6 +8,28 @@ import Foundation protocol KeyValueStore: AnyObject, Sendable { func dataValue(forKey key: String) -> Data? func setDataValue(_ data: Data?, forKey key: String) + func keys(withPrefix prefix: String) -> [String] +} + +internal extension KeyValueStore { + func moveValue(fromKey oldKey: String, toKey newKey: String) { + guard oldKey != newKey, let data = dataValue(forKey: oldKey) else { return } + setDataValue(data, forKey: newKey) + setDataValue(nil, forKey: oldKey) + } + + func moveValues(withPrefix oldPrefix: String, toPrefix newPrefix: String) { + guard oldPrefix != newPrefix else { return } + for key in keys(withPrefix: oldPrefix) { + moveValue(fromKey: key, toKey: newPrefix + key.dropFirst(oldPrefix.count)) + } + } + + func removeValues(withPrefix prefix: String) { + for key in keys(withPrefix: prefix) { + setDataValue(nil, forKey: key) + } + } } extension UserDefaults: KeyValueStore { @@ -22,4 +44,8 @@ extension UserDefaults: KeyValueStore { } set(data, forKey: key) } + + func keys(withPrefix prefix: String) -> [String] { + dictionaryRepresentation().keys.filter { $0.hasPrefix(prefix) } + } } diff --git a/TablePro/Core/Storage/Preferences/PreferenceKeys.swift b/TablePro/Core/Storage/Preferences/PreferenceKeys.swift index c338ce7eae..e5d050ede6 100644 --- a/TablePro/Core/Storage/Preferences/PreferenceKeys.swift +++ b/TablePro/Core/Storage/Preferences/PreferenceKeys.swift @@ -28,8 +28,11 @@ enum PreferenceKeys { lastBackupDirectory.name, ] + static let columnDisplayFormatsPrefix = "com.TablePro.columns.displayFormat." + static let foreignKeyLabelColumnPrefix = "com.TablePro.foreignKey.labelColumn." + static func columnDisplayFormats(_ scope: TableScope) -> DefaultsKey<[String: ValueDisplayFormat]> { - DefaultsKey("com.TablePro.columns.displayFormat." + scope.storageComponent) + DefaultsKey(columnDisplayFormatsPrefix + scope.storageComponent) } static func recentTables(connectionId: UUID) -> DefaultsKey<[RecentTableEntry]> { @@ -37,6 +40,6 @@ enum PreferenceKeys { } static func foreignKeyLabelColumn(_ scope: TableScope) -> DefaultsKey { - DefaultsKey("com.TablePro.foreignKey.labelColumn." + scope.storageComponent) + DefaultsKey(foreignKeyLabelColumnPrefix + scope.storageComponent) } } diff --git a/TablePro/Core/Storage/Preferences/TableScope.swift b/TablePro/Core/Storage/Preferences/TableScope.swift index 6e2560db7e..7b26992ad6 100644 --- a/TablePro/Core/Storage/Preferences/TableScope.swift +++ b/TablePro/Core/Storage/Preferences/TableScope.swift @@ -31,6 +31,10 @@ struct TableScope: Hashable, Codable, Sendable { return encode(parts) + "." } + static func storagePrefix(connectionId: UUID) -> String { + encode([connectionId.uuidString]) + "." + } + private static func encode(_ parts: [String]) -> String { parts .map { $0.addingPercentEncoding(withAllowedCharacters: .alphanumerics) ?? $0 } diff --git a/TablePro/Core/Storage/TableScopedSettingsStore.swift b/TablePro/Core/Storage/TableScopedSettingsStore.swift new file mode 100644 index 0000000000..cf023905c9 --- /dev/null +++ b/TablePro/Core/Storage/TableScopedSettingsStore.swift @@ -0,0 +1,32 @@ +// +// TableScopedSettingsStore.swift +// TablePro +// + +import Foundation + +@MainActor +internal protocol TableScopedSettingsStore: AnyObject { + func renameTable(from oldScope: TableScope, to newScope: TableScope) + func renameContainer( + connectionId: UUID, + fromDatabase: String, + fromSchema: String?, + toDatabase: String, + toSchema: String? + ) + func purgeConnections(_ connectionIds: Set) +} + +@MainActor +internal enum TableScopedSettingsRegistry { + internal static var stores: [any TableScopedSettingsStore] { + [ + FilterSettingsStorage.shared, + FileColumnLayoutPersister.shared, + HighlightRuleStorage.shared, + ValueDisplayFormatStorage.shared, + ForeignKeyLabelColumnStore.shared + ] + } +} diff --git a/TablePro/Core/Storage/ValueDisplayFormatStorage.swift b/TablePro/Core/Storage/ValueDisplayFormatStorage.swift index 0ac34d9b7f..92bc9a742d 100644 --- a/TablePro/Core/Storage/ValueDisplayFormatStorage.swift +++ b/TablePro/Core/Storage/ValueDisplayFormatStorage.swift @@ -6,7 +6,7 @@ import Foundation @MainActor -internal final class ValueDisplayFormatStorage { +internal final class ValueDisplayFormatStorage: TableScopedSettingsStore { static let shared = ValueDisplayFormatStorage() private let store: KeyValueStore @@ -38,6 +38,37 @@ internal final class ValueDisplayFormatStorage { removeLegacy(for: scope) } + func renameTable(from oldScope: TableScope, to newScope: TableScope) { + let oldKey = PreferenceKeys.columnDisplayFormats(oldScope).name + if store.dataValue(forKey: oldKey) == nil { + migrateLegacy(for: oldScope) + } + store.moveValue(fromKey: oldKey, toKey: PreferenceKeys.columnDisplayFormats(newScope).name) + } + + func renameContainer( + connectionId: UUID, + fromDatabase: String, + fromSchema: String?, + toDatabase: String, + toSchema: String? + ) { + store.moveValues( + withPrefix: Self.keyPrefix + + TableScope.storagePrefix(connectionId: connectionId, database: fromDatabase, schema: fromSchema), + toPrefix: Self.keyPrefix + + TableScope.storagePrefix(connectionId: connectionId, database: toDatabase, schema: toSchema) + ) + } + + func purgeConnections(_ connectionIds: Set) { + for connectionId in connectionIds { + store.removeValues(withPrefix: Self.keyPrefix + TableScope.storagePrefix(connectionId: connectionId)) + store.removeValues(withPrefix: Self.legacyKeyPrefix(for: connectionId)) + } + } + + @discardableResult private func migrateLegacy(for scope: TableScope) -> [String: ValueDisplayFormat]? { let legacyKey = Self.legacyKey(for: scope) guard let data = store.dataValue(forKey: legacyKey), @@ -56,7 +87,13 @@ internal final class ValueDisplayFormatStorage { store.setDataValue(nil, forKey: Self.legacyKey(for: scope)) } + private static let keyPrefix = PreferenceKeys.columnDisplayFormatsPrefix + private static func legacyKey(for scope: TableScope) -> String { - "com.TablePro.columns.displayFormat.\(scope.connectionId.uuidString).\(scope.table)" + legacyKeyPrefix(for: scope.connectionId) + scope.table + } + + private static func legacyKeyPrefix(for connectionId: UUID) -> String { + "\(keyPrefix)\(connectionId.uuidString)." } } diff --git a/TablePro/Core/Sync/SyncChangeTracker.swift b/TablePro/Core/Sync/SyncChangeTracker.swift index 7ebf911290..c97d62e915 100644 --- a/TablePro/Core/Sync/SyncChangeTracker.swift +++ b/TablePro/Core/Sync/SyncChangeTracker.swift @@ -61,6 +61,14 @@ final class SyncChangeTracker: Sendable { postChangeNotification() } + func markDeleted(_ type: SyncRecordType, ids: [String]) { + guard !isSuppressed, !ids.isEmpty else { return } + metadataStorage.removeDirty(ids, type: type) + metadataStorage.addTombstones(ids, type: type) + Self.logger.trace("Marked deleted: \(type.rawValue) x\(ids.count)") + postChangeNotification() + } + // MARK: - Query func dirtyRecords(for type: SyncRecordType) -> Set { diff --git a/TablePro/Views/Main/Extensions/MainContentCoordinator+RenameAdoption.swift b/TablePro/Views/Main/Extensions/MainContentCoordinator+RenameAdoption.swift index dd32e6b913..34f5e8d13d 100644 --- a/TablePro/Views/Main/Extensions/MainContentCoordinator+RenameAdoption.swift +++ b/TablePro/Views/Main/Extensions/MainContentCoordinator+RenameAdoption.swift @@ -83,26 +83,12 @@ extension MainContentCoordinator { database: String, schema: String? ) { - FilterSettingsStorage.shared.renameLastFilters( - from: oldName, - to: newName, - connectionId: connectionId, - databaseName: database, - schemaName: schema - ) - FileColumnLayoutPersister.shared.rename( - from: ColumnLayoutTableKey( - connectionId: connectionId, databaseName: database, schemaName: schema, tableName: oldName - ), - to: ColumnLayoutTableKey( - connectionId: connectionId, databaseName: database, schemaName: schema, tableName: newName - ) - ) let scopedDatabase = database.isEmpty ? nil : database - HighlightRuleStorage.shared.rename( - from: TableScope(connectionId: connectionId, database: scopedDatabase, schema: schema, table: oldName), - to: TableScope(connectionId: connectionId, database: scopedDatabase, schema: schema, table: newName) - ) + let oldScope = TableScope(connectionId: connectionId, database: scopedDatabase, schema: schema, table: oldName) + let newScope = TableScope(connectionId: connectionId, database: scopedDatabase, schema: schema, table: newName) + for store in TableScopedSettingsRegistry.stores { + store.renameTable(from: oldScope, to: newScope) + } } private func moveFavorite(_ ref: DatabaseTreeTableRef, to newName: String, database: String?) { @@ -136,18 +122,12 @@ extension MainContentCoordinator { retargetPendingOperations( database: database, schema: schema, toDatabase: toDatabase, toSchema: toSchema ) - FilterSettingsStorage.shared.renameScope( - connectionId: connectionId, fromDatabase: database, fromSchema: schema, - toDatabase: toDatabase, toSchema: toSchema - ) - FileColumnLayoutPersister.shared.renameScope( - connectionId: connectionId, fromDatabase: database, fromSchema: schema, - toDatabase: toDatabase, toSchema: toSchema - ) - HighlightRuleStorage.shared.renameScope( - connectionId: connectionId, fromDatabase: database, fromSchema: schema, - toDatabase: toDatabase, toSchema: toSchema - ) + for store in TableScopedSettingsRegistry.stores { + store.renameContainer( + connectionId: connectionId, fromDatabase: database, fromSchema: schema, + toDatabase: toDatabase, toSchema: toSchema + ) + } retargetFavoriteTables( database: database, schema: schema, toDatabase: toDatabase, toSchema: toSchema ) diff --git a/TableProTests/Core/Storage/ColumnLayoutSyncTests.swift b/TableProTests/Core/Storage/ColumnLayoutSyncTests.swift index f165b45f65..a06b014ad2 100644 --- a/TableProTests/Core/Storage/ColumnLayoutSyncTests.swift +++ b/TableProTests/Core/Storage/ColumnLayoutSyncTests.swift @@ -19,6 +19,21 @@ struct ColumnLayoutSyncTests { return (FileColumnLayoutPersister(storageDirectory: directory, syncTracker: tracker), tracker) } + private func makeTrackedPersister() throws -> (FileColumnLayoutPersister, SyncMetadataStorage, URL) { + let directory = FileManager.default.temporaryDirectory + .appendingPathComponent("cl-sync-\(UUID().uuidString)", isDirectory: true) + let meta = try #require(UserDefaults(suiteName: "cl-sync-meta-\(UUID().uuidString)")) + let metadata = SyncMetadataStorage(userDefaults: meta) + let tracker = SyncChangeTracker(metadataStorage: metadata) + return (FileColumnLayoutPersister(storageDirectory: directory, syncTracker: tracker), metadata, directory) + } + + private func layout(_ widths: [String: CGFloat]) -> ColumnLayoutState { + var state = ColumnLayoutState() + state.columnWidths = widths + return state + } + private func key() -> ColumnLayoutTableKey { ColumnLayoutTableKey(connectionId: UUID(), databaseName: "shop", schemaName: "public", tableName: "orders") } @@ -55,6 +70,68 @@ struct ColumnLayoutSyncTests { #expect(target.load(for: tableKey)?.columnOrder == ["id", "created_at"]) } + @Test("Deleting a connection removes its layout file and tombstones every layout it held") + func purgeConnectionsRemovesFileAndTombstones() throws { + let (persister, metadata, directory) = try makeTrackedPersister() + defer { try? FileManager.default.removeItem(at: directory) } + let connectionId = UUID() + let orders = ColumnLayoutTableKey( + connectionId: connectionId, databaseName: "shop", schemaName: "public", tableName: "orders" + ) + let items = ColumnLayoutTableKey( + connectionId: connectionId, databaseName: "shop", schemaName: "public", tableName: "items" + ) + let kept = ColumnLayoutTableKey( + connectionId: UUID(), databaseName: "shop", schemaName: "public", tableName: "orders" + ) + persister.save(layout(["id": 80]), for: orders) + persister.save(layout(["id": 90]), for: items) + persister.save(layout(["id": 70]), for: kept) + + persister.purgeConnections([connectionId]) + + let file = directory.appendingPathComponent("\(connectionId.uuidString).json") + #expect(!FileManager.default.fileExists(atPath: file.path)) + #expect(persister.load(for: orders) == nil) + #expect(persister.load(for: items) == nil) + #expect(persister.load(for: kept)?.columnWidths == ["id": 70]) + + let tombstones = Set(metadata.tombstones(for: .settings).map(\.id)) + #expect(tombstones == [ + FileColumnLayoutPersister.syncCategory(for: orders.storageKey), + FileColumnLayoutPersister.syncCategory(for: items.storageKey) + ]) + #expect(!metadata.dirtyIds(for: .settings).contains(FileColumnLayoutPersister.syncCategory(for: orders.storageKey))) + } + + @Test("A table rename moves its layout, tombstones the old record and marks the new one dirty") + func renameTableMovesLayoutAndSyncsIt() throws { + let (persister, metadata, directory) = try makeTrackedPersister() + defer { try? FileManager.default.removeItem(at: directory) } + let connectionId = UUID() + let old = TableScope(connectionId: connectionId, database: "shop", schema: "public", table: "orders") + let new = TableScope(connectionId: connectionId, database: "shop", schema: "public", table: "purchases") + let archive = ColumnLayoutTableKey( + connectionId: connectionId, databaseName: "shop", schemaName: "public", tableName: "orders_archive" + ) + let oldKey = ColumnLayoutTableKey( + connectionId: connectionId, databaseName: "shop", schemaName: "public", tableName: "orders" + ) + let newKey = ColumnLayoutTableKey( + connectionId: connectionId, databaseName: "shop", schemaName: "public", tableName: "purchases" + ) + persister.save(layout(["id": 80]), for: oldKey) + persister.save(layout(["id": 60]), for: archive) + + persister.renameTable(from: old, to: new) + + #expect(persister.load(for: oldKey) == nil) + #expect(persister.load(for: newKey)?.columnWidths == ["id": 80]) + #expect(persister.load(for: archive)?.columnWidths == ["id": 60]) + #expect(metadata.tombstones(for: .settings).map(\.id) == [FileColumnLayoutPersister.syncCategory(for: oldKey.storageKey)]) + #expect(metadata.dirtyIds(for: .settings).contains(FileColumnLayoutPersister.syncCategory(for: newKey.storageKey))) + } + @Test("The sync category carries the columnLayout prefix") func categoryPrefix() { #expect(FileColumnLayoutPersister.syncCategory(for: "abc").hasPrefix(FileColumnLayoutPersister.syncCategoryPrefix)) diff --git a/TableProTests/Core/Storage/FilterSettingsStorageTests.swift b/TableProTests/Core/Storage/FilterSettingsStorageTests.swift index 6a0636b9fc..487fb8d20b 100644 --- a/TableProTests/Core/Storage/FilterSettingsStorageTests.swift +++ b/TableProTests/Core/Storage/FilterSettingsStorageTests.swift @@ -131,7 +131,7 @@ struct FilterSettingsStorageTests { keptFilters, for: "users", connectionId: keptConnection, databaseName: "db", schemaName: nil ) - storage.removeFilters(for: deletedConnection) + storage.purgeConnections([deletedConnection]) storage.waitForPendingDiskWrites() #expect( @@ -158,7 +158,7 @@ struct FilterSettingsStorageTests { ) } - storage.removeFilters(for: [first, second]) + storage.purgeConnections([first, second]) storage.waitForPendingDiskWrites() #expect(storage.loadLastFilters(for: "users", connectionId: first, databaseName: "db", schemaName: nil).isEmpty) @@ -184,7 +184,7 @@ struct FilterSettingsStorageTests { for: "users", connectionId: connectionId, databaseName: "db", schemaName: nil ) - storage.removeFilters(for: connectionId) + storage.purgeConnections([connectionId]) storage.waitForPendingDiskWrites() let fresh = FilterSettingsStorage(filterStateDirectory: directory, defaults: defaults) @@ -395,4 +395,84 @@ struct FilterSettingsStorageTests { #expect(state.filters == filters) #expect(state.logicMode == .and) } + + @Test("A table rename moves its filters and browse search and leaves a longer name alone") + func renameTableMovesFiltersAndBrowseSearch() throws { + let defaults = try #require(UserDefaults(suiteName: "FilterSettingsStorageTests-\(UUID().uuidString)")) + let directory = FileManager.default.temporaryDirectory + .appendingPathComponent("FilterSettingsStorageTests-\(UUID().uuidString)", isDirectory: true) + defer { try? FileManager.default.removeItem(at: directory) } + let connectionId = UUID() + let filters = [TestFixtures.makeTableFilter(column: "email", value: "a@b.com")] + let archiveFilters = [TestFixtures.makeTableFilter(column: "id", value: "1")] + let search = BrowseSearchState(pattern: "user:*", typeScope: "hash") + + let storage = FilterSettingsStorage(filterStateDirectory: directory, defaults: defaults) + storage.saveLastFilters(filters, for: "users", connectionId: connectionId, databaseName: "db", schemaName: nil) + storage.saveLastFilters( + archiveFilters, for: "users_archive", connectionId: connectionId, databaseName: "db", schemaName: nil + ) + storage.saveBrowseSearch(search, for: "users", connectionId: connectionId, databaseName: "db", schemaName: nil) + + storage.renameTable( + from: TableScope(connectionId: connectionId, database: "db", schema: nil, table: "users"), + to: TableScope(connectionId: connectionId, database: "db", schema: nil, table: "members") + ) + storage.waitForPendingDiskWrites() + + for reader in [storage, FilterSettingsStorage(filterStateDirectory: directory, defaults: defaults)] { + #expect( + reader.loadLastFilters(for: "members", connectionId: connectionId, databaseName: "db", schemaName: nil) + == filters + ) + #expect( + reader.loadBrowseSearch(for: "members", connectionId: connectionId, databaseName: "db", schemaName: nil) + == search + ) + #expect( + reader.loadLastFilters(for: "users", connectionId: connectionId, databaseName: "db", schemaName: nil) + .isEmpty + ) + #expect( + reader.loadLastFilters( + for: "users_archive", connectionId: connectionId, databaseName: "db", schemaName: nil + ) == archiveFilters + ) + } + } + + @Test("A schema rename moves browse search along with the filters") + func renameContainerMovesBrowseSearch() throws { + let defaults = try #require(UserDefaults(suiteName: "FilterSettingsStorageTests-\(UUID().uuidString)")) + let directory = FileManager.default.temporaryDirectory + .appendingPathComponent("FilterSettingsStorageTests-\(UUID().uuidString)", isDirectory: true) + defer { try? FileManager.default.removeItem(at: directory) } + let connectionId = UUID() + let filters = [TestFixtures.makeTableFilter(column: "email", value: "a@b.com")] + let search = BrowseSearchState(pattern: "user:*", typeScope: "hash") + + let storage = FilterSettingsStorage(filterStateDirectory: directory, defaults: defaults) + storage.saveLastFilters(filters, for: "users", connectionId: connectionId, databaseName: "db", schemaName: "app") + storage.saveBrowseSearch(search, for: "users", connectionId: connectionId, databaseName: "db", schemaName: "app") + + storage.renameContainer( + connectionId: connectionId, fromDatabase: "db", fromSchema: "app", toDatabase: "db", toSchema: "core" + ) + storage.waitForPendingDiskWrites() + + for reader in [storage, FilterSettingsStorage(filterStateDirectory: directory, defaults: defaults)] { + #expect( + reader.loadLastFilters(for: "users", connectionId: connectionId, databaseName: "db", schemaName: "core") + == filters + ) + #expect( + reader.loadBrowseSearch(for: "users", connectionId: connectionId, databaseName: "db", schemaName: "core") + == search + ) + #expect( + !reader.loadBrowseSearch(for: "users", connectionId: connectionId, databaseName: "db", schemaName: "app") + .isActive + ) + } + } } diff --git a/TableProTests/Core/Storage/HighlightRuleStorageTests.swift b/TableProTests/Core/Storage/HighlightRuleStorageTests.swift index f970093cb6..da5be69e6b 100644 --- a/TableProTests/Core/Storage/HighlightRuleStorageTests.swift +++ b/TableProTests/Core/Storage/HighlightRuleStorageTests.swift @@ -55,7 +55,7 @@ struct HighlightRuleStorageTests { let rules = [HighlightRule(columnName: "status", value: "paid")] storage.setRules(rules, for: scope(table: "orders")) - storage.rename(from: scope(table: "orders"), to: scope(table: "purchases")) + storage.renameTable(from: scope(table: "orders"), to: scope(table: "purchases")) let reloaded = HighlightRuleStorage(storageDirectory: directory) #expect(reloaded.rules(for: scope(table: "orders")).isEmpty) @@ -69,7 +69,7 @@ struct HighlightRuleStorageTests { storage.setRules(rules, for: scope(table: "orders")) storage.setRules(rules, for: scope(table: "items")) - storage.renameScope( + storage.renameContainer( connectionId: connectionId, fromDatabase: "shop", fromSchema: "public", toDatabase: "shop", toSchema: "sales" ) @@ -84,12 +84,26 @@ struct HighlightRuleStorageTests { let storage = HighlightRuleStorage(storageDirectory: directory) storage.setRules([HighlightRule(columnName: "status", value: "paid")], for: scope(table: "orders")) - storage.removeRules(for: [connectionId]) + storage.purgeConnections([connectionId]) #expect(storage.rules(for: scope(table: "orders")).isEmpty) #expect(!FileManager.default.fileExists(atPath: fileURL.path)) } + @Test("Deleting a connection removes a set-aside unreadable file too") + func purgeRemovesUnreadableFile() throws { + try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) + try Data("{ not json".utf8).write(to: fileURL) + let storage = HighlightRuleStorage(storageDirectory: directory) + _ = storage.rules(for: scope(table: "orders")) + let preserved = directory.appendingPathComponent("\(connectionId.uuidString).unreadable.json") + #expect(FileManager.default.fileExists(atPath: preserved.path)) + + storage.purgeConnections([connectionId]) + + #expect(!FileManager.default.fileExists(atPath: preserved.path)) + } + @Test("Every change moves the observed revision") func revisionMoves() { let storage = HighlightRuleStorage(storageDirectory: directory) diff --git a/TableProTests/Core/Storage/TableScopedSettingsRegistryTests.swift b/TableProTests/Core/Storage/TableScopedSettingsRegistryTests.swift new file mode 100644 index 0000000000..d190573781 --- /dev/null +++ b/TableProTests/Core/Storage/TableScopedSettingsRegistryTests.swift @@ -0,0 +1,134 @@ +// +// TableScopedSettingsRegistryTests.swift +// TableProTests +// + +import Foundation +@testable import TablePro +import Testing + +@Suite("Table-scoped settings registry") +@MainActor +struct TableScopedSettingsRegistryTests { + @MainActor + private final class RecordingStore: TableScopedSettingsStore { + private(set) var purgedConnectionIds: [Set] = [] + + func renameTable(from oldScope: TableScope, to newScope: TableScope) {} + + func renameContainer( + connectionId: UUID, + fromDatabase: String, + fromSchema: String?, + toDatabase: String, + toSchema: String? + ) {} + + func purgeConnections(_ connectionIds: Set) { + purgedConnectionIds.append(connectionIds) + } + } + + @Test("Deleting a connection purges every table-scoped store once with every id") + func connectionPurgeReachesEveryStore() { + let first = RecordingStore() + let second = RecordingStore() + let deleted: Set = [UUID(), UUID()] + + ConnectionLocalState.purge(connectionIds: deleted, origin: .remote, tableScopedStores: [first, second]) + + #expect(first.purgedConnectionIds == [deleted]) + #expect(second.purgedConnectionIds == [deleted]) + } + + @Test("An empty delete purges nothing") + func emptyPurgeReachesNoStore() { + let store = RecordingStore() + + ConnectionLocalState.purge(connectionIds: [], origin: .remote, tableScopedStores: [store]) + + #expect(store.purgedConnectionIds.isEmpty) + } + + @Test("Every store keyed by a table scope conforms and is registered") + func everyTableScopedStoreIsRegistered() throws { + let root = try Self.repoRoot() + let storageDirectory = root.appendingPathComponent("TablePro/Core/Storage", isDirectory: true) + let registry = try String( + contentsOf: storageDirectory.appendingPathComponent("TableScopedSettingsStore.swift"), + encoding: .utf8 + ) + + let keyUsage = try NSRegularExpression(pattern: #"\b(TableScope|CompositeStorageKey|ColumnLayoutTableKey)\b"#) + let classDeclaration = try NSRegularExpression(pattern: #"\bclass\s+([A-Z]\w*)"#) + var storeTypes: Set = [] + for text in try Self.swiftSources(under: storageDirectory) where Self.matches(keyUsage, in: text) { + storeTypes.formUnion(Self.captures(classDeclaration, in: text)) + } + + let conformance = try NSRegularExpression( + pattern: #"\b(?:class|extension)\s+([A-Z]\w*)\s*:[^{]*\bTableScopedSettingsStore\b"# + ) + var conformingTypes: Set = [] + for text in try Self.swiftSources(under: root.appendingPathComponent("TablePro", isDirectory: true)) { + conformingTypes.formUnion(Self.captures(conformance, in: text)) + } + + #expect(storeTypes.isSuperset(of: [ + "FilterSettingsStorage", + "FileColumnLayoutPersister", + "HighlightRuleStorage", + "ValueDisplayFormatStorage", + "ForeignKeyLabelColumnStore" + ])) + let unconformed = storeTypes.subtracting(conformingTypes) + #expect( + unconformed.isEmpty, + "A store keyed by table scope must conform to TableScopedSettingsStore: \(unconformed.sorted())" + ) + let unregistered = storeTypes.filter { !registry.contains("\($0).shared") } + #expect( + unregistered.isEmpty, + "A table-scoped store must be listed in TableScopedSettingsRegistry.stores: \(unregistered.sorted())" + ) + } + + private static func matches(_ regex: NSRegularExpression, in text: String) -> Bool { + regex.firstMatch(in: text, range: NSRange(text.startIndex..., in: text)) != nil + } + + private static func captures(_ regex: NSRegularExpression, in text: String) -> Set { + let matches = regex.matches(in: text, range: NSRange(text.startIndex..., in: text)) + return Set(matches.compactMap { match in + Range(match.range(at: 1), in: text).map { String(text[$0]) } + }) + } + + private static func swiftSources(under directory: URL) throws -> [String] { + guard let enumerator = FileManager.default.enumerator( + at: directory, + includingPropertiesForKeys: [.isRegularFileKey] + ) else { return [] } + + var sources: [String] = [] + for case let url as URL in enumerator where url.pathExtension == "swift" { + sources.append(try String(contentsOf: url, encoding: .utf8)) + } + return sources + } + + private static func repoRoot() throws -> URL { + var directory = URL(fileURLWithPath: #filePath).deletingLastPathComponent() + for _ in 0 ..< 12 { + if FileManager.default.fileExists(atPath: directory.appendingPathComponent("TablePro.xcodeproj").path) { + return directory + } + directory = directory.deletingLastPathComponent() + } + throw GuardError.repoRootNotFound + } + + private enum GuardError: Error { + case repoRootNotFound + } +} diff --git a/TableProTests/Core/Storage/ValueDisplayFormatStorageTests.swift b/TableProTests/Core/Storage/ValueDisplayFormatStorageTests.swift index 7f4e0508d3..6be6b73ed8 100644 --- a/TableProTests/Core/Storage/ValueDisplayFormatStorageTests.swift +++ b/TableProTests/Core/Storage/ValueDisplayFormatStorageTests.swift @@ -87,4 +87,100 @@ struct ValueDisplayFormatStorageTests { #expect(defaults.data(forKey: legacyKey) == nil) #expect(defaults.data(forKey: PreferenceKeys.columnDisplayFormats(target).name) != nil) } + + @Test("A table rename moves its formats and leaves a longer name alone") + func renameTableMovesOnlyThatTable() throws { + let (storage, _) = try makeStorage() + let conn = UUID() + let other = UUID() + storage.save(["id": .uuid], for: scope("public", connectionId: conn)) + storage.save(["ref": .json], for: scope("public", connectionId: conn, table: "orders_archive")) + storage.save(["id": .json], for: scope("public", connectionId: other)) + + storage.renameTable( + from: scope("public", connectionId: conn), + to: scope("public", connectionId: conn, table: "purchases") + ) + + #expect(storage.load(for: scope("public", connectionId: conn)) == nil) + #expect(storage.load(for: scope("public", connectionId: conn, table: "purchases")) == ["id": .uuid]) + #expect(storage.load(for: scope("public", connectionId: conn, table: "orders_archive")) == ["ref": .json]) + #expect(storage.load(for: scope("public", connectionId: other)) == ["id": .json]) + } + + @Test("A table rename carries formats still stored under the legacy key") + func renameTableMigratesLegacy() throws { + let (storage, defaults) = try makeStorage() + let conn = UUID() + let legacyKey = "com.TablePro.columns.displayFormat.\(conn.uuidString).orders" + defaults.set(try JSONEncoder().encode(["id": ValueDisplayFormat.uuid]), forKey: legacyKey) + + storage.renameTable( + from: scope("public", connectionId: conn), + to: scope("public", connectionId: conn, table: "purchases") + ) + + #expect(defaults.data(forKey: legacyKey) == nil) + #expect(storage.load(for: scope("public", connectionId: conn, table: "purchases")) == ["id": .uuid]) + #expect(storage.load(for: scope("public", connectionId: conn)) == nil) + } + + @Test("A schema rename moves every table in it and nothing outside it") + func renameContainerMovesTheSchema() throws { + let (storage, _) = try makeStorage() + let conn = UUID() + let other = UUID() + storage.save(["id": .uuid], for: scope("public", connectionId: conn)) + storage.save(["ref": .json], for: scope("public", connectionId: conn, table: "items")) + storage.save(["id": .json], for: scope("public_old", connectionId: conn)) + storage.save(["id": .uuid], for: scope("public", connectionId: other)) + + storage.renameContainer( + connectionId: conn, fromDatabase: "shop", fromSchema: "public", toDatabase: "shop", toSchema: "sales" + ) + + #expect(storage.load(for: scope("sales", connectionId: conn)) == ["id": .uuid]) + #expect(storage.load(for: scope("sales", connectionId: conn, table: "items")) == ["ref": .json]) + #expect(storage.load(for: scope("public", connectionId: conn)) == nil) + #expect(storage.load(for: scope("public_old", connectionId: conn)) == ["id": .json]) + #expect(storage.load(for: scope("public", connectionId: other)) == ["id": .uuid]) + } + + @Test("A database rename moves every schema in it") + func renameDatabaseMovesEverySchema() throws { + let (storage, _) = try makeStorage() + let conn = UUID() + storage.save(["id": .uuid], for: scope("public", connectionId: conn)) + storage.save(["id": .json], for: scope("archive", connectionId: conn)) + let longerName = TableScope(connectionId: conn, database: "shopping", schema: "public", table: "orders") + storage.save(["id": .text], for: longerName) + + storage.renameContainer( + connectionId: conn, fromDatabase: "shop", fromSchema: nil, toDatabase: "store", toSchema: nil + ) + + let moved = TableScope(connectionId: conn, database: "store", schema: "public", table: "orders") + let movedArchive = TableScope(connectionId: conn, database: "store", schema: "archive", table: "orders") + #expect(storage.load(for: moved) == ["id": .uuid]) + #expect(storage.load(for: movedArchive) == ["id": .json]) + #expect(storage.load(for: longerName) == ["id": .text]) + #expect(storage.load(for: scope("public", connectionId: conn)) == nil) + } + + @Test("Deleting a connection removes its formats, legacy keys included, and keeps the rest") + func purgeConnectionsRemovesOnlyThatConnection() throws { + let (storage, defaults) = try makeStorage() + let conn = UUID() + let other = UUID() + let legacyKey = "com.TablePro.columns.displayFormat.\(conn.uuidString).customers" + defaults.set(try JSONEncoder().encode(["id": ValueDisplayFormat.uuid]), forKey: legacyKey) + storage.save(["id": .uuid], for: scope("public", connectionId: conn)) + storage.save(["id": .json], for: scope("public", connectionId: other)) + + storage.purgeConnections([conn]) + + #expect(defaults.data(forKey: PreferenceKeys.columnDisplayFormats(scope("public", connectionId: conn)).name) == nil) + #expect(defaults.data(forKey: legacyKey) == nil) + #expect(storage.load(for: scope("public", connectionId: other)) == ["id": .json]) + } } diff --git a/TableProTests/Core/Sync/SyncChangeTrackerTests.swift b/TableProTests/Core/Sync/SyncChangeTrackerTests.swift index 749b5e412e..660b6829cb 100644 --- a/TableProTests/Core/Sync/SyncChangeTrackerTests.swift +++ b/TableProTests/Core/Sync/SyncChangeTrackerTests.swift @@ -4,8 +4,8 @@ // import Foundation -import Testing import TableProSyncTransport +import Testing @testable import TablePro @@ -15,9 +15,9 @@ struct SyncChangeTrackerTests { private let metadata: SyncMetadataStorage private let tracker: SyncChangeTracker - init() { + init() throws { let unique = UUID().uuidString - let syncDefaults = UserDefaults(suiteName: "com.TablePro.tests.SyncChangeTracker.\(unique)")! + let syncDefaults = try #require(UserDefaults(suiteName: "com.TablePro.tests.SyncChangeTracker.\(unique)")) metadata = SyncMetadataStorage(userDefaults: syncDefaults) tracker = SyncChangeTracker(metadataStorage: metadata) } @@ -49,6 +49,34 @@ struct SyncChangeTrackerTests { #expect(metadata.tombstones(for: .connection).contains { $0.id == "conn-1" }) } + @Test("markDeleted with multiple ids clears each dirty flag and tombstones each id once") + func markDeletedMultiple() { + tracker.markDirty(.settings, ids: ["a", "b", "kept"]) + tracker.markDeleted(.settings, ids: ["a", "b"]) + + #expect(tracker.dirtyRecords(for: .settings) == ["kept"]) + #expect(metadata.tombstones(for: .settings).map(\.id).sorted() == ["a", "b"]) + } + + @Test("markDeleted with an empty id list records nothing") + func markDeletedEmptyIsNoop() { + tracker.markDirty(.settings, id: "kept") + tracker.markDeleted(.settings, ids: []) + + #expect(tracker.dirtyRecords(for: .settings) == ["kept"]) + #expect(metadata.tombstones(for: .settings).isEmpty) + } + + @Test("Suppression makes a batch markDeleted a no-op") + func suppressionDisablesBatchDelete() { + tracker.markDirty(.settings, id: "a") + tracker.isSuppressed = true + tracker.markDeleted(.settings, ids: ["a"]) + + #expect(tracker.dirtyRecords(for: .settings) == ["a"]) + #expect(metadata.tombstones(for: .settings).isEmpty) + } + @Test("Suppression makes markDirty and markDeleted no-ops") func suppressionDisablesTracking() { tracker.isSuppressed = true diff --git a/TableProTests/Storage/ForeignKeyLabelColumnStoreTests.swift b/TableProTests/Storage/ForeignKeyLabelColumnStoreTests.swift index 7d4fedbd6f..144260d66f 100644 --- a/TableProTests/Storage/ForeignKeyLabelColumnStoreTests.swift +++ b/TableProTests/Storage/ForeignKeyLabelColumnStoreTests.swift @@ -76,4 +76,79 @@ struct ForeignKeyLabelColumnStoreTests { #expect(store.labelColumn(for: target) == "full name") #expect(store.labelColumn(for: scope(connectionId: target.connectionId)) == nil) } + + @Test("A table rename moves its choice and leaves a longer name alone") + func renameTableMovesOnlyThatTable() throws { + let store = try makeStore() + let connection = UUID() + let other = UUID() + store.setLabelColumn("Name", for: scope(connectionId: connection)) + store.setLabelColumn("Title", for: scope(connectionId: connection, table: "Artist_archive")) + store.setLabelColumn("Code", for: scope(connectionId: other)) + + store.renameTable( + from: scope(connectionId: connection), + to: scope(connectionId: connection, table: "Performer") + ) + + #expect(store.labelColumn(for: scope(connectionId: connection)) == nil) + #expect(store.labelColumn(for: scope(connectionId: connection, table: "Performer")) == "Name") + #expect(store.labelColumn(for: scope(connectionId: connection, table: "Artist_archive")) == "Title") + #expect(store.labelColumn(for: scope(connectionId: other)) == "Code") + } + + @Test("A schema rename moves every table in it and nothing outside it") + func renameContainerMovesTheSchema() throws { + let store = try makeStore() + let connection = UUID() + let other = UUID() + store.setLabelColumn("Name", for: scope(connectionId: connection, schema: "music")) + store.setLabelColumn("Title", for: scope(connectionId: connection, schema: "music", table: "Album")) + store.setLabelColumn("Code", for: scope(connectionId: connection, schema: "music_old")) + store.setLabelColumn("Email", for: scope(connectionId: other, schema: "music")) + + store.renameContainer( + connectionId: connection, fromDatabase: "chinook", fromSchema: "music", + toDatabase: "chinook", toSchema: "catalog" + ) + + #expect(store.labelColumn(for: scope(connectionId: connection, schema: "catalog")) == "Name") + #expect(store.labelColumn(for: scope(connectionId: connection, schema: "catalog", table: "Album")) == "Title") + #expect(store.labelColumn(for: scope(connectionId: connection, schema: "music")) == nil) + #expect(store.labelColumn(for: scope(connectionId: connection, schema: "music_old")) == "Code") + #expect(store.labelColumn(for: scope(connectionId: other, schema: "music")) == "Email") + } + + @Test("A database rename moves its tables and leaves a longer database name alone") + func renameDatabaseMovesItsTables() throws { + let store = try makeStore() + let connection = UUID() + store.setLabelColumn("Name", for: scope(connectionId: connection)) + store.setLabelColumn("Title", for: scope(connectionId: connection, database: "chinook_backup")) + + store.renameContainer( + connectionId: connection, fromDatabase: "chinook", fromSchema: nil, + toDatabase: "music", toSchema: nil + ) + + #expect(store.labelColumn(for: scope(connectionId: connection, database: "music")) == "Name") + #expect(store.labelColumn(for: scope(connectionId: connection)) == nil) + #expect(store.labelColumn(for: scope(connectionId: connection, database: "chinook_backup")) == "Title") + } + + @Test("Deleting a connection removes its choices and keeps every other connection's") + func purgeConnectionsRemovesOnlyThatConnection() throws { + let store = try makeStore() + let connection = UUID() + let other = UUID() + store.setLabelColumn("Name", for: scope(connectionId: connection)) + store.setLabelColumn("Title", for: scope(connectionId: connection, table: "Album")) + store.setLabelColumn("Code", for: scope(connectionId: other)) + + store.purgeConnections([connection]) + + #expect(store.labelColumn(for: scope(connectionId: connection)) == nil) + #expect(store.labelColumn(for: scope(connectionId: connection, table: "Album")) == nil) + #expect(store.labelColumn(for: scope(connectionId: other)) == "Code") + } } From 5ebe4a86b7be8468c8a0af7d4f505818ff2a384e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 00:09:44 +0700 Subject: [PATCH 13/54] fix(plugin-postgresql): read column comments for every relation kind (#2748) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Claude-Session: https://claude.ai/code/session_01X1ejXbmyPqUziRWVxJ5cu8 Signed-off-by: Ngô Quốc Đạt --- CHANGELOG.md | 2 + .../ColumnQueryShape.swift | 15 +++++ .../PostgreSQLPluginDriver+Columns.swift | 27 +------- .../PostgreSQLSchemaQueries.swift | 40 ++++++------ .../RedshiftSchemaQueries.swift | 10 +-- .../Plugins/PostgreSQLColumnQueryTests.swift | 62 +++++++++++++------ 6 files changed, 82 insertions(+), 74 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6d31e1ad0..5d91da9228 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -138,6 +138,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Line and paragraph separators (U+2028, U+2029) shown as line breaks the database does not see. (#2717) - Stop on Cloudflare D1, libSQL and Trino cancelling a sidebar read instead of the running query. - Numeric-looking filter values sent unquoted to text columns when a table first opens or after a foreign key jump. +- Missing column comments on PostgreSQL views, partitioned tables and foreign tables, and missing identity and generated flags on partitioned and foreign tables. +- Wrong primary key columns when another table reuses the key's constraint name on PostgreSQL and Redshift. - Restore reported as failed after a complete restore into a PostgreSQL server older than `pg_restore`. - Garbled non-Latin text saved to MySQL and MariaDB servers that force a Latin 1 session. (#2725) - Garbled non-Latin text when restoring a MySQL or MariaDB SQL export through a Latin 1 client. (#2725) diff --git a/Plugins/PostgreSQLDriverPlugin/ColumnQueryShape.swift b/Plugins/PostgreSQLDriverPlugin/ColumnQueryShape.swift index b0d7f4349c..e7156ebdb9 100644 --- a/Plugins/PostgreSQLDriverPlugin/ColumnQueryShape.swift +++ b/Plugins/PostgreSQLDriverPlugin/ColumnQueryShape.swift @@ -36,4 +36,19 @@ enum ColumnQueryShape { orderBy: includesTableName ? "c.table_name, c.ordinal_position" : "c.ordinal_position" ) } + + static func primaryKeyJoin(schemaLiteral: String, fragments: Fragments) -> String { + """ + LEFT JOIN ( + SELECT DISTINCT \(fragments.pkSelect) + FROM information_schema.table_constraints tc + JOIN information_schema.key_column_usage kcu + ON tc.constraint_name = kcu.constraint_name + AND tc.table_schema = kcu.table_schema + AND tc.table_name = kcu.table_name + WHERE tc.constraint_type = 'PRIMARY KEY' + AND tc.table_schema = '\(schemaLiteral)'\(fragments.pkTableFilter) + ) pk ON \(fragments.pkJoin) + """ + } } diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift index bd1e87d7b1..11ace592c8 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift @@ -11,14 +11,10 @@ extension PostgreSQLPluginDriver { let safeSchema = escapeStringLiteral(schema ?? core.currentSchema) let safeTable = escapeStringLiteral(table) let catalog = try await fetchTypeCatalog() - let projections = columnProjections() let query = PostgreSQLSchemaQueries.columnsQuery( schemaLiteral: safeSchema, tableLiteral: safeTable, - identityProjection: projections.identity, - generatedProjection: projections.generated, - generationExpressionProjection: projections.generationExpression, - attributeJoin: projections.attributeJoin + capabilities: versionedCapabilities ) let result = try await execute(query: query) return result.rows.compactMap { row in @@ -29,14 +25,10 @@ extension PostgreSQLPluginDriver { func fetchAllColumns(schema: String?) async throws -> [String: [PluginColumnInfo]] { let safeSchema = escapeStringLiteral(schema ?? core.currentSchema) let catalog = try await fetchTypeCatalog() - let projections = columnProjections() let query = PostgreSQLSchemaQueries.columnsQuery( schemaLiteral: safeSchema, tableLiteral: nil, - identityProjection: projections.identity, - generatedProjection: projections.generated, - generationExpressionProjection: projections.generationExpression, - attributeJoin: projections.attributeJoin + capabilities: versionedCapabilities ) let result = try await execute(query: query) var allColumns: [String: [PluginColumnInfo]] = [:] @@ -72,21 +64,6 @@ extension PostgreSQLPluginDriver { } } - private func columnProjections() - -> (identity: String, generated: String, generationExpression: String, attributeJoin: String) { - let caps = versionedCapabilities - let identity = caps.hasIdentityColumns ? "a.attidentity" : "NULL::text" - let generated = caps.hasGeneratedColumns ? "a.attgenerated" : "NULL::text" - let attributeJoin = (caps.hasIdentityColumns || caps.hasGeneratedColumns) ? """ - LEFT JOIN pg_catalog.pg_attribute a - ON a.attrelid = st.relid - AND a.attname = c.column_name - AND NOT a.attisdropped - """ : "" - let generationExpression = caps.hasGeneratedColumns ? "c.generation_expression" : "NULL::text" - return (identity, generated, generationExpression, attributeJoin) - } - fileprivate func fetchEnumLabelMap() async throws -> [String: [String]] { let result = try await execute(query: PostgreSQLSchemaQueries.enumLabelQuery) var map: [String: [String]] = [:] diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLSchemaQueries.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLSchemaQueries.swift index c82fc65d5e..15bb6e2bcb 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLSchemaQueries.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLSchemaQueries.swift @@ -249,12 +249,20 @@ enum PostgreSQLSchemaQueries { static func columnsQuery( schemaLiteral: String, tableLiteral: String?, - identityProjection: String, - generatedProjection: String, - generationExpressionProjection: String, - attributeJoin: String + capabilities: PostgreSQLCapabilities ) -> String { let shape = ColumnQueryShape.fragments(tableLiteral: tableLiteral) + let identityProjection = capabilities.hasIdentityColumns ? "a.attidentity" : "NULL::text" + let generatedProjection = capabilities.hasGeneratedColumns ? "a.attgenerated" : "NULL::text" + let generationExpressionProjection = capabilities.hasGeneratedColumns + ? "c.generation_expression" + : "NULL::text" + let attributeJoin = (capabilities.hasIdentityColumns || capabilities.hasGeneratedColumns) ? """ + + LEFT JOIN pg_catalog.pg_attribute a + ON a.attrelid = rel.oid + AND a.attnum = c.ordinal_position + """ : "" return """ SELECT \(shape.selectPrefix)c.column_name, @@ -262,7 +270,7 @@ enum PostgreSQLSchemaQueries { c.is_nullable, c.column_default, c.collation_name, - pgd.description, + pg_catalog.col_description(rel.oid, c.ordinal_position), c.udt_name, CASE WHEN pk.column_name IS NOT NULL THEN 'YES' ELSE 'NO' END AS is_pk, \(identityProjection), @@ -270,22 +278,12 @@ enum PostgreSQLSchemaQueries { c.udt_schema, \(generationExpressionProjection) FROM information_schema.columns c - LEFT JOIN pg_catalog.pg_statio_all_tables st - ON st.schemaname = c.table_schema - AND st.relname = c.table_name - LEFT JOIN pg_catalog.pg_description pgd - ON pgd.objoid = st.relid - AND pgd.objsubid = c.ordinal_position - \(attributeJoin) - LEFT JOIN ( - SELECT DISTINCT \(shape.pkSelect) - FROM information_schema.table_constraints tc - JOIN information_schema.key_column_usage kcu - ON tc.constraint_name = kcu.constraint_name - AND tc.table_schema = kcu.table_schema - WHERE tc.constraint_type = 'PRIMARY KEY' - AND tc.table_schema = '\(schemaLiteral)'\(shape.pkTableFilter) - ) pk ON \(shape.pkJoin) + LEFT JOIN pg_catalog.pg_namespace relns + ON relns.nspname = c.table_schema + LEFT JOIN pg_catalog.pg_class rel + ON rel.relnamespace = relns.oid + AND rel.relname = c.table_name\(attributeJoin) + \(ColumnQueryShape.primaryKeyJoin(schemaLiteral: schemaLiteral, fragments: shape)) WHERE c.table_schema = '\(schemaLiteral)'\(shape.mainTableFilter) ORDER BY \(shape.orderBy) """ diff --git a/Plugins/PostgreSQLDriverPlugin/RedshiftSchemaQueries.swift b/Plugins/PostgreSQLDriverPlugin/RedshiftSchemaQueries.swift index 29d6cf52f9..98b9b6190c 100644 --- a/Plugins/PostgreSQLDriverPlugin/RedshiftSchemaQueries.swift +++ b/Plugins/PostgreSQLDriverPlugin/RedshiftSchemaQueries.swift @@ -34,15 +34,7 @@ enum RedshiftSchemaQueries { LEFT JOIN pg_catalog.pg_description pgd ON pgd.objoid = cls.oid AND pgd.objsubid = c.ordinal_position - LEFT JOIN ( - SELECT DISTINCT \(shape.pkSelect) - FROM information_schema.table_constraints tc - JOIN information_schema.key_column_usage kcu - ON tc.constraint_name = kcu.constraint_name - AND tc.table_schema = kcu.table_schema - WHERE tc.constraint_type = 'PRIMARY KEY' - AND tc.table_schema = '\(schemaLiteral)'\(shape.pkTableFilter) - ) pk ON \(shape.pkJoin) + \(ColumnQueryShape.primaryKeyJoin(schemaLiteral: schemaLiteral, fragments: shape)) WHERE c.table_schema = '\(schemaLiteral)'\(shape.mainTableFilter) ORDER BY \(shape.orderBy) """ diff --git a/TableProTests/Plugins/PostgreSQLColumnQueryTests.swift b/TableProTests/Plugins/PostgreSQLColumnQueryTests.swift index f489466645..f21e85ffe3 100644 --- a/TableProTests/Plugins/PostgreSQLColumnQueryTests.swift +++ b/TableProTests/Plugins/PostgreSQLColumnQueryTests.swift @@ -15,26 +15,15 @@ import Testing @Suite("PostgreSQLSchemaQueries.columnsQuery") struct PostgreSQLColumnsQueryTests { + private let modern = PostgreSQLCapabilities(serverVersion: 170_000) + private let legacy = PostgreSQLCapabilities(serverVersion: 90_100) + private func singleTable(schema: String, table: String) -> String { - PostgreSQLSchemaQueries.columnsQuery( - schemaLiteral: schema, - tableLiteral: table, - identityProjection: "a.attidentity", - generatedProjection: "a.attgenerated", - generationExpressionProjection: "c.generation_expression", - attributeJoin: "LEFT JOIN pg_catalog.pg_attribute a ON a.attrelid = st.relid" - ) + PostgreSQLSchemaQueries.columnsQuery(schemaLiteral: schema, tableLiteral: table, capabilities: modern) } private func allTables(schema: String) -> String { - PostgreSQLSchemaQueries.columnsQuery( - schemaLiteral: schema, - tableLiteral: nil, - identityProjection: "NULL::text", - generatedProjection: "NULL::text", - generationExpressionProjection: "NULL::text", - attributeJoin: "" - ) + PostgreSQLSchemaQueries.columnsQuery(schemaLiteral: schema, tableLiteral: nil, capabilities: legacy) } @Test("single-table query filters on the requested schema and table") @@ -74,12 +63,39 @@ struct PostgreSQLColumnsQueryTests { #expect(query.contains("pk ON c.table_name = pk.table_name AND c.column_name = pk.column_name")) } - @Test("version-dependent projections are interpolated verbatim") - func projectionsInterpolated() { + @Test("identity and generated flags are read from pg_attribute by attribute number on 10 and later") + func modernServerReadsAttributes() { let query = singleTable(schema: "s2", table: "orders") #expect(query.contains("a.attidentity")) #expect(query.contains("a.attgenerated")) - #expect(query.contains("LEFT JOIN pg_catalog.pg_attribute a ON a.attrelid = st.relid")) + #expect(query.contains("c.generation_expression")) + #expect(query.contains("ON a.attrelid = rel.oid")) + #expect(query.contains("AND a.attnum = c.ordinal_position")) + } + + @Test("a server without identity or generated columns never names pg_attribute") + func legacyServerSkipsAttributes() { + let query = allTables(schema: "s2") + #expect(!query.contains("pg_attribute")) + #expect(!query.contains("a.attidentity")) + #expect(!query.contains("a.attgenerated")) + #expect(!query.contains("c.generation_expression")) + } + + @Test("column comments are read through the relation's pg_class oid, not a statistics view") + func commentsKeyOnRelationOid() { + for query in [singleTable(schema: "s2", table: "orders"), allTables(schema: "s2")] { + #expect(!query.contains("pg_statio_all_tables")) + #expect(query.contains("ON rel.relnamespace = relns.oid")) + #expect(query.contains("pg_catalog.col_description(rel.oid, c.ordinal_position)")) + } + } + + @Test("primary key columns are matched to the constraint's own table") + func primaryKeyJoinIsTableScoped() { + for query in [singleTable(schema: "s2", table: "orders"), allTables(schema: "s2")] { + #expect(query.contains("AND tc.table_name = kcu.table_name")) + } } } @@ -110,4 +126,12 @@ struct RedshiftColumnsQueryTests { #expect(query.contains("ORDER BY c.table_name, c.ordinal_position")) #expect(query.contains("pk ON c.table_name = pk.table_name AND c.column_name = pk.column_name")) } + + @Test("primary key columns are matched to the constraint's own table") + func primaryKeyJoinIsTableScoped() { + for table in ["orders", nil] { + let query = RedshiftSchemaQueries.columnsQuery(schemaLiteral: "s2", tableLiteral: table) + #expect(query.contains("AND tc.table_name = kcu.table_name")) + } + } } From 3bb83f1a83344df64bfdf44e60a3cb71ab25d05f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 00:50:21 +0700 Subject: [PATCH 14/54] fix(plugins): decode every SQL import chunk in the file's own encoding and byte order (#2750) --- CHANGELOG.md | 3 + .../Core/Utilities/SQL/SQLChunkDecoder.swift | 154 ++++++++++++++++++ .../Core/Utilities/SQL/SQLFileParser.swift | 36 +--- TablePro/Models/Export/ImportModels.swift | 38 ++++- TablePro/Views/Import/ImportDialog.swift | 7 +- .../Utilities/SQL/SQLChunkDecoderTests.swift | 112 +++++++++++++ .../Utilities/SQL/SQLFileParserTests.swift | 42 +++++ docs/features/import-export.mdx | 4 +- 8 files changed, 352 insertions(+), 44 deletions(-) create mode 100644 TablePro/Core/Utilities/SQL/SQLChunkDecoder.swift create mode 100644 TableProTests/Core/Utilities/SQL/SQLChunkDecoderTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d91da9228..e661eb8a33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Warnings in the SQL editor for full-width punctuation, curly quotes and non-ASCII spaces. (#2717) - Highlight rules that color data grid rows or cells by value. (#2723) - **Encoding** option for MySQL and MariaDB connections, with **UTF-8 via Latin 1** for databases written through a Latin 1 client. (#2725) +- UTF-16 LE, UTF-16 BE and Windows-1252 in the SQL import encoding menu. ### Changed @@ -43,6 +44,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Data grid ignoring the theme's background, text, alternate row, NULL, boolean and row number colors. +- Text past the first 64 KB of a UTF-16 SQL import arriving byte-swapped. +- SQL import failing on a file whose encoding is not UTF-8 when a character lands on a 64 KB boundary. - Garbled non-Latin text saved from iPhone and iPad to MySQL servers that force a Latin 1 session. (#2725) - **Encoding** ignored on iPhone and iPad by a MySQL connection synced from the Mac. (#2725) - Binary MySQL columns shown as text on iPhone and iPad, and searched with `LIKE`. diff --git a/TablePro/Core/Utilities/SQL/SQLChunkDecoder.swift b/TablePro/Core/Utilities/SQL/SQLChunkDecoder.swift new file mode 100644 index 0000000000..672d0c8995 --- /dev/null +++ b/TablePro/Core/Utilities/SQL/SQLChunkDecoder.swift @@ -0,0 +1,154 @@ +// +// SQLChunkDecoder.swift +// TablePro +// + +import Foundation + +/// Turns a file's bytes into text one chunk at a time, holding back whatever runs off the end of +/// a chunk until the next one arrives. +/// +/// `String(data:encoding:)` is the whole of Foundation's decoding API and it has no way to report +/// a partial character, so three measured behaviours have to be worked around rather than caught. +/// +/// A chunk of UTF-16 carrying no byte order mark decodes as big-endian. The mark is at the start +/// of the file, so only the first chunk has one, and every chunk after it in a little-endian file +/// came back byte-swapped: a UTF-16 dump over 64 KiB imported as CJK from its first chunk +/// boundary on, with nothing raised. The byte order is therefore settled once, from the mark, and +/// every chunk after that is decoded with the explicit variant. Stripping the mark becomes this +/// type's job at the same time, because only the `.utf16` spelling consumes one. +/// +/// A chunk holding an odd number of UTF-16 bytes decodes the even part and drops the last byte +/// without failing, so the alignment is held back here rather than left for the decoder to +/// notice. +/// +/// A UTF-16 surrogate pair split across a boundary fails the whole chunk, as does a partial UTF-8 +/// sequence, so a chunk that will not decode gives its last few bytes back to the next one. How +/// many is derived from the encoding rather than assumed: only UTF-8 was handled before, so a +/// character split across a boundary in any other multi-byte encoding failed the import outright. +struct SQLChunkDecoder { + private let declaredEncoding: String.Encoding + private var resolvedEncoding: String.Encoding? + private var unitSize = 1 + private var maximumTrim = 0 + private var pendingTail = Data() + + var hasPendingBytes: Bool { !pendingTail.isEmpty } + + init(encoding: String.Encoding) { + declaredEncoding = encoding + } + + mutating func decode(_ rawData: Data) -> String? { + var data = pendingTail + data.append(rawData) + pendingTail.removeAll(keepingCapacity: true) + + let encoding = resolveIfNeeded(startingWith: &data) + + var carried = Data() + let misalignment = data.count % unitSize + if misalignment > 0 { + carried = Data(data.suffix(misalignment)) + data = Data(data.prefix(data.count - misalignment)) + } + + if let decoded = String(data: data, encoding: encoding) { + pendingTail = carried + return decoded + } + + var trim = unitSize + while trim <= maximumTrim && data.count >= trim { + let head = Data(data.prefix(data.count - trim)) + if head.isEmpty { + pendingTail = data + carried + return "" + } + if let decoded = String(data: head, encoding: encoding) { + pendingTail = Data(data.suffix(trim)) + carried + return decoded + } + trim += unitSize + } + return nil + } + + private mutating func resolveIfNeeded(startingWith data: inout Data) -> String.Encoding { + if let resolvedEncoding { return resolvedEncoding } + + let resolution = Self.resolve(declaredEncoding, startingWith: data) + resolvedEncoding = resolution.encoding + unitSize = Self.unitSize(of: resolution.encoding) + maximumTrim = Self.maximumTrim(of: resolution.encoding, unitSize: unitSize) + if resolution.byteOrderMarkLength > 0, data.count >= resolution.byteOrderMarkLength { + data = Data(data.dropFirst(resolution.byteOrderMarkLength)) + } + return resolution.encoding + } + + private struct Resolution { + let encoding: String.Encoding + let byteOrderMarkLength: Int + } + + private static let utf16LittleEndianMark: [UInt8] = [0xFF, 0xFE] + private static let utf16BigEndianMark: [UInt8] = [0xFE, 0xFF] + private static let utf32LittleEndianMark: [UInt8] = [0xFF, 0xFE, 0x00, 0x00] + private static let utf32BigEndianMark: [UInt8] = [0x00, 0x00, 0xFE, 0xFF] + + /// `.utf8` is absent on purpose: Foundation consumes a UTF-8 mark itself, measured. + private static func resolve(_ encoding: String.Encoding, startingWith data: Data) -> Resolution { + switch encoding { + case .utf16: + if data.starts(with: utf16LittleEndianMark) { + return Resolution(encoding: .utf16LittleEndian, byteOrderMarkLength: 2) + } + if data.starts(with: utf16BigEndianMark) { + return Resolution(encoding: .utf16BigEndian, byteOrderMarkLength: 2) + } + return Resolution(encoding: .utf16BigEndian, byteOrderMarkLength: 0) + case .utf16LittleEndian: + return Resolution(encoding: encoding, byteOrderMarkLength: data.starts(with: utf16LittleEndianMark) ? 2 : 0) + case .utf16BigEndian: + return Resolution(encoding: encoding, byteOrderMarkLength: data.starts(with: utf16BigEndianMark) ? 2 : 0) + case .utf32: + if data.starts(with: utf32LittleEndianMark) { + return Resolution(encoding: .utf32LittleEndian, byteOrderMarkLength: 4) + } + if data.starts(with: utf32BigEndianMark) { + return Resolution(encoding: .utf32BigEndian, byteOrderMarkLength: 4) + } + return Resolution(encoding: .utf32BigEndian, byteOrderMarkLength: 0) + case .utf32LittleEndian: + return Resolution(encoding: encoding, byteOrderMarkLength: data.starts(with: utf32LittleEndianMark) ? 4 : 0) + case .utf32BigEndian: + return Resolution(encoding: encoding, byteOrderMarkLength: data.starts(with: utf32BigEndianMark) ? 4 : 0) + default: + return Resolution(encoding: encoding, byteOrderMarkLength: 0) + } + } + + private static func unitSize(of encoding: String.Encoding) -> Int { + switch encoding { + case .utf16, .utf16LittleEndian, .utf16BigEndian: + return 2 + case .utf32, .utf32LittleEndian, .utf32BigEndian: + return 4 + default: + return 1 + } + } + + /// `CFStringGetMaximumSizeForEncoding` counts bytes per UTF-16 code unit, so it is asked for + /// two of them: that is one Unicode scalar, which is the largest thing a boundary can cut in + /// half. It over-reports for several encodings, which costs a decode attempt that fails and + /// never loses a byte, since a trimmed byte goes back on the front of the next chunk. + private static func maximumTrim(of encoding: String.Encoding, unitSize: Int) -> Int { + let cfEncoding = CFStringConvertNSStringEncodingToEncoding(encoding.rawValue) + guard cfEncoding != kCFStringEncodingInvalidId else { return 0 } + let perScalar = Int(CFStringGetMaximumSizeForEncoding(2, cfEncoding)) + guard perScalar > unitSize else { return 0 } + return min(perScalar, 8) - unitSize + } +} diff --git a/TablePro/Core/Utilities/SQL/SQLFileParser.swift b/TablePro/Core/Utilities/SQL/SQLFileParser.swift index d570eae5c5..c7f9befbad 100644 --- a/TablePro/Core/Utilities/SQL/SQLFileParser.swift +++ b/TablePro/Core/Utilities/SQL/SQLFileParser.swift @@ -417,31 +417,6 @@ final class SQLFileParser: Sendable { return StepResult(advanced: true, deferred: false) } - private static func decodeChunkOrCarryTail( - rawData: Data, - pendingTail: inout Data, - encoding: String.Encoding - ) -> String? { - var data = pendingTail - data.append(rawData) - pendingTail.removeAll(keepingCapacity: true) - - if let decoded = String(data: data, encoding: encoding) { - return decoded - } - - guard encoding == .utf8 else { return nil } - - for trim in 1...3 where data.count > trim { - let head = data.prefix(data.count - trim) - if let decoded = String(data: head, encoding: .utf8) { - pendingTail = Data(data.suffix(trim)) - return decoded - } - } - return nil - } - func parseFile( url: URL, encoding: String.Encoding, @@ -463,7 +438,7 @@ final class SQLFileParser: Sendable { private var fileHandle: FileHandle? private var ctx: ParserContext private let nsBuffer = NSMutableString() - private var pendingTail = Data() + private var decoder: SQLChunkDecoder private var emitIndex = 0 private var finished = false @@ -471,6 +446,7 @@ final class SQLFileParser: Sendable { self.url = url self.encoding = encoding self.dialect = dialect + self.decoder = SQLChunkDecoder(encoding: encoding) self.ctx = ParserContext( dialect: dialect, currentStatement: countOnly ? nil : NSMutableString() @@ -515,7 +491,7 @@ final class SQLFileParser: Sendable { let handle = try openFileIfNeeded() let rawData = handle.readData(ofLength: chunkSize) - if rawData.isEmpty && pendingTail.isEmpty { + if rawData.isEmpty && !decoder.hasPendingBytes { emitTrailingStatement() finished = true closeFile() @@ -523,15 +499,13 @@ final class SQLFileParser: Sendable { } let isFinalChunk = rawData.isEmpty - guard let chunk = SQLFileParser.decodeChunkOrCarryTail( - rawData: rawData, pendingTail: &pendingTail, encoding: encoding - ) else { + guard let chunk = decoder.decode(rawData) else { throw DecompressionError.fileReadFailed( "Failed to decode file with \(encoding.description) encoding" ) } - if isFinalChunk && !pendingTail.isEmpty { + if isFinalChunk && decoder.hasPendingBytes { throw DecompressionError.fileReadFailed( "Trailing bytes did not form a valid \(encoding.description) sequence at end of file" ) diff --git a/TablePro/Models/Export/ImportModels.swift b/TablePro/Models/Export/ImportModels.swift index 9e622d5867..c1fd9b4f38 100644 --- a/TablePro/Models/Export/ImportModels.swift +++ b/TablePro/Models/Export/ImportModels.swift @@ -9,25 +9,45 @@ import Foundation // MARK: - Import Encoding Options -/// Available text encodings for import +/// The text encodings the SQL import dialog offers, matching the list the CSV inspector already +/// offers in `CSVPropertyOptions.encodings`. +/// +/// The raw value is the key the last choice is stored under, so it stays put; `label` is what the +/// menu shows. Latin-1 and Windows-1252 are both here because they disagree over 0x80 to 0x9F, +/// which is where a dump written by MySQL keeps its curly quotes, en dashes and euro sign: read +/// as Latin-1 they arrive as C1 control characters instead. enum ImportEncoding: String, CaseIterable, Identifiable { case utf8 = "UTF-8" case utf16 = "UTF-16" + case utf16LittleEndian = "UTF-16LE" + case utf16BigEndian = "UTF-16BE" case latin1 = "Latin1" + case windows1252 = "Windows-1252" case ascii = "ASCII" var id: String { rawValue } + var label: String { + switch self { + case .utf8: return "UTF-8" + case .utf16: return "UTF-16" + case .utf16LittleEndian: return "UTF-16 LE" + case .utf16BigEndian: return "UTF-16 BE" + case .latin1: return "Latin-1" + case .windows1252: return "Windows-1252" + case .ascii: return "ASCII" + } + } + var encoding: String.Encoding { switch self { - case .utf8: - return .utf8 - case .utf16: - return .utf16 - case .latin1: - return .isoLatin1 - case .ascii: - return .ascii + case .utf8: return .utf8 + case .utf16: return .utf16 + case .utf16LittleEndian: return .utf16LittleEndian + case .utf16BigEndian: return .utf16BigEndian + case .latin1: return .isoLatin1 + case .windows1252: return .windowsCP1252 + case .ascii: return .ascii } } } diff --git a/TablePro/Views/Import/ImportDialog.swift b/TablePro/Views/Import/ImportDialog.swift index d9c7fac35b..3047047ca5 100644 --- a/TablePro/Views/Import/ImportDialog.swift +++ b/TablePro/Views/Import/ImportDialog.swift @@ -279,7 +279,7 @@ struct ImportDialog: View { Picker(String(localized: "Encoding"), selection: $selectedEncoding) { ForEach(ImportEncoding.allCases) { enc in - Text(enc.rawValue).tag(enc) + Text(enc.label).tag(enc) } } .pickerStyle(.menu) @@ -421,11 +421,12 @@ struct ImportDialog: View { let maxPreviewSize = 5 * 1_024 * 1_024 let previewData = handle.readData(ofLength: maxPreviewSize) - if let preview = String(data: previewData, encoding: selectedEncoding.encoding) { + var decoder = SQLChunkDecoder(encoding: selectedEncoding.encoding) + if let preview = decoder.decode(previewData) { filePreview = preview hasPreviewError = false } else { - filePreview = String(format: String(localized: "Failed to load preview using encoding: %@. Try selecting a different text encoding."), selectedEncoding.rawValue) + filePreview = String(format: String(localized: "Failed to load preview using encoding: %@. Try selecting a different text encoding."), selectedEncoding.label) hasPreviewError = true } } catch { diff --git a/TableProTests/Core/Utilities/SQL/SQLChunkDecoderTests.swift b/TableProTests/Core/Utilities/SQL/SQLChunkDecoderTests.swift new file mode 100644 index 0000000000..4f4d640eb2 --- /dev/null +++ b/TableProTests/Core/Utilities/SQL/SQLChunkDecoderTests.swift @@ -0,0 +1,112 @@ +// +// SQLChunkDecoderTests.swift +// TableProTests +// + +import Foundation +import Testing + +@testable import TablePro + +@Suite("SQL chunk decoding") +struct SQLChunkDecoderTests { + private func decodeInChunks(_ data: Data, encoding: String.Encoding, chunk size: Int) -> String? { + var decoder = SQLChunkDecoder(encoding: encoding) + var text = "" + var offset = 0 + while offset < data.count { + let end = min(offset + size, data.count) + guard let piece = decoder.decode(data.subdata(in: offset.. [String] { + let url = FileManager.default.temporaryDirectory + .appendingPathComponent(UUID().uuidString + ".sql") + try data.write(to: url) + defer { try? FileManager.default.removeItem(at: url) } + + var statements: [String] = [] + let parser = SQLFileParser() + for try await (stmt, _) in parser.parseFile(url: url, encoding: encoding, dialect: .mysql) { + statements.append(stmt) + } + return statements + } + + /// The parser reads 64 KiB at a time, and a chunk of UTF-16 without a byte order mark decodes + /// as big-endian, so every statement past the first boundary used to arrive byte-swapped: a + /// dump this size imported as CJK from 64 KiB on, with nothing raised. + @Test("A UTF-16 dump larger than one chunk parses to the statements it holds") + func utf16DumpLargerThanOneChunk() async throws { + let lines = (0..<4_000).map { "INSERT INTO t (a) VALUES ('メール \($0)');" } + let sql = lines.joined(separator: "\n") + "\n" + let body = try #require(sql.data(using: .utf16LittleEndian)) + #expect(body.count > 65_536 * 2) + + let withMark = try await Self.parse(Data([0xFF, 0xFE]) + body, encoding: .utf16) + #expect(withMark == lines.map { String($0.dropLast()) }) + + let withoutMark = try await Self.parse(body, encoding: .utf16LittleEndian) + #expect(withoutMark == lines.map { String($0.dropLast()) }) + } + + /// A multi-byte character landing on a chunk boundary is the ordinary case in a dump of + /// non-Latin text, and only UTF-8 used to carry one across. + @Test("A Shift JIS dump larger than one chunk parses to the statements it holds") + func shiftJISDumpLargerThanOneChunk() async throws { + let lines = (0..<4_000).map { "INSERT INTO t (a) VALUES ('日本語 \($0)');" } + let sql = lines.joined(separator: "\n") + "\n" + let body = try #require(sql.data(using: .shiftJIS)) + #expect(body.count > 65_536) + #expect(try await Self.parse(body, encoding: .shiftJIS) == lines.map { String($0.dropLast()) }) + } } diff --git a/docs/features/import-export.mdx b/docs/features/import-export.mdx index b65c0f9448..00f37f1f1b 100644 --- a/docs/features/import-export.mdx +++ b/docs/features/import-export.mdx @@ -270,7 +270,7 @@ Select a row in the data grid and press `Cmd+V` to paste tabular data straight i | Option | What it does | Default | |--------|-------------|---------| | On error | Stop and Rollback, Stop and Commit, or Skip and Continue | Stop and Rollback | -| Encoding | UTF-8, UTF-16, Latin1, or ASCII | UTF-8 | +| Encoding | UTF-8, UTF-16, UTF-16 LE, UTF-16 BE, Latin-1, Windows-1252, or ASCII | UTF-8 | | Wrap in transaction | Runs every statement inside one transaction. Dimmed in Skip and Continue | Yes | | Disable foreign key checks | Suspends constraint checks for the import | Yes | @@ -280,6 +280,8 @@ Select a row in the data grid and press `Cmd+V` to paste tabular data straight i | **Stop and Commit** | Stops there, keeping what already succeeded | | **Skip and Continue** | Logs it and carries on, including a line the parser cannot read. No transaction | +**UTF-16** reads the byte order from the mark at the start of the file and falls back to big-endian, which is what a file with no mark means. Pick **UTF-16 LE** or **UTF-16 BE** for a file that has no mark and is not big-endian. Latin-1 and Windows-1252 differ over the bytes `0x80` to `0x9F`: a dump written by MySQL keeps its curly quotes, en dashes and euro sign there, so Windows-1252 is the one to pick for it. + Skip and Continue collects up to 1,000 failures with their line numbers and messages, and the summary counts successes against failures behind a **Copy Details** button. **Save Report…** writes them all to a CSV with a line, a statement and the database's own error per row, so a large import's failures can be sorted and searched rather than scrolled. A stop shows the line, the database's own message, and the failing statement, with the dialog still open behind it, ready for a changed setting and another run. ### Disabling foreign key checks From fb899783f7ddb18de4948b6ef994a74bd6b83363 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 00:51:09 +0700 Subject: [PATCH 15/54] fix(datagrid): keep the value-filtered display order stable across a cell edit (#2751) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ngô Quốc Đạt --- CHANGELOG.md | 2 +- TablePro/Models/Query/Delta.swift | 11 + TablePro/Models/Query/TabSession.swift | 8 + .../Models/Query/TabSessionRegistry.swift | 12 +- .../Main/Child/MainEditorContentView.swift | 8 +- .../MainContentCoordinator+GridDisplay.swift | 35 ++- .../MainContentCoordinator+SidebarSave.swift | 21 +- ...ContentCoordinator+TableRowsMutation.swift | 6 +- .../Views/Results/DataGridCoordinator.swift | 4 +- .../Results/DataGridView+RowActions.swift | 7 +- TablePro/Views/Results/DataGridView.swift | 5 +- .../Extensions/DataGridView+CellCommit.swift | 4 +- .../Extensions/DataGridView+ValueFilter.swift | 11 +- .../RowEditingCoordinatorCopyTests.swift | 2 +- .../TabSessionRegistryTableRowsTests.swift | 5 +- TableProTests/Models/Query/DeltaTests.swift | 17 ++ .../Query/TabSessionRegistryTests.swift | 86 ++++++- .../Models/Query/TabSessionTests.swift | 1 + ...nContentCoordinatorDisplayStateTests.swift | 2 +- .../Main/ValueFilterEditedRowTests.swift | 219 ++++++++++++++++++ .../TableViewCoordinatorFindTests.swift | 2 +- .../TableViewCoordinatorHighlightTests.swift | 4 +- ...bleViewCoordinatorRowCountCacheTests.swift | 12 +- ...TableViewCoordinatorValueFilterTests.swift | 7 +- docs/features/data-grid.mdx | 2 +- 25 files changed, 436 insertions(+), 57 deletions(-) create mode 100644 TableProTests/Views/Main/ValueFilterEditedRowTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index e661eb8a33..118a843192 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,7 +67,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Linked Folders and Team Library connections ignoring the welcome window search, with no context menu. - Dragging a connection in filtered welcome window results snapping back without moving it. - Welcome window context menu leaving linked connections out of a mixed selection. - - Idle metadata connections held open for the life of the app, up to six per connection. (#2700) - MongoDB connections reading as healthy after the server went away. (#2700) - Password prompt raised by a background reconnect, on whichever window was in front. (#2700) @@ -150,6 +149,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `Illegal mix of collations` comparing a column with a user variable on MySQL 8. - GEOMETRY values from a parameterized MySQL query shown as raw bytes. - Earlier row's text repeated in later rows of a parameterized MySQL query once a value passed 64 KB. +- Wrong row deleted or updated after an edit took a row out of a column value filter. - Garbled non-ASCII text on PostgreSQL databases not encoded in UTF-8 after `RESET ALL` or `DISCARD ALL`. - Garbled or double-encoded non-ASCII text on iOS with PostgreSQL databases not encoded in UTF-8. - Garbled non-ASCII text when restoring a PostgreSQL SQL export into a database not encoded in UTF-8. diff --git a/TablePro/Models/Query/Delta.swift b/TablePro/Models/Query/Delta.swift index b17239aa27..18da0d0d89 100644 --- a/TablePro/Models/Query/Delta.swift +++ b/TablePro/Models/Query/Delta.swift @@ -14,4 +14,15 @@ enum Delta: Equatable { case fullReplace static let none = Delta.cellsChanged([]) + + var changesRowSet: Bool { + switch self { + case .rowsInserted(let indices), .rowsRemoved(let indices): + return !indices.isEmpty + case .fullReplace: + return true + case .cellChanged, .cellsChanged, .columnsReplaced: + return false + } + } } diff --git a/TablePro/Models/Query/TabSession.swift b/TablePro/Models/Query/TabSession.swift index 0ce770f54b..dfb70d3aa4 100644 --- a/TablePro/Models/Query/TabSession.swift +++ b/TablePro/Models/Query/TabSession.swift @@ -38,11 +38,19 @@ final class TabSession: Identifiable { /// be dropped exactly then and kept across an edit. var bufferEpoch: Int + /// Bumped when rows arrive, leave or are replaced, and never for a cell edit, which is the one + /// distinction the other two counters cannot draw: `dataRevision` moves for an edit and + /// `bufferEpoch` sits still for an insert or a delete. Anything that answers "which row sits at + /// this display position" has to hold still across an edit and move with the row set, because an + /// edit leaves the rows where they are and the grid goes on showing them there. + var rowSetRevision: Int + init(id: UUID = UUID()) { self.id = id self.tableRows = TableRows() self.isEvicted = false self.dataRevision = 0 self.bufferEpoch = 0 + self.rowSetRevision = 0 } } diff --git a/TablePro/Models/Query/TabSessionRegistry.swift b/TablePro/Models/Query/TabSessionRegistry.swift index 809e0c8c84..c73ccac591 100644 --- a/TablePro/Models/Query/TabSessionRegistry.swift +++ b/TablePro/Models/Query/TabSessionRegistry.swift @@ -43,6 +43,7 @@ final class TabSessionRegistry { session.isEvicted = false session.dataRevision &+= 1 session.bufferEpoch &+= 1 + session.rowSetRevision &+= 1 } /// A mutation of what the tab already holds, so it cannot resurrect a tab that holds nothing. @@ -53,15 +54,20 @@ final class TabSessionRegistry { /// mutation that leaves the buffer empty leaves a tab with no rows that `canAutoLoadTableTab` /// reads as already loaded, and eviction cannot re-mark it because it has nothing left to lose: /// the grid stays empty until an explicit refresh. - func updateTableRows(for tabId: UUID, _ mutate: (inout TableRows) -> Void) { + @discardableResult + func updateTableRows(for tabId: UUID, _ mutate: (inout TableRows) -> Delta) -> Delta { let session = ensureSession(for: tabId) var rows = session.tableRows - mutate(&rows) + let delta = mutate(&rows) session.tableRows = rows if !rows.rows.isEmpty { session.isEvicted = false } session.dataRevision &+= 1 + if delta.changesRowSet { + session.rowSetRevision &+= 1 + } + return delta } func removeTableRows(for tabId: UUID) { @@ -70,6 +76,7 @@ final class TabSessionRegistry { session.isEvicted = false session.dataRevision &+= 1 session.bufferEpoch &+= 1 + session.rowSetRevision &+= 1 } func isEvicted(_ tabId: UUID) -> Bool { @@ -88,6 +95,7 @@ final class TabSessionRegistry { session.isEvicted = true session.dataRevision &+= 1 session.bufferEpoch &+= 1 + session.rowSetRevision &+= 1 } private func ensureSession(for tabId: UUID) -> TabSession { diff --git a/TablePro/Views/Main/Child/MainEditorContentView.swift b/TablePro/Views/Main/Child/MainEditorContentView.swift index 07b6b67c9c..a33b9d25e8 100644 --- a/TablePro/Views/Main/Child/MainEditorContentView.swift +++ b/TablePro/Views/Main/Child/MainEditorContentView.swift @@ -892,10 +892,7 @@ struct MainEditorContentView: View { coordinator.tabSessionRegistry.existingTableRows(for: tabId) ?? TableRows() }, tableRowsMutator: { [coordinator] mutate in - coordinator.mutateActiveTableRows(for: tabId) { rows in - mutate(&rows) - return .none - } + coordinator.mutateActiveTableRows(for: tabId) { rows in mutate(&rows) } }, paginationOffsetProvider: { [coordinator] in coordinator.tabManager.tabs.first(where: { $0.id == tabId })?.pagination.currentOffset ?? 0 @@ -925,6 +922,9 @@ struct MainEditorContentView: View { sortState: sortStateBinding(for: tab), columnLayout: columnLayoutBinding(for: tab), valueFilter: valueFilterBinding(for: tab), + displayOrderProvider: { [coordinator] in + coordinator.displayIDs(forTab: tabId) + }, displayState: coordinator.displayState(for: tab), restoredRowSelection: tab.selectedRowIndices, restoredCellSelection: tab.cellSelection, diff --git a/TablePro/Views/Main/Extensions/MainContentCoordinator+GridDisplay.swift b/TablePro/Views/Main/Extensions/MainContentCoordinator+GridDisplay.swift index d7700dfb97..5d09b5b55d 100644 --- a/TablePro/Views/Main/Extensions/MainContentCoordinator+GridDisplay.swift +++ b/TablePro/Views/Main/Extensions/MainContentCoordinator+GridDisplay.swift @@ -11,21 +11,24 @@ import TableProPluginKit /// A resolved display order plus the inputs it was resolved from. /// -/// `dataRevision` is ticked by `TabSessionRegistry` on every row mutation, so a stale entry cannot -/// survive a change to the rows it was computed over. That is the point of stamping rather than -/// asking callers to remember a refresh. +/// `rowSetRevision` is ticked by `TabSessionRegistry` whenever rows arrive, leave or are replaced, +/// and never for a cell edit. An edit that takes a row out of the filter's match therefore leaves it +/// where it is until one of the three inputs here moves, which is what the grid shows, and every +/// reader that maps a display position through this order lands on the row the grid has at that +/// position. The display formats are one of those inputs because the filter matches formatted text, +/// so changing a column's format re-resolves the order the way changing the filter does. struct DisplayOrderCacheEntry { - let dataRevision: Int + let rowSetRevision: Int let valueFilter: GridValueFilterState let displayFormats: [ValueDisplayFormat?] let displayIDs: [RowID]? func matches( - dataRevision: Int, + rowSetRevision: Int, valueFilter: GridValueFilterState, displayFormats: [ValueDisplayFormat?] ) -> Bool { - self.dataRevision == dataRevision + self.rowSetRevision == rowSetRevision && self.valueFilter == valueFilter && self.displayFormats == displayFormats } @@ -147,11 +150,11 @@ extension MainContentCoordinator { guard tab.valueFilter.isActive else { return nil } let session = tabSessionRegistry.session(for: tabId) - let dataRevision = session?.dataRevision ?? 0 + let rowSetRevision = session?.rowSetRevision ?? 0 let formats = displayFormats(for: tab) if let cached = displayOrderCache[tabId], - cached.matches(dataRevision: dataRevision, valueFilter: tab.valueFilter, displayFormats: formats) { + cached.matches(rowSetRevision: rowSetRevision, valueFilter: tab.valueFilter, displayFormats: formats) { return cached.displayIDs } @@ -162,7 +165,7 @@ extension MainContentCoordinator { databaseType: connection.type ) displayOrderCache[tabId] = DisplayOrderCacheEntry( - dataRevision: dataRevision, + rowSetRevision: rowSetRevision, valueFilter: tab.valueFilter, displayFormats: formats, displayIDs: resolved @@ -170,9 +173,23 @@ extension MainContentCoordinator { return resolved } + /// Resolves the order now, against the rows as they stand, and stores it for every later reader. + /// + /// The order is a function of the values the rows held when the filter or the row set last + /// changed, not of the values they hold when someone asks. Resolving it lazily makes the answer + /// depend on whether anything happened to read it before the edit: the first read after an edit + /// that takes a row out of the filter's match drops that row, while the grid goes on showing it, + /// and every display position from there on names a different row than the grid has. + @discardableResult + func refreshDisplayOrder(forTab tabId: UUID) -> [RowID]? { + displayOrderCache.removeValue(forKey: tabId) + return displayIDs(forTab: tabId) + } + func setValueFilter(_ valueFilter: GridValueFilterState, forTab tabId: UUID) { guard tabManager.tabs.first(where: { $0.id == tabId })?.valueFilter != valueFilter else { return } tabManager.mutate(tabId: tabId) { $0.valueFilter = valueFilter } + refreshDisplayOrder(forTab: tabId) } /// Drops a value filter whose rows have been replaced wholesale. diff --git a/TablePro/Views/Main/Extensions/MainContentCoordinator+SidebarSave.swift b/TablePro/Views/Main/Extensions/MainContentCoordinator+SidebarSave.swift index c2d431a4dd..003027a244 100644 --- a/TablePro/Views/Main/Extensions/MainContentCoordinator+SidebarSave.swift +++ b/TablePro/Views/Main/Extensions/MainContentCoordinator+SidebarSave.swift @@ -14,6 +14,16 @@ extension MainContentCoordinator { func saveSidebarEdits( editState: MultiRowEditState ) async throws { + let statements = try sidebarEditStatements(editedFields: editState.getEditedFields()) + guard !statements.isEmpty else { return } + try await executeSidebarChanges(statements: statements) + + runQuery() + } + + func sidebarEditStatements( + editedFields: [(columnIndex: Int, columnName: String, newValue: String?)] + ) throws -> [ParameterizedStatement] { guard let tab = tabManager.selectedTab, !selectionState.indices.isEmpty, tab.tableContext.tableName != nil, @@ -22,11 +32,10 @@ extension MainContentCoordinator { resultsViewMode: tab.display.resultsViewMode ) == .dataGrid else { - return + return [] } - let editedFields = editState.getEditedFields() - guard !editedFields.isEmpty else { return } + guard !editedFields.isEmpty else { return [] } let tableRows = tabSessionRegistry.tableRows(for: tab.id) let displayIDs = activeGridDisplayIDs @@ -55,10 +64,6 @@ extension MainContentCoordinator { ) } - let statements = try changeManager.generateSQL(for: changes) - guard !statements.isEmpty else { return } - try await executeSidebarChanges(statements: statements) - - runQuery() + return try changeManager.generateSQL(for: changes) } } diff --git a/TablePro/Views/Main/Extensions/MainContentCoordinator+TableRowsMutation.swift b/TablePro/Views/Main/Extensions/MainContentCoordinator+TableRowsMutation.swift index cc5092e718..e154f1e9c2 100644 --- a/TablePro/Views/Main/Extensions/MainContentCoordinator+TableRowsMutation.swift +++ b/TablePro/Views/Main/Extensions/MainContentCoordinator+TableRowsMutation.swift @@ -16,9 +16,9 @@ extension MainContentCoordinator { for tabId: UUID, _ mutate: (inout TableRows) -> Delta ) -> Delta { - var delta: Delta = .none - tabSessionRegistry.updateTableRows(for: tabId) { rows in - delta = mutate(&rows) + let delta = tabSessionRegistry.updateTableRows(for: tabId, mutate) + if delta.changesRowSet { + refreshDisplayOrder(forTab: tabId) } return delta } diff --git a/TablePro/Views/Results/DataGridCoordinator.swift b/TablePro/Views/Results/DataGridCoordinator.swift index 9843474696..1298a3cbe7 100644 --- a/TablePro/Views/Results/DataGridCoordinator.swift +++ b/TablePro/Views/Results/DataGridCoordinator.swift @@ -33,7 +33,7 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData NSMenuDelegate { var tableRowsProvider: @MainActor () -> TableRows = { TableRows() } - var tableRowsMutator: @MainActor (@MainActor (inout TableRows) -> Void) -> Void = { _ in } + var tableRowsMutator: @MainActor (@MainActor (inout TableRows) -> Delta) -> Delta = { _ in .none } var paginationOffsetProvider: @MainActor () -> Int = { 0 } var changeManager: AnyChangeManager var isEditable: Bool @@ -49,6 +49,7 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData /// the filter lives here alone and dies with this coordinator, which is all a structure or /// create-table grid needs. var valueFilterBinding: Binding? + var displayOrderProvider: (@MainActor () -> [RowID]?)? private var storedValueFilterState = GridValueFilterState() /// Reads never go back through the binding, because a SwiftUI `Binding` built from a captured /// value type returns the pre-write value until the next body pass. The mirror is authoritative @@ -707,6 +708,7 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData // Local only: this runs while the window is being torn down, and the filter's owner is // either about to go away with it or is deliberately keeping the filter for the next mount. valueFilterBinding = nil + displayOrderProvider = nil adoptValueFilter(GridValueFilterState()) lastUpdateSnapshot = nil columnPool.detachFromTableView() diff --git a/TablePro/Views/Results/DataGridView+RowActions.swift b/TablePro/Views/Results/DataGridView+RowActions.swift index fa7f8e7877..76bc55064a 100644 --- a/TablePro/Views/Results/DataGridView+RowActions.swift +++ b/TablePro/Views/Results/DataGridView+RowActions.swift @@ -28,11 +28,10 @@ extension TableViewCoordinator { func undoInsertRow(at index: Int) { delegate?.dataGridUndoInsert(at: index) changeManager.undoRowInsertion(rowIndex: index) - var capturedDelta: Delta = .none - tableRowsMutator { rows in - capturedDelta = rows.remove(at: IndexSet(integer: index)) + let delta = tableRowsMutator { rows in + rows.remove(at: IndexSet(integer: index)) } - applyDelta(capturedDelta) + applyDelta(delta) } func copyRows(at indices: Set) { diff --git a/TablePro/Views/Results/DataGridView.swift b/TablePro/Views/Results/DataGridView.swift index 98e2c01400..5a9390628c 100644 --- a/TablePro/Views/Results/DataGridView.swift +++ b/TablePro/Views/Results/DataGridView.swift @@ -69,7 +69,7 @@ extension RowVisualState { struct DataGridView: NSViewRepresentable { var tableRowsProvider: @MainActor () -> TableRows = { TableRows() } - var tableRowsMutator: @MainActor (@MainActor (inout TableRows) -> Void) -> Void = { _ in } + var tableRowsMutator: @MainActor (@MainActor (inout TableRows) -> Delta) -> Delta = { _ in .none } var paginationOffsetProvider: @MainActor () -> Int = { 0 } var changeManager: AnyChangeManager let isEditable: Bool @@ -91,6 +91,7 @@ struct DataGridView: NSViewRepresentable { /// menu's row commands all read it with no grid mounted. A grid with no owner keeps the filter /// on its own coordinator, which is all a structure or create-table grid ever needs. (#2251) var valueFilter: Binding? + var displayOrderProvider: (@MainActor () -> [RowID]?)? /// The formatted text and viewport anchor for this result, owned the same way and for the same /// reason as the value filter above. The owner hands back a fresh instance whenever the inputs /// that decide the text have moved, so adopting one is always safe. (#2424) @@ -161,6 +162,7 @@ struct DataGridView: NSViewRepresentable { coordinator.tableRowsMutator = tableRowsMutator coordinator.paginationOffsetProvider = paginationOffsetProvider coordinator.valueFilterBinding = valueFilter + coordinator.displayOrderProvider = displayOrderProvider if let valueFilter { coordinator.adoptValueFilter(valueFilter.wrappedValue) } @@ -234,6 +236,7 @@ struct DataGridView: NSViewRepresentable { // before the snapshot is built. A snapshot taken from the stale order would report no // change and skip the reload. coordinator.valueFilterBinding = valueFilter + coordinator.displayOrderProvider = displayOrderProvider if let valueFilter, coordinator.valueFilterState != valueFilter.wrappedValue { coordinator.adoptValueFilter(valueFilter.wrappedValue) coordinator.recomputeValueFilteredIDs() diff --git a/TablePro/Views/Results/Extensions/DataGridView+CellCommit.swift b/TablePro/Views/Results/Extensions/DataGridView+CellCommit.swift index 285570a131..88f48d07ac 100644 --- a/TablePro/Views/Results/Extensions/DataGridView+CellCommit.swift +++ b/TablePro/Views/Results/Extensions/DataGridView+CellCommit.swift @@ -60,8 +60,8 @@ extension TableViewCoordinator { var delta: Delta = .none if let storageRow { - tableRowsMutator { tableRows in - delta = tableRows.edit(row: storageRow, column: columnIndex, value: typedNewValue) + delta = tableRowsMutator { tableRows in + tableRows.edit(row: storageRow, column: columnIndex, value: typedNewValue) } } cellCommitLogger.debug("recordCellEdit - about to call delegate.dataGridDidEditCell, delegate=\(self.delegate == nil ? "nil" : "present", privacy: .public)") diff --git a/TablePro/Views/Results/Extensions/DataGridView+ValueFilter.swift b/TablePro/Views/Results/Extensions/DataGridView+ValueFilter.swift index d2a2dc945d..85dc0a274a 100644 --- a/TablePro/Views/Results/Extensions/DataGridView+ValueFilter.swift +++ b/TablePro/Views/Results/Extensions/DataGridView+ValueFilter.swift @@ -39,11 +39,14 @@ extension TableViewCoordinator { return result } - /// Recomputes what the grid shows, through the same resolver the tab's owner uses. - /// - /// Both sides run one pure function over the same rows, filter, formats and database type, so - /// the grid and the readers that run without it cannot disagree about the display order. + /// Recomputes what the grid shows. A grid with an owner takes the owner's order, so the grid and + /// the readers that run without it cannot disagree about which row sits at a display position, + /// including after an edit has taken a row out of the filter's match. func recomputeValueFilteredIDs() { + if let displayOrderProvider { + valueFilteredIDs = displayOrderProvider() + return + } let tableRows = tableRowsProvider() valueFilteredIDs = GridDisplayOrderResolver.resolve( tableRows: tableRows, diff --git a/TableProTests/Core/Coordinators/RowEditingCoordinatorCopyTests.swift b/TableProTests/Core/Coordinators/RowEditingCoordinatorCopyTests.swift index 12ff8930b0..336a6117cb 100644 --- a/TableProTests/Core/Coordinators/RowEditingCoordinatorCopyTests.swift +++ b/TableProTests/Core/Coordinators/RowEditingCoordinatorCopyTests.swift @@ -130,7 +130,7 @@ struct RowEditingCoordinatorCopyTests { } /// Fetch All extends the same result rather than replacing it, so the filter stays and the - /// order is re-resolved over the rows that arrived. The memo keys on the registry's data + /// order is re-resolved over the rows that arrived. The memo keys on the registry's row-set /// revision, so this holds with no grid mounted to recompute it. @Test("loading more rows into the same result keeps the value filter and re-resolves the order") func loadingMoreRowsKeepsTheValueFilter() { diff --git a/TableProTests/Core/Services/Query/TabSessionRegistryTableRowsTests.swift b/TableProTests/Core/Services/Query/TabSessionRegistryTableRowsTests.swift index 0e6b0b064f..0d9a07314e 100644 --- a/TableProTests/Core/Services/Query/TabSessionRegistryTableRowsTests.swift +++ b/TableProTests/Core/Services/Query/TabSessionRegistryTableRowsTests.swift @@ -1,8 +1,9 @@ import Foundation import TableProPluginKit -@testable import TablePro import Testing +@testable import TablePro + @Suite("TabSessionRegistry+TableRows") @MainActor struct TabSessionRegistryTableRowsTests { @@ -129,7 +130,7 @@ struct TabSessionRegistryTableRowsTests { ) store.updateTableRows(for: tabId) { rows in - _ = rows.edit(row: 0, column: 0, value: "z") + rows.edit(row: 0, column: 0, value: "z") } let resolved = store.existingTableRows(for: tabId) diff --git a/TableProTests/Models/Query/DeltaTests.swift b/TableProTests/Models/Query/DeltaTests.swift index 79fd0a6172..d2cbc0318b 100644 --- a/TableProTests/Models/Query/DeltaTests.swift +++ b/TableProTests/Models/Query/DeltaTests.swift @@ -75,4 +75,21 @@ struct DeltaTests { #expect(inserted != removed) #expect(Delta.columnsReplaced != Delta.fullReplace) } + + @Test("Rows arriving, leaving or being replaced change the row set") + func structuralDeltasChangeRowSet() { + #expect(Delta.rowsInserted(IndexSet(integer: 3)).changesRowSet) + #expect(Delta.rowsRemoved(IndexSet([1, 4])).changesRowSet) + #expect(Delta.fullReplace.changesRowSet) + } + + @Test("Cell edits, metadata and empty row deltas keep the row set") + func nonStructuralDeltasKeepRowSet() { + #expect(!Delta.cellChanged(row: 0, column: 1).changesRowSet) + #expect(!Delta.cellsChanged([CellPosition(row: 2, column: 0)]).changesRowSet) + #expect(!Delta.none.changesRowSet) + #expect(!Delta.columnsReplaced.changesRowSet) + #expect(!Delta.rowsInserted(IndexSet()).changesRowSet) + #expect(!Delta.rowsRemoved(IndexSet()).changesRowSet) + } } diff --git a/TableProTests/Models/Query/TabSessionRegistryTests.swift b/TableProTests/Models/Query/TabSessionRegistryTests.swift index 5c3182e465..f1cd47c445 100644 --- a/TableProTests/Models/Query/TabSessionRegistryTests.swift +++ b/TableProTests/Models/Query/TabSessionRegistryTests.swift @@ -119,12 +119,96 @@ struct TabSessionRegistryTests { let before = session.dataRevision registry.updateTableRows(for: session.id) { rows in - rows.rows.append(Row(id: .existing(1), values: [.text("b")])) + rows.appendPage([[.text("b")]], startingAt: 1) } #expect(session.dataRevision > before) } + // MARK: - rowSetRevision + + @Test("A cell edit moves dataRevision and leaves rowSetRevision alone") + func cellEditKeepsRowSetRevision() { + let registry = TabSessionRegistry() + let session = TabSession() + registry.register(session) + registry.setTableRows(makeRows(["a", "b"]), for: session.id) + let dataBefore = session.dataRevision + let rowSetBefore = session.rowSetRevision + + let delta = registry.updateTableRows(for: session.id) { rows in + rows.edit(row: 1, column: 0, value: .text("z")) + } + + #expect(delta == .cellChanged(row: 1, column: 0)) + #expect(session.dataRevision > dataBefore) + #expect(session.rowSetRevision == rowSetBefore) + } + + @Test("Inserting, removing or replacing rows moves rowSetRevision") + func structuralMutationsMoveRowSetRevision() { + let registry = TabSessionRegistry() + let session = TabSession() + registry.register(session) + registry.setTableRows(makeRows(["a", "b"]), for: session.id) + + let beforeInsert = session.rowSetRevision + registry.updateTableRows(for: session.id) { rows in + rows.appendInsertedRow(values: [.text("c")]) + } + #expect(session.rowSetRevision > beforeInsert) + + let beforeRemove = session.rowSetRevision + registry.updateTableRows(for: session.id) { rows in + rows.remove(at: IndexSet(integer: 0)) + } + #expect(session.rowSetRevision > beforeRemove) + + let beforeReplace = session.rowSetRevision + registry.updateTableRows(for: session.id) { rows in + rows.replace(rows: [[.text("x")]]) + } + #expect(session.rowSetRevision > beforeReplace) + } + + @Test("Metadata that keeps every row, and a mutation that changes nothing, leave rowSetRevision alone") + func nonStructuralMutationsKeepRowSetRevision() { + let registry = TabSessionRegistry() + let session = TabSession() + registry.register(session) + registry.setTableRows(makeRows(["a"]), for: session.id) + let before = session.rowSetRevision + + registry.updateTableRows(for: session.id) { rows in + rows.updateDisplayMetadata(columnComments: ["name": "the name"]) + } + registry.updateTableRows(for: session.id) { rows in + rows.remove(at: IndexSet(integer: 9)) + } + + #expect(session.rowSetRevision == before) + } + + @Test("Replacing, removing and evicting the buffer each move rowSetRevision") + func bufferReplacementMovesRowSetRevision() { + let registry = TabSessionRegistry() + let session = TabSession() + registry.register(session) + + registry.setTableRows(makeRows(["a"]), for: session.id) + let afterSet = session.rowSetRevision + registry.evict(for: session.id) + let afterEvict = session.rowSetRevision + registry.setTableRows(makeRows(["b"]), for: session.id) + let afterSecondSet = session.rowSetRevision + registry.removeTableRows(for: session.id) + + #expect(afterSet > 0) + #expect(afterEvict > afterSet) + #expect(afterSecondSet > afterEvict) + #expect(session.rowSetRevision > afterSecondSet) + } + @Test("removeTableRows bumps dataRevision") func removeTableRowsBumpsDataRevision() { let registry = TabSessionRegistry() diff --git a/TableProTests/Models/Query/TabSessionTests.swift b/TableProTests/Models/Query/TabSessionTests.swift index 9f5b752f61..c422bb6697 100644 --- a/TableProTests/Models/Query/TabSessionTests.swift +++ b/TableProTests/Models/Query/TabSessionTests.swift @@ -23,6 +23,7 @@ struct TabSessionTests { #expect(session.tableRows.columns.isEmpty) #expect(session.isEvicted == false) #expect(session.dataRevision == 0) + #expect(session.rowSetRevision == 0) } @Test("A session keeps the id it was created with") diff --git a/TableProTests/Views/Main/MainContentCoordinatorDisplayStateTests.swift b/TableProTests/Views/Main/MainContentCoordinatorDisplayStateTests.swift index 1a09dab853..ec1a499a4c 100644 --- a/TableProTests/Views/Main/MainContentCoordinatorDisplayStateTests.swift +++ b/TableProTests/Views/Main/MainContentCoordinatorDisplayStateTests.swift @@ -88,7 +88,7 @@ struct MainContentCoordinatorDisplayStateTests { seedRows(coordinator, for: tab.id) let before = coordinator.displayState(for: tabManager.tabs[0]) - coordinator.tabSessionRegistry.updateTableRows(for: tab.id) { _ in } + coordinator.tabSessionRegistry.updateTableRows(for: tab.id) { _ in .none } #expect(coordinator.displayState(for: tabManager.tabs[0]) === before) } diff --git a/TableProTests/Views/Main/ValueFilterEditedRowTests.swift b/TableProTests/Views/Main/ValueFilterEditedRowTests.swift new file mode 100644 index 0000000000..72be60fac4 --- /dev/null +++ b/TableProTests/Views/Main/ValueFilterEditedRowTests.swift @@ -0,0 +1,219 @@ +// +// ValueFilterEditedRowTests.swift +// TableProTests +// + +import AppKit +import Foundation +import SwiftUI +import TableProPluginKit +import Testing + +@testable import TablePro + +@MainActor +private final class EditedRowLayoutPersister: ColumnLayoutPersisting { + func load(for key: ColumnLayoutTableKey) -> ColumnLayoutState? { nil } + func save(_ layout: ColumnLayoutState, for key: ColumnLayoutTableKey) {} + func clear(for key: ColumnLayoutTableKey) {} +} + +@Suite("Value filter after an edit takes a row out of its match") +@MainActor +struct ValueFilterEditedRowTests { + private struct Fixture { + let coordinator: MainContentCoordinator + let tabId: UUID + } + + private func makeFixture() -> Fixture { + let tabManager = QueryTabManager() + let coordinator = MainContentCoordinator( + connection: TestFixtures.makeConnection(), + tabManager: tabManager, + changeManager: DataChangeManager(), + toolbarState: ConnectionToolbarState() + ) + var tab = QueryTab(title: "users", query: "SELECT * FROM users", tabType: .table, tableName: "users") + tab.execution.lastExecutedAt = Date() + tabManager.tabs.append(tab) + tabManager.selectedTabId = tab.id + + coordinator.setActiveTableRows( + TableRows.from( + queryRows: [ + [.text("1"), .text("Alice")], + [.text("2"), .text("Bob")], + [.text("3"), .text("Carol")] + ], + columns: ["id", "name"], + columnTypes: [.text(rawType: nil), .text(rawType: nil)], + hasAuthoritativeSchema: true + ), + for: tab.id + ) + coordinator.changeManager.configureForTable( + tableName: "users", + columns: ["id", "name"], + primaryKeyColumns: ["id"], + databaseType: .mysql, + generatedColumns: [] + ) + coordinator.setValueFilter(nameFilter(["Bob", "Carol"]), forTab: tab.id) + return Fixture(coordinator: coordinator, tabId: tab.id) + } + + private func nameFilter(_ names: Set) -> GridValueFilterState { + var state = GridValueFilterState() + state.set( + ColumnValueFilter(selectedValues: names, includesNull: false), + columnName: "name", + forColumn: 1 + ) + return state + } + + private func mountGrid(on fixture: Fixture) -> TableViewCoordinator { + let coordinator = fixture.coordinator + let tabId = fixture.tabId + let delegate = DataTabGridDelegate() + let grid = TableViewCoordinator( + changeManager: AnyChangeManager(coordinator.changeManager), + isEditable: true, + selectedRowIndices: .constant([]), + delegate: delegate, + layoutPersister: EditedRowLayoutPersister() + ) + delegate.dataGridAttach(tableViewCoordinator: grid) + coordinator.dataTabDelegate = delegate + grid.tableRowsProvider = { [weak coordinator] in + coordinator?.tabSessionRegistry.existingTableRows(for: tabId) ?? TableRows() + } + grid.tableRowsMutator = { [weak coordinator] mutate in + coordinator?.mutateActiveTableRows(for: tabId) { rows in mutate(&rows) } ?? .none + } + grid.valueFilterBinding = Binding( + get: { coordinator.tabManager.tabs.first { $0.id == tabId }?.valueFilter ?? GridValueFilterState() }, + set: { coordinator.setValueFilter($0, forTab: tabId) } + ) + grid.displayOrderProvider = { [weak coordinator] in + coordinator?.displayIDs(forTab: tabId) + } + grid.adoptValueFilter(coordinator.tabManager.tabs.first { $0.id == tabId }?.valueFilter ?? GridValueFilterState()) + grid.recomputeValueFilteredIDs() + grid.updateCache() + return grid + } + + private func renameBobInStorage(_ fixture: Fixture, to name: String) { + fixture.coordinator.mutateActiveTableRows(for: fixture.tabId) { rows in + rows.edit(row: 1, column: 1, value: .text(name)) + } + } + + private func stringParameters(_ statement: ParameterizedStatement) -> [String] { + statement.parameters.compactMap { $0 as? String } + } + + @Test("an edit that takes a row out of the filter leaves it at its display position") + func editKeepsTheRowInTheDisplayOrder() { + let fixture = makeFixture() + #expect(fixture.coordinator.activeGridDisplayIDs == [.existing(1), .existing(2)]) + + renameBobInStorage(fixture, to: "Zed") + + #expect(fixture.coordinator.activeGridDisplayIDs == [.existing(1), .existing(2)]) + } + + @Test("the order is resolved when the filter is set, not when a reader first asks for it") + func orderDoesNotDependOnWhenItIsFirstRead() { + let fixture = makeFixture() + renameBobInStorage(fixture, to: "Zed") + + #expect(fixture.coordinator.activeGridDisplayIDs == [.existing(1), .existing(2)]) + } + + @Test("the mounted grid and the owner agree on the display order after an inline edit") + func gridAndOwnerAgreeAfterAnInlineEdit() { + let fixture = makeFixture() + let grid = mountGrid(on: fixture) + + grid.recordCellEdit(row: 0, columnIndex: 1, newValue: .text("Zed")) + grid.recomputeValueFilteredIDs() + + #expect(grid.displayIDs == [.existing(1), .existing(2)]) + #expect(grid.displayIDs == fixture.coordinator.activeGridDisplayIDs) + #expect(grid.displayRow(at: 0)?.values[1] == .text("Zed")) + } + + @Test("a grid with an owner shows the owner's order rather than resolving its own") + func gridTakesTheOwnersOrder() { + let fixture = makeFixture() + let grid = mountGrid(on: fixture) + grid.displayOrderProvider = { [.existing(2)] } + + grid.recomputeValueFilteredIDs() + + #expect(grid.displayIDs == [.existing(2)]) + } + + @Test("deleting the row the grid shows after an edit deletes that row and no other") + func deleteAfterAnEditTargetsTheShownRow() throws { + let fixture = makeFixture() + let grid = mountGrid(on: fixture) + grid.recordCellEdit(row: 0, columnIndex: 1, newValue: .text("Zed")) + + fixture.coordinator.deleteSelectedRows(indices: [0]) + + let deletes = try fixture.coordinator.changeManager.generateSQL() + .filter { $0.sql.hasPrefix("DELETE") } + #expect(deletes.count == 1) + let parameters = deletes.first.map(stringParameters) ?? [] + #expect(parameters.contains("2")) + #expect(!parameters.contains("3")) + } + + @Test("a row inspector save after an edit updates the row the grid shows") + func sidebarSaveAfterAnEditTargetsTheShownRow() throws { + let fixture = makeFixture() + renameBobInStorage(fixture, to: "Zed") + fixture.coordinator.selectionState.indices = [0] + + let statements = try fixture.coordinator.sidebarEditStatements( + editedFields: [(columnIndex: 1, columnName: "name", newValue: "Yan")] + ) + + #expect(statements.count == 1) + let parameters = statements.first.map(stringParameters) ?? [] + #expect(parameters.contains("Yan")) + #expect(parameters.contains("2")) + #expect(!parameters.contains("3")) + } + + @Test("adding a row re-resolves the order, so the edited row leaves with the next row-set change") + func addingARowReResolvesTheOrder() { + let fixture = makeFixture() + renameBobInStorage(fixture, to: "Zed") + + fixture.coordinator.mutateActiveTableRows(for: fixture.tabId) { rows in + rows.appendInsertedRow(values: [.text("4"), .text("Dan")]) + } + + guard let insertedID = fixture.coordinator.tabSessionRegistry.tableRows(for: fixture.tabId).rows.last?.id else { + Issue.record("no inserted row") + return + } + #expect(insertedID.isInserted) + #expect(fixture.coordinator.activeGridDisplayIDs == [RowID.existing(2), insertedID]) + } + + @Test("changing the filter re-resolves the order over the edited values") + func changingTheFilterReResolvesTheOrder() { + let fixture = makeFixture() + renameBobInStorage(fixture, to: "Zed") + + fixture.coordinator.setValueFilter(nameFilter(["Zed"]), forTab: fixture.tabId) + + #expect(fixture.coordinator.activeGridDisplayIDs == [.existing(1)]) + } +} diff --git a/TableProTests/Views/Results/TableViewCoordinatorFindTests.swift b/TableProTests/Views/Results/TableViewCoordinatorFindTests.swift index 2536b48be1..43aceaa63e 100644 --- a/TableProTests/Views/Results/TableViewCoordinatorFindTests.swift +++ b/TableProTests/Views/Results/TableViewCoordinatorFindTests.swift @@ -32,7 +32,7 @@ struct TableViewCoordinatorFindTests { columnTypes: [.blob(rawType: "VARBINARY(255)")] ) coordinator.tableRowsProvider = { captured } - coordinator.tableRowsMutator = { (mutation: (inout TableRows) -> Void) in mutation(&captured) } + coordinator.tableRowsMutator = { (mutation: (inout TableRows) -> Delta) in mutation(&captured) } coordinator.updateCache() coordinator.updateDisplayFormats([format]) return coordinator diff --git a/TableProTests/Views/Results/TableViewCoordinatorHighlightTests.swift b/TableProTests/Views/Results/TableViewCoordinatorHighlightTests.swift index 0d644c8514..dd57f78c17 100644 --- a/TableProTests/Views/Results/TableViewCoordinatorHighlightTests.swift +++ b/TableProTests/Views/Results/TableViewCoordinatorHighlightTests.swift @@ -44,8 +44,8 @@ private final class HighlightGrid { ) coordinator.tableRowsProvider = { [weak self] in self?.tableRows ?? TableRows() } coordinator.tableRowsMutator = { [weak self] mutation in - guard let self else { return } - mutation(&self.tableRows) + guard let self else { return .none } + return mutation(&self.tableRows) } coordinator.rebuildColumnMetadataCache(from: tableRows) coordinator.updateCache() diff --git a/TableProTests/Views/Results/TableViewCoordinatorRowCountCacheTests.swift b/TableProTests/Views/Results/TableViewCoordinatorRowCountCacheTests.swift index cd678c42b1..d3f5c4ccb8 100644 --- a/TableProTests/Views/Results/TableViewCoordinatorRowCountCacheTests.swift +++ b/TableProTests/Views/Results/TableViewCoordinatorRowCountCacheTests.swift @@ -45,9 +45,9 @@ struct TableViewCoordinatorRowCountCacheTests { func updateCacheReflectsAppendedRows() { let coordinator = makeCoordinator(rows: []) - coordinator.tableRowsMutator { rows in + _ = coordinator.tableRowsMutator { rows in _ = rows.appendInsertedRow(values: [.text("a")]) - _ = rows.appendInsertedRow(values: [.text("b")]) + return rows.appendInsertedRow(values: [.text("b")]) } coordinator.updateCache() @@ -64,8 +64,8 @@ struct TableViewCoordinatorRowCountCacheTests { ] let coordinator = makeCoordinator(rows: rows) - coordinator.tableRowsMutator { rows in - _ = rows.remove(rowIDs: [.existing(1)]) + _ = coordinator.tableRowsMutator { rows in + rows.remove(rowIDs: [.existing(1)]) } coordinator.updateCache() @@ -80,8 +80,8 @@ struct TableViewCoordinatorRowCountCacheTests { ] let coordinator = makeCoordinator(rows: rows) - coordinator.tableRowsMutator { rows in - _ = rows.replace(rows: [[.text("x")], [.text("y")], [.text("z")], [.text("w")]]) + _ = coordinator.tableRowsMutator { rows in + rows.replace(rows: [[.text("x")], [.text("y")], [.text("z")], [.text("w")]]) } coordinator.updateCache() diff --git a/TableProTests/Views/Results/TableViewCoordinatorValueFilterTests.swift b/TableProTests/Views/Results/TableViewCoordinatorValueFilterTests.swift index 8d4ba364c7..b3f45cacd6 100644 --- a/TableProTests/Views/Results/TableViewCoordinatorValueFilterTests.swift +++ b/TableProTests/Views/Results/TableViewCoordinatorValueFilterTests.swift @@ -158,8 +158,8 @@ struct TableViewCoordinatorValueFilterTests { forColumn: 0 ) - coordinator.tableRowsMutator { rows in - _ = rows.appendInsertedRow(values: [.text("inactive"), .text("z")]) + _ = coordinator.tableRowsMutator { rows in + rows.appendInsertedRow(values: [.text("inactive"), .text("z")]) } coordinator.recomputeValueFilteredIDs() coordinator.updateCache() @@ -177,8 +177,9 @@ struct TableViewCoordinatorValueFilterTests { forColumn: 0 ) - coordinator.tableRowsMutator { rows in + _ = coordinator.tableRowsMutator { rows in rows.columns = ["other", "name"] + return .columnsReplaced } coordinator.applyFullReplace() coordinator.recomputeValueFilteredIDs() diff --git a/docs/features/data-grid.mdx b/docs/features/data-grid.mdx index 9fc8d6c10c..945c365fdd 100644 --- a/docs/features/data-grid.mdx +++ b/docs/features/data-grid.mdx @@ -38,7 +38,7 @@ The header menu carries two filters that answer different questions. Value filter popover -A value filter lives as long as the result does: switching view mode or tab keeps it, replacing the result clears it. **Fetch All** keeps it and applies it to the rows it loads. +A value filter lives as long as the result does: switching view mode or tab keeps it, replacing the result clears it. **Fetch All** keeps it and applies it to the rows it loads. Edit a cell so its row no longer matches and the row stays where it is. The filter runs again when rows arrive or leave, and when you change the filter or the column's display format. ## Highlighting From a399adb596356528ddadb4e57d8f8b1de000f38f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 00:51:26 +0700 Subject: [PATCH 16/54] docs(changelog): scope the foreign key label fix to engines with a schema layer (#2752) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 118a843192..f8ee74bf86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -153,7 +153,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Garbled non-ASCII text on PostgreSQL databases not encoded in UTF-8 after `RESET ALL` or `DISCARD ALL`. - Garbled or double-encoded non-ASCII text on iOS with PostgreSQL databases not encoded in UTF-8. - Garbled non-ASCII text when restoring a PostgreSQL SQL export into a database not encoded in UTF-8. -- Display As formats and foreign key labels lost on a rename, and kept with column layouts after deleting a connection. +- Display As formats lost on a rename, and kept with column layouts after deleting a connection. ### Security From cc37e8fde59ac90131d49361f2a15c302e0ff503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 00:53:47 +0700 Subject: [PATCH 17/54] feat(plugins): refresh materialized views, show view DDL and edit object comments (#2726) (#2753) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ngô Quốc Đạt --- CHANGELOG.md | 11 + Plugins/BeancountDriverPlugin/Info.plist | 2 +- Plugins/BigQueryDriverPlugin/Info.plist | 2 +- Plugins/CSVExportPlugin/Info.plist | 2 +- Plugins/CSVImportPlugin/Info.plist | 2 +- Plugins/CassandraDriverPlugin/Info.plist | 2 +- Plugins/ClickHouseDriverPlugin/Info.plist | 2 +- Plugins/CloudflareD1DriverPlugin/Info.plist | 2 +- .../CloudflareR2SQLDriverPlugin/Info.plist | 2 +- Plugins/DamengDriverPlugin/Info.plist | 2 +- Plugins/DuckDBDriverPlugin/Info.plist | 2 +- Plugins/DynamoDBDriverPlugin/Info.plist | 2 +- Plugins/ElasticsearchDriverPlugin/Info.plist | 2 +- Plugins/EtcdDriverPlugin/Info.plist | 2 +- Plugins/HTMLExportPlugin/Info.plist | 2 +- Plugins/JSONExportPlugin/Info.plist | 2 +- Plugins/JSONImportPlugin/Info.plist | 2 +- Plugins/KafkaDriverPlugin/Info.plist | 2 +- Plugins/LibSQLDriverPlugin/Info.plist | 2 +- Plugins/MQLExportPlugin/Info.plist | 2 +- Plugins/MSSQLDriverPlugin/Info.plist | 2 +- Plugins/MarkdownExportPlugin/Info.plist | 2 +- Plugins/MongoDBDriverPlugin/Info.plist | 2 +- Plugins/MySQLDriverPlugin/Info.plist | 2 +- Plugins/OracleDriverPlugin/Info.plist | 2 +- Plugins/ParquetExportPlugin/Info.plist | 2 +- Plugins/PostgreSQLDriverPlugin/Info.plist | 2 +- .../LibPQDriverCore.swift | 1 + .../LibPQPluginConnection.swift | 16 ++ .../PostgreSQLPluginDriver+PrincipalSQL.swift | 10 +- .../PostgreSQLPluginDriver+Views.swift | 91 ++++++++ .../PostgreSQLPluginDriver.swift | 51 ++-- .../PostgreSQLRelationSQL.swift | 95 ++++++++ .../PostgreSQLViewDefinition.swift | 169 ++++++++++++++ Plugins/RedisDriverPlugin/Info.plist | 2 +- Plugins/SQLExportPlugin/Info.plist | 2 +- Plugins/SQLImportPlugin/Info.plist | 2 +- Plugins/SQLiteDriverPlugin/Info.plist | 2 +- Plugins/SnowflakeDriverPlugin/Info.plist | 2 +- Plugins/SpannerDriverPlugin/Info.plist | 2 +- Plugins/SurrealDBDriverPlugin/Info.plist | 2 +- .../PluginConcurrentRefreshAvailability.swift | 17 ++ .../PluginDatabaseDriver.swift | 30 +++ Plugins/TeradataDriverPlugin/Info.plist | 2 +- Plugins/TrinoDriverPlugin/Info.plist | 2 +- Plugins/TypesenseDriverPlugin/Info.plist | 2 +- Plugins/XLSXExportPlugin/Info.plist | 2 +- Plugins/XLSXImportPlugin/Info.plist | 2 +- Plugins/XMLExportPlugin/Info.plist | 2 +- TablePro/Core/Database/DatabaseDriver.swift | 26 +++ .../DatabaseObjectToolEligibility.swift | 53 +++++ .../Database/MaterializedViewRefreshing.swift | 55 +++++ .../Core/Database/ObjectCommentEditing.swift | 127 ++++++++++ TablePro/Core/Database/TableDDLComposer.swift | 30 +++ TablePro/Core/Events/AppCommands.swift | 27 +++ .../Core/MCP/MCPConnectionBridge+Schema.swift | 8 +- TablePro/Core/Menu/DatabaseMenuBuilder.swift | 18 ++ .../Core/Plugins/PluginDriverAdapter.swift | 17 ++ TablePro/Core/Plugins/PluginManager.swift | 6 +- ...itViewController+DatabaseMenuActions.swift | 16 ++ ...inSplitViewController+MenuValidation.swift | 38 ++- .../Database/DatabaseObjectTarget.swift | 28 +++ .../MaterializedViewRefreshPrompt.swift | 89 +++++++ .../Models/Database/ObjectCommentDraft.swift | 39 ++++ TablePro/Models/Query/DatabaseObjectRef.swift | 33 ++- TablePro/Models/Query/QueryResult.swift | 2 +- TablePro/Models/Query/QueryTabManager.swift | 2 + ...ntentCoordinator+DatabaseObjectTools.swift | 157 +++++++++++++ ...ainContentCoordinator+SidebarActions.swift | 52 +++-- ...ontentCommandActions+DatabaseObjects.swift | 55 ++++- .../Main/MainContentCommandActions.swift | 27 ++- .../Views/Main/MainContentCoordinator.swift | 6 + TablePro/Views/Main/MainContentView.swift | 2 + .../ObjectSource/ObjectSourceTabView.swift | 9 +- ...abaseTreeOutlineCoordinator+Commands.swift | 8 +- .../DatabaseTreeOutlineCoordinator+Menu.swift | 3 +- .../MaterializedViewRefreshAlert.swift | 80 +++++++ .../Menu/DatabaseTreeMenuContext.swift | 2 + .../Sidebar/Menu/DatabaseTreeMenuSpec.swift | 44 +++- .../Sidebar/Menu/SidebarMenuCommand.swift | 3 + .../Views/Sidebar/ObjectCommentSheet.swift | 157 +++++++++++++ .../TableStructureView+DataLoading.swift | 16 +- .../Core/Menu/MainMenuBuilderTests.swift | 39 ++++ .../Models/DatabaseObjectToolsTests.swift | 217 ++++++++++++++++++ .../Plugins/PostgreSQLRelationSQLTests.swift | 131 +++++++++++ .../PostgreSQLViewDefinitionTests.swift | 189 +++++++++++++++ .../Sidebar/DatabaseTreeMenuSpecTests.swift | 98 +++++++- docs/databases/postgresql.mdx | 8 + docs/development/plugin-development.mdx | 2 +- docs/development/plugin-registry.mdx | 4 +- docs/features/table-operations.mdx | 6 + docs/features/table-structure.mdx | 2 + project.yml | 2 + scripts/check-postgres-matview-refresh.sh | 147 ++++++++++++ 94 files changed, 2496 insertions(+), 153 deletions(-) create mode 100644 Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Views.swift create mode 100644 Plugins/PostgreSQLDriverPlugin/PostgreSQLRelationSQL.swift create mode 100644 Plugins/PostgreSQLDriverPlugin/PostgreSQLViewDefinition.swift create mode 100644 Plugins/TableProPluginKit/PluginConcurrentRefreshAvailability.swift create mode 100644 TablePro/Core/Database/DatabaseObjectToolEligibility.swift create mode 100644 TablePro/Core/Database/MaterializedViewRefreshing.swift create mode 100644 TablePro/Core/Database/ObjectCommentEditing.swift create mode 100644 TablePro/Models/Database/DatabaseObjectTarget.swift create mode 100644 TablePro/Models/Database/MaterializedViewRefreshPrompt.swift create mode 100644 TablePro/Models/Database/ObjectCommentDraft.swift create mode 100644 TablePro/Views/Main/Extensions/MainContentCoordinator+DatabaseObjectTools.swift create mode 100644 TablePro/Views/Sidebar/MaterializedViewRefreshAlert.swift create mode 100644 TablePro/Views/Sidebar/ObjectCommentSheet.swift create mode 100644 TableProTests/Models/DatabaseObjectToolsTests.swift create mode 100644 TableProTests/Plugins/PostgreSQLRelationSQLTests.swift create mode 100644 TableProTests/Plugins/PostgreSQLViewDefinitionTests.swift create mode 100755 scripts/check-postgres-matview-refresh.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index f8ee74bf86..84212484b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Warnings in the SQL editor for full-width punctuation, curly quotes and non-ASCII spaces. (#2717) - Highlight rules that color data grid rows or cells by value. (#2723) - **Encoding** option for MySQL and MariaDB connections, with **UTF-8 via Latin 1** for databases written through a Latin 1 client. (#2725) +- **Refresh Materialized View…** on PostgreSQL, with a concurrent refresh where the view qualifies. (#2726) +- **Show DDL** and **Copy DDL** for views and materialized views. (#2726) +- **Edit Comment…** for PostgreSQL tables, views, materialized views and foreign tables. (#2726) - UTF-16 LE, UTF-16 BE and Windows-1252 in the SQL import encoding menu. ### Changed @@ -153,11 +156,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Garbled non-ASCII text on PostgreSQL databases not encoded in UTF-8 after `RESET ALL` or `DISCARD ALL`. - Garbled or double-encoded non-ASCII text on iOS with PostgreSQL databases not encoded in UTF-8. - Garbled non-ASCII text when restoring a PostgreSQL SQL export into a database not encoded in UTF-8. +- Display As formats and foreign key labels lost on a rename, and kept with column layouts after deleting a connection. +- PostgreSQL view definitions without `security_barrier`, `security_invoker` or the check option. (#2726) +- PostgreSQL view definitions that bind to another schema's tables when run elsewhere. (#2726) +- `CREATE TABLE` in Structure > DDL for a PostgreSQL view or materialized view. (#2726) +- **Edit View Definition** in the Database menu opening a same-named view from the browsed schema. (#2726) +- **Edit View Definition** enabled in the Database menu on a read-only connection. (#2726) +- Enum types and sequences written in front of a PostgreSQL view's DDL. (#2726) - Display As formats lost on a rename, and kept with column layouts after deleting a connection. ### Security - BigQuery Google sign-in accepting an authorization response without PKCE or a state check. +- PostgreSQL comment and password literals escaped by quote doubling alone, which a backslash can break out of. (#2726) ## [0.73.0] - 2026-09-09 diff --git a/Plugins/BeancountDriverPlugin/Info.plist b/Plugins/BeancountDriverPlugin/Info.plist index 3a80c6e3ae..506f627671 100644 --- a/Plugins/BeancountDriverPlugin/Info.plist +++ b/Plugins/BeancountDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesDatabaseTypeIds Beancount diff --git a/Plugins/BigQueryDriverPlugin/Info.plist b/Plugins/BigQueryDriverPlugin/Info.plist index ef6bb318fc..9747423174 100644 --- a/Plugins/BigQueryDriverPlugin/Info.plist +++ b/Plugins/BigQueryDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 25 + 26 diff --git a/Plugins/CSVExportPlugin/Info.plist b/Plugins/CSVExportPlugin/Info.plist index 66c614e6ed..5ae5323703 100644 --- a/Plugins/CSVExportPlugin/Info.plist +++ b/Plugins/CSVExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesExportFormatIds csv diff --git a/Plugins/CSVImportPlugin/Info.plist b/Plugins/CSVImportPlugin/Info.plist index 4e75827ae5..377e920221 100644 --- a/Plugins/CSVImportPlugin/Info.plist +++ b/Plugins/CSVImportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesImportFormatIds csv diff --git a/Plugins/CassandraDriverPlugin/Info.plist b/Plugins/CassandraDriverPlugin/Info.plist index e19d005d46..d4199c62eb 100644 --- a/Plugins/CassandraDriverPlugin/Info.plist +++ b/Plugins/CassandraDriverPlugin/Info.plist @@ -21,6 +21,6 @@ NSPrincipalClass $(PRODUCT_MODULE_NAME).CassandraPlugin TableProPluginKitVersion - 25 + 26 diff --git a/Plugins/ClickHouseDriverPlugin/Info.plist b/Plugins/ClickHouseDriverPlugin/Info.plist index b3ebb5d8e1..5fd3dd4c61 100644 --- a/Plugins/ClickHouseDriverPlugin/Info.plist +++ b/Plugins/ClickHouseDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesDatabaseTypeIds ClickHouse diff --git a/Plugins/CloudflareD1DriverPlugin/Info.plist b/Plugins/CloudflareD1DriverPlugin/Info.plist index ef6bb318fc..9747423174 100644 --- a/Plugins/CloudflareD1DriverPlugin/Info.plist +++ b/Plugins/CloudflareD1DriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 25 + 26 diff --git a/Plugins/CloudflareR2SQLDriverPlugin/Info.plist b/Plugins/CloudflareR2SQLDriverPlugin/Info.plist index 5d91dcfa09..158b1c8cb3 100644 --- a/Plugins/CloudflareR2SQLDriverPlugin/Info.plist +++ b/Plugins/CloudflareR2SQLDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesDatabaseTypeIds Cloudflare R2 SQL diff --git a/Plugins/DamengDriverPlugin/Info.plist b/Plugins/DamengDriverPlugin/Info.plist index 721e8b6803..6880e4bcd5 100644 --- a/Plugins/DamengDriverPlugin/Info.plist +++ b/Plugins/DamengDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesDatabaseTypeIds Dameng diff --git a/Plugins/DuckDBDriverPlugin/Info.plist b/Plugins/DuckDBDriverPlugin/Info.plist index 0b0de66a10..9954682bff 100644 --- a/Plugins/DuckDBDriverPlugin/Info.plist +++ b/Plugins/DuckDBDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 25 + 26 diff --git a/Plugins/DynamoDBDriverPlugin/Info.plist b/Plugins/DynamoDBDriverPlugin/Info.plist index ef6bb318fc..9747423174 100644 --- a/Plugins/DynamoDBDriverPlugin/Info.plist +++ b/Plugins/DynamoDBDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 25 + 26 diff --git a/Plugins/ElasticsearchDriverPlugin/Info.plist b/Plugins/ElasticsearchDriverPlugin/Info.plist index 54f69d38bc..97d99a21be 100644 --- a/Plugins/ElasticsearchDriverPlugin/Info.plist +++ b/Plugins/ElasticsearchDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.53.0 TableProPluginKitVersion - 25 + 26 diff --git a/Plugins/EtcdDriverPlugin/Info.plist b/Plugins/EtcdDriverPlugin/Info.plist index ef6bb318fc..9747423174 100644 --- a/Plugins/EtcdDriverPlugin/Info.plist +++ b/Plugins/EtcdDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 25 + 26 diff --git a/Plugins/HTMLExportPlugin/Info.plist b/Plugins/HTMLExportPlugin/Info.plist index 7d3d412288..0e74ce63e0 100644 --- a/Plugins/HTMLExportPlugin/Info.plist +++ b/Plugins/HTMLExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesExportFormatIds html diff --git a/Plugins/JSONExportPlugin/Info.plist b/Plugins/JSONExportPlugin/Info.plist index c2bb35e22c..a32f0751e6 100644 --- a/Plugins/JSONExportPlugin/Info.plist +++ b/Plugins/JSONExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesExportFormatIds json diff --git a/Plugins/JSONImportPlugin/Info.plist b/Plugins/JSONImportPlugin/Info.plist index 26b752a7a8..595fe71df8 100644 --- a/Plugins/JSONImportPlugin/Info.plist +++ b/Plugins/JSONImportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesImportFormatIds json diff --git a/Plugins/KafkaDriverPlugin/Info.plist b/Plugins/KafkaDriverPlugin/Info.plist index bbc26bccee..be82099e32 100644 --- a/Plugins/KafkaDriverPlugin/Info.plist +++ b/Plugins/KafkaDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesDatabaseTypeIds Kafka diff --git a/Plugins/LibSQLDriverPlugin/Info.plist b/Plugins/LibSQLDriverPlugin/Info.plist index ef6bb318fc..9747423174 100644 --- a/Plugins/LibSQLDriverPlugin/Info.plist +++ b/Plugins/LibSQLDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 25 + 26 diff --git a/Plugins/MQLExportPlugin/Info.plist b/Plugins/MQLExportPlugin/Info.plist index 6cccc9fe96..6e2ff052e2 100644 --- a/Plugins/MQLExportPlugin/Info.plist +++ b/Plugins/MQLExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesExportFormatIds mql diff --git a/Plugins/MSSQLDriverPlugin/Info.plist b/Plugins/MSSQLDriverPlugin/Info.plist index 0b0de66a10..9954682bff 100644 --- a/Plugins/MSSQLDriverPlugin/Info.plist +++ b/Plugins/MSSQLDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 25 + 26 diff --git a/Plugins/MarkdownExportPlugin/Info.plist b/Plugins/MarkdownExportPlugin/Info.plist index 409a2f52ed..e14571be83 100644 --- a/Plugins/MarkdownExportPlugin/Info.plist +++ b/Plugins/MarkdownExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesExportFormatIds md diff --git a/Plugins/MongoDBDriverPlugin/Info.plist b/Plugins/MongoDBDriverPlugin/Info.plist index 0b0de66a10..9954682bff 100644 --- a/Plugins/MongoDBDriverPlugin/Info.plist +++ b/Plugins/MongoDBDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 25 + 26 diff --git a/Plugins/MySQLDriverPlugin/Info.plist b/Plugins/MySQLDriverPlugin/Info.plist index 7f89d51299..94c4002f25 100644 --- a/Plugins/MySQLDriverPlugin/Info.plist +++ b/Plugins/MySQLDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesDatabaseTypeIds MySQL diff --git a/Plugins/OracleDriverPlugin/Info.plist b/Plugins/OracleDriverPlugin/Info.plist index 0b0de66a10..9954682bff 100644 --- a/Plugins/OracleDriverPlugin/Info.plist +++ b/Plugins/OracleDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 25 + 26 diff --git a/Plugins/ParquetExportPlugin/Info.plist b/Plugins/ParquetExportPlugin/Info.plist index a44a0be525..a3dbea458f 100644 --- a/Plugins/ParquetExportPlugin/Info.plist +++ b/Plugins/ParquetExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesExportFormatIds parquet diff --git a/Plugins/PostgreSQLDriverPlugin/Info.plist b/Plugins/PostgreSQLDriverPlugin/Info.plist index de1560f729..1a62532486 100644 --- a/Plugins/PostgreSQLDriverPlugin/Info.plist +++ b/Plugins/PostgreSQLDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesDatabaseTypeIds PostgreSQL diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift b/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift index 5a606609c5..265d120aef 100644 --- a/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift +++ b/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift @@ -27,6 +27,7 @@ final class LibPQDriverCore: @unchecked Sendable { var serverVersion: String? { libpqConnection?.serverVersion() } var serverVersionNumber: Int32 { libpqConnection?.serverVersionNumber() ?? 0 } + var isInsideTransactionBlock: Bool { libpqConnection?.isInsideTransactionBlock ?? false } init( config: DriverConnectionConfig, diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift b/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift index df6e9dc16c..eb7958f0ef 100644 --- a/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift +++ b/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift @@ -514,6 +514,22 @@ final class LibPQPluginConnection: @unchecked Sendable { _cachedServerVersionNumber } + /// Whether the session is inside a transaction block, including one a failed statement has + /// aborted. A statement sent now joins that block rather than running on its own. + /// + /// Read on the connection's own queue, like every other libpq call here: one `PGconn` may not + /// be used from two threads at once, and the lock alone guards the pointer rather than the call. + var isInsideTransactionBlock: Bool { + stateLock.lock() + let conn = self.conn + stateLock.unlock() + guard let conn else { return false } + return queue.sync { + let status = PQtransactionStatus(conn) + return status == PQTRANS_INTRANS || status == PQTRANS_INERROR + } + } + func currentDatabase() -> String { database } diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+PrincipalSQL.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+PrincipalSQL.swift index 1d7654d415..f1b84061e2 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+PrincipalSQL.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+PrincipalSQL.swift @@ -13,7 +13,7 @@ extension PostgreSQLPluginDriver { options.append(contentsOf: attributeKeywords(definition.attributes)) if let password = definition.password, !password.isEmpty { - options.append("PASSWORD '\(escapeStringLiteral(password))'") + options.append("PASSWORD \(PostgreSQLObjectQueries.quoteLiteral(password))") } if let limit = definition.connectionLimit { options.append("CONNECTION LIMIT \(limit)") @@ -24,7 +24,7 @@ extension PostgreSQLPluginDriver { "GRANT \(quoteIdentifier($0)) TO \(role)" }) if let comment = definition.comment, !comment.isEmpty { - statements.append("COMMENT ON ROLE \(role) IS '\(escapeStringLiteral(comment))'") + statements.append("COMMENT ON ROLE \(role) IS \(PostgreSQLRelationSQL.commentValue(comment))") } return statements } @@ -51,9 +51,7 @@ extension PostgreSQLPluginDriver { statements.append(contentsOf: membershipStatements(old: old, new: new, role: role)) if old.comment != new.comment { - let comment = new.comment ?? "" - let value = comment.isEmpty ? "NULL" : "'\(escapeStringLiteral(comment))'" - statements.append("COMMENT ON ROLE \(role) IS \(value)") + statements.append("COMMENT ON ROLE \(role) IS \(PostgreSQLRelationSQL.commentValue(new.comment))") } if old.ref.name != new.ref.name { statements.append("ALTER ROLE \(role) RENAME TO \(quoteIdentifier(new.ref.name))") @@ -63,7 +61,7 @@ extension PostgreSQLPluginDriver { func generateSetPasswordSQL(principal: PluginPrincipalRef, password: String) -> [String]? { let role = quoteIdentifier(principal.name) - return ["ALTER ROLE \(role) WITH PASSWORD '\(escapeStringLiteral(password))'"] + return ["ALTER ROLE \(role) WITH PASSWORD \(PostgreSQLObjectQueries.quoteLiteral(password))"] } func generateDropPrincipalSQL( diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Views.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Views.swift new file mode 100644 index 0000000000..dc9f8cc24d --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Views.swift @@ -0,0 +1,91 @@ +// +// PostgreSQLPluginDriver+Views.swift +// PostgreSQLDriverPlugin +// + +import Foundation +import TableProPluginKit + +extension PostgreSQLPluginDriver { + /// `pg_views` and `pg_matviews` return the query alone, so the definition this used to build + /// from them lost the view's options and check option, and read the body under the connection's + /// own search path. The statement is now rebuilt from the catalog with every name qualified. + func fetchViewDefinition(view: String, schema: String?) async throws -> String { + let resolvedSchema = schema ?? core.currentSchema + let query = PostgreSQLViewDefinition.catalogQuery(name: view, schema: resolvedSchema) + let result = try await executeQualifiedRead(query) + guard let row = result.rows.first, + let catalogRow = PostgreSQLViewDefinition.parse(row: row.map(\.asText)) + else { + throw LibPQPluginError(message: "Failed to fetch definition for view '\(view)'", sqlState: nil, detail: nil) + } + return PostgreSQLViewDefinition.statement(name: view, schema: resolvedSchema, row: catalogRow) + } + + func objectCommentStatement(name: String, objectType: String, schema: String?, comment: String?) -> String? { + PostgreSQLRelationSQL.commentStatement( + name: name, + schema: schema ?? core.currentSchema, + objectType: objectType, + comment: comment + ) + } + + func refreshMaterializedViewStatement(name: String, schema: String?, concurrently: Bool) -> String? { + PostgreSQLRelationSQL.refreshStatement( + name: name, + schema: schema ?? core.currentSchema, + concurrently: concurrently + ) + } + + func concurrentRefreshAvailability( + materializedView: String, + schema: String? + ) async throws -> PluginConcurrentRefreshAvailability? { + let query = PostgreSQLRelationSQL.concurrentRefreshQuery( + name: materializedView, + schema: schema ?? core.currentSchema + ) + let result = try await execute(query: query) + guard let row = result.rows.first, row.count >= 2 else { + throw LibPQPluginError( + message: "Materialized view '\(materializedView)' was not found", + sqlState: nil, + detail: nil + ) + } + return PostgreSQLRelationSQL.concurrentRefreshAvailability( + isPopulated: row[0].asText == "1", + hasUsableUniqueIndex: row[1].asText == "1" + ) + } + + /// Reads with `search_path` emptied so every name the server deparses comes back qualified. + /// + /// A pooled connection is never inside a transaction, and there the prefix and the read form + /// one implicit transaction that restores the path as it ends. PGlite has no pool, so its reads + /// share the connection a query tab may have left inside `BEGIN`; the prefix would then outlive + /// the read and every later unqualified name in that tab would fail. A savepoint scopes it there. + private func executeQualifiedRead(_ query: String) async throws -> PluginQueryResult { + let statement = PostgreSQLViewDefinition.qualifiedReadPrefix + query + guard core.isInsideTransactionBlock else { + return try await execute(query: statement) + } + let savepoint = "tablepro_qualified_read" + _ = try await execute(query: "SAVEPOINT \(savepoint)") + /// The rollback is best effort on both paths. It undoes a `SET LOCAL` in a transaction that + /// is about to end anyway, so a connection lost between the read and the rollback has taken + /// the whole transaction with it, and reporting that instead of the definition just read + /// would lose the answer to a failure that no longer matters. + let release = "ROLLBACK TO SAVEPOINT \(savepoint); RELEASE SAVEPOINT \(savepoint)" + do { + let result = try await execute(query: statement) + _ = try? await execute(query: release) + return result + } catch { + _ = try? await execute(query: release) + throw error + } + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift index 937d58b4e7..62322c1d18 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift @@ -529,7 +529,8 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { WHEN a.atthasdef \(defaultGuard) THEN ' DEFAULT ' || pg_get_expr(d.adbin, d.adrelid) ELSE '' - END + END, + c.relkind::text FROM pg_attribute a JOIN pg_class c ON c.oid = a.attrelid JOIN pg_namespace n ON n.oid = c.relnamespace @@ -559,6 +560,14 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { let (cols, cons) = try await (columnsResult, constraintsResult) + /// `pg_attribute` covers views and materialized views as well as tables, so a view reached + /// here as a `CREATE TABLE` of its columns. The Structure tab's DDL and every other caller + /// that asks for a relation's DDL by name get the view's own statement instead. + if let relkind = cols.rows.first?[safe: 1]?.asText, + PostgreSQLViewDefinition.kind(forRelkind: relkind) != nil { + return try await fetchViewDefinition(view: table, schema: resolvedSchema) + } + let columnDefs = cols.rows.compactMap { $0[0].asText } guard !columnDefs.isEmpty else { throw LibPQPluginError(message: "Failed to fetch DDL for table '\(table)'", sqlState: nil, detail: nil) @@ -601,37 +610,6 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { return result.rows.compactMap { $0[0].asText } } - func fetchViewDefinition(view: String, schema: String?) async throws -> String { - let schemaLiteral = escapeLiteral(schema ?? core.currentSchema) - let query = """ - SELECT 'CREATE OR REPLACE VIEW ' || quote_ident(schemaname) || '.' || quote_ident(viewname) || ' AS ' || E'\\n' || definition AS ddl - FROM pg_views - WHERE viewname = '\(escapeLiteral(view))' - AND schemaname = '\(schemaLiteral)' - """ - let result = try await execute(query: query) - if let firstRow = result.rows.first, let ddl = firstRow[0].asText { - return ddl - } - - /// `pg_views` excludes materialized views, so a name that is one reaches here with no rows. - /// Falling through to `fetchTableDDL` instead, which succeeds on a matview because - /// `pg_class` and `pg_attribute` both cover one, put a `CREATE TABLE` in the dump under a - /// `DROP MATERIALIZED VIEW` and restored an empty ordinary table. - let matview = """ - SELECT 'CREATE MATERIALIZED VIEW ' || quote_ident(schemaname) || '.' || quote_ident(matviewname) - || ' AS ' || E'\\n' || definition AS ddl - FROM pg_matviews - WHERE matviewname = '\(escapeLiteral(view))' - AND schemaname = '\(schemaLiteral)' - """ - let matviewResult = try await execute(query: matview) - guard let row = matviewResult.rows.first, let ddl = row[0].asText else { - throw LibPQPluginError(message: "Failed to fetch definition for view '\(view)'", sqlState: nil, detail: nil) - } - return ddl - } - func fetchTableMetadata(table: String, schema: String?) async throws -> PluginTableMetadata { let schemaLiteral = escapeLiteral(schema ?? core.currentSchema) let query = """ @@ -730,6 +708,11 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { } } + /// The kinds `fetchTableDDL` writes a `CREATE TABLE` for. A view's DDL is its own statement, so + /// the enum types and sequences its columns happen to use are not a preamble to it: written in + /// front of a `CREATE VIEW` they recreated objects the view only reads. + private static let relkindsCreatedByTableDDL = "('r', 'p', 'f')" + func fetchDependentTypes(table: String, schema: String?) async throws -> [(name: String, labels: [String])] { let safeTable = escapeLiteral(table) let schemaLiteral = escapeLiteral(schema ?? core.currentSchema) @@ -743,6 +726,7 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { JOIN pg_enum e ON e.enumtypid = t.oid WHERE c.relname = '\(safeTable)' AND n.nspname = '\(schemaLiteral)' + AND c.relkind IN \(Self.relkindsCreatedByTableDDL) AND a.attnum > 0 AND NOT a.attisdropped GROUP BY t.typname @@ -778,6 +762,7 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { AND pg_get_expr(ad.adbin, ad.adrelid) LIKE '%' || quote_ident(s.sequencename) || '%' WHERE c.relname = '\(safeTable)' AND n.nspname = '\(schemaLiteral)' + AND c.relkind IN \(Self.relkindsCreatedByTableDDL) AND pg_get_expr(ad.adbin, ad.adrelid) LIKE '%nextval%' """ let result = try await execute(query: query) @@ -1317,7 +1302,7 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { } if let newComment = newColumn.comment, !newComment.isEmpty, newColumn.comment != oldColumn.comment { - stmts.append("COMMENT ON COLUMN \(qt).\(colName) IS '\(escapeLiteral(newComment))'") + stmts.append("COMMENT ON COLUMN \(qt).\(colName) IS \(PostgreSQLRelationSQL.commentValue(newComment))") } else if oldColumn.comment != nil && (newColumn.comment == nil || newColumn.comment?.isEmpty == true) { stmts.append("COMMENT ON COLUMN \(qt).\(colName) IS NULL") } diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLRelationSQL.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLRelationSQL.swift new file mode 100644 index 0000000000..ee84077a7c --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLRelationSQL.swift @@ -0,0 +1,95 @@ +// +// PostgreSQLRelationSQL.swift +// PostgreSQLDriverPlugin +// +// Statements that act on one table-like relation by name: comments and materialized view +// refreshes. Pure, so it is testable without a server. +// + +import Foundation +import TableProPluginKit + +public enum PostgreSQLRelationSQL { + /// The keyword `COMMENT ON` needs for each relation kind. PostgreSQL checks it against the + /// relation's `relkind` and refuses a mismatch: `COMMENT ON TABLE` on a view fails with + /// "is not a table", and `COMMENT ON VIEW` on a materialized view with "is not a view". + public static func commentKeyword(forObjectType objectType: String) -> String? { + switch objectType.uppercased() { + case "TABLE", "PARTITIONED TABLE": + return "TABLE" + case "VIEW": + return "VIEW" + case "MATERIALIZED VIEW": + return "MATERIALIZED VIEW" + case "FOREIGN TABLE": + return "FOREIGN TABLE" + default: + return nil + } + } + + /// `COMMENT` takes a literal and nothing else, so the value is quoted here rather than bound. The + /// quoting reads the same whatever `standard_conforming_strings` is set to. + public static func commentStatement( + name: String, + schema: String, + objectType: String, + comment: String? + ) -> String? { + guard let keyword = commentKeyword(forObjectType: objectType) else { return nil } + let target = PostgreSQLObjectQueries.qualifiedName(schema: schema, name: name) + return "COMMENT ON \(keyword) \(target) IS \(commentValue(comment))" + } + + public static func commentValue(_ comment: String?) -> String { + guard let comment, !comment.isEmpty else { return "NULL" } + return PostgreSQLObjectQueries.quoteLiteral(comment) + } + + public static func refreshStatement(name: String, schema: String, concurrently: Bool) -> String { + let target = PostgreSQLObjectQueries.qualifiedName(schema: schema, name: name) + return concurrently + ? "REFRESH MATERIALIZED VIEW CONCURRENTLY \(target)" + : "REFRESH MATERIALIZED VIEW \(target)" + } + + /// A concurrent refresh diffs the new result against the stored rows through a unique index, + /// so it needs one the server can use for every row: valid, immediate, on plain columns and + /// without a predicate. It also needs rows to diff against, which an unpopulated view lacks. + /// Measured on PostgreSQL 17 against every index shape `scripts/check-postgres-matview-refresh.sh` + /// builds; that script re-checks the predicate against a live server. + public static func concurrentRefreshQuery(name: String, schema: String) -> String { + """ + SELECT + CASE WHEN c.relispopulated THEN 1 ELSE 0 END, + CASE WHEN EXISTS ( + SELECT 1 + FROM pg_catalog.pg_index i + JOIN pg_catalog.pg_class ic ON ic.oid = i.indexrelid + JOIN pg_catalog.pg_am am ON am.oid = ic.relam + WHERE i.indrelid = c.oid + AND i.indisunique + AND i.indimmediate + AND i.indisvalid + AND i.indpred IS NULL + AND i.indexprs IS NULL + AND am.amname = 'btree' + ) THEN 1 ELSE 0 END + FROM pg_catalog.pg_class c + JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace + WHERE c.relkind = 'm' + AND n.nspname = \(PostgreSQLObjectQueries.quoteLiteral(schema)) + AND c.relname = \(PostgreSQLObjectQueries.quoteLiteral(name)) + """ + } + + /// Population is checked first: an unpopulated view is refused even when its index is fine, and + /// the fix the user needs is a plain refresh, not a new index. + public static func concurrentRefreshAvailability( + isPopulated: Bool, + hasUsableUniqueIndex: Bool + ) -> PluginConcurrentRefreshAvailability { + guard isPopulated else { return .requiresPopulatedView } + return hasUsableUniqueIndex ? .available : .requiresUniqueIndex + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLViewDefinition.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLViewDefinition.swift new file mode 100644 index 0000000000..bdb9656201 --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLViewDefinition.swift @@ -0,0 +1,169 @@ +// +// PostgreSQLViewDefinition.swift +// PostgreSQLDriverPlugin +// +// Rebuilds the CREATE statement of a view or materialized view from the catalog. Pure, so it is +// testable without a server. +// + +import Foundation + +public enum PostgreSQLViewDefinition { + public enum Kind: Equatable, Sendable { + case view + case materializedView + } + + /// Everything the statement is rebuilt from. `pg_get_viewdef` returns the query alone, so the + /// view's options, its check option, and a materialized view's access method and tablespace + /// each come from their own catalog column. + public struct CatalogRow: Equatable, Sendable { + public let kind: Kind + public let query: String + public let options: [String] + public let accessMethod: String? + public let tablespace: String? + + public init(kind: Kind, query: String, options: [String], accessMethod: String?, tablespace: String?) { + self.kind = kind + self.query = query + self.options = options + self.accessMethod = accessMethod + self.tablespace = tablespace + } + } + + /// Run with `search_path` emptied first (see `qualifiedReadPrefix`). `pg_get_viewdef` writes a + /// table name bare whenever the reading session could resolve it without its schema, and the + /// scoped connection this runs on has its path set to the view's own schema, so the body came + /// back naming `orders` rather than `sales.orders`. Run anywhere else, that text silently bound + /// to whichever `orders` the new session found first. + public static func catalogQuery(name: String, schema: String) -> String { + """ + SELECT + c.relkind::text, + pg_catalog.pg_get_viewdef(c.oid, true), + pg_catalog.array_to_json(c.reloptions)::text, + am.amname::text, + ts.spcname::text + FROM pg_catalog.pg_class c + JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace + LEFT JOIN pg_catalog.pg_am am ON am.oid = c.relam + LEFT JOIN pg_catalog.pg_tablespace ts ON ts.oid = c.reltablespace + WHERE c.relkind IN ('v', 'm') + AND n.nspname = \(PostgreSQLObjectQueries.quoteLiteral(schema)) + AND c.relname = \(PostgreSQLObjectQueries.quoteLiteral(name)) + """ + } + + /// `SET LOCAL` lasts only as long as the transaction it runs in. Sent in the same query string + /// as the read, the pair is one implicit transaction, so the path is back to what it was as + /// soon as the read returns. Inside a transaction the caller already holds, it would last until + /// that transaction ends, which is why the driver wraps the read in a savepoint there. + public static let qualifiedReadPrefix = "SET LOCAL search_path = ''; " + + public static func parse(row: [String?]) -> CatalogRow? { + guard row.count >= 5, + let relkind = row[0], + let query = row[1], + let kind = kind(forRelkind: relkind) + else { return nil } + return CatalogRow( + kind: kind, + query: query, + options: options(fromJSON: row[2]), + accessMethod: row[3]?.nilIfBlank, + tablespace: row[4]?.nilIfBlank + ) + } + + public static func kind(forRelkind relkind: String) -> Kind? { + switch relkind { + case "v": return .view + case "m": return .materializedView + default: return nil + } + } + + /// Read as JSON rather than as array text, because an option value may itself hold a comma or + /// a quote and splitting `{a=1,b=2}` on commas would cut it in two. + public static func options(fromJSON json: String?) -> [String] { + guard let data = json?.data(using: .utf8), + let decoded = try? JSONDecoder().decode([String].self, from: data) + else { return [] } + return decoded + } + + public static func statement(name: String, schema: String, row: CatalogRow) -> String { + let target = PostgreSQLObjectQueries.qualifiedName(schema: schema, name: name) + let body = trimmedQuery(row.query) + switch row.kind { + case .view: + return viewStatement(target: target, body: body, options: row.options) + case .materializedView: + return materializedViewStatement(target: target, body: body, row: row) + } + } + + /// `CREATE OR REPLACE VIEW` resets every option the statement leaves out, so running a + /// definition that dropped `security_barrier`, `security_invoker` or the check option quietly + /// turned a restricted view into an unrestricted one. The check option is stored as a + /// reloption but written as its own clause after the query, the way `pg_dump` writes it. + private static func viewStatement(target: String, body: String, options: [String]) -> String { + let parsed = options.map(splitOption) + let checkOption = parsed.first { $0.name == "check_option" }?.value + let storage = parsed.filter { $0.name != "check_option" } + var header = "CREATE OR REPLACE VIEW \(target)" + if let withClause = withClause(storage) { + header += " \(withClause)" + } + var statement = "\(header) AS\n\(body)" + if let checkOption, !checkOption.isEmpty { + statement += "\n WITH \(checkOption.uppercased()) CHECK OPTION" + } + return statement + ";" + } + + /// The access method is written only when it is not the default, because `USING` does not + /// exist before PostgreSQL 12 and `heap` is what every server creates without it. + private static func materializedViewStatement(target: String, body: String, row: CatalogRow) -> String { + var header = "CREATE MATERIALIZED VIEW \(target)" + if let accessMethod = row.accessMethod, accessMethod != "heap" { + header += " USING \(PostgreSQLObjectQueries.quoteIdentifier(accessMethod))" + } + if let withClause = withClause(row.options.map(splitOption)) { + header += " \(withClause)" + } + if let tablespace = row.tablespace { + header += " TABLESPACE \(PostgreSQLObjectQueries.quoteIdentifier(tablespace))" + } + return "\(header) AS\n\(body);" + } + + private static func withClause(_ options: [(name: String, value: String)]) -> String? { + guard !options.isEmpty else { return nil } + let rendered = options.map { "\($0.name)=\(PostgreSQLObjectQueries.quoteLiteral($0.value))" } + return "WITH (\(rendered.joined(separator: ", ")))" + } + + private static func splitOption(_ option: String) -> (name: String, value: String) { + guard let separator = option.firstIndex(of: "=") else { return (option, "") } + return (String(option[.. String { + var trimmed = Substring(query) + while let last = trimmed.last, last.isWhitespace || last == ";" { + trimmed = trimmed.dropLast() + } + return String(trimmed) + } +} + +private extension String { + var nilIfBlank: String? { + trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ? nil : self + } +} diff --git a/Plugins/RedisDriverPlugin/Info.plist b/Plugins/RedisDriverPlugin/Info.plist index 5f674c5304..4a492e698e 100644 --- a/Plugins/RedisDriverPlugin/Info.plist +++ b/Plugins/RedisDriverPlugin/Info.plist @@ -21,7 +21,7 @@ NSPrincipalClass $(PRODUCT_MODULE_NAME).RedisPlugin TableProPluginKitVersion - 25 + 26 TableProProvidesDatabaseTypeIds Redis diff --git a/Plugins/SQLExportPlugin/Info.plist b/Plugins/SQLExportPlugin/Info.plist index e867e0845b..68e02581a9 100644 --- a/Plugins/SQLExportPlugin/Info.plist +++ b/Plugins/SQLExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesExportFormatIds sql diff --git a/Plugins/SQLImportPlugin/Info.plist b/Plugins/SQLImportPlugin/Info.plist index a8fc462857..09e7f15ffc 100644 --- a/Plugins/SQLImportPlugin/Info.plist +++ b/Plugins/SQLImportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesImportFormatIds sql diff --git a/Plugins/SQLiteDriverPlugin/Info.plist b/Plugins/SQLiteDriverPlugin/Info.plist index 6f3dc93304..b925ecd541 100644 --- a/Plugins/SQLiteDriverPlugin/Info.plist +++ b/Plugins/SQLiteDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesDatabaseTypeIds SQLite diff --git a/Plugins/SnowflakeDriverPlugin/Info.plist b/Plugins/SnowflakeDriverPlugin/Info.plist index fe6251ddc5..c329f1bc3b 100644 --- a/Plugins/SnowflakeDriverPlugin/Info.plist +++ b/Plugins/SnowflakeDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.48.0 TableProPluginKitVersion - 25 + 26 diff --git a/Plugins/SpannerDriverPlugin/Info.plist b/Plugins/SpannerDriverPlugin/Info.plist index f39f4e4f74..8085ee8319 100644 --- a/Plugins/SpannerDriverPlugin/Info.plist +++ b/Plugins/SpannerDriverPlugin/Info.plist @@ -5,7 +5,7 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 25 + 26 TableProProvidesDatabaseTypeIds Spanner diff --git a/Plugins/SurrealDBDriverPlugin/Info.plist b/Plugins/SurrealDBDriverPlugin/Info.plist index 6b07b3e92d..c01f11f50c 100644 --- a/Plugins/SurrealDBDriverPlugin/Info.plist +++ b/Plugins/SurrealDBDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesDatabaseTypeIds SurrealDB diff --git a/Plugins/TableProPluginKit/PluginConcurrentRefreshAvailability.swift b/Plugins/TableProPluginKit/PluginConcurrentRefreshAvailability.swift new file mode 100644 index 0000000000..c097e3b1b1 --- /dev/null +++ b/Plugins/TableProPluginKit/PluginConcurrentRefreshAvailability.swift @@ -0,0 +1,17 @@ +// +// PluginConcurrentRefreshAvailability.swift +// TableProPluginKit +// + +import Foundation + +/// Whether one materialized view can be refreshed without blocking the sessions reading it. +/// +/// The answer depends on the view, not only on the engine: PostgreSQL refuses a concurrent refresh +/// of a view that has no usable unique index or has never been populated, and the prompt says which +/// rather than offering an option the server will reject. +public enum PluginConcurrentRefreshAvailability: String, Sendable, Equatable { + case available + case requiresUniqueIndex + case requiresPopulatedView +} diff --git a/Plugins/TableProPluginKit/PluginDatabaseDriver.swift b/Plugins/TableProPluginKit/PluginDatabaseDriver.swift index 98ff627810..a386a7c258 100644 --- a/Plugins/TableProPluginKit/PluginDatabaseDriver.swift +++ b/Plugins/TableProPluginKit/PluginDatabaseDriver.swift @@ -337,6 +337,23 @@ public protocol PluginDatabaseDriver: AnyObject, Sendable { /// namespaces out and say so rather than emitting DDL the server will reject. func createSchemaStatement(name: String) -> String? + /// Sets or clears the comment on a table-like object. `objectType` is the object's type as the + /// table listing reported it, because engines that key the statement on the kind refuse the + /// wrong keyword: PostgreSQL answers `COMMENT ON TABLE` on a view with "is not a table". A nil + /// or empty comment removes it. Return nil for a kind the engine cannot comment on. + func objectCommentStatement(name: String, objectType: String, schema: String?, comment: String?) -> String? + + /// The statement that recomputes a materialized view's stored rows. Return nil where the engine + /// has no materialized views or keeps them current on its own. + func refreshMaterializedViewStatement(name: String, schema: String?, concurrently: Bool) -> String? + + /// Whether this view can be refreshed without blocking its readers. Return nil where the engine + /// has no such refresh, so the option is not offered at all. + func concurrentRefreshAvailability( + materializedView: String, + schema: String? + ) async throws -> PluginConcurrentRefreshAvailability? + // Maintenance operations (optional — return nil if not supported) func supportedMaintenanceOperations() -> [String]? func maintenanceStatements(operation: String, table: String?, schema: String?, options: [String: String]) -> [String]? @@ -777,6 +794,19 @@ public extension PluginDatabaseDriver { func foreignKeyEnableStatements() -> [String]? { nil } func createSchemaStatement(name: String) -> String? { nil } + func objectCommentStatement(name: String, objectType: String, schema: String?, comment: String?) -> String? { + nil + } + + func refreshMaterializedViewStatement(name: String, schema: String?, concurrently: Bool) -> String? { nil } + + func concurrentRefreshAvailability( + materializedView: String, + schema: String? + ) async throws -> PluginConcurrentRefreshAvailability? { + nil + } + func supportedMaintenanceOperations() -> [String]? { nil } func maintenanceStatements(operation: String, table: String?, schema: String?, options: [String: String]) -> [String]? { nil } diff --git a/Plugins/TeradataDriverPlugin/Info.plist b/Plugins/TeradataDriverPlugin/Info.plist index 0b0de66a10..9954682bff 100644 --- a/Plugins/TeradataDriverPlugin/Info.plist +++ b/Plugins/TeradataDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 25 + 26 diff --git a/Plugins/TrinoDriverPlugin/Info.plist b/Plugins/TrinoDriverPlugin/Info.plist index 0b0de66a10..9954682bff 100644 --- a/Plugins/TrinoDriverPlugin/Info.plist +++ b/Plugins/TrinoDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 25 + 26 diff --git a/Plugins/TypesenseDriverPlugin/Info.plist b/Plugins/TypesenseDriverPlugin/Info.plist index 32b33c04ab..693b19d340 100644 --- a/Plugins/TypesenseDriverPlugin/Info.plist +++ b/Plugins/TypesenseDriverPlugin/Info.plist @@ -5,7 +5,7 @@ TableProMinAppVersion 0.73.0 TableProPluginKitVersion - 25 + 26 TableProProvidesDatabaseTypeIds Typesense diff --git a/Plugins/XLSXExportPlugin/Info.plist b/Plugins/XLSXExportPlugin/Info.plist index da5eb3df35..c598c94a4e 100644 --- a/Plugins/XLSXExportPlugin/Info.plist +++ b/Plugins/XLSXExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesExportFormatIds xlsx diff --git a/Plugins/XLSXImportPlugin/Info.plist b/Plugins/XLSXImportPlugin/Info.plist index 0f1314ddaf..0777cf21ff 100644 --- a/Plugins/XLSXImportPlugin/Info.plist +++ b/Plugins/XLSXImportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesImportFormatIds xlsx diff --git a/Plugins/XMLExportPlugin/Info.plist b/Plugins/XMLExportPlugin/Info.plist index c7a610a36f..38b44294d9 100644 --- a/Plugins/XMLExportPlugin/Info.plist +++ b/Plugins/XMLExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 25 + 26 TableProProvidesExportFormatIds xml diff --git a/TablePro/Core/Database/DatabaseDriver.swift b/TablePro/Core/Database/DatabaseDriver.swift index 286c439326..bb06d0cdcf 100644 --- a/TablePro/Core/Database/DatabaseDriver.swift +++ b/TablePro/Core/Database/DatabaseDriver.swift @@ -243,6 +243,19 @@ protocol DatabaseDriver: AnyObject, Sendable { /// Generates SQL statements for a maintenance operation. func maintenanceStatements(operation: String, table: String?, options: [String: String]) -> [String]? + // MARK: - Object Comments and Materialized Views + + /// Nil for an object kind the engine cannot comment on. Takes the object's own schema, never + /// the connection's current one, because the object named may live anywhere in the tree. + func objectCommentStatement(name: String, objectType: String, schema: String?, comment: String?) -> String? + + func refreshMaterializedViewStatement(name: String, schema: String?, concurrently: Bool) -> String? + + func concurrentRefreshAvailability( + materializedView: String, + schema: String? + ) async throws -> PluginConcurrentRefreshAvailability? + // MARK: - Query Cancellation /// Cancel the currently running query, if any. @@ -552,6 +565,19 @@ extension DatabaseDriver { func supportedMaintenanceOperations() -> [String]? { nil } func maintenanceStatements(operation: String, table: String?, options: [String: String]) -> [String]? { nil } + func objectCommentStatement(name: String, objectType: String, schema: String?, comment: String?) -> String? { + nil + } + + func refreshMaterializedViewStatement(name: String, schema: String?, concurrently: Bool) -> String? { nil } + + func concurrentRefreshAvailability( + materializedView: String, + schema: String? + ) async throws -> PluginConcurrentRefreshAvailability? { + nil + } + /// Default: no schema support (MySQL/SQLite don't use schemas in the same way) func fetchSchemas() async throws -> [String] { [] } diff --git a/TablePro/Core/Database/DatabaseObjectToolEligibility.swift b/TablePro/Core/Database/DatabaseObjectToolEligibility.swift new file mode 100644 index 0000000000..b91b31bcdd --- /dev/null +++ b/TablePro/Core/Database/DatabaseObjectToolEligibility.swift @@ -0,0 +1,53 @@ +// +// DatabaseObjectToolEligibility.swift +// TablePro +// + +import Foundation + +/// Which of the per-object commands (Show DDL, Copy DDL, Refresh Materialized View, Edit Comment) +/// apply to a row. The sidebar and the menu bar ask the same functions, so the two can never offer +/// a command to a different set of objects; the sidebar omits what the menu bar disables. +enum DatabaseObjectToolEligibility { + /// What the connection's driver can do, read once per menu build rather than per item. + /// + /// Derived by asking the driver's own statement hooks, so a driver cannot declare a capability + /// it has no statement for. + struct Support: Equatable { + var canRefreshMaterializedViews = false + var commentableTypes: Set = [] + + static let none = Support() + + @MainActor + static func of(_ driver: DatabaseDriver?) -> Support { + guard let driver else { return .none } + let commentable = TableInfo.TableType.allCases.filter { type in + driver.objectCommentStatement(name: "t", objectType: type.rawValue, schema: "s", comment: nil) != nil + } + return Support( + canRefreshMaterializedViews: driver.refreshMaterializedViewStatement( + name: "t", schema: "s", concurrently: false + ) != nil, + commentableTypes: Set(commentable) + ) + } + } + + /// A view's source is its definition rather than its columns, which is what the DDL viewer + /// shows. Offered read-only too: reading a definition changes nothing. + static func canShowDDL(_ type: TableInfo.TableType?) -> Bool { + guard let type else { return false } + return DatabaseObjectKind(tableType: type) != nil + } + + static func canRefresh(_ type: TableInfo.TableType?, support: Support, isReadOnly: Bool) -> Bool { + guard !isReadOnly, type == .materializedView else { return false } + return support.canRefreshMaterializedViews + } + + static func canEditComment(_ type: TableInfo.TableType?, support: Support, isReadOnly: Bool) -> Bool { + guard !isReadOnly, let type else { return false } + return support.commentableTypes.contains(type) + } +} diff --git a/TablePro/Core/Database/MaterializedViewRefreshing.swift b/TablePro/Core/Database/MaterializedViewRefreshing.swift new file mode 100644 index 0000000000..7179168faa --- /dev/null +++ b/TablePro/Core/Database/MaterializedViewRefreshing.swift @@ -0,0 +1,55 @@ +// +// MaterializedViewRefreshing.swift +// TablePro +// +// Recomputes a materialized view's rows through the execution gate. +// + +import Combine +import Foundation +import TableProPluginKit + +@MainActor +enum MaterializedViewRefreshing { + /// Nil where the engine has no refresh that leaves readers alone, so the prompt offers no + /// option at all rather than one that is always off. + static func concurrentRefreshAvailability( + of target: DatabaseObjectTarget + ) async throws -> PluginConcurrentRefreshAvailability? { + let name = target.name + let schema = target.schema + return try await DatabaseManager.shared.withMetadataDriver(scope: target.scope) { driver in + try await driver.concurrentRefreshAvailability(materializedView: name, schema: schema) + } + } + + /// Runs on its own connection wherever the engine has one to give, never inside a transaction a + /// query tab left open: a plain refresh holds an exclusive lock on the view until the + /// transaction it runs in ends, which inside the user's would be until they committed. + static func refresh( + _ target: DatabaseObjectTarget, + concurrently: Bool, + connection: DatabaseConnection, + gate: any ExecutionGate = ExecutionGateProvider.shared + ) async throws { + guard let driver = DatabaseManager.shared.driver(for: connection.id) else { + throw DatabaseObjectCommandError.notConnected + } + guard let sql = driver.refreshMaterializedViewStatement( + name: target.name, + schema: target.schema, + concurrently: concurrently + ) else { + throw DatabaseObjectCommandError.unsupported + } + try await DatabaseObjectCommandRunner.run( + sql, + on: target, + connection: connection, + kind: .maintenance, + operationDescription: String(localized: "Refresh Materialized View"), + gate: gate + ) + AppCommands.shared.objectChanged.send(target.change(.rows)) + } +} diff --git a/TablePro/Core/Database/ObjectCommentEditing.swift b/TablePro/Core/Database/ObjectCommentEditing.swift new file mode 100644 index 0000000000..bbe40db341 --- /dev/null +++ b/TablePro/Core/Database/ObjectCommentEditing.swift @@ -0,0 +1,127 @@ +// +// ObjectCommentEditing.swift +// TablePro +// +// Sets or clears the comment on a table, view, materialized view or foreign table through the +// execution gate. +// + +import Combine +import Foundation +import TableProPluginKit + +enum DatabaseObjectCommandError: LocalizedError, Equatable { + case notConnected + case unsupported + case denied(String) + + var errorDescription: String? { + switch self { + case .notConnected: String(localized: "Not connected to database") + case .unsupported: String(localized: "This database cannot run this command on this object") + case let .denied(reason): reason + } + } +} + +@MainActor +enum ObjectCommentEditing { + /// The current comment, read fresh rather than taken from the sidebar's listing, which may + /// predate a change made in another window or another app. + static func currentComment(of target: DatabaseObjectTarget) async throws -> String? { + let name = target.name + let metadata = try await DatabaseManager.shared.withMetadataDriver(scope: target.scope) { driver in + try await driver.fetchTableMetadata(tableName: name) + } + return metadata.comment + } + + static func statement(for comment: String?, on target: DatabaseObjectTarget, driver: DatabaseDriver) -> String? { + driver.objectCommentStatement( + name: target.name, + objectType: target.type.rawValue, + schema: target.schema, + comment: comment + ) + } + + /// Runs on the schema change route, like every other statement the app writes on the user's + /// behalf: on the session driver it would join a transaction a query tab left open and be + /// undone by that tab's rollback. + static func setComment( + _ comment: String?, + on target: DatabaseObjectTarget, + connection: DatabaseConnection, + gate: any ExecutionGate = ExecutionGateProvider.shared + ) async throws { + guard let driver = DatabaseManager.shared.driver(for: connection.id) else { + throw DatabaseObjectCommandError.notConnected + } + guard let sql = statement(for: comment, on: target, driver: driver) else { + throw DatabaseObjectCommandError.unsupported + } + try await DatabaseObjectCommandRunner.run( + sql, + on: target, + connection: connection, + kind: .schemaMutation, + operationDescription: String(localized: "Edit Comment"), + gate: gate + ) + AppCommands.shared.objectChanged.send(target.change(.comment)) + } +} + +/// The part every object command shares: authorize, run on a lease no Stop can reach, record it. +@MainActor +enum DatabaseObjectCommandRunner { + static func run( + _ sql: String, + on target: DatabaseObjectTarget, + connection: DatabaseConnection, + kind: OperationKind, + operationDescription: String, + gate: any ExecutionGate + ) async throws { + let decision = await gate.authorize( + OperationRequest( + connectionId: connection.id, + databaseType: connection.type, + sql: sql, + kind: kind, + caller: .userInterface, + capabilities: .interactiveUser, + operationDescription: operationDescription + ) + ) + guard case .authorized = decision else { + throw DatabaseObjectCommandError.denied( + decision.deniedReason ?? String(localized: "Operation not permitted") + ) + } + + let scope = target.scope + let startedAt = Date() + try await DatabaseManager.shared.withScopedDriver( + scope: scope, + route: DatabaseManager.shared.schemaChangeRoute(for: scope), + cancellation: .protectedWrite + ) { driver in + _ = try await driver.execute(query: sql) + } + + await DatabaseManager.shared.historyRecorder.record( + QueryHistoryRecordRequest( + query: sql, + connectionId: connection.id, + databaseName: scope.database, + databaseType: connection.type, + schemaName: scope.schema, + source: .structureDDL, + executionTime: Date().timeIntervalSince(startedAt), + rowCount: -1, + wasSuccessful: true + ) + ) + } +} diff --git a/TablePro/Core/Database/TableDDLComposer.swift b/TablePro/Core/Database/TableDDLComposer.swift index bd3438ee58..ede092bda1 100644 --- a/TablePro/Core/Database/TableDDLComposer.swift +++ b/TablePro/Core/Database/TableDDLComposer.swift @@ -26,4 +26,34 @@ internal enum TableDDLComposer { } return composed + "\n\n" + statements.joined(separator: "\n") } + + /// One object's whole definition, read on a driver already pinned to its scope. The Structure + /// tab's DDL, Show DDL and Copy DDL all come through here, so the three can never disagree about + /// the same object. `includesDependencies` adds the sequences and enum types the table's columns + /// use, which the Structure tab writes first so its text runs on its own. + internal static func fetchDDL( + for table: String, + using driver: DatabaseDriver, + includesDependencies: Bool + ) async throws -> String { + let preamble = includesDependencies ? try await dependencyPreamble(for: table, using: driver) : "" + let baseDDL = try await driver.fetchTableDDL(table: table) + let indexDDL = (try? await driver.fetchIndexDDL(table: table)) ?? [] + return compose(tableDDL: baseDDL, indexDDL: indexDDL, preamble: preamble) + } + + private static func dependencyPreamble(for table: String, using driver: DatabaseDriver) async throws -> String { + let sequences = try await driver.fetchDependentSequences(forTable: table) + let enumTypes = try await driver.fetchDependentTypes(forTable: table) + var preamble = "" + for sequence in sequences { + preamble += sequence.ddl + "\n\n" + } + for enumType in enumTypes { + let quotedName = "\"\(enumType.name.replacingOccurrences(of: "\"", with: "\"\""))\"" + let quotedLabels = enumType.labels.map { "'\(SQLEscaping.escapeStringLiteral($0))'" } + preamble += "CREATE TYPE \(quotedName) AS ENUM (\(quotedLabels.joined(separator: ", ")));\n" + } + return preamble + } } diff --git a/TablePro/Core/Events/AppCommands.swift b/TablePro/Core/Events/AppCommands.swift index 1cfa82b8c0..06be42a315 100644 --- a/TablePro/Core/Events/AppCommands.swift +++ b/TablePro/Core/Events/AppCommands.swift @@ -31,6 +31,32 @@ struct DataRefreshRequest: Sendable, Equatable { } } +/// A change to one named object, addressed by name rather than by scope. +/// +/// `DataRefreshRequest` reloads whichever tab each window has selected in the scope, whatever table +/// it shows, and asks the user to discard its edits first. A change that touches one object has no +/// business interrupting a tab on another, and the tabs that do show it are reloaded whether they +/// are in front or not. +struct DatabaseObjectChange: Sendable, Equatable { + enum Kind: Sendable, Equatable { + /// The object's rows were recomputed, as a materialized view refresh does. + case rows + /// The object's comment changed. + case comment + } + + let connectionId: UUID + let scope: DatabaseScope + let name: String + let kind: Kind + + /// Whether a tab's table is this object. Schema is compared as the tab stores it, which is the + /// resolved schema for an engine that has them and nil for one that does not. + func matches(tableName: String?, databaseName: String, schemaName: String?) -> Bool { + tableName == name && databaseName == scope.database && schemaName == scope.schema + } +} + @MainActor final class AppCommands { static let shared = AppCommands() @@ -38,6 +64,7 @@ final class AppCommands { // MARK: - Refresh let refreshData = PassthroughSubject() + let objectChanged = PassthroughSubject() let refreshPrincipals = PassthroughSubject() // MARK: - File / Connection Import-Export diff --git a/TablePro/Core/MCP/MCPConnectionBridge+Schema.swift b/TablePro/Core/MCP/MCPConnectionBridge+Schema.swift index f465555686..73259b1c29 100644 --- a/TablePro/Core/MCP/MCPConnectionBridge+Schema.swift +++ b/TablePro/Core/MCP/MCPConnectionBridge+Schema.swift @@ -98,17 +98,13 @@ extension MCPConnectionBridge { /// The table's own statement plus the indexes it does not declare, because a caller asking for /// a table's DDL wants what recreates it, not the half the export replays first. static func composedTableDDL(driver: DatabaseDriver, table: String) async -> String? { - guard let base = try? await driver.fetchTableDDL(table: table) else { return nil } - let indexes = (try? await driver.fetchIndexDDL(table: table)) ?? [] - return TableDDLComposer.compose(tableDDL: base, indexDDL: indexes) + try? await TableDDLComposer.fetchDDL(for: table, using: driver, includesDependencies: false) } func getTableDDL(scope: DatabaseScope, table: String) async throws -> JsonValue { try await ensureConnected(scope.connectionId) let ddl = try await DatabaseManager.shared.withMetadataDriver(scope: scope) { driver in - let base = try await driver.fetchTableDDL(table: table) - let indexes = (try? await driver.fetchIndexDDL(table: table)) ?? [] - return TableDDLComposer.compose(tableDDL: base, indexDDL: indexes) + try await TableDDLComposer.fetchDDL(for: table, using: driver, includesDependencies: false) } return .object([ "table": .string(table), diff --git a/TablePro/Core/Menu/DatabaseMenuBuilder.swift b/TablePro/Core/Menu/DatabaseMenuBuilder.swift index 29927b5d8b..c0c05d6930 100644 --- a/TablePro/Core/Menu/DatabaseMenuBuilder.swift +++ b/TablePro/Core/Menu/DatabaseMenuBuilder.swift @@ -67,6 +67,24 @@ enum DatabaseMenuBuilder { String(localized: "Edit View Definition…"), action: #selector(MainSplitViewController.editViewDefinition(_:)) ), + /// The sidebar's own per-object commands, mirrored so each is reachable from the menu + /// bar and the keyboard, and spelled exactly as the sidebar spells them. + MenuItemFactory.item( + String(localized: "Show DDL"), + action: #selector(MainSplitViewController.showObjectDDL(_:)) + ), + MenuItemFactory.item( + String(localized: "Copy DDL"), + action: #selector(MainSplitViewController.copyObjectDDL(_:)) + ), + MenuItemFactory.item( + String(localized: "Refresh Materialized View…"), + action: #selector(MainSplitViewController.refreshMaterializedView(_:)) + ), + MenuItemFactory.item( + String(localized: "Edit Comment…"), + action: #selector(MainSplitViewController.editObjectComment(_:)) + ), schemaSubmenu(), sessionContextSubmenu(), safeModeSubmenu(), diff --git a/TablePro/Core/Plugins/PluginDriverAdapter.swift b/TablePro/Core/Plugins/PluginDriverAdapter.swift index e7372081e2..4bd0fd4be6 100644 --- a/TablePro/Core/Plugins/PluginDriverAdapter.swift +++ b/TablePro/Core/Plugins/PluginDriverAdapter.swift @@ -766,6 +766,23 @@ final class PluginDriverAdapter: DatabaseDriver, SchemaSwitchable, DatabaseRepor pluginDriver.maintenanceStatements(operation: operation, table: table, schema: pluginDriver.currentSchema, options: options) } + // MARK: - Object Comments and Materialized Views + + func objectCommentStatement(name: String, objectType: String, schema: String?, comment: String?) -> String? { + pluginDriver.objectCommentStatement(name: name, objectType: objectType, schema: schema, comment: comment) + } + + func refreshMaterializedViewStatement(name: String, schema: String?, concurrently: Bool) -> String? { + pluginDriver.refreshMaterializedViewStatement(name: name, schema: schema, concurrently: concurrently) + } + + func concurrentRefreshAvailability( + materializedView: String, + schema: String? + ) async throws -> PluginConcurrentRefreshAvailability? { + try await pluginDriver.concurrentRefreshAvailability(materializedView: materializedView, schema: schema) + } + // MARK: - All Tables Metadata SQL func allTablesMetadataSQL(schema: String?) -> String? { diff --git a/TablePro/Core/Plugins/PluginManager.swift b/TablePro/Core/Plugins/PluginManager.swift index 2742308b23..a883efcaa7 100644 --- a/TablePro/Core/Plugins/PluginManager.swift +++ b/TablePro/Core/Plugins/PluginManager.swift @@ -14,6 +14,10 @@ import TableProPluginKit @MainActor @Observable final class PluginManager { static let shared = PluginManager(userDefaults: AppStorageEnvironment.shared.defaults) + /// Raised to 26 for `objectCommentStatement`, `refreshMaterializedViewStatement` and + /// `concurrentRefreshAvailability` on `PluginDatabaseDriver`, plus the + /// `PluginConcurrentRefreshAvailability` the last one answers with. + /// /// Raised to 23 for `releasableResourceCommandTitle` and `releaseIdleResource` on /// `PluginDatabaseDriver`, plus the `PluginResourceRelease` they answer with. Together they let /// a driver hand back a resource its session is holding without ending the session. DuckDB is @@ -37,7 +41,7 @@ final class PluginManager { /// rebuilt CassandraDriver for the v20 requirements it implements none of. Left at 20, such a /// plugin passes `validateBundleVersions` in a shipped v20 app and then fails /// `Bundle.loadAndReturnError`; at 21 that app refuses it and says to update. - nonisolated static let currentPluginKitVersion = 25 + nonisolated static let currentPluginKitVersion = 26 /// Still 19, so every plugin already published for the previous release keeps loading. nonisolated static let minimumCompatiblePluginKitVersion = 19 diff --git a/TablePro/Core/Services/Infrastructure/MainSplitViewController+DatabaseMenuActions.swift b/TablePro/Core/Services/Infrastructure/MainSplitViewController+DatabaseMenuActions.swift index df58cf61b5..17b461d795 100644 --- a/TablePro/Core/Services/Infrastructure/MainSplitViewController+DatabaseMenuActions.swift +++ b/TablePro/Core/Services/Infrastructure/MainSplitViewController+DatabaseMenuActions.swift @@ -88,6 +88,22 @@ extension MainSplitViewController { commandActions?.editViewDefinition() } + @objc func showObjectDDL(_ sender: Any?) { + commandActions?.showObjectDDL() + } + + @objc func copyObjectDDL(_ sender: Any?) { + commandActions?.copyObjectDDL() + } + + @objc func refreshMaterializedView(_ sender: Any?) { + commandActions?.refreshMaterializedView() + } + + @objc func editObjectComment(_ sender: Any?) { + commandActions?.editObjectComment() + } + @objc func runMaintenanceOperation(_ sender: Any?) { guard let operation = (sender as? NSMenuItem)?.representedObject as? String else { return } commandActions?.runMaintenanceOperation(operation) diff --git a/TablePro/Core/Services/Infrastructure/MainSplitViewController+MenuValidation.swift b/TablePro/Core/Services/Infrastructure/MainSplitViewController+MenuValidation.swift index 997bf4727f..e5f15e41ed 100644 --- a/TablePro/Core/Services/Infrastructure/MainSplitViewController+MenuValidation.swift +++ b/TablePro/Core/Services/Infrastructure/MainSplitViewController+MenuValidation.swift @@ -68,6 +68,9 @@ struct MenuValidationContext: Equatable { var canReleaseFileLock = false var canShowTableStructure = false var canEditViewDefinition = false + var canShowObjectDDL = false + var canRefreshMaterializedView = false + var canEditObjectComment = false var canCreateDatabase = false var canCopyObjects = false var canDuplicateDatabase = false @@ -229,10 +232,13 @@ extension MainSplitViewController: NSMenuItemValidation { return context.canCopyObjects case #selector(duplicateCurrentDatabase(_:)): return context.canDuplicateDatabase - case #selector(showTableStructure(_:)): - return context.isConnected && context.canShowTableStructure - case #selector(editViewDefinition(_:)): - return context.isConnected && context.canEditViewDefinition + case #selector(showTableStructure(_:)), + #selector(editViewDefinition(_:)), + #selector(showObjectDDL(_:)), + #selector(copyObjectDDL(_:)), + #selector(refreshMaterializedView(_:)), + #selector(editObjectComment(_:)): + return objectCommandIsEnabled(selector, context: context) case #selector(runMaintenanceOperation(_:)): return context.isConnected && context.hasMaintenanceOperations case #selector(switchToSchema(_:)): @@ -284,6 +290,27 @@ extension MainSplitViewController: NSMenuItemValidation { } } + /// The commands that act on the object selected in the sidebar. They answer on the same facts + /// the sidebar's own contextual menu reads, so a command the sidebar omits is dimmed here rather + /// than enabled over an object it cannot act on. + private static func objectCommandIsEnabled(_ selector: Selector, context: MenuValidationContext) -> Bool { + guard context.isConnected else { return false } + switch selector { + case #selector(showTableStructure(_:)): + return context.canShowTableStructure + case #selector(editViewDefinition(_:)): + return !context.isReadOnly && context.canEditViewDefinition + case #selector(showObjectDDL(_:)), #selector(copyObjectDDL(_:)): + return context.canShowObjectDDL + case #selector(refreshMaterializedView(_:)): + return context.canRefreshMaterializedView + case #selector(editObjectComment(_:)): + return context.canEditObjectComment + default: + return false + } + } + /// The workspace-rail facts come from the window in both branches. They are true of the window, /// not of the connection it happens to be showing, and reading them off a connection that has /// no coordinator left disabled the only menu route to the window's other connections. @@ -329,6 +356,9 @@ extension MainSplitViewController: NSMenuItemValidation { canReleaseFileLock: canReleaseFileLock, canShowTableStructure: actions.canShowTableStructure, canEditViewDefinition: actions.canEditViewDefinition, + canShowObjectDDL: actions.canShowObjectDDL, + canRefreshMaterializedView: actions.canRefreshMaterializedView, + canEditObjectComment: actions.canEditObjectComment, canCreateDatabase: actions.canCreateDatabase, canCopyObjects: actions.canCopyObjects, canDuplicateDatabase: actions.canDuplicateDatabase, diff --git a/TablePro/Models/Database/DatabaseObjectTarget.swift b/TablePro/Models/Database/DatabaseObjectTarget.swift new file mode 100644 index 0000000000..10584eb011 --- /dev/null +++ b/TablePro/Models/Database/DatabaseObjectTarget.swift @@ -0,0 +1,28 @@ +// +// DatabaseObjectTarget.swift +// TablePro +// + +import Foundation + +/// One table-like object a command acts on, with the scope its statement runs in. +/// +/// The scope comes from the object's own database and schema, never from where the sidebar or the +/// selected tab happens to point, so a command raised on a view in another schema cannot act on a +/// same-named view in the browsed one. +struct DatabaseObjectTarget: Equatable, Sendable { + let name: String + let type: TableInfo.TableType + let schema: String? + let scope: DatabaseScope + + /// How the object is named to the user: its schema and its name, as the sidebar shows them. + var qualifiedName: String { + guard let schema, !schema.isEmpty else { return name } + return "\(schema).\(name)" + } + + func change(_ kind: DatabaseObjectChange.Kind) -> DatabaseObjectChange { + DatabaseObjectChange(connectionId: scope.connectionId, scope: scope, name: name, kind: kind) + } +} diff --git a/TablePro/Models/Database/MaterializedViewRefreshPrompt.swift b/TablePro/Models/Database/MaterializedViewRefreshPrompt.swift new file mode 100644 index 0000000000..3bb3c1f253 --- /dev/null +++ b/TablePro/Models/Database/MaterializedViewRefreshPrompt.swift @@ -0,0 +1,89 @@ +// +// MaterializedViewRefreshPrompt.swift +// TablePro +// + +import Foundation +import TableProPluginKit + +/// What the Refresh Materialized View confirmation says, kept apart from the alert so it can be +/// asserted without presenting one. +/// +/// The option to refresh without blocking readers is shown only where the engine has one, and it is +/// enabled only for a view the server will accept it for. Offering it on engine version alone is how +/// other clients ended up with a checkbox the server then refuses. +internal struct MaterializedViewRefreshPrompt: Equatable { + internal let qualifiedName: String + /// Nil when the engine has no concurrent refresh at all. + internal let availability: PluginConcurrentRefreshAvailability? + /// The check failed, so whether the view qualifies is not known. The option is shown disabled + /// rather than left out, so the user is not told the engine lacks it. + internal let availabilityCheckFailed: Bool + + internal init( + qualifiedName: String, + availability: PluginConcurrentRefreshAvailability?, + availabilityCheckFailed: Bool = false + ) { + self.qualifiedName = qualifiedName + self.availability = availability + self.availabilityCheckFailed = availabilityCheckFailed + } + + internal var messageText: String { + String(format: String(localized: "Refresh the materialized view “%@”?"), qualifiedName) + } + + internal var informativeText: String { + String( + localized: """ + The view's query runs again and replaces its stored rows. A plain refresh stops other \ + sessions from reading the view until it finishes. + """ + ) + } + + internal var confirmButtonTitle: String { + String(localized: "Refresh") + } + + internal var cancelButtonTitle: String { + String(localized: "Cancel") + } + + internal var showsConcurrentOption: Bool { + availability != nil || availabilityCheckFailed + } + + internal var isConcurrentOptionEnabled: Bool { + availability == .available + } + + internal var concurrentOptionTitle: String { + String(localized: "Refresh concurrently") + } + + internal var concurrentOptionDescription: String { + if availabilityCheckFailed { + return String(localized: "Couldn't check whether this view can be refreshed concurrently.") + } + switch availability { + case .available: + return String(localized: "Other sessions keep reading the view. Slower, because the new rows are compared with the old ones.") + case .requiresUniqueIndex: + return String(localized: "Needs a valid unique index on the view's columns, with no WHERE clause and no expressions.") + case .requiresPopulatedView: + return String(localized: "Available once the view holds rows. Refresh it once without this option first.") + case .none: + return "" + @unknown default: + return String(localized: "This view can't be refreshed concurrently.") + } + } + + /// Only honoured while the option is enabled, so a stale checkbox can never ask the server for + /// a refresh it has already said it would refuse. + internal func refreshesConcurrently(checkboxIsOn: Bool) -> Bool { + isConcurrentOptionEnabled && checkboxIsOn + } +} diff --git a/TablePro/Models/Database/ObjectCommentDraft.swift b/TablePro/Models/Database/ObjectCommentDraft.swift new file mode 100644 index 0000000000..8602e56907 --- /dev/null +++ b/TablePro/Models/Database/ObjectCommentDraft.swift @@ -0,0 +1,39 @@ +// +// ObjectCommentDraft.swift +// TablePro +// + +import Foundation + +/// The text in the Edit Comment sheet and what saving it would write. +/// +/// A comment that is empty or only whitespace is removed rather than stored, which is what an empty +/// field means to the person clearing it and what PostgreSQL itself does with an empty string. +internal struct ObjectCommentDraft: Equatable { + internal let original: String? + internal var text: String + + internal init(original: String?) { + let normalized = Self.normalized(original) + self.original = normalized + self.text = normalized ?? "" + } + + /// Nil removes the comment. + internal var commentToSave: String? { + Self.normalized(text) + } + + internal var hasChanges: Bool { + commentToSave != original + } + + internal var removesComment: Bool { + original != nil && commentToSave == nil + } + + private static func normalized(_ comment: String?) -> String? { + guard let comment, !comment.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { return nil } + return comment + } +} diff --git a/TablePro/Models/Query/DatabaseObjectRef.swift b/TablePro/Models/Query/DatabaseObjectRef.swift index fcbfb0fa7a..0fb52de0f9 100644 --- a/TablePro/Models/Query/DatabaseObjectRef.swift +++ b/TablePro/Models/Query/DatabaseObjectRef.swift @@ -2,7 +2,7 @@ // DatabaseObjectRef.swift // TablePro // -// Everything needed to find one routine, trigger or type again and read its source. +// Everything needed to find one routine, trigger, type or view again and read its source. // import Foundation @@ -12,13 +12,26 @@ enum DatabaseObjectKind: String, Codable, Sendable, Hashable { case function case trigger case userType + case view + case materializedView var sidebarObjectKind: SidebarObjectKind { switch self { - case .procedure: return .procedure - case .function: return .function - case .trigger: return .trigger - case .userType: return .type + case .procedure: return .procedure + case .function: return .function + case .trigger: return .trigger + case .userType: return .type + case .view: return .view + case .materializedView: return .materializedView + } + } + + /// The kind a table listing row opens as, or nil for a row whose source is its table DDL. + init?(tableType: TableInfo.TableType) { + switch tableType { + case .view: self = .view + case .materializedView: self = .materializedView + case .table, .foreignTable, .systemTable, .partitionedTable, .externalTable: return nil } } @@ -100,6 +113,12 @@ struct DatabaseObjectRef: Hashable, Codable, Sendable { ) } + /// A view or materialized view, whose source is read the way the Structure tab reads it. + init?(relation table: TableInfo, database: String, schema: String?) { + guard let kind = DatabaseObjectKind(tableType: table.type) else { return nil } + self.init(kind: kind, name: table.name, database: database, schema: schema) + } + init(userType: UserDefinedTypeInfo, database: String) { self.init( kind: .userType, @@ -122,7 +141,7 @@ struct DatabaseObjectRef: Hashable, Codable, Sendable { case .trigger: guard let table, !table.isEmpty else { return qualifiedName } return String(format: String(localized: "%1$@ on %2$@"), qualifiedName, table) - case .userType: + case .userType, .view, .materializedView: return qualifiedName } } @@ -171,7 +190,7 @@ struct DatabaseObjectRef: Hashable, Codable, Sendable { argumentSignature: argumentSignature, identity: identity ) - case .trigger, .userType: + case .trigger, .userType, .view, .materializedView: return nil } } diff --git a/TablePro/Models/Query/QueryResult.swift b/TablePro/Models/Query/QueryResult.swift index a75b0316da..7e933dd217 100644 --- a/TablePro/Models/Query/QueryResult.swift +++ b/TablePro/Models/Query/QueryResult.swift @@ -120,7 +120,7 @@ struct TableInfo: Identifiable, Hashable, Sendable { let schema: String? let comment: String? - enum TableType: String, Sendable { + enum TableType: String, Sendable, CaseIterable { case table = "TABLE" case view = "VIEW" case materializedView = "MATERIALIZED VIEW" diff --git a/TablePro/Models/Query/QueryTabManager.swift b/TablePro/Models/Query/QueryTabManager.swift index eab0a2c32c..25d7f1c6b7 100644 --- a/TablePro/Models/Query/QueryTabManager.swift +++ b/TablePro/Models/Query/QueryTabManager.swift @@ -420,6 +420,8 @@ final class QueryTabManager { case .function: format = String(localized: "Function: %@") case .trigger: format = String(localized: "Trigger: %@") case .userType: format = String(localized: "Type: %@") + case .view: format = String(localized: "View: %@") + case .materializedView: format = String(localized: "Materialized View: %@") } return String(format: format, objectRef.displayIdentity) } diff --git a/TablePro/Views/Main/Extensions/MainContentCoordinator+DatabaseObjectTools.swift b/TablePro/Views/Main/Extensions/MainContentCoordinator+DatabaseObjectTools.swift new file mode 100644 index 0000000000..036b4ce68e --- /dev/null +++ b/TablePro/Views/Main/Extensions/MainContentCoordinator+DatabaseObjectTools.swift @@ -0,0 +1,157 @@ +// +// MainContentCoordinator+DatabaseObjectTools.swift +// TablePro +// +// Copy DDL, Refresh Materialized View and Edit Comment on one table-like object. +// + +import AppKit +import Foundation +import os +import TableProPluginKit + +extension MainContentCoordinator { + private static let objectToolsLogger = Logger(subsystem: "com.TablePro", category: "DatabaseObjectTools") + + /// The object a sidebar row or the menu bar's selection names, scoped to its own database and + /// schema. A row whose database is nil belongs to the database being browsed. + func objectTarget(for ref: DatabaseTreeTableRef) -> DatabaseObjectTarget? { + guard let scope = services.databaseManager.resolvedScope( + database: ref.database, + schema: ref.qualifyingSchema, + for: connectionId + ) else { return nil } + return DatabaseObjectTarget( + name: ref.table.name, + type: ref.table.type, + schema: scope.schema ?? ref.qualifyingSchema, + scope: scope + ) + } + + // MARK: - Copy DDL + + /// The same text the DDL viewer and the Structure tab's DDL show, read in the object's own scope. + func copyDDL(of ref: DatabaseTreeTableRef) { + guard let target = objectTarget(for: ref) else { return } + let name = target.name + Task { + do { + let ddl = try await services.databaseManager.withMetadataDriver(scope: target.scope) { driver in + try await TableDDLComposer.fetchDDL(for: name, using: driver, includesDependencies: true) + } + ClipboardService.shared.writeText(ddl) + } catch { + Self.objectToolsLogger.error("Copy DDL failed: \(error.localizedDescription, privacy: .public)") + AlertHelper.showErrorSheet( + title: String(localized: "Couldn't Copy DDL"), + message: error.localizedDescription, + window: contentWindow + ) + } + } + } + + // MARK: - Refresh Materialized View + + func refreshMaterializedView(_ ref: DatabaseTreeTableRef) { + guard !safeModeLevel.blocksAllWrites, let target = objectTarget(for: ref) else { return } + Task { + let prompt = await refreshPrompt(for: target) + MaterializedViewRefreshAlert.present(prompt: prompt, window: contentWindow) { [weak self] concurrently in + guard let self, let concurrently else { return } + self.runMaterializedViewRefresh(target, concurrently: concurrently) + } + } + } + + /// A failed check still asks the question: the refresh itself does not depend on it, and a + /// server that could not answer the catalog read will say why when the refresh runs. + private func refreshPrompt(for target: DatabaseObjectTarget) async -> MaterializedViewRefreshPrompt { + do { + let availability = try await MaterializedViewRefreshing.concurrentRefreshAvailability(of: target) + return MaterializedViewRefreshPrompt(qualifiedName: target.qualifiedName, availability: availability) + } catch { + Self.objectToolsLogger.error( + "Concurrent refresh check failed: \(error.localizedDescription, privacy: .public)" + ) + return MaterializedViewRefreshPrompt( + qualifiedName: target.qualifiedName, + availability: nil, + availabilityCheckFailed: true + ) + } + } + + private func runMaterializedViewRefresh(_ target: DatabaseObjectTarget, concurrently: Bool) { + Task { + do { + try await MaterializedViewRefreshing.refresh(target, concurrently: concurrently, connection: connection) + AlertHelper.showInfoSheet( + title: String(localized: "Materialized View Refreshed"), + message: String(format: String(localized: "“%@” now holds the current result of its query."), target.qualifiedName), + window: contentWindow + ) + } catch { + AlertHelper.showErrorSheet( + title: String(localized: "Couldn't Refresh Materialized View"), + message: error.localizedDescription, + window: contentWindow + ) + } + } + } + + // MARK: - Edit Comment + + func editComment(of ref: DatabaseTreeTableRef) { + guard !safeModeLevel.blocksAllWrites, let target = objectTarget(for: ref) else { return } + activeSheet = .editObjectComment(target) + } + + // MARK: - Object Changes + + /// Brings every tab showing the changed object up to date, and no other tab. The selected one + /// reloads now, asking first if it holds edits; a background one drops its rows so it reloads + /// when it is next shown. + /// + /// The selected tab goes through `handleRefresh`, the entry Cmd+R uses, rather than straight to + /// the data reload: that one refuses to run while the Structure pane is in front and refreshes + /// the structure instead, and a tab excluded from the eviction loop for being selected would + /// otherwise keep its rows with nothing left to reload them. + func applyObjectChange( + _ change: DatabaseObjectChange, + hasPendingTableOps: Bool, + onDiscard: @escaping () -> Void + ) { + guard change.connectionId == connectionId else { return } + let showing = tabManager.tabs.filter { tab in + tab.tabType == .table && change.matches( + tableName: tab.tableContext.tableName, + databaseName: tab.tableContext.resolvedDatabaseName(browsing: browseDatabaseName), + schemaName: tab.tableContext.schemaName + ) + } + let selected = tabManager.selectedTab.flatMap { tab in showing.contains { $0.id == tab.id } ? tab : nil } + + switch change.kind { + case .rows: + for tab in showing where tab.id != selected?.id { + evictReloadableTableRows(for: tab.id) + } + if selected != nil { + handleRefresh(hasPendingTableOps: hasPendingTableOps, onDiscard: onDiscard) + } + case .comment: + for tab in showing { + tableMetadataCache.removeValue(forKey: tab.id) + } + if let selected, let tableName = selected.tableContext.tableName { + Task { await loadTableMetadata(tableName: tableName, for: selected) } + } + if change.scope.database == browseDatabaseName { + Task { await refreshTables() } + } + } + } +} diff --git a/TablePro/Views/Main/Extensions/MainContentCoordinator+SidebarActions.swift b/TablePro/Views/Main/Extensions/MainContentCoordinator+SidebarActions.swift index 1c080ca685..ec94a0109e 100644 --- a/TablePro/Views/Main/Extensions/MainContentCoordinator+SidebarActions.swift +++ b/TablePro/Views/Main/Extensions/MainContentCoordinator+SidebarActions.swift @@ -134,35 +134,49 @@ extension MainContentCoordinator { WindowManager.shared.openTab(payload: payload) } - func editViewDefinition(_ viewName: String) { + /// Reads the view the row names, in the database and schema the row names, and opens the query + /// tab there. It used to read through the browse scope with the name alone, so a view selected + /// in another schema opened the definition of a same-named view in the browsed one, and running + /// it replaced that other view. + func editViewDefinition(_ ref: DatabaseTreeTableRef) { + guard let target = objectTarget(for: ref) else { return } + let viewName = ref.table.name Task { + let query: String do { - let definition = try await DatabaseManager.shared.withBrowseMetadataDriver(connectionId: self.connection.id) { driver in + query = try await DatabaseManager.shared.withMetadataDriver(scope: target.scope) { driver in try await driver.fetchViewDefinition(view: viewName) } - - let payload = EditorTabPayload( - connectionId: connection.id, - tabType: .query, - initialQuery: definition - ) - WindowManager.shared.openTab(payload: payload) } catch { - let driver = DatabaseManager.shared.driver(for: self.connection.id) - let template = driver?.editViewFallbackTemplate(viewName: viewName) - ?? "CREATE OR REPLACE VIEW \(viewName) AS\nSELECT * FROM table_name;" - let fallbackSQL = "-- Could not fetch view definition: \(error.localizedDescription)\n\(template)" - - let payload = EditorTabPayload( - connectionId: connection.id, - tabType: .query, - initialQuery: fallbackSQL + query = Self.viewDefinitionFallback( + viewName: viewName, + error: error, + driver: DatabaseManager.shared.driver(for: self.connection.id) ) - WindowManager.shared.openTab(payload: payload) } + WindowManager.shared.openTab(payload: EditorTabPayload( + connectionId: connection.id, + tabType: .query, + databaseName: target.scope.database, + schemaName: target.scope.schema, + initialQuery: query + )) } } + /// Every line of the error is commented out. A driver error can span several lines, and only the + /// first used to be, so the rest landed in the query tab as SQL. + static func viewDefinitionFallback(viewName: String, error: Error, driver: DatabaseDriver?) -> String { + let template = driver?.editViewFallbackTemplate(viewName: viewName) + ?? "CREATE OR REPLACE VIEW \(viewName) AS\nSELECT * FROM table_name;" + let reason = error.localizedDescription + .split(separator: "\n", omittingEmptySubsequences: false) + .map { "-- \($0)" } + .joined(separator: "\n") + let heading = "-- " + String(localized: "Could not fetch the view definition:") + return "\(heading)\n\(reason)\n\(template)" + } + // MARK: - Export/Import /// The scope travels with the names because a bare name does not identify a table. Without it diff --git a/TablePro/Views/Main/MainContentCommandActions+DatabaseObjects.swift b/TablePro/Views/Main/MainContentCommandActions+DatabaseObjects.swift index 635524e5b0..b55f1724b2 100644 --- a/TablePro/Views/Main/MainContentCommandActions+DatabaseObjects.swift +++ b/TablePro/Views/Main/MainContentCommandActions+DatabaseObjects.swift @@ -25,8 +25,59 @@ extension MainContentCommandActions { } func editViewDefinition() { - guard let object = selectedObject, object.type == .view else { return } - coordinator?.editViewDefinition(object.name) + guard let ref = selectedObjectRef, ref.table.type == .view else { return } + coordinator?.editViewDefinition(ref) + } + + var canShowObjectDDL: Bool { + DatabaseObjectToolEligibility.canShowDDL(selectedObject?.type) + } + + func showObjectDDL() { + guard let ref = selectedObjectRef, + let objectRef = DatabaseObjectRef( + relation: ref.table, + database: ref.database ?? "", + schema: ref.qualifyingSchema + ) + else { return } + coordinator?.showObjectSource(objectRef) + } + + func copyObjectDDL() { + guard let ref = selectedObjectRef, canShowObjectDDL else { return } + coordinator?.copyDDL(of: ref) + } + + var canRefreshMaterializedView: Bool { + DatabaseObjectToolEligibility.canRefresh( + selectedObject?.type, + support: objectToolSupport, + isReadOnly: isReadOnly + ) + } + + func refreshMaterializedView() { + guard let ref = selectedObjectRef, canRefreshMaterializedView else { return } + coordinator?.refreshMaterializedView(ref) + } + + var canEditObjectComment: Bool { + DatabaseObjectToolEligibility.canEditComment( + selectedObject?.type, + support: objectToolSupport, + isReadOnly: isReadOnly + ) + } + + func editObjectComment() { + guard let ref = selectedObjectRef, canEditObjectComment else { return } + coordinator?.editComment(of: ref) + } + + private var objectToolSupport: DatabaseObjectToolEligibility.Support { + guard let connectionId = coordinator?.connectionId else { return .none } + return .of(DatabaseManager.shared.driver(for: connectionId)) } var maintenanceOperations: [String] { diff --git a/TablePro/Views/Main/MainContentCommandActions.swift b/TablePro/Views/Main/MainContentCommandActions.swift index b2b3ae6211..d338bc898c 100644 --- a/TablePro/Views/Main/MainContentCommandActions.swift +++ b/TablePro/Views/Main/MainContentCommandActions.swift @@ -501,12 +501,20 @@ final class MainContentCommandActions { TableOperationEligibility.canTruncate(selectedTables.wrappedValue) } + /// The one selected object with the database and schema it lives in, or nil when the selection + /// is empty or spans several. A command that acts on the object takes this rather than the bare + /// `TableInfo`, which names no database, so it reaches the object the user selected even while + /// the browser points at another database or schema. + var selectedObjectRef: DatabaseTreeTableRef? { + let selection = selectedTables.wrappedValue + guard selection.count == 1 else { return nil } + return selection.first + } + /// The one selected object, or nil when the selection is empty or spans several. /// Commands that open a single object need this rather than `hasTableSelection`. var selectedObject: TableInfo? { - let selection = selectedTables.wrappedValue - guard selection.count == 1 else { return nil } - return selection.first?.table + selectedObjectRef?.table } var hasQueryText: Bool { @@ -1465,6 +1473,19 @@ final class MainContentCommandActions { } } .store(in: &eventCancellables) + + AppCommands.shared.objectChanged + .receive(on: RunLoop.main) + .sink { [weak self] change in + guard let self, change.connectionId == self.connection.id, + let coordinator = self.coordinator else { return } + coordinator.applyObjectChange( + change, + hasPendingTableOps: self.hasPendingTableOps, + onDiscard: { [weak self] in self?.clearPendingTableOps() } + ) + } + .store(in: &eventCancellables) } // MARK: Database Broadcasts diff --git a/TablePro/Views/Main/MainContentCoordinator.swift b/TablePro/Views/Main/MainContentCoordinator.swift index 4d5cf1eb98..9b7c5b5c50 100644 --- a/TablePro/Views/Main/MainContentCoordinator.swift +++ b/TablePro/Views/Main/MainContentCoordinator.swift @@ -70,6 +70,10 @@ enum ActiveSheet: Identifiable { /// This is the rule the sidebar's other destructive commands already keep by carrying their ref. case maintenance(operation: String, tableName: String, database: String?, schema: String?) case createDatabase + /// The object's own database and schema travel in the target, for the reason `.maintenance` + /// carries them: the comment is written to the object the user right-clicked, not to a + /// same-named one wherever the browser points by the time Save is pressed. + case editObjectComment(DatabaseObjectTarget) /// Copying carries the whole launch request, because the source database, the source schema /// and the objects the user right-clicked are all part of what the sheet opens onto, and the /// object browser may be pointed somewhere else by the time the sheet appears. @@ -92,6 +96,8 @@ enum ActiveSheet: Identifiable { case .maintenance(let operation, let tableName, let database, let schema): "maintenance-\(operation)-\(database ?? "")-\(schema ?? "")-\(tableName)" case .createDatabase: "createDatabase" + case .editObjectComment(let target): + "editObjectComment-\(target.scope.database)-\(target.scope.schema ?? "")-\(target.name)" case .copyObjects(let launch): "copyObjects-\(launch.id)" case .rewind: "rewind" case .tableRebuildReview: "tableRebuildReview" diff --git a/TablePro/Views/Main/MainContentView.swift b/TablePro/Views/Main/MainContentView.swift index 9607edd0f9..82d7edff16 100644 --- a/TablePro/Views/Main/MainContentView.swift +++ b/TablePro/Views/Main/MainContentView.swift @@ -205,6 +205,8 @@ struct MainContentView: View { ) case .copyObjects(let launch): CopyObjectsSheet(launch: launch, connection: connection) + case .editObjectComment(let target): + ObjectCommentSheet(target: target, connection: connection) case .exportDialog, .exportQueryResults, .importDialog, .rowImport, .transferTables, .backupDatabase, .restoreDatabase, .serverSideExport: transferSheetContent(for: sheet, dismiss: dismissBinding) diff --git a/TablePro/Views/ObjectSource/ObjectSourceTabView.swift b/TablePro/Views/ObjectSource/ObjectSourceTabView.swift index fc550814a0..3b7d855957 100644 --- a/TablePro/Views/ObjectSource/ObjectSourceTabView.swift +++ b/TablePro/Views/ObjectSource/ObjectSourceTabView.swift @@ -2,7 +2,7 @@ // ObjectSourceTabView.swift // TablePro // -// Tab showing the source of one stored procedure, function, trigger or user-defined type. +// Tab showing the source of one stored procedure, function, trigger, user-defined type or view. // import SwiftUI @@ -107,6 +107,13 @@ final class ObjectSourceLoader { enumLabels: fetched.enumLabels, userType: fetched ) + case .view, .materializedView: + let source = try await TableDDLComposer.fetchDDL( + for: objectRef.name, + using: driver, + includesDependencies: true + ) + return Fetched(source: source, attributes: objectRef.attributes, enumLabels: [], userType: nil) } } } diff --git a/TablePro/Views/Sidebar/DatabaseTreeOutlineCoordinator+Commands.swift b/TablePro/Views/Sidebar/DatabaseTreeOutlineCoordinator+Commands.swift index 44b694fb8e..0fb8c3fc92 100644 --- a/TablePro/Views/Sidebar/DatabaseTreeOutlineCoordinator+Commands.swift +++ b/TablePro/Views/Sidebar/DatabaseTreeOutlineCoordinator+Commands.swift @@ -29,8 +29,14 @@ extension DatabaseTreeOutlineCoordinator { } case .editViewDefinition(let ref): activateThen(ref) { [weak self] in - self?.mainCoordinator?.editViewDefinition(ref.table.name) + self?.mainCoordinator?.editViewDefinition(ref) } + case .copyDDL(let ref): + mainCoordinator?.copyDDL(of: ref) + case .refreshMaterializedView(let ref): + mainCoordinator?.refreshMaterializedView(ref) + case .editComment(let ref): + mainCoordinator?.editComment(of: ref) case .showStructure(let ref): activateThen(ref) { [weak self] in self?.mainCoordinator?.openTableTab( diff --git a/TablePro/Views/Sidebar/DatabaseTreeOutlineCoordinator+Menu.swift b/TablePro/Views/Sidebar/DatabaseTreeOutlineCoordinator+Menu.swift index 3f5dfac085..96abd9e56a 100644 --- a/TablePro/Views/Sidebar/DatabaseTreeOutlineCoordinator+Menu.swift +++ b/TablePro/Views/Sidebar/DatabaseTreeOutlineCoordinator+Menu.swift @@ -86,7 +86,8 @@ extension DatabaseTreeOutlineCoordinator: NSMenuDelegate { isReadOnly: mainCoordinator?.safeModeLevel.blocksAllWrites ?? false ), canBackUp: backupIsAvailable(), - canCreateType: DatabaseManager.shared.driver(for: connectionId)?.createTypeTemplate(schema: nil) != nil + canCreateType: DatabaseManager.shared.driver(for: connectionId)?.createTypeTemplate(schema: nil) != nil, + objectToolSupport: .of(DatabaseManager.shared.driver(for: connectionId)) ) } diff --git a/TablePro/Views/Sidebar/MaterializedViewRefreshAlert.swift b/TablePro/Views/Sidebar/MaterializedViewRefreshAlert.swift new file mode 100644 index 0000000000..d23fa10e93 --- /dev/null +++ b/TablePro/Views/Sidebar/MaterializedViewRefreshAlert.swift @@ -0,0 +1,80 @@ +// +// MaterializedViewRefreshAlert.swift +// TablePro +// + +import AppKit + +/// An informational alert, not a destructive one: the user chose this command on purpose and a +/// refresh loses nothing, so the confirming button keeps Return, which the HIG reserves taking away +/// for an action people did not deliberately choose. +@MainActor +internal enum MaterializedViewRefreshAlert { + private static let accessoryWidth: CGFloat = 300 + private static let descriptionIndent: CGFloat = 20 + + /// - Parameter completion: nil when cancelled, otherwise whether to refresh concurrently. + internal static func present( + prompt: MaterializedViewRefreshPrompt, + window: NSWindow?, + completion: @escaping @MainActor (Bool?) -> Void + ) { + let alert = NSAlert() + alert.messageText = prompt.messageText + alert.informativeText = prompt.informativeText + alert.alertStyle = .informational + alert.addButton(withTitle: prompt.confirmButtonTitle) + AlertHelper.addCancelButton(to: alert, title: prompt.cancelButtonTitle) + + let checkbox = prompt.showsConcurrentOption ? concurrentCheckbox(prompt: prompt) : nil + if let checkbox { + alert.accessoryView = accessoryView(checkbox: checkbox, description: prompt.concurrentOptionDescription) + alert.layout() + } + + AlertHelper.present(alert, in: window) { response in + guard response == .alertFirstButtonReturn else { + completion(nil) + return + } + completion(prompt.refreshesConcurrently(checkboxIsOn: checkbox?.state == .on)) + } + } + + private static func concurrentCheckbox(prompt: MaterializedViewRefreshPrompt) -> NSButton { + let button = NSButton(checkboxWithTitle: prompt.concurrentOptionTitle, target: nil, action: nil) + button.state = .off + button.isEnabled = prompt.isConcurrentOptionEnabled + button.setAccessibilityIdentifier("refresh-materialized-view-concurrently") + if !prompt.isConcurrentOptionEnabled { + button.toolTip = prompt.concurrentOptionDescription + button.setAccessibilityHelp(prompt.concurrentOptionDescription) + } + return button + } + + private static func accessoryView(checkbox: NSButton, description: String) -> NSView { + let label = NSTextField(wrappingLabelWithString: description) + label.font = .systemFont(ofSize: NSFont.smallSystemFontSize) + label.textColor = .secondaryLabelColor + label.preferredMaxLayoutWidth = accessoryWidth - descriptionIndent + + let indented = NSStackView(views: [label]) + indented.orientation = .horizontal + indented.alignment = .top + indented.edgeInsets = NSEdgeInsets(top: 0, left: descriptionIndent, bottom: 0, right: 0) + + let rows: [NSView] = [checkbox, indented] + let stack = NSStackView(views: rows) + stack.orientation = .vertical + stack.alignment = .leading + stack.spacing = 6 + stack.translatesAutoresizingMaskIntoConstraints = false + for row in rows { + row.widthAnchor.constraint(equalToConstant: accessoryWidth).isActive = true + } + stack.layoutSubtreeIfNeeded() + stack.frame = NSRect(origin: .zero, size: stack.fittingSize) + return stack + } +} diff --git a/TablePro/Views/Sidebar/Menu/DatabaseTreeMenuContext.swift b/TablePro/Views/Sidebar/Menu/DatabaseTreeMenuContext.swift index 274bf70692..aac5b9476a 100644 --- a/TablePro/Views/Sidebar/Menu/DatabaseTreeMenuContext.swift +++ b/TablePro/Views/Sidebar/Menu/DatabaseTreeMenuContext.swift @@ -51,4 +51,6 @@ internal struct DatabaseTreeMenuContext { internal var canBackUp: Bool = false /// Whether the driver can offer a CREATE TYPE template. Read-only mode still hides the item. internal var canCreateType: Bool = false + /// Which materialized-view and comment commands the driver has statements for. + internal var objectToolSupport: DatabaseObjectToolEligibility.Support = .none } diff --git a/TablePro/Views/Sidebar/Menu/DatabaseTreeMenuSpec.swift b/TablePro/Views/Sidebar/Menu/DatabaseTreeMenuSpec.swift index 2a2275be8e..d7d935655d 100644 --- a/TablePro/Views/Sidebar/Menu/DatabaseTreeMenuSpec.swift +++ b/TablePro/Views/Sidebar/Menu/DatabaseTreeMenuSpec.swift @@ -91,27 +91,38 @@ internal enum DatabaseTreeMenuSpec { .command(String(localized: "Open in New Tab"), .openInNewTab(ref)), .command(String(localized: "Show Structure"), .showStructure(ref)) ] + if let objectRef = sourceObjectRef(for: ref) { + items.append(.command(String(localized: "Show DDL"), .showObjectSource(objectRef))) + } if SidebarContextMenuLogic.isView(clickedTable: ref.table), !context.isReadOnly { items.append(.command(String(localized: "Edit View Definition"), .editViewDefinition(ref))) } return items } + /// A view's source opens in the read-only DDL viewer, addressed by the row's own database and + /// schema so it reads the view the user clicked rather than a same-named one where the browser is. + private static func sourceObjectRef(for ref: DatabaseTreeTableRef) -> DatabaseObjectRef? { + DatabaseObjectRef(relation: ref.table, database: ref.database ?? "", schema: ref.qualifyingSchema) + } + private static func noteItems( _ ref: DatabaseTreeTableRef, targets: [DatabaseTreeTableRef], context: DatabaseTreeMenuContext ) -> [DatabaseTreeMenuItem] { let names = targets.map(\.table.name).sorted() - return [ - .command(copyNamesTitle(count: names.count), .copyTableNames(names)), - .command( - context.isFavorite - ? String(localized: "Remove from Favorites") - : String(localized: "Add to Favorites"), - .toggleFavorite(ref) - ) - ] + var items: [DatabaseTreeMenuItem] = [.command(copyNamesTitle(count: names.count), .copyTableNames(names))] + if DatabaseObjectToolEligibility.canShowDDL(ref.table.type) { + items.append(.command(String(localized: "Copy DDL"), .copyDDL(ref))) + } + items.append(.command( + context.isFavorite + ? String(localized: "Remove from Favorites") + : String(localized: "Add to Favorites"), + .toggleFavorite(ref) + )) + return items } /// Everything that moves the object's data somewhere else, in the order the work usually runs: @@ -140,6 +151,14 @@ internal enum DatabaseTreeMenuSpec { .copyObjectsTo(objects: copySelections(for: sameScope), ref: ref) )) } + /// Beside Maintenance, the other command that runs a server operation on the object's data. + if DatabaseObjectToolEligibility.canRefresh( + ref.table.type, + support: context.objectToolSupport, + isReadOnly: context.isReadOnly + ) { + items.append(.command(String(localized: "Refresh Materialized View…"), .refreshMaterializedView(ref))) + } if SidebarContextMenuLogic.maintenanceGroupEnabled( isReadOnly: context.isReadOnly, hasSelection: true, @@ -165,6 +184,13 @@ internal enum DatabaseTreeMenuSpec { ) -> [DatabaseTreeMenuItem] { guard !context.isReadOnly else { return [] } var items: [DatabaseTreeMenuItem] = [] + if DatabaseObjectToolEligibility.canEditComment( + ref.table.type, + support: context.objectToolSupport, + isReadOnly: context.isReadOnly + ) { + items.append(.command(String(localized: "Edit Comment…"), .editComment(ref))) + } if ObjectRenameEligibility.canRename(table: ref.table, context: context.renameEligibility) { items.append(.command(String(localized: "Rename"), .beginRenameTable(ref: ref, isRecentRow: isRecentRow))) } diff --git a/TablePro/Views/Sidebar/Menu/SidebarMenuCommand.swift b/TablePro/Views/Sidebar/Menu/SidebarMenuCommand.swift index 077f337998..349e0b2acc 100644 --- a/TablePro/Views/Sidebar/Menu/SidebarMenuCommand.swift +++ b/TablePro/Views/Sidebar/Menu/SidebarMenuCommand.swift @@ -23,6 +23,9 @@ internal enum SidebarMenuCommand: Equatable { case showAllDatabases case openInNewTab(DatabaseTreeTableRef) case editViewDefinition(DatabaseTreeTableRef) + case copyDDL(DatabaseTreeTableRef) + case refreshMaterializedView(DatabaseTreeTableRef) + case editComment(DatabaseTreeTableRef) case showStructure(DatabaseTreeTableRef) case showERDiagram case copyTableNames([String]) diff --git a/TablePro/Views/Sidebar/ObjectCommentSheet.swift b/TablePro/Views/Sidebar/ObjectCommentSheet.swift new file mode 100644 index 0000000000..3e1c20ecce --- /dev/null +++ b/TablePro/Views/Sidebar/ObjectCommentSheet.swift @@ -0,0 +1,157 @@ +// +// ObjectCommentSheet.swift +// TablePro +// + +import os +import SwiftUI + +/// Edits the comment on one table, view, materialized view or foreign table. +/// +/// A sheet with an explicit Save rather than a field that commits on its own: the write is a +/// statement against the server, and a popover or an inspector field that saves when it loses +/// focus would run it on a stray click. +struct ObjectCommentSheet: View { + private static let logger = Logger(subsystem: "com.TablePro", category: "ObjectCommentSheet") + + private enum Phase: Equatable { + case loading + case editing + case saving + case loadFailed(String) + } + + @Environment(\.dismiss) private var dismiss + + let target: DatabaseObjectTarget + let connection: DatabaseConnection + + @State private var draft = ObjectCommentDraft(original: nil) + @State private var phase: Phase = .loading + @State private var saveError: String? + @FocusState private var isEditorFocused: Bool + + var body: some View { + VStack(alignment: .leading, spacing: 0) { + header + Divider() + content + .padding(20) + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) + Divider() + buttonBar + } + .frame(width: 480, height: 320) + .task { await load() } + } + + private var header: some View { + VStack(alignment: .leading, spacing: 2) { + Text("Edit Comment") + .font(.headline) + Text(target.qualifiedName) + .font(.subheadline) + .foregroundStyle(.secondary) + .lineLimit(1) + .truncationMode(.middle) + .textSelection(.enabled) + } + .padding(.horizontal, 20) + .padding(.vertical, 14) + } + + @ViewBuilder + private var content: some View { + switch phase { + case .loading: + ProgressView() + .controlSize(.small) + .frame(maxWidth: .infinity, maxHeight: .infinity) + case .loadFailed(let message): + ContentUnavailableView { + Label("Comment Unavailable", systemImage: "exclamationmark.triangle") + } description: { + Text(message) + } actions: { + Button("Try Again") { + Task { await load() } + } + } + case .editing, .saving: + editor + } + } + + private var editor: some View { + VStack(alignment: .leading, spacing: 8) { + TextEditor(text: $draft.text) + .font(ThemeEngine.shared.valueFontSwiftUI) + .focused($isEditorFocused) + .disabled(phase == .saving) + .overlay( + RoundedRectangle(cornerRadius: 4) + .stroke(Color(nsColor: .separatorColor)) + ) + .accessibilityLabel(String(localized: "Comment")) + .accessibilityIdentifier("object-comment-editor") + if let saveError { + Text(saveError) + .font(.callout) + .foregroundStyle(.red) + .fixedSize(horizontal: false, vertical: true) + .textSelection(.enabled) + } else { + Text("Leave the comment empty to remove it.") + .font(.caption) + .foregroundStyle(.secondary) + } + } + } + + private var buttonBar: some View { + HStack { + if phase == .saving { + ProgressView() + .controlSize(.small) + } + Spacer() + Button(String(localized: "Cancel")) { + dismiss() + } + .keyboardShortcut(.cancelAction) + Button(draft.removesComment ? String(localized: "Remove Comment") : String(localized: "Save")) { + Task { await save() } + } + .keyboardShortcut(.defaultAction) + .disabled(phase != .editing || !draft.hasChanges) + .accessibilityIdentifier("object-comment-save") + } + .padding(.horizontal, 20) + .padding(.vertical, 14) + } + + private func load() async { + phase = .loading + do { + let comment = try await ObjectCommentEditing.currentComment(of: target) + draft = ObjectCommentDraft(original: comment) + phase = .editing + isEditorFocused = true + } catch { + Self.logger.error("Failed to read comment: \(error.localizedDescription, privacy: .public)") + phase = .loadFailed(error.localizedDescription) + } + } + + private func save() async { + phase = .saving + saveError = nil + do { + try await ObjectCommentEditing.setComment(draft.commentToSave, on: target, connection: connection) + dismiss() + } catch { + saveError = error.localizedDescription + phase = .editing + } + } +} diff --git a/TablePro/Views/Structure/TableStructureView+DataLoading.swift b/TablePro/Views/Structure/TableStructureView+DataLoading.swift index b892ae260a..6aab7f1449 100644 --- a/TablePro/Views/Structure/TableStructureView+DataLoading.swift +++ b/TablePro/Views/Structure/TableStructureView+DataLoading.swift @@ -70,21 +70,7 @@ extension TableStructureView { case .ddl: let table = tableName ddlStatement = try await structureLoader.perform { driver in - let sequences = try await driver.fetchDependentSequences(forTable: table) - let enumTypes = try await driver.fetchDependentTypes(forTable: table) - let baseDDL = try await driver.fetchTableDDL(table: table) - let indexDDL = (try? await driver.fetchIndexDDL(table: table)) ?? [] - var preamble = "" - for seq in sequences { - preamble += seq.ddl + "\n\n" - } - for enumType in enumTypes { - let quotedName = "\"\(enumType.name.replacingOccurrences(of: "\"", with: "\"\""))\"" - let quotedLabels = enumType.labels.map { "'\(SQLEscaping.escapeStringLiteral($0))'" } - preamble += "CREATE TYPE \(quotedName) AS ENUM (\(quotedLabels.joined(separator: ", ")));\n" - } - return TableDDLComposer.compose( - tableDDL: baseDDL, indexDDL: indexDDL, preamble: preamble) + try await TableDDLComposer.fetchDDL(for: table, using: driver, includesDependencies: true) } case .triggers: do { diff --git a/TableProTests/Core/Menu/MainMenuBuilderTests.swift b/TableProTests/Core/Menu/MainMenuBuilderTests.swift index d088d362d4..47bbbafb62 100644 --- a/TableProTests/Core/Menu/MainMenuBuilderTests.swift +++ b/TableProTests/Core/Menu/MainMenuBuilderTests.swift @@ -637,6 +637,45 @@ struct MainMenuValidationTests { #expect(enabled(#selector(MainSplitViewController.editViewDefinition(_:)), context)) } + /// The sidebar hides Edit View Definition on a read-only connection. The menu bar used to leave + /// it enabled, so it opened the definition and the save then failed at the gate. + @Test("Editing a view definition is disabled on a read-only connection") + func editViewDefinitionNeedsWriteAccess() { + var context = MenuValidationContext() + context.isConnected = true + context.canEditViewDefinition = true + #expect(enabled(#selector(MainSplitViewController.editViewDefinition(_:)), context)) + context.isReadOnly = true + #expect(!enabled(#selector(MainSplitViewController.editViewDefinition(_:)), context)) + } + + /// Reading a definition writes nothing, so these stay available on a read-only connection, + /// exactly as the sidebar offers them there. + @Test("Show DDL and Copy DDL need a view and survive read-only") + func ddlCommandsFollowTheSelectedObject() { + var context = MenuValidationContext() + context.isConnected = true + #expect(!enabled(#selector(MainSplitViewController.showObjectDDL(_:)), context)) + #expect(!enabled(#selector(MainSplitViewController.copyObjectDDL(_:)), context)) + context.canShowObjectDDL = true + #expect(enabled(#selector(MainSplitViewController.showObjectDDL(_:)), context)) + #expect(enabled(#selector(MainSplitViewController.copyObjectDDL(_:)), context)) + context.isReadOnly = true + #expect(enabled(#selector(MainSplitViewController.showObjectDDL(_:)), context)) + } + + @Test("Refresh and Edit Comment need the driver and the object to support them") + func refreshAndCommentNeedSupport() { + var context = MenuValidationContext() + context.isConnected = true + #expect(!enabled(#selector(MainSplitViewController.refreshMaterializedView(_:)), context)) + #expect(!enabled(#selector(MainSplitViewController.editObjectComment(_:)), context)) + context.canRefreshMaterializedView = true + context.canEditObjectComment = true + #expect(enabled(#selector(MainSplitViewController.refreshMaterializedView(_:)), context)) + #expect(enabled(#selector(MainSplitViewController.editObjectComment(_:)), context)) + } + @Test("Maintenance stays disabled when the driver offers no operations") func maintenanceNeedsOperations() { var context = MenuValidationContext() diff --git a/TableProTests/Models/DatabaseObjectToolsTests.swift b/TableProTests/Models/DatabaseObjectToolsTests.swift new file mode 100644 index 0000000000..d8c3fd816d --- /dev/null +++ b/TableProTests/Models/DatabaseObjectToolsTests.swift @@ -0,0 +1,217 @@ +// +// DatabaseObjectToolsTests.swift +// TableProTests +// + +import Foundation +import TableProPluginKit +import Testing + +@testable import TablePro + +@Suite("Per-object command eligibility") +struct DatabaseObjectToolEligibilityTests { + private let support = DatabaseObjectToolEligibility.Support( + canRefreshMaterializedViews: true, + commentableTypes: [.table, .partitionedTable, .view, .materializedView, .foreignTable] + ) + + @Test("A view's source is its definition, so only the view kinds show DDL") + func ddlIsViewOnly() { + #expect(DatabaseObjectToolEligibility.canShowDDL(.view)) + #expect(DatabaseObjectToolEligibility.canShowDDL(.materializedView)) + for type in [TableInfo.TableType.table, .partitionedTable, .foreignTable, .systemTable, .externalTable] { + #expect(!DatabaseObjectToolEligibility.canShowDDL(type)) + } + #expect(!DatabaseObjectToolEligibility.canShowDDL(nil)) + } + + @Test("Refresh needs a materialized view, a driver statement and write access") + func refreshRequirements() { + #expect(DatabaseObjectToolEligibility.canRefresh(.materializedView, support: support, isReadOnly: false)) + #expect(!DatabaseObjectToolEligibility.canRefresh(.materializedView, support: support, isReadOnly: true)) + #expect(!DatabaseObjectToolEligibility.canRefresh(.view, support: support, isReadOnly: false)) + #expect(!DatabaseObjectToolEligibility.canRefresh(.materializedView, support: .none, isReadOnly: false)) + #expect(!DatabaseObjectToolEligibility.canRefresh(nil, support: support, isReadOnly: false)) + } + + @Test("Editing a comment follows the kinds the driver can comment on") + func commentRequirements() { + #expect(DatabaseObjectToolEligibility.canEditComment(.table, support: support, isReadOnly: false)) + #expect(DatabaseObjectToolEligibility.canEditComment(.materializedView, support: support, isReadOnly: false)) + #expect(!DatabaseObjectToolEligibility.canEditComment(.externalTable, support: support, isReadOnly: false)) + #expect(!DatabaseObjectToolEligibility.canEditComment(.table, support: support, isReadOnly: true)) + #expect(!DatabaseObjectToolEligibility.canEditComment(.table, support: .none, isReadOnly: false)) + } +} + +@Suite("Materialized view refresh prompt") +struct MaterializedViewRefreshPromptTests { + private func prompt( + _ availability: PluginConcurrentRefreshAvailability?, + checkFailed: Bool = false + ) -> MaterializedViewRefreshPrompt { + MaterializedViewRefreshPrompt( + qualifiedName: "sales.mv", + availability: availability, + availabilityCheckFailed: checkFailed + ) + } + + @Test("The prompt names the view it is about") + func promptNamesTheView() { + #expect(prompt(.available).messageText.contains("sales.mv")) + #expect(prompt(.available).confirmButtonTitle == String(localized: "Refresh")) + } + + /// The informative text has to warn about the lock, because a plain refresh holds an exclusive + /// lock on the view for its whole duration. + @Test("The prompt says a plain refresh blocks readers") + func promptWarnsAboutReaders() { + #expect(prompt(.available).informativeText.lowercased().contains("other sessions")) + } + + @Test("The concurrent option is enabled only for a view the server would accept") + func concurrentOptionEnablement() { + #expect(prompt(.available).isConcurrentOptionEnabled) + #expect(!prompt(.requiresUniqueIndex).isConcurrentOptionEnabled) + #expect(!prompt(.requiresPopulatedView).isConcurrentOptionEnabled) + #expect(!prompt(nil).isConcurrentOptionEnabled) + } + + /// An engine with no concurrent refresh shows no option at all. A check that failed shows it + /// disabled with its reason, rather than implying the engine lacks it. + @Test("The option is absent for an engine without one and present when the check failed") + func optionVisibility() { + #expect(prompt(.available).showsConcurrentOption) + #expect(prompt(.requiresUniqueIndex).showsConcurrentOption) + #expect(!prompt(nil).showsConcurrentOption) + #expect(prompt(nil, checkFailed: true).showsConcurrentOption) + #expect(!prompt(nil, checkFailed: true).isConcurrentOptionEnabled) + } + + @Test("Each unavailable reason explains itself") + func reasonsAreExplained() { + #expect(prompt(.requiresUniqueIndex).concurrentOptionDescription.contains("unique index")) + #expect(prompt(.requiresPopulatedView).concurrentOptionDescription.contains("rows")) + #expect(!prompt(nil, checkFailed: true).concurrentOptionDescription.isEmpty) + #expect(prompt(nil).concurrentOptionDescription.isEmpty) + } + + /// A checkbox left on by a previous state cannot ask for a refresh the server has already said + /// it would refuse. + @Test("A checked box is honoured only while the option is enabled") + func checkboxIsGated() { + #expect(prompt(.available).refreshesConcurrently(checkboxIsOn: true)) + #expect(!prompt(.available).refreshesConcurrently(checkboxIsOn: false)) + #expect(!prompt(.requiresUniqueIndex).refreshesConcurrently(checkboxIsOn: true)) + #expect(!prompt(nil, checkFailed: true).refreshesConcurrently(checkboxIsOn: true)) + } +} + +@Suite("Object comment draft") +struct ObjectCommentDraftTests { + @Test("A draft starts from the stored comment") + func startsFromStoredComment() { + let draft = ObjectCommentDraft(original: "daily totals") + + #expect(draft.text == "daily totals") + #expect(!draft.hasChanges) + #expect(draft.commentToSave == "daily totals") + #expect(!draft.removesComment) + } + + @Test("An object with no comment starts empty and has nothing to save") + func startsEmptyWithoutComment() { + let draft = ObjectCommentDraft(original: nil) + + #expect(draft.text.isEmpty) + #expect(!draft.hasChanges) + #expect(draft.commentToSave == nil) + #expect(!draft.removesComment) + } + + /// Clearing the field means removing the comment, which is the same thing PostgreSQL does with + /// an empty string. + @Test("Emptying the field removes the comment", arguments: ["", " ", "\n\t"]) + func emptyingRemovesTheComment(text: String) { + var draft = ObjectCommentDraft(original: "daily totals") + draft.text = text + + #expect(draft.commentToSave == nil) + #expect(draft.hasChanges) + #expect(draft.removesComment) + } + + @Test("Whitespace around a stored comment does not count as a change") + func whitespaceOnlyOriginalIsNoComment() { + let draft = ObjectCommentDraft(original: " ") + + #expect(draft.commentToSave == nil) + #expect(!draft.hasChanges) + } + + @Test("Editing the text is a change, and multiple lines are kept") + func editingIsAChange() { + var draft = ObjectCommentDraft(original: "one") + draft.text = "one\ntwo" + + #expect(draft.hasChanges) + #expect(draft.commentToSave == "one\ntwo") + #expect(!draft.removesComment) + } +} + +@MainActor +@Suite("Object source refs for views") +struct DatabaseObjectRefViewKindTests { + private func table(_ name: String, type: TableInfo.TableType) -> TableInfo { + TableInfo(name: name, type: type, rowCount: nil, schema: "sales") + } + + @Test("A view and a materialized view open as object source, other kinds do not") + func kindFromTableType() { + #expect(DatabaseObjectKind(tableType: .view) == .view) + #expect(DatabaseObjectKind(tableType: .materializedView) == .materializedView) + for type in [TableInfo.TableType.table, .partitionedTable, .foreignTable, .systemTable, .externalTable] { + #expect(DatabaseObjectKind(tableType: type) == nil) + } + } + + @Test("A ref built from a listing row carries the object's own database and schema") + func refCarriesScope() { + let ref = DatabaseObjectRef(relation: table("mv", type: .materializedView), database: "app", schema: "sales") + + #expect(ref?.kind == .materializedView) + #expect(ref?.database == "app") + #expect(ref?.schema == "sales") + #expect(ref?.qualifiedName == "sales.mv") + #expect(ref?.displayIdentity == "sales.mv") + #expect(DatabaseObjectRef(relation: table("users", type: .table), database: "app", schema: "sales") == nil) + } + + @Test("The view kinds map to their sidebar kind and survive a round trip") + func kindsRoundTrip() throws { + #expect(DatabaseObjectKind.view.sidebarObjectKind == .view) + #expect(DatabaseObjectKind.materializedView.sidebarObjectKind == .materializedView) + + for kind in [DatabaseObjectKind.view, .materializedView] { + let ref = DatabaseObjectRef(kind: kind, name: "mv", database: "app", schema: "sales") + let decoded = try JSONDecoder().decode( + DatabaseObjectRef.self, + from: try JSONEncoder().encode(ref) + ) + #expect(decoded == ref) + } + } + + @Test("The tab title names the kind") + func tabTitleNamesTheKind() { + let view = DatabaseObjectRef(kind: .view, name: "vw", database: "app", schema: "sales") + let matview = DatabaseObjectRef(kind: .materializedView, name: "mv", database: "app", schema: "sales") + + #expect(QueryTabManager.objectSourceTitle(for: view).contains("sales.vw")) + #expect(QueryTabManager.objectSourceTitle(for: matview).contains("sales.mv")) + #expect(QueryTabManager.objectSourceTitle(for: view) != QueryTabManager.objectSourceTitle(for: matview)) + } +} diff --git a/TableProTests/Plugins/PostgreSQLRelationSQLTests.swift b/TableProTests/Plugins/PostgreSQLRelationSQLTests.swift new file mode 100644 index 0000000000..220fe8b167 --- /dev/null +++ b/TableProTests/Plugins/PostgreSQLRelationSQLTests.swift @@ -0,0 +1,131 @@ +// +// PostgreSQLRelationSQLTests.swift +// TableProTests +// +// Tests for PostgreSQLRelationSQL (compiled via project.yml from PostgreSQLDriverPlugin). The +// expectations come from PostgreSQL 17.11: COMMENT ON checks its keyword against the relation's +// relkind, and CONCURRENTLY is refused for a view with no usable unique index or no rows. +// + +import Foundation +import TableProPluginKit +import Testing + +@Suite("PostgreSQL relation statements") +struct PostgreSQLRelationSQLTests { + // MARK: - Comments + + @Test("The COMMENT keyword follows the object kind", arguments: [ + ("TABLE", "TABLE"), + ("PARTITIONED TABLE", "TABLE"), + ("VIEW", "VIEW"), + ("MATERIALIZED VIEW", "MATERIALIZED VIEW"), + ("FOREIGN TABLE", "FOREIGN TABLE") + ]) + func commentKeywordFollowsKind(objectType: String, keyword: String) { + #expect(PostgreSQLRelationSQL.commentKeyword(forObjectType: objectType) == keyword) + } + + /// `COMMENT ON TABLE` on a view fails with "is not a table", so a kind with no keyword of its + /// own produces no statement rather than one the server refuses. + @Test("A kind PostgreSQL cannot comment on produces no statement", arguments: [ + "SYSTEM TABLE", "EXTERNAL TABLE", "SEQUENCE", "" + ]) + func unsupportedKindsProduceNoStatement(objectType: String) { + #expect(PostgreSQLRelationSQL.commentKeyword(forObjectType: objectType) == nil) + #expect(PostgreSQLRelationSQL.commentStatement( + name: "t", schema: "s", objectType: objectType, comment: "x" + ) == nil) + } + + @Test("A comment statement qualifies and quotes the object") + func commentStatementQualifies() { + let sql = PostgreSQLRelationSQL.commentStatement( + name: "Mat \"View\" X", + schema: "My \"Odd\" Schema", + objectType: "MATERIALIZED VIEW", + comment: "it's here" + ) + + #expect(sql == "COMMENT ON MATERIALIZED VIEW \"My \"\"Odd\"\" Schema\".\"Mat \"\"View\"\" X\" IS 'it''s here'") + } + + /// Quote doubling alone is injectable when `standard_conforming_strings` is off, where a + /// trailing backslash eats the closing quote. A value holding one is written as an E'' string. + @Test("A comment with a backslash is written as an E-string") + func backslashCommentUsesEString() { + let sql = PostgreSQLRelationSQL.commentStatement( + name: "t", schema: "s", objectType: "TABLE", comment: #"Path C:\temp\"# + ) + + #expect(sql == #"COMMENT ON TABLE "s"."t" IS E'Path C:\\temp\\'"#) + } + + @Test("An empty or missing comment clears it") + func emptyCommentClears() { + #expect(PostgreSQLRelationSQL.commentValue(nil) == "NULL") + #expect(PostgreSQLRelationSQL.commentValue("") == "NULL") + #expect(PostgreSQLRelationSQL.commentStatement( + name: "t", schema: "s", objectType: "TABLE", comment: nil + ) == "COMMENT ON TABLE \"s\".\"t\" IS NULL") + } + + /// Whitespace is a value here. Deciding that a field holding only spaces means "remove the + /// comment" belongs to the sheet, which normalizes before asking for a statement. + @Test("Whitespace is quoted rather than treated as a clear") + func whitespaceCommentIsStored() { + #expect(PostgreSQLRelationSQL.commentValue(" ") == "' '") + } + + // MARK: - Refresh + + @Test("Refresh qualifies the view and adds CONCURRENTLY only when asked") + func refreshStatementShape() { + #expect(PostgreSQLRelationSQL.refreshStatement(name: "mv", schema: "sales", concurrently: false) + == "REFRESH MATERIALIZED VIEW \"sales\".\"mv\"") + #expect(PostgreSQLRelationSQL.refreshStatement(name: "mv", schema: "sales", concurrently: true) + == "REFRESH MATERIALIZED VIEW CONCURRENTLY \"sales\".\"mv\"") + } + + @Test("Refresh quotes a name that needs it") + func refreshQuotesNames() { + #expect(PostgreSQLRelationSQL.refreshStatement( + name: "MV \"Totals\"", schema: "Sales Q1", concurrently: false + ) == "REFRESH MATERIALIZED VIEW \"Sales Q1\".\"MV \"\"Totals\"\"\"") + } + + /// The predicate measured against every index shape on PostgreSQL 17.11: + /// `scripts/check-postgres-matview-refresh.sh` re-runs that comparison against a live server. + @Test("The eligibility query tests exactly what the server requires") + func eligibilityQueryPredicate() { + let sql = PostgreSQLRelationSQL.concurrentRefreshQuery(name: "mv", schema: "sales") + + #expect(sql.contains("c.relispopulated")) + #expect(sql.contains("i.indisunique")) + #expect(sql.contains("i.indimmediate")) + #expect(sql.contains("i.indisvalid")) + #expect(sql.contains("i.indpred IS NULL")) + #expect(sql.contains("i.indexprs IS NULL")) + #expect(sql.contains("c.relkind = 'm'")) + #expect(sql.contains("n.nspname = 'sales'")) + #expect(sql.contains("c.relname = 'mv'")) + } + + /// An unpopulated view is refused whatever its indexes are, and the fix for it is a plain + /// refresh rather than a new index, so population is reported first. + @Test("Population is reported before the index requirement") + func populationTakesPrecedence() { + #expect(PostgreSQLRelationSQL.concurrentRefreshAvailability( + isPopulated: false, hasUsableUniqueIndex: true + ) == .requiresPopulatedView) + #expect(PostgreSQLRelationSQL.concurrentRefreshAvailability( + isPopulated: false, hasUsableUniqueIndex: false + ) == .requiresPopulatedView) + #expect(PostgreSQLRelationSQL.concurrentRefreshAvailability( + isPopulated: true, hasUsableUniqueIndex: false + ) == .requiresUniqueIndex) + #expect(PostgreSQLRelationSQL.concurrentRefreshAvailability( + isPopulated: true, hasUsableUniqueIndex: true + ) == .available) + } +} diff --git a/TableProTests/Plugins/PostgreSQLViewDefinitionTests.swift b/TableProTests/Plugins/PostgreSQLViewDefinitionTests.swift new file mode 100644 index 0000000000..f60efcbf34 --- /dev/null +++ b/TableProTests/Plugins/PostgreSQLViewDefinitionTests.swift @@ -0,0 +1,189 @@ +// +// PostgreSQLViewDefinitionTests.swift +// TableProTests +// +// Tests for PostgreSQLViewDefinition (compiled via project.yml from PostgreSQLDriverPlugin). +// The catalog values below are what PostgreSQL 17.11 returns for the objects described. +// + +import Foundation +import Testing + +@Suite("PostgreSQL view definition") +struct PostgreSQLViewDefinitionTests { + private let body = " SELECT id,\n v\n FROM sales.orders\n WHERE (id > 0);" + + private func row( + kind: PostgreSQLViewDefinition.Kind, + options: [String] = [], + accessMethod: String? = nil, + tablespace: String? = nil + ) -> PostgreSQLViewDefinition.CatalogRow { + PostgreSQLViewDefinition.CatalogRow( + kind: kind, + query: body, + options: options, + accessMethod: accessMethod, + tablespace: tablespace + ) + } + + // MARK: - Views + + @Test("A plain view is a CREATE OR REPLACE VIEW ending in one semicolon") + func plainView() { + let sql = PostgreSQLViewDefinition.statement(name: "vw", schema: "sales", row: row(kind: .view)) + + #expect(sql == """ + CREATE OR REPLACE VIEW "sales"."vw" AS + SELECT id, + v + FROM sales.orders + WHERE (id > 0); + """) + #expect(!sql.hasSuffix(";;")) + } + + /// `CREATE OR REPLACE VIEW` replaces the options it does not name, so a definition that left + /// these out turned a `security_barrier` or `security_invoker` view into an unrestricted one and + /// dropped its check option. Measured on 17.11: reloptions went to NULL and a role with rights + /// on the view alone could then read the base table through it. + @Test("A view keeps its options and its check option") + func viewKeepsOptionsAndCheckOption() { + let sql = PostgreSQLViewDefinition.statement( + name: "vw", + schema: "sales", + row: row( + kind: .view, + options: ["security_barrier=true", "security_invoker=true", "check_option=cascaded"] + ) + ) + + #expect(sql.hasPrefix( + "CREATE OR REPLACE VIEW \"sales\".\"vw\" WITH (security_barrier='true', security_invoker='true') AS" + )) + #expect(sql.hasSuffix("\n WITH CASCADED CHECK OPTION;")) + #expect(!sql.contains("check_option")) + } + + @Test("A local check option is named as such") + func localCheckOption() { + let sql = PostgreSQLViewDefinition.statement( + name: "vw", schema: "sales", row: row(kind: .view, options: ["check_option=local"]) + ) + + #expect(sql.hasSuffix("\n WITH LOCAL CHECK OPTION;")) + #expect(!sql.contains("WITH (")) + } + + // MARK: - Materialized views + + @Test("A materialized view is a CREATE MATERIALIZED VIEW") + func plainMaterializedView() { + let sql = PostgreSQLViewDefinition.statement( + name: "mv", schema: "sales", row: row(kind: .materializedView, accessMethod: "heap") + ) + + #expect(sql.hasPrefix("CREATE MATERIALIZED VIEW \"sales\".\"mv\" AS\n")) + #expect(sql.hasSuffix(";")) + } + + /// `USING` does not exist before PostgreSQL 12 and `heap` is what a server creates without it, + /// so it is written only for a view that is actually stored another way. + @Test("Only a non-default access method is written") + func accessMethodOnlyWhenNotHeap() { + let sql = PostgreSQLViewDefinition.statement( + name: "mv", + schema: "sales", + row: row(kind: .materializedView, accessMethod: "columnar", tablespace: "fast") + ) + + #expect(sql.hasPrefix("CREATE MATERIALIZED VIEW \"sales\".\"mv\" USING \"columnar\" TABLESPACE \"fast\" AS\n")) + } + + @Test("A materialized view keeps its storage parameters") + func materializedViewKeepsStorageParameters() { + let sql = PostgreSQLViewDefinition.statement( + name: "mv", schema: "sales", row: row(kind: .materializedView, options: ["fillfactor=70"]) + ) + + #expect(sql.contains("WITH (fillfactor='70')")) + } + + /// Population is the view's data state rather than part of its definition. Writing `WITH NO + /// DATA` into it would make two otherwise identical views compare as different and have schema + /// sync drop and recreate one, losing its rows. + @Test("Population state is not part of the statement") + func populationIsNotInTheStatement() { + let sql = PostgreSQLViewDefinition.statement( + name: "mv", schema: "sales", row: row(kind: .materializedView) + ) + + #expect(!sql.contains("WITH NO DATA")) + #expect(!sql.contains("WITH DATA")) + } + + // MARK: - Catalog parsing + + @Test("relkind selects the kind, and anything else is not a view") + func relkindMapping() { + #expect(PostgreSQLViewDefinition.kind(forRelkind: "v") == .view) + #expect(PostgreSQLViewDefinition.kind(forRelkind: "m") == .materializedView) + for relkind in ["r", "p", "f", "i", "S", "t", ""] { + #expect(PostgreSQLViewDefinition.kind(forRelkind: relkind) == nil) + } + } + + /// Read as JSON rather than by splitting the array text, because an option value may hold a + /// comma or a quote of its own. + @Test("Options are parsed from JSON, commas inside a value included") + func optionsParsedFromJSON() { + #expect(PostgreSQLViewDefinition.options(fromJSON: #"["security_barrier=true"]"#) == ["security_barrier=true"]) + #expect(PostgreSQLViewDefinition.options(fromJSON: #"["toast.autovacuum_enabled=false","fillfactor=70"]"#) + == ["toast.autovacuum_enabled=false", "fillfactor=70"]) + #expect(PostgreSQLViewDefinition.options(fromJSON: #"["note=a, b"]"#) == ["note=a, b"]) + #expect(PostgreSQLViewDefinition.options(fromJSON: nil).isEmpty) + #expect(PostgreSQLViewDefinition.options(fromJSON: "").isEmpty) + } + + @Test("A catalog row parses into the kind, query, options and storage") + func parseRow() { + let parsed = PostgreSQLViewDefinition.parse(row: [ + "m", body, #"["fillfactor=70"]"#, "heap", "fast" + ]) + + #expect(parsed?.kind == .materializedView) + #expect(parsed?.query == body) + #expect(parsed?.options == ["fillfactor=70"]) + #expect(parsed?.accessMethod == "heap") + #expect(parsed?.tablespace == "fast") + } + + @Test("A row for something that is not a view parses to nothing") + func parseRejectsOtherKinds() { + #expect(PostgreSQLViewDefinition.parse(row: ["r", body, nil, nil, nil]) == nil) + #expect(PostgreSQLViewDefinition.parse(row: [nil, nil, nil, nil, nil]) == nil) + #expect(PostgreSQLViewDefinition.parse(row: ["v", body]) == nil) + } + + /// The body is read with `search_path` emptied, so every name in it is qualified and the text + /// binds to the same tables wherever it is run. + @Test("The catalog query empties the search path and addresses the view by schema and name") + func catalogQueryIsQualifiedAndScoped() { + let query = PostgreSQLViewDefinition.catalogQuery(name: "vw", schema: "sales") + + #expect(PostgreSQLViewDefinition.qualifiedReadPrefix == "SET LOCAL search_path = ''; ") + #expect(query.contains("pg_catalog.pg_get_viewdef(c.oid, true)")) + #expect(query.contains("n.nspname = 'sales'")) + #expect(query.contains("c.relname = 'vw'")) + #expect(query.contains("c.relkind IN ('v', 'm')")) + } + + @Test("A name that needs quoting is quoted, and a literal that needs escaping is escaped") + func catalogQueryQuotesIdentifiers() { + let query = PostgreSQLViewDefinition.catalogQuery(name: "it's", schema: "My \"Odd\" Schema") + + #expect(query.contains("c.relname = 'it''s'")) + #expect(query.contains("n.nspname = 'My \"Odd\" Schema'")) + } +} diff --git a/TableProTests/Views/Sidebar/DatabaseTreeMenuSpecTests.swift b/TableProTests/Views/Sidebar/DatabaseTreeMenuSpecTests.swift index 8b09fe1240..ca07ad29e9 100644 --- a/TableProTests/Views/Sidebar/DatabaseTreeMenuSpecTests.swift +++ b/TableProTests/Views/Sidebar/DatabaseTreeMenuSpecTests.swift @@ -34,7 +34,8 @@ struct DatabaseTreeMenuSpecTests { supportsRename: Bool = true, canCopyObjects: Bool = true, canDuplicateDatabase: Bool = true, - canCreateType: Bool = false + canCreateType: Bool = false, + objectToolSupport: DatabaseObjectToolEligibility.Support = .none ) -> DatabaseTreeMenuContext { DatabaseTreeMenuContext( clicked: clicked, @@ -78,7 +79,17 @@ struct DatabaseTreeMenuSpecTests { hasDatabaseFilter: hasDatabaseFilter, canCopyObjects: canCopyObjects, canDuplicateDatabase: canDuplicateDatabase, - canCreateType: canCreateType + canCreateType: canCreateType, + objectToolSupport: objectToolSupport + ) + } + + /// What the PostgreSQL driver answers: every table-like kind can be commented on, and a + /// materialized view can be refreshed. + private var postgresSupport: DatabaseObjectToolEligibility.Support { + DatabaseObjectToolEligibility.Support( + canRefreshMaterializedViews: true, + commentableTypes: [.table, .partitionedTable, .view, .materializedView, .foreignTable] ) } @@ -380,6 +391,89 @@ struct DatabaseTreeMenuSpecTests { .contains(.editViewDefinition(table))) } + @Test("Show DDL and Copy DDL are offered for a view and a materialized view, and not for a table") + func showAndCopyDDLAreViewOnly() { + let view = tableRef("active_users", type: .view) + let matview = tableRef("sales_totals", type: .materializedView) + let table = tableRef("users") + + for ref in [view, matview] { + let issued = commands(DatabaseTreeMenuSpec.sections(for: context(clicked: .table(ref)))) + #expect(issued.contains(.copyDDL(ref))) + #expect(issued.contains { command in + guard case .showObjectSource(let objectRef) = command else { return false } + return objectRef.name == ref.table.name && objectRef.schema == "public" && objectRef.database == "app" + }) + } + + let tableCommands = commands(DatabaseTreeMenuSpec.sections(for: context(clicked: .table(table)))) + #expect(!tableCommands.contains(.copyDDL(table))) + #expect(!tableCommands.contains { command in + if case .showObjectSource = command { return true } + return false + }) + } + + /// Reading a definition writes nothing, so a read-only connection still offers it. Editing the + /// definition is the command that disappears. + @Test("Read-only keeps Show DDL and Copy DDL") + func readOnlyKeepsDDLCommands() { + let view = tableRef("active_users", type: .view) + let issued = commands(DatabaseTreeMenuSpec.sections(for: context(clicked: .table(view), isReadOnly: true))) + + #expect(issued.contains(.copyDDL(view))) + #expect(!issued.contains(.editViewDefinition(view))) + } + + @Test("Only a materialized view offers Refresh Materialized View") + func refreshIsMaterializedViewOnly() { + let matview = tableRef("sales_totals", type: .materializedView) + let view = tableRef("active_users", type: .view) + let table = tableRef("users") + + #expect(commands(DatabaseTreeMenuSpec.sections( + for: context(clicked: .table(matview), objectToolSupport: postgresSupport) + )).contains(.refreshMaterializedView(matview))) + + for ref in [view, table] { + #expect(!commands(DatabaseTreeMenuSpec.sections( + for: context(clicked: .table(ref), objectToolSupport: postgresSupport) + )).contains(.refreshMaterializedView(ref))) + } + } + + @Test("Refresh is absent without a driver statement for it, and when read-only") + func refreshNeedsDriverSupportAndWriteAccess() { + let matview = tableRef("sales_totals", type: .materializedView) + + #expect(!commands(DatabaseTreeMenuSpec.sections(for: context(clicked: .table(matview)))) + .contains(.refreshMaterializedView(matview))) + #expect(!commands(DatabaseTreeMenuSpec.sections( + for: context(clicked: .table(matview), isReadOnly: true, objectToolSupport: postgresSupport) + )).contains(.refreshMaterializedView(matview))) + } + + @Test("Edit Comment follows the kinds the driver can comment on") + func editCommentFollowsDriverSupport() { + let table = tableRef("users") + let matview = tableRef("sales_totals", type: .materializedView) + let external = tableRef("events", type: .externalTable) + + for ref in [table, matview] { + #expect(commands(DatabaseTreeMenuSpec.sections( + for: context(clicked: .table(ref), objectToolSupport: postgresSupport) + )).contains(.editComment(ref))) + } + #expect(!commands(DatabaseTreeMenuSpec.sections( + for: context(clicked: .table(external), objectToolSupport: postgresSupport) + )).contains(.editComment(external))) + #expect(!commands(DatabaseTreeMenuSpec.sections(for: context(clicked: .table(table)))) + .contains(.editComment(table))) + #expect(!commands(DatabaseTreeMenuSpec.sections( + for: context(clicked: .table(table), isReadOnly: true, objectToolSupport: postgresSupport) + )).contains(.editComment(table))) + } + // MARK: - Containers @Test("Use as Active is omitted for the container already in use") diff --git a/docs/databases/postgresql.mdx b/docs/databases/postgresql.mdx index aa65eea563..d8029a760f 100644 --- a/docs/databases/postgresql.mdx +++ b/docs/databases/postgresql.mdx @@ -66,6 +66,14 @@ In the list editor, reorder rows with the arrows, add and remove elements, and s Enums, composites, domains and ranges are listed under **Types** in each schema, the `CREATE` statement rebuilt from `pg_type`. An enum's labels are edited in place with `ALTER TYPE … ADD VALUE` and, from PostgreSQL 10, `RENAME VALUE`; PostgreSQL has no statement that drops or reorders a label. The structure editor's type picker offers the schema's types under **User-Defined**. See [User-Defined Types](/features/user-defined-types). +## Views and comments + +A view's definition is rebuilt to run anywhere. Every table it reads is schema-qualified, and `WITH (security_barrier)`, `WITH (security_invoker)` and `WITH CASCADED CHECK OPTION` are written back, so executing the statement elsewhere keeps the restrictions the original carried. Read it with **Show DDL**, copy it with **Copy DDL**, or edit it with **Edit View Definition**. A materialized view's statement carries its access method, storage parameters and tablespace, and the DDL tab adds its indexes. + +`REFRESH MATERIALIZED VIEW` runs from **Refresh Materialized View…**. A plain refresh holds an `ACCESS EXCLUSIVE` lock, so nothing reads the view until it finishes. **Refresh concurrently** takes `EXCLUSIVE` instead and leaves readers working, and PostgreSQL accepts it only for a populated view with a valid unique index on plain columns, no `WHERE` clause and no expressions; a partial or expression index does not qualify. The refresh runs on its own connection, outside any transaction a query editor holds open. Refreshing needs ownership of the view, or the `MAINTAIN` privilege from PostgreSQL 17. + +**Edit Comment…** writes `COMMENT ON`, picking `TABLE`, `VIEW`, `MATERIALIZED VIEW` or `FOREIGN TABLE` to match the object. Column comments are written from the Columns tab as `COMMENT ON COLUMN`. Clearing the field writes `IS NULL`, which removes the comment. Only the object's owner may comment on it. + ## Cross-database tabs PostgreSQL has no in-place `USE`, so a tab bound to a database other than the connection's active one runs on a second connection opened for that database. It shares no temp tables, session variables, or open transaction with the query editor on the main connection: keep a multi-statement transaction or a `CREATE TEMP TABLE` on tabs bound to one database. Binding itself is on [Tabs](/features/tabs#where-a-tab-points). diff --git a/docs/development/plugin-development.mdx b/docs/development/plugin-development.mdx index 6892661ea4..91c89bc9b8 100644 --- a/docs/development/plugin-development.mdx +++ b/docs/development/plugin-development.mdx @@ -13,7 +13,7 @@ A plugin is a macOS loadable bundle target with `WRAPPER_EXTENSION = tableplugin | Key | Type | Required | Purpose | |-----|------|----------|---------| -| `TableProPluginKitVersion` | integer | Yes | The PluginKit ABI the plugin was built against. Current value: 25 | +| `TableProPluginKitVersion` | integer | Yes | The PluginKit ABI the plugin was built against. Current value: 26 | | `TableProProvidesDatabaseTypeIds` | array of strings | Recommended | Database type IDs the plugin serves, which is what makes lazy loading possible | | `CFBundleShortVersionString` | string | Yes | Plugin version, read by registry update checks | | `TableProMinAppVersion` | string | No | The loader rejects the plugin on an older app | diff --git a/docs/development/plugin-registry.mdx b/docs/development/plugin-registry.mdx index cdddf55118..316ed240f8 100644 --- a/docs/development/plugin-registry.mdx +++ b/docs/development/plugin-registry.mdx @@ -68,13 +68,13 @@ Themes carry no native code, so they match on architecture alone. "binaries": [ { "architecture": "arm64", - "pluginKitVersion": 25, + "pluginKitVersion": 26, "downloadURL": "https://github.com/TableProApp/TablePro/releases/download/plugin-oracle-v1.0.26/OracleDriver-arm64.zip", "sha256": "" }, { "architecture": "x86_64", - "pluginKitVersion": 25, + "pluginKitVersion": 26, "downloadURL": "https://github.com/TableProApp/TablePro/releases/download/plugin-oracle-v1.0.26/OracleDriver-x86_64.zip", "sha256": "" } diff --git a/docs/features/table-operations.mdx b/docs/features/table-operations.mdx index 89dd4de7cf..aeb9a64a07 100644 --- a/docs/features/table-operations.mdx +++ b/docs/features/table-operations.mdx @@ -84,6 +84,12 @@ Views carry an eye icon in the sidebar; materialized views and foreign tables ge Right-click empty space and choose **New View…** to write a new one; right-click an existing view and choose **Edit View Definition** to open the current definition in a query tab. Either way, execute the statement to apply it. +**Show DDL** opens the definition in a read-only tab, with **Copy**, **Export** and **Open in Editor** on it; **Copy DDL** puts the same statement straight on the clipboard. Both stay available on a read-only connection, where **Edit View Definition** is hidden. + +A materialized view holds stored rows, so refreshing it is a server operation. Right-click one and choose **Refresh Materialized View…**, or use **Database > Refresh Materialized View…**. The confirmation names the view and warns that other sessions cannot read it while the refresh runs. **Refresh concurrently** leaves readers alone; it is available on PostgreSQL for a view that holds rows and carries a unique index on plain columns with no `WHERE` clause, and the alert says which of the two is missing when it is dimmed. Tabs showing the view reload when the refresh finishes. A plain view stores nothing, so `Cmd+R` re-runs its query instead. + +Comments are edited per object. Right-click a table, view, materialized view or foreign table, choose **Edit Comment…**, and type the text; saving an empty field removes the comment. Column comments live in the [Columns tab](/features/table-structure#columns-tab). Both need an engine that writes comments, which today means PostgreSQL and PGlite. + ## Databases and schemas `Cmd+K` switches database, covered in [Managing Connections](/connections#switch-connections-and-databases). The switcher takes the engine's own vocabulary: Schema on Oracle and Spanner, Keyspace on Cassandra, Dataset on BigQuery, Namespace on SurrealDB. SQLite is file-based, so it points at the welcome window to open a different file. diff --git a/docs/features/table-structure.mdx b/docs/features/table-structure.mdx index 8aed9204f1..20324feba5 100644 --- a/docs/features/table-structure.mdx +++ b/docs/features/table-structure.mdx @@ -171,6 +171,8 @@ Triggers are available for MySQL, MariaDB, PostgreSQL, SQLite, SQL Server, Oracl Read-only `CREATE TABLE` with syntax highlighting and font size controls. **Copy**, **Export** as a `.sql` file, and **Open in Editor** send it onward. On PostgreSQL the `CREATE SEQUENCE` and `CREATE TYPE … AS ENUM` statements the table depends on are prepended, so the script runs on an empty database. +Open the tab on a view and it carries that view's own `CREATE VIEW` or `CREATE MATERIALIZED VIEW` instead, the same statement **Show DDL** opens. A materialized view's indexes follow it. + ## Parts tab (ClickHouse) Lists partitions and parts from `system.parts`. **Optimize** merges parts; **Drop Partition** and **Detach Partition** act on the selected partition. Detached data stays on disk and is unreadable until it is re-attached. diff --git a/project.yml b/project.yml index 69d7414378..17dcbc20f2 100644 --- a/project.yml +++ b/project.yml @@ -519,6 +519,8 @@ targets: - Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogTypeNames.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLCheckConstraintDefinition.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift + - Plugins/PostgreSQLDriverPlugin/PostgreSQLRelationSQL.swift + - Plugins/PostgreSQLDriverPlugin/PostgreSQLViewDefinition.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLSchemaQueries.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLSystemDatabases.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLTableListingLadder.swift diff --git a/scripts/check-postgres-matview-refresh.sh b/scripts/check-postgres-matview-refresh.sh new file mode 100755 index 0000000000..faf48af890 --- /dev/null +++ b/scripts/check-postgres-matview-refresh.sh @@ -0,0 +1,147 @@ +#!/usr/bin/env bash +# +# Check the concurrent-refresh rule against a real PostgreSQL server. +# +# PostgreSQL refuses REFRESH MATERIALIZED VIEW CONCURRENTLY unless the view is populated and has a +# unique index it can diff through, and it says so only when the statement runs. TablePro decides +# whether to offer the option beforehand, from a catalog predicate in PostgreSQLRelationSQL. That +# predicate is a hand-written copy of a server rule, which is the shape that drifts silently: offer +# the option too freely and the refresh fails, too rarely and the option is missing for a view that +# qualifies. +# +# This builds a materialized view for every index shape that matters, asks the predicate, runs the +# real refresh, and compares the two answers. +# +# Usage: +# scripts/check-postgres-matview-refresh.sh [host] [port] [user] +# +# Needs psql and a reachable PostgreSQL 9.4 or newer the user may create a database on. Exits +# non-zero on a disagreement. + +set -uo pipefail + +HOST="${1:-127.0.0.1}" +PORT="${2:-5432}" +USER_NAME="${3:-postgres}" +SOURCE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/Plugins/PostgreSQLDriverPlugin/PostgreSQLRelationSQL.swift" +DATABASE="tablepro_matview_refresh_check" + +command -v psql > /dev/null || { + echo "psql not found" >&2 + exit 3 +} +[ -f "$SOURCE" ] || { + echo "not found: $SOURCE" >&2 + exit 3 +} + +psql_do() { + psql -X -q -h "$HOST" -p "$PORT" -U "$USER_NAME" -d "$1" -v ON_ERROR_STOP=1 "${@:2}" +} + +if ! psql_do postgres -Atc "SELECT 1" > /dev/null 2>&1; then + echo "no PostgreSQL at $HOST:$PORT as $USER_NAME" >&2 + exit 3 +fi + +VERSION="$(psql_do postgres -Atc "SHOW server_version")" +echo "Checking the concurrent-refresh predicate against PostgreSQL $VERSION at $HOST:$PORT" + +# The predicate as the plugin builds it, read out of the source so the two cannot drift. The Swift +# side interpolates the schema and the name; here they are bound per view instead. +PREDICATE="c.relispopulated AND EXISTS ( + SELECT 1 + FROM pg_catalog.pg_index i + JOIN pg_catalog.pg_class ic ON ic.oid = i.indexrelid + JOIN pg_catalog.pg_am am ON am.oid = ic.relam + WHERE i.indrelid = c.oid + AND i.indisunique + AND i.indimmediate + AND i.indisvalid + AND i.indpred IS NULL + AND i.indexprs IS NULL + AND am.amname = 'btree' +)" + +for fragment in "i.indisunique" "i.indimmediate" "i.indisvalid" "i.indpred IS NULL" "i.indexprs IS NULL" "c.relispopulated"; do + grep -qF "$fragment" "$SOURCE" || { + echo "FAIL: $SOURCE no longer tests $fragment; update this script with the predicate" >&2 + exit 1 + } +done + +psql_do postgres -c "DROP DATABASE IF EXISTS $DATABASE" > /dev/null +psql_do postgres -c "CREATE DATABASE $DATABASE" > /dev/null +trap 'psql -X -q -h "$HOST" -p "$PORT" -U "$USER_NAME" -d postgres -c "DROP DATABASE IF EXISTS $DATABASE" > /dev/null 2>&1' EXIT + +psql_do "$DATABASE" > /dev/null <<'SQL' +CREATE TABLE src (id int NOT NULL, a text, b text); +INSERT INTO src SELECT g, 'a' || g, 'b' || (g % 3) FROM generate_series(1, 20) g; + +CREATE MATERIALIZED VIEW mv_none AS SELECT id, a, b FROM src; + +CREATE MATERIALIZED VIEW mv_unique AS SELECT id, a, b FROM src; +CREATE UNIQUE INDEX mv_unique_id ON mv_unique (id); + +CREATE MATERIALIZED VIEW mv_unique_multi AS SELECT id, a, b FROM src; +CREATE UNIQUE INDEX mv_unique_multi_id ON mv_unique_multi (b, id); + +CREATE MATERIALIZED VIEW mv_unique_include AS SELECT id, a, b FROM src; + +CREATE MATERIALIZED VIEW mv_partial AS SELECT id, a, b FROM src; +CREATE UNIQUE INDEX mv_partial_id ON mv_partial (id) WHERE id > 5; + +CREATE MATERIALIZED VIEW mv_expression AS SELECT id, a, b FROM src; +CREATE UNIQUE INDEX mv_expression_a ON mv_expression (lower(a)); + +CREATE MATERIALIZED VIEW mv_mixed AS SELECT id, a, b FROM src; +CREATE UNIQUE INDEX mv_mixed_id_lower ON mv_mixed (id, lower(a)); + +CREATE MATERIALIZED VIEW mv_not_unique AS SELECT id, a, b FROM src; +CREATE INDEX mv_not_unique_id ON mv_not_unique (id); + +CREATE MATERIALIZED VIEW mv_unpopulated AS SELECT id, a, b FROM src WITH NO DATA; +CREATE UNIQUE INDEX mv_unpopulated_id ON mv_unpopulated (id); +SQL + +# INCLUDE arrived in PostgreSQL 11; where it is missing the view keeps a plain unique index, which +# still belongs in the comparison. +psql_do "$DATABASE" -c "CREATE UNIQUE INDEX mv_unique_include_id ON mv_unique_include (id) INCLUDE (a)" > /dev/null 2>&1 \ + || psql_do "$DATABASE" -c "CREATE UNIQUE INDEX mv_unique_include_id ON mv_unique_include (id)" > /dev/null + +VIEWS="$(psql_do "$DATABASE" -Atc " + SELECT c.relname + FROM pg_catalog.pg_class c + JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace + WHERE c.relkind = 'm' AND n.nspname = 'public' + ORDER BY c.relname")" + +failures=0 +for view in $VIEWS; do + predicted="$(psql_do "$DATABASE" -Atc " + SELECT CASE WHEN $PREDICATE THEN 'yes' ELSE 'no' END + FROM pg_catalog.pg_class c + JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace + WHERE c.relkind = 'm' AND n.nspname = 'public' AND c.relname = '$view'")" + + if psql -X -q -h "$HOST" -p "$PORT" -U "$USER_NAME" -d "$DATABASE" -v ON_ERROR_STOP=1 \ + -c "REFRESH MATERIALIZED VIEW CONCURRENTLY public.$view" > /dev/null 2>&1; then + actual="yes" + else + actual="no" + fi + + if [ "$predicted" = "$actual" ]; then + printf 'ok %-22s predicate=%-3s server=%s\n' "$view" "$predicted" "$actual" + else + printf 'FAIL %-22s predicate=%-3s server=%s\n' "$view" "$predicted" "$actual" + failures=$((failures + 1)) + fi +done + +if [ "$failures" -gt 0 ]; then + echo "$failures view(s) disagree with the predicate in PostgreSQLRelationSQL.swift" >&2 + exit 1 +fi + +echo "The predicate agrees with PostgreSQL $VERSION on every index shape." From 2751c606f22a201a0822f35081e9c20564d2b884 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 00:54:42 +0700 Subject: [PATCH 18/54] fix(plugin-mysql): take the open transaction from the server and hold the session's other state against a replay (#2754) --- CLAUDE.md | 4 +- .../MariaDBPluginConnection.swift | 26 ++++ .../MySQLDriverPlugin/MySQLPluginDriver.swift | 60 ++++++--- .../MySQLSessionFootprint.swift | 123 +++++++++++++----- .../MySQLStatementClassification.swift | 7 + .../Plugins/MySQLSessionFootprintTests.swift | 101 +++++++++++++- .../MySQLStatementClassificationTests.swift | 24 ++++ .../Plugins/SQLStatementSplittingTests.swift | 13 +- docs/databases/mysql.mdx | 6 +- 9 files changed, 302 insertions(+), 62 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 048cd8d80e..cd23f38fec 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -227,7 +227,9 @@ To ship one: add the record type or field in CloudKit Console (or `xcrun cktool **A MySQL session's character set is server state, and the driver sets it rather than asking for it**: `MYSQL_SET_CHARSET_NAME` only puts a collation byte in the handshake, and the server is free to ignore it. `init_connect='SET NAMES latin1'` for any user without `CONNECTION_ADMIN`, MariaDB's `skip-character-set-client-handshake`, and a server with no `utf8mb4` all leave the session latin1 while libmariadb still reports `utf8mb4`. The driver sends UTF-8 either way, so every comment and value it wrote there was stored double-encoded, which is the `メール` of #2725, and a user-variable comparison on MySQL 8 failed with `ERROR 1267` under the handshake's `utf8mb4_general_ci`. So `MariaDBCharacterSet.establishSession`, which the macOS plugin and the iOS driver share, calls `mysql_set_character_set` on every connect path, falls back to a plain `SET NAMES utf8` (libmariadb itself rewrites `utf8` to `utf8mb3`, which a pre-5.5.3 server does not know), and keeps the server's own session when it refuses both rather than failing the connect: a MySQL-protocol engine that rejects `SET NAMES` must still connect. Two rules follow. Outgoing SQL stays the UTF-8 bytes of the Swift string and never follows a mid-session `SET NAMES`: a legacy dump that declares `SET NAMES latin1` over UTF-8 bytes restores byte-for-byte only because nothing re-encodes it, which is also what the `mysql` client does. And every result cell decodes through `MySQLColumnDecoding` by its field's own `charsetnr`, never as "UTF-8 and hope": a latin1 field reads UTF-8 first and then MySQL's latin1, which is cp1252 plus five C1 pass-through bytes and not Foundation's `.isoLatin1` or `.windowsCP1252`. The Foundation encodings in `MySQLCharacterSet` are a hand transcription of the server's tables; `scripts/check-mysql-charset-decoding.sh` diffs them against a live server, and a charset that disagrees stays out of the table. **UTF-8 via Latin 1** (`mysqlConnectionEncoding`) sets only `character_set_client` to latin1 and repairs the text client-side, so correctly stored text is never read back as `?`, which a latin1 results charset would do and a structure edit would then write back. -**A reconnect the user did not ask for hands back a different session, so only a session holding nothing may replay a statement across one**: `MySQLPluginDriver.executeWithReconnect` retakes a connection the server dropped and runs the statement again, and the new session has none of the old one's state. Measured on MySQL 8.4.11 by killing the connection under it: `SELECT @probe` answered `NULL` where it had answered 42, `SELECT DATABASE()` answered the database the driver connects to over the one a `USE` had selected, and `@@SESSION.sql_mode` answered the server default over the session's `ANSI_QUOTES`, all three without raising. `mysqlMayReplay` is the single gate and reads `MySQLSessionFootprint.isClean`, not `hasOpenTransaction` alone; the same footprint gates the idle release, so one flag covers both paths. Only the driver's own statements go in with `countsAsActivity: false`, and only because the driver puts them back itself: the query timeout, and the `USE` behind a database switch, which reconnects through `_activeDatabase`. And `/*!40101 ... */` is not a comment, it is SQL the server runs, so `SQLStatementSplitting` keeps it whole rather than stripping it; a mysqldump preamble run from the editor sets the character set, the time zone and six `@OLD_` variables inside them, and dropping them left the footprint reading clean. +**A reconnect the user did not ask for hands back a different session, so only a session holding nothing may replay a statement across one**: `MySQLPluginDriver.executeWithReconnect` retakes a connection the server dropped and runs the statement again, and the new session has none of the old one's state. Measured on MySQL 8.4.11 by killing the connection under it: `SELECT @probe` answered `NULL` where it had answered 42, `SELECT DATABASE()` answered the database the driver connects to over the one a `USE` had selected, and `@@SESSION.sql_mode` answered the server default over the session's `ANSI_QUOTES`, all three without raising. `mysqlMayReplay` is the single gate and reads `MySQLSessionFootprint.isClean`, not `hasOpenTransaction` alone; `blockingReason` is the same predicate in the user's words and gates the idle release, so `MySQLSessionFootprintTests` asserts the two agree for every flag. + +Four rules follow. A statement whose *answer* is session-scoped is not replayable even though it changes nothing and leaves the footprint clean: `LAST_INSERT_ID`, `ROW_COUNT`, `FOUND_ROWS` and `CONNECTION_ID` are in `mysqlSideEffectingMarkers` for that reason, measured as a fresh connection answering `SELECT LAST_INSERT_ID()` with `0`. The open transaction is the server's own answer rather than a reading of the text, through `mariadb_get_info(MARIADB_CONNECTION_SERVER_STATUS)` in `MariaDBPluginConnection.recordTransactionState` and `footprint.observeServerTransaction`: measured, that reports the transaction `SET autocommit = 0` plus a plain `SELECT` opens, the one inside `/*!40101 BEGIN */` and the one an `XA START` opens, none of which any text scan can see. Only the driver's own statements go in with `countsAsActivity: false`, and only because the driver puts them back itself: the query timeout, and the `USE` behind a database switch, which reconnects through `_activeDatabase` and refreshes `lastActivity` by hand so the idle timer still sees the switch as use. And `/*!40101 ... */` is not a comment, it is SQL the server runs, so `SQLStatementSplitting` keeps it whole rather than stripping it and `MySQLSessionFootprint` reads the body, trailing text included; a mysqldump preamble run from the editor sets the character set, the time zone and eight `@OLD_` variables inside them, and dropping them left the footprint reading clean. The version number is not checked against the server, so a statement the server is too old to run still counts, which holds a clean connection rather than releasing a dirty one. **A MongoDB update or delete is anchored on `_id` or it does not run**: `generateDelete` used to fall back to a filter built from the remaining columns, which silently dropped every value it could not stringify (all binary) and then `deleteOne`d the first partial match, so a document with a binary `_id` could delete a different document. Both paths now skip with a logged warning instead, matching what `generateUpdate` already did. diff --git a/Plugins/MySQLDriverPlugin/MariaDBPluginConnection.swift b/Plugins/MySQLDriverPlugin/MariaDBPluginConnection.swift index 024749bb08..c9e703e640 100644 --- a/Plugins/MySQLDriverPlugin/MariaDBPluginConnection.swift +++ b/Plugins/MySQLDriverPlugin/MariaDBPluginConnection.swift @@ -115,6 +115,29 @@ final class MariaDBPluginConnection: @unchecked Sendable { return _isConnected } + /// Whether the server says the session is inside a transaction, from the status flags in the + /// reply to the last statement. This is the one thing about the session the server does + /// answer for free, and it is exact where reading the statement text is a guess: measured on + /// MySQL 8.4.11, it reports the transaction that `SET autocommit = 0` plus a plain `SELECT` + /// opens, the one inside `/*!40101 BEGIN */`, and the one an `XA START` opens, none of which + /// the text can show. + var isInTransaction: Bool { + stateLock.lock() + defer { stateLock.unlock() } + return _isInTransaction + } + + private var _isInTransaction = false + + private func recordTransactionState(on mysql: UnsafeMutablePointer) { + var serverStatus: UInt32 = 0 + guard mariadb_get_info(mysql, MARIADB_CONNECTION_SERVER_STATUS, &serverStatus) == 0 else { return } + let isOpen = (serverStatus & UInt32(SERVER_STATUS_IN_TRANS)) != 0 + stateLock.lock() + _isInTransaction = isOpen + stateLock.unlock() + } + private var isShuttingDown: Bool { get { stateLock.lock() @@ -524,6 +547,7 @@ final class MariaDBPluginConnection: @unchecked Sendable { guard !isShuttingDown, let mysql = self.mysql else { throw MariaDBPluginError.notConnected } + defer { recordTransactionState(on: mysql) } let generation = cancellationGate.beginQuery() defer { cancellationGate.endQuery(generation) } @@ -842,6 +866,7 @@ final class MariaDBPluginConnection: @unchecked Sendable { guard !isShuttingDown, let mysql = self.mysql else { throw MariaDBPluginError.notConnected } + defer { recordTransactionState(on: mysql) } guard flavor.preparesOnServer else { return try executeQuerySync(DatabendLiteral.inline(query, parameters: parameters), rowCap: rowCap) @@ -950,6 +975,7 @@ final class MariaDBPluginConnection: @unchecked Sendable { continuation.finish(throwing: MariaDBPluginError.notConnected) return } + defer { recordTransactionState(on: mysql) } let generation = cancellationGate.beginQuery() defer { cancellationGate.endQuery(generation) } diff --git a/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift b/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift index 5e07d7746f..0f8e42873b 100644 --- a/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift +++ b/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift @@ -17,7 +17,12 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { /// The database a metadata read is scoped to. MySQL has no schema level, so this is what a /// caller means by "schema" everywhere in the catalog queries. - var activeDatabaseName: String { _activeDatabase } + /// + /// Guarded by `sessionLock`, because `switchDatabase` writes it from whichever task made the + /// switch and `connect()` reads it from the reacquire task to decide what to reconnect to. + var activeDatabaseName: String { + sessionLock.withLock { _activeDatabase } + } internal var cachedPrivilegeCatalog: PluginPrivilegeCatalog? @@ -25,10 +30,10 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { var flavor: MySQLServerFlavor { sessionLock.withLock { _flavor } } - /// What the session is holding that a reconnect would destroy. Tracked from the statements - /// that go through the driver, because MySQL will not answer the question: measured on 8.4.11, - /// an ordinary user is refused on every table that would report its own temporary tables, user - /// variables, locks or transaction. + /// What the session is holding that a reconnect would destroy. The open transaction comes + /// from the server's status flags; the rest is read from the statements that go through the + /// driver, because MySQL will not answer those: measured on 8.4.11, an ordinary user is + /// refused on every table that would report its own temporary tables, variables or locks. private var footprint = MySQLSessionFootprint() /// Set by `applyQueryTimeout` so any reconnect can put it back. The server forgets it, and a @@ -121,7 +126,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { port: config.port, user: config.username, password: config.password, - database: _activeDatabase, + database: activeDatabaseName, sslConfig: sslConfig, enableCleartextPlugin: config.additionalFields["enableCleartextPlugin"] == "true", queryTimeoutSeconds: config.additionalFields["queryTimeoutSeconds"].flatMap { Int($0) } ?? 0, @@ -189,7 +194,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { func ping() async throws { guard !sessionLock.withLock({ isReleased }) else { return } let conn = try requireLiveConnection() - defer { endOperation() } + defer { endOperation(on: conn) } _ = try await conn.executeQuery("SELECT 1", rowCap: nil) } @@ -215,7 +220,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { return try await executeWithReconnect(query: query, isRetry: false, rowCap: cap) } let conn = try await requireConnection() - defer { endOperation() } + defer { endOperation(on: conn) } noteActivity(query) let startTime = Date() let result = try await conn.executeParameterizedQuery(query, parameters: parameters, rowCap: cap) @@ -241,7 +246,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { func executeParameterized(query: String, parameters: [PluginCellValue]) async throws -> PluginQueryResult { let conn = try await requireConnection() - defer { endOperation() } + defer { endOperation(on: conn) } noteActivity(query) let startTime = Date() @@ -278,7 +283,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { let startTime = Date() let conn = try await requireConnection() - defer { endOperation() } + defer { endOperation(on: conn) } if countsAsActivity { noteActivity(query) } @@ -375,8 +380,14 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { } } - private func endOperation() { - sessionLock.withLock { activeOperations = max(0, activeOperations - 1) } + /// The server's answer about the transaction arrives with the reply to the statement, so it + /// is taken where the statement is handed back rather than guessed from the text. + private func endOperation(on conn: MariaDBPluginConnection) { + let isInTransaction = conn.isInTransaction + sessionLock.withLock { + footprint.observeServerTransaction(isOpen: isInTransaction) + activeOperations = max(0, activeOperations - 1) + } } /// Concurrent callers wait on the one attempt rather than each starting their own. A metadata @@ -554,7 +565,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { let query = """ SELECT COLUMN_NAME, GENERATION_EXPRESSION FROM INFORMATION_SCHEMA.COLUMNS - WHERE TABLE_SCHEMA = \'\(mysqlEscapeStringLiteral(_activeDatabase))\' + WHERE TABLE_SCHEMA = \'\(mysqlEscapeStringLiteral(activeDatabaseName))\' AND TABLE_NAME = \'\(mysqlEscapeStringLiteral(table))\' AND GENERATION_EXPRESSION <> \'\' """ @@ -579,7 +590,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { return [] } guard !flavor.isTiDB else { return try await tidbCheckConstraints(table: table) } - let database = mysqlEscapeStringLiteral(_activeDatabase) + let database = mysqlEscapeStringLiteral(activeDatabaseName) let safeTable = mysqlEscapeStringLiteral(table) let query: String if flavor.isMariaDB { @@ -616,7 +627,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { /// the bulk read reports a changed generation expression as no difference at all. func fetchAllColumns(schema: String?) async throws -> [String: [PluginColumnInfo]] { guard !flavor.isDatabend else { return try await databendAllColumns() } - let dbName = _activeDatabase + let dbName = activeDatabaseName let escapedDb = dbName.replacingOccurrences(of: "'", with: "''") let hasGenerationExpression = MySQLServerVersion.hasGenerationExpression( banner: _serverVersion, flavor: flavor @@ -706,7 +717,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { func fetchForeignKeys(table: String, schema: String?) async throws -> [PluginForeignKeyInfo] { guard !flavor.isDatabend else { return [] } - let dbName = _activeDatabase + let dbName = activeDatabaseName let escapedDb = dbName.replacingOccurrences(of: "'", with: "''") let escapedTable = table.replacingOccurrences(of: "'", with: "''") @@ -753,7 +764,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { /// The same builder the schema-wide list uses, with one more predicate. func fetchTriggers(table: String, schema: String?) async throws -> [PluginTriggerInfo] { guard !flavor.isDatabend else { return [] } - let dbName = schema?.isEmpty == false ? (schema ?? _activeDatabase) : _activeDatabase + let dbName = schema?.isEmpty == false ? (schema ?? activeDatabaseName) : activeDatabaseName let triggers = try await triggerList(schema: dbName, table: table) Self.logger.info("[trigger] mysql fetchTriggers db=\(dbName, privacy: .public) table=\(table, privacy: .public) parsed=\(triggers.count)") return triggers @@ -780,7 +791,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { func fetchAllForeignKeys(schema: String?) async throws -> [String: [PluginForeignKeyInfo]] { guard !flavor.isDatabend else { return [:] } - let dbName = _activeDatabase + let dbName = activeDatabaseName let escapedDb = dbName.replacingOccurrences(of: "'", with: "''") let query = """ @@ -825,7 +836,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { } func fetchApproximateRowCount(table: String, schema: String?) async throws -> Int? { - let dbName = _activeDatabase + let dbName = activeDatabaseName let escapedDb = dbName.replacingOccurrences(of: "'", with: "''") let escapedTable = table.replacingOccurrences(of: "'", with: "''") @@ -923,7 +934,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { let task = Task { do { let conn = try await requireConnection() - defer { self.endOperation() } + defer { self.endOperation(on: conn) } noteActivity(query) for try await element in conn.streamQuery(query) { continuation.yield(element) @@ -1022,13 +1033,20 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { /// switched to is not the session's to lose, and counting it would leave the footprint dirty /// from the first database switch onward. A `USE` the user types is a different statement: the /// driver does not know about it, a reconnect silently undoes it, and the footprint says so. + /// + /// The clock still moves, because a database switch is the user using the connection: leaving + /// it alone let the idle timer fire seconds after a switch and charge the next click a full + /// reconnect. func switchDatabase(to database: String) async throws { _ = try await executeWithReconnect( query: "USE \(quoteIdentifier(database))", isRetry: false, countsAsActivity: false ) - _activeDatabase = database + sessionLock.withLock { + _activeDatabase = database + lastActivity = ContinuousClock.now + } } // MARK: - Query Timeout diff --git a/Plugins/MySQLDriverPlugin/MySQLSessionFootprint.swift b/Plugins/MySQLDriverPlugin/MySQLSessionFootprint.swift index 38650a4716..340773b1af 100644 --- a/Plugins/MySQLDriverPlugin/MySQLSessionFootprint.swift +++ b/Plugins/MySQLDriverPlugin/MySQLSessionFootprint.swift @@ -17,10 +17,11 @@ import TableProPluginKit /// statement, every `GET_LOCK` advisory lock and `LAST_INSERT_ID`, and rolls an open transaction /// back reporting success. /// -/// This is tracked from the statement text rather than asked of the server, which is the opposite -/// of what the DuckDB driver does, because MySQL will not answer the question. Measured on MySQL -/// 8.4.11, a user granted only its own database is refused on every table that would report this: -/// error 1142 on `performance_schema.user_variables_by_thread`, `prepared_statements_instances`, +/// The open transaction is the server's own answer, from the status flags it puts in every reply +/// (`observeServerTransaction`). The rest is read from the statement text, because MySQL will not +/// answer those. Measured on MySQL 8.4.11, a user granted only its own database is refused on +/// every table that would report them: error 1142 on +/// `performance_schema.user_variables_by_thread`, `prepared_statements_instances`, /// `metadata_locks` and `events_transactions_current`, and error 1227 on /// `information_schema.INNODB_TRX` and `INNODB_TEMP_TABLE_INFO`. Asking would therefore work only /// for a privileged user, and `GET_LOCK` has no enumeration for anybody. Reading the statements @@ -36,6 +37,7 @@ struct MySQLSessionFootprint: Equatable { private(set) var hasPreparedStatements = false private(set) var hasAdvisoryLocks = false private(set) var hasLockedTables = false + private(set) var hasOpenHandlers = false private(set) var hasSessionSettings = false /// A `USE` the user ran themselves. The driver's own database switch does not come through @@ -66,6 +68,9 @@ struct MySQLSessionFootprint: Equatable { if hasAdvisoryLocks { return String(localized: "This connection holds advisory locks, which reconnecting would release.") } + if hasOpenHandlers { + return String(localized: "This connection has open HANDLER cursors, which reconnecting would close.") + } if hasPreparedStatements { return String(localized: "This connection has prepared statements, which reconnecting would discard.") } @@ -85,16 +90,29 @@ struct MySQLSessionFootprint: Equatable { } mutating func observe(_ sql: String) { - switch SQLTransactionTracking.effect(of: sql) { + for statement in SQLStatementSplitting.statements(in: sql) { + let body = Self.executableBody(of: statement) + observeTransaction(body) + observeStatement(body) + } + } + + /// The server's own answer, taken from the status flags in its last reply, which is exact + /// where reading the statements is a guess. Measured on MySQL 8.4.11: `SET autocommit = 0` + /// followed by a plain `SELECT` reports a transaction that appears nowhere in the text, and so + /// do `/*!40101 BEGIN */` and `XA START 'x'`. It is applied after the statement has run, so + /// the text-derived guess is what stands until the reply arrives. + mutating func observeServerTransaction(isOpen: Bool) { + hasOpenTransaction = isOpen + } + + private mutating func observeTransaction(_ statement: String) { + switch SQLTransactionTracking.effect(of: statement) { case .opens: hasOpenTransaction = true case .closes: hasOpenTransaction = false case .unchanged: break @unknown default: hasOpenTransaction = true } - - for statement in SQLStatementSplitting.statements(in: sql) { - observeStatement(statement) - } } /// Forgets everything, for a reconnect the driver has decided is safe. Only the statements @@ -104,33 +122,46 @@ struct MySQLSessionFootprint: Equatable { } private mutating func observeStatement(_ statement: String) { - let normalized = Self.executableBody(of: statement).uppercased() - guard !normalized.isEmpty else { return } + let normalized = statement.uppercased() + let head = Self.collapsedHead(of: normalized) + guard !head.isEmpty else { return } - if normalized.hasPrefix("CREATE TEMPORARY ") || normalized.hasPrefix("CREATE OR REPLACE TEMPORARY ") { + if head.hasPrefix("CREATE TEMPORARY ") || head.hasPrefix("CREATE OR REPLACE TEMPORARY ") { hasTemporaryTables = true } /// Set, not cleared: a drop names one table and says nothing about the others, and a /// session with a temporary table left is still one a reconnect would damage. - if normalized.hasPrefix("DROP TEMPORARY ") { + if head.hasPrefix("DROP TEMPORARY ") { hasTemporaryTables = true } - if normalized.hasPrefix("PREPARE ") { + if head.hasPrefix("PREPARE ") { hasPreparedStatements = true } - if normalized.hasPrefix("DEALLOCATE ") { + if head.hasPrefix("DEALLOCATE ") { hasPreparedStatements = true } - if normalized.hasPrefix("LOCK TABLE") { + if head.hasPrefix("LOCK TABLE") { hasLockedTables = true } - if normalized.hasPrefix("UNLOCK TABLES") { + /// `FLUSH TABLES WITH READ LOCK` takes a global read lock that is the session's and + /// nothing else's, and the sessions that hold one are idle by design while a backup + /// copies files. Measured on MySQL 8.4.11: a writer got error 1205 while it was held, and + /// the same write went through the moment the holding connection was killed. + if head.hasPrefix("FLUSH "), Self.isFlushHoldingALock(normalized) { + hasLockedTables = true + } + if head.hasPrefix("UNLOCK TABLES") { hasLockedTables = false } - if normalized.hasPrefix("CALL ") { + /// Set, not cleared, for the same reason a dropped temporary table is: a `HANDLER ... CLOSE` + /// names one cursor. + if head.hasPrefix("HANDLER ") { + hasOpenHandlers = true + } + if head.hasPrefix("CALL ") { ranOpaqueRoutine = true } - if normalized.hasPrefix("USE ") { + if head.hasPrefix("USE ") { hasChangedDatabase = true } if normalized.contains("GET_LOCK(") { @@ -139,8 +170,8 @@ struct MySQLSessionFootprint: Equatable { if normalized.contains("RELEASE_ALL_LOCKS(") { hasAdvisoryLocks = false } - if normalized.hasPrefix("SET ") { - observeSet(normalized) + if head.hasPrefix("SET ") { + observeSet(head) } /// `SELECT ... INTO @x` and `EXECUTE ... INTO @x` write a user variable without a leading /// `SET`, and `SELECT @x := 1` writes one without either. Both spellings lose the variable @@ -150,24 +181,53 @@ struct MySQLSessionFootprint: Equatable { } } - /// What MySQL runs when the statement is one of its version-gated comments, and the statement - /// itself otherwise. + /// What MySQL runs when the statement opens with one of its version-gated comments, and the + /// statement itself otherwise. /// /// `/*!40101 SET NAMES utf8mb4 */` is executed by any server from 4.1.1, and MariaDB spells /// its own `/*M!100301 ... */`. mysqldump writes its whole preamble this way, so a restore run - /// from the editor sets `character_set_client`, the time zone and half a dozen `@OLD_` - /// variables inside them. `SQLStatementSplitting` leaves them whole rather than reading them - /// as comments, because only the engine that executes the body can say what it is. + /// from the editor sets the character set, the time zone and eight `@OLD_` variables inside + /// them. `SQLStatementSplitting` leaves them whole rather than reading them as comments, + /// because only the engine that executes the body can say what it is. + /// + /// Whatever follows the comment is kept, so a line that carries a note after it, or a second + /// version-gated block, is still classified by the first thing the server would run. The + /// version number itself is not checked against the server: counting a statement the server + /// is too old to run holds a connection that is in fact clean, which is the safe direction. private static func executableBody(of statement: String) -> String { guard statement.hasPrefix("/*!") || statement.hasPrefix("/*M!") else { return statement } - guard let close = statement.range(of: "*/"), - statement[close.upperBound...].allSatisfy({ $0.isWhitespace }) else { return statement } + guard let close = statement.range(of: "*/") else { return statement } let marked = statement[statement.index(statement.startIndex, offsetBy: 2).. String { + normalized + .prefix(headLength) + .split(whereSeparator: { $0.isWhitespace }) + .joined(separator: " ") + } + + private static let headLength = 64 + + /// A `FLUSH` names its tables before the clause that matters, and a list of them runs past + /// the head, so this one reads the whole statement. No `FLUSH` is long enough for that to + /// cost anything. + private static func isFlushHoldingALock(_ normalized: String) -> Bool { + let collapsed = normalized.split(whereSeparator: { $0.isWhitespace }).joined(separator: " ") + return collapsed.contains(" WITH READ LOCK") || collapsed.contains(" FOR EXPORT") } /// `SET` covers three different things: a user variable (`SET @x = 1`), a session setting @@ -177,7 +237,10 @@ struct MySQLSessionFootprint: Equatable { private mutating func observeSet(_ normalized: String) { let body = normalized.dropFirst("SET ".count).trimmingCharacters(in: .whitespaces) guard !body.hasPrefix("@@GLOBAL."), !body.hasPrefix("GLOBAL ") else { return } - if body.hasPrefix("@") { + /// `@@` is a system variable under another spelling, not a user variable: reporting + /// `SET @@SESSION.sql_mode` as "session variables set" blocks the release for the right + /// reason and tells the user the wrong one. + if body.hasPrefix("@"), !body.hasPrefix("@@") { hasUserVariables = true } else { hasSessionSettings = true diff --git a/Plugins/MySQLDriverPlugin/MySQLStatementClassification.swift b/Plugins/MySQLDriverPlugin/MySQLStatementClassification.swift index f1ccf27b4c..ccf55c9acc 100644 --- a/Plugins/MySQLDriverPlugin/MySQLStatementClassification.swift +++ b/Plugins/MySQLDriverPlugin/MySQLStatementClassification.swift @@ -23,6 +23,12 @@ internal func mysqlStatementIsReadOnly(_ query: String) -> Bool { /// re-run burns a second sequence value while the grid shows one, and `SELECT GET_LOCK(...)` takes /// the lock again. Neither reports anything: the retry looks like a connection that healed itself. /// +/// The last four change nothing and are here for the other half of the same problem: their answer +/// belongs to the session that ran the statement before them, and the replay runs on a new one. +/// Measured on MySQL 8.4.11, a fresh connection answers `SELECT LAST_INSERT_ID()` with `0`, so an +/// `INSERT` followed by a dropped connection and a replayed `SELECT LAST_INSERT_ID()` showed `0` +/// for a row that had an id. The footprint cannot cover these: an `INSERT` leaves it clean. +/// /// The scan is deliberately crude and only ever errs toward "do not replay", which costs the user a /// connection error where they would have got a transparent retry. It cannot see inside a stored /// function, so a `SELECT my_function()` that writes is still replayable. @@ -33,6 +39,7 @@ private let mysqlSideEffectingMarkers: [String] = [ "FOR UPDATE", "FOR SHARE", "LOCK IN SHARE MODE", "UUID_SHORT", "MASTER_POS_WAIT", "SOURCE_POS_WAIT", "BENCHMARK", "SLEEP", ":=", + "LAST_INSERT_ID", "ROW_COUNT", "FOUND_ROWS", "CONNECTION_ID", ] /// Whether a statement the server dropped the connection under can be run again on the session diff --git a/TableProTests/Plugins/MySQLSessionFootprintTests.swift b/TableProTests/Plugins/MySQLSessionFootprintTests.swift index a795298f3b..3c44cc3d83 100644 --- a/TableProTests/Plugins/MySQLSessionFootprintTests.swift +++ b/TableProTests/Plugins/MySQLSessionFootprintTests.swift @@ -110,10 +110,10 @@ struct MySQLSessionFootprintTests { #expect(footprint(after: "SELECT @counter := 1").hasUserVariables) } - /// mysqldump writes its whole preamble as version-gated comments, which MySQL executes. They - /// read as comments, so the statement splitter used to drop them and a restore run from the - /// editor left the session holding six user variables and two session settings that the - /// footprint reported as nothing. + /// mysqldump writes its whole preamble as version-gated comments, which MySQL executes: eight + /// `@OLD_` variables and the character set, time zone and check settings, plus one + /// `@saved_cs_client` per table. They read as comments, so the statement splitter used to + /// drop them and a restore run from the editor left a session the footprint called clean. @Test("A version-gated comment sets session state, and is seen") func versionGatedCommentsAreSeen() { let preamble = """ @@ -149,6 +149,99 @@ struct MySQLSessionFootprintTests { #expect(footprint(after: "SELECT * FROM t USE INDEX (i)").isClean) } + /// The two gates read different things: the replay asks `isClean` and the idle release asks + /// `blockingReason`. A flag added without an arm in the ladder would tighten one and leave + /// the other handing the connection back. + @Test("Every flag that makes the footprint dirty also gives a reason") + func everyFlagGivesAReason() { + for statement in [ + "CREATE TEMPORARY TABLE staging (a INT)", + "SET @total = 5", + "PREPARE stmt FROM 'SELECT 1'", + "SELECT GET_LOCK('job', 10)", + "LOCK TABLES users WRITE", + "FLUSH TABLES WITH READ LOCK", + "HANDLER users OPEN", + "SET SESSION sql_mode = 'ANSI'", + "USE reporting", + "CALL rebuild_report()", + ] { + let result = footprint(after: statement) + #expect(result.isClean == (result.blockingReason == nil), "\(statement)") + #expect(!result.isClean, "\(statement)") + } + var open = MySQLSessionFootprint() + open.observeServerTransaction(isOpen: true) + #expect(open.isClean == (open.blockingReason == nil)) + } + + /// The server answers this one itself, in the status flags of every reply, and it is exact + /// where the text is a guess. Measured on MySQL 8.4.11: `SET autocommit = 0` followed by a + /// plain `SELECT` reports a transaction that appears nowhere in the statements. + @Test("The server's own transaction flag wins over what the text said") + func serverTransactionFlagWins() { + var result = footprint(after: "SELECT 1") + result.observeServerTransaction(isOpen: true) + #expect(result.hasOpenTransaction) + #expect(!result.isClean) + + var closed = footprint(after: "BEGIN") + #expect(closed.hasOpenTransaction) + closed.observeServerTransaction(isOpen: false) + #expect(closed.isClean) + } + + /// A transaction opened inside a version-gated comment runs on the server. Measured on MySQL + /// 8.4.11 through `information_schema.INNODB_TRX`: `/*!40101 BEGIN */` then an `INSERT` leaves + /// one transaction open, and a `ROLLBACK` discards the row. + @Test("A transaction opened inside a version-gated comment is seen") + func versionGatedTransactionsAreSeen() { + #expect(footprint(after: "/*!40101 BEGIN */").hasOpenTransaction) + #expect(footprint(after: "/*!40101 START TRANSACTION */").hasOpenTransaction) + #expect(footprint(after: "/*!40101 BEGIN */", "/*!40101 COMMIT */").isClean) + } + + /// `FLUSH TABLES WITH READ LOCK` takes a lock that is the session's alone, and the session + /// holding one is idle by design while a backup copies files, which is exactly when the idle + /// release fires. Measured on MySQL 8.4.11: a writer got error 1205 while it was held, and + /// the same write went through the moment the holding connection was killed. + @Test("A global read lock and an open HANDLER block a release") + func locksOutsideLockTablesAreTracked() { + #expect(footprint(after: "FLUSH TABLES WITH READ LOCK").hasLockedTables) + #expect(footprint(after: "FLUSH TABLES users, orders FOR EXPORT").hasLockedTables) + #expect(footprint(after: "FLUSH PRIVILEGES").isClean) + #expect(footprint(after: "HANDLER users OPEN").hasOpenHandlers) + #expect(footprint(after: "HANDLER users READ FIRST").hasOpenHandlers) + } + + /// The prefix checks used to run against the raw text, so one extra space or a line break + /// between the keywords hid the statement completely. + @Test("Whitespace between the keywords does not hide a statement") + func whitespaceDoesNotHideAStatement() { + #expect(footprint(after: "CREATE TEMPORARY TABLE staging (a INT)").hasTemporaryTables) + #expect(footprint(after: "CREATE TEMPORARY\nTABLE staging (a INT)").hasTemporaryTables) + #expect(footprint(after: "PREPARE\n stmt FROM 'SELECT 1'").hasPreparedStatements) + #expect(footprint(after: "SET\n @x = 1").hasUserVariables) + } + + /// A dump line that carries a note after its version-gated comment, or two of them on one + /// line, is still a statement the server runs. + @Test("Text after a version-gated comment does not hide what it ran") + func trailingTextAfterAVersionGatedComment() { + #expect(footprint(after: "/*!40101 SET @x = 1 */ -- saved").hasUserVariables) + #expect(footprint(after: "/*!40101 SET @x = 1 */ /*!40103 SET @y = 2 */").hasUserVariables) + #expect(footprint(after: "/*!40101 SET @x = 1").isClean) + } + + /// `@@` is a system variable under another spelling. The release is blocked either way; the + /// reason the user reads should be the right one. + @Test("A system variable set with @@ reads as a session setting") + func systemVariablesAreNotUserVariables() { + let result = footprint(after: "SET @@SESSION.sql_mode = 'ANSI'") + #expect(result.hasSessionSettings) + #expect(!result.hasUserVariables) + } + @Test("A reset clears everything, for a session that is genuinely new") func resetClearsEverything() { var result = footprint(after: "BEGIN", "CREATE TEMPORARY TABLE staging (a INT)") diff --git a/TableProTests/Plugins/MySQLStatementClassificationTests.swift b/TableProTests/Plugins/MySQLStatementClassificationTests.swift index 6903a627a6..8b083afefe 100644 --- a/TableProTests/Plugins/MySQLStatementClassificationTests.swift +++ b/TableProTests/Plugins/MySQLStatementClassificationTests.swift @@ -133,13 +133,37 @@ struct MySQLReplaySafetyTests { "CREATE TEMPORARY TABLE staging (a INT)", "PREPARE stmt FROM 'SELECT 1'", "LOCK TABLES users WRITE", + "FLUSH TABLES WITH READ LOCK", + "HANDLER users OPEN", "USE reporting", "BEGIN", + "/*!40101 BEGIN */", "CALL rebuild_report()", "/*!40103 SET TIME_ZONE='+00:00' */", ] { #expect(!mysqlMayReplay("SELECT * FROM users", on: footprint(after: statement)), "\(statement)") } + + var serverSideTransaction = MySQLSessionFootprint() + serverSideTransaction.observeServerTransaction(isOpen: true) + #expect(!mysqlMayReplay("SELECT * FROM users", on: serverSideTransaction)) + } + + /// These change nothing, so the footprint stays clean, and their answer still belongs to the + /// session that ran the statement before them. Measured on MySQL 8.4.11: a fresh connection + /// answers `SELECT LAST_INSERT_ID()` with `0`, so an `INSERT`, a dropped connection and a + /// replayed read showed `0` for a row that had an id. + @Test("A read of a session-scoped value is never replayed") + func sessionScopedReadsAreNotReplayed() { + for query in [ + "SELECT LAST_INSERT_ID()", + "SELECT ROW_COUNT()", + "SELECT FOUND_ROWS()", + "SELECT CONNECTION_ID()", + "select last_insert_id()", + ] { + #expect(!mysqlMayReplay(query, on: MySQLSessionFootprint()), "\(query)") + } } @Test("A statement that is unsafe on its own is not replayed on a clean session either") diff --git a/TableProTests/Plugins/SQLStatementSplittingTests.swift b/TableProTests/Plugins/SQLStatementSplittingTests.swift index 83c678562c..ca0a54ed5f 100644 --- a/TableProTests/Plugins/SQLStatementSplittingTests.swift +++ b/TableProTests/Plugins/SQLStatementSplittingTests.swift @@ -44,10 +44,17 @@ struct SQLStatementSplittingTests { ) } - /// Keeping it must not make it read as a transaction statement. The keyword is no longer the - /// first word of the statement, and closing already requires the whole statement to be one. - @Test("A transaction keyword inside a version-gated comment does not close a transaction") + /// Keeping it must not make it read as a transaction statement here. The keyword is no longer + /// the first word of the statement, and closing already requires the whole statement to be + /// one. `MySQLSessionFootprint` reads the body itself, because MySQL does run it; every other + /// caller treats the whole thing as a statement it does not recognise. + /// + /// `/*! */ COMMIT` is the case that tells the two implementations apart: stripping the + /// comment left a bare `COMMIT` and read as `.closes`. + @Test("A transaction keyword around a version-gated comment does not close a transaction") func executableCommentsNeverClose() { + #expect(SQLTransactionTracking.effect(of: "BEGIN; /*! */ COMMIT") == .opens) + #expect(SQLTransactionTracking.effect(of: "/*! */ COMMIT") == .unchanged) #expect(SQLTransactionTracking.effect(of: "BEGIN; /*!40101 COMMIT */") == .opens) #expect(SQLTransactionTracking.effect(of: "/*!40101 COMMIT */") == .unchanged) } diff --git a/docs/databases/mysql.mdx b/docs/databases/mysql.mdx index 35812037f2..3afe2dcbfc 100644 --- a/docs/databases/mysql.mdx +++ b/docs/databases/mysql.mdx @@ -74,13 +74,13 @@ To stop the check itself, set **Check connections** to **Only when I use the con Reconnecting costs a TCP connect, the TLS handshake and authentication: measured at 2ms against a server on the same machine and 800ms to 1.9s across the internet. That cost lands on the first query after an idle period, so leave this at `0` for a remote server unless the slot matters more than the wait. -A release is refused, with the reason, while the session holds anything a reconnect would destroy: an open transaction, a temporary table, a prepared statement, a `GET_LOCK`, `LOCK TABLES`, a user variable, a changed session setting, a database selected with `USE`, or a stored routine call, whose body is opaque. The statements a dump runs inside `/*!40101 ... */` count, since the server executes them. +A release is refused, with the reason, while the session holds anything a reconnect would destroy: an open transaction, a temporary table, a prepared statement, a `GET_LOCK`, `LOCK TABLES`, `FLUSH TABLES WITH READ LOCK`, an open `HANDLER`, a user variable, a changed session setting, a database selected with `USE`, or a stored routine call, whose body is opaque. The statements a dump runs inside `/*!40101 ... */` count, since the server executes them. The transaction comes from the server itself, so one opened by `SET autocommit = 0` or by an `XA START` counts as well. ## When the server drops the connection -A read that fails because the server closed the connection is run once more on a new one, and only from a session holding nothing: the same list as above. Every other statement reports the error, because the second session answers from different state. Measured on MySQL 8.4.11, replaying regardless: `SELECT @total` came back `NULL` where it had come back 42, and `SELECT DATABASE()` came back as the connection's own database rather than the one `USE` had selected, neither of them raising anything. +A read that fails because the server closed the connection is run once more on a new one, and only from a session holding nothing: the same list as above. Every other statement reports the error, because the second session answers from different state. Measured on MySQL 8.4.11, replaying regardless: `SELECT @total` came back `NULL` where it had come back 42, and `SELECT DATABASE()` came back as the connection's own database rather than the one `USE` had selected, neither of them raising anything. `LAST_INSERT_ID()`, `ROW_COUNT()`, `FOUND_ROWS()` and `CONNECTION_ID()` are never replayed either, whatever the session holds: their answer belongs to the connection that is gone. -**Database > Reconnect** takes a new connection and puts back the database, the schema and the startup commands. +A connection with startup commands that run `SET` is holding a changed session setting from the moment it opens, so it reports the error rather than retrying. **Database > Reconnect** takes a new connection and puts back the database and the startup commands. ## Garbled non-Latin text From 42903a71a519d31c509bccd5f643d01e0727c452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 01:17:52 +0700 Subject: [PATCH 19/54] fix(plugin-postgresql): end COPY state so the connection stays usable (#2755) --- CHANGELOG.md | 1 + ...ibPQCopyDirection+UnsupportedMessage.swift | 19 +++ .../LibPQCopyState.swift | 76 +++++++++++ .../LibPQPendingResultDrain.swift | 60 +++++++++ .../LibPQPluginConnection.swift | 106 ++++++++++++--- .../Drivers/PostgreSQLCopyState.swift | 14 ++ .../Drivers/PostgreSQLDriver.swift | 57 +++++++- .../Drivers/PostgreSQLCopyStateTests.swift | 61 +++++++++ TableProMobile/project.yml | 3 + .../LibPQPendingResultDrainTests.swift | 124 ++++++++++++++++++ project.yml | 2 + 11 files changed, 500 insertions(+), 23 deletions(-) create mode 100644 Plugins/PostgreSQLDriverPlugin/LibPQCopyDirection+UnsupportedMessage.swift create mode 100644 Plugins/PostgreSQLDriverPlugin/LibPQCopyState.swift create mode 100644 Plugins/PostgreSQLDriverPlugin/LibPQPendingResultDrain.swift create mode 100644 TableProMobile/TableProMobile/Drivers/PostgreSQLCopyState.swift create mode 100644 TableProMobile/TableProMobileTests/Drivers/PostgreSQLCopyStateTests.swift create mode 100644 TableProTests/Plugins/LibPQPendingResultDrainTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 84212484b2..bbb304422b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Wrong SQLSTATE code in PostgreSQL, Redshift, CockroachDB and PGlite error messages. - Read-only write explanation never shown on PostgreSQL servers. - Safe Mode minimum from a configuration profile missing from the toolbar, the Database menu and the connection form. (#2030) +- PostgreSQL connection hanging after running `COPY FROM STDIN` or `COPY TO STDOUT` in the query editor and on iOS. - Stop not ending queries on MySQL and MariaDB servers without TLS. - Wrong results after MySQL retakes a dropped connection, on a session that had set a variable, a session setting or a database. - Session state set by the `/*! ... */` statements a MySQL dump writes counting as a comment. diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQCopyDirection+UnsupportedMessage.swift b/Plugins/PostgreSQLDriverPlugin/LibPQCopyDirection+UnsupportedMessage.swift new file mode 100644 index 0000000000..5feed69b60 --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/LibPQCopyDirection+UnsupportedMessage.swift @@ -0,0 +1,19 @@ +// +// LibPQCopyDirection+UnsupportedMessage.swift +// PostgreSQLDriverPlugin +// + +import Foundation + +nonisolated extension LibPQCopyDirection { + var unsupportedMessage: String { + switch self { + case .copyIn: + return String(localized: "The query editor cannot send data to COPY FROM STDIN, so no rows were sent. Use Import to load a file into a table.") + case .copyOut: + return String(localized: "The query editor cannot receive the output of COPY TO STDOUT, so it was discarded. Run a SELECT, or use Export to save the rows to a file.") + case .copyBoth: + return String(localized: "The query editor cannot run a replication COPY.") + } + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQCopyState.swift b/Plugins/PostgreSQLDriverPlugin/LibPQCopyState.swift new file mode 100644 index 0000000000..eb25f8e47f --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/LibPQCopyState.swift @@ -0,0 +1,76 @@ +// +// LibPQCopyState.swift +// PostgreSQLDriverPlugin +// + +import CLibPQ +import Foundation + +nonisolated enum LibPQCopyState { + static let unsentInputReason = "no COPY data was sent" + + static func copy(of result: OpaquePointer) -> LibPQCopy? { + guard let direction = direction(of: PQresultStatus(result)) else { return nil } + return LibPQCopy(direction: direction, format: PQbinaryTuples(result) == 1 ? .binary : .textual) + } + + static func direction(of status: ExecStatusType) -> LibPQCopyDirection? { + switch status { + case PGRES_COPY_IN: return .copyIn + case PGRES_COPY_OUT: return .copyOut + case PGRES_COPY_BOTH: return .copyBoth + default: return nil + } + } + + static func finishPendingResults(_ conn: OpaquePointer, cancellingOutput: Bool) -> LibPQDrainOutcome { + LibPQPendingResultDrain.drain( + nextResult: { + guard let result = PQgetResult(conn) else { return nil } + defer { PQclear(result) } + return copy(of: result).map(LibPQPendingResult.copy) ?? .completed + }, + endCopy: { end($0, conn: conn, cancellingOutput: cancellingOutput) } + ) + } + + /// A textual or CSV `COPY FROM STDIN` ends with CopyDone, which completes the statement with + /// zero rows and leaves an open transaction in `INTRANS`. CopyFail aborts the transaction, so + /// it is kept for binary input alone, where CopyDone fails on the missing file signature. + /// Measured on 9.1.24 and 17.11. + static func end(_ copy: LibPQCopy, conn: OpaquePointer, cancellingOutput: Bool) { + switch copy.direction { + case .copyIn: + endInput(copy, conn: conn) + case .copyOut: + discardOutput(conn, cancelling: cancellingOutput) + case .copyBoth: + endInput(copy, conn: conn) + discardOutput(conn, cancelling: cancellingOutput) + } + } + + private static func endInput(_ copy: LibPQCopy, conn: OpaquePointer) { + guard copy.format == .binary else { + _ = PQputCopyEnd(conn, nil) + return + } + _ = unsentInputReason.withCString { PQputCopyEnd(conn, $0) } + } + + private static func discardOutput(_ conn: OpaquePointer, cancelling: Bool) { + if cancelling { cancelStatement(conn) } + var buffer: UnsafeMutablePointer? + while PQgetCopyData(conn, &buffer, 0) > 0 { + PQfreemem(buffer) + buffer = nil + } + } + + private static func cancelStatement(_ conn: OpaquePointer) { + guard let cancelObject = PQgetCancel(conn) else { return } + defer { PQfreeCancel(cancelObject) } + var errbuf = [CChar](repeating: 0, count: 256) + PQcancel(cancelObject, &errbuf, Int32(errbuf.count)) + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQPendingResultDrain.swift b/Plugins/PostgreSQLDriverPlugin/LibPQPendingResultDrain.swift new file mode 100644 index 0000000000..204df32393 --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/LibPQPendingResultDrain.swift @@ -0,0 +1,60 @@ +// +// LibPQPendingResultDrain.swift +// PostgreSQLDriverPlugin +// + +import Foundation + +nonisolated enum LibPQCopyDirection: Sendable, Equatable { + case copyIn + case copyOut + case copyBoth +} + +nonisolated enum LibPQCopyFormat: Sendable, Equatable { + case textual + case binary +} + +nonisolated struct LibPQCopy: Sendable, Equatable { + let direction: LibPQCopyDirection + let format: LibPQCopyFormat +} + +nonisolated enum LibPQPendingResult: Sendable, Equatable { + case copy(LibPQCopy) + case completed +} + +nonisolated struct LibPQDrainOutcome: Sendable, Equatable { + let endedCopies: [LibPQCopy] + let stuckInCopy: LibPQCopy? + + static let idle = LibPQDrainOutcome(endedCopies: [], stuckInCopy: nil) + + var abandonedCopy: LibPQCopy? { endedCopies.first ?? stuckInCopy } + var leavesConnectionUnusable: Bool { stuckInCopy != nil } +} + +nonisolated enum LibPQPendingResultDrain { + static func drain( + nextResult: () -> LibPQPendingResult?, + endCopy: (LibPQCopy) -> Void + ) -> LibPQDrainOutcome { + var endedCopies: [LibPQCopy] = [] + var copyAwaitingCompletion: LibPQCopy? + while let pending = nextResult() { + guard case .copy(let copy) = pending else { + copyAwaitingCompletion = nil + continue + } + if let unfinished = copyAwaitingCompletion { + return LibPQDrainOutcome(endedCopies: endedCopies, stuckInCopy: unfinished) + } + copyAwaitingCompletion = copy + endedCopies.append(copy) + endCopy(copy) + } + return LibPQDrainOutcome(endedCopies: endedCopies, stuckInCopy: nil) + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift b/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift index eb7958f0ef..58bfbf0129 100644 --- a/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift +++ b/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift @@ -548,6 +548,7 @@ final class LibPQPluginConnection: @unchecked Sendable { let generation = cancellationGate.beginQuery() defer { cancellationGate.endQuery(generation) } + let cancelsOutput = cancelsAbandonedOutput(conn) let localQuery = String(query) let result: OpaquePointer? = localQuery.withCString { queryPtr in PQexec(conn, queryPtr) @@ -580,6 +581,10 @@ final class LibPQPluginConnection: @unchecked Sendable { return try fetchResults(from: result, conn: conn, generation: generation) default: + if let copy = LibPQCopyState.copy(of: result) { + PQclear(result) + throw abandonedCopyError(copy, conn: conn, cancellingOutput: cancelsOutput, generation: generation) + } let error = getResultError(from: result) PQclear(result) if cancellationGate.isCancelled(generation) { throw CancellationError() } @@ -609,14 +614,14 @@ final class LibPQPluginConnection: @unchecked Sendable { /// Started before the drain, so a result the previous statement abandoned is charged to the /// time before the first row rather than appearing as this query's row transfer. let sentAt = Date() - while let stale = PQgetResult(conn) { PQclear(stale) } /// Cancelling a statement inside a transaction block puts the transaction into the aborted /// state, and every later command fails until ROLLBACK. Reading the tail of one result costs /// less than throwing away the transaction the user opened, so the cancel is withheld here /// and the connection is drained instead. - let insideTransaction = PQtransactionStatus(conn) == PQTRANS_INTRANS - let suppressCancel = suppressServerSideCancel || insideTransaction + let cancelsOutput = cancelsAbandonedOutput(conn) + let suppressCancel = !cancelsOutput + _ = finishPendingResults(conn, cancellingOutput: cancelsOutput) let localQuery = String(query) let sendOk = localQuery.withCString { queryPtr in @@ -625,7 +630,7 @@ final class LibPQPluginConnection: @unchecked Sendable { guard sendOk != 0 else { throw getError(from: conn) } guard PQsetSingleRowMode(conn) != 0 else { - Self.cancelAndDrain(conn, suppressCancel: suppressCancel) + _ = cancelAndDrain(conn, suppressCancel: suppressCancel) throw LibPQPluginError(message: "Failed to enter single-row mode", sqlState: nil, detail: nil) } @@ -660,7 +665,7 @@ final class LibPQPluginConnection: @unchecked Sendable { rows.append(row) if cancellationGate.isCancelled(generation) { - Self.cancelAndDrain(conn, suppressCancel: suppressCancel) + _ = cancelAndDrain(conn, suppressCancel: suppressCancel) throw CancellationError() } if rows.count > rowCap { @@ -683,22 +688,27 @@ final class LibPQPluginConnection: @unchecked Sendable { continue } + if let copy = LibPQCopyState.copy(of: result) { + pendingError = Self.unsupportedCopyError(copy) + PQclear(result) + break + } + pendingError = getResultError(from: result) PQclear(result) break } - if truncated { - Self.cancelAndDrain(conn, suppressCancel: suppressCancel) - } else { - while let trailing = PQgetResult(conn) { PQclear(trailing) } - } + let outcome = truncated + ? cancelAndDrain(conn, suppressCancel: suppressCancel) + : finishPendingResults(conn, cancellingOutput: cancelsOutput) if let pendingError { if cancellationGate.isCancelled(generation) { throw CancellationError() } throw pendingError } if cancellationGate.isCancelled(generation) { throw CancellationError() } + if let abandoned = abandonedCopyError(outcome, generation: generation) { throw abandoned } if truncated { rows.removeLast() } @@ -729,6 +739,7 @@ final class LibPQPluginConnection: @unchecked Sendable { let generation = cancellationGate.beginQuery() defer { cancellationGate.endQuery(generation) } + let cancelsOutput = cancelsAbandonedOutput(conn) var paramValues: [UnsafePointer?] = [] var paramLengths: [Int32] = [] var paramFormats: [Int32] = [] @@ -818,6 +829,10 @@ final class LibPQPluginConnection: @unchecked Sendable { return try fetchResults(from: result, conn: conn, generation: generation) default: + if let copy = LibPQCopyState.copy(of: result) { + PQclear(result) + throw abandonedCopyError(copy, conn: conn, cancellingOutput: cancelsOutput, generation: generation) + } let error = getResultError(from: result) PQclear(result) if cancellationGate.isCancelled(generation) { throw CancellationError() } @@ -825,9 +840,52 @@ final class LibPQPluginConnection: @unchecked Sendable { } } + // MARK: - Pending Results + + /// A statement the user did not get to see is worse than a slow one, so a COPY ended by any + /// drain is reported rather than swallowed: `INSERT INTO t VALUES (1); COPY t FROM STDIN` used + /// to come back as "INSERT 0 1" with the COPY discarded. + private func abandonedCopyError(_ outcome: LibPQDrainOutcome, generation: Int) -> Error? { + guard let copy = outcome.abandonedCopy else { return nil } + if cancellationGate.isCancelled(generation) { return CancellationError() } + return Self.unsupportedCopyError(copy) + } + + private func abandonedCopyError( + _ copy: LibPQCopy, + conn: OpaquePointer, + cancellingOutput: Bool, + generation: Int + ) -> Error { + _ = finishPendingResults(conn, cancellingOutput: cancellingOutput) + if cancellationGate.isCancelled(generation) { return CancellationError() } + return Self.unsupportedCopyError(copy) + } + + private static func unsupportedCopyError(_ copy: LibPQCopy) -> LibPQPluginError { + LibPQPluginError(message: copy.direction.unsupportedMessage, sqlState: nil, detail: nil) + } + + /// Reading `COPY TO STDOUT` to its end defeats the row cap the bounded read exists for, so the + /// statement is cancelled first wherever a cancel is safe. Inside a transaction block it is not, + /// because a cancel aborts the transaction the user opened. + private func cancelsAbandonedOutput(_ conn: OpaquePointer) -> Bool { + !suppressServerSideCancel && PQtransactionStatus(conn) != PQTRANS_INTRANS + } + + private func finishPendingResults(_ conn: OpaquePointer, cancellingOutput: Bool) -> LibPQDrainOutcome { + let outcome = LibPQCopyState.finishPendingResults(conn, cancellingOutput: cancellingOutput) + guard let stuck = outcome.stuckInCopy else { return outcome } + logger.fault( + "libpq stayed in \(String(describing: stuck.direction), privacy: .public); dropping the connection" + ) + disconnect() + return outcome + } + // MARK: - Streaming Query - private static func cancelAndDrain(_ conn: OpaquePointer, suppressCancel: Bool) { + private func cancelAndDrain(_ conn: OpaquePointer, suppressCancel: Bool) -> LibPQDrainOutcome { if !suppressCancel { let cancelObj = PQgetCancel(conn) if let cancelObj { @@ -836,7 +894,7 @@ final class LibPQPluginConnection: @unchecked Sendable { PQfreeCancel(cancelObj) } } - while let res = PQgetResult(conn) { PQclear(res) } + return finishPendingResults(conn, cancellingOutput: false) } /// The abort is polled by the producer rather than acted on from `onTermination`, because both @@ -866,12 +924,11 @@ final class LibPQPluginConnection: @unchecked Sendable { return } - while let res = PQgetResult(conn) { PQclear(res) } - /// Read before the query goes out: once it is in flight the status is /// PQTRANS_ACTIVE, and the transaction this guard exists for is invisible. - let suppressCancel = suppressServerSideCancel - || PQtransactionStatus(conn) == PQTRANS_INTRANS + let cancelsOutput = cancelsAbandonedOutput(conn) + let suppressCancel = !cancelsOutput + _ = finishPendingResults(conn, cancellingOutput: cancelsOutput) let sendOk = queryToRun.withCString { queryPtr in PQsendQuery(conn, queryPtr) @@ -883,7 +940,7 @@ final class LibPQPluginConnection: @unchecked Sendable { } if PQsetSingleRowMode(conn) == 0 { - Self.cancelAndDrain(conn, suppressCancel: suppressCancel) + _ = cancelAndDrain(conn, suppressCancel: suppressCancel) continuation.finish(throwing: LibPQPluginError( message: "Failed to enter single-row mode", sqlState: nil, detail: nil)) return @@ -951,7 +1008,7 @@ final class LibPQPluginConnection: @unchecked Sendable { if !batch.isEmpty { continuation.yield(.rows(batch)) } - Self.cancelAndDrain(conn, suppressCancel: suppressCancel) + _ = cancelAndDrain(conn, suppressCancel: suppressCancel) continuation.finish(throwing: CancellationError()) return } @@ -962,10 +1019,15 @@ final class LibPQPluginConnection: @unchecked Sendable { lastCommandTag = getCommandTag(from: result) PQclear(result) break + } else if let copy = LibPQCopyState.copy(of: result) { + PQclear(result) + continuation.finish(throwing: abandonedCopyError( + copy, conn: conn, cancellingOutput: cancelsOutput, generation: generation)) + return } else { let error = getResultError(from: result) PQclear(result) - while let res = PQgetResult(conn) { PQclear(res) } + _ = finishPendingResults(conn, cancellingOutput: cancelsOutput) if cancellationGate.isCancelled(generation) { continuation.finish(throwing: CancellationError()) return @@ -979,7 +1041,7 @@ final class LibPQPluginConnection: @unchecked Sendable { continuation.yield(.rows(batch)) } - while let res = PQgetResult(conn) { PQclear(res) } + let outcome = finishPendingResults(conn, cancellingOutput: cancelsOutput) /// The header went out with the first row, so this stream keeps what it said; /// the lookup is for the results that follow. let missing = unresolvedOids(in: columnOids) @@ -987,6 +1049,10 @@ final class LibPQPluginConnection: @unchecked Sendable { learnTypeNames(for: missing, conn: conn) } noteCommandTag(lastCommandTag, conn: conn) + if let abandoned = abandonedCopyError(outcome, generation: generation) { + continuation.finish(throwing: abandoned) + return + } continuation.finish() } } diff --git a/TableProMobile/TableProMobile/Drivers/PostgreSQLCopyState.swift b/TableProMobile/TableProMobile/Drivers/PostgreSQLCopyState.swift new file mode 100644 index 0000000000..9c29e5cdf2 --- /dev/null +++ b/TableProMobile/TableProMobile/Drivers/PostgreSQLCopyState.swift @@ -0,0 +1,14 @@ +import Foundation + +nonisolated extension LibPQCopyDirection { + var unsupportedMessage: String { + switch self { + case .copyIn: + return String(localized: "TablePro cannot send data to COPY FROM STDIN, so no rows were sent. Insert the rows with INSERT instead.") + case .copyOut: + return String(localized: "TablePro cannot receive the output of COPY TO STDOUT, so it was discarded. Run a SELECT instead.") + case .copyBoth: + return String(localized: "TablePro cannot run a replication COPY.") + } + } +} diff --git a/TableProMobile/TableProMobile/Drivers/PostgreSQLDriver.swift b/TableProMobile/TableProMobile/Drivers/PostgreSQLDriver.swift index 41f1c9bd67..dc6932f7d4 100644 --- a/TableProMobile/TableProMobile/Drivers/PostgreSQLDriver.swift +++ b/TableProMobile/TableProMobile/Drivers/PostgreSQLDriver.swift @@ -1,5 +1,6 @@ import CLibPQ import Foundation +import os import TableProDatabase import TableProModels @@ -94,6 +95,10 @@ nonisolated final class PostgreSQLDriver: DatabaseDriver, @unchecked Sendable { let beginResult = try await actor.beginStream(query: query) switch beginResult { case .commandOk(let affectedRows): + if let abandoned = await actor.takeAbandonedCopyError() { + continuation.finish(throwing: abandoned) + return + } if affectedRows != 0 { continuation.yield(.rowsAffected(affectedRows)) } @@ -115,6 +120,10 @@ nonisolated final class PostgreSQLDriver: DatabaseDriver, @unchecked Sendable { continuation.yield(.truncated(reason: .rowCap(options.maxRows))) } await actor.endStream() + if let abandoned = await actor.takeAbandonedCopyError() { + continuation.finish(throwing: abandoned) + return + } continuation.finish() } } catch is CancellationError { @@ -479,6 +488,7 @@ private actor PostgreSQLActor { guard let conn else { throw PostgreSQLError.notConnected } let start = Date() + let cancelsOutput = cancelsAbandonedOutput(conn) let result = PQexec(conn, query) defer { if result != nil { PQclear(result) } @@ -486,6 +496,11 @@ private actor PostgreSQLActor { let status = PQresultStatus(result) + if let copy = result.flatMap(LibPQCopyState.copy(of:)) { + _ = finishPendingResults(conn, cancellingOutput: cancelsOutput) + throw PostgreSQLError.unsupported(copy.direction.unsupportedMessage) + } + if status == PGRES_FATAL_ERROR { let msg = result.flatMap { String(cString: PQresultErrorMessage($0)) } ?? "Unknown error" throw PostgreSQLError.queryFailed(msg) @@ -546,10 +561,14 @@ private actor PostgreSQLActor { private var pendingResult: OpaquePointer? private var streamingFinished = true + private var abandonedCopy: LibPQCopy? + private var streamCancelsAbandonedOutput = false func beginStream(query: String) throws -> PGBeginStreamResult { guard let conn else { throw PostgreSQLError.notConnected } + streamCancelsAbandonedOutput = cancelsAbandonedOutput(conn) endStream() + abandonedCopy = nil guard PQsendQuery(conn, query) == 1 else { throw PostgreSQLError.queryFailed(String(cString: PQerrorMessage(conn))) @@ -566,6 +585,12 @@ private actor PostgreSQLActor { } let status = PQresultStatus(firstResult) + if let copy = LibPQCopyState.copy(of: firstResult) { + PQclear(firstResult) + drainResults() + abandonedCopy = nil + throw PostgreSQLError.unsupported(copy.direction.unsupportedMessage) + } switch status { case PGRES_COMMAND_OK: let affectedStr = String(cString: PQcmdTuples(firstResult)) @@ -654,11 +679,37 @@ private actor PostgreSQLActor { pendingResult = nil } guard let conn else { return } - while let extra = PQgetResult(conn) { - PQclear(extra) - } + let outcome = finishPendingResults(conn, cancellingOutput: streamCancelsAbandonedOutput) + guard let copy = outcome.abandonedCopy, abandonedCopy == nil else { return } + abandonedCopy = copy } + /// A COPY the drain ended is reported, never swallowed: `INSERT INTO t VALUES (1); COPY t FROM + /// STDIN` used to stream as a plain "INSERT 0 1" with the COPY silently discarded. + func takeAbandonedCopyError() -> PostgreSQLError? { + guard let copy = abandonedCopy else { return nil } + abandonedCopy = nil + return PostgreSQLError.unsupported(copy.direction.unsupportedMessage) + } + + private func finishPendingResults(_ conn: OpaquePointer, cancellingOutput: Bool) -> LibPQDrainOutcome { + let outcome = LibPQCopyState.finishPendingResults(conn, cancellingOutput: cancellingOutput) + guard let stuck = outcome.stuckInCopy else { return outcome } + Self.logger.fault( + "libpq stayed in \(String(describing: stuck.direction), privacy: .public); dropping the connection" + ) + close() + return outcome + } + + /// Cancelling inside a transaction block aborts it, so the cancel that keeps a `COPY TO STDOUT` + /// from transferring the whole table is sent only outside one. + private func cancelsAbandonedOutput(_ conn: OpaquePointer) -> Bool { + PQtransactionStatus(conn) != PQTRANS_INTRANS + } + + private static let logger = Logger(subsystem: "com.TablePro", category: "PostgreSQLActor") + private func parseColumns(_ result: OpaquePointer) -> [ColumnInfo] { let colCount = Int(PQnfields(result)) var cols: [ColumnInfo] = [] diff --git a/TableProMobile/TableProMobileTests/Drivers/PostgreSQLCopyStateTests.swift b/TableProMobile/TableProMobileTests/Drivers/PostgreSQLCopyStateTests.swift new file mode 100644 index 0000000000..65e27e0c65 --- /dev/null +++ b/TableProMobile/TableProMobileTests/Drivers/PostgreSQLCopyStateTests.swift @@ -0,0 +1,61 @@ +import CLibPQ +import Foundation +@testable import TableProMobile +import Testing + +@Suite("PostgreSQL COPY state") +struct PostgreSQLCopyStateTests { + @Test("Every libpq COPY status maps to its direction") + func copyStatusMapping() { + #expect(LibPQCopyState.direction(of: PGRES_COPY_IN) == .copyIn) + #expect(LibPQCopyState.direction(of: PGRES_COPY_OUT) == .copyOut) + #expect(LibPQCopyState.direction(of: PGRES_COPY_BOTH) == .copyBoth) + } + + @Test("A result that is not a COPY maps to no direction") + func nonCopyStatusMapping() { + #expect(LibPQCopyState.direction(of: PGRES_COMMAND_OK) == nil) + #expect(LibPQCopyState.direction(of: PGRES_TUPLES_OK) == nil) + #expect(LibPQCopyState.direction(of: PGRES_SINGLE_TUPLE) == nil) + #expect(LibPQCopyState.direction(of: PGRES_FATAL_ERROR) == nil) + #expect(LibPQCopyState.direction(of: PGRES_EMPTY_QUERY) == nil) + } + + @Test("Every direction explains itself and names the COPY form it rejects") + func unsupportedMessages() { + #expect(LibPQCopyDirection.copyIn.unsupportedMessage.contains("COPY FROM STDIN")) + #expect(LibPQCopyDirection.copyIn.unsupportedMessage.contains("no rows were sent")) + #expect(LibPQCopyDirection.copyOut.unsupportedMessage.contains("COPY TO STDOUT")) + #expect(!LibPQCopyDirection.copyBoth.unsupportedMessage.isEmpty) + let messages = Set([LibPQCopyDirection.copyIn, .copyOut, .copyBoth].map(\.unsupportedMessage)) + #expect(messages.count == 3) + } + + @Test("A COPY behind an earlier statement is ended and reported, never discarded in silence") + func copyAfterAnotherStatementIsReported() { + let copy = LibPQCopy(direction: .copyIn, format: .textual) + var pending: [LibPQPendingResult] = [.completed, .copy(copy)] + var ended: [LibPQCopy] = [] + let outcome = LibPQPendingResultDrain.drain( + nextResult: { pending.isEmpty ? nil : pending.removeFirst() }, + endCopy: { ended.append($0) } + ) + #expect(ended == [copy]) + #expect(outcome.abandonedCopy == copy) + } + + @Test("A COPY libpq never leaves stops the drain and marks the connection unusable") + func stuckCopyTerminates() { + var reads = 0 + let outcome = LibPQPendingResultDrain.drain( + nextResult: { + reads += 1 + return .copy(LibPQCopy(direction: .copyOut, format: .textual)) + }, + endCopy: { _ in } + ) + #expect(outcome.stuckInCopy == LibPQCopy(direction: .copyOut, format: .textual)) + #expect(outcome.leavesConnectionUnusable) + #expect(reads == 2) + } +} diff --git a/TableProMobile/project.yml b/TableProMobile/project.yml index 716475f94f..f417e9da2b 100644 --- a/TableProMobile/project.yml +++ b/TableProMobile/project.yml @@ -63,6 +63,9 @@ targets: - ../Plugins/MySQLDriverPlugin/MySQLConnectionEncoding.swift - ../Plugins/MySQLDriverPlugin/MySQLLatin1.swift - ../Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift + # libpq COPY handling the iOS PostgreSQL driver shares with the macOS plugin. + - ../Plugins/PostgreSQLDriverPlugin/LibPQPendingResultDrain.swift + - ../Plugins/PostgreSQLDriverPlugin/LibPQCopyState.swift configFiles: Debug: ../Configs/Version-iOS.xcconfig Release: ../Configs/Version-iOS.xcconfig diff --git a/TableProTests/Plugins/LibPQPendingResultDrainTests.swift b/TableProTests/Plugins/LibPQPendingResultDrainTests.swift new file mode 100644 index 0000000000..f65a1def90 --- /dev/null +++ b/TableProTests/Plugins/LibPQPendingResultDrainTests.swift @@ -0,0 +1,124 @@ +// +// LibPQPendingResultDrainTests.swift +// TableProTests +// + +import Foundation +import Testing + +private final class SimulatedLibPQConnection { + private var queue: [LibPQPendingResult] + private var activeCopy: LibPQCopy? + private let leavesCopyOnEnd: Bool + private(set) var endedCopies: [LibPQCopy] = [] + private(set) var reads = 0 + + init(results: [LibPQPendingResult], leavesCopyOnEnd: Bool = true) { + self.queue = results + self.leavesCopyOnEnd = leavesCopyOnEnd + } + + func nextResult() -> LibPQPendingResult? { + reads += 1 + if let activeCopy { return .copy(activeCopy) } + guard !queue.isEmpty else { return nil } + let next = queue.removeFirst() + if case .copy(let copy) = next { activeCopy = copy } + return next + } + + func endCopy(_ copy: LibPQCopy) { + endedCopies.append(copy) + guard leavesCopyOnEnd else { return } + activeCopy = nil + queue.insert(.completed, at: 0) + } + + func drain() -> LibPQDrainOutcome { + LibPQPendingResultDrain.drain(nextResult: nextResult, endCopy: endCopy) + } +} + +private func textual(_ direction: LibPQCopyDirection) -> LibPQCopy { + LibPQCopy(direction: direction, format: .textual) +} + +@Suite("LibPQPendingResultDrain") +struct LibPQPendingResultDrainTests { + @Test("An idle connection drains without ending anything") + func idleConnection() { + let connection = SimulatedLibPQConnection(results: []) + let outcome = connection.drain() + #expect(outcome == .idle) + #expect(outcome.abandonedCopy == nil) + #expect(!outcome.leavesConnectionUnusable) + #expect(connection.endedCopies.isEmpty) + } + + @Test("Ordinary results are read until libpq has none left") + func ordinaryResults() { + let connection = SimulatedLibPQConnection(results: [.completed, .completed, .completed]) + #expect(connection.drain() == .idle) + #expect(connection.endedCopies.isEmpty) + #expect(connection.reads == 4) + } + + @Test( + "A COPY that repeats its state until ended is ended once and reported", + arguments: [LibPQCopyDirection.copyIn, .copyOut, .copyBoth] + ) + func copyStateIsEndedAndReported(direction: LibPQCopyDirection) { + let connection = SimulatedLibPQConnection(results: [.copy(textual(direction))]) + let outcome = connection.drain() + #expect(connection.endedCopies == [textual(direction)]) + #expect(outcome.abandonedCopy == textual(direction)) + #expect(!outcome.leavesConnectionUnusable) + } + + @Test("A COPY behind an earlier statement is still reported, so nothing is discarded in silence") + func copyAfterAnotherStatementIsReported() { + let connection = SimulatedLibPQConnection(results: [.completed, .copy(textual(.copyIn))]) + let outcome = connection.drain() + #expect(outcome.abandonedCopy == textual(.copyIn)) + #expect(connection.endedCopies == [textual(.copyIn)]) + } + + @Test("Each COPY in a multi-statement string is ended in turn and the first is reported") + func consecutiveCopyStatements() { + let connection = SimulatedLibPQConnection( + results: [.completed, .copy(textual(.copyOut)), .copy(textual(.copyIn)), .completed] + ) + let outcome = connection.drain() + #expect(connection.endedCopies == [textual(.copyOut), textual(.copyIn)]) + #expect(outcome.abandonedCopy == textual(.copyOut)) + } + + @Test("The COPY format travels with the direction, because binary input cannot end with CopyDone") + func formatIsCarried() { + let binary = LibPQCopy(direction: .copyIn, format: .binary) + let connection = SimulatedLibPQConnection(results: [.copy(binary)]) + #expect(connection.drain().abandonedCopy == binary) + #expect(connection.endedCopies == [binary]) + } + + @Test("A COPY libpq refuses to leave stops the drain and marks the connection unusable") + func stuckCopyTerminates() { + let connection = SimulatedLibPQConnection(results: [.copy(textual(.copyIn))], leavesCopyOnEnd: false) + let outcome = connection.drain() + #expect(outcome.stuckInCopy == textual(.copyIn)) + #expect(outcome.leavesConnectionUnusable) + #expect(outcome.abandonedCopy == textual(.copyIn)) + #expect(connection.endedCopies == [textual(.copyIn)]) + #expect(connection.reads == 2) + } + + @Test("Every direction explains itself in query editor terms and names the COPY form it rejects") + func unsupportedMessages() { + #expect(LibPQCopyDirection.copyIn.unsupportedMessage.contains("COPY FROM STDIN")) + #expect(LibPQCopyDirection.copyIn.unsupportedMessage.contains("no rows were sent")) + #expect(LibPQCopyDirection.copyOut.unsupportedMessage.contains("COPY TO STDOUT")) + #expect(!LibPQCopyDirection.copyBoth.unsupportedMessage.isEmpty) + let messages = Set([LibPQCopyDirection.copyIn, .copyOut, .copyBoth].map(\.unsupportedMessage)) + #expect(messages.count == 3) + } +} diff --git a/project.yml b/project.yml index 17dcbc20f2..43256ed70f 100644 --- a/project.yml +++ b/project.yml @@ -511,6 +511,8 @@ targets: - Plugins/PostgreSQLDriverPlugin/LibPQByteaDecoder.swift - Plugins/PostgreSQLDriverPlugin/LibPQCellDecoding.swift - Plugins/PostgreSQLDriverPlugin/LibPQConnectionString.swift + - Plugins/PostgreSQLDriverPlugin/LibPQCopyDirection+UnsupportedMessage.swift + - Plugins/PostgreSQLDriverPlugin/LibPQPendingResultDrain.swift - Plugins/PostgreSQLDriverPlugin/LibPQPluginError.swift - Plugins/PostgreSQLDriverPlugin/LibPQSSLMapping.swift - Plugins/PostgreSQLDriverPlugin/PostGISSpatialRewrite.swift From ba311ae14f6ba3202d666364efe44ef0df1c8558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 01:18:32 +0700 Subject: [PATCH 20/54] fix(plugins): decode ClickHouse values per column and N-prefix SQL Server literals (#2756) --- CHANGELOG.md | 6 + .../MSSQLSchemaQueries.swift | 28 ++--- .../MSSQLStringLiteral.swift | 57 +++++++++ .../MSSQLSchemaQueriesTests.swift | 32 ++++- .../MSSQLStringLiteralTests.swift | 88 ++++++++++++++ .../ClickHouseParameterBinding.swift | 69 +++++++++++ .../ClickHousePlugin.swift | 4 +- .../ClickHousePluginDriver+Http.swift | 52 +------- .../MSSQLObjectQueries.swift | 15 +-- Plugins/MSSQLDriverPlugin/MSSQLPlugin.swift | 61 ++++++---- .../MSSQLPluginDriver+DDL.swift | 22 ++-- .../MSSQLPluginDriver+Schema.swift | 53 ++++----- .../ClickHouseResponseClassifier.swift | 111 +++++++++++------- .../ClickHouseTabSeparatedBytes.swift | 98 ++++++++++++++++ .../Core/Coordinators/FilterCoordinator.swift | 3 +- .../Core/Database/FilterSQLGenerator.swift | 19 ++- .../Core/Database/ForeignKeyLookupQuery.swift | 4 +- .../Query/ForeignKeyLookupService.swift | 1 + .../Services/Query/TableQueryBuilder.swift | 6 +- .../SQL/SQLStringLiteralPrefix.swift | 27 +++++ .../FilterSQLGeneratorMSSQLTests.swift | 66 +++++++++-- .../Database/ForeignKeyLookupQueryTests.swift | 4 +- .../SQLStringLiteralPrefixTests.swift | 29 +++++ .../TableQueryBuilderMSSQLTests.swift | 8 ++ .../ClickHouseParameterBindingTests.swift | 88 ++++++++++++++ .../ClickHouseResponseClassifierTests.swift | 107 +++++++++++++++++ .../Plugins/ObjectCatalogQueryTests.swift | 21 +++- docs/databases/clickhouse.mdx | 1 + project.yml | 1 + 29 files changed, 876 insertions(+), 205 deletions(-) create mode 100644 Packages/TableProCore/Sources/TableProMSSQLCore/MSSQLStringLiteral.swift create mode 100644 Packages/TableProCore/Tests/TableProMSSQLCoreTests/MSSQLStringLiteralTests.swift create mode 100644 Plugins/ClickHouseDriverPlugin/ClickHouseParameterBinding.swift create mode 100644 Plugins/TableProPluginKit/ClickHouseTabSeparatedBytes.swift create mode 100644 TablePro/Core/Utilities/SQL/SQLStringLiteralPrefix.swift create mode 100644 TableProTests/Core/Database/SQLStringLiteralPrefixTests.swift create mode 100644 TableProTests/Plugins/ClickHouseParameterBindingTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index bbb304422b..7ea940ec84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -165,6 +165,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **Edit View Definition** enabled in the Database menu on a read-only connection. (#2726) - Enum types and sequences written in front of a PostgreSQL view's DDL. (#2726) - Display As formats lost on a rename, and kept with column layouts after deleting a connection. +- Garbled ClickHouse text whenever another value in the same result held binary data. +- Carriage returns, quotes, NUL bytes and Enum type names shown with backslash escapes on ClickHouse. +- Edits and deletes matching no row on ClickHouse tables with a binary value in the row. +- Non-ASCII SQL Server filter values turned into `?` and matching the wrong rows on non-Unicode collations. +- Empty structure, missing indexes and failed renames for non-ASCII SQL Server object names on non-Unicode collations. +- Changing a defaulted SQL Server column failing when a name contains a quote or non-ASCII text. ### Security diff --git a/Packages/TableProCore/Sources/TableProMSSQLCore/MSSQLSchemaQueries.swift b/Packages/TableProCore/Sources/TableProMSSQLCore/MSSQLSchemaQueries.swift index b701a5e2b9..aaf6df3da3 100644 --- a/Packages/TableProCore/Sources/TableProMSSQLCore/MSSQLSchemaQueries.swift +++ b/Packages/TableProCore/Sources/TableProMSSQLCore/MSSQLSchemaQueries.swift @@ -2,7 +2,7 @@ import Foundation public enum MSSQLSchemaQueries { public static func escape(_ value: String) -> String { - value.replacingOccurrences(of: "'", with: "''") + MSSQLStringLiteral.escaped(value) } public static func escapeBracket(_ value: String) -> String { @@ -127,19 +127,19 @@ public enum MSSQLSchemaQueries { """ public static func tables(schema: String) -> String { - let s = escape(schema) + let s = MSSQLStringLiteral.quoted(schema) return """ SELECT t.TABLE_NAME, t.TABLE_TYPE FROM INFORMATION_SCHEMA.TABLES t - WHERE t.TABLE_SCHEMA = '\(s)' + WHERE t.TABLE_SCHEMA = \(s) AND t.TABLE_TYPE IN ('BASE TABLE', 'VIEW') ORDER BY t.TABLE_NAME """ } public static func columns(schema: String, table: String) -> String { - let s = escape(schema) - let t = escape(table) + let s = MSSQLStringLiteral.quoted(schema) + let t = MSSQLStringLiteral.quoted(table) return """ SELECT c.COLUMN_NAME, @@ -160,17 +160,17 @@ public enum MSSQLSchemaQueries { ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND tc.TABLE_SCHEMA = kcu.TABLE_SCHEMA WHERE tc.CONSTRAINT_TYPE = 'PRIMARY KEY' - AND tc.TABLE_SCHEMA = '\(s)' - AND tc.TABLE_NAME = '\(t)' + AND tc.TABLE_SCHEMA = \(s) + AND tc.TABLE_NAME = \(t) ) pk ON c.COLUMN_NAME = pk.COLUMN_NAME - WHERE c.TABLE_NAME = '\(t)' - AND c.TABLE_SCHEMA = '\(s)' + WHERE c.TABLE_NAME = \(t) + AND c.TABLE_SCHEMA = \(s) ORDER BY c.ORDINAL_POSITION """ } public static func indexes(schema: String, table: String) -> String { - let object = bracketed(schema: schema, table: table) + let object = MSSQLStringLiteral.quoted(bracketed(schema: schema, table: table)) return """ SELECT i.name, i.is_unique, i.is_primary_key, c.name AS column_name FROM sys.indexes i @@ -178,15 +178,15 @@ public enum MSSQLSchemaQueries { ON i.object_id = ic.object_id AND i.index_id = ic.index_id JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id - WHERE i.object_id = OBJECT_ID('\(object)') + WHERE i.object_id = OBJECT_ID(\(object)) AND i.name IS NOT NULL ORDER BY i.index_id, ic.key_ordinal """ } public static func foreignKeys(schema: String, table: String) -> String { - let s = escape(schema) - let t = escape(table) + let s = MSSQLStringLiteral.quoted(schema) + let t = MSSQLStringLiteral.quoted(table) return """ SELECT fk.name AS constraint_name, @@ -204,7 +204,7 @@ public enum MSSQLSchemaQueries { JOIN sys.schemas sr ON tr.schema_id = sr.schema_id JOIN sys.columns cr ON fkc.referenced_object_id = cr.object_id AND fkc.referenced_column_id = cr.column_id - WHERE tp.name = '\(t)' AND s.name = '\(s)' + WHERE tp.name = \(t) AND s.name = \(s) ORDER BY fk.name """ } diff --git a/Packages/TableProCore/Sources/TableProMSSQLCore/MSSQLStringLiteral.swift b/Packages/TableProCore/Sources/TableProMSSQLCore/MSSQLStringLiteral.swift new file mode 100644 index 0000000000..346f5317f5 --- /dev/null +++ b/Packages/TableProCore/Sources/TableProMSSQLCore/MSSQLStringLiteral.swift @@ -0,0 +1,57 @@ +import Foundation + +/// The single owner of how SQL Server spells a string literal carrying user text. +/// +/// A plain `'…'` is a `varchar` literal, so the server converts it to the database's collation +/// code page while it parses the batch. On a non-Unicode collation every character outside that +/// page becomes `?`, and it happens whatever the target column is: inserting `'日本語'` into an +/// `NVARCHAR(50)` column stores `??????`, and `WHERE n = '日本語'` then matches the row that was +/// damaged earlier rather than the row that holds the text. `N'…'` is an `nvarchar` literal and is +/// converted by nothing. It costs nothing on ASCII, where `N'abc' = 'abc'`. +/// +/// Only text the user or the catalog supplies goes through here. A number, an identifier, a `0x` +/// binary literal and a fixed catalog constant such as `'PRIMARY KEY'` must stay as they are. +public enum MSSQLStringLiteral { + public static func escaped(_ value: String) -> String { + value.replacingOccurrences(of: "'", with: "''") + } + + public static func quoted(_ value: String) -> String { + "N'\(escaped(value))'" + } + + /// `LIKE` takes its pattern as an ordinary string literal, so the prefix belongs here too. The + /// wildcards the user typed are escaped and declared with `ESCAPE '\'`, which stays a plain + /// literal because a backslash is ASCII. + public static func likePattern(_ value: String, prefixWildcard: Bool, suffixWildcard: Bool) -> String { + let body = escapeForLike(value) + let pattern = (prefixWildcard ? "%" : "") + body + (suffixWildcard ? "%" : "") + return "N'\(pattern)' ESCAPE '\\'" + } + + public static func escapeForLike(_ value: String) -> String { + escaped( + value + .replacingOccurrences(of: "\\", with: "\\\\") + .replacingOccurrences(of: "%", with: "\\%") + .replacingOccurrences(of: "_", with: "\\_") + ) + } + + /// The `LIKE` arms of the shared filter builder write their own literal rather than asking the + /// driver for one, so SQL Server answers them here and lets everything else fall through. + public static func likeCondition(quotedColumn: String, op: String, value: String) -> String? { + switch op { + case "CONTAINS": + return "\(quotedColumn) LIKE \(likePattern(value, prefixWildcard: true, suffixWildcard: true))" + case "NOT CONTAINS": + return "\(quotedColumn) NOT LIKE \(likePattern(value, prefixWildcard: true, suffixWildcard: true))" + case "STARTS WITH": + return "\(quotedColumn) LIKE \(likePattern(value, prefixWildcard: false, suffixWildcard: true))" + case "ENDS WITH": + return "\(quotedColumn) LIKE \(likePattern(value, prefixWildcard: true, suffixWildcard: false))" + default: + return nil + } + } +} diff --git a/Packages/TableProCore/Tests/TableProMSSQLCoreTests/MSSQLSchemaQueriesTests.swift b/Packages/TableProCore/Tests/TableProMSSQLCoreTests/MSSQLSchemaQueriesTests.swift index 43c552ccba..6063679359 100644 --- a/Packages/TableProCore/Tests/TableProMSSQLCoreTests/MSSQLSchemaQueriesTests.swift +++ b/Packages/TableProCore/Tests/TableProMSSQLCoreTests/MSSQLSchemaQueriesTests.swift @@ -18,7 +18,7 @@ final class MSSQLSchemaQueriesTests: XCTestCase { func testTablesQueryEscapesSchema() { let sql = MSSQLSchemaQueries.tables(schema: "O'Brien") - XCTAssertTrue(sql.contains("'O''Brien'")) + XCTAssertTrue(sql.contains("N'O''Brien'")) XCTAssertTrue(sql.contains("INFORMATION_SCHEMA.TABLES")) XCTAssertTrue(sql.contains("'BASE TABLE'")) XCTAssertTrue(sql.contains("'VIEW'")) @@ -28,21 +28,21 @@ final class MSSQLSchemaQueriesTests: XCTestCase { let sql = MSSQLSchemaQueries.columns(schema: "dbo", table: "Users") XCTAssertTrue(sql.contains("IsIdentity")) XCTAssertTrue(sql.contains("PRIMARY KEY")) - XCTAssertTrue(sql.contains("'Users'")) - XCTAssertTrue(sql.contains("'dbo'")) + XCTAssertTrue(sql.contains("N'Users'")) + XCTAssertTrue(sql.contains("N'dbo'")) } func testIndexesQueryUsesBracketedIdentifier() { let sql = MSSQLSchemaQueries.indexes(schema: "dbo", table: "Users") - XCTAssertTrue(sql.contains("OBJECT_ID('[dbo].[Users]')")) + XCTAssertTrue(sql.contains("OBJECT_ID(N'[dbo].[Users]')")) XCTAssertTrue(sql.contains("sys.indexes")) } func testForeignKeysQueryFiltersByTableAndSchema() { let sql = MSSQLSchemaQueries.foreignKeys(schema: "dbo", table: "Orders") XCTAssertTrue(sql.contains("sys.foreign_keys")) - XCTAssertTrue(sql.contains("'Orders'")) - XCTAssertTrue(sql.contains("'dbo'")) + XCTAssertTrue(sql.contains("N'Orders'")) + XCTAssertTrue(sql.contains("N'dbo'")) } func testForeignKeysQuerySelectsReferencedSchema() { @@ -175,4 +175,24 @@ final class MSSQLSchemaQueriesTests: XCTestCase { "SELECT * FROM [sales].[routeCache] ORDER BY (SELECT NULL) OFFSET 0 ROWS FETCH NEXT 200 ROWS ONLY" ) } + + func testCatalogPredicatesSurviveANonAsciiName() { + let columns = MSSQLSchemaQueries.columns(schema: "dbo", table: "顧客テーブル") + XCTAssertTrue(columns.contains("N'顧客テーブル'")) + XCTAssertFalse(columns.contains("= '顧客テーブル'")) + + let indexes = MSSQLSchemaQueries.indexes(schema: "dbo", table: "顧客テーブル") + XCTAssertTrue(indexes.contains("OBJECT_ID(N'[dbo].[顧客テーブル]')")) + + let foreignKeys = MSSQLSchemaQueries.foreignKeys(schema: "スキーマ", table: "顧客テーブル") + XCTAssertTrue(foreignKeys.contains("N'顧客テーブル'")) + XCTAssertTrue(foreignKeys.contains("N'スキーマ'")) + } + + func testFixedCatalogConstantsStayUnprefixed() { + let tables = MSSQLSchemaQueries.tables(schema: "dbo") + XCTAssertTrue(tables.contains("IN ('BASE TABLE', 'VIEW')")) + XCTAssertTrue(MSSQLSchemaQueries.columns(schema: "dbo", table: "t").contains("= 'PRIMARY KEY'")) + XCTAssertTrue(MSSQLSchemaQueries.schemas.contains("'information_schema'")) + } } diff --git a/Packages/TableProCore/Tests/TableProMSSQLCoreTests/MSSQLStringLiteralTests.swift b/Packages/TableProCore/Tests/TableProMSSQLCoreTests/MSSQLStringLiteralTests.swift new file mode 100644 index 0000000000..31c5e5d18d --- /dev/null +++ b/Packages/TableProCore/Tests/TableProMSSQLCoreTests/MSSQLStringLiteralTests.swift @@ -0,0 +1,88 @@ +@testable import TableProMSSQLCore +import XCTest + +final class MSSQLStringLiteralTests: XCTestCase { + func testQuotedPrefixesWithN() { + XCTAssertEqual(MSSQLStringLiteral.quoted("plain"), "N'plain'") + } + + func testQuotedKeepsNonAsciiText() { + XCTAssertEqual(MSSQLStringLiteral.quoted("日本語メール"), "N'日本語メール'") + } + + func testQuotedDoublesSingleQuotes() { + XCTAssertEqual(MSSQLStringLiteral.quoted("O'Brien"), "N'O''Brien'") + XCTAssertEqual(MSSQLStringLiteral.quoted("'; DROP TABLE t --"), "N'''; DROP TABLE t --'") + } + + func testQuotedHandlesEmptyString() { + XCTAssertEqual(MSSQLStringLiteral.quoted(""), "N''") + } + + func testEscapedReturnsBodyWithoutQuotes() { + XCTAssertEqual(MSSQLStringLiteral.escaped("O'Brien"), "O''Brien") + XCTAssertEqual(MSSQLStringLiteral.escaped("plain"), "plain") + } + + func testLikePatternWrapsWildcardsInsideTheLiteral() { + XCTAssertEqual( + MSSQLStringLiteral.likePattern("メール", prefixWildcard: true, suffixWildcard: true), + "N'%メール%' ESCAPE '\\'" + ) + XCTAssertEqual( + MSSQLStringLiteral.likePattern("abc", prefixWildcard: false, suffixWildcard: true), + "N'abc%' ESCAPE '\\'" + ) + XCTAssertEqual( + MSSQLStringLiteral.likePattern("abc", prefixWildcard: true, suffixWildcard: false), + "N'%abc' ESCAPE '\\'" + ) + } + + func testLikePatternEscapesUserWildcards() { + XCTAssertEqual( + MSSQLStringLiteral.likePattern("50%_off", prefixWildcard: true, suffixWildcard: true), + "N'%50\\%\\_off%' ESCAPE '\\'" + ) + } + + func testLikePatternEscapesBackslashBeforeWildcards() { + XCTAssertEqual( + MSSQLStringLiteral.likePattern("a\\b", prefixWildcard: false, suffixWildcard: false), + "N'a\\\\b' ESCAPE '\\'" + ) + } + + func testLikePatternDoublesSingleQuotes() { + XCTAssertEqual( + MSSQLStringLiteral.likePattern("O'Brien", prefixWildcard: true, suffixWildcard: true), + "N'%O''Brien%' ESCAPE '\\'" + ) + } + + func testLikeConditionCoversTheFourPatternOperators() { + XCTAssertEqual( + MSSQLStringLiteral.likeCondition(quotedColumn: "[n]", op: "CONTAINS", value: "日本"), + "[n] LIKE N'%日本%' ESCAPE '\\'" + ) + XCTAssertEqual( + MSSQLStringLiteral.likeCondition(quotedColumn: "[n]", op: "NOT CONTAINS", value: "日本"), + "[n] NOT LIKE N'%日本%' ESCAPE '\\'" + ) + XCTAssertEqual( + MSSQLStringLiteral.likeCondition(quotedColumn: "[n]", op: "STARTS WITH", value: "日本"), + "[n] LIKE N'日本%' ESCAPE '\\'" + ) + XCTAssertEqual( + MSSQLStringLiteral.likeCondition(quotedColumn: "[n]", op: "ENDS WITH", value: "日本"), + "[n] LIKE N'%日本' ESCAPE '\\'" + ) + } + + func testLikeConditionLeavesOtherOperatorsToTheSharedBuilder() { + XCTAssertNil(MSSQLStringLiteral.likeCondition(quotedColumn: "[n]", op: "=", value: "x")) + XCTAssertNil(MSSQLStringLiteral.likeCondition(quotedColumn: "[n]", op: "IN", value: "a,b")) + XCTAssertNil(MSSQLStringLiteral.likeCondition(quotedColumn: "[n]", op: "IS NULL", value: "")) + XCTAssertNil(MSSQLStringLiteral.likeCondition(quotedColumn: "[n]", op: "REGEX", value: "x")) + } +} diff --git a/Plugins/ClickHouseDriverPlugin/ClickHouseParameterBinding.swift b/Plugins/ClickHouseDriverPlugin/ClickHouseParameterBinding.swift new file mode 100644 index 0000000000..489a94ed98 --- /dev/null +++ b/Plugins/ClickHouseDriverPlugin/ClickHouseParameterBinding.swift @@ -0,0 +1,69 @@ +// +// ClickHouseParameterBinding.swift +// ClickHouseDriverPlugin +// + +import Foundation +import TableProPluginKit + +nonisolated internal enum ClickHouseParameterBinding { + struct Bound { + let query: String + let params: [String: String?] + } + + /// A ClickHouse HTTP parameter is text: `{p1:String}` takes the characters of `param_p1` + /// verbatim, so bytes handed over as `0xDEADBEEF` compare as those ten characters and every + /// predicate on a binary column matches nothing. Bytes are written into the statement as + /// `unhex('…')` instead, which the server turns back into the value the read produced. The hex + /// is generated here and holds nothing but `0-9A-F`, so it closes no quote. + static func bind(query: String, parameters: [PluginCellValue]) -> Bound { + var converted = "" + converted.reserveCapacity((query as NSString).length) + var paramMap: [String: String?] = [:] + var consumed = 0 + var namedCount = 0 + var inSingleQuote = false + var inDoubleQuote = false + var isEscaped = false + + for char in query { + if isEscaped { + isEscaped = false + converted.append(char) + continue + } + if char == "\\" && (inSingleQuote || inDoubleQuote) { + isEscaped = true + converted.append(char) + continue + } + if char == "'" && !inDoubleQuote { + inSingleQuote.toggle() + } else if char == "\"" && !inSingleQuote { + inDoubleQuote.toggle() + } + guard char == "?", !inSingleQuote, !inDoubleQuote, consumed < parameters.count else { + converted.append(char) + continue + } + let parameter = parameters[consumed] + consumed += 1 + if case .bytes(let data) = parameter { + converted.append(hexLiteral(data)) + continue + } + namedCount += 1 + let name = "p\(namedCount)" + converted.append("{\(name):String}") + paramMap[name] = parameter.asText + } + + return Bound(query: converted, params: paramMap) + } + + static func hexLiteral(_ data: Data) -> String { + let hex = data.map { String(format: "%02X", $0) }.joined() + return "unhex('\(hex)')" + } +} diff --git a/Plugins/ClickHouseDriverPlugin/ClickHousePlugin.swift b/Plugins/ClickHouseDriverPlugin/ClickHousePlugin.swift index fba95f35b0..7b50dd3864 100644 --- a/Plugins/ClickHouseDriverPlugin/ClickHousePlugin.swift +++ b/Plugins/ClickHouseDriverPlugin/ClickHousePlugin.swift @@ -286,8 +286,8 @@ final class ClickHousePluginDriver: PluginDatabaseDriver, @unchecked Sendable { let startTime = Date() let queryId = UUID().uuidString - let (convertedQuery, paramMap) = Self.buildClickHouseParams(query: query, parameters: parameters) - let result = try await executeRawWithParams(convertedQuery, params: paramMap, queryId: queryId) + let bound = ClickHouseParameterBinding.bind(query: query, parameters: parameters) + let result = try await executeRawWithParams(bound.query, params: bound.params, queryId: queryId) let executionTime = Date().timeIntervalSince(startTime) return PluginQueryResult( diff --git a/Plugins/ClickHouseDriverPlugin/ClickHousePluginDriver+Http.swift b/Plugins/ClickHouseDriverPlugin/ClickHousePluginDriver+Http.swift index c14d0f002b..5d2cbd513c 100644 --- a/Plugins/ClickHouseDriverPlugin/ClickHousePluginDriver+Http.swift +++ b/Plugins/ClickHouseDriverPlugin/ClickHousePluginDriver+Http.swift @@ -47,7 +47,7 @@ extension ClickHousePluginDriver { let httpResponse = response as? HTTPURLResponse if let httpResponse, httpResponse.statusCode >= 400 { - let body = String(data: data, encoding: .utf8) ?? "Unknown error" + let body = String(decoding: data, as: UTF8.self) // swiftlint:disable:this optional_data_string_conversion let exceptionCode = httpResponse.value(forHTTPHeaderField: "X-ClickHouse-Exception-Code") ?? "none" Self.logger.error("ClickHouse HTTP \(httpResponse.statusCode) exception \(exceptionCode): \(body)") throw ClickHouseError(message: body.trimmingCharacters(in: .whitespacesAndNewlines)) @@ -154,54 +154,4 @@ extension ClickHousePluginDriver { return request } - - /// Convert `?` placeholders to `{p1:String}` and build parameter map for ClickHouse HTTP params. - static func buildClickHouseParams( - query: String, - parameters: [PluginCellValue] - ) -> (String, [String: String?]) { - var converted = "" - var paramIndex = 0 - var inSingleQuote = false - var inDoubleQuote = false - var isEscaped = false - - for char in query { - if isEscaped { - isEscaped = false - converted.append(char) - continue - } - if char == "\\" && (inSingleQuote || inDoubleQuote) { - isEscaped = true - converted.append(char) - continue - } - if char == "'" && !inDoubleQuote { - inSingleQuote.toggle() - } else if char == "\"" && !inSingleQuote { - inDoubleQuote.toggle() - } - if char == "?" && !inSingleQuote && !inDoubleQuote && paramIndex < parameters.count { - paramIndex += 1 - converted.append("{p\(paramIndex):String}") - } else { - converted.append(char) - } - } - - var paramMap: [String: String?] = [:] - for i in 0.. String { - value.replacingOccurrences(of: "'", with: "''") + MSSQLStringLiteral.escaped(value) } /// Reads sys.sql_modules, never INFORMATION_SCHEMA.ROUTINES.ROUTINE_DEFINITION. That column is /// nvarchar(4000) and silently returns the first 4000 characters of a longer body, which looks /// like a routine that ends mid-statement. public static func routineList(schema: String) -> String { - let schemaLiteral = escapeLiteral(schema) + let schemaLiteral = MSSQLStringLiteral.quoted(schema) return """ SELECT o.name, @@ -41,7 +42,7 @@ public enum MSSQLObjectQueries { FROM sys.objects o JOIN sys.schemas s ON s.schema_id = o.schema_id LEFT JOIN sys.sql_modules m ON m.object_id = o.object_id - WHERE s.name = '\(schemaLiteral)' + WHERE s.name = \(schemaLiteral) AND o.type IN ('P', 'FN', 'IF', 'TF') AND o.is_ms_shipped = 0 ORDER BY o.type, o.name @@ -54,7 +55,7 @@ public enum MSSQLObjectQueries { FROM sys.sql_modules m JOIN sys.objects o ON o.object_id = m.object_id JOIN sys.schemas s ON s.schema_id = o.schema_id - WHERE s.name = '\(escapeLiteral(schema))' AND o.name = '\(escapeLiteral(name))' + WHERE s.name = \(MSSQLStringLiteral.quoted(schema)) AND o.name = \(MSSQLStringLiteral.quoted(name)) """ } @@ -62,8 +63,8 @@ public enum MSSQLObjectQueries { /// one table is one more predicate on the same query, so the per-table list and the /// schema-wide list cannot disagree. public static func triggerList(schema: String, table: String?) -> String { - let schemaLiteral = escapeLiteral(schema) - let tablePredicate = table.map { "AND parent.name = '\(escapeLiteral($0))'" } ?? "" + let schemaLiteral = MSSQLStringLiteral.quoted(schema) + let tablePredicate = table.map { "AND parent.name = \(MSSQLStringLiteral.quoted($0))" } ?? "" return """ SELECT t.name, @@ -78,7 +79,7 @@ public enum MSSQLObjectQueries { JOIN sys.schemas s ON s.schema_id = parent.schema_id JOIN sys.trigger_events te ON te.object_id = t.object_id WHERE t.parent_class = 1 - AND s.name = '\(schemaLiteral)' + AND s.name = \(schemaLiteral) \(tablePredicate) ORDER BY parent.name, t.name, te.type_desc """ diff --git a/Plugins/MSSQLDriverPlugin/MSSQLPlugin.swift b/Plugins/MSSQLDriverPlugin/MSSQLPlugin.swift index 04249db1ac..2b92c2c854 100644 --- a/Plugins/MSSQLDriverPlugin/MSSQLPlugin.swift +++ b/Plugins/MSSQLDriverPlugin/MSSQLPlugin.swift @@ -273,7 +273,8 @@ final class MSSQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { if MSSQLCapabilities.parse(serverVersion).hasCreateOrAlterView { return "CREATE OR ALTER VIEW \(quoted) AS\nSELECT * FROM table_name;" } - return "IF OBJECT_ID('\(viewName)', 'V') IS NOT NULL DROP VIEW \(quoted);\nCREATE VIEW \(quoted) AS\nSELECT * FROM table_name;" + let viewLiteral = MSSQLStringLiteral.quoted(viewName) + return "IF OBJECT_ID(\(viewLiteral), 'V') IS NOT NULL DROP VIEW \(quoted);\nCREATE VIEW \(quoted) AS\nSELECT * FROM table_name;" } func castColumnToText(_ column: String) -> String { @@ -285,10 +286,6 @@ final class MSSQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { self._currentSchema = config.additionalFields["mssqlSchema"].flatMap { $0.isEmpty ? nil : $0 } ?? "dbo" } - private var escapedSchema: String { - _currentSchema.replacingOccurrences(of: "'", with: "''") - } - // MARK: - Connection func connect() async throws { @@ -686,13 +683,12 @@ final class MSSQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { } func fetchApproximateRowCount(table: String, schema: String?) async throws -> Int? { - let esc = effectiveSchemaEscaped(schema) - let escapedTable = table.replacingOccurrences(of: "'", with: "''") - let objectName = "[\(esc)].[\(escapedTable)]" + let objectLiteral = MSSQLStringLiteral.quoted( + MSSQLSchemaQueries.bracketed(schema: effectiveSchema(schema), table: table)) let sql = """ SELECT SUM(p.rows) FROM sys.partitions p - WHERE p.object_id = OBJECT_ID(N'\(objectName)') AND p.index_id IN (0, 1) + WHERE p.object_id = OBJECT_ID(\(objectLiteral)) AND p.index_id IN (0, 1) """ let result = try await execute(query: sql) if let row = result.rows.first, let cell = row.first, let str = cell.asText { @@ -774,16 +770,7 @@ final class MSSQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { offset: Int, columnKinds: [String: PluginColumnKind] ) -> String? { - let whereClause = PluginSQLFilter.buildWhereClause( - filters: filters, - logicMode: logicMode, - columnKinds: columnKinds, - quoteIdentifier: mssqlQuoteIdentifier, - escapeTypedValue: mssqlEscapeValue, - regexCondition: { quoted, value in - "\(quoted) LIKE '%\(value.replacingOccurrences(of: "'", with: "''"))%'" - } - ) + let whereClause = mssqlWhereClause(filters: filters, logicMode: logicMode, columnKinds: columnKinds) let orderBy = PluginSQLFilter.buildOrderByClause( sortColumns: sortColumns, columns: columns, quoteIdentifier: mssqlQuoteIdentifier ) ?? "ORDER BY (SELECT NULL)" @@ -799,13 +786,43 @@ final class MSSQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { quoteIdentifier(identifier) } + /// The shared builder writes the `LIKE` arms' literal itself rather than asking for one, so + /// SQL Server answers those arms first and lets every other operator fall through to it. + private func mssqlWhereClause( + filters: [(column: String, op: String, value: String)], + logicMode: String, + columnKinds: [String: PluginColumnKind] + ) -> String { + let conditions = filters.compactMap { filter -> String? in + let quoted = mssqlQuoteIdentifier(filter.column) + if let like = MSSQLStringLiteral.likeCondition( + quotedColumn: quoted, op: filter.op, value: filter.value + ) { + return like + } + return PluginSQLFilter.buildFilterCondition( + column: filter.column, + op: filter.op, + value: filter.value, + kind: columnKinds[filter.column], + quoteIdentifier: mssqlQuoteIdentifier, + escapeTypedValue: mssqlEscapeValue, + regexCondition: { quoted, value in + "\(quoted) LIKE \(MSSQLStringLiteral.quoted("%\(value)%"))" + } + ) + } + guard !conditions.isEmpty else { return "" } + return conditions.joined(separator: logicMode == "and" ? " AND " : " OR ") + } + private func mssqlEscapeValue(_ value: String, kind: PluginColumnKind?) -> String { PluginSQLLiteral.escapedLiteral( value, kind: kind, trueLiteral: "1", falseLiteral: "0", - quote: { "'\($0.replacingOccurrences(of: "'", with: "''"))'" } + quote: MSSQLStringLiteral.quoted ) } @@ -881,8 +898,8 @@ final class MSSQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { return schema } - func effectiveSchemaEscaped(_ schema: String?) -> String { - MSSQLSchemaQueries.escape(effectiveSchema(schema)) + func effectiveSchemaQuoted(_ schema: String?) -> String { + MSSQLStringLiteral.quoted(effectiveSchema(schema)) } } diff --git a/Plugins/MSSQLDriverPlugin/MSSQLPluginDriver+DDL.swift b/Plugins/MSSQLDriverPlugin/MSSQLPluginDriver+DDL.swift index 704d8840b1..3a8f847c56 100644 --- a/Plugins/MSSQLDriverPlugin/MSSQLPluginDriver+DDL.swift +++ b/Plugins/MSSQLDriverPlugin/MSSQLPluginDriver+DDL.swift @@ -116,22 +116,25 @@ extension MSSQLPluginDriver { // Rename column first so subsequent statements reference the correct name if oldColumn.name != newColumn.name { - let escapedPath = "\(escapeStringLiteral(_currentSchema)).\(escapeStringLiteral(table)).\(escapeStringLiteral(oldColumn.name))" - stmts.append("EXEC sp_rename '\(escapedPath)', '\(escapeStringLiteral(newColumn.name))', 'COLUMN'") + let path = MSSQLStringLiteral.quoted("\(_currentSchema).\(table).\(oldColumn.name)") + let renamed = MSSQLStringLiteral.quoted(newColumn.name) + stmts.append("EXEC sp_rename \(path), \(renamed), 'COLUMN'") } let colName = quoteIdentifier(newColumn.name) // Drop existing default constraint before ALTER COLUMN or default change if (defaultChanged || needsTypeChange) && oldColumn.defaultValue != nil { - let objectId = escapeStringLiteral("\(_currentSchema).\(table)") + let objectLiteral = MSSQLStringLiteral.quoted(qt) + let dropPrefix = MSSQLStringLiteral.quoted("ALTER TABLE \(qt) DROP CONSTRAINT ") stmts.append(""" DECLARE @dfName NVARCHAR(256); \ SELECT @dfName = dc.name FROM sys.default_constraints dc \ JOIN sys.columns c ON dc.parent_column_id = c.column_id AND dc.parent_object_id = c.object_id \ - WHERE c.name = '\(escapeStringLiteral(newColumn.name))' \ - AND dc.parent_object_id = OBJECT_ID('\(objectId)'); \ - IF @dfName IS NOT NULL EXEC('ALTER TABLE \(qt) DROP CONSTRAINT [' + @dfName + ']') + WHERE c.name = \(MSSQLStringLiteral.quoted(newColumn.name)) \ + AND dc.parent_object_id = OBJECT_ID(\(objectLiteral)); \ + IF @dfName IS NOT NULL BEGIN DECLARE @dropSql NVARCHAR(MAX) = \(dropPrefix) + QUOTENAME(@dfName); \ + EXEC(@dropSql); END """) } @@ -185,17 +188,14 @@ extension MSSQLPluginDriver { /// `sys.check_constraints.parent_column_id` is 0 for a multi-column check, so the columns come /// from `sys.sql_expression_dependencies`, which lists them for both shapes. func fetchCheckConstraints(table: String, schema: String?) async throws -> [PluginCheckConstraintInfo] { - // Bracket-quoting makes `target` a safe identifier, but it lands inside a string literal - // here, so it needs literal escaping too: a legal name like O'Reilly would otherwise - // terminate the literal. - let target = escapeStringLiteral(mssqlQualifiedTable(table)) + let targetLiteral = MSSQLStringLiteral.quoted(mssqlQualifiedTable(table)) let query = """ SELECT cc.name, cc.definition, cc.is_not_trusted, COL_NAME(d.referenced_id, d.referenced_minor_id) FROM sys.check_constraints cc LEFT JOIN sys.sql_expression_dependencies d ON d.referencing_id = cc.object_id AND d.referenced_minor_id > 0 - WHERE cc.parent_object_id = OBJECT_ID(\'\(target)\') + WHERE cc.parent_object_id = OBJECT_ID(\(targetLiteral)) ORDER BY cc.name """ let result = try await execute(query: query) diff --git a/Plugins/MSSQLDriverPlugin/MSSQLPluginDriver+Schema.swift b/Plugins/MSSQLDriverPlugin/MSSQLPluginDriver+Schema.swift index 1d3cee5d57..141dd5b162 100644 --- a/Plugins/MSSQLDriverPlugin/MSSQLPluginDriver+Schema.swift +++ b/Plugins/MSSQLDriverPlugin/MSSQLPluginDriver+Schema.swift @@ -13,11 +13,11 @@ extension MSSQLPluginDriver { func fetchTables(schema: String?) async throws -> [PluginTableInfo] { let resolved = effectiveSchema(schema) - let esc = MSSQLSchemaQueries.escape(resolved) + let schemaLiteral = MSSQLStringLiteral.quoted(resolved) let sql = """ SELECT t.TABLE_NAME, t.TABLE_TYPE FROM INFORMATION_SCHEMA.TABLES t - WHERE t.TABLE_SCHEMA = '\(esc)' + WHERE t.TABLE_SCHEMA = \(schemaLiteral) AND t.TABLE_TYPE IN ('BASE TABLE', 'VIEW') ORDER BY t.TABLE_NAME """ @@ -31,8 +31,8 @@ extension MSSQLPluginDriver { } func fetchColumns(table: String, schema: String?) async throws -> [PluginColumnInfo] { - let escapedTable = table.replacingOccurrences(of: "'", with: "''") - let esc = effectiveSchemaEscaped(schema) + let tableLiteral = MSSQLStringLiteral.quoted(table) + let schemaLiteral = effectiveSchemaQuoted(schema) let sql = """ SELECT c.COLUMN_NAME, @@ -53,11 +53,11 @@ extension MSSQLPluginDriver { ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND tc.TABLE_SCHEMA = kcu.TABLE_SCHEMA WHERE tc.CONSTRAINT_TYPE = 'PRIMARY KEY' - AND tc.TABLE_SCHEMA = '\(esc)' - AND tc.TABLE_NAME = '\(escapedTable)' + AND tc.TABLE_SCHEMA = \(schemaLiteral) + AND tc.TABLE_NAME = \(tableLiteral) ) pk ON c.COLUMN_NAME = pk.COLUMN_NAME - WHERE c.TABLE_NAME = '\(escapedTable)' - AND c.TABLE_SCHEMA = '\(esc)' + WHERE c.TABLE_NAME = \(tableLiteral) + AND c.TABLE_SCHEMA = \(schemaLiteral) ORDER BY c.ORDINAL_POSITION """ let result = try await execute(query: sql) @@ -153,7 +153,7 @@ extension MSSQLPluginDriver { func fetchIndexes(table: String, schema: String?) async throws -> [PluginIndexInfo] { /// Bracket-escaped for the identifier and literal-escaped for the string it sits in: /// SQL Server allows both `]` and `'` in an identifier. - let bracketedFull = MSSQLSchemaQueries.escape( + let objectLiteral = MSSQLStringLiteral.quoted( MSSQLSchemaQueries.bracketed(schema: effectiveSchema(schema), table: table)) let sql = """ SELECT i.name, i.is_unique, i.is_primary_key, c.name AS column_name, i.type_desc @@ -162,7 +162,7 @@ extension MSSQLPluginDriver { ON i.object_id = ic.object_id AND i.index_id = ic.index_id JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id - WHERE i.object_id = OBJECT_ID('\(bracketedFull)') + WHERE i.object_id = OBJECT_ID(\(objectLiteral)) AND i.name IS NOT NULL ORDER BY i.index_id, ic.key_ordinal """ @@ -208,7 +208,7 @@ extension MSSQLPluginDriver { /// The bracketed name is spliced into a string literal, so a name carrying a quote needs /// the literal escape as well as the bracket one. SQL Server allows both characters in an /// identifier. - let objectRef = MSSQLSchemaQueries.escape( + let objectLiteral = MSSQLStringLiteral.quoted( MSSQLSchemaQueries.bracketed(schema: effectiveSchema(schema), table: table)) let sql = """ SELECT i.name, i.type_desc, i.is_unique, i.filter_definition, @@ -218,7 +218,7 @@ extension MSSQLPluginDriver { ON i.object_id = ic.object_id AND i.index_id = ic.index_id JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id - WHERE i.object_id = OBJECT_ID('\(objectRef)') + WHERE i.object_id = OBJECT_ID(\(objectLiteral)) AND i.name IS NOT NULL AND i.is_primary_key = 0 AND i.type IN (1, 2) @@ -270,7 +270,8 @@ extension MSSQLPluginDriver { func fetchTriggerDefinition(name: String, table: String, schema: String?) async throws -> String? { let esc = MSSQLSchemaQueries.escapeBracket(effectiveSchema(schema)) let bracketedName = name.replacingOccurrences(of: "]", with: "]]") - let sql = "SELECT OBJECT_DEFINITION(OBJECT_ID('[\(esc)].[\(bracketedName)]'))" + let objectLiteral = MSSQLStringLiteral.quoted("[\(esc)].[\(bracketedName)]") + let sql = "SELECT OBJECT_DEFINITION(OBJECT_ID(\(objectLiteral)))" let result = try await execute(query: sql) guard let definition = result.rows.first?[safe: 0]?.asText, !definition.isEmpty else { return nil } guard let range = definition.range(of: "CREATE TRIGGER", options: .caseInsensitive) else { @@ -285,7 +286,7 @@ extension MSSQLPluginDriver { } func fetchAllColumns(schema: String?) async throws -> [String: [PluginColumnInfo]] { - let esc = effectiveSchemaEscaped(schema) + let schemaLiteral = effectiveSchemaQuoted(schema) let sql = """ SELECT c.TABLE_NAME, @@ -307,9 +308,9 @@ extension MSSQLPluginDriver { ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND tc.TABLE_SCHEMA = kcu.TABLE_SCHEMA WHERE tc.CONSTRAINT_TYPE = 'PRIMARY KEY' - AND tc.TABLE_SCHEMA = '\(esc)' + AND tc.TABLE_SCHEMA = \(schemaLiteral) ) pk ON c.TABLE_NAME = pk.TABLE_NAME AND c.COLUMN_NAME = pk.COLUMN_NAME - WHERE c.TABLE_SCHEMA = '\(esc)' + WHERE c.TABLE_SCHEMA = \(schemaLiteral) ORDER BY c.TABLE_NAME, c.ORDINAL_POSITION """ let result = try await execute(query: sql) @@ -377,7 +378,7 @@ extension MSSQLPluginDriver { var tableDDLIncludesForeignKeys: Bool { true } func fetchAllForeignKeys(schema: String?) async throws -> [String: [PluginForeignKeyInfo]] { - let esc = effectiveSchemaEscaped(schema) + let schemaLiteral = effectiveSchemaQuoted(schema) let sql = """ SELECT tp.name AS table_name, @@ -396,7 +397,7 @@ extension MSSQLPluginDriver { JOIN sys.schemas sr ON tr.schema_id = sr.schema_id JOIN sys.columns cr ON fkc.referenced_object_id = cr.object_id AND fkc.referenced_column_id = cr.column_id - WHERE s.name = '\(esc)' + WHERE s.name = \(schemaLiteral) ORDER BY tp.name, fk.name """ let result = try await execute(query: sql) @@ -472,13 +473,12 @@ extension MSSQLPluginDriver { } func fetchTableDDL(table: String, schema: String?) async throws -> String { - let escapedTable = table.replacingOccurrences(of: "'", with: "''") - let esc = effectiveSchemaEscaped(schema) + let qualified = MSSQLSchemaQueries.bracketed(schema: effectiveSchema(schema), table: table) let cols = try await fetchColumns(table: table, schema: schema) let indexes = try await fetchIndexes(table: table, schema: schema) let fks = try await fetchForeignKeys(table: table, schema: schema) - var ddl = "CREATE TABLE [\(esc)].[\(escapedTable)] (\n" + var ddl = "CREATE TABLE \(qualified) (\n" let colDefs = cols.map { col -> String in var def = " [\(col.name)] \(col.dataType.uppercased())" if col.extra == "IDENTITY" { def += " IDENTITY(1,1)" } @@ -506,16 +506,15 @@ extension MSSQLPluginDriver { } func fetchViewDefinition(view: String, schema: String?) async throws -> String { - let esc = effectiveSchemaEscaped(schema) - let escapedView = "\(esc).\(view.replacingOccurrences(of: "'", with: "''"))" - let sql = "SELECT definition FROM sys.sql_modules WHERE object_id = OBJECT_ID('\(escapedView)')" + let viewLiteral = MSSQLStringLiteral.quoted("\(effectiveSchema(schema)).\(view)") + let sql = "SELECT definition FROM sys.sql_modules WHERE object_id = OBJECT_ID(\(viewLiteral))" let result = try await execute(query: sql) return result.rows.first?.first?.asText ?? "" } func fetchTableMetadata(table: String, schema: String?) async throws -> PluginTableMetadata { - let escapedTable = table.replacingOccurrences(of: "'", with: "''") - let esc = effectiveSchemaEscaped(schema) + let tableLiteral = MSSQLStringLiteral.quoted(table) + let schemaLiteral = effectiveSchemaQuoted(schema) let sql = """ SELECT SUM(p.rows) AS row_count, @@ -528,7 +527,7 @@ extension MSSQLPluginDriver { JOIN sys.allocation_units a ON p.partition_id = a.container_id LEFT JOIN sys.extended_properties ep ON ep.major_id = t.object_id AND ep.minor_id = 0 AND ep.name = 'MS_Description' - WHERE t.name = '\(escapedTable)' AND s.name = '\(esc)' + WHERE t.name = \(tableLiteral) AND s.name = \(schemaLiteral) GROUP BY ep.value """ let result = try await execute(query: sql) diff --git a/Plugins/TableProPluginKit/ClickHouseResponseClassifier.swift b/Plugins/TableProPluginKit/ClickHouseResponseClassifier.swift index fb60bc6624..9cd46409fa 100644 --- a/Plugins/TableProPluginKit/ClickHouseResponseClassifier.swift +++ b/Plugins/TableProPluginKit/ClickHouseResponseClassifier.swift @@ -37,11 +37,11 @@ public enum ClickHouseResponseClassifier { if let format = headerValue(headers, named: formatHeaderName), format != requestedFormat { return rawOutcome(body: body) } - let text = decodedText(body) - guard !text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { + let bytes = [UInt8](body) + guard !ClickHouseTabSeparatedBytes.isAsciiWhitespace(bytes) else { return noResultSetOutcome(headers: headers) } - let lines = text.components(separatedBy: "\n") + let lines = ClickHouseTabSeparatedBytes.lines(bytes) guard lines.count >= 2 else { return rawOutcome(body: body) } @@ -58,30 +58,8 @@ public enum ClickHouseResponseClassifier { } public static func unescapeTsvField(_ field: String) -> String { - var result = "" - result.reserveCapacity((field as NSString).length) - var iterator = field.makeIterator() - - while let char = iterator.next() { - if char == "\\" { - if let next = iterator.next() { - switch next { - case "\\": result.append("\\") - case "t": result.append("\t") - case "n": result.append("\n") - default: - result.append("\\") - result.append(next) - } - } else { - result.append("\\") - } - } else { - result.append(char) - } - } - - return result + let bytes = Array(field.utf8) + return String(decoding: ClickHouseTabSeparatedBytes.unescape(bytes[...]), as: UTF8.self) // swiftlint:disable:this optional_data_string_conversion } private static func noResultSetOutcome(headers: [String: String]) -> Outcome { @@ -94,31 +72,49 @@ public enum ClickHouseResponseClassifier { ) } + /// A body the server wrote in a format the user asked for is one opaque value. It is text when + /// it decodes as text and bytes when it does not, because a `Native` or `Parquet` body read as + /// Latin-1 is mojibake that cannot be copied back out. private static func rawOutcome(body: Data) -> Outcome { let isTruncated = body.count > rawBodyByteCap - let text = decodedText(body.prefix(rawBodyByteCap)) + let capped = [UInt8](body.prefix(rawBodyByteCap)) + let decodable = isTruncated ? Array(droppingCutSequence(capped)) : capped + let value: PluginCellValue = utf8Text(decodable).map { .text($0) } ?? .bytes(Data(capped)) return Outcome( columns: [String(localized: "Output")], columnTypeNames: ["String"], - rows: [[.text(text)]], + rows: [[value]], affectedRows: 1, isTruncated: isTruncated ) } - private static func tabSeparatedOutcome(lines: [String], rowLimit: Int) -> Outcome { - let columns = lines[0].components(separatedBy: "\t") - let columnTypeNames = lines[1].components(separatedBy: "\t") + private static func tabSeparatedOutcome(lines: [ArraySlice], rowLimit: Int) -> Outcome { + let columns = ClickHouseTabSeparatedBytes.fields(lines[0]).map(ClickHouseTabSeparatedBytes.headerText) + let columnTypeNames = ClickHouseTabSeparatedBytes.fields(lines[1]).map(ClickHouseTabSeparatedBytes.headerText) var rows: [[PluginCellValue]] = [] + var binaryColumns = Set() var isTruncated = false for index in 2..= rowLimit { @@ -130,19 +126,52 @@ public enum ClickHouseResponseClassifier { return Outcome( columns: columns, columnTypeNames: columnTypeNames, - rows: rows, + rows: demoteBinaryColumns(binaryColumns, in: rows), affectedRows: rows.count, isTruncated: isTruncated ) } - private static func decodedText(_ data: Data) -> String { - for suffixLength in 0...3 where data.count >= suffixLength { - if let text = String(bytes: data.dropLast(suffixLength), encoding: .utf8) { - return text + /// One value that is not text makes the whole column binary. A `FixedString(16)` of raw UUIDs + /// decodes on the rows whose bytes happen to be valid UTF-8 and not on the rest, and a column + /// that renders as hex on some rows and as mojibake on others is the worse answer. Re-encoding + /// a decoded value is exact: UTF-8 round-trips whenever the decode succeeded. + private static func demoteBinaryColumns( + _ binaryColumns: Set, + in rows: [[PluginCellValue]] + ) -> [[PluginCellValue]] { + guard !binaryColumns.isEmpty else { return rows } + return rows.map { row in + row.enumerated().map { column, value in + guard binaryColumns.contains(column), case .text(let text) = value else { return value } + return .bytes(Data(text.utf8)) + } + } + } + + private static func utf8Text(_ bytes: [UInt8]) -> String? { + String(bytes: bytes, encoding: .utf8) + } + + /// The byte cap can stop inside a multi-byte character, so a truncated body sheds that one + /// incomplete sequence and nothing else. Dropping trailing bytes until the rest decodes would + /// call a short binary body text, and a field is never cut, so it never comes through here. + private static func droppingCutSequence(_ bytes: [UInt8]) -> ArraySlice { + guard !bytes.isEmpty else { return bytes[...] } + for offset in 1...min(3, bytes.count) { + let index = bytes.count - offset + let byte = bytes[index] + if byte & 0xC0 == 0x80 { continue } + let sequenceLength: Int + switch byte { + case 0xC0...0xDF: sequenceLength = 2 + case 0xE0...0xEF: sequenceLength = 3 + case 0xF0...0xF7: sequenceLength = 4 + default: return bytes[...] } + return offset < sequenceLength ? bytes[.. String? { diff --git a/Plugins/TableProPluginKit/ClickHouseTabSeparatedBytes.swift b/Plugins/TableProPluginKit/ClickHouseTabSeparatedBytes.swift new file mode 100644 index 0000000000..a71f741181 --- /dev/null +++ b/Plugins/TableProPluginKit/ClickHouseTabSeparatedBytes.swift @@ -0,0 +1,98 @@ +import Foundation + +/// ClickHouse writes `TabSeparated` as a byte stream, not as text. A `String` column is an +/// arbitrary byte sequence, and the only bytes the format escapes are the eight below, so a value +/// holding a hash, a protobuf or a lone `0xC3` reaches the client verbatim. Splitting and +/// unescaping therefore happen on bytes, and only a finished field is offered to a text decode. +internal enum ClickHouseTabSeparatedBytes { + static let lineSeparator: UInt8 = 0x0A + static let fieldSeparator: UInt8 = 0x09 + private static let backslash: UInt8 = 0x5C + private static let nullMarkerSuffix: UInt8 = 0x4E + + static func lines(_ bytes: [UInt8]) -> [ArraySlice] { + split(bytes[...], on: lineSeparator) + } + + static func fields(_ line: ArraySlice) -> [ArraySlice] { + split(line, on: fieldSeparator) + } + + static func isNullMarker(_ field: ArraySlice) -> Bool { + field.count == 2 && field.first == backslash && field.last == nullMarkerSuffix + } + + static func isAsciiWhitespace(_ bytes: [UInt8]) -> Bool { + bytes.allSatisfy { $0 == 0x20 || $0 == 0x09 || $0 == 0x0A || $0 == 0x0D || $0 == 0x0B || $0 == 0x0C } + } + + /// The escape table ClickHouse's own `writeEscapedString` emits. An unrecognised escape keeps + /// both of its bytes: a future addition then reads oddly rather than losing the character. + static func unescape(_ field: ArraySlice) -> [UInt8] { + guard field.contains(backslash) else { return Array(field) } + + var result: [UInt8] = [] + result.reserveCapacity(field.count) + var index = field.startIndex + + while index < field.endIndex { + let byte = field[index] + guard byte == backslash else { + result.append(byte) + index = field.index(after: index) + continue + } + let next = field.index(after: index) + guard next < field.endIndex else { + result.append(backslash) + break + } + if let decoded = escapedByte(field[next]) { + result.append(decoded) + } else { + result.append(backslash) + result.append(field[next]) + } + index = field.index(after: next) + } + + return result + } + + /// Nil when the byte after the backslash is not one ClickHouse escapes. + static func escapedByte(_ byte: UInt8) -> UInt8? { + switch byte { + case 0x5C: return 0x5C + case 0x74: return 0x09 + case 0x6E: return 0x0A + case 0x72: return 0x0D + case 0x30: return 0x00 + case 0x62: return 0x08 + case 0x66: return 0x0C + case 0x27: return 0x27 + default: return nil + } + } + + /// A header field has to become a `String`, so an undecodable byte is replaced rather than + /// dropping the column. A value never takes this path; it stays bytes instead. + static func headerText(_ field: ArraySlice) -> String { + String(decoding: unescape(field), as: UTF8.self) // swiftlint:disable:this optional_data_string_conversion + } + + private static func split(_ bytes: ArraySlice, on separator: UInt8) -> [ArraySlice] { + var parts: [ArraySlice] = [] + var start = bytes.startIndex + var index = bytes.startIndex + + while index < bytes.endIndex { + if bytes[index] == separator { + parts.append(bytes[start.. String private let columnTypesByName: [String: ColumnType] + private let stringLiteralPrefix: String init( dialect: SQLDialectDescriptor, columns: [String] = [], columnTypes: [ColumnType] = [], - quoteIdentifier: ((String) -> String)? = nil + quoteIdentifier: ((String) -> String)? = nil, + stringLiteralPrefix: String = "" ) { self.dialect = dialect self.quoteIdentifierFn = quoteIdentifier ?? quoteIdentifierFromDialect(dialect) self.columnTypesByName = ColumnTypeSQLQuoting.lookupByName(columns: columns, columnTypes: columnTypes) + self.stringLiteralPrefix = stringLiteralPrefix + } + + /// The one place a string literal is spelled, so the engine's prefix cannot be forgotten on + /// one arm and applied on another. + private func quotedLiteral(_ escapedBody: String) -> String { + "\(stringLiteralPrefix)'\(escapedBody)'" } // MARK: - Public API @@ -147,7 +156,7 @@ struct FilterSQLGenerator { case .regex: let operand = patternOperand(quotedColumn, columnType: columnType) guard dialect.regexSyntax != .unsupported else { - let pattern = "'%\(escapeSQLQuote(filter.value))%'" + let pattern = quotedLiteral("%\(escapeSQLQuote(filter.value))%") return "\(folding.foldingLikeOperand(operand)) \(folding.likeKeyword) " + folding.foldingLikeOperand(pattern) } @@ -292,7 +301,7 @@ struct FilterSQLGenerator { negated: Bool, folding: PluginSQLCaseFolding ) -> String { - let quotedPattern = "'\(escapeSQLQuote(pattern))'" + let quotedPattern = quotedLiteral(escapeSQLQuote(pattern)) let keyword = negated ? folding.notLikeKeyword : folding.likeKeyword let operand = folding.foldingLikeOperand(column) return "\(operand) \(keyword) \(folding.foldingLikeOperand(quotedPattern))\(likeEscapeClause)" @@ -357,7 +366,7 @@ struct FilterSQLGenerator { guard ignoresCase else { return "match(\(column), '\(escapedPattern)')" } return "match(\(column), '(?i)\(escapedPattern)')" case .unsupported: - return "\(column) LIKE '%\(escapedPattern)%'" + return "\(column) LIKE \(quotedLiteral("%\(escapedPattern)%"))" } } @@ -379,7 +388,7 @@ struct FilterSQLGenerator { return .value(trimmed) } - return .value("'\(escapeStringValue(trimmed))'") + return .value(quotedLiteral(escapeStringValue(trimmed))) } private func booleanLiteral(for value: String, columnType: ColumnType?) -> String? { diff --git a/TablePro/Core/Database/ForeignKeyLookupQuery.swift b/TablePro/Core/Database/ForeignKeyLookupQuery.swift index 895e12594c..747a48c5ef 100644 --- a/TablePro/Core/Database/ForeignKeyLookupQuery.swift +++ b/TablePro/Core/Database/ForeignKeyLookupQuery.swift @@ -27,6 +27,7 @@ enum ForeignKeyLookupQuery { label: ForeignKeyLookupColumn?, searchTerm: String, dialect: SQLDialectDescriptor, + stringLiteralPrefix: String, quoteIdentifier: @escaping (String) -> String ) -> String? { let selected = selectedColumns(key: key, label: label) @@ -35,7 +36,8 @@ enum ForeignKeyLookupQuery { dialect: dialect, columns: selected.map(\.name), columnTypes: selected.map(\.type), - quoteIdentifier: quoteIdentifier + quoteIdentifier: quoteIdentifier, + stringLiteralPrefix: stringLiteralPrefix ) /// A referenced column may be a nullable `UNIQUE` one, and ascending order puts its NULLs diff --git a/TablePro/Core/Services/Query/ForeignKeyLookupService.swift b/TablePro/Core/Services/Query/ForeignKeyLookupService.swift index 8f1e7a294d..754ba09d52 100644 --- a/TablePro/Core/Services/Query/ForeignKeyLookupService.swift +++ b/TablePro/Core/Services/Query/ForeignKeyLookupService.swift @@ -72,6 +72,7 @@ enum ForeignKeyLookupService { label: label, searchTerm: term, dialect: dialect, + stringLiteralPrefix: SQLStringLiteralPrefix.forDatabaseType(databaseType), quoteIdentifier: driver.quoteIdentifier ) else { return [] diff --git a/TablePro/Core/Services/Query/TableQueryBuilder.swift b/TablePro/Core/Services/Query/TableQueryBuilder.swift index 2c81faffda..ac2c9aac5f 100644 --- a/TablePro/Core/Services/Query/TableQueryBuilder.swift +++ b/TablePro/Core/Services/Query/TableQueryBuilder.swift @@ -128,7 +128,8 @@ struct TableQueryBuilder { if let dialect { let activeFilters = filters.filter { $0.isEnabled } let filterGen = FilterSQLGenerator( - dialect: dialect, columns: columns, columnTypes: columnTypes, quoteIdentifier: dialectQuote + dialect: dialect, columns: columns, columnTypes: columnTypes, quoteIdentifier: dialectQuote, + stringLiteralPrefix: SQLStringLiteralPrefix.forDatabaseType(databaseType) ) let whereClause = filterGen.generateWhereClause(from: activeFilters, logicMode: logicMode) if !whereClause.isEmpty { @@ -196,7 +197,8 @@ struct TableQueryBuilder { let quotedTable = qualifiedTable(tableName, schema: schemaName) let activeFilters = filters.filter { $0.isEnabled } let filterGen = FilterSQLGenerator( - dialect: dialect, columns: columns, columnTypes: columnTypes, quoteIdentifier: dialectQuote + dialect: dialect, columns: columns, columnTypes: columnTypes, quoteIdentifier: dialectQuote, + stringLiteralPrefix: SQLStringLiteralPrefix.forDatabaseType(databaseType) ) let whereClause = filterGen.generateWhereClause(from: activeFilters, logicMode: logicMode) diff --git a/TablePro/Core/Utilities/SQL/SQLStringLiteralPrefix.swift b/TablePro/Core/Utilities/SQL/SQLStringLiteralPrefix.swift new file mode 100644 index 0000000000..1efadeca7b --- /dev/null +++ b/TablePro/Core/Utilities/SQL/SQLStringLiteralPrefix.swift @@ -0,0 +1,27 @@ +// +// SQLStringLiteralPrefix.swift +// TablePro +// + +import Foundation + +/// What an engine puts in front of a string literal that carries user text. +/// +/// SQL Server is the one engine that needs anything: a plain `'…'` is a `varchar` literal, so the +/// server converts it to the database collation's code page while it parses the batch, and on a +/// non-Unicode collation every character outside that page becomes `?`. That happens whatever the +/// column is, so `WHERE n = '日本語'` on an `NVARCHAR` column matches nothing the user meant. +/// `N'…'` is an `nvarchar` literal and is converted by nothing; on ASCII the two are equal. +/// +/// A number, an identifier and a `0x` binary literal never come through here. +enum SQLStringLiteralPrefix { + static func forDatabaseType(_ databaseType: DatabaseType?) -> String { + guard let databaseType else { return "" } + switch databaseType { + case .mssql: + return "N" + default: + return "" + } + } +} diff --git a/TableProTests/Core/Database/FilterSQLGeneratorMSSQLTests.swift b/TableProTests/Core/Database/FilterSQLGeneratorMSSQLTests.swift index e5b73df353..6ae2760d0e 100644 --- a/TableProTests/Core/Database/FilterSQLGeneratorMSSQLTests.swift +++ b/TableProTests/Core/Database/FilterSQLGeneratorMSSQLTests.swift @@ -18,7 +18,10 @@ struct FilterSQLGeneratorMSSQLTests { likeEscapeStyle: .explicit, paginationStyle: .offsetFetch ) - private let generator = FilterSQLGenerator(dialect: Self.mssqlDialect) + private let generator = FilterSQLGenerator( + dialect: Self.mssqlDialect, + stringLiteralPrefix: SQLStringLiteralPrefix.forDatabaseType(.mssql) + ) // MARK: - Helpers @@ -37,21 +40,21 @@ struct FilterSQLGeneratorMSSQLTests { func equalOperator() { let filter = makeFilter(op: .equal) let result = generator.generateCondition(from: filter) - #expect(result == "[name] = 'test'") + #expect(result == "[name] = N'test'") } @Test("Not equal operator uses bracket-quoted column") func notEqualOperator() { let filter = makeFilter(op: .notEqual) let result = generator.generateCondition(from: filter) - #expect(result == "[name] != 'test'") + #expect(result == "[name] != N'test'") } @Test("Contains operator generates LIKE with ESCAPE clause") func containsOperator() { let filter = makeFilter(op: .contains) let result = generator.generateCondition(from: filter) - #expect(result?.contains("[name] LIKE '%test%'") == true) + #expect(result?.contains("[name] LIKE N'%test%'") == true) #expect(result?.contains("ESCAPE") == true) } @@ -59,7 +62,7 @@ struct FilterSQLGeneratorMSSQLTests { func notContainsOperator() { let filter = makeFilter(op: .notContains) let result = generator.generateCondition(from: filter) - #expect(result?.contains("[name] NOT LIKE '%test%'") == true) + #expect(result?.contains("[name] NOT LIKE N'%test%'") == true) #expect(result?.contains("ESCAPE") == true) } @@ -67,7 +70,7 @@ struct FilterSQLGeneratorMSSQLTests { func startsWithOperator() { let filter = makeFilter(op: .startsWith) let result = generator.generateCondition(from: filter) - #expect(result?.contains("[name] LIKE 'test%'") == true) + #expect(result?.contains("[name] LIKE N'test%'") == true) #expect(result?.contains("ESCAPE") == true) } @@ -75,7 +78,7 @@ struct FilterSQLGeneratorMSSQLTests { func endsWithOperator() { let filter = makeFilter(op: .endsWith) let result = generator.generateCondition(from: filter) - #expect(result?.contains("[name] LIKE '%test'") == true) + #expect(result?.contains("[name] LIKE N'%test'") == true) #expect(result?.contains("ESCAPE") == true) } @@ -130,7 +133,7 @@ struct FilterSQLGeneratorMSSQLTests { func singleQuoteEscaping() { let filter = makeFilter(column: "name", op: .equal, value: "O'Brien") let result = generator.generateCondition(from: filter) - #expect(result == "[name] = 'O''Brien'") + #expect(result == "[name] = N'O''Brien'") } // MARK: - WHERE Clause Tests @@ -144,7 +147,7 @@ struct FilterSQLGeneratorMSSQLTests { let result = generator.generateWhereClause(from: filters, logicMode: .and) #expect(result.contains("WHERE")) #expect(result.contains("AND")) - #expect(result.contains("[name] = 'Alice'")) + #expect(result.contains("[name] = N'Alice'")) #expect(result.contains("[age] > 18")) } @@ -157,8 +160,8 @@ struct FilterSQLGeneratorMSSQLTests { let result = generator.generateWhereClause(from: filters, logicMode: .or) #expect(result.contains("WHERE")) #expect(result.contains("OR")) - #expect(result.contains("[name] = 'Alice'")) - #expect(result.contains("[name] = 'Bob'")) + #expect(result.contains("[name] = N'Alice'")) + #expect(result.contains("[name] = N'Bob'")) } // MARK: - Identifier Quoting Tests @@ -169,4 +172,45 @@ struct FilterSQLGeneratorMSSQLTests { let result = generator.generateCondition(from: filter) #expect(result?.hasPrefix("[user_name]") == true) } + + // MARK: - Unicode Literals + + @Test("A non-ASCII value is an nvarchar literal, so a non-Unicode collation cannot flatten it") + func nonAsciiValueIsANationalLiteral() { + let filter = makeFilter(op: .equal, value: "日本語メール") + #expect(generator.generateCondition(from: filter) == "[name] = N'日本語メール'") + } + + @Test("Every value-carrying operator writes a national literal") + func everyValueOperatorWritesANationalLiteral() { + let operators: [FilterOperator] = [ + .equal, .notEqual, .contains, .notContains, .startsWith, .endsWith, .regex + ] + for op in operators { + let result = generator.generateCondition(from: makeFilter(op: op, value: "メール")) ?? "" + let body = result.replacingOccurrences(of: " ESCAPE '!'", with: "") + #expect(body.contains("N'"), "\(op) wrote no national literal") + #expect(!body.contains(" '"), "\(op) wrote a plain literal: \(result)") + } + } + + @Test("An IN list prefixes every element") + func inListPrefixesEveryElement() { + let filter = makeFilter(op: .inList, value: "メール,alpha") + let result = generator.generateCondition(from: filter) + #expect(result == "[name] IN (N'メール', N'alpha')") + } + + @Test("Numbers and NULL never take the prefix") + func numbersAndNullAreNotPrefixed() { + #expect(generator.generateCondition(from: makeFilter(column: "age", op: .greaterThan, value: "30")) + == "[age] > 30") + #expect(generator.generateCondition(from: makeFilter(op: .isNull)) == "[name] IS NULL") + } + + @Test("A driver with no prefix is untouched") + func otherEnginesKeepPlainLiterals() { + let plain = FilterSQLGenerator(dialect: Self.mssqlDialect) + #expect(plain.generateCondition(from: makeFilter(op: .equal)) == "[name] = 'test'") + } } diff --git a/TableProTests/Core/Database/ForeignKeyLookupQueryTests.swift b/TableProTests/Core/Database/ForeignKeyLookupQueryTests.swift index 94c3f87cf8..61720ad6e9 100644 --- a/TableProTests/Core/Database/ForeignKeyLookupQueryTests.swift +++ b/TableProTests/Core/Database/ForeignKeyLookupQueryTests.swift @@ -33,7 +33,8 @@ struct ForeignKeyLookupQueryTests { key: ForeignKeyLookupColumn? = nil, label: ForeignKeyLookupColumn?, term: String, - dialect: SQLDialectDescriptor? = nil + dialect: SQLDialectDescriptor? = nil, + stringLiteralPrefix: String = "" ) -> String? { ForeignKeyLookupQuery.rows( quotedTable: "\"Artist\"", @@ -41,6 +42,7 @@ struct ForeignKeyLookupQueryTests { label: label, searchTerm: term, dialect: dialect ?? self.dialect(), + stringLiteralPrefix: stringLiteralPrefix, quoteIdentifier: quote ) } diff --git a/TableProTests/Core/Database/SQLStringLiteralPrefixTests.swift b/TableProTests/Core/Database/SQLStringLiteralPrefixTests.swift new file mode 100644 index 0000000000..757388cc3e --- /dev/null +++ b/TableProTests/Core/Database/SQLStringLiteralPrefixTests.swift @@ -0,0 +1,29 @@ +// +// SQLStringLiteralPrefixTests.swift +// TableProTests +// + +import Foundation +@testable import TablePro +import Testing + +@Suite("SQL String Literal Prefix") +struct SQLStringLiteralPrefixTests { + @Test("SQL Server asks for a national literal") + func sqlServerAsksForANationalLiteral() { + #expect(SQLStringLiteralPrefix.forDatabaseType(.mssql) == "N") + } + + @Test("Every other engine writes a plain literal") + func otherEnginesWritePlainLiterals() { + for type in DatabaseType.allKnownTypes where type != .mssql { + #expect(SQLStringLiteralPrefix.forDatabaseType(type) == "", "\(type.rawValue) asked for a prefix") + } + } + + @Test("An unknown type from a future plugin writes a plain literal") + func unknownTypesWritePlainLiterals() { + #expect(SQLStringLiteralPrefix.forDatabaseType(DatabaseType(rawValue: "SomeFutureEngine")) == "") + #expect(SQLStringLiteralPrefix.forDatabaseType(nil) == "") + } +} diff --git a/TableProTests/Core/Services/TableQueryBuilderMSSQLTests.swift b/TableProTests/Core/Services/TableQueryBuilderMSSQLTests.swift index 3bacae282b..780fafb86f 100644 --- a/TableProTests/Core/Services/TableQueryBuilderMSSQLTests.swift +++ b/TableProTests/Core/Services/TableQueryBuilderMSSQLTests.swift @@ -112,4 +112,12 @@ struct TableQueryBuilderMSSQLTests { let query = fallback.buildBaseQuery(tableName: "users") #expect(query == "SELECT * FROM [users] ORDER BY (SELECT NULL) OFFSET 0 ROWS FETCH NEXT 200 ROWS ONLY") } + + @Test("The filtered row count spells a non-ASCII value the way the browse query does") + func filteredCountUsesNationalLiterals() { + let filters = [TestFixtures.makeTableFilter(column: "name", op: .equal, value: "日本語メール")] + let count = builder.buildFilteredCountQuery(tableName: "users", filters: filters, columns: ["name"]) + #expect(count?.contains("[name] = N'日本語メール'") == true) + #expect(count?.contains("= '日本語メール'") == false) + } } diff --git a/TableProTests/Plugins/ClickHouseParameterBindingTests.swift b/TableProTests/Plugins/ClickHouseParameterBindingTests.swift new file mode 100644 index 0000000000..6de5594233 --- /dev/null +++ b/TableProTests/Plugins/ClickHouseParameterBindingTests.swift @@ -0,0 +1,88 @@ +// +// ClickHouseParameterBindingTests.swift +// TableProTests +// + +import Foundation +import TableProPluginKit +import Testing + +@Suite("ClickHouse Parameter Binding") +struct ClickHouseParameterBindingTests { + @Test("Text parameters become named HTTP substitutions") + func textParametersBecomeNamedSubstitutions() { + let bound = ClickHouseParameterBinding.bind( + query: "SELECT * FROM t WHERE a = ? AND b = ?", + parameters: [.text("one"), .text("two")] + ) + #expect(bound.query == "SELECT * FROM t WHERE a = {p1:String} AND b = {p2:String}") + #expect(bound.params["p1"] == "one") + #expect(bound.params["p2"] == "two") + } + + @Test("A null parameter keeps its slot with no value") + func nullParameterKeepsItsSlot() { + let bound = ClickHouseParameterBinding.bind( + query: "SELECT * FROM t WHERE a = ?", + parameters: [.null] + ) + #expect(bound.query == "SELECT * FROM t WHERE a = {p1:String}") + #expect(bound.params["p1"] == .some(nil)) + } + + @Test("A binary parameter is written into the statement as unhex, never as text") + func binaryParameterBecomesUnhex() { + let bound = ClickHouseParameterBinding.bind( + query: "ALTER TABLE t DELETE WHERE raw = ?", + parameters: [.bytes(Data([0xDE, 0xAD, 0xBE, 0xEF]))] + ) + #expect(bound.query == "ALTER TABLE t DELETE WHERE raw = unhex('DEADBEEF')") + #expect(bound.params.isEmpty) + } + + @Test("Named numbering stays contiguous when a binary parameter is inlined") + func namedNumberingSkipsInlinedBinary() { + let bound = ClickHouseParameterBinding.bind( + query: "ALTER TABLE t UPDATE txt = ? WHERE raw = ? AND id = ?", + parameters: [.text("new"), .bytes(Data([0x01, 0x02])), .text("7")] + ) + #expect(bound.query == "ALTER TABLE t UPDATE txt = {p1:String} WHERE raw = unhex('0102') AND id = {p2:String}") + #expect(bound.params["p1"] == "new") + #expect(bound.params["p2"] == "7") + #expect(bound.params.count == 2) + } + + @Test("An empty binary value is still a binary literal") + func emptyBinaryParameterIsALiteral() { + let bound = ClickHouseParameterBinding.bind( + query: "SELECT ?", + parameters: [.bytes(Data())] + ) + #expect(bound.query == "SELECT unhex('')") + } + + @Test("A question mark inside a string literal is not a placeholder") + func questionMarkInsideALiteralIsNotAPlaceholder() { + let bound = ClickHouseParameterBinding.bind( + query: "SELECT * FROM t WHERE a = 'why?' AND b = ?", + parameters: [.text("x")] + ) + #expect(bound.query == "SELECT * FROM t WHERE a = 'why?' AND b = {p1:String}") + #expect(bound.params["p1"] == "x") + } + + @Test("Extra placeholders past the parameter list are left alone") + func extraPlaceholdersAreLeftAlone() { + let bound = ClickHouseParameterBinding.bind( + query: "SELECT ?, ?", + parameters: [.text("only")] + ) + #expect(bound.query == "SELECT {p1:String}, ?") + } + + @Test("The hex a binary parameter produces cannot close the literal it sits in") + func hexLiteralIsAlphanumericOnly() { + let literal = ClickHouseParameterBinding.hexLiteral(Data([0x27, 0x5C, 0x00, 0xFF])) + #expect(literal == "unhex('275C00FF')") + } +} diff --git a/TableProTests/Plugins/ClickHouseResponseClassifierTests.swift b/TableProTests/Plugins/ClickHouseResponseClassifierTests.swift index 0aeabd04cd..5e8f9e25e8 100644 --- a/TableProTests/Plugins/ClickHouseResponseClassifierTests.swift +++ b/TableProTests/Plugins/ClickHouseResponseClassifierTests.swift @@ -99,6 +99,113 @@ struct ClickHouseResponseClassifierTests { #expect(outcome.rows == [[.text("a\tb\nc\\d")]]) } + // MARK: - The Full Escape Table ClickHouse Writes + + @Test("Every escape the server emits is decoded, not left as two characters") + func serverEscapeTableIsDecoded() { + let outcome = classify( + headers: matchingFormatHeaders, + bodyText: "cr\tquote\tbell\tff\tnul\nString\tString\tString\tString\tString\n" + + "a\\rb\ta\\'b\ta\\bb\ta\\fb\ta\\0b\n" + ) + #expect(outcome.rows == [[ + .text("a\rb"), + .text("a'b"), + .text("a\u{8}b"), + .text("a\u{C}b"), + .text("a\u{0}b") + ]]) + } + + @Test("A column type name carrying escaped quotes is reported unescaped") + func columnTypeNameIsUnescaped() { + let outcome = classify( + headers: matchingFormatHeaders, + bodyText: "e\nEnum8(\\'q\\' = 1)\nq\n" + ) + #expect(outcome.columnTypeNames == ["Enum8('q' = 1)"]) + } + + @Test("A column name carrying an escaped tab keeps the column count") + func columnNameWithEscapedTabIsOneColumn() { + let outcome = classify(headers: matchingFormatHeaders, bodyText: "a\\tb\nString\nv\n") + #expect(outcome.columns == ["a\tb"]) + #expect(outcome.rows == [[.text("v")]]) + } + + // MARK: - Binary Values + + @Test("A binary value stays bytes instead of being forced through a text decode") + func binaryValueStaysBytes() { + var body = Data("raw\nString\n".utf8) + body.append(contentsOf: [0xDE, 0xAD, 0xBE, 0xEF, 0x0A]) + let outcome = ClickHouseResponseClassifier.classify(headers: matchingFormatHeaders, body: body) + #expect(outcome.rows == [[.bytes(Data([0xDE, 0xAD, 0xBE, 0xEF]))]]) + } + + @Test("A binary value in one column never mojibakes a text value in another") + func binaryValueLeavesOtherColumnsIntact() { + var body = Data("raw\ttxt\nString\tString\n".utf8) + body.append(contentsOf: [0xDE, 0xAD, 0xBE, 0xEF, 0x09]) + body.append(contentsOf: Data("héllo\n".utf8)) + let outcome = ClickHouseResponseClassifier.classify(headers: matchingFormatHeaders, body: body) + #expect(outcome.rows == [[.bytes(Data([0xDE, 0xAD, 0xBE, 0xEF])), .text("héllo")]]) + } + + @Test("One undecodable value makes the whole column bytes, losslessly") + func oneBinaryValueDemotesItsWholeColumn() { + var body = Data("v\nString\n".utf8) + body.append(contentsOf: Data("héllo\n".utf8)) + body.append(contentsOf: [0xC3, 0x0A]) + let outcome = ClickHouseResponseClassifier.classify(headers: matchingFormatHeaders, body: body) + #expect(outcome.rows == [ + [.bytes(Data("héllo".utf8))], + [.bytes(Data([0xC3]))] + ]) + } + + @Test("A binary value does not demote a text column beside it") + func demotionIsPerColumn() { + var body = Data("a\tb\nString\tString\n".utf8) + body.append(contentsOf: [0xC3, 0x09]) + body.append(contentsOf: Data("keep\n".utf8)) + let outcome = ClickHouseResponseClassifier.classify(headers: matchingFormatHeaders, body: body) + #expect(outcome.rows == [[.bytes(Data([0xC3])), .text("keep")]]) + } + + @Test("A tab or newline inside binary data arrives escaped and never splits a field") + func escapedControlBytesInBinaryDoNotSplitFields() { + var body = Data("v\nString\n".utf8) + body.append(contentsOf: Array("\\t\\n".utf8)) + body.append(contentsOf: [0x0B, 0x41, 0x0A]) + let outcome = ClickHouseResponseClassifier.classify(headers: matchingFormatHeaders, body: body) + #expect(outcome.rows == [[.text("\t\n\u{B}A")]]) + } + + @Test("A body in another format that is not text is kept as bytes") + func nonTextRawBodyIsKeptAsBytes() { + let body = Data([0x00, 0x01, 0xFF, 0xFE]) + let outcome = ClickHouseResponseClassifier.classify(headers: ["X-ClickHouse-Format": "Native"], body: body) + #expect(outcome.rows == [[.bytes(body)]]) + } + + @Test("A body cut by the byte cap mid-character still reads as text") + func cappedBodyCutMidCharacterIsText() { + let cap = 1_048_576 + var body = Data(repeating: UInt8(ascii: "x"), count: cap - 1) + body.append(contentsOf: Data("é".utf8)) + let outcome = ClickHouseResponseClassifier.classify(headers: ["X-ClickHouse-Format": "Pretty"], body: body) + #expect(outcome.isTruncated) + #expect(outcome.rows[0][0].asText?.utf8.count == cap - 1) + } + + @Test("A body the cap did not cut is never trimmed to make it decode") + func uncutBodyIsNotTrimmed() { + let body = Data([0x61, 0x62, 0xC3]) + let outcome = ClickHouseResponseClassifier.classify(headers: ["X-ClickHouse-Format": "Native"], body: body) + #expect(outcome.rows == [[.bytes(body)]]) + } + @Test("Rows beyond the limit are dropped and marked truncated") func rowLimitTruncates() { let outcome = classify( diff --git a/TableProTests/Plugins/ObjectCatalogQueryTests.swift b/TableProTests/Plugins/ObjectCatalogQueryTests.swift index f6ca78bddc..07775e9fc9 100644 --- a/TableProTests/Plugins/ObjectCatalogQueryTests.swift +++ b/TableProTests/Plugins/ObjectCatalogQueryTests.swift @@ -172,7 +172,7 @@ struct MSSQLObjectQueryTests { let all = MSSQLObjectQueries.triggerList(schema: "dbo", table: nil) let one = MSSQLObjectQueries.triggerList(schema: "dbo", table: "Orders") #expect(!all.contains("parent.name =")) - #expect(one.contains("parent.name = 'Orders'")) + #expect(one.contains("parent.name = N'Orders'")) #expect(all.contains("sys.trigger_events")) } @@ -186,8 +186,23 @@ struct MSSQLObjectQueryTests { @Test("A quote in a schema or table is escaped") func literalsAreEscaped() { - #expect(MSSQLObjectQueries.routineList(schema: "it's").contains("'it''s'")) - #expect(MSSQLObjectQueries.triggerList(schema: "dbo", table: "o'brien").contains("'o''brien'")) + #expect(MSSQLObjectQueries.routineList(schema: "it's").contains("N'it''s'")) + #expect(MSSQLObjectQueries.triggerList(schema: "dbo", table: "o'brien").contains("N'o''brien'")) + } + + @Test("A non-ASCII schema, routine or table name is an nvarchar literal") + func catalogNamesAreNationalLiterals() { + #expect(MSSQLObjectQueries.routineList(schema: "販売").contains("s.name = N'販売'")) + let definition = MSSQLObjectQueries.routineDefinition(schema: "販売", name: "集計") + #expect(definition.contains("s.name = N'販売' AND o.name = N'集計'")) + let triggers = MSSQLObjectQueries.triggerList(schema: "販売", table: "注文") + #expect(triggers.contains("s.name = N'販売'")) + #expect(triggers.contains("parent.name = N'注文'")) + } + + @Test("Fixed catalog type codes stay plain literals") + func catalogTypeCodesStayPlain() { + #expect(MSSQLObjectQueries.routineList(schema: "dbo").contains("o.type IN ('P', 'FN', 'IF', 'TF')")) } } diff --git a/docs/databases/clickhouse.mdx b/docs/databases/clickhouse.mdx index f9f39f7613..389e4b1706 100644 --- a/docs/databases/clickhouse.mdx +++ b/docs/databases/clickhouse.mdx @@ -86,6 +86,7 @@ The CA file may be PEM or DER. If **Verify CA** cannot read it, the connection f - No auto-increment, and the primary key and sorting key are fixed at creation. Structure editing covers adding, modifying, and dropping columns and data-skipping indexes; recreate the table for anything else. - A `SET` does not carry to the next statement. Every statement is its own HTTP request with no session id, and the setting is gone by the next one. Put it in a `SETTINGS` clause on the query itself. - A query with its own `FORMAT` clause, such as `SELECT 1 FORMAT JSON`, shows the server's raw output in one column instead of a parsed table. Drop the clause to get a grid. +- A column with even one value that is not valid UTF-8 shows every row as hex, and its cells do not open for inline editing. `String` and `FixedString` hold raw bytes, so a hash or a stray byte is enough. Select `toValidUTF8(column)` to read it as text, with the bad bytes replaced. ## Troubleshooting diff --git a/project.yml b/project.yml index 43256ed70f..8c24b7d442 100644 --- a/project.yml +++ b/project.yml @@ -403,6 +403,7 @@ targets: - Plugins/ClickHouseDriverPlugin/ClickHouseCapabilities.swift - Plugins/ClickHouseDriverPlugin/ClickHouseCredentials.swift - Plugins/ClickHouseDriverPlugin/ClickHouseGeneratedColumnClassification.swift + - Plugins/ClickHouseDriverPlugin/ClickHouseParameterBinding.swift - Plugins/ClickHouseDriverPlugin/ClickHousePlugin.swift - Plugins/ClickHouseDriverPlugin/ClickHousePluginDriver+Http.swift - Plugins/ClickHouseDriverPlugin/ClickHousePluginDriver+Schema.swift From c0fe860c3776b4d7778ebbba6bf06eb2237a69fa Mon Sep 17 00:00:00 2001 From: Ngo Quoc Dat Date: Sat, 12 Sep 2026 07:54:04 +0700 Subject: [PATCH 21/54] refactor(plugin-mysql): identify OceanBase by its version comment and edit keyless tables as MySQL does --- CHANGELOG.md | 2 +- .../MySQLDriverPlugin/MySQLKillTarget.swift | 8 +- .../MySQLPluginDriver+Flavor.swift | 20 +-- .../MySQLPluginDriver+OceanBase.swift | 86 ----------- .../MySQLDriverPlugin/MySQLPluginDriver.swift | 22 +-- .../MySQLDriverPlugin/MySQLServerFlavor.swift | 35 +++-- .../OceanBaseHiddenPrimaryKey.swift | 33 ---- Plugins/MySQLDriverPlugin/OceanBaseSQL.swift | 141 ------------------ ...etadataRegistry+MySQLVariantDefaults.swift | 61 +++++--- .../DockerComposeExtractor.swift | 23 ++- ...ementGeneratorOceanBaseHiddenPKTests.swift | 61 -------- .../Plugins/MySQLVariantSupportTests.swift | 7 +- .../ProjectYamlExtractorTests.swift | 43 ++++++ .../Plugins/MySQLServerFlavorTests.swift | 61 +++++--- .../OceanBaseHiddenPrimaryKeyTests.swift | 53 ------- TableProTests/Plugins/OceanBaseSQLTests.swift | 94 ------------ docs/databases/oceanbase.mdx | 10 +- docs/external-api/ios-shortcuts.mdx | 6 +- docs/ios/index.mdx | 5 +- project.yml | 2 - 20 files changed, 187 insertions(+), 586 deletions(-) delete mode 100644 Plugins/MySQLDriverPlugin/MySQLPluginDriver+OceanBase.swift delete mode 100644 Plugins/MySQLDriverPlugin/OceanBaseHiddenPrimaryKey.swift delete mode 100644 Plugins/MySQLDriverPlugin/OceanBaseSQL.swift delete mode 100644 TableProTests/Core/ChangeTracking/SQLStatementGeneratorOceanBaseHiddenPKTests.swift delete mode 100644 TableProTests/Plugins/OceanBaseHiddenPrimaryKeyTests.swift delete mode 100644 TableProTests/Plugins/OceanBaseSQLTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index a9b014ed23..fa16fa6e37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- OceanBase MySQL-mode connection type, including grid saves on servers opened as MySQL. (#1748) +- OceanBase MySQL-mode connection type. (#1748) - Google Cloud Spanner as a registry plugin over the REST API. (#1226, #2480) - TiDB and Databend connection types on the MySQL driver. (#1066, #2514) - Empty state in the inspector and the assistant for a connection that is not up. diff --git a/Plugins/MySQLDriverPlugin/MySQLKillTarget.swift b/Plugins/MySQLDriverPlugin/MySQLKillTarget.swift index 19b9362d61..2eaa49764e 100644 --- a/Plugins/MySQLDriverPlugin/MySQLKillTarget.swift +++ b/Plugins/MySQLDriverPlugin/MySQLKillTarget.swift @@ -4,7 +4,6 @@ internal enum MySQLKillTarget: Equatable, Sendable { case threadId case tidbConnection(UInt64) case databendSession(String) - case oceanbaseConnection(UInt64) func statement(threadId: UInt) -> String? { switch self { @@ -14,8 +13,6 @@ internal enum MySQLKillTarget: Equatable, Sendable { return "KILL TIDB QUERY \(id)" case .databendSession(let session): return "KILL QUERY '\(mysqlEscapeStringLiteral(session))'" - case .oceanbaseConnection(let id): - return "KILL QUERY \(id)" } } } @@ -29,10 +26,7 @@ internal extension MySQLServerFlavor { case .databend: guard let session = connectionIdentifier, !session.isEmpty else { return .threadId } return .databendSession(session) - case .oceanbase: - guard let id = connectionIdentifier.flatMap(UInt64.init) else { return .threadId } - return .oceanbaseConnection(id) - case .mysql, .mariadb: + case .mysql, .mariadb, .oceanbase: return .threadId } } diff --git a/Plugins/MySQLDriverPlugin/MySQLPluginDriver+Flavor.swift b/Plugins/MySQLDriverPlugin/MySQLPluginDriver+Flavor.swift index 1d177e64ee..aca207660c 100644 --- a/Plugins/MySQLDriverPlugin/MySQLPluginDriver+Flavor.swift +++ b/Plugins/MySQLDriverPlugin/MySQLPluginDriver+Flavor.swift @@ -10,6 +10,7 @@ internal struct MySQLFlavorMismatchError: Error, Equatable { enum Kind: Equatable { case databendNeedsItsOwnType case notDatabend + case notOceanBase } let kind: Kind @@ -22,6 +23,8 @@ extension MySQLFlavorMismatchError: PluginDriverError { return String(localized: "This server is Databend. Edit the connection and choose Databend as its type.") case .notDatabend: return String(localized: "This server did not identify as Databend. Check the host and port of its MySQL handler.") + case .notOceanBase: + return String(localized: "This server did not identify as OceanBase. Check the host and port of its MySQL mode tenant.") } } } @@ -56,18 +59,11 @@ extension MySQLPluginDriver { } if variant == MySQLServerFlavor.oceanbaseVariant { - if MySQLFlavorResolution.needsOceanBaseProbe(banner: banner, variant: variant) { - if let comment = await firstValue(of: MySQLFlavorResolution.oceanbaseProbe, on: connection), - let version = MySQLServerFlavor.oceanbaseVersion(fromBanner: comment) { - return .oceanbase(version: version) - } - return .oceanbase(version: nil) + guard let comment = await firstValue(of: MySQLFlavorResolution.oceanbaseProbe, on: connection), + MySQLServerFlavor.namesOceanBase(comment) else { + throw MySQLFlavorMismatchError(kind: .notOceanBase) } - return bannerFlavor.isOceanBase ? bannerFlavor : .oceanbase(version: nil) - } - - if bannerFlavor.isOceanBase { - return bannerFlavor + return .oceanbase(version: MySQLServerFlavor.oceanbaseVersion(fromVersionComment: comment)) } guard MySQLFlavorResolution.needsTiDBVersionProbe(banner: banner, variant: variant) else { @@ -81,7 +77,7 @@ extension MySQLPluginDriver { } func killTarget(for flavor: MySQLServerFlavor, on connection: MariaDBPluginConnection) async -> MySQLKillTarget { - guard flavor.isTiDB || flavor.isDatabend || flavor.isOceanBase else { return .threadId } + guard flavor.isTiDB || flavor.isDatabend else { return .threadId } let identifier = await firstValue(of: MySQLFlavorResolution.connectionIdentifierProbe, on: connection) return flavor.killTarget(connectionIdentifier: identifier) } diff --git a/Plugins/MySQLDriverPlugin/MySQLPluginDriver+OceanBase.swift b/Plugins/MySQLDriverPlugin/MySQLPluginDriver+OceanBase.swift deleted file mode 100644 index c7db8b9e55..0000000000 --- a/Plugins/MySQLDriverPlugin/MySQLPluginDriver+OceanBase.swift +++ /dev/null @@ -1,86 +0,0 @@ -import Foundation -import TableProPluginKit - -extension MySQLPluginDriver { - func rewriteOceanBaseQueryIfNeeded(_ query: String) async -> String { - guard flavor.isOceanBase else { return query } - if let table = OceanBaseSQL.simpleSelectStarTable(from: query) { - let hidden = await oceanbaseHiddenPrimaryKeyColumns(for: table) - return OceanBaseSQL.projectingHiddenPrimaryKeys( - sql: query, - hiddenColumns: hidden, - quote: quoteIdentifier - ) - } - return OceanBaseSQL.withHiddenColumnVisibilityHint(query) - } - - func attachingOceanBaseHiddenPrimaryKeys( - to columns: [PluginColumnInfo], - table: String - ) async throws -> [PluginColumnInfo] { - let indexes = try await fetchIndexes(table: table, schema: nil) - let primaryColumns = indexes.first(where: \.isPrimary)?.columns ?? [] - var attached = OceanBaseHiddenPrimaryKey.attaching( - to: columns, - primaryIndexColumns: primaryColumns - ) - let visibleNames = Set(columns.map(\.name)) - if attached.count == columns.count, !columns.contains(where: \.isPrimaryKey) { - for name in OceanBaseSQL.documentedHiddenNames where !visibleNames.contains(name) { - if await oceanbaseColumnExists(name, table: table) { - attached.append(OceanBaseHiddenPrimaryKey.synthesizedColumn(named: name)) - } - } - } - let hiddenNames = attached.compactMap { column in - visibleNames.contains(column.name) ? nil : column.name - } - rememberOceanBaseHiddenPrimaryKeys(hiddenNames, for: table) - return attached - } - - func attachingOceanBaseHiddenPrimaryKeys( - to allColumns: [String: [PluginColumnInfo]], - primaryColumnsByTable: [String: [String]] - ) -> [String: [PluginColumnInfo]] { - var merged = allColumns - for (table, columns) in allColumns { - let attached = OceanBaseHiddenPrimaryKey.attaching( - to: columns, - primaryIndexColumns: primaryColumnsByTable[table] ?? [] - ) - merged[table] = attached - let hiddenNames = attached.compactMap { column in - columns.contains(where: { $0.name == column.name }) ? nil : column.name - } - rememberOceanBaseHiddenPrimaryKeys(hiddenNames, for: table) - } - return merged - } - - private func oceanbaseHiddenPrimaryKeyColumns(for table: String) async -> [String] { - if let cached = cachedOceanBaseHiddenPrimaryKeys(for: table) { - return cached - } - do { - _ = try await fetchColumns(table: table, schema: nil) - } catch { - return [] - } - return cachedOceanBaseHiddenPrimaryKeys(for: table) ?? [] - } - - private func oceanbaseColumnExists(_ column: String, table: String) async -> Bool { - do { - _ = try await execute(query: OceanBaseSQL.documentedHiddenColumnProbe( - table: table, - column: column, - quote: quoteIdentifier - )) - return true - } catch { - return false - } - } -} diff --git a/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift b/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift index 91c53e1397..5e07d7746f 100644 --- a/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift +++ b/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift @@ -60,8 +60,6 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { /// connection between `requireConnection` returning and the query reaching the server. private var activeOperations = 0 - private var oceanbaseHiddenPrimaryKeys: [String: [String]] = [:] - internal static let logger = Logger(subsystem: "com.TablePro", category: "MySQLPluginDriver") var currentSchema: String? { nil } @@ -216,7 +214,6 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { guard let parameters else { return try await executeWithReconnect(query: query, isRetry: false, rowCap: cap) } - let query = await rewriteOceanBaseQueryIfNeeded(query) let conn = try await requireConnection() defer { endOperation() } noteActivity(query) @@ -243,7 +240,6 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { } func executeParameterized(query: String, parameters: [PluginCellValue]) async throws -> PluginQueryResult { - let query = await rewriteOceanBaseQueryIfNeeded(query) let conn = try await requireConnection() defer { endOperation() } noteActivity(query) @@ -280,7 +276,6 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { countsAsActivity: Bool = true ) async throws -> PluginQueryResult { let startTime = Date() - let query = await rewriteOceanBaseQueryIfNeeded(query) let conn = try await requireConnection() defer { endOperation() } @@ -508,7 +503,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { let result = try await execute(query: "SHOW FULL COLUMNS FROM \(quoteIdentifier(table))") let generationExpressions = try await fetchGenerationExpressions(table: table) - let columns = result.rows.compactMap { row -> PluginColumnInfo? in + return result.rows.compactMap { row in guard let name = row[safe: 0]?.asText, let dataType = row[safe: 1]?.asText else { return nil } @@ -550,8 +545,6 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { generationKind: mysqlGenerationKind(extra: extra) ) } - guard flavor.isOceanBase else { return columns } - return try await attachingOceanBaseHiddenPrimaryKeys(to: columns, table: table) } private func fetchGenerationExpressions(table: String) async throws -> [String: String] { @@ -688,10 +681,7 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { allColumns[tableName, default: []].append(column) } - guard flavor.isOceanBase else { return allColumns } - let indexes = try await fetchAllIndexes(schema: schema) - let primaryByTable = indexes.mapValues { $0.first(where: \.isPrimary)?.columns ?? [] } - return attachingOceanBaseHiddenPrimaryKeys(to: allColumns, primaryColumnsByTable: primaryByTable) + return allColumns } func fetchIndexes(table: String, schema: String?) async throws -> [PluginIndexInfo] { @@ -1265,14 +1255,6 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { // MARK: - Private Helpers - func cachedOceanBaseHiddenPrimaryKeys(for table: String) -> [String]? { - sessionLock.withLock { oceanbaseHiddenPrimaryKeys[table] } - } - - func rememberOceanBaseHiddenPrimaryKeys(_ columns: [String], for table: String) { - sessionLock.withLock { oceanbaseHiddenPrimaryKeys[table] = columns } - } - private func extractTableName(from query: String) -> String? { guard let regex = Self.tableNameRegex, let match = regex.firstMatch(in: query, range: NSRange(query.startIndex..., in: query)), diff --git a/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift b/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift index cf728545ae..98c5b13f61 100644 --- a/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift +++ b/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift @@ -44,9 +44,6 @@ nonisolated internal enum MySQLServerFlavor: Equatable, Sendable { if let version = tidbVersion(fromBanner: banner) { return .tidb(version: version) } - if banner.range(of: "oceanbase", options: .caseInsensitive) != nil { - return .oceanbase(version: oceanbaseVersion(fromBanner: banner)) - } if isDatabendBanner(banner) { return .databend } @@ -68,15 +65,16 @@ nonisolated internal enum MySQLServerFlavor: Equatable, Sendable { banner.range(of: #"^\d+\.\d+\.\d+-v\d+\.\d+\.\d+-"#, options: .regularExpression) != nil } - static func oceanbaseVersion(fromBanner banner: String) -> MySQLEngineVersion? { - guard banner.range(of: "oceanbase", options: .caseInsensitive) != nil else { return nil } - if let marker = banner.range(of: "OceanBase_CE-v", options: .caseInsensitive) - ?? banner.range(of: "OceanBase-v", options: .caseInsensitive) { - return MySQLEngineVersion(parsing: banner[marker.upperBound...]) - } - guard let name = banner.range(of: "OceanBase", options: .caseInsensitive) else { return nil } - var rest = banner[name.upperBound...] - rest = rest.drop(while: { $0.isLetter || $0 == "_" || $0 == "-" || $0.isWhitespace }) + /// The MySQL handshake banner is OceanBase's `_display_mysql_version`, which is `5.7.25` on a + /// direct connection and `5.6.25` through OBProxy: it never names the engine. `@@version_comment` + /// is what does, as `OceanBase_CE 4.4.2.1 (r...)` or `OceanBase 3.1.3 (r...)`. + static func namesOceanBase(_ versionComment: String) -> Bool { + versionComment.range(of: "oceanbase", options: .caseInsensitive) != nil + } + + static func oceanbaseVersion(fromVersionComment comment: String) -> MySQLEngineVersion? { + guard let name = comment.range(of: "OceanBase", options: .caseInsensitive) else { return nil } + let rest = comment[name.upperBound...].drop { $0.isLetter || $0 == "_" || $0 == "-" || $0.isWhitespace } return MySQLEngineVersion(parsing: rest) } @@ -137,12 +135,21 @@ nonisolated internal enum MySQLServerFlavor: Equatable, Sendable { return mode == .readWrite ? "START TRANSACTION READ WRITE" : "START TRANSACTION" } + /// OceanBase enforces `ob_query_timeout` of its own, 10 seconds by default, and + /// `max_execution_time` only outranks it while it is above zero. Zero is the setting's "no + /// limit", which an export relies on, so it has to lift OceanBase's own limit as well. The + /// server clamps the value it accepts there and warns; this is what it clamps to. + static let oceanbaseUnlimitedQueryTimeoutMicroseconds = 3_216_672_000_000_000 + func queryTimeoutStatement(seconds: Int) -> String { switch self { case .mariadb: return "SET SESSION max_statement_time = \(seconds)" case .databend: return "SET max_execute_time_in_seconds = \(seconds)" + case .oceanbase where seconds <= 0: + return "SET SESSION max_execution_time = 0, ob_query_timeout = " + + "\(Self.oceanbaseUnlimitedQueryTimeoutMicroseconds)" case .mysql, .tidb, .oceanbase: return "SET SESSION max_execution_time = \(seconds * 1_000)" } @@ -177,10 +184,6 @@ nonisolated internal enum MySQLFlavorResolution { variant == MySQLServerFlavor.databendVariant && !MySQLServerFlavor.fromBanner(banner).isDatabend } - static func needsOceanBaseProbe(banner: String?, variant: String?) -> Bool { - variant == MySQLServerFlavor.oceanbaseVariant && !MySQLServerFlavor.fromBanner(banner).isOceanBase - } - static let tidbVersionProbe = "SELECT tidb_version()" static let databendProbe = "SELECT value FROM system.settings WHERE name = 'max_result_rows'" static let oceanbaseProbe = "SELECT @@version_comment" diff --git a/Plugins/MySQLDriverPlugin/OceanBaseHiddenPrimaryKey.swift b/Plugins/MySQLDriverPlugin/OceanBaseHiddenPrimaryKey.swift deleted file mode 100644 index 49b3d6ce72..0000000000 --- a/Plugins/MySQLDriverPlugin/OceanBaseHiddenPrimaryKey.swift +++ /dev/null @@ -1,33 +0,0 @@ -import Foundation -import TableProPluginKit - -internal enum OceanBaseHiddenPrimaryKey { - static func synthesizedColumn(named name: String) -> PluginColumnInfo { - PluginColumnInfo( - name: name, - dataType: "BIGINT", - isNullable: false, - isPrimaryKey: true, - defaultValue: nil, - extra: "auto_increment", - identityKind: .always, - isGenerated: false, - allowedValues: nil, - generationExpression: nil, - generationKind: nil - ) - } - - static func attaching( - to columns: [PluginColumnInfo], - primaryIndexColumns: [String] - ) -> [PluginColumnInfo] { - let visible = Set(columns.map(\.name)) - let hidden = OceanBaseSQL.hiddenPrimaryKeyColumns( - primaryIndexColumns: primaryIndexColumns, - visibleColumnNames: visible - ) - guard !hidden.isEmpty else { return columns } - return columns + hidden.map(synthesizedColumn(named:)) - } -} diff --git a/Plugins/MySQLDriverPlugin/OceanBaseSQL.swift b/Plugins/MySQLDriverPlugin/OceanBaseSQL.swift deleted file mode 100644 index 321dd6531b..0000000000 --- a/Plugins/MySQLDriverPlugin/OceanBaseSQL.swift +++ /dev/null @@ -1,141 +0,0 @@ -import Foundation - -internal enum OceanBaseSQL { - static let visibilityHint = "/*+ opt_param('hidden_column_visible','true') */" - static let incrementColumn = "__pk_increment" - static let clusterColumn = "__pk_cluster_column" - static let documentedHiddenNames = [incrementColumn, clusterColumn] - - private static let hintedVerbs: Set = [ - "SELECT", "UPDATE", "DELETE", "INSERT", "REPLACE" - ] - - static func isDocumentedHiddenName(_ name: String) -> Bool { - documentedHiddenNames.contains(name) - } - - static func hiddenPrimaryKeyColumns( - primaryIndexColumns: [String], - visibleColumnNames: Set - ) -> [String] { - var seen = Set() - var hidden: [String] = [] - for column in primaryIndexColumns where !visibleColumnNames.contains(column) { - guard seen.insert(column).inserted else { continue } - hidden.append(column) - } - return hidden - } - - static func withHiddenColumnVisibilityHint(_ sql: String) -> String { - let trimmed = sql.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return sql } - if trimmed.contains("hidden_column_visible") { return sql } - guard let verbEnd = firstKeywordEnd(in: trimmed) else { return sql } - let verb = String(trimmed[trimmed.startIndex.. String - ) -> String { - let hinted = withHiddenColumnVisibilityHint(sql) - guard !hiddenColumns.isEmpty else { return hinted } - guard simpleSelectStarTable(from: hinted) != nil else { return hinted } - let extras = hiddenColumns.map(quote).joined(separator: ", ") - guard let regex = try? NSRegularExpression( - pattern: #"(?is)^(SELECT(?:\s+/\*\+[^*]*\*/)?)\s+\*\s+FROM\b"# - ) else { - return hinted - } - let nsSQL = hinted as NSString - guard let match = regex.firstMatch(in: hinted, range: NSRange(location: 0, length: nsSQL.length)), - match.numberOfRanges > 1 - else { - return hinted - } - let prefix = nsSQL.substring(with: match.range(at: 1)) - let afterFrom = nsSQL.substring(from: match.range.upperBound) - return "\(prefix) *, \(extras) FROM\(afterFrom)" - } - - static func simpleSelectStarTable(from sql: String) -> String? { - let trimmed = sql.trimmingCharacters(in: .whitespacesAndNewlines) - guard let regex = try? NSRegularExpression( - pattern: #"(?is)^SELECT(?:\s+/\*\+[^*]*\*/)?\s+\*\s+FROM\s+"# - ) else { - return nil - } - let nsSQL = trimmed as NSString - guard let match = regex.firstMatch(in: trimmed, range: NSRange(location: 0, length: nsSQL.length)) else { - return nil - } - var rest = nsSQL.substring(from: match.range.upperBound) - .trimmingCharacters(in: .whitespacesAndNewlines) - guard !rest.hasPrefix("(") else { return nil } - return trailingQualifiedIdentifier(from: &rest) - } - - static func documentedHiddenColumnProbe(table: String, column: String, quote: (String) -> String) -> String { - "SELECT \(visibilityHint) \(quote(column)) FROM \(quote(table)) LIMIT 0" - } - - private static func firstKeywordEnd(in sql: String) -> String.Index? { - var index = sql.startIndex - while index < sql.endIndex, sql[index].isWhitespace { - sql.formIndex(after: &index) - } - guard index < sql.endIndex, sql[index].isLetter else { return nil } - while index < sql.endIndex, sql[index].isLetter { - sql.formIndex(after: &index) - } - return index - } - - private static func trailingQualifiedIdentifier(from rest: inout String) -> String? { - var parts: [String] = [] - while let ident = parseLeadingIdentifier(from: &rest) { - parts.append(ident) - rest = rest.trimmingCharacters(in: .whitespacesAndNewlines) - guard rest.hasPrefix(".") else { break } - rest.removeFirst() - rest = rest.trimmingCharacters(in: .whitespacesAndNewlines) - } - return parts.last - } - - private static func parseLeadingIdentifier(from rest: inout String) -> String? { - rest = rest.trimmingCharacters(in: .whitespacesAndNewlines) - guard let first = rest.first else { return nil } - if first == "`" { - rest.removeFirst() - guard let end = rest.firstIndex(of: "`") else { return nil } - let value = String(rest[.. rest.startIndex else { return nil } - let value = String(rest[.. [String: [String]] { - mysqlColumnTypes.filter { $0.key != "Spatial" } - } - - static func oceanbaseColumnTypes(from mysqlColumnTypes: [String: [String]]) -> [String: [String]] { + static func mysqlColumnTypesWithoutSpatial(from mysqlColumnTypes: [String: [String]]) -> [String: [String]] { mysqlColumnTypes.filter { $0.key != "Spatial" } } @@ -44,7 +44,18 @@ extension PluginMetadataRegistry { idleReleaseField: ConnectionField ) -> [(typeId: String, snapshot: PluginMetadataSnapshot)] { [ - ("TiDB", PluginMetadataSnapshot( + tidbVariant(dialect: dialect, mysqlColumnTypes: mysqlColumnTypes, idleReleaseField: idleReleaseField), + databendVariant(dialect: dialect, idleReleaseField: idleReleaseField), + oceanbaseVariant(dialect: dialect, mysqlColumnTypes: mysqlColumnTypes, idleReleaseField: idleReleaseField), + ] + } + + private static func tidbVariant( + dialect: SQLDialectDescriptor, + mysqlColumnTypes: [String: [String]], + idleReleaseField: ConnectionField + ) -> (typeId: String, snapshot: PluginMetadataSnapshot) { + ("TiDB", PluginMetadataSnapshot( displayName: "TiDB", iconName: "tidb-icon", defaultPort: 4_000, requiresAuthentication: true, supportsForeignKeys: true, supportsSchemaEditing: true, isDownloadable: false, primaryUrlScheme: "tidb", parameterStyle: .questionMark, @@ -98,15 +109,21 @@ extension PluginMetadataRegistry { editor: PluginMetadataSnapshot.EditorConfig( sqlDialect: dialect, statementCompletions: [], - columnTypesByCategory: tidbColumnTypes(from: mysqlColumnTypes) + columnTypesByCategory: mysqlColumnTypesWithoutSpatial(from: mysqlColumnTypes) ), connection: PluginMetadataSnapshot.ConnectionConfig( additionalConnectionFields: [idleReleaseField], category: .relational, tagline: String(localized: "Distributed SQL, MySQL-compatible") - ) - )), - ("Databend", PluginMetadataSnapshot( + ) + )) + } + + private static func databendVariant( + dialect: SQLDialectDescriptor, + idleReleaseField: ConnectionField + ) -> (typeId: String, snapshot: PluginMetadataSnapshot) { + ("Databend", PluginMetadataSnapshot( displayName: "Databend", iconName: "databend-icon", defaultPort: 3_307, requiresAuthentication: true, supportsForeignKeys: false, supportsSchemaEditing: true, isDownloadable: false, primaryUrlScheme: "", parameterStyle: .questionMark, @@ -166,15 +183,20 @@ extension PluginMetadataRegistry { additionalConnectionFields: [idleReleaseField], category: .analytical, tagline: String(localized: "Cloud data warehouse, built in Rust") - ) - )), - ("OceanBase", PluginMetadataSnapshot( + ) + )) + } + + private static func oceanbaseVariant( + dialect: SQLDialectDescriptor, + mysqlColumnTypes: [String: [String]], + idleReleaseField: ConnectionField + ) -> (typeId: String, snapshot: PluginMetadataSnapshot) { + ("OceanBase", PluginMetadataSnapshot( displayName: "OceanBase", iconName: "oceanbase-icon", defaultPort: 2_881, requiresAuthentication: true, supportsForeignKeys: true, supportsSchemaEditing: true, isDownloadable: false, primaryUrlScheme: "oceanbase", parameterStyle: .questionMark, - navigationModel: .standard, explainVariants: [ - ExplainVariant(id: "explain", label: "EXPLAIN", sqlPrefix: "EXPLAIN", format: .plainText) - ], pathFieldRole: .database, + navigationModel: .standard, explainVariants: oceanbaseExplainVariants, pathFieldRole: .database, supportsHealthMonitor: true, urlSchemes: ["oceanbase"], postConnectActions: [.selectDatabaseFromLastSession], brandColorHex: "#006AFF", queryLanguageName: "SQL", editorLanguage: .sql, @@ -211,7 +233,7 @@ extension PluginMetadataRegistry { tableEntityName: "Tables", containerEntityName: "Database", defaultPrimaryKeyColumn: nil, - immutableColumns: ["__pk_increment", "__pk_cluster_column"], + immutableColumns: [], systemDatabaseNames: ["information_schema", "mysql", "oceanbase"], systemSchemaNames: [], fileExtensions: [], @@ -224,14 +246,13 @@ extension PluginMetadataRegistry { editor: PluginMetadataSnapshot.EditorConfig( sqlDialect: dialect, statementCompletions: [], - columnTypesByCategory: oceanbaseColumnTypes(from: mysqlColumnTypes) + columnTypesByCategory: mysqlColumnTypesWithoutSpatial(from: mysqlColumnTypes) ), connection: PluginMetadataSnapshot.ConnectionConfig( additionalConnectionFields: [idleReleaseField], category: .relational, tagline: String(localized: "Distributed HTAP, MySQL-compatible") - ) + ) )) - ] } } diff --git a/TablePro/Core/Services/ProjectImport/DockerComposeExtractor.swift b/TablePro/Core/Services/ProjectImport/DockerComposeExtractor.swift index faccd4b180..6e7ab04f7b 100644 --- a/TablePro/Core/Services/ProjectImport/DockerComposeExtractor.swift +++ b/TablePro/Core/Services/ProjectImport/DockerComposeExtractor.swift @@ -70,6 +70,16 @@ enum DockerComposeExtractor { "datafuselabs/databend-query", "databendlabs/databend-query", ] + /// The `oceanbase` organization also publishes OCP, obagent, the config server and miniob, none of + /// which speak the MySQL protocol, so the repository is matched rather than the whole image name. + /// OBProxy serves SQL on 2883, the observer on 2881. + private static let oceanbaseRepositories: [String: Int] = [ + "oceanbase/oceanbase-ce": 2_881, + "oceanbase/oceanbase": 2_881, + "oceanbase/obproxy-ce": 2_883, + "oceanbase/obproxy": 2_883, + ] + static func databaseKind(for image: String) -> ServiceDatabase? { let name = image.lowercased() let repositoryPath = repositoryComponents(of: name) @@ -79,8 +89,8 @@ enum DockerComposeExtractor { if databendRepositories.contains(repositoryPath.suffix(2).joined(separator: "/")) { return ServiceDatabase(type: .databend, defaultPort: 3_307) } - if name.contains("oceanbase") { - return ServiceDatabase(type: .oceanbase, defaultPort: 2_881) + if let port = oceanbaseRepositories[repositoryPath.suffix(2).joined(separator: "/")] { + return ServiceDatabase(type: .oceanbase, defaultPort: port) } if name.contains("postgres"), !name.contains("postgrest") { return ServiceDatabase(type: .postgresql, defaultPort: 5_432) @@ -183,9 +193,12 @@ enum DockerComposeExtractor { fields.password = variables["QUERY_DEFAULT_PASSWORD"] ?? "" fields.database = "default" case .oceanbase: - fields.username = "root@sys" - fields.password = "" - fields.database = "" + let tenant = variables["OB_TENANT_NAME"] ?? (variables["OB_TENANT_PASSWORD"] != nil ? "test" : "sys") + fields.username = "root@\(tenant)" + fields.password = tenant == "sys" + ? variables["OB_SYS_PASSWORD"] ?? "" + : variables["OB_TENANT_PASSWORD"] ?? "" + fields.database = variables["OB_DATABASE"] ?? "" case .mariadb, .mysql: let prefix = variables["MARIADB_PASSWORD"] != nil || variables["MARIADB_DATABASE"] != nil ? "MARIADB" diff --git a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorOceanBaseHiddenPKTests.swift b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorOceanBaseHiddenPKTests.swift deleted file mode 100644 index 2f11a7ee96..0000000000 --- a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorOceanBaseHiddenPKTests.swift +++ /dev/null @@ -1,61 +0,0 @@ -import TableProPluginKit -@testable import TablePro -import Testing - -@Suite("SQL Statement Generator OceanBase hidden PK") -struct SQLStatementGeneratorOceanBaseHiddenPKTests { - private func makeGenerator( - columns: [String], - primaryKeyColumns: [String], - generatedColumns: Set = [] - ) throws -> SQLStatementGenerator { - try SQLStatementGenerator( - tableName: "orders", - columns: columns, - primaryKeyColumns: primaryKeyColumns, - databaseType: .oceanbase, - generatedColumns: generatedColumns, - dialect: nil - ) - } - - @Test("An UPDATE is skipped when the hidden PK is named but not in the result columns") - func missingHiddenKeySkipsUpdate() throws { - let generator = try makeGenerator( - columns: ["name", "amount"], - primaryKeyColumns: ["__pk_increment"] - ) - let change = RowChange( - rowIndex: 0, - type: .update, - cellChanges: [ - CellChange(columnIndex: 0, columnName: "name", oldValue: "old", newValue: "new") - ], - originalRow: ["old", "1"].map(PluginCellValue.fromOptional) - ) - #expect(generator.generateUpdateSQL(for: change) == nil) - } - - @Test("An UPDATE matches on the hidden PK once it is a result column") - func hiddenKeyAnchorsUpdate() throws { - let generator = try makeGenerator( - columns: ["name", "amount", "__pk_increment"], - primaryKeyColumns: ["__pk_increment"], - generatedColumns: ["__pk_increment"] - ) - let change = RowChange( - rowIndex: 0, - type: .update, - cellChanges: [ - CellChange(columnIndex: 0, columnName: "name", oldValue: "old", newValue: "new") - ], - originalRow: ["old", "1", "42"].map(PluginCellValue.fromOptional) - ) - let statement = try #require(generator.generateUpdateSQL(for: change)) - #expect(statement.sql == "UPDATE `orders` SET `name` = ? WHERE `__pk_increment` = ?") - #expect(statement.parameters.count == 2) - #expect(statement.parameters[0] as? String == "new") - #expect(statement.parameters[1] as? String == "42") - #expect(!statement.sql.contains("SET `__pk_increment`")) - } -} diff --git a/TableProTests/Core/Plugins/MySQLVariantSupportTests.swift b/TableProTests/Core/Plugins/MySQLVariantSupportTests.swift index cf4228ea12..202b3bbb14 100644 --- a/TableProTests/Core/Plugins/MySQLVariantSupportTests.swift +++ b/TableProTests/Core/Plugins/MySQLVariantSupportTests.swift @@ -143,9 +143,10 @@ struct MySQLVariantSupportTests { #expect(ColumnDefaultVocabulary.options(for: .tidb) == ColumnDefaultVocabulary.options(for: .mysql)) } - @Test("OceanBase treats the hidden primary key columns as immutable") - func oceanbaseImmutableHiddenKeys() { - #expect(PluginManager.shared.immutableColumns(for: .oceanbase) == ["__pk_increment", "__pk_cluster_column"]) + @Test("No MySQL variant marks a column immutable") + func variantsHaveNoImmutableColumns() { + #expect(PluginManager.shared.immutableColumns(for: .oceanbase).isEmpty) + #expect(PluginManager.shared.immutableColumns(for: .tidb).isEmpty) #expect(PluginManager.shared.immutableColumns(for: .mysql).isEmpty) } diff --git a/TableProTests/Core/Services/ProjectImport/ProjectYamlExtractorTests.swift b/TableProTests/Core/Services/ProjectImport/ProjectYamlExtractorTests.swift index c3bbc97428..774ba1e4a5 100644 --- a/TableProTests/Core/Services/ProjectImport/ProjectYamlExtractorTests.swift +++ b/TableProTests/Core/Services/ProjectImport/ProjectYamlExtractorTests.swift @@ -278,6 +278,49 @@ struct DockerComposeExtractorTests { #expect(oceanbase?.parsedURL.database.isEmpty == true) } + @Test("An OceanBase tenant password names that tenant, and OBProxy is imported on its own port") + func testOceanBaseTenantAndProxy() { + let candidates = extract(""" + services: + ob: + image: oceanbase/oceanbase-ce:4.4.2 + environment: + OB_TENANT_NAME: app + OB_TENANT_PASSWORD: tenantpw + OB_SYS_PASSWORD: syspw + OB_DATABASE: shop + ports: + - "2881:2881" + proxy: + image: oceanbase/obproxy-ce:latest + ports: + - "2883:2883" + """) + let observer = candidates.first { $0.sourceKey == "services.ob" } + #expect(observer?.parsedURL.username == "root@app") + #expect(observer?.parsedURL.password == "tenantpw") + #expect(observer?.parsedURL.database == "shop") + let proxy = candidates.first { $0.sourceKey == "services.proxy" } + #expect(proxy?.parsedURL.type == .oceanbase) + #expect(proxy?.parsedURL.port == 2_883) + } + + @Test("OceanBase images that do not serve SQL are not imported") + func testOceanBaseNonDatabaseImages() { + let candidates = extract(""" + services: + ocp: + image: oceanbase/ocp-ce:latest + ports: + - "8080:8080" + agent: + image: oceanbase/obagent:latest + miniob: + image: oceanbase/miniob:latest + """) + #expect(candidates.isEmpty) + } + @Test("Interpolation uses the adjacent dotenv file") func testInterpolationFromDotenv() { let contents = """ diff --git a/TableProTests/Plugins/MySQLServerFlavorTests.swift b/TableProTests/Plugins/MySQLServerFlavorTests.swift index 7781acfebf..c2c27cd4c1 100644 --- a/TableProTests/Plugins/MySQLServerFlavorTests.swift +++ b/TableProTests/Plugins/MySQLServerFlavorTests.swift @@ -17,9 +17,6 @@ struct MySQLServerFlavorTests { ("11.4.2-MariaDB-log", .mariadb), ("8.0.11-TiDB-v7.5.1", .tidb(version: MySQLEngineVersion(major: 7, minor: 5, patch: 1))), ("8.0.11-TiDB-v8.5.1", .tidb(version: MySQLEngineVersion(major: 8, minor: 5, patch: 1))), - ("5.7.25-OceanBase-v4.2.1", .oceanbase(version: MySQLEngineVersion(major: 4, minor: 2, patch: 1))), - ("5.7.25 OceanBase 3.1.3", .oceanbase(version: MySQLEngineVersion(major: 3, minor: 1, patch: 3))), - ("5.7.25-OceanBase_CE-v4.3.5", .oceanbase(version: MySQLEngineVersion(major: 4, minor: 3, patch: 5))), (databendBanner, .databend) ]) func bannerNamesTheEngine(banner: String, expected: MySQLServerFlavor) { @@ -38,24 +35,39 @@ struct MySQLServerFlavorTests { #expect(MySQLServerFlavor.tidbVersion(fromReleaseInfo: "8.0.36") == nil) } - @Test("A TiDB, Databend or OceanBase connection whose banner does not say so is confirmed with a query") + @Test("A TiDB or Databend connection whose banner does not say so is confirmed with a query") func probesOnlyWhenTheBannerIsSilent() { #expect(MySQLFlavorResolution.needsTiDBVersionProbe(banner: "8.0.35", variant: "TiDB")) #expect(!MySQLFlavorResolution.needsTiDBVersionProbe(banner: "8.0.11-TiDB-v7.5.1", variant: "TiDB")) #expect(!MySQLFlavorResolution.needsTiDBVersionProbe(banner: "8.0.35", variant: nil)) #expect(MySQLFlavorResolution.needsDatabendProbe(banner: "8.0.36", variant: "Databend")) #expect(!MySQLFlavorResolution.needsDatabendProbe(banner: Self.databendBanner, variant: "Databend")) - #expect(MySQLFlavorResolution.needsOceanBaseProbe(banner: "5.7.25", variant: "OceanBase")) - #expect(!MySQLFlavorResolution.needsOceanBaseProbe(banner: "5.7.25-OceanBase-v4.2.1", variant: "OceanBase")) - #expect(!MySQLFlavorResolution.needsOceanBaseProbe(banner: "5.7.25-OceanBase-v4.2.1", variant: nil)) } - @Test("A MySQL connection whose banner names OceanBase is OceanBase") - func mysqlOpenedOceanBaseIsOceanBase() { - let flavor = MySQLServerFlavor.fromBanner("5.7.25-OceanBase-v4.2.1") - #expect(flavor.isOceanBase) - #expect(flavor.oceanbaseVersion == MySQLEngineVersion(major: 4, minor: 2, patch: 1)) - #expect(!MySQLServerFlavor.fromBanner("5.7.25").isOceanBase) + @Test("OceanBase's handshake banner is a plain MySQL version, so no banner reads as OceanBase") + func oceanbaseBannerIsPlainMySQL() { + #expect(MySQLServerFlavor.fromBanner("5.7.25") == .mysql) + #expect(MySQLServerFlavor.fromBanner("5.6.25") == .mysql) + } + + @Test("The version comment names OceanBase and carries its version", arguments: [ + ("OceanBase_CE 4.4.2.1 (r101000022026050611-8cf64ed5) (Built May 6 2026 12:29:53)", + MySQLEngineVersion(major: 4, minor: 4, patch: 2)), + ("OceanBase 4.2.1.2 (r102000042023121309-6b1e1a4b)", MySQLEngineVersion(major: 4, minor: 2, patch: 1)), + ("OceanBase 3.1.3 (r10200392021123009-9a4f2a41)", MySQLEngineVersion(major: 3, minor: 1, patch: 3)), + ("OceanBase_CE-v4.3.5", MySQLEngineVersion(major: 4, minor: 3, patch: 5)) + ]) + func oceanbaseVersionComment(comment: String, expected: MySQLEngineVersion) { + #expect(MySQLServerFlavor.namesOceanBase(comment)) + #expect(MySQLServerFlavor.oceanbaseVersion(fromVersionComment: comment) == expected) + } + + @Test("A version comment from another engine does not name OceanBase") + func otherEnginesDoNotNameOceanBase() { + #expect(!MySQLServerFlavor.namesOceanBase("MySQL Community Server - GPL")) + #expect(!MySQLServerFlavor.namesOceanBase("mariadb.org binary distribution")) + #expect(!MySQLServerFlavor.namesOceanBase("")) + #expect(MySQLServerFlavor.oceanbaseVersion(fromVersionComment: "MySQL Community Server - GPL") == nil) } @Test("System databases are the exact spellings each engine reports") @@ -127,6 +139,7 @@ struct MySQLServerFlavorTests { (.mysql, 30, "SET SESSION max_execution_time = 30000"), (.tidb(version: nil), 30, "SET SESSION max_execution_time = 30000"), (.oceanbase(version: nil), 30, "SET SESSION max_execution_time = 30000"), + (.oceanbase(version: nil), 0, "SET SESSION max_execution_time = 0, ob_query_timeout = 3216672000000000"), (.databend, 30, "SET max_execute_time_in_seconds = 30") ]) func queryTimeout(flavor: MySQLServerFlavor, seconds: Int, expected: String) { @@ -143,14 +156,11 @@ struct MySQLServerFlavorTests { #expect(!MySQLServerFlavor.databend.isInterruptedByKill(errno: 1_105, message: "SyntaxException. Code: 1005")) } - @Test("TiDB kills by its 64-bit connection id, OceanBase by CONNECTION_ID, Databend by its session id") + @Test("TiDB kills by its 64-bit connection id and Databend by its session id") func killStatements() { let tidb = MySQLServerFlavor.tidb(version: nil).killTarget(connectionIdentifier: "2199023255571") #expect(tidb.statement(threadId: 19) == "KILL TIDB QUERY 2199023255571") - let oceanbase = MySQLServerFlavor.oceanbase(version: nil).killTarget(connectionIdentifier: "3221490143") - #expect(oceanbase.statement(threadId: 19) == "KILL QUERY 3221490143") - let databend = MySQLServerFlavor.databend.killTarget(connectionIdentifier: "1f7e5199-119f-484a-aaff-e8d5143a7979") #expect(databend.statement(threadId: 89) == "KILL QUERY '1f7e5199-119f-484a-aaff-e8d5143a7979'") @@ -159,11 +169,18 @@ struct MySQLServerFlavorTests { #expect(mysql.statement(threadId: 0) == nil) } + @Test("OceanBase kills by the handshake thread id, which is its own session id") + func oceanbaseKillsByThreadId() { + let flavor = MySQLServerFlavor.oceanbase(version: nil) + #expect(flavor.killTarget(connectionIdentifier: "3221490143") == .threadId) + #expect(flavor.killTarget(connectionIdentifier: nil) == .threadId) + #expect(flavor.killTarget(connectionIdentifier: nil).statement(threadId: 3_221_490_143) == "KILL QUERY 3221490143") + } + @Test("A connection id that cannot be read falls back to the handshake thread id") func killFallsBackToThreadId() { #expect(MySQLServerFlavor.tidb(version: nil).killTarget(connectionIdentifier: nil) == .threadId) #expect(MySQLServerFlavor.tidb(version: nil).killTarget(connectionIdentifier: "not-a-number") == .threadId) - #expect(MySQLServerFlavor.oceanbase(version: nil).killTarget(connectionIdentifier: nil) == .threadId) #expect(MySQLServerFlavor.databend.killTarget(connectionIdentifier: "") == .threadId) } @@ -185,11 +202,11 @@ struct MySQLServerFlavorTests { #expect(!MySQLServerVersion.hasGenerationExpression(banner: Self.databendBanner, flavor: .databend)) #expect(MySQLServerVersion.hasGenerationExpression(banner: "8.0.11-TiDB-v7.5.1", flavor: .tidb(version: nil))) #expect(MySQLServerVersion.hasGenerationExpression( - banner: "5.7.25-OceanBase-v4.2.1", + banner: "5.7.25", flavor: .oceanbase(version: MySQLEngineVersion(major: 4, minor: 2, patch: 1)) )) #expect(!MySQLServerVersion.hasGenerationExpression( - banner: "5.7.25 OceanBase 3.1.3", + banner: "5.7.25", flavor: .oceanbase(version: MySQLEngineVersion(major: 3, minor: 1, patch: 3)) )) #expect(!MySQLServerVersion.hasGenerationExpression( @@ -197,11 +214,11 @@ struct MySQLServerFlavorTests { flavor: .oceanbase(version: nil) )) #expect(MySQLServerVersion.hasCheckConstraints( - banner: "5.7.25-OceanBase-v4.2.1", + banner: "5.7.25", flavor: .oceanbase(version: MySQLEngineVersion(major: 4, minor: 0, patch: 0)) )) #expect(!MySQLServerVersion.hasCheckConstraints( - banner: "5.7.25 OceanBase 3.1.3", + banner: "5.7.25", flavor: .oceanbase(version: MySQLEngineVersion(major: 3, minor: 1, patch: 3)) )) } diff --git a/TableProTests/Plugins/OceanBaseHiddenPrimaryKeyTests.swift b/TableProTests/Plugins/OceanBaseHiddenPrimaryKeyTests.swift deleted file mode 100644 index 5a2c2fb78b..0000000000 --- a/TableProTests/Plugins/OceanBaseHiddenPrimaryKeyTests.swift +++ /dev/null @@ -1,53 +0,0 @@ -import Foundation -import TableProPluginKit -import Testing - -@Suite("OceanBase hidden primary key") -struct OceanBaseHiddenPrimaryKeyTests { - @Test("A SHOW INDEX PRIMARY column missing from SHOW COLUMNS is attached as BIGINT PK") - func attachesHiddenPrimary() { - let visible = [ - PluginColumnInfo(name: "name", dataType: "VARCHAR(32)", isNullable: true, isPrimaryKey: false) - ] - let attached = OceanBaseHiddenPrimaryKey.attaching( - to: visible, - primaryIndexColumns: ["__pk_increment"] - ) - #expect(attached.map(\.name) == ["name", "__pk_increment"]) - let hidden = attached[1] - #expect(hidden.isPrimaryKey) - #expect(hidden.dataType == "BIGINT") - #expect(hidden.identityKind == .always) - #expect(!hidden.isNullable) - } - - @Test("A visible primary key is left alone") - func visiblePrimaryIsUnchanged() { - let visible = [ - PluginColumnInfo(name: "id", dataType: "INT", isNullable: false, isPrimaryKey: true), - PluginColumnInfo(name: "name", dataType: "VARCHAR(32)", isNullable: true, isPrimaryKey: false) - ] - let attached = OceanBaseHiddenPrimaryKey.attaching( - to: visible, - primaryIndexColumns: ["id"] - ) - #expect(attached.map(\.name) == ["id", "name"]) - } - - @Test("An already-visible hidden name is not duplicated") - func doesNotDuplicate() { - let visible = [ - PluginColumnInfo( - name: "__pk_increment", - dataType: "BIGINT", - isNullable: false, - isPrimaryKey: true - ) - ] - let attached = OceanBaseHiddenPrimaryKey.attaching( - to: visible, - primaryIndexColumns: ["__pk_increment"] - ) - #expect(attached.count == 1) - } -} diff --git a/TableProTests/Plugins/OceanBaseSQLTests.swift b/TableProTests/Plugins/OceanBaseSQLTests.swift deleted file mode 100644 index ce91f19c16..0000000000 --- a/TableProTests/Plugins/OceanBaseSQLTests.swift +++ /dev/null @@ -1,94 +0,0 @@ -import Foundation -import Testing - -@Suite("OceanBase SQL rewrite") -struct OceanBaseSQLTests { - private func quote(_ name: String) -> String { - "`\(name.replacingOccurrences(of: "`", with: "``"))`" - } - - @Test("The visibility hint sits after the first verb") - func hintFollowsTheVerb() { - #expect( - OceanBaseSQL.withHiddenColumnVisibilityHint("SELECT * FROM t") - == "SELECT \(OceanBaseSQL.visibilityHint) * FROM t" - ) - #expect( - OceanBaseSQL.withHiddenColumnVisibilityHint("UPDATE t SET a = 1 WHERE b = 2") - == "UPDATE \(OceanBaseSQL.visibilityHint) t SET a = 1 WHERE b = 2" - ) - #expect( - OceanBaseSQL.withHiddenColumnVisibilityHint("DELETE FROM t WHERE id = 1") - == "DELETE \(OceanBaseSQL.visibilityHint) FROM t WHERE id = 1" - ) - } - - @Test("SHOW, SET and KILL are left alone") - func sessionCommandsAreNotHinted() { - for sql in ["SHOW FULL COLUMNS FROM t", "SET SESSION max_execution_time = 1000", "KILL QUERY 42"] { - #expect(OceanBaseSQL.withHiddenColumnVisibilityHint(sql) == sql) - } - } - - @Test("A statement that already carries the hint is not hinted again") - func existingHintIsKept() { - let sql = "SELECT \(OceanBaseSQL.visibilityHint) `__pk_increment` FROM t LIMIT 0" - #expect(OceanBaseSQL.withHiddenColumnVisibilityHint(sql) == sql) - } - - @Test("SELECT * from a table expands with hidden primary key columns") - func selectStarProjectsHiddenKeys() { - let rewritten = OceanBaseSQL.projectingHiddenPrimaryKeys( - sql: "SELECT * FROM orders", - hiddenColumns: ["__pk_increment"], - quote: quote - ) - #expect(rewritten == "SELECT \(OceanBaseSQL.visibilityHint) *, `__pk_increment` FROM orders") - } - - @Test("SELECT * from a subquery is not expanded") - func subquerySelectStarIsNotExpanded() { - let sql = "SELECT * FROM (SELECT 1) AS x" - #expect(OceanBaseSQL.simpleSelectStarTable(from: sql) == nil) - #expect( - OceanBaseSQL.projectingHiddenPrimaryKeys(sql: sql, hiddenColumns: ["__pk_increment"], quote: quote) - == "SELECT \(OceanBaseSQL.visibilityHint) * FROM (SELECT 1) AS x" - ) - } - - @Test("A qualified identifier keeps the table name, not the schema") - func qualifiedTableName() { - #expect(OceanBaseSQL.simpleSelectStarTable(from: "SELECT * FROM `test`.`orders`") == "orders") - #expect(OceanBaseSQL.simpleSelectStarTable(from: "select * from orders WHERE 1") == "orders") - } - - @Test("Hidden primary key names are the ones SHOW INDEX lists that SHOW COLUMNS omits") - func hiddenNamesComeFromThePrimaryIndex() { - #expect( - OceanBaseSQL.hiddenPrimaryKeyColumns( - primaryIndexColumns: ["__pk_increment"], - visibleColumnNames: ["id", "name"] - ) == ["__pk_increment"] - ) - #expect( - OceanBaseSQL.hiddenPrimaryKeyColumns( - primaryIndexColumns: ["id"], - visibleColumnNames: ["id", "name"] - ).isEmpty - ) - #expect( - OceanBaseSQL.hiddenPrimaryKeyColumns( - primaryIndexColumns: ["__pk_increment", "__pk_cluster_column"], - visibleColumnNames: ["name"] - ) == ["__pk_increment", "__pk_cluster_column"] - ) - } - - @Test("The documented probe names a hidden column under the visibility hint") - func documentedProbe() { - #expect( - OceanBaseSQL.documentedHiddenColumnProbe(table: "orders", column: "__pk_increment", quote: quote) - == "SELECT \(OceanBaseSQL.visibilityHint) `__pk_increment` FROM `orders` LIMIT 0" - ) - } -} diff --git a/docs/databases/oceanbase.mdx b/docs/databases/oceanbase.mdx index be783601ef..5537d8f629 100644 --- a/docs/databases/oceanbase.mdx +++ b/docs/databases/oceanbase.mdx @@ -26,18 +26,18 @@ oceanbase://root%40sys:password@host:2881/database `oceanbase+ssh://` opens it through an SSH tunnel. See [Connection URL Reference](/connections/urls). -## Hidden primary keys +## Tables without a primary key -A table with no explicit primary key still has one: `__pk_increment`, and on some clusters `__pk_cluster_column`. `SHOW FULL COLUMNS` and a plain `SELECT *` omit those names, so a grid save that matches on visible columns cannot find the row. +OceanBase keeps a hidden `__pk_increment` column on a table declared without a primary key, but the catalog never reports it and a plain `SELECT *` never returns it, so TablePro edits such a table the way it edits one on [MySQL](/databases/mysql): the `UPDATE` or `DELETE` matches every column of the row, and a save that would touch more than one row is rolled back with a message that identical rows cannot be told apart. -Opening the table projects the hidden key into the result. Stop and parameterized `UPDATE` / `DELETE` then match on it. The column is not editable. +The connection type decides the sidebar, the type picker, EXPLAIN and Stop. A server reached through a connection saved as **MySQL** is treated as MySQL, because the MySQL handshake reports `5.7.25` and names no engine. Choose **OceanBase** for what this page describes. -A connection saved as **MySQL** that reaches an OceanBase server takes the same path. The sidebar, type picker and EXPLAIN follow the connection type, so choose **OceanBase** for those. +Opening an OceanBase connection reads `@@version_comment`. A server that does not name OceanBase there is refused, so a mistyped host or port fails at connect instead of part way through a session. ## What the MySQL driver does not copy - The sidebar hides `information_schema`, `mysql` and `oceanbase`. User databases such as `test` stay listed. -- **Stop** sends `KILL QUERY` for `CONNECTION_ID()`, which is wider than the 32-bit handshake thread id. +- **Stop** sends `KILL QUERY` for the session's own id, as on MySQL. - `EXPLAIN` is plain text. `EXPLAIN FORMAT=JSON` is not offered. - The type picker has MySQL's types without the Spatial group. - [Users & Roles](/features/users-roles) has no connection limit field. diff --git a/docs/external-api/ios-shortcuts.mdx b/docs/external-api/ios-shortcuts.mdx index cd39ca0a0f..a96411b0a9 100644 --- a/docs/external-api/ios-shortcuts.mdx +++ b/docs/external-api/ios-shortcuts.mdx @@ -44,9 +44,9 @@ To browse everything the app offers, open Shortcuts, tap the action list, and go -Inserts work on MySQL, MariaDB, TiDB, PostgreSQL, Redshift, SQL Server, SQLite, DuckDB and Oracle. Any -other type, Redis for example, fails with *"Redis connections do not support adding rows from -Shortcuts."* +Inserts work on MySQL, MariaDB, TiDB, OceanBase, PostgreSQL, Redshift, SQL Server, SQLite, DuckDB and +Oracle. Any other type, Redis for example, fails with *"Redis connections do not support adding rows +from Shortcuts."* Siri takes "Open [connection] in TablePro", "Connect to [connection] in TablePro", "Add a row in TablePro" and "Add rows in TablePro", with a connection name in place of the brackets. diff --git a/docs/ios/index.mdx b/docs/ios/index.mdx index 042e8a94bc..8bd71a27c0 100644 --- a/docs/ios/index.mdx +++ b/docs/ios/index.mdx @@ -1,6 +1,6 @@ --- title: iPhone and iPad -description: Browse tables, run queries, and edit rows on nine database engines from a synced connection list +description: Browse tables, run queries, and edit rows on ten database engines from a synced connection list --- You need iOS 18 or later. Builds ship on their own schedule, so a feature in a Mac release note may not be on your phone yet. Your version and build are under **Settings > About**. Connections saved on a Mac come over iCloud; the rest of your Mac setup stays on the Mac. @@ -12,12 +12,13 @@ You need iOS 18 or later. Builds ship on their own schedule, so a feature in a M ## Supported databases -Every driver is compiled in, so there is no plugin system and nothing to install. The type picker offers these nine: +Every driver is compiled in, so there is no plugin system and nothing to install. The type picker offers these ten: | Type | Notes | | --- | --- | | **MySQL** / **MariaDB** | Port 3306 by default | | **TiDB** | Port 4000 by default. Sequences are not listed as tables | +| **OceanBase** | Port 2881 by default. Sign in as `user@tenant` | | **PostgreSQL** | Port 5432 by default | | **SQL Server** | TDS, including Microsoft Entra ID sign-in on a connection synced from the Mac | | **Oracle** | Service name or SID | diff --git a/project.yml b/project.yml index adbffc33bc..69d7414378 100644 --- a/project.yml +++ b/project.yml @@ -499,8 +499,6 @@ targets: - Plugins/MySQLDriverPlugin/DatabendLiteral.swift - Plugins/MySQLDriverPlugin/DatabendResultShape.swift - Plugins/MySQLDriverPlugin/TiDBCheckConstraints.swift - - Plugins/MySQLDriverPlugin/OceanBaseSQL.swift - - Plugins/MySQLDriverPlugin/OceanBaseHiddenPrimaryKey.swift - Plugins/SQLiteDriverPlugin/SQLiteCheckConstraintParser.swift - Plugins/SQLiteDriverPlugin/SQLiteCreateTableDDL.swift - Plugins/SQLiteDriverPlugin/SQLiteDefaultValue.swift From e98fb5fe54dcda8f96f92b477f46a0fceb1f1fec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 08:00:15 +0700 Subject: [PATCH 22/54] fix(plugin-postgresql): pair composite foreign-key columns by position (#2757) * fix(plugin-postgresql): pair composite foreign-key columns by position * fix(plugin-postgresql): make the shared foreign-key catalog reader nonisolated --- CHANGELOG.md | 3 + .../CockroachPluginDriver.swift | 49 +---- .../PostgreSQLCatalogForeignKeys.swift | 192 ++++++++++++++++++ .../RedshiftPluginDriver.swift | 44 +--- .../Drivers/PostgreSQLDriver.swift | 78 ++++--- .../PostgreSQLForeignKeyQueryTests.swift | 61 ++++++ TableProMobile/project.yml | 2 + .../PostgreSQLCatalogForeignKeysTests.swift | 186 +++++++++++++++++ project.yml | 1 + 9 files changed, 499 insertions(+), 117 deletions(-) create mode 100644 Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogForeignKeys.swift create mode 100644 TableProMobile/TableProMobileTests/Drivers/PostgreSQLForeignKeyQueryTests.swift create mode 100644 TableProTests/Plugins/PostgreSQLCatalogForeignKeysTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ea940ec84..c820062a95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -158,6 +158,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Garbled or double-encoded non-ASCII text on iOS with PostgreSQL databases not encoded in UTF-8. - Garbled non-ASCII text when restoring a PostgreSQL SQL export into a database not encoded in UTF-8. - Display As formats and foreign key labels lost on a rename, and kept with column layouts after deleting a connection. +- Composite foreign keys listing mismatched column pairs on iOS, CockroachDB and Redshift. +- Foreign keys missing on iOS for a PostgreSQL role that does not own the table. +- Redshift foreign keys from other schemas shown on a table. - PostgreSQL view definitions without `security_barrier`, `security_invoker` or the check option. (#2726) - PostgreSQL view definitions that bind to another schema's tables when run elsewhere. (#2726) - `CREATE TABLE` in Structure > DDL for a PostgreSQL view or materialized view. (#2726) diff --git a/Plugins/PostgreSQLDriverPlugin/CockroachPluginDriver.swift b/Plugins/PostgreSQLDriverPlugin/CockroachPluginDriver.swift index 4bba73bc63..9a89bb138f 100644 --- a/Plugins/PostgreSQLDriverPlugin/CockroachPluginDriver.swift +++ b/Plugins/PostgreSQLDriverPlugin/CockroachPluginDriver.swift @@ -144,48 +144,15 @@ final class CockroachPluginDriver: LibPQBackedDriver, @unchecked Sendable { var tableDDLIncludesForeignKeys: Bool { true } func fetchForeignKeys(table: String, schema: String?) async throws -> [PluginForeignKeyInfo] { - let safeTable = escapeLiteral(table) - let schemaLiteral = escapeLiteral(schema ?? core.currentSchema) - let query = """ - SELECT - tc.constraint_name, - kcu.column_name, - ccu.table_name AS referenced_table, - ccu.column_name AS referenced_column, - rc.delete_rule, - rc.update_rule - FROM information_schema.table_constraints tc - JOIN information_schema.key_column_usage kcu - ON tc.constraint_name = kcu.constraint_name - AND tc.table_schema = kcu.table_schema - JOIN information_schema.referential_constraints rc - ON tc.constraint_name = rc.constraint_name - AND tc.table_schema = rc.constraint_schema - JOIN information_schema.constraint_column_usage ccu - ON rc.unique_constraint_name = ccu.constraint_name - AND rc.unique_constraint_schema = ccu.table_schema - WHERE tc.table_name = '\(safeTable)' - AND tc.table_schema = '\(schemaLiteral)' - AND tc.constraint_type = 'FOREIGN KEY' - ORDER BY tc.constraint_name - """ - let result = try await execute(query: query) - return result.rows.compactMap { row -> PluginForeignKeyInfo? in - guard row.count >= 6, - let name = row[0].asText, - let column = row[1].asText, - let refTable = row[2].asText, - let refColumn = row[3].asText - else { return nil } - return PluginForeignKeyInfo( - name: name, - column: column, - referencedTable: refTable, - referencedColumn: refColumn, - onDelete: row[4].asText ?? "NO ACTION", - onUpdate: row[5].asText ?? "NO ACTION" + let query = PostgreSQLCatalogForeignKeys.query( + schemaLiteral: PostgreSQLObjectQueries.quoteLiteral(schema ?? core.currentSchema), + tableLiteral: PostgreSQLObjectQueries.quoteLiteral(table), + excludesPartitionClones: PostgreSQLCatalogForeignKeys.excludesPartitionClones( + serverVersionNumber: core.serverVersionNumber ) - } + ) + let result = try await execute(query: query) + return PostgreSQLCatalogForeignKeys.foreignKeys(from: result.rows.map { $0.map(\.asText) }) } func fetchTableDDL(table: String, schema: String?) async throws -> String { diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogForeignKeys.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogForeignKeys.swift new file mode 100644 index 0000000000..6e00ee739f --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogForeignKeys.swift @@ -0,0 +1,192 @@ +import Foundation +import TableProPluginKit + +nonisolated enum PostgreSQLCatalogForeignKeys { + static let constraintParentMinimumServerVersion: Int32 = 110_000 + + enum Column: Int, CaseIterable { + case constraintIdentity + case constraintName + case referencedSchema + case referencedTable + case deleteAction + case updateAction + case sourceKeys + case referencedKeys + case side + case attributeNumber + case attributeName + } + + enum Side: String, CaseIterable { + case source = "s" + case referenced = "r" + + fileprivate var relationColumn: String { + switch self { + case .source: return "c.conrelid" + case .referenced: return "c.confrelid" + } + } + + fileprivate var keyColumn: String { + switch self { + case .source: return "c.conkey" + case .referenced: return "c.confkey" + } + } + } + + static func query(schemaLiteral: String, tableLiteral: String, excludesPartitionClones: Bool) -> String { + let cloneFilter = excludesPartitionClones ? """ + + AND NOT EXISTS ( + SELECT 1 + FROM pg_catalog.pg_constraint parent + WHERE parent.oid = c.conparentid + AND parent.conrelid = c.conrelid) + """ : "" + let branches = Side.allCases.map { side in + """ + SELECT c.oid, c.conname, ref_ns.nspname, ref_cl.relname, c.confdeltype, c.confupdtype, + c.conkey, c.confkey, '\(side.rawValue)', a.attnum, a.attname + FROM pg_catalog.pg_constraint c + JOIN pg_catalog.pg_class cl ON cl.oid = c.conrelid + JOIN pg_catalog.pg_namespace ns ON ns.oid = cl.relnamespace + JOIN pg_catalog.pg_class ref_cl ON ref_cl.oid = c.confrelid + JOIN pg_catalog.pg_namespace ref_ns ON ref_ns.oid = ref_cl.relnamespace + JOIN pg_catalog.pg_attribute a ON a.attrelid = \(side.relationColumn) AND a.attnum = ANY (\(side.keyColumn)) + WHERE c.contype = 'f' + AND ns.nspname = \(schemaLiteral) + AND cl.relname = \(tableLiteral)\(cloneFilter) + """ + } + return branches.joined(separator: "\nUNION ALL\n") + "\nORDER BY 2, 1" + } + + static func excludesPartitionClones(serverVersionNumber: Int32) -> Bool { + serverVersionNumber >= constraintParentMinimumServerVersion + } + + static func foreignKeys(from rows: [[String?]]) -> [PluginForeignKeyInfo] { + var identities: [String] = [] + var constraints: [String: CatalogForeignKey] = [:] + for row in rows { + guard let keyRow = CatalogKeyRow(row) else { continue } + if constraints[keyRow.constraintIdentity] == nil { + identities.append(keyRow.constraintIdentity) + constraints[keyRow.constraintIdentity] = CatalogForeignKey(keyRow) + } + constraints[keyRow.constraintIdentity]?.record(keyRow) + } + return identities.flatMap { constraints[$0]?.pairs ?? [] } + } + + static func referentialAction(_ code: String?) -> String { + switch code { + case "r": return "RESTRICT" + case "c": return "CASCADE" + case "n": return "SET NULL" + case "d": return "SET DEFAULT" + default: return "NO ACTION" + } + } +} + +nonisolated private struct CatalogKeyRow { + let constraintIdentity: String + let constraintName: String + let referencedSchema: String? + let referencedTable: String + let deleteAction: String? + let updateAction: String? + let sourceKeys: [Int] + let referencedKeys: [Int] + let side: PostgreSQLCatalogForeignKeys.Side + let attributeNumber: Int + let attributeName: String + + init?(_ row: [String?]) { + typealias Column = PostgreSQLCatalogForeignKeys.Column + guard row.count >= Column.allCases.count, + let identity = row[Column.constraintIdentity.rawValue], + let name = row[Column.constraintName.rawValue], + let referencedTable = row[Column.referencedTable.rawValue], + let sourceKeys = Self.attributeNumbers(row[Column.sourceKeys.rawValue]), + let referencedKeys = Self.attributeNumbers(row[Column.referencedKeys.rawValue]), + let sideCode = row[Column.side.rawValue], + let side = PostgreSQLCatalogForeignKeys.Side(rawValue: sideCode), + let attributeNumberText = row[Column.attributeNumber.rawValue], + let attributeNumber = Int(attributeNumberText), + let attributeName = row[Column.attributeName.rawValue] + else { return nil } + self.constraintIdentity = identity + self.constraintName = name + self.referencedSchema = row[Column.referencedSchema.rawValue] + self.referencedTable = referencedTable + self.deleteAction = row[Column.deleteAction.rawValue] + self.updateAction = row[Column.updateAction.rawValue] + self.sourceKeys = sourceKeys + self.referencedKeys = referencedKeys + self.side = side + self.attributeNumber = attributeNumber + self.attributeName = attributeName + } + + private static func attributeNumbers(_ text: String?) -> [Int]? { + guard let text, let elements = PostgresArrayLiteralCodec.parse(text) else { return nil } + var numbers: [Int] = [] + for element in elements { + guard case .value(let value) = element, let number = Int(value) else { return nil } + numbers.append(number) + } + return numbers + } +} + +nonisolated private struct CatalogForeignKey { + let name: String + let referencedSchema: String? + let referencedTable: String + let onDelete: String + let onUpdate: String + let sourceKeys: [Int] + let referencedKeys: [Int] + var sourceNames: [Int: String] = [:] + var referencedNames: [Int: String] = [:] + + init(_ row: CatalogKeyRow) { + self.name = row.constraintName + self.referencedSchema = row.referencedSchema + self.referencedTable = row.referencedTable + self.onDelete = PostgreSQLCatalogForeignKeys.referentialAction(row.deleteAction) + self.onUpdate = PostgreSQLCatalogForeignKeys.referentialAction(row.updateAction) + self.sourceKeys = row.sourceKeys + self.referencedKeys = row.referencedKeys + } + + mutating func record(_ row: CatalogKeyRow) { + switch row.side { + case .source: sourceNames[row.attributeNumber] = row.attributeName + case .referenced: referencedNames[row.attributeNumber] = row.attributeName + } + } + + var pairs: [PluginForeignKeyInfo] { + guard sourceKeys.count == referencedKeys.count else { return [] } + return zip(sourceKeys, referencedKeys).compactMap { sourceKey, referencedKey in + guard let column = sourceNames[sourceKey], let referencedColumn = referencedNames[referencedKey] else { + return nil + } + return PluginForeignKeyInfo( + name: name, + column: column, + referencedTable: referencedTable, + referencedColumn: referencedColumn, + referencedSchema: referencedSchema, + onDelete: onDelete, + onUpdate: onUpdate + ) + } + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/RedshiftPluginDriver.swift b/Plugins/PostgreSQLDriverPlugin/RedshiftPluginDriver.swift index a05d06cd87..675b55994e 100644 --- a/Plugins/PostgreSQLDriverPlugin/RedshiftPluginDriver.swift +++ b/Plugins/PostgreSQLDriverPlugin/RedshiftPluginDriver.swift @@ -365,43 +365,15 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { var tableDDLIncludesForeignKeys: Bool { true } func fetchForeignKeys(table: String, schema: String?) async throws -> [PluginForeignKeyInfo] { - let safeTable = escapeLiteral(table) - let query = """ - SELECT - tc.constraint_name, - kcu.column_name, - ccu.table_name AS referenced_table, - ccu.column_name AS referenced_column, - rc.delete_rule, - rc.update_rule - FROM information_schema.table_constraints tc - JOIN information_schema.key_column_usage kcu - ON tc.constraint_name = kcu.constraint_name - JOIN information_schema.referential_constraints rc - ON tc.constraint_name = rc.constraint_name - JOIN information_schema.constraint_column_usage ccu - ON rc.unique_constraint_name = ccu.constraint_name - WHERE tc.table_name = '\(safeTable)' - AND tc.constraint_type = 'FOREIGN KEY' - ORDER BY tc.constraint_name - """ - let result = try await execute(query: query) - return result.rows.compactMap { row -> PluginForeignKeyInfo? in - guard row.count >= 6, - let name = row[0].asText, - let column = row[1].asText, - let refTable = row[2].asText, - let refColumn = row[3].asText - else { return nil } - return PluginForeignKeyInfo( - name: name, - column: column, - referencedTable: refTable, - referencedColumn: refColumn, - onDelete: row[4].asText ?? "NO ACTION", - onUpdate: row[5].asText ?? "NO ACTION" + let query = PostgreSQLCatalogForeignKeys.query( + schemaLiteral: PostgreSQLObjectQueries.quoteLiteral(schema ?? core.currentSchema), + tableLiteral: PostgreSQLObjectQueries.quoteLiteral(table), + excludesPartitionClones: PostgreSQLCatalogForeignKeys.excludesPartitionClones( + serverVersionNumber: core.serverVersionNumber ) - } + ) + let result = try await execute(query: query) + return PostgreSQLCatalogForeignKeys.foreignKeys(from: result.rows.map { $0.map(\.asText) }) } func fetchApproximateRowCount(table: String, schema: String?) async throws -> Int? { diff --git a/TableProMobile/TableProMobile/Drivers/PostgreSQLDriver.swift b/TableProMobile/TableProMobile/Drivers/PostgreSQLDriver.swift index dc6932f7d4..58945a8619 100644 --- a/TableProMobile/TableProMobile/Drivers/PostgreSQLDriver.swift +++ b/TableProMobile/TableProMobile/Drivers/PostgreSQLDriver.swift @@ -3,6 +3,7 @@ import Foundation import os import TableProDatabase import TableProModels +import TableProPluginKit nonisolated final class PostgreSQLDriver: DatabaseDriver, @unchecked Sendable { private let actor = PostgreSQLActor() @@ -19,6 +20,7 @@ nonisolated final class PostgreSQLDriver: DatabaseDriver, @unchecked Sendable { // Set once during connect()/switchSchema() before the driver is shared — safe for concurrent reads nonisolated(unsafe) private(set) var currentSchema: String? = "public" nonisolated(unsafe) private(set) var serverVersion: String? + nonisolated(unsafe) private(set) var serverVersionNumber: Int32 = 0 nonisolated(unsafe) private var reportsIdentityColumns: Bool? @@ -40,6 +42,7 @@ nonisolated final class PostgreSQLDriver: DatabaseDriver, @unchecked Sendable { try await actor.connect(host: host, port: port, user: user, password: password, database: database, ssl: ssl) _ = try? await actor.execute("SET standard_conforming_strings = on") serverVersion = await actor.serverVersion() + serverVersionNumber = await actor.serverVersionNumber() await adoptServerSchema() } @@ -286,51 +289,41 @@ nonisolated final class PostgreSQLDriver: DatabaseDriver, @unchecked Sendable { } func fetchForeignKeys(table: String, schema: String?) async throws -> [ForeignKeyInfo] { - let schemaName = schema ?? effectiveSchema - let safeTbl = table.replacingOccurrences(of: "'", with: "''") - let safeSchema = schemaName.replacingOccurrences(of: "'", with: "''") - - let raw = try await actor.execute(""" - SELECT - tc.constraint_name, - kcu.column_name, - ccu.table_name AS referenced_table, - ccu.column_name AS referenced_column, - rc.delete_rule, - rc.update_rule - FROM information_schema.table_constraints tc - JOIN information_schema.key_column_usage kcu - ON tc.constraint_name = kcu.constraint_name - AND tc.table_schema = kcu.table_schema - JOIN information_schema.constraint_column_usage ccu - ON tc.constraint_name = ccu.constraint_name - AND tc.table_schema = ccu.table_schema - JOIN information_schema.referential_constraints rc - ON tc.constraint_name = rc.constraint_name - AND tc.table_schema = rc.constraint_schema - WHERE tc.constraint_type = 'FOREIGN KEY' - AND tc.table_schema = '\(safeSchema)' - AND tc.table_name = '\(safeTbl)' - ORDER BY tc.constraint_name - """) + let raw = try await actor.execute( + Self.foreignKeysQuery( + schema: schema ?? effectiveSchema, + table: table, + serverVersionNumber: serverVersionNumber + ) + ) - return raw.rows.compactMap { row in - guard row.count >= 6, - let name = row[0], - let column = row[1], - let refTable = row[2], - let refColumn = row[3] else { return nil } - return ForeignKeyInfo( - name: name, - column: column, - referencedTable: refTable, - referencedColumn: refColumn, - onDelete: row[4] ?? "NO ACTION", - onUpdate: row[5] ?? "NO ACTION" + return PostgreSQLCatalogForeignKeys.foreignKeys(from: raw.rows).map { key in + ForeignKeyInfo( + name: key.name, + column: key.column, + referencedTable: key.referencedTable, + referencedColumn: key.referencedColumn, + referencedSchema: key.referencedSchema, + onDelete: key.onDelete, + onUpdate: key.onUpdate ) } } + static func foreignKeysQuery(schema: String, table: String, serverVersionNumber: Int32) -> String { + PostgreSQLCatalogForeignKeys.query( + schemaLiteral: literal(schema), + tableLiteral: literal(table), + excludesPartitionClones: PostgreSQLCatalogForeignKeys.excludesPartitionClones( + serverVersionNumber: serverVersionNumber + ) + ) + } + + private static func literal(_ value: String) -> String { + "'\(value.replacingOccurrences(of: "'", with: "''"))'" + } + func fetchDatabases() async throws -> [String] { let raw = try await actor.execute( "SELECT datname FROM pg_database WHERE datistemplate = false ORDER BY datname" @@ -469,6 +462,11 @@ private actor PostgreSQLActor { } } + func serverVersionNumber() -> Int32 { + guard let conn else { return 0 } + return PQserverVersion(conn) + } + func serverVersion() -> String? { guard let conn else { return nil } let version = PQserverVersion(conn) diff --git a/TableProMobile/TableProMobileTests/Drivers/PostgreSQLForeignKeyQueryTests.swift b/TableProMobile/TableProMobileTests/Drivers/PostgreSQLForeignKeyQueryTests.swift new file mode 100644 index 0000000000..240af440e8 --- /dev/null +++ b/TableProMobile/TableProMobileTests/Drivers/PostgreSQLForeignKeyQueryTests.swift @@ -0,0 +1,61 @@ +import Foundation +@testable import TableProMobile +import TableProPluginKit +import Testing + +@Suite("PostgreSQL foreign key query") +struct PostgreSQLForeignKeyQueryTests { + private func row(_ side: String, _ attributeNumber: Int, _ attributeName: String) -> [String?] { + var cells: [String?] = Array(repeating: nil, count: PostgreSQLCatalogForeignKeys.Column.allCases.count) + cells[PostgreSQLCatalogForeignKeys.Column.constraintIdentity.rawValue] = "42" + cells[PostgreSQLCatalogForeignKeys.Column.constraintName.rawValue] = "fk_xy" + cells[PostgreSQLCatalogForeignKeys.Column.referencedSchema.rawValue] = "sales" + cells[PostgreSQLCatalogForeignKeys.Column.referencedTable.rawValue] = "parent" + cells[PostgreSQLCatalogForeignKeys.Column.deleteAction.rawValue] = "c" + cells[PostgreSQLCatalogForeignKeys.Column.updateAction.rawValue] = "a" + cells[PostgreSQLCatalogForeignKeys.Column.sourceKeys.rawValue] = "{2,3}" + cells[PostgreSQLCatalogForeignKeys.Column.referencedKeys.rawValue] = "{1,2}" + cells[PostgreSQLCatalogForeignKeys.Column.side.rawValue] = side + cells[PostgreSQLCatalogForeignKeys.Column.attributeNumber.rawValue] = String(attributeNumber) + cells[PostgreSQLCatalogForeignKeys.Column.attributeName.rawValue] = attributeName + return cells + } + + @Test("a composite key decodes to one pair per column, in key order") + func decodesOnePairPerColumn() { + let rows = [row("s", 2, "a"), row("s", 3, "b"), row("r", 1, "x"), row("r", 2, "y")] + + let keys = PostgreSQLCatalogForeignKeys.foreignKeys(from: rows) + + #expect(keys.map(\.column) == ["a", "b"]) + #expect(keys.map(\.referencedColumn) == ["x", "y"]) + #expect(keys.allSatisfy { $0.referencedSchema == "sales" }) + #expect(keys.allSatisfy { $0.onDelete == "CASCADE" && $0.onUpdate == "NO ACTION" }) + } + + @Test("the constraint is found by the table's own schema and name") + func filtersOnSchemaAndTable() { + let query = PostgreSQLDriver.foreignKeysQuery(schema: "sales", table: "orders", serverVersionNumber: 170_011) + + #expect(query.contains("ns.nspname = 'sales'")) + #expect(query.contains("cl.relname = 'orders'")) + } + + @Test("quotes in the schema and table names are doubled") + func escapesQuotes() { + let query = PostgreSQLDriver.foreignKeysQuery(schema: "o'brien", table: "it's", serverVersionNumber: 170_011) + + #expect(query.contains("ns.nspname = 'o''brien'")) + #expect(query.contains("cl.relname = 'it''s'")) + } + + @Test("a Redshift server never receives the PostgreSQL 11 clone filter") + func redshiftKeepsPortableQuery() { + let redshift = PostgreSQLDriver.foreignKeysQuery(schema: "public", table: "t", serverVersionNumber: 80_002) + let modern = PostgreSQLDriver.foreignKeysQuery(schema: "public", table: "t", serverVersionNumber: 170_011) + + #expect(!redshift.contains("conparentid")) + #expect(!redshift.contains("generate_subscripts")) + #expect(modern.contains("conparentid")) + } +} diff --git a/TableProMobile/project.yml b/TableProMobile/project.yml index f417e9da2b..5958c8994f 100644 --- a/TableProMobile/project.yml +++ b/TableProMobile/project.yml @@ -63,6 +63,8 @@ targets: - ../Plugins/MySQLDriverPlugin/MySQLConnectionEncoding.swift - ../Plugins/MySQLDriverPlugin/MySQLLatin1.swift - ../Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift + # Foreign key catalog read the iOS PostgreSQL driver shares with the macOS plugin. + - ../Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogForeignKeys.swift # libpq COPY handling the iOS PostgreSQL driver shares with the macOS plugin. - ../Plugins/PostgreSQLDriverPlugin/LibPQPendingResultDrain.swift - ../Plugins/PostgreSQLDriverPlugin/LibPQCopyState.swift diff --git a/TableProTests/Plugins/PostgreSQLCatalogForeignKeysTests.swift b/TableProTests/Plugins/PostgreSQLCatalogForeignKeysTests.swift new file mode 100644 index 0000000000..982e99ba8c --- /dev/null +++ b/TableProTests/Plugins/PostgreSQLCatalogForeignKeysTests.swift @@ -0,0 +1,186 @@ +import Foundation +import TableProPluginKit +import Testing + +@Suite("PostgreSQLCatalogForeignKeys") +struct PostgreSQLCatalogForeignKeysTests { + private func row( + identity: String = "100", + name: String, + referencedSchema: String? = "app", + referencedTable: String = "parent", + deleteAction: String = "a", + updateAction: String = "a", + sourceKeys: String, + referencedKeys: String, + side: String, + attributeNumber: Int, + attributeName: String + ) -> [String?] { + var cells: [String?] = Array(repeating: nil, count: PostgreSQLCatalogForeignKeys.Column.allCases.count) + cells[PostgreSQLCatalogForeignKeys.Column.constraintIdentity.rawValue] = identity + cells[PostgreSQLCatalogForeignKeys.Column.constraintName.rawValue] = name + cells[PostgreSQLCatalogForeignKeys.Column.referencedSchema.rawValue] = referencedSchema + cells[PostgreSQLCatalogForeignKeys.Column.referencedTable.rawValue] = referencedTable + cells[PostgreSQLCatalogForeignKeys.Column.deleteAction.rawValue] = deleteAction + cells[PostgreSQLCatalogForeignKeys.Column.updateAction.rawValue] = updateAction + cells[PostgreSQLCatalogForeignKeys.Column.sourceKeys.rawValue] = sourceKeys + cells[PostgreSQLCatalogForeignKeys.Column.referencedKeys.rawValue] = referencedKeys + cells[PostgreSQLCatalogForeignKeys.Column.side.rawValue] = side + cells[PostgreSQLCatalogForeignKeys.Column.attributeNumber.rawValue] = String(attributeNumber) + cells[PostgreSQLCatalogForeignKeys.Column.attributeName.rawValue] = attributeName + return cells + } + + private func pairs(_ keys: [PluginForeignKeyInfo]) -> [String] { + keys.map { "\($0.name):\($0.column)->\($0.referencedTable).\($0.referencedColumn)" } + } + + @Test("A composite key yields one pair per column, in key order") + func compositeKeyPairsByPosition() { + let rows = [ + row(name: "fk_xy", sourceKeys: "{2,3}", referencedKeys: "{1,2}", side: "r", attributeNumber: 1, attributeName: "x"), + row(name: "fk_xy", sourceKeys: "{2,3}", referencedKeys: "{1,2}", side: "r", attributeNumber: 2, attributeName: "y"), + row(name: "fk_xy", sourceKeys: "{2,3}", referencedKeys: "{1,2}", side: "s", attributeNumber: 2, attributeName: "a"), + row(name: "fk_xy", sourceKeys: "{2,3}", referencedKeys: "{1,2}", side: "s", attributeNumber: 3, attributeName: "b") + ] + let keys = PostgreSQLCatalogForeignKeys.foreignKeys(from: rows) + #expect(pairs(keys) == ["fk_xy:a->parent.x", "fk_xy:b->parent.y"]) + } + + @Test("Columns listed in a different order than the referenced key pair by the key arrays, not by attribute order") + func reorderedReferencePairsByKeyArrays() { + let rows = [ + row(name: "fk_ba", sourceKeys: "{3,2}", referencedKeys: "{2,1}", side: "s", attributeNumber: 2, attributeName: "a"), + row(name: "fk_ba", sourceKeys: "{3,2}", referencedKeys: "{2,1}", side: "s", attributeNumber: 3, attributeName: "b"), + row(name: "fk_ba", sourceKeys: "{3,2}", referencedKeys: "{2,1}", side: "r", attributeNumber: 1, attributeName: "x"), + row(name: "fk_ba", sourceKeys: "{3,2}", referencedKeys: "{2,1}", side: "r", attributeNumber: 2, attributeName: "y") + ] + let keys = PostgreSQLCatalogForeignKeys.foreignKeys(from: rows) + #expect(pairs(keys) == ["fk_ba:b->parent.y", "fk_ba:a->parent.x"]) + } + + @Test("Two constraints with the same name stay separate when their identities differ") + func sameNameDifferentConstraintsStaySeparate() { + let rows = [ + row(identity: "1", name: "fk", referencedTable: "one", sourceKeys: "{1}", referencedKeys: "{1}", side: "s", attributeNumber: 1, attributeName: "a"), + row(identity: "1", name: "fk", referencedTable: "one", sourceKeys: "{1}", referencedKeys: "{1}", side: "r", attributeNumber: 1, attributeName: "id"), + row(identity: "2", name: "fk", referencedTable: "two", sourceKeys: "{2}", referencedKeys: "{1}", side: "s", attributeNumber: 2, attributeName: "b"), + row(identity: "2", name: "fk", referencedTable: "two", sourceKeys: "{2}", referencedKeys: "{1}", side: "r", attributeNumber: 1, attributeName: "key") + ] + let keys = PostgreSQLCatalogForeignKeys.foreignKeys(from: rows) + #expect(pairs(keys) == ["fk:a->one.id", "fk:b->two.key"]) + } + + @Test("A self-referencing composite key pairs source and referenced attributes of the same table") + func selfReferenceUsesBothSides() { + let rows = [ + row(name: "tree_self", referencedTable: "tree", sourceKeys: "{3,4}", referencedKeys: "{1,2}", side: "s", attributeNumber: 3, attributeName: "pp"), + row(name: "tree_self", referencedTable: "tree", sourceKeys: "{3,4}", referencedKeys: "{1,2}", side: "s", attributeNumber: 4, attributeName: "pq"), + row(name: "tree_self", referencedTable: "tree", sourceKeys: "{3,4}", referencedKeys: "{1,2}", side: "r", attributeNumber: 1, attributeName: "p"), + row(name: "tree_self", referencedTable: "tree", sourceKeys: "{3,4}", referencedKeys: "{1,2}", side: "r", attributeNumber: 2, attributeName: "q") + ] + let keys = PostgreSQLCatalogForeignKeys.foreignKeys(from: rows) + #expect(pairs(keys) == ["tree_self:pp->tree.p", "tree_self:pq->tree.q"]) + } + + @Test("Referenced schema and referential actions come from the catalog row") + func carriesSchemaAndActions() throws { + let rows = [("s", "Weird, Col"), ("r", "id")].map { side, attributeName in + row( + name: "fk", + referencedSchema: "billing", + deleteAction: "c", + updateAction: "n", + sourceKeys: "{1}", + referencedKeys: "{1}", + side: side, + attributeNumber: 1, + attributeName: attributeName + ) + } + let key = try #require(PostgreSQLCatalogForeignKeys.foreignKeys(from: rows).first) + #expect(key.column == "Weird, Col") + #expect(key.referencedSchema == "billing") + #expect(key.onDelete == "CASCADE") + #expect(key.onUpdate == "SET NULL") + } + + @Test("Every referential action code maps to its SQL keyword") + func referentialActionCodes() { + #expect(PostgreSQLCatalogForeignKeys.referentialAction("a") == "NO ACTION") + #expect(PostgreSQLCatalogForeignKeys.referentialAction("r") == "RESTRICT") + #expect(PostgreSQLCatalogForeignKeys.referentialAction("c") == "CASCADE") + #expect(PostgreSQLCatalogForeignKeys.referentialAction("n") == "SET NULL") + #expect(PostgreSQLCatalogForeignKeys.referentialAction("d") == "SET DEFAULT") + #expect(PostgreSQLCatalogForeignKeys.referentialAction(nil) == "NO ACTION") + } + + @Test("Key arrays of different lengths produce no pairs rather than a guessed pairing") + func mismatchedKeyArraysProduceNothing() { + let rows = [ + row(name: "fk", sourceKeys: "{1,2}", referencedKeys: "{1}", side: "s", attributeNumber: 1, attributeName: "a"), + row(name: "fk", sourceKeys: "{1,2}", referencedKeys: "{1}", side: "r", attributeNumber: 1, attributeName: "x") + ] + #expect(PostgreSQLCatalogForeignKeys.foreignKeys(from: rows).isEmpty) + } + + @Test("A row whose key array cannot be read is skipped") + func unreadableKeyArrayIsSkipped() { + let rows = [ + row(name: "fk", sourceKeys: "1,2", referencedKeys: "{1,2}", side: "s", attributeNumber: 1, attributeName: "a") + ] + #expect(PostgreSQLCatalogForeignKeys.foreignKeys(from: rows).isEmpty) + } + + @Test("The query filters on the table's own schema and name and reads both key arrays") + func queryFiltersOnSchemaAndTable() { + let query = PostgreSQLCatalogForeignKeys.query( + schemaLiteral: "'sales'", + tableLiteral: "'orders'", + excludesPartitionClones: true + ) + #expect(query.contains("ns.nspname = 'sales'")) + #expect(query.contains("cl.relname = 'orders'")) + #expect(query.contains("a.attnum = ANY (c.conkey)")) + #expect(query.contains("a.attnum = ANY (c.confkey)")) + #expect(!query.contains("information_schema")) + } + + @Test("Both branches project every decoded column") + func branchesProjectEveryColumn() { + let query = PostgreSQLCatalogForeignKeys.query( + schemaLiteral: "'public'", + tableLiteral: "'t'", + excludesPartitionClones: false + ) + let branches = query.components(separatedBy: "UNION ALL") + #expect(branches.count == PostgreSQLCatalogForeignKeys.Side.allCases.count) + } + + @Test("Partition clones are excluded from PostgreSQL 11 on, where conparentid exists") + func partitionCloneGateFollowsServerVersion() { + #expect(!PostgreSQLCatalogForeignKeys.excludesPartitionClones(serverVersionNumber: 0)) + #expect(!PostgreSQLCatalogForeignKeys.excludesPartitionClones(serverVersionNumber: 80_002)) + #expect(!PostgreSQLCatalogForeignKeys.excludesPartitionClones(serverVersionNumber: 100_021)) + #expect(PostgreSQLCatalogForeignKeys.excludesPartitionClones(serverVersionNumber: 110_016)) + #expect(PostgreSQLCatalogForeignKeys.excludesPartitionClones(serverVersionNumber: 170_011)) + } + + @Test("A server without conparentid is never sent the clone filter") + func cloneFilterOmittedWhenUnsupported() { + let filtered = PostgreSQLCatalogForeignKeys.query( + schemaLiteral: "'public'", + tableLiteral: "'t'", + excludesPartitionClones: true + ) + let plain = PostgreSQLCatalogForeignKeys.query( + schemaLiteral: "'public'", + tableLiteral: "'t'", + excludesPartitionClones: false + ) + #expect(filtered.contains("parent.oid = c.conparentid")) + #expect(filtered.contains("parent.conrelid = c.conrelid")) + #expect(!plain.contains("conparentid")) + } +} diff --git a/project.yml b/project.yml index 8c24b7d442..ab69c92a6f 100644 --- a/project.yml +++ b/project.yml @@ -518,6 +518,7 @@ targets: - Plugins/PostgreSQLDriverPlugin/LibPQSSLMapping.swift - Plugins/PostgreSQLDriverPlugin/PostGISSpatialRewrite.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift + - Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogForeignKeys.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogPresence.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogTypeNames.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLCheckConstraintDefinition.swift From 586e622c69583f1adf7c550556f146f908bb8ffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 08:00:27 +0700 Subject: [PATCH 23/54] fix(plugin-postgresql): force standard_conforming_strings on every session (#2760) --- CHANGELOG.md | 1 + .../LibPQDriverCore.swift | 5 ++ .../LibPQPluginConnection.swift | 57 ++++++++++++ .../LibPQStringConformance.swift | 35 ++++++++ .../PostgreSQLObjectQueries.swift | 22 ++--- .../PostgreSQLPrincipalQueries.swift | 4 +- .../Plugins/LibPQStringConformanceTests.swift | 87 +++++++++++++++++++ .../Plugins/ObjectCatalogQueryTests.swift | 20 +++++ project.yml | 1 + 9 files changed, 219 insertions(+), 13 deletions(-) create mode 100644 Plugins/PostgreSQLDriverPlugin/LibPQStringConformance.swift create mode 100644 TableProTests/Plugins/LibPQStringConformanceTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index c820062a95..fdc24d3451 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -178,6 +178,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Security - BigQuery Google sign-in accepting an authorization response without PKCE or a state check. +- PostgreSQL sessions inheriting `standard_conforming_strings = off`, which let a backslash break out of any quoted literal. - PostgreSQL comment and password literals escaped by quote doubling alone, which a backslash can break out of. (#2726) ## [0.73.0] - 2026-09-09 diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift b/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift index 265d120aef..36a40a59cb 100644 --- a/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift +++ b/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift @@ -27,6 +27,7 @@ final class LibPQDriverCore: @unchecked Sendable { var serverVersion: String? { libpqConnection?.serverVersion() } var serverVersionNumber: Int32 { libpqConnection?.serverVersionNumber() ?? 0 } + var standardConformingStrings: Bool { libpqConnection?.standardConformingStrings ?? true } var isInsideTransactionBlock: Bool { libpqConnection?.isInsideTransactionBlock ?? false } init( @@ -334,6 +335,10 @@ extension LibPQBackedDriver { var serverVersion: String? { core.serverVersion } var parameterStyle: ParameterStyle { .dollar } + func escapeStringLiteral(_ value: String) -> String { + LibPQStringConformance.escape(value, standardConformingStrings: core.standardConformingStrings) + } + func escapeLiteral(_ str: String) -> String { escapeStringLiteral(str) } diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift b/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift index 58bfbf0129..676cd6be24 100644 --- a/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift +++ b/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift @@ -119,6 +119,7 @@ final class LibPQPluginConnection: @unchecked Sendable { private var _isConnectCancelled: Bool = false private var _postgisOidMap: [UInt32: String] = [:] private var _catalogTypeNames: [UInt32: String] = [:] + private var _standardConformingStrings = true var isConnected: Bool { stateLock.lock() @@ -126,6 +127,10 @@ final class LibPQPluginConnection: @unchecked Sendable { return _isConnected } + var standardConformingStrings: Bool { + stateLock.withLock { _standardConformingStrings } + } + private var isShuttingDown: Bool { get { stateLock.lock() @@ -300,6 +305,12 @@ final class LibPQPluginConnection: @unchecked Sendable { private func configureEstablishedConnection(_ connection: OpaquePointer) { logUnexpectedClientEncoding(of: connection) + runSessionSetupStatement(LibPQStringConformance.enableStatement, on: connection) + storeStandardConformingStrings( + reportedStandardConformingStrings(on: connection) + ?? queriedStandardConformingStrings(on: connection) + ?? true + ) let version = PQserverVersion(connection) guard version > 0 else { return } @@ -324,6 +335,48 @@ final class LibPQPluginConnection: @unchecked Sendable { ) } + private func runSessionSetupStatement(_ statement: String, on connection: OpaquePointer) { + let result = statement.withCString { PQexec(connection, $0) } + defer { PQclear(result) } + guard PQresultStatus(result) != PGRES_COMMAND_OK else { return } + let message = result.flatMap { PQresultErrorMessage($0) }.map { String(cString: $0) } ?? "" + logger.warning( + "Session setup statement failed: \(statement, privacy: .public) \(message, privacy: .public)" + ) + } + + private func reportedStandardConformingStrings(on connection: OpaquePointer) -> Bool? { + guard let value = PQparameterStatus(connection, LibPQStringConformance.parameterName) else { + return nil + } + return LibPQStringConformance.isOn(String(cString: value)) + } + + private func queriedStandardConformingStrings(on connection: OpaquePointer) -> Bool? { + let result = LibPQStringConformance.showQuery.withCString { PQexec(connection, $0) } + defer { PQclear(result) } + guard PQresultStatus(result) == PGRES_TUPLES_OK, + PQntuples(result) > 0, + let value = PQgetvalue(result, 0, 0) else { + return nil + } + return LibPQStringConformance.isOn(String(cString: value)) + } + + private func refreshStandardConformingStrings(from connection: OpaquePointer) { + guard let reported = reportedStandardConformingStrings(on: connection) else { return } + storeStandardConformingStrings(reported) + } + + private func storeStandardConformingStrings(_ value: Bool) { + let changed = stateLock.withLock { + defer { _standardConformingStrings = value } + return _standardConformingStrings != value + } + guard changed, !value else { return } + logger.warning("standard_conforming_strings is off; string literals escape backslashes") + } + private var connectionString: String { LibPQConnectionString.build( host: host, @@ -547,6 +600,7 @@ final class LibPQPluginConnection: @unchecked Sendable { let generation = cancellationGate.beginQuery() defer { cancellationGate.endQuery(generation) } + defer { refreshStandardConformingStrings(from: conn) } let cancelsOutput = cancelsAbandonedOutput(conn) let localQuery = String(query) @@ -610,6 +664,7 @@ final class LibPQPluginConnection: @unchecked Sendable { let generation = cancellationGate.beginQuery() defer { cancellationGate.endQuery(generation) } + defer { refreshStandardConformingStrings(from: conn) } /// Started before the drain, so a result the previous statement abandoned is charged to the /// time before the first row rather than appearing as this query's row transfer. @@ -738,6 +793,7 @@ final class LibPQPluginConnection: @unchecked Sendable { let generation = cancellationGate.beginQuery() defer { cancellationGate.endQuery(generation) } + defer { refreshStandardConformingStrings(from: conn) } let cancelsOutput = cancelsAbandonedOutput(conn) var paramValues: [UnsafePointer?] = [] @@ -916,6 +972,7 @@ final class LibPQPluginConnection: @unchecked Sendable { let generation = cancellationGate.beginQuery() defer { cancellationGate.endQuery(generation) } + defer { refreshStandardConformingStrings(from: conn) } /// The consumer can go away before this block is scheduled, in which case the /// query is never sent at all. diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQStringConformance.swift b/Plugins/PostgreSQLDriverPlugin/LibPQStringConformance.swift new file mode 100644 index 0000000000..0227cf52c5 --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/LibPQStringConformance.swift @@ -0,0 +1,35 @@ +// +// LibPQStringConformance.swift +// PostgreSQLDriverPlugin +// + +import Foundation + +enum LibPQStringConformance { + static let parameterName = "standard_conforming_strings" + + static let enableStatement = "SET standard_conforming_strings TO on" + + static let showQuery = "SHOW standard_conforming_strings" + + static func isOn(_ reportedValue: String?) -> Bool? { + guard let reportedValue else { return nil } + let normalized = reportedValue.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() + switch normalized { + case "on", "true", "yes", "1": + return true + case "off", "false", "no", "0": + return false + default: + return nil + } + } + + static func escape(_ value: String, standardConformingStrings: Bool) -> String { + let quoted = value + .replacingOccurrences(of: "\0", with: "") + .replacingOccurrences(of: "'", with: "''") + guard !standardConformingStrings else { return quoted } + return quoted.replacingOccurrences(of: "\\", with: "\\\\") + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift index b7b5f544eb..80af3410f0 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift @@ -52,7 +52,7 @@ public enum PostgreSQLObjectQueries { /// pg_get_functiondef raises on them, which would fail the whole listing over one object the /// viewer could not have shown anyway. public static func routineList(schema: String, serverVersionNumber: Int32) -> String { - let schemaLiteral = escapeLiteral(schema) + let schemaLiteral = quoteLiteral(schema) let modern = usesProkind(serverVersionNumber: serverVersionNumber) let kindColumn = modern ? "p.prokind" @@ -75,7 +75,7 @@ public enum PostgreSQLObjectQueries { FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace JOIN pg_catalog.pg_language l ON l.oid = p.prolang - WHERE n.nspname = '\(schemaLiteral)' + WHERE n.nspname = \(schemaLiteral) AND \(kindFilter) AND NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_depend d @@ -89,22 +89,22 @@ public enum PostgreSQLObjectQueries { /// instead of whichever row the planner happened to return first. public static func routineDefinition(identity: String) -> String { """ - SELECT pg_catalog.pg_get_functiondef('\(escapeLiteral(identity))'::oid) + SELECT pg_catalog.pg_get_functiondef(\(quoteLiteral(identity))::oid) """ } public static func routineDefinitionByName(name: String, schema: String, arguments: String?) -> String { - let nameLiteral = escapeLiteral(name) - let schemaLiteral = escapeLiteral(schema) + let nameLiteral = quoteLiteral(name) + let schemaLiteral = quoteLiteral(schema) let argumentsPredicate = arguments.map { - "AND '(' || pg_catalog.pg_get_function_identity_arguments(p.oid) || ')' = '\(escapeLiteral($0))'" + "AND '(' || pg_catalog.pg_get_function_identity_arguments(p.oid) || ')' = \(quoteLiteral($0))" } ?? "" return """ SELECT pg_catalog.pg_get_functiondef(p.oid) FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace - WHERE n.nspname = '\(schemaLiteral)' - AND p.proname = '\(nameLiteral)' + WHERE n.nspname = \(schemaLiteral) + AND p.proname = \(nameLiteral) \(argumentsPredicate) ORDER BY p.oid LIMIT 1 @@ -114,8 +114,8 @@ public enum PostgreSQLObjectQueries { /// One query for the whole schema. The per-table fetch is the same SELECT with one more /// predicate, so the two lists cannot disagree about a table they both cover. public static func triggerList(schema: String, table: String?) -> String { - let schemaLiteral = escapeLiteral(schema) - let tablePredicate = table.map { "AND c.relname = '\(escapeLiteral($0))'" } ?? "" + let schemaLiteral = quoteLiteral(schema) + let tablePredicate = table.map { "AND c.relname = \(quoteLiteral($0))" } ?? "" return """ SELECT t.tgname AS name, @@ -137,7 +137,7 @@ public enum PostgreSQLObjectQueries { FROM pg_catalog.pg_trigger t JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace - WHERE n.nspname = '\(schemaLiteral)' + WHERE n.nspname = \(schemaLiteral) AND NOT t.tgisinternal \(tablePredicate) ORDER BY c.relname, t.tgname diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPrincipalQueries.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPrincipalQueries.swift index 14633fbdf3..542d3d9620 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPrincipalQueries.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPrincipalQueries.swift @@ -93,7 +93,7 @@ enum PostgreSQLPrincipalQueries { SELECT n.nspname FROM pg_namespace n WHERE n.nspname NOT IN ('pg_catalog', 'information_schema') - AND n.nspname NOT LIKE 'pg\\_%' + AND n.nspname NOT LIKE 'pg!_%' ESCAPE '!' ORDER BY n.nspname """ @@ -152,7 +152,7 @@ enum PostgreSQLPrincipalQueries { r.rolconnlimit, pg_catalog.shobj_description(r.oid, 'pg_authid') FROM pg_roles r - WHERE r.rolname NOT LIKE 'pg\\_%' + WHERE r.rolname NOT LIKE 'pg!_%' ESCAPE '!' ORDER BY r.rolname """ } diff --git a/TableProTests/Plugins/LibPQStringConformanceTests.swift b/TableProTests/Plugins/LibPQStringConformanceTests.swift new file mode 100644 index 0000000000..f376342cb3 --- /dev/null +++ b/TableProTests/Plugins/LibPQStringConformanceTests.swift @@ -0,0 +1,87 @@ +// +// LibPQStringConformanceTests.swift +// TableProTests +// + +import Foundation +import Testing + +@Suite("LibPQStringConformance") +struct LibPQStringConformanceTests { + @Test("Every session turns standard_conforming_strings on") + func sessionSetupForcesStandardConformingStrings() { + #expect(LibPQStringConformance.enableStatement == "SET standard_conforming_strings TO on") + } + + @Test("The setup statement and the fallback read name the parameter the connection tracks") + func setupNamesTrackedParameter() { + #expect(LibPQStringConformance.enableStatement.lowercased().contains(LibPQStringConformance.parameterName)) + #expect(LibPQStringConformance.showQuery.lowercased().hasSuffix(LibPQStringConformance.parameterName)) + } + + @Test("Reported values parse the way the server spells them") + func parsesReportedValues() { + #expect(LibPQStringConformance.isOn("on") == true) + #expect(LibPQStringConformance.isOn("ON") == true) + #expect(LibPQStringConformance.isOn(" on ") == true) + #expect(LibPQStringConformance.isOn("off") == false) + #expect(LibPQStringConformance.isOn("Off") == false) + #expect(LibPQStringConformance.isOn(nil) == nil) + #expect(LibPQStringConformance.isOn("maybe") == nil) + } + + @Test("With the setting on, only quotes are doubled") + func escapeWhenConforming() { + #expect(LibPQStringConformance.escape("plain", standardConformingStrings: true) == "plain") + #expect(LibPQStringConformance.escape("it's", standardConformingStrings: true) == "it''s") + #expect(LibPQStringConformance.escape("back\\slash", standardConformingStrings: true) == "back\\slash") + } + + @Test("With the setting off, backslashes are doubled as well") + func escapeWhenNotConforming() { + #expect(LibPQStringConformance.escape("plain", standardConformingStrings: false) == "plain") + #expect(LibPQStringConformance.escape("it's", standardConformingStrings: false) == "it''s") + #expect(LibPQStringConformance.escape("back\\slash", standardConformingStrings: false) == "back\\\\slash") + } + + @Test("A backslash before a quote cannot close the literal when the setting is off") + func injectionPayloadStaysInsideLiteral() { + let payload = "\\'; CREATE TABLE injected (x int); --" + let escaped = LibPQStringConformance.escape(payload, standardConformingStrings: false) + #expect(escaped == "\\\\''; CREATE TABLE injected (x int); --") + #expect(Self.decodeLegacyLiteralBody(escaped) == payload) + } + + @Test("The escaped body decodes back to the original under either setting") + func roundTripsUnderBothSettings() { + let values = ["", "a", "it's", "back\\slash", "\\'", "''", "\\\\", "mixed \\' and ' and \\"] + for value in values { + let conforming = LibPQStringConformance.escape(value, standardConformingStrings: true) + #expect(conforming.replacingOccurrences(of: "''", with: "'") == value) + let legacy = LibPQStringConformance.escape(value, standardConformingStrings: false) + #expect(Self.decodeLegacyLiteralBody(legacy) == value) + } + } + + @Test("NUL characters are dropped under either setting") + func dropsNul() { + #expect(LibPQStringConformance.escape("a\0b", standardConformingStrings: true) == "ab") + #expect(LibPQStringConformance.escape("a\0b", standardConformingStrings: false) == "ab") + } + + private static func decodeLegacyLiteralBody(_ body: String) -> String { + var decoded = "" + var iterator = Array(body).makeIterator() + while let character = iterator.next() { + switch character { + case "\\": + if let next = iterator.next() { decoded.append(next) } + case "'": + if let next = iterator.next() { decoded.append(next) } + default: + decoded.append(character) + } + } + return decoded + } +} diff --git a/TableProTests/Plugins/ObjectCatalogQueryTests.swift b/TableProTests/Plugins/ObjectCatalogQueryTests.swift index 07775e9fc9..fb9c286d18 100644 --- a/TableProTests/Plugins/ObjectCatalogQueryTests.swift +++ b/TableProTests/Plugins/ObjectCatalogQueryTests.swift @@ -83,6 +83,26 @@ struct PostgreSQLObjectQueryTests { let triggers = PostgreSQLObjectQueries.triggerList(schema: "public", table: "o'brien") #expect(triggers.contains("'o''brien'")) } + + @Test("A backslash before a quote in a name becomes an E'' literal in every query") + func backslashNamesUseEscapeStringLiterals() { + let hostile = "a\\'; DROP TABLE victim; --" + let expected = "E'a\\\\''; DROP TABLE victim; --'" + + let list = PostgreSQLObjectQueries.routineList(schema: hostile, serverVersionNumber: 160_000) + #expect(list.contains("n.nspname = \(expected)")) + + let byName = PostgreSQLObjectQueries.routineDefinitionByName( + name: hostile, schema: hostile, arguments: hostile + ) + #expect(byName.contains("p.proname = \(expected)")) + #expect(byName.contains("n.nspname = \(expected)")) + #expect(byName.contains("')' = \(expected)")) + + let triggers = PostgreSQLObjectQueries.triggerList(schema: hostile, table: hostile) + #expect(triggers.contains("c.relname = \(expected)")) + #expect(triggers.contains("n.nspname = \(expected)")) + } } @Suite("MySQL Object Catalog Queries") diff --git a/project.yml b/project.yml index ab69c92a6f..72d83f9240 100644 --- a/project.yml +++ b/project.yml @@ -516,6 +516,7 @@ targets: - Plugins/PostgreSQLDriverPlugin/LibPQPendingResultDrain.swift - Plugins/PostgreSQLDriverPlugin/LibPQPluginError.swift - Plugins/PostgreSQLDriverPlugin/LibPQSSLMapping.swift + - Plugins/PostgreSQLDriverPlugin/LibPQStringConformance.swift - Plugins/PostgreSQLDriverPlugin/PostGISSpatialRewrite.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogForeignKeys.swift From c015a0e222dcf2a876ab24d9304429f3cb37afb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 08:00:49 +0700 Subject: [PATCH 24/54] fix(datagrid): key pending edits by row identity instead of display position (#2761) * fix(datagrid): key pending edits by row identity instead of display position * test(datagrid): find the Discard button in the window, not on the Touch Bar --- CHANGELOG.md | 2 + .../ChangeTracking/AnyChangeManager.swift | 27 +- .../ChangeTracking/DataChangeManager.swift | 190 +++++---- .../ChangeTracking/DataChangeModels.swift | 23 +- .../Core/ChangeTracking/PendingChanges.swift | 319 ++++++--------- .../SQLStatementGenerator.swift | 32 +- .../RowEditingCoordinator+Discard.swift | 28 +- .../RowEditingCoordinator+SaveChanges.swift | 2 +- .../Coordinators/RowEditingCoordinator.swift | 162 ++------ .../Core/DataWrite/Rewind/RewindPlanner.swift | 6 +- .../DataWrite/RowChangeStatementFactory.swift | 115 ++++-- .../DataWrite/RowWriteOperationBuilder.swift | 12 +- .../StructureChangeManager.swift | 12 +- .../Core/Scripting/ScriptingSnapshot.swift | 6 +- .../Services/Query/RowOperationsManager.swift | 234 ++++------- .../Utilities/SQL/DisplayedResultReader.swift | 6 +- .../Utilities/SQL/ResultJsonSerializer.swift | 6 +- TablePro/Models/Query/QueryTabState.swift | 14 +- TablePro/Models/Query/TableRows.swift | 15 +- .../Inspector/InspectorChangeManager.swift | 9 +- .../Main/Child/DataTabGridDelegate.swift | 5 - .../Main/Child/MainEditorContentView.swift | 4 +- .../MainContentCoordinator+Alerts.swift | 3 +- ...ContentCoordinator+NavigationHistory.swift | 5 +- ...MainContentCoordinator+RowOperations.swift | 4 - .../MainContentCoordinator+SidebarSave.swift | 2 +- .../Extensions/MainContentView+Bindings.swift | 10 +- .../MainContentView+EventHandlers.swift | 14 +- TablePro/Views/Main/MainContentView.swift | 3 - .../Results/ColumnValueFilterPopover.swift | 2 + .../Views/Results/DataGridCoordinator.swift | 16 +- TablePro/Views/Results/DataGridRowView.swift | 2 +- .../Results/DataGridView+RowActions.swift | 15 +- TablePro/Views/Results/DataGridView.swift | 2 +- .../Views/Results/DataGridViewDelegate.swift | 8 - .../Extensions/DataGridView+CellCommit.swift | 7 +- .../Extensions/DataGridView+CellPaste.swift | 2 +- .../Extensions/DataGridView+Click.swift | 4 +- .../Extensions/DataGridView+Columns.swift | 2 +- .../Extensions/DataGridView+Editing.swift | 2 +- .../Extensions/DataGridView+FillColumn.swift | 22 +- .../DataGridView+RowDecoration.swift | 4 +- .../Extensions/DataGridView+RowIdentity.swift | 32 ++ .../Extensions/DataGridView+ValueFilter.swift | 5 +- TablePro/Views/Results/ResultsJsonView.swift | 18 +- TablePro/Views/Results/RowVisualIndex.swift | 84 ++-- .../AnyChangeManagerTests.swift | 14 +- .../DataChangeManagerClickHouseTests.swift | 4 +- .../DataChangeManagerExtendedTests.swift | 316 +++++++------- .../DataChangeManagerTests.swift | 76 ++-- .../DataChangeModelsTests.swift | 20 +- .../PendingChangesReindexTests.swift | 105 ----- .../PendingChangesRowIdentityTests.swift | 136 +++++++ .../ChangeTracking/PendingChangesTests.swift | 131 +++--- ...tementGeneratorBatchDeleteScaleTests.swift | 22 +- .../SQLStatementGeneratorBinaryTests.swift | 20 +- ...QLStatementGeneratorCompositePKTests.swift | 76 ++-- ...atementGeneratorGeneratedColumnTests.swift | 34 +- .../SQLStatementGeneratorMSSQLTests.swift | 46 +-- .../SQLStatementGeneratorNoPKTests.swift | 64 +-- .../SQLStatementGeneratorOrderingTests.swift | 32 +- ...LStatementGeneratorPKRegressionTests.swift | 46 +-- ...tatementGeneratorParameterStyleTests.swift | 56 +-- .../SQLStatementGeneratorRowMatchTests.swift | 28 +- .../SQLStatementGeneratorTests.swift | 384 +++++++++--------- .../RowEditingCoordinatorJsonModeTests.swift | 2 +- ...owEditingCoordinatorValueFilterTests.swift | 149 +++++++ .../DataWrite/PluginKeyedChangesTests.swift | 73 ++++ .../RowWriteOperationBuilderTests.swift | 32 +- .../Services/RowOperationsManagerTests.swift | 139 +++++-- ...Tests.swift => UndoRowIdentityTests.swift} | 67 +-- .../DisplayedResultReaderTests.swift | 14 +- .../Utilities/ResultJsonSerializerTests.swift | 18 +- TableProTests/Helpers/TestFixtures.swift | 2 +- .../Main/CommandActionsBulkCloseTests.swift | 2 +- .../CoordinatorColumnVisibilityTests.swift | 2 +- TableProTests/Views/Main/EvictionTests.swift | 2 +- .../MainContentCoordinatorLazyLoadTests.swift | 2 +- ...MainContentCoordinatorTabSwitchTests.swift | 8 +- .../Main/QueryFailureReportingTests.swift | 2 +- .../Views/Main/TabCloseProtectionTests.swift | 2 +- .../DataGridCellFactoryPerfTests.swift | 2 +- .../Results/Extensions/FillColumnTests.swift | 16 +- .../Views/Results/ResultsJsonViewTests.swift | 16 +- .../Views/Results/RowVisualIndexTests.swift | 84 +++- ...TableViewCoordinatorRowIdentityTests.swift | 177 ++++++++ .../Results/ValueFilterChangeGuardTests.swift | 5 +- TableProUITests/ValueFilterEditUITests.swift | 155 +++++++ 88 files changed, 2269 insertions(+), 1809 deletions(-) create mode 100644 TablePro/Views/Results/Extensions/DataGridView+RowIdentity.swift delete mode 100644 TableProTests/Core/ChangeTracking/PendingChangesReindexTests.swift create mode 100644 TableProTests/Core/ChangeTracking/PendingChangesRowIdentityTests.swift create mode 100644 TableProTests/Core/Coordinators/RowEditingCoordinatorValueFilterTests.swift create mode 100644 TableProTests/Core/DataWrite/PluginKeyedChangesTests.swift rename TableProTests/Core/Services/{UndoRowIndexTests.swift => UndoRowIdentityTests.swift} (55%) create mode 100644 TableProTests/Views/Results/TableViewCoordinatorRowIdentityTests.swift create mode 100644 TableProUITests/ValueFilterEditUITests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index fdc24d3451..364e0d84c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Discard restoring a different row than the one edited under a column value filter. +- Add Row under a column value filter selecting and opening the wrong row for editing. - Data grid ignoring the theme's background, text, alternate row, NULL, boolean and row number colors. - Text past the first 64 KB of a UTF-16 SQL import arriving byte-swapped. - SQL import failing on a file whose encoding is not UTF-8 when a character lands on a 64 KB boundary. diff --git a/TablePro/Core/ChangeTracking/AnyChangeManager.swift b/TablePro/Core/ChangeTracking/AnyChangeManager.swift index 9ca4f262ad..5f41912018 100644 --- a/TablePro/Core/ChangeTracking/AnyChangeManager.swift +++ b/TablePro/Core/ChangeTracking/AnyChangeManager.swift @@ -8,19 +8,18 @@ protocol ChangeManaging: AnyObject { var reloadVersion: Int { get } var canRedo: Bool { get } var rowChanges: [RowChange] { get } - var insertedRowIndices: Set { get } + var insertedRowIDs: Set { get } var generatedColumns: Set { get } - func isRowDeleted(_ rowIndex: Int) -> Bool + func isRowDeleted(_ rowID: RowID) -> Bool func recordCellChange( - rowIndex: Int, + rowID: RowID, columnIndex: Int, columnName: String, oldValue: PluginCellValue, newValue: PluginCellValue, originalRow: [PluginCellValue]? ) - func undoRowDeletion(rowIndex: Int) - func undoRowInsertion(rowIndex: Int) + func undoRowDeletion(rowID: RowID) } /// Only the data grid tracks server-computed columns; the structure and @@ -38,15 +37,15 @@ final class AnyChangeManager { var reloadVersion: Int { wrapped.reloadVersion } var canRedo: Bool { wrapped.canRedo } var rowChanges: [RowChange] { wrapped.rowChanges } - var insertedRowIndices: Set { wrapped.insertedRowIndices } + var insertedRowIDs: Set { wrapped.insertedRowIDs } var generatedColumns: Set { wrapped.generatedColumns } - func isRowDeleted(_ rowIndex: Int) -> Bool { - wrapped.isRowDeleted(rowIndex) + func isRowDeleted(_ rowID: RowID) -> Bool { + wrapped.isRowDeleted(rowID) } func recordCellChange( - rowIndex: Int, + rowID: RowID, columnIndex: Int, columnName: String, oldValue: PluginCellValue, @@ -54,7 +53,7 @@ final class AnyChangeManager { originalRow: [PluginCellValue] ) { wrapped.recordCellChange( - rowIndex: rowIndex, + rowID: rowID, columnIndex: columnIndex, columnName: columnName, oldValue: oldValue, @@ -63,12 +62,8 @@ final class AnyChangeManager { ) } - func undoRowDeletion(rowIndex: Int) { - wrapped.undoRowDeletion(rowIndex: rowIndex) - } - - func undoRowInsertion(rowIndex: Int) { - wrapped.undoRowInsertion(rowIndex: rowIndex) + func undoRowDeletion(rowID: RowID) { + wrapped.undoRowDeletion(rowID: rowID) } init(_ manager: any ChangeManaging) { diff --git a/TablePro/Core/ChangeTracking/DataChangeManager.swift b/TablePro/Core/ChangeTracking/DataChangeManager.swift index 30942e2781..97e482758b 100644 --- a/TablePro/Core/ChangeTracking/DataChangeManager.swift +++ b/TablePro/Core/ChangeTracking/DataChangeManager.swift @@ -47,8 +47,8 @@ final class DataChangeManager: ChangeManaging { var changes: [RowChange] { pending.changes } var rowChanges: [RowChange] { pending.changes } - var insertedRowIndices: Set { pending.insertedRowIndices } - var deletedRowIndices: Set { pending.deletedRowIndices } + var insertedRowIDs: Set { pending.insertedRowIDs } + var deletedRowIDs: Set { pending.deletedRowIDs } var tableName: String = "" var schemaName: String? @@ -148,7 +148,7 @@ final class DataChangeManager: ChangeManaging { // MARK: - Change Tracking func recordCellChange( - rowIndex: Int, + rowID: RowID, columnIndex: Int, columnName: String, oldValue: PluginCellValue, @@ -167,7 +167,7 @@ final class DataChangeManager: ChangeManaging { return } let recorded = pending.recordCellChange( - rowIndex: rowIndex, + rowID: rowID, columnIndex: columnIndex, columnName: columnName, oldValue: oldValue, @@ -180,30 +180,30 @@ final class DataChangeManager: ChangeManaging { } registerUndo(actionName: String(localized: "Edit Cell")) { target in target.applyDataUndo(.cellEdit( - rowIndex: rowIndex, columnIndex: columnIndex, columnName: columnName, + rowID: rowID, columnIndex: columnIndex, columnName: columnName, previousValue: oldValue, newValue: newValue, originalRow: originalRow )) } hasChanges = !pending.isEmpty } - func recordRowDeletion(rowIndex: Int, originalRow: [PluginCellValue]) { - pending.recordRowDeletion(rowIndex: rowIndex, originalRow: originalRow) + func recordRowDeletion(rowID: RowID, originalRow: [PluginCellValue]) { + pending.recordRowDeletion(rowID: rowID, originalRow: originalRow) registerUndo(actionName: String(localized: "Delete Row")) { target in - target.applyDataUndo(.rowDeletion(rowIndex: rowIndex, originalRow: originalRow)) + target.applyDataUndo(.rowDeletion(rowID: rowID, originalRow: originalRow)) } hasChanges = true } - func recordBatchRowDeletion(rows: [(rowIndex: Int, originalRow: [PluginCellValue])]) { + func recordBatchRowDeletion(rows: [(rowID: RowID, originalRow: [PluginCellValue])]) { guard rows.count > 1 else { if let row = rows.first { - recordRowDeletion(rowIndex: row.rowIndex, originalRow: row.originalRow) + recordRowDeletion(rowID: row.rowID, originalRow: row.originalRow) } return } - for (rowIndex, originalRow) in rows { - pending.recordRowDeletion(rowIndex: rowIndex, originalRow: originalRow) + for (rowID, originalRow) in rows { + pending.recordRowDeletion(rowID: rowID, originalRow: originalRow) } let batchData = rows registerUndo(actionName: String(localized: "Delete Rows")) { target in @@ -212,32 +212,29 @@ final class DataChangeManager: ChangeManaging { hasChanges = true } - func recordRowInsertion(rowIndex: Int, values: [PluginCellValue]) { - pending.recordRowInsertion(rowIndex: rowIndex, values: values) + func recordRowInsertion(rowID: RowID, values: [PluginCellValue]) { + pending.recordRowInsertion(rowID: rowID, values: values) registerUndo(actionName: String(localized: "Insert Row")) { target in - target.applyDataUndo(.rowInsertion(rowIndex: rowIndex)) + target.applyDataUndo(.rowInsertion(rowID: rowID)) } hasChanges = true } // MARK: - Undo Operations - func undoRowDeletion(rowIndex: Int) { - guard pending.undoRowDeletion(rowIndex: rowIndex) else { return } + func undoRowDeletion(rowID: RowID) { + guard pending.undoRowDeletion(rowID: rowID) else { return } hasChanges = !pending.isEmpty } - func undoRowInsertion(rowIndex: Int) { - guard pending.undoRowInsertion(rowIndex: rowIndex) else { return } - hasChanges = !pending.isEmpty - } - - func undoBatchRowInsertion(rowIndices: [Int]) { - let validRows = rowIndices.filter { pending.isRowInserted($0) } + func undoBatchRowInsertion(rows: [InsertedRowLocation]) { + let validRows = rows.filter { pending.isRowInserted($0.rowID) } guard !validRows.isEmpty else { return } - let rowValues = pending.undoBatchRowInsertion(rowIndices: validRows, columnCount: columns.count) + let rowValues = pending.undoBatchRowInsertion( + rowIDs: validRows.map(\.rowID), columnCount: columns.count + ) registerUndo(actionName: String(localized: "Insert Rows")) { target in - target.applyDataUndo(.batchRowInsertion(rowIndices: validRows, rowValues: rowValues)) + target.applyDataUndo(.batchRowInsertion(rows: validRows, rowValues: rowValues)) } hasChanges = !pending.isEmpty } @@ -246,24 +243,24 @@ final class DataChangeManager: ChangeManaging { private func applyDataUndo(_ action: UndoAction) { switch action { - case .cellEdit(let rowIndex, let columnIndex, let columnName, let previousValue, let newValue, let originalRow): + case .cellEdit(let rowID, let columnIndex, let columnName, let previousValue, let newValue, let originalRow): applyCellEditUndo( - rowIndex: rowIndex, columnIndex: columnIndex, columnName: columnName, + rowID: rowID, columnIndex: columnIndex, columnName: columnName, previousValue: previousValue, newValue: newValue, originalRow: originalRow, action: action ) - case .rowInsertion(let rowIndex): - applyRowInsertionUndo(rowIndex: rowIndex, action: action) + case .rowInsertion(let rowID): + applyRowInsertionUndo(rowID: rowID, action: action) - case .rowDeletion(let rowIndex, let originalRow): - applyRowDeletionUndo(rowIndex: rowIndex, originalRow: originalRow, action: action) + case .rowDeletion(let rowID, let originalRow): + applyRowDeletionUndo(rowID: rowID, originalRow: originalRow, action: action) case .batchRowDeletion(let rows): applyBatchRowDeletionUndo(rows: rows, action: action) - case .batchRowInsertion(let rowIndices, let rowValues): - applyBatchRowInsertionUndo(rowIndices: rowIndices, rowValues: rowValues, action: action) + case .batchRowInsertion(let rows, let rowValues): + applyBatchRowInsertionUndo(rows: rows, rowValues: rowValues, action: action) } hasChanges = !pending.isEmpty @@ -274,79 +271,76 @@ final class DataChangeManager: ChangeManaging { } private func applyCellEditUndo( - rowIndex: Int, columnIndex: Int, columnName: String, + rowID: RowID, columnIndex: Int, columnName: String, previousValue: PluginCellValue, newValue: PluginCellValue, originalRow: [PluginCellValue]?, action: UndoAction ) { registerUndo(actionName: String(localized: "Edit Cell")) { target in target.applyDataUndo(.cellEdit( - rowIndex: rowIndex, columnIndex: columnIndex, columnName: columnName, + rowID: rowID, columnIndex: columnIndex, columnName: columnName, previousValue: newValue, newValue: previousValue, originalRow: originalRow )) } - if let updateChange = pending.change(forRow: rowIndex, type: .update) { + if let updateChange = pending.change(forRow: rowID, type: .update) { if updateChange.cellChanges.contains(where: { $0.columnIndex == columnIndex }) { pending.revertUpdateCell( - rowIndex: rowIndex, columnIndex: columnIndex, + rowID: rowID, columnIndex: columnIndex, columnName: columnName, previousValue: previousValue ) } - } else if pending.change(forRow: rowIndex, type: .insert) != nil { + } else if pending.change(forRow: rowID, type: .insert) != nil { pending.updateInsertedCellDirectly( - rowIndex: rowIndex, columnIndex: columnIndex, + rowID: rowID, columnIndex: columnIndex, columnName: columnName, newValue: previousValue ) } else { pending.reapplyCellChange( - rowIndex: rowIndex, + rowID: rowID, columnIndex: columnIndex, columnName: columnName, originalDBValue: newValue, newValue: previousValue, originalRow: originalRow ) } lastUndoResult = UndoResult( - action: action, needsRowRemoval: false, needsRowRestore: false, restoreRow: nil, - delta: .cellChanged(row: rowIndex, column: columnIndex) + action: action, needsRowRemoval: false, needsRowRestore: false, restoreRow: nil ) } - private func applyRowInsertionUndo(rowIndex: Int, action: UndoAction) { - let savedValues = pending.savedInsertedValues(forRow: rowIndex) + private func applyRowInsertionUndo(rowID: RowID, action: UndoAction) { + let savedValues = pending.savedInsertedValues(forRow: rowID) registerUndo(actionName: String(localized: "Insert Row")) { [savedValues] target in if let savedValues { - target.pending.restoreInsertedValues(forRow: rowIndex, values: savedValues) + target.pending.restoreInsertedValues(forRow: rowID, values: savedValues) } - target.applyDataUndo(.rowInsertion(rowIndex: rowIndex)) + target.applyDataUndo(.rowInsertion(rowID: rowID)) } - if pending.isRowInserted(rowIndex) { - _ = pending.undoRowInsertion(rowIndex: rowIndex) + if pending.isRowInserted(rowID) { + _ = pending.undoRowInsertion(rowID: rowID) lastUndoResult = UndoResult( - action: action, needsRowRemoval: true, needsRowRestore: false, restoreRow: nil, - delta: .rowsRemoved(IndexSet(integer: rowIndex)) + action: action, needsRowRemoval: true, needsRowRestore: false, restoreRow: nil ) } else { - pending.reinsertRow(rowIndex: rowIndex, columns: columns, savedValues: savedValues) + pending.reinsertRow(rowID: rowID, columns: columns, savedValues: savedValues) lastUndoResult = UndoResult( - action: action, needsRowRemoval: false, needsRowRestore: true, restoreRow: savedValues, - delta: .rowsInserted(IndexSet(integer: rowIndex)) + action: action, needsRowRemoval: false, needsRowRestore: true, restoreRow: savedValues ) } } - private func applyRowDeletionUndo(rowIndex: Int, originalRow: [PluginCellValue], action: UndoAction) { + private func applyRowDeletionUndo(rowID: RowID, originalRow: [PluginCellValue], action: UndoAction) { registerUndo(actionName: String(localized: "Delete Row")) { target in - target.applyDataUndo(.rowDeletion(rowIndex: rowIndex, originalRow: originalRow)) + target.applyDataUndo(.rowDeletion(rowID: rowID, originalRow: originalRow)) } - if pending.isRowDeleted(rowIndex) { - _ = pending.undoRowDeletion(rowIndex: rowIndex) + if pending.isRowDeleted(rowID) { + _ = pending.undoRowDeletion(rowID: rowID) lastUndoResult = UndoResult( action: action, needsRowRemoval: false, needsRowRestore: true, restoreRow: originalRow, delta: .fullReplace ) } else { - pending.reapplyRowDeletion(rowIndex: rowIndex, originalRow: originalRow) + pending.reapplyRowDeletion(rowID: rowID, originalRow: originalRow) lastUndoResult = UndoResult( action: action, needsRowRemoval: true, needsRowRestore: false, restoreRow: nil, delta: .fullReplace @@ -355,24 +349,24 @@ final class DataChangeManager: ChangeManaging { } private func applyBatchRowDeletionUndo( - rows: [(rowIndex: Int, originalRow: [PluginCellValue])], action: UndoAction + rows: [(rowID: RowID, originalRow: [PluginCellValue])], action: UndoAction ) { registerUndo(actionName: String(localized: "Delete Rows")) { target in target.applyDataUndo(.batchRowDeletion(rows: rows)) } - let isUndo = rows.contains { pending.isRowDeleted($0.rowIndex) } + let isUndo = rows.contains { pending.isRowDeleted($0.rowID) } if isUndo { - for (rowIndex, _) in rows.reversed() { - _ = pending.undoRowDeletion(rowIndex: rowIndex) + for (rowID, _) in rows.reversed() { + _ = pending.undoRowDeletion(rowID: rowID) } lastUndoResult = UndoResult( action: action, needsRowRemoval: false, needsRowRestore: true, restoreRow: nil, delta: .fullReplace ) } else { - for (rowIndex, originalRow) in rows { - pending.reapplyRowDeletion(rowIndex: rowIndex, originalRow: originalRow) + for (rowID, originalRow) in rows { + pending.reapplyRowDeletion(rowID: rowID, originalRow: originalRow) } lastUndoResult = UndoResult( action: action, needsRowRemoval: true, needsRowRestore: false, restoreRow: nil, @@ -382,25 +376,23 @@ final class DataChangeManager: ChangeManaging { } private func applyBatchRowInsertionUndo( - rowIndices: [Int], rowValues: [[PluginCellValue]], action: UndoAction + rows: [InsertedRowLocation], rowValues: [[PluginCellValue]], action: UndoAction ) { registerUndo(actionName: String(localized: "Insert Rows")) { target in - target.applyDataUndo(.batchRowInsertion(rowIndices: rowIndices, rowValues: rowValues)) + target.applyDataUndo(.batchRowInsertion(rows: rows, rowValues: rowValues)) } - let firstInserted = rowIndices.first.map { pending.isRowInserted($0) } ?? false - let indices = IndexSet(rowIndices) + let rowIDs = rows.map(\.rowID) + let firstInserted = rowIDs.first.map { pending.isRowInserted($0) } ?? false if firstInserted { - _ = pending.undoBatchRowInsertion(rowIndices: rowIndices, columnCount: columns.count) + _ = pending.undoBatchRowInsertion(rowIDs: rowIDs, columnCount: columns.count) lastUndoResult = UndoResult( - action: action, needsRowRemoval: true, needsRowRestore: false, restoreRow: nil, - delta: .rowsRemoved(indices) + action: action, needsRowRemoval: true, needsRowRestore: false, restoreRow: nil ) } else { - pending.reinsertBatch(rowIndices: rowIndices, rowValues: rowValues, columns: columns) + pending.reinsertBatch(rowIDs: rowIDs, rowValues: rowValues, columns: columns) lastUndoResult = UndoResult( - action: action, needsRowRemoval: false, needsRowRestore: true, restoreRow: nil, - delta: .rowsInserted(indices) + action: action, needsRowRemoval: false, needsRowRestore: true, restoreRow: nil ) } } @@ -411,22 +403,22 @@ final class DataChangeManager: ChangeManaging { try generateSQL( for: pending.changes, insertedRowData: pending.insertedRowData, - deletedRowIndices: pending.deletedRowIndices, - insertedRowIndices: pending.insertedRowIndices + deletedRowIDs: pending.deletedRowIDs, + insertedRowIDs: pending.insertedRowIDs ) } func generateSQL( for changes: [RowChange], - insertedRowData: [Int: [PluginCellValue]] = [:], - deletedRowIndices: Set = [], - insertedRowIndices: Set = [] + insertedRowData: [RowID: [PluginCellValue]] = [:], + deletedRowIDs: Set = [], + insertedRowIDs: Set = [] ) throws -> [ParameterizedStatement] { try statementFactory().statements( for: changes, insertedRowData: insertedRowData, - deletedRowIndices: deletedRowIndices, - insertedRowIndices: insertedRowIndices + deletedRowIDs: deletedRowIDs, + insertedRowIDs: insertedRowIDs ) } @@ -440,8 +432,8 @@ final class DataChangeManager: ChangeManaging { let operations = RowWriteOperationBuilder.operations( from: pending.changes, insertedRowData: pending.insertedRowData, - deletedRowIndices: pending.deletedRowIndices, - insertedRowIndices: pending.insertedRowIndices, + deletedRowIDs: pending.deletedRowIDs, + insertedRowIDs: pending.insertedRowIDs, target: DataWriteTarget(database: database, schema: schema, table: tableName), columns: columns, primaryKeyColumns: primaryKeyColumns, @@ -452,8 +444,8 @@ final class DataChangeManager: ChangeManaging { if let attributed = try factory.attributedStatements( for: pending.changes, insertedRowData: pending.insertedRowData, - deletedRowIndices: pending.deletedRowIndices, - insertedRowIndices: pending.insertedRowIndices + deletedRowIDs: pending.deletedRowIDs, + insertedRowIDs: pending.insertedRowIDs ) { let steps = attributed.map { DataWriteStep( @@ -469,8 +461,8 @@ final class DataChangeManager: ChangeManaging { let steps = try factory.statements( for: pending.changes, insertedRowData: pending.insertedRowData, - deletedRowIndices: pending.deletedRowIndices, - insertedRowIndices: pending.insertedRowIndices + deletedRowIDs: pending.deletedRowIDs, + insertedRowIDs: pending.insertedRowIDs ).map { DataWriteStep(kind: .rowWrite, statement: $0, expectedRowCount: nil, tableName: tableName) } @@ -495,12 +487,12 @@ final class DataChangeManager: ChangeManaging { // MARK: - Actions - func getOriginalValues() -> [(rowIndex: Int, columnIndex: Int, value: PluginCellValue)] { - var originals: [(rowIndex: Int, columnIndex: Int, value: PluginCellValue)] = [] + func getOriginalValues() -> [(rowID: RowID, columnIndex: Int, value: PluginCellValue)] { + var originals: [(rowID: RowID, columnIndex: Int, value: PluginCellValue)] = [] for change in pending.changes where change.type == .update { for cellChange in change.cellChanges { originals.append(( - rowIndex: change.rowIndex, + rowID: change.rowID, columnIndex: cellChange.columnIndex, value: cellChange.oldValue )) @@ -542,19 +534,19 @@ final class DataChangeManager: ChangeManaging { // MARK: - O(1) Lookups - func isRowDeleted(_ rowIndex: Int) -> Bool { - pending.isRowDeleted(rowIndex) + func isRowDeleted(_ rowID: RowID) -> Bool { + pending.isRowDeleted(rowID) } - func isRowInserted(_ rowIndex: Int) -> Bool { - pending.isRowInserted(rowIndex) + func isRowInserted(_ rowID: RowID) -> Bool { + pending.isRowInserted(rowID) } - func isCellModified(rowIndex: Int, columnIndex: Int) -> Bool { - pending.isCellModified(rowIndex: rowIndex, columnIndex: columnIndex) + func isCellModified(rowID: RowID, columnIndex: Int) -> Bool { + pending.isCellModified(rowID: rowID, columnIndex: columnIndex) } - func getModifiedColumnsForRow(_ rowIndex: Int) -> Set { - pending.modifiedColumns(forRow: rowIndex) + func getModifiedColumnsForRow(_ rowID: RowID) -> Set { + pending.modifiedColumns(forRow: rowID) } } diff --git a/TablePro/Core/ChangeTracking/DataChangeModels.swift b/TablePro/Core/ChangeTracking/DataChangeModels.swift index ad37d3b007..1ef76b0850 100644 --- a/TablePro/Core/ChangeTracking/DataChangeModels.swift +++ b/TablePro/Core/ChangeTracking/DataChangeModels.swift @@ -35,7 +35,7 @@ struct CellChange: Identifiable, Equatable { struct RowChange: Identifiable, Equatable { let id: UUID - var rowIndex: Int + let rowID: RowID let type: ChangeType var cellChanges: [CellChange] let originalRow: [PluginCellValue]? @@ -49,14 +49,14 @@ struct RowChange: Identifiable, Equatable { var sequence: Int init( - rowIndex: Int, + rowID: RowID, type: ChangeType, cellChanges: [CellChange] = [], originalRow: [PluginCellValue]? = nil, sequence: Int = 0 ) { self.id = UUID() - self.rowIndex = rowIndex + self.rowID = rowID self.type = type self.cellChanges = cellChanges self.originalRow = originalRow @@ -65,21 +65,26 @@ struct RowChange: Identifiable, Equatable { } struct RowChangeKey: Hashable { - let rowIndex: Int + let rowID: RowID let type: ChangeType } +struct InsertedRowLocation { + let rowID: RowID + let storageIndex: Int +} + enum UndoAction { case cellEdit( - rowIndex: Int, + rowID: RowID, columnIndex: Int, columnName: String, previousValue: PluginCellValue, newValue: PluginCellValue, originalRow: [PluginCellValue]? ) - case rowInsertion(rowIndex: Int) - case rowDeletion(rowIndex: Int, originalRow: [PluginCellValue]) - case batchRowDeletion(rows: [(rowIndex: Int, originalRow: [PluginCellValue])]) - case batchRowInsertion(rowIndices: [Int], rowValues: [[PluginCellValue]]) + case rowInsertion(rowID: RowID) + case rowDeletion(rowID: RowID, originalRow: [PluginCellValue]) + case batchRowDeletion(rows: [(rowID: RowID, originalRow: [PluginCellValue])]) + case batchRowInsertion(rows: [InsertedRowLocation], rowValues: [[PluginCellValue]]) } diff --git a/TablePro/Core/ChangeTracking/PendingChanges.swift b/TablePro/Core/ChangeTracking/PendingChanges.swift index 6bc949235c..28dd97c47f 100644 --- a/TablePro/Core/ChangeTracking/PendingChanges.swift +++ b/TablePro/Core/ChangeTracking/PendingChanges.swift @@ -4,7 +4,7 @@ // // Value type holding all uncommitted edits to a result set. // Owns the consistency invariants between `changes`, `changeIndex`, -// `deletedRowIndices`, `insertedRowIndices`, `modifiedCells`, and +// `deletedRowIDs`, `insertedRowIDs`, `modifiedCells`, and // `insertedRowData`. Callers mutate through methods that maintain // the cross-collection state. // @@ -14,15 +14,15 @@ import TableProPluginKit struct PendingChanges: Equatable { private(set) var changes: [RowChange] = [] - private(set) var deletedRowIndices: Set = [] + private(set) var deletedRowIDs: Set = [] /// Stamped onto every change so statement generation can recover the order the user worked in. /// `changes` cannot carry that order itself: a cancelled change is removed by swapping the last /// element into its slot. private var nextSequence = 0 - private(set) var insertedRowIndices: Set = [] - private(set) var modifiedCells: [Int: Set] = [:] - private(set) var insertedRowData: [Int: [PluginCellValue]] = [:] + private(set) var insertedRowIDs: Set = [] + private(set) var modifiedCells: [RowID: Set] = [:] + private(set) var insertedRowData: [RowID: [PluginCellValue]] = [:] private var changeIndex: [RowChangeKey: Int] = [:] @@ -31,24 +31,24 @@ struct PendingChanges: Equatable { // MARK: - Read - func isRowDeleted(_ rowIndex: Int) -> Bool { - deletedRowIndices.contains(rowIndex) + func isRowDeleted(_ rowID: RowID) -> Bool { + deletedRowIDs.contains(rowID) } - func isRowInserted(_ rowIndex: Int) -> Bool { - insertedRowIndices.contains(rowIndex) + func isRowInserted(_ rowID: RowID) -> Bool { + insertedRowIDs.contains(rowID) } - func isCellModified(rowIndex: Int, columnIndex: Int) -> Bool { - modifiedCells[rowIndex]?.contains(columnIndex) == true + func isCellModified(rowID: RowID, columnIndex: Int) -> Bool { + modifiedCells[rowID]?.contains(columnIndex) == true } - func modifiedColumns(forRow rowIndex: Int) -> Set { - modifiedCells[rowIndex] ?? [] + func modifiedColumns(forRow rowID: RowID) -> Set { + modifiedCells[rowID] ?? [] } - func change(forRow rowIndex: Int, type: ChangeType) -> RowChange? { - guard let idx = changeIndex[RowChangeKey(rowIndex: rowIndex, type: type)] else { return nil } + func change(forRow rowID: RowID, type: ChangeType) -> RowChange? { + guard let idx = changeIndex[RowChangeKey(rowID: rowID, type: type)] else { return nil } return changes[idx] } @@ -58,7 +58,7 @@ struct PendingChanges: Equatable { /// Returns the result so the caller can decide whether to register undo. @discardableResult mutating func recordCellChange( - rowIndex: Int, + rowID: RowID, columnIndex: Int, columnName: String, oldValue: PluginCellValue, @@ -67,7 +67,7 @@ struct PendingChanges: Equatable { ) -> Bool { if oldValue == newValue { return rollbackCellIfMatchesOriginal( - rowIndex: rowIndex, columnIndex: columnIndex, restoredValue: newValue + rowID: rowID, columnIndex: columnIndex, restoredValue: newValue ) } @@ -78,102 +78,91 @@ struct PendingChanges: Equatable { newValue: newValue ) - if let insertIdx = changeIndex[RowChangeKey(rowIndex: rowIndex, type: .insert)] { + if let insertIdx = changeIndex[RowChangeKey(rowID: rowID, type: .insert)] { updateInsertedCell(at: insertIdx, columnIndex: columnIndex, columnName: columnName, newValue: newValue) return true } - let updateKey = RowChangeKey(rowIndex: rowIndex, type: .update) + let updateKey = RowChangeKey(rowID: rowID, type: .update) if let updateIdx = changeIndex[updateKey] { mergeUpdateCell(at: updateIdx, cellChange: cellChange) } else { let row = RowChange( - rowIndex: rowIndex, type: .update, + rowID: rowID, type: .update, cellChanges: [cellChange], originalRow: originalRow ) changes.append(row) changeIndex[updateKey] = changes.count - 1 - modifiedCells[rowIndex, default: []].insert(columnIndex) + modifiedCells[rowID, default: []].insert(columnIndex) } return true } - mutating func recordRowDeletion(rowIndex: Int, originalRow: [PluginCellValue]) { - guard !deletedRowIndices.contains(rowIndex) else { return } - removeChange(rowIndex: rowIndex, type: .update) - modifiedCells.removeValue(forKey: rowIndex) - appendChange(RowChange(rowIndex: rowIndex, type: .delete, originalRow: originalRow)) - deletedRowIndices.insert(rowIndex) + mutating func recordRowDeletion(rowID: RowID, originalRow: [PluginCellValue]) { + guard !deletedRowIDs.contains(rowID) else { return } + removeChange(rowID: rowID, type: .update) + modifiedCells.removeValue(forKey: rowID) + appendChange(RowChange(rowID: rowID, type: .delete, originalRow: originalRow)) + deletedRowIDs.insert(rowID) } - mutating func recordRowInsertion(rowIndex: Int, values: [PluginCellValue]) { - guard !insertedRowIndices.contains(rowIndex) else { - insertedRowData[rowIndex] = values + mutating func recordRowInsertion(rowID: RowID, values: [PluginCellValue]) { + guard !insertedRowIDs.contains(rowID) else { + insertedRowData[rowID] = values return } - insertedRowData[rowIndex] = values - appendChange(RowChange(rowIndex: rowIndex, type: .insert, cellChanges: [])) - insertedRowIndices.insert(rowIndex) + insertedRowData[rowID] = values + appendChange(RowChange(rowID: rowID, type: .insert, cellChanges: [])) + insertedRowIDs.insert(rowID) } // MARK: - Mutate (cancelling pending edits) - mutating func undoRowDeletion(rowIndex: Int) -> Bool { - guard deletedRowIndices.contains(rowIndex) else { return false } - removeChange(rowIndex: rowIndex, type: .delete) - deletedRowIndices.remove(rowIndex) + mutating func undoRowDeletion(rowID: RowID) -> Bool { + guard deletedRowIDs.contains(rowID) else { return false } + removeChange(rowID: rowID, type: .delete) + deletedRowIDs.remove(rowID) return true } - mutating func undoRowInsertion(rowIndex: Int) -> Bool { - guard insertedRowIndices.contains(rowIndex) else { return false } - - removeChange(rowIndex: rowIndex, type: .insert) - insertedRowIndices.remove(rowIndex) - insertedRowData.removeValue(forKey: rowIndex) - - shiftRowIndicesDown(at: rowIndex) + mutating func undoRowInsertion(rowID: RowID) -> Bool { + guard insertedRowIDs.contains(rowID) else { return false } + removeChange(rowID: rowID, type: .insert) + insertedRowIDs.remove(rowID) + insertedRowData.removeValue(forKey: rowID) return true } /// Undo a batch of inserted rows. Returns the saved values for each row in the same order. - mutating func undoBatchRowInsertion(rowIndices: [Int], columnCount: Int) -> [[PluginCellValue]] { - let validRows = rowIndices.filter { insertedRowIndices.contains($0) } + mutating func undoBatchRowInsertion(rowIDs: [RowID], columnCount: Int) -> [[PluginCellValue]] { + let validRows = rowIDs.filter { insertedRowIDs.contains($0) } /// `insertedRowData` holds the whole row. `cellChanges` holds only the columns the user /// typed, so rebuilding from it drops the untouched ones and slides the rest left: a name /// typed into the third column comes back in the first. - let rowValues = validRows.map { rowIndex in - insertedRowData[rowIndex] ?? Array(repeating: PluginCellValue.null, count: columnCount) + let rowValues = validRows.map { rowID in + insertedRowData[rowID] ?? Array(repeating: PluginCellValue.null, count: columnCount) } - for rowIndex in validRows { - removeChange(rowIndex: rowIndex, type: .insert) - insertedRowIndices.remove(rowIndex) - insertedRowData.removeValue(forKey: rowIndex) + for rowID in validRows { + _ = undoRowInsertion(rowID: rowID) } - - shiftRowIndicesDown(atSortedRows: validRows.sorted()) return rowValues } // MARK: - Replay (driven by NSUndoManager invocation) /// Re-apply a deletion during undo replay (skips undo registration). - mutating func reapplyRowDeletion(rowIndex: Int, originalRow: [PluginCellValue]) { - guard !deletedRowIndices.contains(rowIndex) else { return } - removeChange(rowIndex: rowIndex, type: .update) - modifiedCells.removeValue(forKey: rowIndex) - appendChange(RowChange(rowIndex: rowIndex, type: .delete, originalRow: originalRow)) - deletedRowIndices.insert(rowIndex) + mutating func reapplyRowDeletion(rowID: RowID, originalRow: [PluginCellValue]) { + recordRowDeletion(rowID: rowID, originalRow: originalRow) } /// Re-apply a cell edit during undo replay (skips undo registration). /// `originalDBValue` is the cell's value in the unmodified database row. /// It must be preserved so that a later collapse compares correctly. mutating func reapplyCellChange( - rowIndex: Int, + rowID: RowID, columnIndex: Int, columnName: String, originalDBValue: PluginCellValue, @@ -187,55 +176,52 @@ struct PendingChanges: Equatable { newValue: newValue ) - if let insertIdx = changeIndex[RowChangeKey(rowIndex: rowIndex, type: .insert)] { + if let insertIdx = changeIndex[RowChangeKey(rowID: rowID, type: .insert)] { updateInsertedCell(at: insertIdx, columnIndex: columnIndex, columnName: columnName, newValue: newValue) return } - let updateKey = RowChangeKey(rowIndex: rowIndex, type: .update) + let updateKey = RowChangeKey(rowID: rowID, type: .update) if let updateIdx = changeIndex[updateKey] { mergeUpdateCell(at: updateIdx, cellChange: cellChange) } else { let row = RowChange( - rowIndex: rowIndex, type: .update, + rowID: rowID, type: .update, cellChanges: [cellChange], originalRow: originalRow ) changes.append(row) changeIndex[updateKey] = changes.count - 1 - modifiedCells[rowIndex, default: []].insert(columnIndex) + modifiedCells[rowID, default: []].insert(columnIndex) } } - /// Replace an inserted row's cell value during undo replay (no shift, no undo). + /// Replace an inserted row's cell value during undo replay (no undo). mutating func updateInsertedCellDirectly( - rowIndex: Int, + rowID: RowID, columnIndex: Int, columnName: String, newValue: PluginCellValue ) { - guard let insertIdx = changeIndex[RowChangeKey(rowIndex: rowIndex, type: .insert)] else { return } + guard let insertIdx = changeIndex[RowChangeKey(rowID: rowID, type: .insert)] else { return } updateInsertedCell(at: insertIdx, columnIndex: columnIndex, columnName: columnName, newValue: newValue) } /// Restore a cell's value during undo replay when an existing change matches. mutating func revertUpdateCell( - rowIndex: Int, + rowID: RowID, columnIndex: Int, columnName: String, previousValue: PluginCellValue ) { - guard let updateIdx = changeIndex[RowChangeKey(rowIndex: rowIndex, type: .update)], + guard let updateIdx = changeIndex[RowChangeKey(rowID: rowID, type: .update)], let cellIdx = changes[updateIdx].cellChanges.firstIndex(where: { $0.columnIndex == columnIndex }) else { return } let originalOldValue = changes[updateIdx].cellChanges[cellIdx].oldValue if previousValue == originalOldValue { changes[updateIdx].cellChanges.remove(at: cellIdx) - modifiedCells[rowIndex]?.remove(columnIndex) - if modifiedCells[rowIndex]?.isEmpty == true { - modifiedCells.removeValue(forKey: rowIndex) - } + removeModifiedCell(rowID: rowID, columnIndex: columnIndex) if changes[updateIdx].cellChanges.isEmpty { removeChangeAt(updateIdx) } @@ -250,31 +236,25 @@ struct PendingChanges: Equatable { } /// Insert a synthetic .insert RowChange for undo replay (e.g., after redoing a deletion's undo). - mutating func reinsertRow(rowIndex: Int, columns: [String], savedValues: [PluginCellValue]?) { - shiftRowIndicesUp(from: rowIndex) - insertedRowIndices.insert(rowIndex) + mutating func reinsertRow(rowID: RowID, columns: [String], savedValues: [PluginCellValue]?) { + insertedRowIDs.insert(rowID) let cellChanges = columns.enumerated().map { index, columnName in CellChange( columnIndex: index, columnName: columnName, oldValue: nil, newValue: savedValues?[safe: index] ?? nil ) } - appendChange(RowChange(rowIndex: rowIndex, type: .insert, cellChanges: cellChanges)) + appendChange(RowChange(rowID: rowID, type: .insert, cellChanges: cellChanges)) if let savedValues { - insertedRowData[rowIndex] = savedValues + insertedRowData[rowID] = savedValues } } /// Insert a batch of rows (for undo replay of a batch deletion's undo). mutating func reinsertBatch( - rowIndices: [Int], rowValues: [[PluginCellValue]], columns: [String] + rowIDs: [RowID], rowValues: [[PluginCellValue]], columns: [String] ) { - for rowIndex in rowIndices.sorted() { - shiftRowIndicesUp(from: rowIndex) - } - for (index, rowIndex) in rowIndices.enumerated().reversed() { - guard index < rowValues.count else { continue } - let values = rowValues[index] + for (rowID, values) in zip(rowIDs, rowValues) { let cellChanges = values.enumerated().map { colIndex, value in CellChange( columnIndex: colIndex, @@ -282,21 +262,20 @@ struct PendingChanges: Equatable { oldValue: nil, newValue: value ) } - appendChange(RowChange(rowIndex: rowIndex, type: .insert, cellChanges: cellChanges)) - insertedRowIndices.insert(rowIndex) - insertedRowData[rowIndex] = values + appendChange(RowChange(rowID: rowID, type: .insert, cellChanges: cellChanges)) + insertedRowIDs.insert(rowID) + insertedRowData[rowID] = values } - rebuildChangeIndex() } /// Save inserted-row values for a redo replay closure that may need them. - func savedInsertedValues(forRow rowIndex: Int) -> [PluginCellValue]? { - insertedRowData[rowIndex] + func savedInsertedValues(forRow rowID: RowID) -> [PluginCellValue]? { + insertedRowData[rowID] } /// Restore inserted-row values when undo restores a row. - mutating func restoreInsertedValues(forRow rowIndex: Int, values: [PluginCellValue]) { - insertedRowData[rowIndex] = values + mutating func restoreInsertedValues(forRow rowID: RowID, values: [PluginCellValue]) { + insertedRowData[rowID] = values } // MARK: - Reset / persistence @@ -305,16 +284,16 @@ struct PendingChanges: Equatable { nextSequence = 0 changes.removeAll() changeIndex.removeAll() - deletedRowIndices.removeAll() - insertedRowIndices.removeAll() + deletedRowIDs.removeAll() + insertedRowIDs.removeAll() modifiedCells.removeAll() insertedRowData.removeAll() } mutating func restore(from snapshot: TabChangeSnapshot) { changes = snapshot.changes - deletedRowIndices = snapshot.deletedRowIndices - insertedRowIndices = snapshot.insertedRowIndices + deletedRowIDs = snapshot.deletedRowIDs + insertedRowIDs = snapshot.insertedRowIDs modifiedCells = snapshot.modifiedCells insertedRowData = snapshot.insertedRowData nextSequence = (changes.map(\.sequence).max() ?? -1) + 1 @@ -324,8 +303,8 @@ struct PendingChanges: Equatable { func snapshot(primaryKeyColumns: [String], columns: [String]) -> TabChangeSnapshot { var snap = TabChangeSnapshot() snap.changes = changes - snap.deletedRowIndices = deletedRowIndices - snap.insertedRowIndices = insertedRowIndices + snap.deletedRowIDs = deletedRowIDs + snap.insertedRowIDs = insertedRowIDs snap.modifiedCells = modifiedCells snap.insertedRowData = insertedRowData snap.primaryKeyColumns = primaryKeyColumns @@ -340,12 +319,12 @@ struct PendingChanges: Equatable { stamped.sequence = nextSequence nextSequence += 1 changes.append(stamped) - changeIndex[RowChangeKey(rowIndex: stamped.rowIndex, type: stamped.type)] = changes.count - 1 + changeIndex[RowChangeKey(rowID: stamped.rowID, type: stamped.type)] = changes.count - 1 } @discardableResult - private mutating func removeChange(rowIndex: Int, type: ChangeType) -> Bool { - let key = RowChangeKey(rowIndex: rowIndex, type: type) + private mutating func removeChange(rowID: RowID, type: ChangeType) -> Bool { + let key = RowChangeKey(rowID: rowID, type: type) guard let arrayIndex = changeIndex[key] else { return false } removeChangeAt(arrayIndex) return true @@ -353,13 +332,13 @@ struct PendingChanges: Equatable { private mutating func removeChangeAt(_ arrayIndex: Int) { let removed = changes[arrayIndex] - changeIndex.removeValue(forKey: RowChangeKey(rowIndex: removed.rowIndex, type: removed.type)) + changeIndex.removeValue(forKey: RowChangeKey(rowID: removed.rowID, type: removed.type)) let lastIndex = changes.count - 1 if arrayIndex != lastIndex { let moved = changes[lastIndex] changes.swapAt(arrayIndex, lastIndex) - changeIndex[RowChangeKey(rowIndex: moved.rowIndex, type: moved.type)] = arrayIndex + changeIndex[RowChangeKey(rowID: moved.rowID, type: moved.type)] = arrayIndex } changes.removeLast() } @@ -367,17 +346,24 @@ struct PendingChanges: Equatable { private mutating func rebuildChangeIndex() { changeIndex.removeAll(keepingCapacity: true) for (index, change) in changes.enumerated() { - changeIndex[RowChangeKey(rowIndex: change.rowIndex, type: change.type)] = index + changeIndex[RowChangeKey(rowID: change.rowID, type: change.type)] = index + } + } + + private mutating func removeModifiedCell(rowID: RowID, columnIndex: Int) { + modifiedCells[rowID]?.remove(columnIndex) + if modifiedCells[rowID]?.isEmpty == true { + modifiedCells.removeValue(forKey: rowID) } } private mutating func updateInsertedCell( at insertIdx: Int, columnIndex: Int, columnName: String, newValue: PluginCellValue ) { - let rowIndex = changes[insertIdx].rowIndex - if var stored = insertedRowData[rowIndex], columnIndex < stored.count { + let rowID = changes[insertIdx].rowID + if var stored = insertedRowData[rowID], columnIndex < stored.count { stored[columnIndex] = newValue - insertedRowData[rowIndex] = stored + insertedRowData[rowID] = stored } let replacement = CellChange( @@ -392,113 +378,46 @@ struct PendingChanges: Equatable { } private mutating func mergeUpdateCell(at updateIdx: Int, cellChange: CellChange) { - let rowIndex = changes[updateIdx].rowIndex - if let cellIdx = changes[updateIdx].cellChanges.firstIndex(where: { + let rowID = changes[updateIdx].rowID + guard let cellIdx = changes[updateIdx].cellChanges.firstIndex(where: { $0.columnIndex == cellChange.columnIndex - }) { - let originalOldValue = changes[updateIdx].cellChanges[cellIdx].oldValue - let merged = CellChange( - columnIndex: cellChange.columnIndex, - columnName: cellChange.columnName, - oldValue: originalOldValue, - newValue: cellChange.newValue - ) - changes[updateIdx].cellChanges[cellIdx] = merged - - if originalOldValue == cellChange.newValue { - changes[updateIdx].cellChanges.remove(at: cellIdx) - modifiedCells[rowIndex]?.remove(cellChange.columnIndex) - if modifiedCells[rowIndex]?.isEmpty == true { - modifiedCells.removeValue(forKey: rowIndex) - } - if changes[updateIdx].cellChanges.isEmpty { - removeChangeAt(updateIdx) - } - } - } else { + }) else { changes[updateIdx].cellChanges.append(cellChange) - modifiedCells[rowIndex, default: []].insert(cellChange.columnIndex) + modifiedCells[rowID, default: []].insert(cellChange.columnIndex) + return + } + + let originalOldValue = changes[updateIdx].cellChanges[cellIdx].oldValue + changes[updateIdx].cellChanges[cellIdx] = CellChange( + columnIndex: cellChange.columnIndex, + columnName: cellChange.columnName, + oldValue: originalOldValue, + newValue: cellChange.newValue + ) + + guard originalOldValue == cellChange.newValue else { return } + changes[updateIdx].cellChanges.remove(at: cellIdx) + removeModifiedCell(rowID: rowID, columnIndex: cellChange.columnIndex) + if changes[updateIdx].cellChanges.isEmpty { + removeChangeAt(updateIdx) } } @discardableResult private mutating func rollbackCellIfMatchesOriginal( - rowIndex: Int, columnIndex: Int, restoredValue: PluginCellValue + rowID: RowID, columnIndex: Int, restoredValue: PluginCellValue ) -> Bool { - let updateKey = RowChangeKey(rowIndex: rowIndex, type: .update) + let updateKey = RowChangeKey(rowID: rowID, type: .update) guard let updateIdx = changeIndex[updateKey], let cellIdx = changes[updateIdx].cellChanges.firstIndex(where: { $0.columnIndex == columnIndex }), changes[updateIdx].cellChanges[cellIdx].oldValue == restoredValue else { return false } changes[updateIdx].cellChanges.remove(at: cellIdx) - modifiedCells[rowIndex]?.remove(columnIndex) - if modifiedCells[rowIndex]?.isEmpty == true { - modifiedCells.removeValue(forKey: rowIndex) - } + removeModifiedCell(rowID: rowID, columnIndex: columnIndex) if changes[updateIdx].cellChanges.isEmpty { removeChangeAt(updateIdx) } return true } - - /// Renumbers every collection this type keys by row index, in one place. - /// - /// The state is six things that have to agree: `changes[].rowIndex`, `changeIndex`, - /// `insertedRowIndices`, `deletedRowIndices`, `insertedRowData` and `modifiedCells`. There used - /// to be three renumbering paths handling three different subsets of them, and the gaps were - /// invisible: undoing one row of a pasted batch left the surviving rows' values filed under - /// their old indices, so Save wrote one row with another row's values and dropped the rest - /// without reporting anything. A single primitive is what makes that class of omission - /// impossible rather than merely absent. - /// - /// A new row always lands at the end of the grid, so nothing pending is ever below an inserted - /// one and the delete and modified-cell arms do not fire today. They are here because the - /// alternative is three renumbering paths covering three different subsets again, which is - /// what this replaced. - private mutating func reindex(_ transform: (Int) -> Int) { - for i in 0 ..< changes.count { - changes[i].rowIndex = transform(changes[i].rowIndex) - } - insertedRowIndices = Set(insertedRowIndices.map(transform)) - deletedRowIndices = Set(deletedRowIndices.map(transform)) - insertedRowData = Dictionary( - uniqueKeysWithValues: insertedRowData.map { (transform($0.key), $0.value) } - ) - modifiedCells = Dictionary( - uniqueKeysWithValues: modifiedCells.map { (transform($0.key), $0.value) } - ) - rebuildChangeIndex() - } - - private mutating func shiftRowIndicesUp(from insertionPoint: Int) { - reindex { $0 >= insertionPoint ? $0 + 1 : $0 } - } - - private mutating func shiftRowIndicesDown(at removedRow: Int) { - modifiedCells.removeValue(forKey: removedRow) - reindex { $0 > removedRow ? $0 - 1 : $0 } - } - - /// The same renumbering for a whole batch removed at once. - private mutating func shiftRowIndicesDown(atSortedRows removedRows: [Int]) { - for removedRow in removedRows { - modifiedCells.removeValue(forKey: removedRow) - } - reindex { $0 - Self.countLessThan($0, in: removedRows) } - } - - /// Binary search: count of elements strictly less than `target` in a sorted array. - private static func countLessThan(_ target: Int, in sorted: [Int]) -> Int { - var lo = 0, hi = sorted.count - while lo < hi { - let mid = (lo + hi) / 2 - if sorted[mid] < target { - lo = mid + 1 - } else { - hi = mid - } - } - return lo - } } diff --git a/TablePro/Core/ChangeTracking/SQLStatementGenerator.swift b/TablePro/Core/ChangeTracking/SQLStatementGenerator.swift index 658d7bb227..bb55dedc58 100644 --- a/TablePro/Core/ChangeTracking/SQLStatementGenerator.swift +++ b/TablePro/Core/ChangeTracking/SQLStatementGenerator.swift @@ -88,20 +88,20 @@ struct SQLStatementGenerator { /// - Parameters: /// - changes: Array of row changes to process /// - insertedRowData: Lazy storage for inserted row values - /// - deletedRowIndices: Set of deleted row indices for validation - /// - insertedRowIndices: Set of inserted row indices for validation + /// - deletedRowIDs: Rows still marked as deleted + /// - insertedRowIDs: Rows still marked as inserted /// - Returns: Array of parameterized SQL statements func generateStatements( from changes: [RowChange], - insertedRowData: [Int: [PluginCellValue]], - deletedRowIndices: Set, - insertedRowIndices: Set + insertedRowData: [RowID: [PluginCellValue]], + deletedRowIDs: Set, + insertedRowIDs: Set ) -> [ParameterizedStatement] { generateAttributedStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: deletedRowIndices, - insertedRowIndices: insertedRowIndices + deletedRowIDs: deletedRowIDs, + insertedRowIDs: insertedRowIDs ).map(\.statement) } @@ -117,9 +117,9 @@ struct SQLStatementGenerator { /// separated from another delete by an insert stays on its own side of it. func generateAttributedStatements( from changes: [RowChange], - insertedRowData: [Int: [PluginCellValue]], - deletedRowIndices: Set, - insertedRowIndices: Set + insertedRowData: [RowID: [PluginCellValue]], + deletedRowIDs: Set, + insertedRowIDs: Set ) -> [AttributedStatement] { var statements: [AttributedStatement] = [] var deleteRun: [RowChange] = [] @@ -139,14 +139,14 @@ struct SQLStatementGenerator { } case .insert: // SAFETY: Verify the row is still marked as inserted - guard insertedRowIndices.contains(change.rowIndex) else { continue } + guard insertedRowIDs.contains(change.rowID) else { continue } flushDeleteRun() if let stmt = generateInsertSQL(for: change, insertedRowData: insertedRowData) { statements.append(AttributedStatement(statement: stmt, kind: .insert, rowCount: 1)) } case .delete: // SAFETY: Verify the row is still marked as deleted - guard deletedRowIndices.contains(change.rowIndex) else { continue } + guard deletedRowIDs.contains(change.rowID) else { continue } deleteRun.append(change) } } @@ -166,16 +166,16 @@ struct SQLStatementGenerator { // MARK: - INSERT Generation - private func generateInsertSQL(for change: RowChange, insertedRowData: [Int: [PluginCellValue]]) + private func generateInsertSQL(for change: RowChange, insertedRowData: [RowID: [PluginCellValue]]) -> ParameterizedStatement? { - if let values = insertedRowData[change.rowIndex] { - return generateInsertSQLFromStoredData(rowIndex: change.rowIndex, values: values) + if let values = insertedRowData[change.rowID] { + return generateInsertSQLFromStoredData(values: values) } return generateInsertSQLFromCellChanges(for: change) } - private func generateInsertSQLFromStoredData(rowIndex: Int, values: [PluginCellValue]) + private func generateInsertSQLFromStoredData(values: [PluginCellValue]) -> ParameterizedStatement? { var nonDefaultColumns: [String] = [] diff --git a/TablePro/Core/Coordinators/RowEditingCoordinator+Discard.swift b/TablePro/Core/Coordinators/RowEditingCoordinator+Discard.swift index 706c9e02f9..164cc3960e 100644 --- a/TablePro/Core/Coordinators/RowEditingCoordinator+Discard.swift +++ b/TablePro/Core/Coordinators/RowEditingCoordinator+Discard.swift @@ -75,15 +75,16 @@ extension RowEditingCoordinator { /// them, and the next edit captures an unsaved value as its baseline. A discard that re-queries /// replaces the buffer wholesale and needs none of this; one that does not has to undo it here. func restoreRowBufferToOriginals() { - let originalValues = parent.changeManager.getOriginalValues() var deltas: [Delta] = [] - if let (tab, _) = parent.tabManager.selectedTabAndIndex { + if let (tab, _) = parent.tabManager.selectedTabAndIndex, + let tableRows = parent.tabSessionRegistry.existingTableRows(for: tab.id) { let tabId = tab.id - let insertedIDs = collectInsertedRowIDs( - tabId: tabId, - indices: parent.changeManager.insertedRowIndices - ) - let edits = originalValues.map { (row: $0.0, column: $0.1, value: $0.2) } + let insertedIDs = parent.changeManager.insertedRowIDs + let edits = parent.changeManager.getOriginalValues().compactMap { original in + tableRows.index(of: original.rowID).map { + (row: $0, column: original.columnIndex, value: original.value) + } + } if !edits.isEmpty { let editDelta = parent.mutateActiveTableRows(for: tabId) { rows in rows.editMany(edits) @@ -106,17 +107,4 @@ extension RowEditingCoordinator { parent.dataTabDelegate?.tableViewCoordinator?.applyDelta(delta) } } - - private func collectInsertedRowIDs(tabId: UUID, indices: Set) -> Set { - guard !indices.isEmpty else { return [] } - guard let tableRows = parent.tabSessionRegistry.existingTableRows(for: tabId) else { return [] } - var ids = Set() - for index in indices where index >= 0 && index < tableRows.rows.count { - let id = tableRows.rows[index].id - if id.isInserted { - ids.insert(id) - } - } - return ids - } } diff --git a/TablePro/Core/Coordinators/RowEditingCoordinator+SaveChanges.swift b/TablePro/Core/Coordinators/RowEditingCoordinator+SaveChanges.swift index 58897638e6..a916a71a90 100644 --- a/TablePro/Core/Coordinators/RowEditingCoordinator+SaveChanges.swift +++ b/TablePro/Core/Coordinators/RowEditingCoordinator+SaveChanges.swift @@ -78,7 +78,7 @@ extension RowEditingCoordinator { } let connId = parent.connection.id let kind: OperationKind = hasPendingTableOps ? .destructiveQuery : .writeQuery - let deleteConfirmation = BulkDeleteConfirmation(deletedRowCount: parent.changeManager.deletedRowIndices.count) + let deleteConfirmation = BulkDeleteConfirmation(deletedRowCount: parent.changeManager.deletedRowIDs.count) Task { [weak self, parent] in guard let self else { return } diff --git a/TablePro/Core/Coordinators/RowEditingCoordinator.swift b/TablePro/Core/Coordinators/RowEditingCoordinator.swift index c7638895c2..8757383d6f 100644 --- a/TablePro/Core/Coordinators/RowEditingCoordinator.swift +++ b/TablePro/Core/Coordinators/RowEditingCoordinator.swift @@ -62,12 +62,9 @@ final class RowEditingCoordinator { guard let result = addResult else { return } - if selectionPointsTheGrid { - parent.selectionState.indices = [result.rowIndex] - } parent.tabManager.mutate(at: tabIndex) { $0.hasUserInteraction = true } parent.dataTabDelegate?.tableViewCoordinator?.applyDelta(result.delta) - parent.dataTabDelegate?.tableViewCoordinator?.beginEditingFirstEditableColumn(displayRow: result.rowIndex) + selectAndEditInsertedRow(result.rowID, tabId: tabId) } func deleteSelectedRows(indices: Set) { @@ -76,12 +73,8 @@ final class RowEditingCoordinator { tab.tableContext.isEditable, !indices.isEmpty else { return } - if parent.activeGridDisplayIDs != nil { - deleteFilteredRows(indices: indices, tab: tab, tabIndex: tabIndex) - return - } - let tabId = tab.id + let displayIDs = parent.activeGridDisplayIDs var deleteResult = RowOperationsManager.DeleteRowsResult( nextRowToSelect: -1, @@ -91,63 +84,14 @@ final class RowEditingCoordinator { parent.mutateActiveTableRows(for: tabId) { rows in let result = parent.rowOperationsManager.deleteSelectedRows( selectedIndices: indices, + displayIDs: displayIDs, tableRows: &rows ) deleteResult = result return result.delta } - let totalRows = parent.tabSessionRegistry.tableRows(for: tabId).count - if selectionPointsTheGrid { - if deleteResult.nextRowToSelect >= 0 && deleteResult.nextRowToSelect < totalRows { - parent.selectionState.indices = [deleteResult.nextRowToSelect] - } else { - parent.selectionState.indices.removeAll() - } - } - - parent.tabManager.mutate(at: tabIndex) { $0.hasUserInteraction = true } - - if !deleteResult.physicallyRemovedIndices.isEmpty { - parent.dataTabDelegate?.tableViewCoordinator?.applyDelta(deleteResult.delta) - } else { - parent.dataTabDelegate?.tableViewCoordinator?.invalidateCachesForUndoRedo() - } - } - - private func deleteFilteredRows(indices: Set, tab: QueryTab, tabIndex: Int) { - let tabId = tab.id - let displayIDs = parent.activeGridDisplayIDs - let tableRows = parent.tabSessionRegistry.tableRows(for: tabId) - - var existingRows: [(displayIndex: Int, originalRow: [PluginCellValue])] = [] - var insertedStorageIndices: [Int] = [] - for displayIndex in indices { - guard let storageIndex = DisplayRowMapping.rowIndex( - forDisplay: displayIndex, displayIDs: displayIDs, in: tableRows - ) else { continue } - let row = tableRows.rows[storageIndex] - if row.id.isInserted { - insertedStorageIndices.append(storageIndex) - } else if !parent.changeManager.isRowDeleted(displayIndex) { - existingRows.append((displayIndex: displayIndex, originalRow: Array(row.values))) - } - } - - guard !existingRows.isEmpty || !insertedStorageIndices.isEmpty else { return } - - var deleteResult = RowOperationsManager.DeleteRowsResult( - nextRowToSelect: -1, physicallyRemovedIndices: [], delta: .none - ) - parent.mutateActiveTableRows(for: tabId) { rows in - let result = parent.rowOperationsManager.deleteRows( - existingRows: existingRows, - insertedStorageIndices: insertedStorageIndices, - tableRows: &rows - ) - deleteResult = result - return result.delta - } + guard deleteResult.stagedRowCount > 0 else { return } parent.tabManager.mutate(at: tabIndex) { $0.hasUserInteraction = true } @@ -160,10 +104,10 @@ final class RowEditingCoordinator { guard selectionPointsTheGrid else { return } let displayCount = parent.activeGridDisplayIDs?.count ?? parent.tabSessionRegistry.tableRows(for: tabId).count - if let minSelected = indices.min(), displayCount > 0 { - parent.selectionState.indices = [min(minSelected, displayCount - 1)] + if deleteResult.nextRowToSelect >= 0 && deleteResult.nextRowToSelect < displayCount { + parent.selectionState.indices = [deleteResult.nextRowToSelect] } else { - parent.selectionState.indices = [] + parent.selectionState.indices.removeAll() } } @@ -171,45 +115,14 @@ final class RowEditingCoordinator { guard !parent.safeModeLevel.blocksAllWrites, let (tab, tabIndex) = parent.tabManager.selectedTabAndIndex, tab.tableContext.isEditable, - tab.tableContext.tableName != nil, - parent.tabSessionRegistry.tableRows(for: tab.id).hasAuthoritativeSchema else { return } - - if parent.activeGridDisplayIDs != nil { - duplicateFilteredRow(displayIndex: index, tab: tab, tabIndex: tabIndex) - return - } - - let tabId = tab.id - guard index >= 0, index < parent.tabSessionRegistry.tableRows(for: tabId).count else { return } - - parent.dataTabDelegate?.tableViewCoordinator?.commitActiveCellEdit() - - var dupResult: RowOperationsManager.AddNewRowResult? - parent.mutateActiveTableRows(for: tabId) { rows in - let result = parent.rowOperationsManager.duplicateRow( - sourceRowIndex: index, - tableRows: &rows - ) - dupResult = result - return result?.delta ?? .none - } - - guard let result = dupResult else { return } - - if selectionPointsTheGrid { - parent.selectionState.indices = [result.rowIndex] - } - parent.tabManager.mutate(at: tabIndex) { $0.hasUserInteraction = true } - parent.dataTabDelegate?.tableViewCoordinator?.applyDelta(result.delta) - parent.dataTabDelegate?.tableViewCoordinator?.beginEditingFirstEditableColumn(displayRow: result.rowIndex) - } + tab.tableContext.tableName != nil else { return } - private func duplicateFilteredRow(displayIndex: Int, tab: QueryTab, tabIndex: Int) { let tabId = tab.id let tableRows = parent.tabSessionRegistry.tableRows(for: tabId) - guard let storageIndex = DisplayRowMapping.rowIndex( - forDisplay: displayIndex, displayIDs: parent.activeGridDisplayIDs, in: tableRows - ), storageIndex >= 0, storageIndex < tableRows.count else { return } + guard tableRows.hasAuthoritativeSchema, + let storageIndex = DisplayRowMapping.rowIndex( + forDisplay: index, displayIDs: parent.activeGridDisplayIDs, in: tableRows + ) else { return } parent.dataTabDelegate?.tableViewCoordinator?.commitActiveCellEdit() @@ -227,36 +140,30 @@ final class RowEditingCoordinator { parent.tabManager.mutate(at: tabIndex) { $0.hasUserInteraction = true } parent.dataTabDelegate?.tableViewCoordinator?.applyDelta(result.delta) - - guard selectionPointsTheGrid else { return } - let displayCount = parent.activeGridDisplayIDs?.count - ?? parent.tabSessionRegistry.tableRows(for: tabId).count - let newDisplayIndex = displayCount - 1 - guard newDisplayIndex >= 0 else { return } - parent.selectionState.indices = [newDisplayIndex] - parent.dataTabDelegate?.tableViewCoordinator?.beginEditingFirstEditableColumn(displayRow: newDisplayIndex) + selectAndEditInsertedRow(result.rowID, tabId: tabId) } - func undoInsertRow(at rowIndex: Int) { - guard let (tab, _) = parent.tabManager.selectedTabAndIndex else { return } - let tabId = tab.id + private func selectAndEditInsertedRow(_ rowID: RowID, tabId: UUID) { + guard selectionPointsTheGrid, + let displayIndex = displayIndex(of: rowID, tabId: tabId) else { return } + parent.selectionState.indices = [displayIndex] + parent.dataTabDelegate?.tableViewCoordinator?.beginEditingFirstEditableColumn(displayRow: displayIndex) + } - var undoResult = RowOperationsManager.UndoInsertRowResult( - adjustedSelection: parent.selectionState.indices, - delta: .none + private func displayIndex(of rowID: RowID, tabId: UUID) -> Int? { + DisplayRowMapping.displayIndex( + forRowID: rowID, + displayIDs: parent.activeGridDisplayIDs, + in: parent.tabSessionRegistry.tableRows(for: tabId) ) - parent.mutateActiveTableRows(for: tabId) { rows in - let result = parent.rowOperationsManager.undoInsertRow( - at: rowIndex, - tableRows: &rows, - selectedIndices: parent.selectionState.indices - ) - undoResult = result - return result.delta - } + } - parent.selectionState.indices = undoResult.adjustedSelection - parent.dataTabDelegate?.tableViewCoordinator?.applyDelta(undoResult.delta) + private func displayIndices(of rowIDs: Set, tabId: UUID) -> Set { + guard let displayIDs = parent.activeGridDisplayIDs else { + let tableRows = parent.tabSessionRegistry.tableRows(for: tabId) + return Set(rowIDs.compactMap { tableRows.index(of: $0) }) + } + return Set(displayIDs.indices.filter { rowIDs.contains(displayIDs[$0]) }) } func handleUndoResult(_ result: UndoResult) { @@ -265,11 +172,8 @@ final class RowEditingCoordinator { let tabId = tab.id var application = RowOperationsManager.UndoApplicationResult(adjustedSelection: nil, delta: .none) - let displayIDs = parent.activeGridDisplayIDs parent.mutateActiveTableRows(for: tabId) { rows in - let applied = parent.rowOperationsManager.applyUndoResult( - result, displayIDs: displayIDs, tableRows: &rows - ) + let applied = parent.rowOperationsManager.applyUndoResult(result, tableRows: &rows) application = applied return applied.delta } @@ -341,7 +245,7 @@ final class RowEditingCoordinator { guard !pasteResult.pastedRows.isEmpty else { return } - let newIndices = Set(pasteResult.pastedRows.map { $0.rowIndex }) + let newIndices = displayIndices(of: Set(pasteResult.pastedRows.map(\.rowID)), tabId: tabId) if selectionPointsTheGrid { parent.selectionState.indices = newIndices } diff --git a/TablePro/Core/DataWrite/Rewind/RewindPlanner.swift b/TablePro/Core/DataWrite/Rewind/RewindPlanner.swift index 9d97db452d..cdb9df9d42 100644 --- a/TablePro/Core/DataWrite/Rewind/RewindPlanner.swift +++ b/TablePro/Core/DataWrite/Rewind/RewindPlanner.swift @@ -205,7 +205,7 @@ struct RewindPlanner { } guard !cellChanges.isEmpty else { return [] } return try factory.statements( - for: [RowChange(rowIndex: 0, type: .update, cellChanges: cellChanges, originalRow: postImage)] + for: [RowChange(rowID: .existing(0), type: .update, cellChanges: cellChanges, originalRow: postImage)] ) case .delete: guard let preImage = operation.preImage else { return [] } @@ -213,8 +213,8 @@ struct RewindPlanner { case .insert: guard let postImage = operation.postImage else { return [] } return try factory.statements( - for: [RowChange(rowIndex: 0, type: .delete, cellChanges: [], originalRow: postImage)], - deletedRowIndices: [0] + for: [RowChange(rowID: .existing(0), type: .delete, cellChanges: [], originalRow: postImage)], + deletedRowIDs: [.existing(0)] ) } } diff --git a/TablePro/Core/DataWrite/RowChangeStatementFactory.swift b/TablePro/Core/DataWrite/RowChangeStatementFactory.swift index 2bd64c93da..940e6dc91d 100644 --- a/TablePro/Core/DataWrite/RowChangeStatementFactory.swift +++ b/TablePro/Core/DataWrite/RowChangeStatementFactory.swift @@ -46,23 +46,23 @@ struct RowChangeStatementFactory { func statements( for changes: [RowChange], - insertedRowData: [Int: [PluginCellValue]] = [:], - deletedRowIndices: Set = [], - insertedRowIndices: Set = [] + insertedRowData: [RowID: [PluginCellValue]] = [:], + deletedRowIDs: Set = [], + insertedRowIDs: Set = [] ) throws -> [ParameterizedStatement] { if let pluginStatements = pluginGeneratedStatements( for: changes, insertedRowData: insertedRowData, - deletedRowIndices: deletedRowIndices, - insertedRowIndices: insertedRowIndices + deletedRowIDs: deletedRowIDs, + insertedRowIDs: insertedRowIDs ) { return pluginStatements } return try attributedHostStatements( for: changes, insertedRowData: insertedRowData, - deletedRowIndices: deletedRowIndices, - insertedRowIndices: insertedRowIndices + deletedRowIDs: deletedRowIDs, + insertedRowIDs: insertedRowIDs ).map(\.statement) } @@ -72,40 +72,40 @@ struct RowChangeStatementFactory { /// which rows went into which statement and a guessed count is worse than no count. func attributedStatements( for changes: [RowChange], - insertedRowData: [Int: [PluginCellValue]] = [:], - deletedRowIndices: Set = [], - insertedRowIndices: Set = [] + insertedRowData: [RowID: [PluginCellValue]] = [:], + deletedRowIDs: Set = [], + insertedRowIDs: Set = [] ) throws -> [AttributedStatement]? { if pluginGeneratedStatements( for: changes, insertedRowData: insertedRowData, - deletedRowIndices: deletedRowIndices, - insertedRowIndices: insertedRowIndices + deletedRowIDs: deletedRowIDs, + insertedRowIDs: insertedRowIDs ) != nil { return nil } return try attributedHostStatements( for: changes, insertedRowData: insertedRowData, - deletedRowIndices: deletedRowIndices, - insertedRowIndices: insertedRowIndices + deletedRowIDs: deletedRowIDs, + insertedRowIDs: insertedRowIDs ) } private func attributedHostStatements( for changes: [RowChange], - insertedRowData: [Int: [PluginCellValue]], - deletedRowIndices: Set, - insertedRowIndices: Set + insertedRowData: [RowID: [PluginCellValue]], + deletedRowIDs: Set, + insertedRowIDs: Set ) throws -> [AttributedStatement] { let statements = try hostGenerator().generateAttributedStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: deletedRowIndices, - insertedRowIndices: insertedRowIndices + deletedRowIDs: deletedRowIDs, + insertedRowIDs: insertedRowIDs ) - try validate(statements.map(\.statement), against: changes, deletedRowIndices: deletedRowIndices) - let deletableCount = changes.count { $0.type == .delete && deletedRowIndices.contains($0.rowIndex) } + try validate(statements.map(\.statement), against: changes, deletedRowIDs: deletedRowIDs) + let deletableCount = changes.count { $0.type == .delete && deletedRowIDs.contains($0.rowID) } let identifiedDeletes = statements.filter { $0.kind == .delete }.reduce(0) { $0 + $1.rowCount } if identifiedDeletes < deletableCount { throw DataWriteError.rowsNotIdentifiable(tableName, .delete) @@ -140,12 +140,13 @@ struct RowChangeStatementFactory { let generator = try hostGenerator() var statements: [ParameterizedStatement] = [] for (offset, row) in rows.enumerated() { - let change = RowChange(rowIndex: offset, type: .insert, cellChanges: [], originalRow: row) + let rowID = RowID.existing(offset) + let change = RowChange(rowID: rowID, type: .insert, cellChanges: [], originalRow: row) let generated = generator.generateStatements( from: [change], - insertedRowData: [offset: row], - deletedRowIndices: [], - insertedRowIndices: [offset] + insertedRowData: [rowID: row], + deletedRowIDs: [], + insertedRowIDs: [rowID] ) guard let statement = generated.first else { throw DataWriteError.statementGenerationFailed(tableName) @@ -159,30 +160,35 @@ struct RowChangeStatementFactory { /// `SQLStatementGenerator`, which is what decides whether the host may fall back. var pluginOwnsStatementGeneration: Bool { pluginGeneratedStatements( - for: [RowChange(rowIndex: 0, type: .update, cellChanges: [], originalRow: nil)], + for: [RowChange(rowID: .existing(0), type: .update, cellChanges: [], originalRow: nil)], insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) != nil } private func pluginGeneratedStatements( for changes: [RowChange], - insertedRowData: [Int: [PluginCellValue]], - deletedRowIndices: Set, - insertedRowIndices: Set + insertedRowData: [RowID: [PluginCellValue]], + deletedRowIDs: Set, + insertedRowIDs: Set ) -> [ParameterizedStatement]? { guard let pluginDriver else { return nil } - let pluginChanges = changes.map(PluginRowChange.init(_:)) + let keyed = PluginKeyedChanges( + changes: changes, + insertedRowData: insertedRowData, + deletedRowIDs: deletedRowIDs, + insertedRowIDs: insertedRowIDs + ) guard let statements = pluginDriver.generateStatements( table: tableName, schema: schemaName, columns: columns, primaryKeyColumns: primaryKeyColumns, - changes: pluginChanges, - insertedRowData: insertedRowData, - deletedRowIndices: deletedRowIndices, - insertedRowIndices: insertedRowIndices + changes: keyed.changes, + insertedRowData: keyed.insertedRowData, + deletedRowIndices: keyed.deletedRowIndices, + insertedRowIndices: keyed.insertedRowIndices ) else { return nil } return statements.map { ParameterizedStatement(sql: $0.statement, parameters: $0.parameters.map(\.asAny)) @@ -208,7 +214,7 @@ struct RowChangeStatementFactory { private func validate( _ statements: [ParameterizedStatement], against changes: [RowChange], - deletedRowIndices: Set + deletedRowIDs: Set ) throws { let expectedUpdates = changes.count(where: { $0.type == .update }) let actualUpdates = statements.count(where: { $0.sql.hasPrefix("UPDATE") }) @@ -216,17 +222,46 @@ struct RowChangeStatementFactory { throw DataWriteError.rowsNotIdentifiable(tableName, .update) } - let deletable = changes.filter { $0.type == .delete && deletedRowIndices.contains($0.rowIndex) } + let deletable = changes.filter { $0.type == .delete && deletedRowIDs.contains($0.rowID) } if !deletable.isEmpty, deletable.allSatisfy({ $0.originalRow == nil }) { throw DataWriteError.rowsNotIdentifiable(tableName, .delete) } } } +struct PluginKeyedChanges { + let changes: [PluginRowChange] + let insertedRowData: [Int: [PluginCellValue]] + let deletedRowIndices: Set + let insertedRowIndices: Set + + init( + changes: [RowChange], + insertedRowData: [RowID: [PluginCellValue]], + deletedRowIDs: Set, + insertedRowIDs: Set + ) { + var keys: [RowID: Int] = [:] + for change in changes where keys[change.rowID] == nil { + keys[change.rowID] = keys.count + } + self.changes = changes.compactMap { change in + keys[change.rowID].map { PluginRowChange(change, key: $0) } + } + self.insertedRowData = Dictionary( + uniqueKeysWithValues: insertedRowData.compactMap { rowID, values in + keys[rowID].map { ($0, values) } + } + ) + self.deletedRowIndices = Set(deletedRowIDs.compactMap { keys[$0] }) + self.insertedRowIndices = Set(insertedRowIDs.compactMap { keys[$0] }) + } +} + private extension PluginRowChange { - init(_ change: RowChange) { + init(_ change: RowChange, key: Int) { self.init( - rowIndex: change.rowIndex, + rowIndex: key, type: { switch change.type { case .insert: return .insert diff --git a/TablePro/Core/DataWrite/RowWriteOperationBuilder.swift b/TablePro/Core/DataWrite/RowWriteOperationBuilder.swift index 0017a91957..d6da086be3 100644 --- a/TablePro/Core/DataWrite/RowWriteOperationBuilder.swift +++ b/TablePro/Core/DataWrite/RowWriteOperationBuilder.swift @@ -22,9 +22,9 @@ enum RowWriteOperationBuilder { static func operations( from changes: [RowChange], - insertedRowData: [Int: [PluginCellValue]], - deletedRowIndices: Set, - insertedRowIndices: Set, + insertedRowData: [RowID: [PluginCellValue]], + deletedRowIDs: Set, + insertedRowIDs: Set, target: DataWriteTarget, columns: [String], primaryKeyColumns: [String], @@ -40,16 +40,16 @@ enum RowWriteOperationBuilder { containsTableOperation: containsTableOperation ) case .delete: - guard deletedRowIndices.contains(change.rowIndex) else { return nil } + guard deletedRowIDs.contains(change.rowID) else { return nil } return delete( change, target: target, columns: columns, primaryKeyColumns: primaryKeyColumns, containsTableOperation: containsTableOperation ) case .insert: - guard insertedRowIndices.contains(change.rowIndex) else { return nil } + guard insertedRowIDs.contains(change.rowID) else { return nil } return insert( - change, values: insertedRowData[change.rowIndex], + change, values: insertedRowData[change.rowID], target: target, columns: columns, primaryKeyColumns: primaryKeyColumns, containsTableOperation: containsTableOperation diff --git a/TablePro/Core/SchemaTracking/StructureChangeManager.swift b/TablePro/Core/SchemaTracking/StructureChangeManager.swift index e6032bd19a..ef96735e78 100644 --- a/TablePro/Core/SchemaTracking/StructureChangeManager.swift +++ b/TablePro/Core/SchemaTracking/StructureChangeManager.swift @@ -376,7 +376,7 @@ final class StructureChangeManager: ChangeManaging { // MARK: - Row-Specific Undo Delete /// Clear the deletion mark for the entity at `row` in `tab`. Mirrors - /// `DataChangeManager.undoRowDeletion(rowIndex:)`: the global NSUndoManager + /// `DataChangeManager.undoRowDeletion(rowID:)`: the global NSUndoManager /// stack is intentionally left alone. The original `applySchemaUndo(...)` /// handler the deletion registered remains on the stack; if global Cmd+Z /// later invokes it, the handler finds `pendingChanges` no longer marks @@ -733,12 +733,12 @@ final class StructureChangeManager: ChangeManaging { var rowChanges: [RowChange] { [] } - var insertedRowIndices: Set { [] } + var insertedRowIDs: Set { [] } - func isRowDeleted(_ rowIndex: Int) -> Bool { false } + func isRowDeleted(_ rowID: RowID) -> Bool { false } func recordCellChange( - rowIndex: Int, + rowID: RowID, columnIndex: Int, columnName: String, oldValue: PluginCellValue, @@ -746,9 +746,7 @@ final class StructureChangeManager: ChangeManaging { originalRow: [PluginCellValue]? ) {} - func undoRowDeletion(rowIndex: Int) {} - - func undoRowInsertion(rowIndex: Int) {} + func undoRowDeletion(rowID: RowID) {} } // MARK: - Schema Undo Action diff --git a/TablePro/Core/Scripting/ScriptingSnapshot.swift b/TablePro/Core/Scripting/ScriptingSnapshot.swift index 9d5910ba39..ff3679e5e3 100644 --- a/TablePro/Core/Scripting/ScriptingSnapshot.swift +++ b/TablePro/Core/Scripting/ScriptingSnapshot.swift @@ -203,15 +203,15 @@ internal enum ScriptingSnapshot { /// A row marked for deletion is still in the buffer and is deliberately not in the result the /// grid is showing, so it is not in what a script reads either. let deleted = isSelectedTab - ? coordinator.changeManager.deletedRowIndices - : tab.pendingChanges.deletedRowIndices + ? coordinator.changeManager.deletedRowIDs + : tab.pendingChanges.deletedRowIDs let tableRows = coordinator.tabSessionRegistry.tableRows(for: tabId) let read = DisplayedResultReader.read( tableRows: tableRows, displayIDs: coordinator.displayIDs(forTab: tabId), selectedDisplayIndices: selected, - deletedDisplayIndices: deleted, + deletedRowIDs: deleted, columns: .fromColumnLayout(tab.columnLayout, columns: tableRows.columns) ) let metadata = tab.display.activeResultSet.map { diff --git a/TablePro/Core/Services/Query/RowOperationsManager.swift b/TablePro/Core/Services/Query/RowOperationsManager.swift index 57c75d5f10..545c48c677 100644 --- a/TablePro/Core/Services/Query/RowOperationsManager.swift +++ b/TablePro/Core/Services/Query/RowOperationsManager.swift @@ -10,7 +10,7 @@ final class RowOperationsManager { static let maxClipboardRows = 50_000 struct AddNewRowResult { - let rowIndex: Int + let rowID: RowID let values: [PluginCellValue] let delta: Delta } @@ -19,10 +19,11 @@ final class RowOperationsManager { let nextRowToSelect: Int let physicallyRemovedIndices: [Int] let delta: Delta + var stagedRowCount: Int = 0 } struct PastedRowInfo { - let rowIndex: Int + let rowID: RowID let values: [PluginCellValue] } @@ -36,11 +37,6 @@ final class RowOperationsManager { let delta: Delta } - struct UndoInsertRowResult { - let adjustedSelection: Set - let delta: Delta - } - private let changeManager: DataChangeManager init(changeManager: DataChangeManager) { @@ -56,13 +52,7 @@ final class RowOperationsManager { newRowValues.append(.null) } } - - let newRowIndex = tableRows.count - let delta = tableRows.appendInsertedRow(values: newRowValues) - - changeManager.recordRowInsertion(rowIndex: newRowIndex, values: newRowValues) - - return AddNewRowResult(rowIndex: newRowIndex, values: newRowValues, delta: delta) + return appendInsertedRow(values: newRowValues, to: &tableRows) } func duplicateRow( @@ -83,191 +73,137 @@ final class RowOperationsManager { newValues[index] = .text("__DEFAULT__") } } + return appendInsertedRow(values: newValues, to: &tableRows) + } - let newRowIndex = tableRows.count - let delta = tableRows.appendInsertedRow(values: newValues) - - changeManager.recordRowInsertion(rowIndex: newRowIndex, values: newValues) - - return AddNewRowResult(rowIndex: newRowIndex, values: newValues, delta: delta) + private func appendInsertedRow(values: [PluginCellValue], to tableRows: inout TableRows) -> AddNewRowResult { + let rowID = RowID.inserted(UUID()) + let delta = tableRows.appendInsertedRow(id: rowID, values: values) + changeManager.recordRowInsertion(rowID: rowID, values: values) + return AddNewRowResult(rowID: rowID, values: values, delta: delta) } func deleteSelectedRows( selectedIndices: Set, + displayIDs: [RowID]? = nil, tableRows: inout TableRows ) -> DeleteRowsResult { guard !selectedIndices.isEmpty else { return DeleteRowsResult(nextRowToSelect: -1, physicallyRemovedIndices: [], delta: .none) } - var insertedRowsToDelete: [Int] = [] - var existingRowsToDelete: [(rowIndex: Int, originalRow: [PluginCellValue])] = [] - - let minSelectedRow = selectedIndices.min() ?? 0 - let maxSelectedRow = selectedIndices.max() ?? 0 - - for rowIndex in selectedIndices.sorted(by: >) { - if changeManager.isRowInserted(rowIndex) { - insertedRowsToDelete.append(rowIndex) - } else if !changeManager.isRowDeleted(rowIndex) { - if rowIndex < tableRows.count { - existingRowsToDelete.append((rowIndex: rowIndex, originalRow: Array(tableRows.rows[rowIndex].values))) - } + let displayCountBefore = displayIDs?.count ?? tableRows.count + var insertedRowsToRemove: [InsertedRowLocation] = [] + var existingRowsToDelete: [(rowID: RowID, originalRow: [PluginCellValue])] = [] + + for displayIndex in selectedIndices.sorted(by: >) { + guard let storageIndex = DisplayRowMapping.rowIndex( + forDisplay: displayIndex, displayIDs: displayIDs, in: tableRows + ) else { continue } + let row = tableRows.rows[storageIndex] + if row.id.isInserted { + insertedRowsToRemove.append(InsertedRowLocation(rowID: row.id, storageIndex: storageIndex)) + } else if !changeManager.isRowDeleted(row.id) { + existingRowsToDelete.append((rowID: row.id, originalRow: Array(row.values))) } } - let sortedInsertedRows = insertedRowsToDelete.sorted(by: >) - var delta: Delta = .none - if !sortedInsertedRows.isEmpty { - delta = tableRows.remove(at: IndexSet(sortedInsertedRows)) - changeManager.undoBatchRowInsertion(rowIndices: sortedInsertedRows) + if !insertedRowsToRemove.isEmpty { + delta = tableRows.remove(at: IndexSet(insertedRowsToRemove.map(\.storageIndex))) + changeManager.undoBatchRowInsertion(rows: insertedRowsToRemove) } if !existingRowsToDelete.isEmpty { changeManager.recordBatchRowDeletion(rows: existingRowsToDelete) } - let totalRows = tableRows.count - let rowsDeleted = sortedInsertedRows.count - let adjustedMaxRow = maxSelectedRow - rowsDeleted - let adjustedMinRow = minSelectedRow - sortedInsertedRows.count(where: { $0 < minSelectedRow }) - - let nextRow: Int - if adjustedMaxRow + 1 < totalRows { - nextRow = min(adjustedMaxRow + 1, totalRows - 1) - } else if adjustedMinRow > 0 { - nextRow = adjustedMinRow - 1 - } else if totalRows > 0 { - nextRow = 0 - } else { - nextRow = -1 - } - return DeleteRowsResult( - nextRowToSelect: nextRow, - physicallyRemovedIndices: sortedInsertedRows, - delta: delta + nextRowToSelect: Self.nextRowToSelect( + afterDeleting: selectedIndices, + removedCount: insertedRowsToRemove.count, + displayCountAfter: displayCountBefore - insertedRowsToRemove.count + ), + physicallyRemovedIndices: insertedRowsToRemove.map(\.storageIndex), + delta: delta, + stagedRowCount: insertedRowsToRemove.count + existingRowsToDelete.count ) } - func deleteRows( - existingRows: [(displayIndex: Int, originalRow: [PluginCellValue])], - insertedStorageIndices: [Int], - tableRows: inout TableRows - ) -> DeleteRowsResult { - let sortedInsertedRows = insertedStorageIndices.sorted(by: >) - - var delta: Delta = .none - if !sortedInsertedRows.isEmpty { - delta = tableRows.remove(at: IndexSet(sortedInsertedRows)) - changeManager.undoBatchRowInsertion(rowIndices: sortedInsertedRows) + private static func nextRowToSelect( + afterDeleting selectedIndices: Set, + removedCount: Int, + displayCountAfter: Int + ) -> Int { + let minSelectedRow = selectedIndices.min() ?? 0 + let adjustedMaxRow = (selectedIndices.max() ?? 0) - removedCount + if adjustedMaxRow + 1 < displayCountAfter { + return adjustedMaxRow + 1 } - - if !existingRows.isEmpty { - changeManager.recordBatchRowDeletion( - rows: existingRows.map { (rowIndex: $0.displayIndex, originalRow: $0.originalRow) } - ) + if minSelectedRow > 0 { + return minSelectedRow - 1 } - - return DeleteRowsResult( - nextRowToSelect: -1, - physicallyRemovedIndices: sortedInsertedRows, - delta: delta - ) + return displayCountAfter > 0 ? 0 : -1 } - /// `displayIDs` is the grid's display order when a per-column value filter is narrowing it. - /// - /// A cell edit is tracked by its display row, the same as the modified and deleted marks the - /// grid draws, but `TableRows` is indexed by storage position. The forward write converts; this - /// one has to as well, or undoing an edit under a filter puts the old value into whichever row - /// happens to sit at that storage offset. The row arms need no conversion: an inserted row is - /// tracked by its storage index from the start, which is what lets it be physically removed. - func applyUndoResult( - _ result: UndoResult, - displayIDs: [RowID]?, - tableRows: inout TableRows - ) -> UndoApplicationResult { + func applyUndoResult(_ result: UndoResult, tableRows: inout TableRows) -> UndoApplicationResult { switch result.action { - case .cellEdit(let rowIndex, let columnIndex, _, let previousValue, _, _): - guard let storageRow = DisplayRowMapping.rowIndex( - forDisplay: rowIndex, displayIDs: displayIDs, in: tableRows - ) else { + case .cellEdit(let rowID, let columnIndex, _, let previousValue, _, _): + guard let storageRow = tableRows.index(of: rowID) else { return UndoApplicationResult(adjustedSelection: nil, delta: .none) } let delta = tableRows.edit(row: storageRow, column: columnIndex, value: previousValue) return UndoApplicationResult(adjustedSelection: nil, delta: delta) - case .rowInsertion(let rowIndex): + case .rowInsertion(let rowID): if result.needsRowRemoval { - guard rowIndex >= 0, rowIndex < tableRows.count else { + let delta = tableRows.remove(rowIDs: [rowID]) + guard delta != .none else { return UndoApplicationResult(adjustedSelection: nil, delta: .none) } - let delta = tableRows.remove(at: IndexSet(integer: rowIndex)) return UndoApplicationResult(adjustedSelection: Set(), delta: delta) - } else if result.needsRowRestore { - let columnCount = tableRows.columns.count - let values = result.restoreRow ?? [PluginCellValue](repeating: .null, count: columnCount) - let delta = tableRows.insertInsertedRow(at: rowIndex, values: values) + } + if result.needsRowRestore { + let values = result.restoreRow + ?? [PluginCellValue](repeating: .null, count: tableRows.columns.count) + let delta = tableRows.appendInsertedRow(id: rowID, values: values) return UndoApplicationResult(adjustedSelection: nil, delta: delta) } return UndoApplicationResult(adjustedSelection: nil, delta: .none) - case .rowDeletion: - return UndoApplicationResult(adjustedSelection: nil, delta: result.delta) - - case .batchRowDeletion: + case .rowDeletion, .batchRowDeletion: return UndoApplicationResult(adjustedSelection: nil, delta: result.delta) - case .batchRowInsertion(let rowIndices, let rowValues): + case .batchRowInsertion(let rows, let rowValues): if result.needsRowRemoval { - let validIndices = IndexSet(rowIndices.filter { $0 >= 0 && $0 < tableRows.count }) - guard !validIndices.isEmpty else { - return UndoApplicationResult(adjustedSelection: nil, delta: .none) - } - let delta = tableRows.remove(at: validIndices) + let delta = tableRows.remove(rowIDs: Set(rows.map(\.rowID))) return UndoApplicationResult(adjustedSelection: nil, delta: delta) - } else if result.needsRowRestore { - var insertedIndices = IndexSet() - let pairs = zip(rowIndices, rowValues).sorted { $0.0 < $1.0 } - for (rowIndex, values) in pairs { - guard rowIndex >= 0, rowIndex <= tableRows.count else { continue } - _ = tableRows.insertInsertedRow(at: rowIndex, values: values) - insertedIndices.insert(rowIndex) - } - guard !insertedIndices.isEmpty else { - return UndoApplicationResult(adjustedSelection: nil, delta: .none) - } - return UndoApplicationResult(adjustedSelection: nil, delta: .rowsInserted(insertedIndices)) + } + if result.needsRowRestore { + return UndoApplicationResult( + adjustedSelection: nil, + delta: restoreInsertedRows(rows, values: rowValues, into: &tableRows) + ) } return UndoApplicationResult(adjustedSelection: nil, delta: .none) } } - func undoInsertRow( - at rowIndex: Int, - tableRows: inout TableRows, - selectedIndices: Set - ) -> UndoInsertRowResult { - guard rowIndex >= 0 && rowIndex < tableRows.count else { - return UndoInsertRowResult(adjustedSelection: selectedIndices, delta: .none) - } - - let delta = tableRows.remove(at: IndexSet(integer: rowIndex)) - - var adjustedSelection = Set() - for idx in selectedIndices { - if idx == rowIndex { + private func restoreInsertedRows( + _ rows: [InsertedRowLocation], + values rowValues: [[PluginCellValue]], + into tableRows: inout TableRows + ) -> Delta { + var insertedIndices = IndexSet() + let ascending = zip(rows, rowValues).sorted { $0.0.storageIndex < $1.0.storageIndex } + for (location, values) in ascending { + let index = min(location.storageIndex, tableRows.count) + guard tableRows.insertInsertedRow(at: index, id: location.rowID, values: values) != .none else { continue - } else if idx > rowIndex { - adjustedSelection.insert(idx - 1) - } else { - adjustedSelection.insert(idx) } + insertedIndices.insert(index) } - - return UndoInsertRowResult(adjustedSelection: adjustedSelection, delta: delta) + return insertedIndices.isEmpty ? .none : .rowsInserted(insertedIndices) } func copySelectedRowsToClipboard( @@ -437,13 +373,9 @@ final class RowOperationsManager { for index in serverOwned where index < rowValues.count { rowValues[index] = .text("__DEFAULT__") } - let newRowIndex = tableRows.count - _ = tableRows.appendInsertedRow(values: rowValues) - insertedIndices.insert(newRowIndex) - - changeManager.recordRowInsertion(rowIndex: newRowIndex, values: rowValues) - - pastedRowInfo.append(PastedRowInfo(rowIndex: newRowIndex, values: rowValues)) + insertedIndices.insert(tableRows.count) + let inserted = appendInsertedRow(values: rowValues, to: &tableRows) + pastedRowInfo.append(PastedRowInfo(rowID: inserted.rowID, values: rowValues)) } let delta: Delta = insertedIndices.isEmpty ? .none : .rowsInserted(insertedIndices) diff --git a/TablePro/Core/Utilities/SQL/DisplayedResultReader.swift b/TablePro/Core/Utilities/SQL/DisplayedResultReader.swift index ab8a162e1c..48341d9574 100644 --- a/TablePro/Core/Utilities/SQL/DisplayedResultReader.swift +++ b/TablePro/Core/Utilities/SQL/DisplayedResultReader.swift @@ -24,13 +24,13 @@ internal enum DisplayedResultReader { /// - Parameter selectedDisplayIndices: display positions to narrow to. Empty means every /// displayed row, which is what an untouched result set shows. - /// - Parameter deletedDisplayIndices: display positions marked for deletion but not yet saved. + /// - Parameter deletedRowIDs: rows marked for deletion but not yet saved. /// Empty, the default, reads every row. internal static func read( tableRows: TableRows, displayIDs: [RowID]?, selectedDisplayIndices: Set, - deletedDisplayIndices: Set = [], + deletedRowIDs: Set = [], columns projection: VisibleColumnProjection ) -> Output { let positions: [Int] @@ -45,7 +45,7 @@ internal enum DisplayedResultReader { guard let row = DisplayRowMapping.row( forDisplay: displayIndex, displayIDs: displayIDs, in: tableRows ) else { return nil } - guard !deletedDisplayIndices.contains(displayIndex) else { + guard !deletedRowIDs.contains(row.id) else { skippedDeleted += 1 return nil } diff --git a/TablePro/Core/Utilities/SQL/ResultJsonSerializer.swift b/TablePro/Core/Utilities/SQL/ResultJsonSerializer.swift index 9a32005289..c2f9ead605 100644 --- a/TablePro/Core/Utilities/SQL/ResultJsonSerializer.swift +++ b/TablePro/Core/Utilities/SQL/ResultJsonSerializer.swift @@ -29,20 +29,20 @@ internal enum ResultJsonSerializer { /// - Parameter selectedDisplayIndices: display positions to narrow to. Empty means every /// displayed row, which is what an untouched result set shows. - /// - Parameter deletedDisplayIndices: display positions marked for deletion but not yet saved. + /// - Parameter deletedRowIDs: rows marked for deletion but not yet saved. /// Empty, the default, serialises every row. internal static func serialize( tableRows: TableRows, displayIDs: [RowID]?, selectedDisplayIndices: Set, - deletedDisplayIndices: Set = [], + deletedRowIDs: Set = [], columns projection: VisibleColumnProjection ) -> Output { let read = DisplayedResultReader.read( tableRows: tableRows, displayIDs: displayIDs, selectedDisplayIndices: selectedDisplayIndices, - deletedDisplayIndices: deletedDisplayIndices, + deletedRowIDs: deletedRowIDs, columns: projection ) diff --git a/TablePro/Models/Query/QueryTabState.swift b/TablePro/Models/Query/QueryTabState.swift index 48e920e70f..91c29b5768 100644 --- a/TablePro/Models/Query/QueryTabState.swift +++ b/TablePro/Models/Query/QueryTabState.swift @@ -141,17 +141,17 @@ struct PersistedTab: Codable { struct TabChangeSnapshot: Equatable { var changes: [RowChange] - var deletedRowIndices: Set - var insertedRowIndices: Set - var modifiedCells: [Int: Set] - var insertedRowData: [Int: [PluginCellValue]] + var deletedRowIDs: Set + var insertedRowIDs: Set + var modifiedCells: [RowID: Set] + var insertedRowData: [RowID: [PluginCellValue]] var primaryKeyColumns: [String] var columns: [String] init() { self.changes = [] - self.deletedRowIndices = [] - self.insertedRowIndices = [] + self.deletedRowIDs = [] + self.insertedRowIDs = [] self.modifiedCells = [:] self.insertedRowData = [:] self.primaryKeyColumns = [] @@ -159,7 +159,7 @@ struct TabChangeSnapshot: Equatable { } var hasChanges: Bool { - !changes.isEmpty || !insertedRowIndices.isEmpty || !deletedRowIndices.isEmpty + !changes.isEmpty || !insertedRowIDs.isEmpty || !deletedRowIDs.isEmpty } } diff --git a/TablePro/Models/Query/TableRows.swift b/TablePro/Models/Query/TableRows.swift index e91db7569a..c6c45c23f3 100644 --- a/TablePro/Models/Query/TableRows.swift +++ b/TablePro/Models/Query/TableRows.swift @@ -119,9 +119,10 @@ struct TableRows: Sendable { } @discardableResult - mutating func appendInsertedRow(values: [PluginCellValue]) -> Delta { + mutating func appendInsertedRow(id: RowID = .inserted(UUID()), values: [PluginCellValue]) -> Delta { + guard indexByID[id] == nil else { return .none } let normalized = Self.normalize(values: values, toCount: columns.count) - let row = Row(id: .inserted(UUID()), values: normalized) + let row = Row(id: id, values: normalized) let newIndex = rows.count rows.append(row) indexByID[row.id] = newIndex @@ -129,10 +130,14 @@ struct TableRows: Sendable { } @discardableResult - mutating func insertInsertedRow(at index: Int, values: [PluginCellValue]) -> Delta { - guard index >= 0, index <= rows.count else { return .none } + mutating func insertInsertedRow( + at index: Int, + id: RowID = .inserted(UUID()), + values: [PluginCellValue] + ) -> Delta { + guard index >= 0, index <= rows.count, indexByID[id] == nil else { return .none } let normalized = Self.normalize(values: values, toCount: columns.count) - let row = Row(id: .inserted(UUID()), values: normalized) + let row = Row(id: id, values: normalized) rows.insert(row, at: index) for offset in index.. { [] } + var insertedRowIDs: Set { [] } - func isRowDeleted(_ rowIndex: Int) -> Bool { false } + func isRowDeleted(_ rowID: RowID) -> Bool { false } func recordCellChange( - rowIndex: Int, + rowID: RowID, columnIndex: Int, columnName: String, oldValue: PluginCellValue, @@ -26,8 +26,7 @@ final class InspectorChangeManager: ChangeManaging { originalRow: [PluginCellValue]? ) {} - func undoRowDeletion(rowIndex: Int) {} - func undoRowInsertion(rowIndex: Int) {} + func undoRowDeletion(rowID: RowID) {} func bumpReload() { reloadVersion &+= 1 diff --git a/TablePro/Views/Main/Child/DataTabGridDelegate.swift b/TablePro/Views/Main/Child/DataTabGridDelegate.swift index 2de98910ef..4a06441cda 100644 --- a/TablePro/Views/Main/Child/DataTabGridDelegate.swift +++ b/TablePro/Views/Main/Child/DataTabGridDelegate.swift @@ -18,7 +18,6 @@ final class DataTabGridDelegate: DataGridViewDelegate { var onCellEdit: ((Int, Int, String?) -> Void)? var onSortStateChanged: ((SortState) -> Void)? var onAddRow: (() -> Void)? - var onUndoInsert: ((Int) -> Void)? var onFilterColumn: ((String) -> Void)? // MARK: - DataGridViewDelegate @@ -56,10 +55,6 @@ final class DataTabGridDelegate: DataGridViewDelegate { onAddRow?() } - func dataGridUndoInsert(at index: Int) { - onUndoInsert?(index) - } - func dataGridFilterColumn(_ columnName: String) { onFilterColumn?(columnName) } diff --git a/TablePro/Views/Main/Child/MainEditorContentView.swift b/TablePro/Views/Main/Child/MainEditorContentView.swift index a33b9d25e8..50f2d85b25 100644 --- a/TablePro/Views/Main/Child/MainEditorContentView.swift +++ b/TablePro/Views/Main/Child/MainEditorContentView.swift @@ -44,7 +44,6 @@ struct MainEditorContentView: View { let onCellEdit: (Int, Int, String?) -> Void let onSortStateChanged: (SortState) -> Void let onAddRow: () -> Void - let onUndoInsert: (Int) -> Void let onSelectionChange: (Set) -> Void let onFilterColumn: (String) -> Void let onApplyFilters: ([TableFilter]) -> Void @@ -205,7 +204,6 @@ struct MainEditorContentView: View { dataTabDelegate.selectionState = selectionState dataTabDelegate.onCellEdit = onCellEdit dataTabDelegate.onSortStateChanged = onSortStateChanged - dataTabDelegate.onUndoInsert = onUndoInsert dataTabDelegate.onFilterColumn = onFilterColumn } @@ -706,7 +704,7 @@ struct MainEditorContentView: View { tableRows: resolvedTableRows(for: tab), selectedRowIndices: selectionState.indices, displayIDs: coordinator.displayIDs(forTab: tab.id), - deletedRowIndices: changeManager.deletedRowIndices, + deletedRowIDs: changeManager.deletedRowIDs, valueFilter: tab.valueFilter, dataRevision: coordinator.tabSessionRegistry.session(for: tab.id)?.dataRevision ?? 0, displayRevision: coordinator.gridDisplayRevision, diff --git a/TablePro/Views/Main/Extensions/MainContentCoordinator+Alerts.swift b/TablePro/Views/Main/Extensions/MainContentCoordinator+Alerts.swift index 7eec831fdf..b99c3504b0 100644 --- a/TablePro/Views/Main/Extensions/MainContentCoordinator+Alerts.swift +++ b/TablePro/Views/Main/Extensions/MainContentCoordinator+Alerts.swift @@ -48,8 +48,7 @@ extension MainContentCoordinator { case .navigation: return String(localized: "Moving through this tab's history replaces what it is showing and will discard all unsaved changes.") /// No mention of reloading, unlike sort and the WHERE filter: a value filter narrows the - /// rows already loaded and never re-queries. What it does change is which row each display - /// position names, which is what the edits are recorded against. + /// rows already loaded and never re-queries. case .displayOrder: return String(localized: "Changing which rows are shown will discard all unsaved changes.") /// Named for the reload, like sort and the WHERE filter, because that is what costs the diff --git a/TablePro/Views/Main/Extensions/MainContentCoordinator+NavigationHistory.swift b/TablePro/Views/Main/Extensions/MainContentCoordinator+NavigationHistory.swift index 56728952d5..6914e24b3c 100644 --- a/TablePro/Views/Main/Extensions/MainContentCoordinator+NavigationHistory.swift +++ b/TablePro/Views/Main/Extensions/MainContentCoordinator+NavigationHistory.swift @@ -102,15 +102,12 @@ extension MainContentCoordinator { let tableRows = tabSessionRegistry.tableRows(for: tab.id) guard let row = gridCoordinator.displayRow(at: displayIndex, in: tableRows) else { return nil } - let rowIndex = gridCoordinator.tableRowsIndex(forDisplayRow: displayIndex) - return NavigationRowAnchor.build( keyColumns: keyColumns, columns: tableRows.columns, values: row.values, isModified: { column in - guard let rowIndex else { return false } - return changeManager.isCellModified(rowIndex: rowIndex, columnIndex: column) + changeManager.isCellModified(rowID: row.id, columnIndex: column) } ) } diff --git a/TablePro/Views/Main/Extensions/MainContentCoordinator+RowOperations.swift b/TablePro/Views/Main/Extensions/MainContentCoordinator+RowOperations.swift index 7dcbc5619a..6476a3f396 100644 --- a/TablePro/Views/Main/Extensions/MainContentCoordinator+RowOperations.swift +++ b/TablePro/Views/Main/Extensions/MainContentCoordinator+RowOperations.swift @@ -38,10 +38,6 @@ extension MainContentCoordinator { rowEditingCoordinator.duplicateSelectedRow(index: index) } - func undoInsertRow(at rowIndex: Int) { - rowEditingCoordinator.undoInsertRow(at: rowIndex) - } - func handleUndoResult(_ result: UndoResult) { rowEditingCoordinator.handleUndoResult(result) } diff --git a/TablePro/Views/Main/Extensions/MainContentCoordinator+SidebarSave.swift b/TablePro/Views/Main/Extensions/MainContentCoordinator+SidebarSave.swift index 003027a244..eafcfe3321 100644 --- a/TablePro/Views/Main/Extensions/MainContentCoordinator+SidebarSave.swift +++ b/TablePro/Views/Main/Extensions/MainContentCoordinator+SidebarSave.swift @@ -47,7 +47,7 @@ extension MainContentCoordinator { ) else { return nil } let originalRow = Array(resolvedRow.values) return RowChange( - rowIndex: rowIndex, + rowID: resolvedRow.id, type: .update, cellChanges: editedFields.map { field in let oldValue: PluginCellValue = field.columnIndex < originalRow.count diff --git a/TablePro/Views/Main/Extensions/MainContentView+Bindings.swift b/TablePro/Views/Main/Extensions/MainContentView+Bindings.swift index 65b9fcda95..230e39edac 100644 --- a/TablePro/Views/Main/Extensions/MainContentView+Bindings.swift +++ b/TablePro/Views/Main/Extensions/MainContentView+Bindings.swift @@ -144,8 +144,14 @@ extension MainContentView { var isSelectedRowDeleted: Bool { guard gridSelectionOwner == .dataGrid, - let firstIndex = coordinator.selectionState.indices.min() else { return false } - return coordinator.changeManager.isRowDeleted(firstIndex) + let tabId = coordinator.tabManager.selectedTab?.id, + let firstIndex = coordinator.selectionState.indices.min(), + let row = DisplayRowMapping.row( + forDisplay: firstIndex, + displayIDs: coordinator.activeGridDisplayIDs, + in: coordinator.tabSessionRegistry.tableRows(for: tabId) + ) else { return false } + return coordinator.changeManager.isRowDeleted(row.id) } // MARK: - Sort State Binding diff --git a/TablePro/Views/Main/Extensions/MainContentView+EventHandlers.swift b/TablePro/Views/Main/Extensions/MainContentView+EventHandlers.swift index 195e77f3cc..6f4be4606a 100644 --- a/TablePro/Views/Main/Extensions/MainContentView+EventHandlers.swift +++ b/TablePro/Views/Main/Extensions/MainContentView+EventHandlers.swift @@ -169,12 +169,10 @@ extension MainContentView { let tableRows = coordinator.tabSessionRegistry.tableRows(for: tab.id) let displayIDs = coordinator.activeGridDisplayIDs - var allRows: [[PluginCellValue]] = [] - for displayIndex in selectedIndices.sorted() { - if let row = DisplayRowMapping.row(forDisplay: displayIndex, displayIDs: displayIDs, in: tableRows) { - allRows.append(Array(row.values)) - } + let selectedRows = selectedIndices.sorted().compactMap { + DisplayRowMapping.row(forDisplay: $0, displayIDs: displayIDs, in: tableRows) } + let allRows = selectedRows.map { Array($0.values) } var columnTypes = tableRows.columnTypes for (i, col) in tableRows.columns.enumerated() where i < columnTypes.count { @@ -193,8 +191,8 @@ extension MainContentView { } var modifiedColumns = Set() - for rowIndex in selectedIndices { - modifiedColumns.formUnion(changeManager.getModifiedColumnsForRow(rowIndex)) + for row in selectedRows { + modifiedColumns.formUnion(changeManager.getModifiedColumnsForRow(row.id)) } let pkColumns = Set(tab.tableContext.primaryKeyColumns) @@ -253,7 +251,7 @@ extension MainContentView { } capturedCoordinator.changeManager.recordCellChange( - rowIndex: rowIndex, + rowID: resolvedRow.id, columnIndex: columnIndex, columnName: columnName, oldValue: oldValue, diff --git a/TablePro/Views/Main/MainContentView.swift b/TablePro/Views/Main/MainContentView.swift index 82d7edff16..e9108bdbd3 100644 --- a/TablePro/Views/Main/MainContentView.swift +++ b/TablePro/Views/Main/MainContentView.swift @@ -407,9 +407,6 @@ struct MainContentView: View { onAddRow: { coordinator.addNewRow() }, - onUndoInsert: { rowIndex in - coordinator.undoInsertRow(at: rowIndex) - }, onSelectionChange: { newIndices in /// Any grid selection counts, not just a table tab's. The setting is called /// "Auto-show inspector on row select" and both docs pages describe it that way, diff --git a/TablePro/Views/Results/ColumnValueFilterPopover.swift b/TablePro/Views/Results/ColumnValueFilterPopover.swift index f08d51bf17..007afaec75 100644 --- a/TablePro/Views/Results/ColumnValueFilterPopover.swift +++ b/TablePro/Views/Results/ColumnValueFilterPopover.swift @@ -85,6 +85,7 @@ struct ColumnValueFilterPopover: View { ) HStack(spacing: 6) { TristateCheckbox(state: selectAllState) { toggleSelectAll() } + .accessibilityLabel(String(localized: "Select All")) Text("Select All") Spacer() } @@ -109,6 +110,7 @@ struct ColumnValueFilterPopover: View { } } .toggleStyle(.checkbox) + .accessibilityIdentifier("value-filter-value") } } .listStyle(.plain) diff --git a/TablePro/Views/Results/DataGridCoordinator.swift b/TablePro/Views/Results/DataGridCoordinator.swift index 1298a3cbe7..cd8afb63b7 100644 --- a/TablePro/Views/Results/DataGridCoordinator.swift +++ b/TablePro/Views/Results/DataGridCoordinator.swift @@ -751,7 +751,7 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData reloadAfterRowMutationWithValueFilter() return } - visualIndex.rebuild(from: changeManager, displayIDs: displayIDs) + visualIndex.rebuild(from: changeManager) updateCache() tableView.insertRows(at: indices, withAnimation: Self.rowAnimation(.slideDown)) repaintVisibleRowDecorations() @@ -769,7 +769,7 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData reloadAfterRowMutationWithValueFilter() return } - visualIndex.rebuild(from: changeManager, displayIDs: displayIDs) + visualIndex.rebuild(from: changeManager) updateCache() tableView.removeRows(at: indices, withAnimation: Self.rowAnimation(.slideUp)) repaintVisibleRowDecorations() @@ -808,7 +808,7 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData guard let tableView else { return } recomputeValueFilteredIDs() updateCache() - visualIndex.rebuild(from: changeManager, displayIDs: displayIDs) + visualIndex.rebuild(from: changeManager) tableView.reloadData() startBackgroundPrewarm() } @@ -930,7 +930,7 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData func invalidateAllDisplayCaches() { displayCache.removeAll() - visualIndex.rebuild(from: changeManager, displayIDs: displayIDs) + visualIndex.rebuild(from: changeManager) } @discardableResult @@ -1070,7 +1070,7 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData else { return } guard row >= 0, row < tableView.numberOfRows else { return } invalidateDisplayCache(forDisplayRow: row, column: column) - visualIndex.updateRow(row, from: changeManager, displayIDs: displayIDs) + updateVisualIndex(forDisplayRow: row) redrawCells(rows: IndexSet(integer: row), tableColumnIndexes: IndexSet(integer: tableColumn)) invalidateRowDecoration(displayRow: row) case .cellsChanged(let positions): @@ -1088,7 +1088,7 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData } guard !rowSet.isEmpty, !colSet.isEmpty else { return } for row in rowSet { - visualIndex.updateRow(row, from: changeManager, displayIDs: displayIDs) + updateVisualIndex(forDisplayRow: row) } redrawCells(rows: rowSet, tableColumnIndexes: colSet) for row in rowSet { @@ -1418,7 +1418,9 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData if let delegateState = delegate?.dataGridVisualState(forRow: row) { return delegateState } - return visualIndex.visualState(for: row).highlighted(highlight(forDisplayRow: row)) + guard !visualIndex.isEmpty || !highlightRuleSet.isEmpty, + let displayed = displayRow(at: row) else { return .empty } + return visualState(of: displayed, atDisplayRow: row) } // MARK: - NSTableViewDataSource diff --git a/TablePro/Views/Results/DataGridRowView.swift b/TablePro/Views/Results/DataGridRowView.swift index a083518d32..34e0681537 100644 --- a/TablePro/Views/Results/DataGridRowView.swift +++ b/TablePro/Views/Results/DataGridRowView.swift @@ -404,7 +404,7 @@ class DataGridRowView: NSTableRowView { let menu = NSMenu() - if coordinator.changeManager.isRowDeleted(rowIndex) { + if coordinator.isRowDeleted(displayRow: rowIndex) { menu.addItem( withTitle: String(localized: "Undo Delete"), action: #selector(undoDeleteRow), keyEquivalent: "" ).target = self diff --git a/TablePro/Views/Results/DataGridView+RowActions.swift b/TablePro/Views/Results/DataGridView+RowActions.swift index 76bc55064a..24b602aaa1 100644 --- a/TablePro/Views/Results/DataGridView+RowActions.swift +++ b/TablePro/Views/Results/DataGridView+RowActions.swift @@ -14,8 +14,9 @@ private let rowActionsLogger = Logger(subsystem: "com.TablePro", category: "Data extension TableViewCoordinator { @MainActor func undoDeleteRow(at index: Int) { - changeManager.undoRowDeletion(rowIndex: index) - visualIndex.updateRow(index, from: changeManager, displayIDs: displayIDs) + guard let rowID = rowID(forDisplayRow: index) else { return } + changeManager.undoRowDeletion(rowID: rowID) + visualIndex.updateRow(rowID, from: changeManager) repaintRows(IndexSet(integer: index)) refreshRowVisualState(at: index) } @@ -24,16 +25,6 @@ extension TableViewCoordinator { delegate?.dataGridAddRow() } - @MainActor - func undoInsertRow(at index: Int) { - delegate?.dataGridUndoInsert(at: index) - changeManager.undoRowInsertion(rowIndex: index) - let delta = tableRowsMutator { rows in - rows.remove(at: IndexSet(integer: index)) - } - applyDelta(delta) - } - func copyRows(at indices: Set) { let sortedIndices = indices.sorted() let tableRows = tableRowsProvider() diff --git a/TablePro/Views/Results/DataGridView.swift b/TablePro/Views/Results/DataGridView.swift index 5a9390628c..19c1780495 100644 --- a/TablePro/Views/Results/DataGridView.swift +++ b/TablePro/Views/Results/DataGridView.swift @@ -379,7 +379,7 @@ struct DataGridView: NSViewRepresentable { delegate?.dataGridAttach(tableViewCoordinator: coordinator) coordinator.recomputeValueFilteredIDs() coordinator.updateCache() - coordinator.visualIndex.rebuild(from: coordinator.changeManager, displayIDs: coordinator.displayIDs) + coordinator.visualIndex.rebuild(from: coordinator.changeManager) if !latestRows.columns.isEmpty { coordinator.isRebuildingColumns = true diff --git a/TablePro/Views/Results/DataGridViewDelegate.swift b/TablePro/Views/Results/DataGridViewDelegate.swift index 68b40dc12f..9eae9ed423 100644 --- a/TablePro/Views/Results/DataGridViewDelegate.swift +++ b/TablePro/Views/Results/DataGridViewDelegate.swift @@ -17,15 +17,8 @@ protocol DataGridViewDelegate: AnyObject { func dataGridUndo() func dataGridRedo() func dataGridAddRow() - func dataGridUndoInsert(at index: Int) func dataGridMoveRow(from source: Int, to destination: Int) func dataGridSortStateChanged(_ state: SortState) - /// Asks the owner to approve a change that re-points the display order before it happens. - /// - /// A pending cell edit is recorded against a display row, so anything that changes which row - /// a position names re-points it: the tint moves and a later edit at that position merges - /// into another row's change. Sort, pagination and the WHERE filter already confirm; a grid - /// with no owner has no edits to lose and runs the work directly. func dataGridConfirmDisplayOrderChange(then apply: @escaping () -> Void) func dataGridFilterColumn(_ columnName: String) func dataGridNavigateFK(value: String, fkInfo: ForeignKeyInfo, openInNewTab: Bool) @@ -70,7 +63,6 @@ extension DataGridViewDelegate { func dataGridUndo() {} func dataGridRedo() {} func dataGridAddRow() {} - func dataGridUndoInsert(at index: Int) {} func dataGridMoveRow(from source: Int, to destination: Int) {} func dataGridSortStateChanged(_ state: SortState) {} func dataGridConfirmDisplayOrderChange(then apply: @escaping () -> Void) { apply() } diff --git a/TablePro/Views/Results/Extensions/DataGridView+CellCommit.swift b/TablePro/Views/Results/Extensions/DataGridView+CellCommit.swift index 88f48d07ac..9bbb5fa5bf 100644 --- a/TablePro/Views/Results/Extensions/DataGridView+CellCommit.swift +++ b/TablePro/Views/Results/Extensions/DataGridView+CellCommit.swift @@ -18,7 +18,7 @@ extension TableViewCoordinator { guard recordCellEdit(row: row, columnIndex: columnIndex, newValue: typedNewValue) != nil else { return } invalidateDisplayCache() - visualIndex.updateRow(row, from: changeManager, displayIDs: displayIDs) + updateVisualIndex(forDisplayRow: row) invalidateRowDecoration(displayRow: row) guard let tableColumnIndex = tableColumnIndex(for: columnIndex) else { return } @@ -46,11 +46,10 @@ extension TableViewCoordinator { isCommittingCellEdit = true defer { isCommittingCellEdit = false } - let storageRow = tableRowsIndex(forDisplayRow: row) let columnName = tableRows.columns[columnIndex] let originalRow = Array(displayRowValues.values) changeManager.recordCellChange( - rowIndex: row, + rowID: displayRowValues.id, columnIndex: columnIndex, columnName: columnName, oldValue: oldValue, @@ -59,7 +58,7 @@ extension TableViewCoordinator { ) var delta: Delta = .none - if let storageRow { + if let storageRow = tableRows.index(of: displayRowValues.id) { delta = tableRowsMutator { tableRows in tableRows.edit(row: storageRow, column: columnIndex, value: typedNewValue) } diff --git a/TablePro/Views/Results/Extensions/DataGridView+CellPaste.swift b/TablePro/Views/Results/Extensions/DataGridView+CellPaste.swift index 30b79fd1f5..ea274ff522 100644 --- a/TablePro/Views/Results/Extensions/DataGridView+CellPaste.swift +++ b/TablePro/Views/Results/Extensions/DataGridView+CellPaste.swift @@ -42,7 +42,7 @@ extension TableViewCoordinator { for (gridRow, rowValues) in grid.enumerated() { let targetRow = anchorRow + gridRow guard targetRow < maxRow else { break } - guard !changeManager.isRowDeleted(targetRow) else { continue } + guard !isRowDeleted(displayRow: targetRow) else { continue } for (gridCol, cellValue) in rowValues.enumerated() { let targetPosition = anchorPosition + gridCol diff --git a/TablePro/Views/Results/Extensions/DataGridView+Click.swift b/TablePro/Views/Results/Extensions/DataGridView+Click.swift index 76a3341a47..3e5bc37280 100644 --- a/TablePro/Views/Results/Extensions/DataGridView+Click.swift +++ b/TablePro/Views/Results/Extensions/DataGridView+Click.swift @@ -75,7 +75,7 @@ extension TableViewCoordinator { columnType: columnType, value: cellValue(at: row, column: columnIndex), isTableEditable: isEditable, - isRowDeleted: changeManager.isRowDeleted(row), + isRowDeleted: isRowDeleted(displayRow: row), isImmutableColumn: immutable.contains(columnName), isBinaryValue: typedValue.asBytes != nil, isForeignKey: tableRows.columnForeignKeys[columnName] != nil, @@ -89,7 +89,7 @@ extension TableViewCoordinator { func handleChevronAction(row: Int, columnIndex: Int) { guard isEditable else { return } guard row >= 0, columnIndex >= 0 else { return } - guard !changeManager.isRowDeleted(row) else { return } + guard !isRowDeleted(displayRow: row) else { return } guard let tableView else { return } guard let column = tableColumnIndex(for: columnIndex) else { return } diff --git a/TablePro/Views/Results/Extensions/DataGridView+Columns.swift b/TablePro/Views/Results/Extensions/DataGridView+Columns.swift index a21e7c2109..e84898cb9f 100644 --- a/TablePro/Views/Results/Extensions/DataGridView+Columns.swift +++ b/TablePro/Views/Results/Extensions/DataGridView+Columns.swift @@ -92,7 +92,7 @@ extension TableViewCoordinator { placeholder: DataGridCellContent.placeholder(for: rawValue) ), state: DataGridCellState( - visualState: visualState(for: row), + visualState: visualState(of: displayRow, atDisplayRow: row), isFocused: isFocused, isEditable: isEditable, isLargeDataset: isLargeDataset, diff --git a/TablePro/Views/Results/Extensions/DataGridView+Editing.swift b/TablePro/Views/Results/Extensions/DataGridView+Editing.swift index 48a6d35917..38c85fe920 100644 --- a/TablePro/Views/Results/Extensions/DataGridView+Editing.swift +++ b/TablePro/Views/Results/Extensions/DataGridView+Editing.swift @@ -17,7 +17,7 @@ extension TableViewCoordinator { guard isEditable else { return .blocked } let tableRows = tableRowsProvider() guard row >= 0, columnIndex >= 0, columnIndex < tableRows.columns.count else { return .blocked } - guard !changeManager.isRowDeleted(row) else { return .blocked } + guard !isRowDeleted(displayRow: row) else { return .blocked } guard isColumnWritable(tableRows.columns[columnIndex]) else { return .blocked } diff --git a/TablePro/Views/Results/Extensions/DataGridView+FillColumn.swift b/TablePro/Views/Results/Extensions/DataGridView+FillColumn.swift index c189968a8f..dc5f3b56c9 100644 --- a/TablePro/Views/Results/Extensions/DataGridView+FillColumn.swift +++ b/TablePro/Views/Results/Extensions/DataGridView+FillColumn.swift @@ -18,11 +18,7 @@ extension TableViewCoordinator { let tableRows = tableRowsProvider() guard columnIndex >= 0, columnIndex < tableRows.columns.count else { return } - let rowCount = Self.fillTargetRows( - rowCount: cachedRowCount, - isEditable: isEditable, - isRowDeleted: changeManager.isRowDeleted - ).count + let rowCount = fillTargetRows().count guard rowCount > 0 else { return } let columnName = tableRows.columns[columnIndex] @@ -45,11 +41,7 @@ extension TableViewCoordinator { } func applyFillColumn(columnIndex: Int, value: PluginCellValue) { - let targetRows = Self.fillTargetRows( - rowCount: cachedRowCount, - isEditable: isEditable, - isRowDeleted: changeManager.isRowDeleted - ) + let targetRows = fillTargetRows() guard !targetRows.isEmpty else { return } let undoManager = tableView?.window?.undoManager @@ -68,6 +60,16 @@ extension TableViewCoordinator { tableView?.reloadData() } + private func fillTargetRows() -> [Int] { + let tableRows = tableRowsProvider() + return Self.fillTargetRows(rowCount: cachedRowCount, isEditable: isEditable) { displayIndex in + guard let storageIndex = DisplayRowMapping.rowIndex( + forDisplay: displayIndex, displayIDs: displayIDs, in: tableRows + ) else { return false } + return changeManager.isRowDeleted(tableRows.rows[storageIndex].id) + } + } + static func fillTargetRows(rowCount: Int, isEditable: Bool, isRowDeleted: (Int) -> Bool) -> [Int] { guard isEditable, rowCount > 0 else { return [] } return (0.. RowHighlight { - guard !highlightRuleSet.isEmpty, let row = displayRow(at: displayIndex) else { return .none } + func highlight(for row: Row) -> RowHighlight { + guard !highlightRuleSet.isEmpty else { return .none } if let cached = displayCache.highlight(forID: row.id) { return cached } let resolved = highlightRuleSet.highlight(for: row.values) displayCache.setHighlight(resolved, forID: row.id) diff --git a/TablePro/Views/Results/Extensions/DataGridView+RowIdentity.swift b/TablePro/Views/Results/Extensions/DataGridView+RowIdentity.swift new file mode 100644 index 0000000000..3319dc39ab --- /dev/null +++ b/TablePro/Views/Results/Extensions/DataGridView+RowIdentity.swift @@ -0,0 +1,32 @@ +// +// DataGridView+RowIdentity.swift +// TablePro +// + +import Foundation + +extension TableViewCoordinator { + func rowID(forDisplayRow displayIndex: Int) -> RowID? { + displayRow(at: displayIndex)?.id + } + + func isRowDeleted(displayRow displayIndex: Int) -> Bool { + guard let rowID = rowID(forDisplayRow: displayIndex) else { return false } + return changeManager.isRowDeleted(rowID) + } + + func updateVisualIndex(forDisplayRow displayIndex: Int) { + guard let rowID = rowID(forDisplayRow: displayIndex) else { return } + visualIndex.updateRow(rowID, from: changeManager) + } + + /// The row's marks for a caller that has already resolved it, which every drawn cell has: + /// resolving it again costs a `TableRows` copy per cell. + func visualState(of displayed: Row, atDisplayRow row: Int) -> RowVisualState { + if let delegateState = delegate?.dataGridVisualState(forRow: row) { + return delegateState + } + guard !visualIndex.isEmpty || !highlightRuleSet.isEmpty else { return .empty } + return visualIndex.visualState(for: displayed.id).highlighted(highlight(for: displayed)) + } +} diff --git a/TablePro/Views/Results/Extensions/DataGridView+ValueFilter.swift b/TablePro/Views/Results/Extensions/DataGridView+ValueFilter.swift index 85dc0a274a..a6fa5b87d5 100644 --- a/TablePro/Views/Results/Extensions/DataGridView+ValueFilter.swift +++ b/TablePro/Views/Results/Extensions/DataGridView+ValueFilter.swift @@ -70,9 +70,6 @@ extension TableViewCoordinator { valueFilterState = state } - /// Confirmed before the state moves, not after: the alert's whole purpose is to let the reader - /// keep edits that this change would re-point, so the filter must not be written until they - /// have said yes. func applyValueFilter( _ filter: ColumnValueFilter?, columnName: String, @@ -124,7 +121,7 @@ extension TableViewCoordinator { func reloadAfterValueFilterChange() { recomputeValueFilteredIDs() updateCache() - visualIndex.rebuild(from: changeManager, displayIDs: displayIDs) + visualIndex.rebuild(from: changeManager) selectionController.clear() tableView?.reloadData() updateValueFilterHeaderIndicators() diff --git a/TablePro/Views/Results/ResultsJsonView.swift b/TablePro/Views/Results/ResultsJsonView.swift index 7504bbdb51..d96114e889 100644 --- a/TablePro/Views/Results/ResultsJsonView.swift +++ b/TablePro/Views/Results/ResultsJsonView.swift @@ -10,7 +10,7 @@ internal struct ResultsJsonView: View { let tableRows: TableRows let selectedRowIndices: Set let displayIDs: [RowID]? - let deletedRowIndices: Set + let deletedRowIDs: Set let valueFilter: GridValueFilterState let dataRevision: Int let displayRevision: Int @@ -32,7 +32,7 @@ internal struct ResultsJsonView: View { tableRows: TableRows, selectedRowIndices: Set, displayIDs: [RowID]?, - deletedRowIndices: Set, + deletedRowIDs: Set, valueFilter: GridValueFilterState, dataRevision: Int, displayRevision: Int, @@ -41,7 +41,7 @@ internal struct ResultsJsonView: View { self.tableRows = tableRows self.selectedRowIndices = selectedRowIndices self.displayIDs = displayIDs - self.deletedRowIndices = deletedRowIndices + self.deletedRowIDs = deletedRowIDs self.valueFilter = valueFilter self.dataRevision = dataRevision self.displayRevision = displayRevision @@ -58,7 +58,7 @@ internal struct ResultsJsonView: View { let dataRevision: Int let displayRevision: Int let selectedRowIndices: Set - let deletedRowIndices: Set + let deletedRowIDs: Set let valueFilter: GridValueFilterState let hiddenColumns: Set let columnOrder: [String]? @@ -69,7 +69,7 @@ internal struct ResultsJsonView: View { dataRevision: dataRevision, displayRevision: displayRevision, selectedRowIndices: selectedRowIndices, - deletedRowIndices: deletedRowIndices, + deletedRowIDs: deletedRowIDs, valueFilter: valueFilter, hiddenColumns: columnLayout.hiddenColumns, columnOrder: columnLayout.columnOrder @@ -209,7 +209,7 @@ internal struct ResultsJsonView: View { let snapshot = tableRows let ids = displayIDs let selectedIndices = selectedRowIndices - let deletedIndices = deletedRowIndices + let deletedIDs = deletedRowIDs let layout = columnLayout let result = await Task.detached(priority: .userInitiated) { @@ -217,7 +217,7 @@ internal struct ResultsJsonView: View { tableRows: snapshot, displayIDs: ids, selectedIndices: selectedIndices, - deletedIndices: deletedIndices, + deletedRowIDs: deletedIDs, columnLayout: layout ) }.value @@ -251,14 +251,14 @@ internal struct ResultsJsonView: View { tableRows: TableRows, displayIDs: [RowID]?, selectedIndices: Set, - deletedIndices: Set = [], + deletedRowIDs: Set = [], columnLayout: ColumnLayoutState ) -> RenderedJson { let output = ResultJsonSerializer.serialize( tableRows: tableRows, displayIDs: displayIDs, selectedDisplayIndices: selectedIndices, - deletedDisplayIndices: deletedIndices, + deletedRowIDs: deletedRowIDs, columns: .fromColumnLayout(columnLayout, columns: tableRows.columns) ) return RenderedJson( diff --git a/TablePro/Views/Results/RowVisualIndex.swift b/TablePro/Views/Results/RowVisualIndex.swift index 83dac3f93a..9e0d71d1c5 100644 --- a/TablePro/Views/Results/RowVisualIndex.swift +++ b/TablePro/Views/Results/RowVisualIndex.swift @@ -7,67 +7,57 @@ import Foundation @MainActor final class RowVisualIndex { - private var states: [Int: RowVisualState] = [:] + private var states: [RowID: RowVisualState] = [:] - func visualState(for row: Int) -> RowVisualState { - states[row] ?? .empty + var isEmpty: Bool { states.isEmpty } + + func visualState(for rowID: RowID) -> RowVisualState { + states[rowID] ?? .empty } func clear() { states.removeAll(keepingCapacity: true) } - func rebuild(from changeManager: AnyChangeManager, displayIDs: [RowID]?) { + func rebuild(from changeManager: AnyChangeManager) { states.removeAll(keepingCapacity: true) - let insertedRowIndices = Self.insertedRowIndices( - from: changeManager, - displayIDs: displayIDs - ) - - if !changeManager.hasChanges && insertedRowIndices.isEmpty { - return - } + let insertedRowIDs = changeManager.insertedRowIDs + guard changeManager.hasChanges || !insertedRowIDs.isEmpty else { return } for rowChange in changeManager.rowChanges { - states[rowChange.rowIndex] = Self.makeState( + states[rowChange.rowID] = Self.makeState( for: rowChange, - inserted: insertedRowIndices.contains(rowChange.rowIndex) + inserted: insertedRowIDs.contains(rowChange.rowID) ) } - for rowIndex in insertedRowIndices where states[rowIndex] == nil { - states[rowIndex] = RowVisualState( - isDeleted: false, - isInserted: true, - modifiedColumns: [] - ) + for rowID in insertedRowIDs where states[rowID] == nil { + states[rowID] = Self.insertedState } } - func updateRow(_ rowIndex: Int, from changeManager: AnyChangeManager, displayIDs: [RowID]?) { - let isInsertedDisplay = Self.isRowInsertedAtDisplayIndex( - rowIndex, - changeManager: changeManager, - displayIDs: displayIDs - ) + func updateRow(_ rowID: RowID, from changeManager: AnyChangeManager) { + let isInserted = changeManager.insertedRowIDs.contains(rowID) - if let rowChange = changeManager.rowChanges.first(where: { $0.rowIndex == rowIndex }) { - states[rowIndex] = Self.makeState(for: rowChange, inserted: isInsertedDisplay) + if let rowChange = changeManager.rowChanges.first(where: { $0.rowID == rowID }) { + states[rowID] = Self.makeState(for: rowChange, inserted: isInserted) return } - if isInsertedDisplay { - states[rowIndex] = RowVisualState( - isDeleted: false, - isInserted: true, - modifiedColumns: [] - ) + if isInserted { + states[rowID] = Self.insertedState } else { - states.removeValue(forKey: rowIndex) + states.removeValue(forKey: rowID) } } + private static let insertedState = RowVisualState( + isDeleted: false, + isInserted: true, + modifiedColumns: [] + ) + private static func makeState(for rowChange: RowChange, inserted: Bool) -> RowVisualState { let isDeleted = rowChange.type == .delete let isInserted = inserted || rowChange.type == .insert @@ -80,28 +70,4 @@ final class RowVisualIndex { modifiedColumns: modifiedColumns ) } - - private static func insertedRowIndices( - from changeManager: AnyChangeManager, - displayIDs: [RowID]? - ) -> Set { - guard let displayIDs else { return changeManager.insertedRowIndices } - var indices = Set() - for (displayIndex, id) in displayIDs.enumerated() where id.isInserted { - indices.insert(displayIndex) - } - return indices - } - - private static func isRowInsertedAtDisplayIndex( - _ rowIndex: Int, - changeManager: AnyChangeManager, - displayIDs: [RowID]? - ) -> Bool { - if let displayIDs { - guard rowIndex >= 0, rowIndex < displayIDs.count else { return false } - return displayIDs[rowIndex].isInserted - } - return changeManager.insertedRowIndices.contains(rowIndex) - } } diff --git a/TableProTests/Core/ChangeTracking/AnyChangeManagerTests.swift b/TableProTests/Core/ChangeTracking/AnyChangeManagerTests.swift index 1f85196441..5ece352754 100644 --- a/TableProTests/Core/ChangeTracking/AnyChangeManagerTests.swift +++ b/TableProTests/Core/ChangeTracking/AnyChangeManagerTests.swift @@ -23,7 +23,7 @@ struct AnyChangeManagerTests { #expect(wrapper.hasChanges == false) - dataManager.recordCellChange(rowIndex: 0, columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob") + dataManager.recordCellChange(rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob") #expect(dataManager.hasChanges == true) #expect(wrapper.hasChanges == true) @@ -47,11 +47,11 @@ struct AnyChangeManagerTests { dataManager.configureForTable(tableName: "users", columns: ["id", "name"], primaryKeyColumns: ["id"], databaseType: .mysql, generatedColumns: []) let wrapper = AnyChangeManager(dataManager) - #expect(wrapper.isRowDeleted(0) == false) + #expect(wrapper.isRowDeleted(.existing(0)) == false) - dataManager.recordRowDeletion(rowIndex: 0, originalRow: ["1", "Alice"]) + dataManager.recordRowDeletion(rowID: .existing(0), originalRow: ["1", "Alice"]) - #expect(wrapper.isRowDeleted(0) == true) + #expect(wrapper.isRowDeleted(.existing(0)) == true) } @Test("recordCellChange forwards to DataChangeManager") @@ -60,7 +60,7 @@ struct AnyChangeManagerTests { dataManager.configureForTable(tableName: "users", columns: ["id", "name"], primaryKeyColumns: ["id"], databaseType: .mysql, generatedColumns: []) let wrapper = AnyChangeManager(dataManager) - wrapper.recordCellChange(rowIndex: 0, columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob", originalRow: ["1", "Alice"]) + wrapper.recordCellChange(rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob", originalRow: ["1", "Alice"]) #expect(dataManager.hasChanges == true) #expect(!wrapper.rowChanges.isEmpty) @@ -89,8 +89,8 @@ struct AnyChangeManagerTests { let structureManager = StructureChangeManager() let wrapper = AnyChangeManager(structureManager) - #expect(wrapper.isRowDeleted(0) == false) - #expect(wrapper.isRowDeleted(100) == false) + #expect(wrapper.isRowDeleted(.existing(0)) == false) + #expect(wrapper.isRowDeleted(.existing(100)) == false) } @Test("StructureChangeManager wrapper: hasChanges forwards correctly when false") diff --git a/TableProTests/Core/ChangeTracking/DataChangeManagerClickHouseTests.swift b/TableProTests/Core/ChangeTracking/DataChangeManagerClickHouseTests.swift index 865541fb4a..8ad21e2df3 100644 --- a/TableProTests/Core/ChangeTracking/DataChangeManagerClickHouseTests.swift +++ b/TableProTests/Core/ChangeTracking/DataChangeManagerClickHouseTests.swift @@ -26,7 +26,7 @@ struct DataChangeManagerClickHouseTests { ) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "status", oldValue: "pending", @@ -52,7 +52,7 @@ struct DataChangeManagerClickHouseTests { ) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", diff --git a/TableProTests/Core/ChangeTracking/DataChangeManagerExtendedTests.swift b/TableProTests/Core/ChangeTracking/DataChangeManagerExtendedTests.swift index f530a83f6a..73fb6b5c4f 100644 --- a/TableProTests/Core/ChangeTracking/DataChangeManagerExtendedTests.swift +++ b/TableProTests/Core/ChangeTracking/DataChangeManagerExtendedTests.swift @@ -37,33 +37,33 @@ struct DataChangeManagerExtendedTests { @Test("Record row insertion sets hasChanges to true") func recordRowInsertionSetsHasChanges() { let manager = makeManager() - manager.recordRowInsertion(rowIndex: 5, values: ["a", "b", "c"]) + manager.recordRowInsertion(rowID: insertedID(5), values: ["a", "b", "c"]) #expect(manager.hasChanges) } @Test("Record row insertion stores values in insertedRowData") func recordRowInsertionStoresInInsertedRowData() { let manager = makeManager() - manager.recordRowInsertion(rowIndex: 5, values: ["a", "b", "c"]) + manager.recordRowInsertion(rowID: insertedID(5), values: ["a", "b", "c"]) let state = manager.saveState() - #expect(state.insertedRowData[5] == ["a", "b", "c"]) + #expect(state.insertedRowData[insertedID(5)] == ["a", "b", "c"]) } @Test("Record row insertion adds insert-type change with empty cellChanges") func recordRowInsertionAddsInsertChange() { let manager = makeManager() - manager.recordRowInsertion(rowIndex: 5, values: ["a", "b", "c"]) + manager.recordRowInsertion(rowID: insertedID(5), values: ["a", "b", "c"]) #expect(manager.changes.count == 1) #expect(manager.changes[0].type == .insert) #expect(manager.changes[0].cellChanges.isEmpty) } - @Test("Record row insertion tracks index in insertedRowIndices") + @Test("Record row insertion tracks index in insertedRowIDs") func recordRowInsertionTracksInInsertedRowIndices() { let manager = makeManager() - manager.recordRowInsertion(rowIndex: 5, values: ["a", "b", "c"]) - #expect(manager.isRowInserted(5)) - #expect(!manager.isRowInserted(0)) + manager.recordRowInsertion(rowID: insertedID(5), values: ["a", "b", "c"]) + #expect(manager.isRowInserted(insertedID(5))) + #expect(!manager.isRowInserted(.existing(0))) } @Test("Record row insertion increments reloadVersion by 1") @@ -76,7 +76,7 @@ struct DataChangeManagerExtendedTests { let manager = makeManager() let before = manager.reloadVersion - manager.recordRowInsertion(rowIndex: 5, values: ["a", "b", "c"]) + manager.recordRowInsertion(rowID: insertedID(5), values: ["a", "b", "c"]) #expect(manager.reloadVersion == before) @@ -88,7 +88,7 @@ struct DataChangeManagerExtendedTests { @Test("Record row insertion enables undo") func recordRowInsertionEnablesUndo() { let manager = makeManager() - manager.recordRowInsertion(rowIndex: 5, values: ["a", "b", "c"]) + manager.recordRowInsertion(rowID: insertedID(5), values: ["a", "b", "c"]) #expect(manager.canUndo) } @@ -96,20 +96,20 @@ struct DataChangeManagerExtendedTests { func recordRowInsertionClearsRedoStack() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "A", newValue: "B" ) manager.undoManagerProvider?()?.undo() #expect(manager.canRedo) - manager.recordRowInsertion(rowIndex: 5, values: ["a", "b", "c"]) + manager.recordRowInsertion(rowID: insertedID(5), values: ["a", "b", "c"]) #expect(!manager.canRedo) } @Test("Multiple row insertions tracked separately") func multipleRowInsertionsTrackedSeparately() { let manager = makeManager() - manager.recordRowInsertion(rowIndex: 0, values: ["a", "b", "c"]) - manager.recordRowInsertion(rowIndex: 1, values: ["d", "e", "f"]) + manager.recordRowInsertion(rowID: insertedID(0), values: ["a", "b", "c"]) + manager.recordRowInsertion(rowID: insertedID(1), values: ["d", "e", "f"]) #expect(manager.changes.count == 2) #expect(manager.changes[0].type == .insert) #expect(manager.changes[1].type == .insert) @@ -120,75 +120,75 @@ struct DataChangeManagerExtendedTests { @Test("isRowDeleted returns true for deleted row, false for others") func isRowDeletedCorrectness() { let manager = makeManager() - manager.recordRowDeletion(rowIndex: 2, originalRow: ["3", "Charlie", "c@test.com"]) - #expect(manager.isRowDeleted(2)) - #expect(!manager.isRowDeleted(0)) + manager.recordRowDeletion(rowID: .existing(2), originalRow: ["3", "Charlie", "c@test.com"]) + #expect(manager.isRowDeleted(.existing(2))) + #expect(!manager.isRowDeleted(.existing(0))) } @Test("isRowInserted returns true for inserted row, false for others") func isRowInsertedCorrectness() { let manager = makeManager() - manager.recordRowInsertion(rowIndex: 5, values: ["a", "b", "c"]) - #expect(manager.isRowInserted(5)) - #expect(!manager.isRowInserted(0)) + manager.recordRowInsertion(rowID: insertedID(5), values: ["a", "b", "c"]) + #expect(manager.isRowInserted(insertedID(5))) + #expect(!manager.isRowInserted(.existing(0))) } @Test("isCellModified returns true after edit, false for unmodified cells") func isCellModifiedTrueAfterEdit() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) - #expect(manager.isCellModified(rowIndex: 0, columnIndex: 1)) - #expect(!manager.isCellModified(rowIndex: 0, columnIndex: 0)) + #expect(manager.isCellModified(rowID: .existing(0), columnIndex: 1)) + #expect(!manager.isCellModified(rowID: .existing(0), columnIndex: 0)) } @Test("isCellModified returns false after reverting to original value") func isCellModifiedFalseAfterRevertToOriginal() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "A", newValue: "B" ) manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "B", newValue: "A" ) - #expect(!manager.isCellModified(rowIndex: 0, columnIndex: 1)) + #expect(!manager.isCellModified(rowID: .existing(0), columnIndex: 1)) } @Test("getModifiedColumnsForRow returns correct set of modified columns") func getModifiedColumnsCorrectSet() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) manager.recordCellChange( - rowIndex: 0, columnIndex: 2, columnName: "email", + rowID: .existing(0), columnIndex: 2, columnName: "email", oldValue: "a@test.com", newValue: "b@test.com" ) - #expect(manager.getModifiedColumnsForRow(0) == [1, 2]) + #expect(manager.getModifiedColumnsForRow(.existing(0)) == [1, 2]) } @Test("getModifiedColumnsForRow returns empty set for unmodified row") func getModifiedColumnsEmptyForUnmodifiedRow() { let manager = makeManager() - #expect(manager.getModifiedColumnsForRow(99).isEmpty) + #expect(manager.getModifiedColumnsForRow(.existing(99)).isEmpty) } @Test("Cell modification cleared when row is deleted") func cellModificationClearedOnRowDeletion() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) - #expect(manager.isCellModified(rowIndex: 0, columnIndex: 1)) - manager.recordRowDeletion(rowIndex: 0, originalRow: ["1", "Bob", "a@test.com"]) - #expect(!manager.isCellModified(rowIndex: 0, columnIndex: 1)) - #expect(manager.getModifiedColumnsForRow(0).isEmpty) + #expect(manager.isCellModified(rowID: .existing(0), columnIndex: 1)) + manager.recordRowDeletion(rowID: .existing(0), originalRow: ["1", "Bob", "a@test.com"]) + #expect(!manager.isCellModified(rowID: .existing(0), columnIndex: 1)) + #expect(manager.getModifiedColumnsForRow(.existing(0)).isEmpty) } // MARK: - State Save/Restore @@ -197,7 +197,7 @@ struct DataChangeManagerExtendedTests { func saveStateCapturesChanges() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) let state = manager.saveState() @@ -208,36 +208,36 @@ struct DataChangeManagerExtendedTests { @Test("saveState captures deleted row indices") func saveStateCapturesDeletedRowIndices() { let manager = makeManager() - manager.recordRowDeletion(rowIndex: 2, originalRow: ["3", "Charlie", "c@test.com"]) + manager.recordRowDeletion(rowID: .existing(2), originalRow: ["3", "Charlie", "c@test.com"]) let state = manager.saveState() - #expect(state.deletedRowIndices.contains(2)) + #expect(state.deletedRowIDs.contains(.existing(2))) } @Test("saveState captures inserted row indices") func saveStateCapturesInsertedRowIndices() { let manager = makeManager() - manager.recordRowInsertion(rowIndex: 0, values: ["a", "b", "c"]) + manager.recordRowInsertion(rowID: insertedID(0), values: ["a", "b", "c"]) let state = manager.saveState() - #expect(state.insertedRowIndices.contains(0)) + #expect(state.insertedRowIDs.contains(insertedID(0))) } @Test("saveState captures modified cells") func saveStateCapturesModifiedCells() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) let state = manager.saveState() - #expect(state.modifiedCells[0]?.contains(1) == true) + #expect(state.modifiedCells[.existing(0)]?.contains(1) == true) } @Test("saveState captures inserted row data") func saveStateCapturesInsertedRowData() { let manager = makeManager() - manager.recordRowInsertion(rowIndex: 0, values: ["x", "y", "z"]) + manager.recordRowInsertion(rowID: insertedID(0), values: ["x", "y", "z"]) let state = manager.saveState() - #expect(state.insertedRowData[0] == ["x", "y", "z"]) + #expect(state.insertedRowData[insertedID(0)] == ["x", "y", "z"]) } @Test("saveState captures columns and primary key") @@ -252,7 +252,7 @@ struct DataChangeManagerExtendedTests { func roundTripPreservesHasChanges() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) let state = manager.saveState() @@ -265,38 +265,38 @@ struct DataChangeManagerExtendedTests { @Test("Round-trip save/restore preserves isRowDeleted") func roundTripPreservesIsRowDeleted() { let manager = makeManager() - manager.recordRowDeletion(rowIndex: 2, originalRow: ["3", "Charlie", "c@test.com"]) + manager.recordRowDeletion(rowID: .existing(2), originalRow: ["3", "Charlie", "c@test.com"]) let state = manager.saveState() manager.clearChanges() manager.restoreState(from: state, tableName: "test_table", databaseType: .mysql, generatedColumns: []) - #expect(manager.isRowDeleted(2)) + #expect(manager.isRowDeleted(.existing(2))) } @Test("Round-trip save/restore preserves isCellModified") func roundTripPreservesIsCellModified() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) let state = manager.saveState() manager.clearChanges() manager.restoreState(from: state, tableName: "test_table", databaseType: .mysql, generatedColumns: []) - #expect(manager.isCellModified(rowIndex: 0, columnIndex: 1)) + #expect(manager.isCellModified(rowID: .existing(0), columnIndex: 1)) } @Test("Round-trip save/restore allows continued editing") func roundTripCanContinueEditing() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) let state = manager.saveState() manager.clearChanges() manager.restoreState(from: state, tableName: "test_table", databaseType: .mysql, generatedColumns: []) manager.recordCellChange( - rowIndex: 0, columnIndex: 2, columnName: "email", + rowID: .existing(0), columnIndex: 2, columnName: "email", oldValue: "a@test.com", newValue: "b@test.com" ) #expect(manager.changes.count == 1) @@ -318,7 +318,7 @@ struct DataChangeManagerExtendedTests { func discardChangesSetsHasChangesFalse() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) manager.discardChanges() @@ -329,16 +329,16 @@ struct DataChangeManagerExtendedTests { func discardChangesClearsAllTrackedChanges() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) - manager.recordRowDeletion(rowIndex: 1, originalRow: ["2", "Charlie", "c@test.com"]) - manager.recordRowInsertion(rowIndex: 5, values: ["x", "y", "z"]) + manager.recordRowDeletion(rowID: .existing(1), originalRow: ["2", "Charlie", "c@test.com"]) + manager.recordRowInsertion(rowID: insertedID(5), values: ["x", "y", "z"]) manager.discardChanges() #expect(manager.changes.isEmpty) - #expect(!manager.isRowDeleted(1)) - #expect(!manager.isRowInserted(5)) - #expect(!manager.isCellModified(rowIndex: 0, columnIndex: 1)) + #expect(!manager.isRowDeleted(.existing(1))) + #expect(!manager.isRowInserted(insertedID(5))) + #expect(!manager.isCellModified(rowID: .existing(0), columnIndex: 1)) } @Test("only clearChangesAndUndoHistory drops the undo stack") @@ -346,7 +346,7 @@ struct DataChangeManagerExtendedTests { // discardChanges preserves undo/redo let manager1 = makeManager() manager1.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) manager1.undoManagerProvider?()?.undo() @@ -360,7 +360,7 @@ struct DataChangeManagerExtendedTests { /// `clearChanges` wiped undo, which would make the two indistinguishable. let manager2 = makeManager() manager2.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) manager2.undoManagerProvider?()?.undo() @@ -377,7 +377,7 @@ struct DataChangeManagerExtendedTests { func discardChangesIncrementsReloadVersion() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) let before = manager.reloadVersion @@ -389,16 +389,16 @@ struct DataChangeManagerExtendedTests { func discardChangesAllQueryMethodsReturnDefaults() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) - manager.recordRowDeletion(rowIndex: 1, originalRow: ["2", "Charlie", "c@test.com"]) - manager.recordRowInsertion(rowIndex: 5, values: ["x", "y", "z"]) + manager.recordRowDeletion(rowID: .existing(1), originalRow: ["2", "Charlie", "c@test.com"]) + manager.recordRowInsertion(rowID: insertedID(5), values: ["x", "y", "z"]) manager.discardChanges() - #expect(!manager.isRowDeleted(1)) - #expect(!manager.isRowInserted(5)) - #expect(!manager.isCellModified(rowIndex: 0, columnIndex: 1)) - #expect(manager.getModifiedColumnsForRow(0).isEmpty) + #expect(!manager.isRowDeleted(.existing(1))) + #expect(!manager.isRowInserted(insertedID(5))) + #expect(!manager.isCellModified(rowID: .existing(0), columnIndex: 1)) + #expect(manager.getModifiedColumnsForRow(.existing(0)).isEmpty) #expect(manager.getOriginalValues().isEmpty) } @@ -408,11 +408,11 @@ struct DataChangeManagerExtendedTests { func multipleSequentialUndos() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) manager.recordCellChange( - rowIndex: 1, columnIndex: 1, columnName: "name", + rowID: .existing(1), columnIndex: 1, columnName: "name", oldValue: "Charlie", newValue: "Dave" ) manager.undoManagerProvider?()?.undo() @@ -425,7 +425,7 @@ struct DataChangeManagerExtendedTests { func undoCellEditThenRedoRestoresChange() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "A", newValue: "B" ) manager.undoManagerProvider?()?.undo() @@ -435,51 +435,51 @@ struct DataChangeManagerExtendedTests { #expect(manager.changes[0].cellChanges[0].newValue == "B") } - @Test("Undo row insertion removes from insertedRowIndices") + @Test("Undo row insertion removes from insertedRowIDs") func undoRowInsertionRemovesFromIndices() { let manager = makeManager() - manager.recordRowInsertion(rowIndex: 5, values: ["a", "b", "c"]) + manager.recordRowInsertion(rowID: insertedID(5), values: ["a", "b", "c"]) manager.undoManagerProvider?()?.undo() - #expect(!manager.isRowInserted(5)) + #expect(!manager.isRowInserted(insertedID(5))) } - @Test("Undo row deletion removes from deletedRowIndices") + @Test("Undo row deletion removes from deletedRowIDs") func undoRowDeletionRemovesFromIndices() { let manager = makeManager() - manager.recordRowDeletion(rowIndex: 2, originalRow: ["3", "Charlie", "c@test.com"]) + manager.recordRowDeletion(rowID: .existing(2), originalRow: ["3", "Charlie", "c@test.com"]) manager.undoManagerProvider?()?.undo() - #expect(!manager.isRowDeleted(2)) + #expect(!manager.isRowDeleted(.existing(2))) } @Test("Undo row insertion then redo re-inserts the row") func undoRowInsertionThenRedoReInserts() { let manager = makeManager() - manager.recordRowInsertion(rowIndex: 5, values: ["a", "b", "c"]) + manager.recordRowInsertion(rowID: insertedID(5), values: ["a", "b", "c"]) manager.undoManagerProvider?()?.undo() - #expect(!manager.isRowInserted(5)) + #expect(!manager.isRowInserted(insertedID(5))) manager.undoManagerProvider?()?.redo() - #expect(manager.isRowInserted(5)) + #expect(manager.isRowInserted(insertedID(5))) } @Test("Undo row deletion then redo re-deletes the row") func undoRowDeletionThenRedoReDeletes() { let manager = makeManager() - manager.recordRowDeletion(rowIndex: 2, originalRow: ["3", "Charlie", "c@test.com"]) + manager.recordRowDeletion(rowID: .existing(2), originalRow: ["3", "Charlie", "c@test.com"]) manager.undoManagerProvider?()?.undo() - #expect(!manager.isRowDeleted(2)) + #expect(!manager.isRowDeleted(.existing(2))) manager.undoManagerProvider?()?.redo() - #expect(manager.isRowDeleted(2)) + #expect(manager.isRowDeleted(.existing(2))) } @Test("Full undo/redo chain: edit A, edit B, undo B, undo A, redo A, redo B") func fullUndoRedoChainABUndoBUndoARedoARedoB() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "A2" ) manager.recordCellChange( - rowIndex: 1, columnIndex: 1, columnName: "name", + rowID: .existing(1), columnIndex: 1, columnName: "name", oldValue: "Bob", newValue: "B2" ) #expect(manager.changes.count == 2) @@ -503,7 +503,7 @@ struct DataChangeManagerExtendedTests { var captured: UndoResult? manager.onUndoApplied = { captured = $0 } manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) manager.undoManagerProvider?()?.undo() @@ -517,7 +517,7 @@ struct DataChangeManagerExtendedTests { let manager = makeManager() var captured: UndoResult? manager.onUndoApplied = { captured = $0 } - manager.recordRowInsertion(rowIndex: 5, values: ["a", "b", "c"]) + manager.recordRowInsertion(rowID: insertedID(5), values: ["a", "b", "c"]) manager.undoManagerProvider?()?.undo() #expect(captured != nil) #expect(captured?.needsRowRemoval == true) @@ -528,7 +528,7 @@ struct DataChangeManagerExtendedTests { let manager = makeManager() var captured: UndoResult? manager.onUndoApplied = { captured = $0 } - manager.recordRowDeletion(rowIndex: 0, originalRow: ["1", "Alice"]) + manager.recordRowDeletion(rowID: .existing(0), originalRow: ["1", "Alice"]) manager.undoManagerProvider?()?.undo() #expect(captured != nil) #expect(captured?.needsRowRestore == true) @@ -563,56 +563,56 @@ struct DataChangeManagerExtendedTests { func editThenDeleteSameRow() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) - manager.recordRowDeletion(rowIndex: 0, originalRow: ["1", "Bob", "a@test.com"]) + manager.recordRowDeletion(rowID: .existing(0), originalRow: ["1", "Bob", "a@test.com"]) #expect(manager.changes.count == 1) #expect(manager.changes[0].type == .delete) - #expect(!manager.isCellModified(rowIndex: 0, columnIndex: 1)) + #expect(!manager.isCellModified(rowID: .existing(0), columnIndex: 1)) } @Test("Insert then edit updates insertedRowData") func insertThenEditUpdatesInsertedRowData() { let manager = makeManager() - manager.recordRowInsertion(rowIndex: 0, values: ["", "", ""]) + manager.recordRowInsertion(rowID: insertedID(0), values: ["", "", ""]) manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: insertedID(0), columnIndex: 1, columnName: "name", oldValue: nil, newValue: "hello" ) #expect(manager.changes.count == 1) #expect(manager.changes[0].type == .insert) let state = manager.saveState() - #expect(state.insertedRowData[0]?[1] == "hello") + #expect(state.insertedRowData[insertedID(0)]?[1] == "hello") } @Test("Insert then edit then undo reverts inserted row cell data") func insertThenEditThenUndoRevertsCell() { let manager = makeManager() - manager.recordRowInsertion(rowIndex: 0, values: [nil, nil, nil]) + manager.recordRowInsertion(rowID: insertedID(0), values: [nil, nil, nil]) manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: insertedID(0), columnIndex: 1, columnName: "name", oldValue: nil, newValue: "hello" ) manager.undoManagerProvider?()?.undo() let state = manager.saveState() /// `.null`, not a Swift nil. An inserted row holds an explicit SQL NULL for a cell with no /// value, so undoing an edit restores `.null` rather than removing the entry. - #expect(state.insertedRowData[0]?[1] == .null) + #expect(state.insertedRowData[insertedID(0)]?[1] == .null) } @Test("Edit multiple cells in same row all tracked") func editMultipleCellsSameRowAllTracked() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) manager.recordCellChange( - rowIndex: 0, columnIndex: 2, columnName: "email", + rowID: .existing(0), columnIndex: 2, columnName: "email", oldValue: "a@test.com", newValue: "b@test.com" ) - #expect(manager.getModifiedColumnsForRow(0) == [1, 2]) + #expect(manager.getModifiedColumnsForRow(.existing(0)) == [1, 2]) #expect(manager.changes[0].cellChanges.count == 2) } @@ -620,79 +620,79 @@ struct DataChangeManagerExtendedTests { func editMultipleCellsRevertOneOnlyRevertedRemoved() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "A", newValue: "B" ) manager.recordCellChange( - rowIndex: 0, columnIndex: 2, columnName: "email", + rowID: .existing(0), columnIndex: 2, columnName: "email", oldValue: "C", newValue: "D" ) manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "B", newValue: "A" ) - #expect(manager.getModifiedColumnsForRow(0) == [2]) - #expect(!manager.isCellModified(rowIndex: 0, columnIndex: 1)) + #expect(manager.getModifiedColumnsForRow(.existing(0)) == [2]) + #expect(!manager.isCellModified(rowID: .existing(0), columnIndex: 1)) } @Test("Batch deletion clears prior edits for deleted rows") func batchDeletionClearsPriorEdits() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "A2" ) manager.recordCellChange( - rowIndex: 1, columnIndex: 1, columnName: "name", + rowID: .existing(1), columnIndex: 1, columnName: "name", oldValue: "Bob", newValue: "B2" ) manager.recordCellChange( - rowIndex: 2, columnIndex: 1, columnName: "name", + rowID: .existing(2), columnIndex: 1, columnName: "name", oldValue: "Charlie", newValue: "C2" ) manager.recordBatchRowDeletion(rows: [ - (rowIndex: 0, originalRow: ["1", "A2", "a@test.com"]), - (rowIndex: 1, originalRow: ["2", "B2", "b@test.com"]) + (rowID: .existing(0), originalRow: ["1", "A2", "a@test.com"]), + (rowID: .existing(1), originalRow: ["2", "B2", "b@test.com"]) ]) - #expect(manager.isRowDeleted(0)) - #expect(manager.isRowDeleted(1)) - #expect(!manager.isCellModified(rowIndex: 0, columnIndex: 1)) - #expect(!manager.isCellModified(rowIndex: 1, columnIndex: 1)) - #expect(manager.isCellModified(rowIndex: 2, columnIndex: 1)) + #expect(manager.isRowDeleted(.existing(0))) + #expect(manager.isRowDeleted(.existing(1))) + #expect(!manager.isCellModified(rowID: .existing(0), columnIndex: 1)) + #expect(!manager.isCellModified(rowID: .existing(1), columnIndex: 1)) + #expect(manager.isCellModified(rowID: .existing(2), columnIndex: 1)) } @Test("Undo batch deletion restores all rows") func undoBatchDeletionRestoresAllRows() { let manager = makeManager() manager.recordBatchRowDeletion(rows: [ - (rowIndex: 0, originalRow: ["1", "Alice", "a@test.com"]), - (rowIndex: 1, originalRow: ["2", "Bob", "b@test.com"]), - (rowIndex: 2, originalRow: ["3", "Charlie", "c@test.com"]) + (rowID: .existing(0), originalRow: ["1", "Alice", "a@test.com"]), + (rowID: .existing(1), originalRow: ["2", "Bob", "b@test.com"]), + (rowID: .existing(2), originalRow: ["3", "Charlie", "c@test.com"]) ]) manager.undoManagerProvider?()?.undo() - #expect(!manager.isRowDeleted(0)) - #expect(!manager.isRowDeleted(1)) - #expect(!manager.isRowDeleted(2)) + #expect(!manager.isRowDeleted(.existing(0))) + #expect(!manager.isRowDeleted(.existing(1))) + #expect(!manager.isRowDeleted(.existing(2))) } @Test("getOriginalValues returns correct data for edits") func getOriginalValuesReturnsCorrectData() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "A", newValue: "B" ) manager.recordCellChange( - rowIndex: 1, columnIndex: 2, columnName: "email", + rowID: .existing(1), columnIndex: 2, columnName: "email", oldValue: "C", newValue: "D" ) - manager.recordRowDeletion(rowIndex: 2, originalRow: ["3", "Charlie", "c@test.com"]) + manager.recordRowDeletion(rowID: .existing(2), originalRow: ["3", "Charlie", "c@test.com"]) let originals = manager.getOriginalValues() #expect(originals.count == 2) - let first = originals.first { $0.rowIndex == 0 } + let first = originals.first { $0.rowID == .existing(0) } #expect(first?.columnIndex == 1) #expect(first?.value == "A") - let second = originals.first { $0.rowIndex == 1 } + let second = originals.first { $0.rowID == .existing(1) } #expect(second?.columnIndex == 2) #expect(second?.value == "C") } @@ -702,8 +702,8 @@ struct DataChangeManagerExtendedTests { @Test("Recording deletion for already-deleted row is idempotent") func recordDeletionForAlreadyDeletedRow() { let manager = makeManager() - manager.recordRowDeletion(rowIndex: 0, originalRow: ["1", "Alice", "a@test.com"]) - manager.recordRowDeletion(rowIndex: 0, originalRow: ["1", "Alice", "a@test.com"]) + manager.recordRowDeletion(rowID: .existing(0), originalRow: ["1", "Alice", "a@test.com"]) + manager.recordRowDeletion(rowID: .existing(0), originalRow: ["1", "Alice", "a@test.com"]) #expect(manager.changes.count == 1) } @@ -725,12 +725,12 @@ struct DataChangeManagerExtendedTests { @Test("Concurrent insertions at different indices all tracked") func concurrentInsertionsAtDifferentIndices() { let manager = makeManager() - manager.recordRowInsertion(rowIndex: 0, values: ["a", "b", "c"]) - manager.recordRowInsertion(rowIndex: 5, values: ["d", "e", "f"]) - manager.recordRowInsertion(rowIndex: 10, values: ["g", "h", "i"]) - #expect(manager.isRowInserted(0)) - #expect(manager.isRowInserted(5)) - #expect(manager.isRowInserted(10)) + manager.recordRowInsertion(rowID: insertedID(0), values: ["a", "b", "c"]) + manager.recordRowInsertion(rowID: insertedID(5), values: ["d", "e", "f"]) + manager.recordRowInsertion(rowID: insertedID(10), values: ["g", "h", "i"]) + #expect(manager.isRowInserted(insertedID(0))) + #expect(manager.isRowInserted(insertedID(5))) + #expect(manager.isRowInserted(insertedID(10))) #expect(manager.changes.count == 3) } @@ -738,7 +738,7 @@ struct DataChangeManagerExtendedTests { func recordCellChangeNilToNilIsNoOp() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: nil, newValue: nil ) #expect(!manager.hasChanges) @@ -750,10 +750,10 @@ struct DataChangeManagerExtendedTests { func invariantModifiedCellsConsistentWithChangesAfterEdit() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) - #expect(manager.isCellModified(rowIndex: 0, columnIndex: 1)) + #expect(manager.isCellModified(rowID: .existing(0), columnIndex: 1)) #expect(manager.changes[0].cellChanges.contains { $0.columnIndex == 1 }) } @@ -761,24 +761,24 @@ struct DataChangeManagerExtendedTests { func invariantModifiedCellsClearedWhenAllReverted() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) manager.recordCellChange( - rowIndex: 0, columnIndex: 2, columnName: "email", + rowID: .existing(0), columnIndex: 2, columnName: "email", oldValue: "a@test.com", newValue: "b@test.com" ) manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Bob", newValue: "Alice" ) manager.recordCellChange( - rowIndex: 0, columnIndex: 2, columnName: "email", + rowID: .existing(0), columnIndex: 2, columnName: "email", oldValue: "b@test.com", newValue: "a@test.com" ) - #expect(!manager.isCellModified(rowIndex: 0, columnIndex: 1)) - #expect(!manager.isCellModified(rowIndex: 0, columnIndex: 2)) - #expect(manager.getModifiedColumnsForRow(0).isEmpty) + #expect(!manager.isCellModified(rowID: .existing(0), columnIndex: 1)) + #expect(!manager.isCellModified(rowID: .existing(0), columnIndex: 2)) + #expect(manager.getModifiedColumnsForRow(.existing(0)).isEmpty) #expect(manager.changes.isEmpty) } @@ -786,28 +786,28 @@ struct DataChangeManagerExtendedTests { func invariantAfterUndoModifiedCellsMatchChanges() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) manager.recordCellChange( - rowIndex: 0, columnIndex: 2, columnName: "email", + rowID: .existing(0), columnIndex: 2, columnName: "email", oldValue: "a@test.com", newValue: "b@test.com" ) manager.undoManagerProvider?()?.undo() - #expect(!manager.isCellModified(rowIndex: 0, columnIndex: 2)) - #expect(manager.isCellModified(rowIndex: 0, columnIndex: 1)) + #expect(!manager.isCellModified(rowID: .existing(0), columnIndex: 2)) + #expect(manager.isCellModified(rowID: .existing(0), columnIndex: 1)) } @Test("After redo, modifiedCells matches restored changes") func invariantAfterRedoModifiedCellsMatchChanges() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) manager.undoManagerProvider?()?.undo() manager.undoManagerProvider?()?.redo() - #expect(manager.isCellModified(rowIndex: 0, columnIndex: 1)) + #expect(manager.isCellModified(rowID: .existing(0), columnIndex: 1)) #expect(!manager.changes.isEmpty) } @@ -815,15 +815,15 @@ struct DataChangeManagerExtendedTests { func editUndoRedoUndoCollapses() { let manager = makeManager() manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) manager.undoManagerProvider?()?.undo() manager.undoManagerProvider?()?.redo() - #expect(manager.isCellModified(rowIndex: 0, columnIndex: 1)) + #expect(manager.isCellModified(rowID: .existing(0), columnIndex: 1)) manager.undoManagerProvider?()?.undo() - #expect(!manager.isCellModified(rowIndex: 0, columnIndex: 1)) + #expect(!manager.isCellModified(rowID: .existing(0), columnIndex: 1)) #expect(manager.changes.isEmpty) #expect(!manager.hasChanges) } @@ -831,14 +831,18 @@ struct DataChangeManagerExtendedTests { @Test("Inserted row edit consistency between changes and insertedRowData") func invariantInsertedRowEditConsistency() { let manager = makeManager() - manager.recordRowInsertion(rowIndex: 0, values: ["", "", ""]) + manager.recordRowInsertion(rowID: insertedID(0), values: ["", "", ""]) manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: insertedID(0), columnIndex: 1, columnName: "name", oldValue: nil, newValue: "hello" ) let cellChange = manager.changes[0].cellChanges.first { $0.columnIndex == 1 } #expect(cellChange?.newValue == "hello") let state = manager.saveState() - #expect(state.insertedRowData[0]?[1] == "hello") + #expect(state.insertedRowData[insertedID(0)]?[1] == "hello") } } + +private func insertedID(_ seed: Int) -> RowID { + .inserted(UUID(uuidString: String(format: "00000000-0000-0000-0000-%012d", seed)) ?? UUID()) +} diff --git a/TableProTests/Core/ChangeTracking/DataChangeManagerTests.swift b/TableProTests/Core/ChangeTracking/DataChangeManagerTests.swift index c0c5310d27..c3bdedbd34 100644 --- a/TableProTests/Core/ChangeTracking/DataChangeManagerTests.swift +++ b/TableProTests/Core/ChangeTracking/DataChangeManagerTests.swift @@ -45,7 +45,7 @@ struct DataChangeManagerTests { func generateSQLThrowsWhenDialectNotConfigured() { let manager = DataChangeManager() manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", @@ -70,7 +70,7 @@ struct DataChangeManagerTests { ) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", @@ -114,7 +114,7 @@ struct DataChangeManagerTests { ) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", @@ -136,7 +136,7 @@ struct DataChangeManagerTests { ) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", @@ -145,7 +145,7 @@ struct DataChangeManagerTests { #expect(manager.changes.count == 1) #expect(manager.changes[0].type == .update) - #expect(manager.changes[0].rowIndex == 0) + #expect(manager.changes[0].rowID == .existing(0)) #expect(manager.changes[0].cellChanges.count == 1) #expect(manager.changes[0].cellChanges[0].columnName == "name") #expect(manager.changes[0].cellChanges[0].oldValue == "Alice") @@ -164,7 +164,7 @@ struct DataChangeManagerTests { ) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", @@ -187,7 +187,7 @@ struct DataChangeManagerTests { ) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", @@ -195,7 +195,7 @@ struct DataChangeManagerTests { ) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Bob", @@ -220,7 +220,7 @@ struct DataChangeManagerTests { ) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", @@ -229,7 +229,7 @@ struct DataChangeManagerTests { #expect(manager.hasChanges) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Bob", @@ -252,7 +252,7 @@ struct DataChangeManagerTests { ) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", @@ -260,7 +260,7 @@ struct DataChangeManagerTests { ) manager.recordCellChange( - rowIndex: 1, + rowID: .existing(1), columnIndex: 1, columnName: "name", oldValue: "Charlie", @@ -268,8 +268,8 @@ struct DataChangeManagerTests { ) #expect(manager.changes.count == 2) - #expect(manager.changes[0].rowIndex == 0) - #expect(manager.changes[1].rowIndex == 1) + #expect(manager.changes[0].rowID == .existing(0)) + #expect(manager.changes[1].rowID == .existing(1)) } // MARK: - Row Deletion Tests @@ -285,7 +285,7 @@ struct DataChangeManagerTests { generatedColumns: [] ) - manager.recordRowDeletion(rowIndex: 0, originalRow: ["1", "Alice"]) + manager.recordRowDeletion(rowID: .existing(0), originalRow: ["1", "Alice"]) #expect(manager.hasChanges) } @@ -302,7 +302,7 @@ struct DataChangeManagerTests { ) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", @@ -311,11 +311,11 @@ struct DataChangeManagerTests { #expect(manager.changes.count == 1) #expect(manager.changes[0].type == .update) - manager.recordRowDeletion(rowIndex: 0, originalRow: ["1", "Bob"]) + manager.recordRowDeletion(rowID: .existing(0), originalRow: ["1", "Bob"]) #expect(manager.changes.count == 1) #expect(manager.changes[0].type == .delete) - #expect(manager.changes[0].rowIndex == 0) + #expect(manager.changes[0].rowID == .existing(0)) } @Test("Deleted row tracked in changes with type delete") @@ -329,11 +329,11 @@ struct DataChangeManagerTests { generatedColumns: [] ) - manager.recordRowDeletion(rowIndex: 2, originalRow: ["3", "Charlie"]) + manager.recordRowDeletion(rowID: .existing(2), originalRow: ["3", "Charlie"]) #expect(manager.changes.count == 1) #expect(manager.changes[0].type == .delete) - #expect(manager.changes[0].rowIndex == 2) + #expect(manager.changes[0].rowID == .existing(2)) #expect(manager.changes[0].originalRow == ["3", "Charlie"]) } @@ -348,10 +348,10 @@ struct DataChangeManagerTests { generatedColumns: [] ) - let rows: [(rowIndex: Int, originalRow: [PluginCellValue])] = [ - (rowIndex: 0, originalRow: [.text("1"), .text("Alice")]), - (rowIndex: 1, originalRow: [.text("2"), .text("Bob")]), - (rowIndex: 2, originalRow: [.text("3"), .text("Charlie")]) + let rows: [(rowID: RowID, originalRow: [PluginCellValue])] = [ + (rowID: .existing(0), originalRow: [.text("1"), .text("Alice")]), + (rowID: .existing(1), originalRow: [.text("2"), .text("Bob")]), + (rowID: .existing(2), originalRow: [.text("3"), .text("Charlie")]) ] manager.recordBatchRowDeletion(rows: rows) @@ -375,13 +375,13 @@ struct DataChangeManagerTests { ) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", newValue: "Bob" ) - manager.recordRowDeletion(rowIndex: 1, originalRow: ["2", "Charlie"]) + manager.recordRowDeletion(rowID: .existing(1), originalRow: ["2", "Charlie"]) manager.clearChanges() @@ -402,7 +402,7 @@ struct DataChangeManagerTests { ) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", @@ -429,7 +429,7 @@ struct DataChangeManagerTests { ) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", @@ -451,7 +451,7 @@ struct DataChangeManagerTests { ) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", @@ -477,7 +477,7 @@ struct DataChangeManagerTests { ) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", @@ -501,7 +501,7 @@ struct DataChangeManagerTests { ) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", @@ -512,7 +512,7 @@ struct DataChangeManagerTests { #expect(manager.canRedo) manager.recordCellChange( - rowIndex: 1, + rowID: .existing(1), columnIndex: 1, columnName: "name", oldValue: "Charlie", @@ -551,7 +551,7 @@ struct DataChangeManagerTests { let initialVersion = manager.reloadVersion manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", @@ -577,7 +577,7 @@ struct DataChangeManagerTests { ) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", @@ -615,7 +615,7 @@ struct DataChangeManagerNonWritableTests { let manager = makeManager(generatedColumns: ["id"]) manager.recordCellChange( - rowIndex: 0, columnIndex: 0, columnName: "id", + rowID: .existing(0), columnIndex: 0, columnName: "id", oldValue: .text("1"), newValue: .text("99") ) @@ -628,7 +628,7 @@ struct DataChangeManagerNonWritableTests { let manager = makeManager(generatedColumns: ["id"]) manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: .text("Alice"), newValue: .text("Bob") ) @@ -641,11 +641,11 @@ struct DataChangeManagerNonWritableTests { let manager = makeManager(generatedColumns: ["id"]) manager.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: .text("Alice"), newValue: .text("Bob") ) manager.recordCellChange( - rowIndex: 0, columnIndex: 0, columnName: "id", + rowID: .existing(0), columnIndex: 0, columnName: "id", oldValue: .text("1"), newValue: .text("99") ) diff --git a/TableProTests/Core/ChangeTracking/DataChangeModelsTests.swift b/TableProTests/Core/ChangeTracking/DataChangeModelsTests.swift index cac0a254d1..0a91f01c0b 100644 --- a/TableProTests/Core/ChangeTracking/DataChangeModelsTests.swift +++ b/TableProTests/Core/ChangeTracking/DataChangeModelsTests.swift @@ -84,13 +84,13 @@ struct DataChangeModelsTests { ) let rowChange = RowChange( - rowIndex: 3, + rowID: .existing(3), type: .update, cellChanges: [cellChange], originalRow: ["1", "active", "user@example.com"] ) - #expect(rowChange.rowIndex == 3) + #expect(rowChange.rowID == .existing(3)) #expect(rowChange.type == .update) #expect(rowChange.cellChanges.count == 1) #expect(rowChange.cellChanges[0] == cellChange) @@ -100,7 +100,7 @@ struct DataChangeModelsTests { @Test("RowChange with empty cellChanges") func rowChangeEmptyCellChanges() { let rowChange = RowChange( - rowIndex: 0, + rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil @@ -116,8 +116,8 @@ struct DataChangeModelsTests { let pending = TabChangeSnapshot() #expect(pending.changes.isEmpty) - #expect(pending.deletedRowIndices.isEmpty) - #expect(pending.insertedRowIndices.isEmpty) + #expect(pending.deletedRowIDs.isEmpty) + #expect(pending.insertedRowIDs.isEmpty) #expect(pending.modifiedCells.isEmpty) #expect(pending.insertedRowData.isEmpty) #expect(pending.primaryKeyColumns.isEmpty) @@ -134,7 +134,7 @@ struct DataChangeModelsTests { @Test("TabChangeSnapshot hasChanges is true with changes") func tabPendingChangesHasChangesWithChanges() { let rowChange = RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update ) @@ -144,18 +144,18 @@ struct DataChangeModelsTests { #expect(pending.hasChanges) } - @Test("TabChangeSnapshot hasChanges is true with deletedRowIndices") + @Test("TabChangeSnapshot hasChanges is true with deletedRowIDs") func tabPendingChangesHasChangesWithDeleted() { var pending = TabChangeSnapshot() - pending.deletedRowIndices = [1, 2, 3] + pending.deletedRowIDs = [.existing(1), .existing(2), .existing(3)] #expect(pending.hasChanges) } - @Test("TabChangeSnapshot hasChanges is true with insertedRowIndices") + @Test("TabChangeSnapshot hasChanges is true with insertedRowIDs") func tabPendingChangesHasChangesWithInserted() { var pending = TabChangeSnapshot() - pending.insertedRowIndices = [0, 1] + pending.insertedRowIDs = [.inserted(UUID()), .inserted(UUID())] #expect(pending.hasChanges) } diff --git a/TableProTests/Core/ChangeTracking/PendingChangesReindexTests.swift b/TableProTests/Core/ChangeTracking/PendingChangesReindexTests.swift deleted file mode 100644 index c5a075f56d..0000000000 --- a/TableProTests/Core/ChangeTracking/PendingChangesReindexTests.swift +++ /dev/null @@ -1,105 +0,0 @@ -// -// PendingChangesReindexTests.swift -// TableProTests -// -// Undoing one row of a pasted batch used to renumber only two of the six things PendingChanges -// keys by row index, so the survivors' values stayed filed under their old numbers and Save wrote -// one row with another row's values while dropping the rest, reporting success either way. -// - -import Foundation -import TableProPluginKit -@testable import TablePro -import Testing - -@Suite("PendingChanges - reindexing") -struct PendingChangesReindexTests { - @Test("Undoing one row of a batch leaves the survivors' values under their new indices") - func partialBatchUndoKeepsSurvivorValues() { - var pending = PendingChanges() - pending.recordRowInsertion(rowIndex: 10, values: ["a1", "a2"]) - pending.recordRowInsertion(rowIndex: 11, values: ["b1", "b2"]) - pending.recordRowInsertion(rowIndex: 12, values: ["c1", "c2"]) - - let removed = pending.undoBatchRowInsertion(rowIndices: [10], columnCount: 2) - - #expect(removed == [["a1", "a2"]]) - #expect(pending.savedInsertedValues(forRow: 10) == ["b1", "b2"]) - #expect(pending.savedInsertedValues(forRow: 11) == ["c1", "c2"]) - #expect(pending.savedInsertedValues(forRow: 12) == nil) - #expect(pending.isRowInserted(10)) - #expect(pending.isRowInserted(11)) - #expect(!pending.isRowInserted(12)) - } - - @Test("The returned values are the whole row, not only the columns that were typed into") - func partialBatchUndoReturnsWholeRow() { - var pending = PendingChanges() - pending.recordRowInsertion(rowIndex: 0, values: [.null, .null, .null, .null]) - pending.recordCellChange( - rowIndex: 0, columnIndex: 2, columnName: "name", - oldValue: .null, newValue: "Bob" - ) - - let removed = pending.undoBatchRowInsertion(rowIndices: [0], columnCount: 4) - - #expect(removed.first?.count == 4) - #expect(removed.first?[2] == "Bob") - #expect(removed.first?[0] == .null) - } - - @Test("A restored batch comes back with the values it had, not a compacted version of them") - func undoThenRedoRoundTrips() { - var pending = PendingChanges() - pending.recordRowInsertion(rowIndex: 0, values: [.null, .null, .null]) - pending.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", - oldValue: .null, newValue: "Bob" - ) - - let removed = pending.undoBatchRowInsertion(rowIndices: [0], columnCount: 3) - pending.reinsertBatch(rowIndices: [0], rowValues: removed, columns: ["id", "name", "note"]) - - #expect(pending.savedInsertedValues(forRow: 0)?.count == 3) - #expect(pending.savedInsertedValues(forRow: 0)?[1] == "Bob") - } -} - -@Suite("PendingChanges - change order") -struct PendingChangesSequenceTests { - @Test("Every recorded change gets a rising sequence number") - func sequenceRises() { - var pending = PendingChanges() - pending.recordRowDeletion(rowIndex: 0, originalRow: ["a"]) - pending.recordRowInsertion(rowIndex: 1, values: ["b"]) - - let sequences = pending.changes.map(\.sequence) - #expect(sequences == sequences.sorted()) - #expect(Set(sequences).count == sequences.count) - } - - /// A cancelled change is removed by swapping the last element into its slot, so array order - /// stops matching edit order. The sequence number is what survives that. - @Test("Cancelling a change does not disturb the order of the ones that remain") - func cancellingKeepsOrder() { - var pending = PendingChanges() - pending.recordCellChange( - rowIndex: 0, columnIndex: 0, columnName: "a", - oldValue: "before", newValue: "after", originalRow: ["before"] - ) - pending.recordRowDeletion(rowIndex: 1, originalRow: ["b"]) - pending.recordRowInsertion(rowIndex: 2, values: ["c"]) - - let deleteSequence = pending.changes.first { $0.type == .delete }?.sequence - let insertSequence = pending.changes.first { $0.type == .insert }?.sequence - - pending.recordCellChange( - rowIndex: 0, columnIndex: 0, columnName: "a", - oldValue: "after", newValue: "before", originalRow: ["before"] - ) - - #expect(pending.changes.contains { $0.type == .delete && $0.sequence == deleteSequence }) - #expect(pending.changes.contains { $0.type == .insert && $0.sequence == insertSequence }) - #expect(deleteSequence.map { seq in insertSequence.map { $0 > seq } ?? false } == true) - } -} diff --git a/TableProTests/Core/ChangeTracking/PendingChangesRowIdentityTests.swift b/TableProTests/Core/ChangeTracking/PendingChangesRowIdentityTests.swift new file mode 100644 index 0000000000..7d4976a946 --- /dev/null +++ b/TableProTests/Core/ChangeTracking/PendingChangesRowIdentityTests.swift @@ -0,0 +1,136 @@ +// +// PendingChangesRowIdentityTests.swift +// TableProTests +// + +import Foundation +import TableProPluginKit +@testable import TablePro +import Testing + +@Suite("PendingChanges - row identity") +struct PendingChangesRowIdentityTests { + @Test("Undoing one row of a batch leaves the survivors' values on their own rows") + func partialBatchUndoKeepsSurvivorValues() { + var pending = PendingChanges() + let first = RowID.inserted(UUID()) + let second = RowID.inserted(UUID()) + let third = RowID.inserted(UUID()) + pending.recordRowInsertion(rowID: first, values: ["a1", "a2"]) + pending.recordRowInsertion(rowID: second, values: ["b1", "b2"]) + pending.recordRowInsertion(rowID: third, values: ["c1", "c2"]) + + let removed = pending.undoBatchRowInsertion(rowIDs: [first], columnCount: 2) + + #expect(removed == [["a1", "a2"]]) + #expect(pending.savedInsertedValues(forRow: first) == nil) + #expect(pending.savedInsertedValues(forRow: second) == ["b1", "b2"]) + #expect(pending.savedInsertedValues(forRow: third) == ["c1", "c2"]) + #expect(!pending.isRowInserted(first)) + #expect(pending.isRowInserted(second)) + #expect(pending.isRowInserted(third)) + } + + @Test("Undoing an inserted row leaves another row's edits where they were") + func undoInsertionKeepsOtherRowsEdits() { + var pending = PendingChanges() + let inserted = RowID.inserted(UUID()) + pending.recordRowInsertion(rowID: inserted, values: [.null, .null]) + pending.recordCellChange( + rowID: .existing(4), columnIndex: 1, columnName: "name", + oldValue: "Ann", newValue: "Bea", originalRow: ["4", "Ann"] + ) + + _ = pending.undoRowInsertion(rowID: inserted) + + #expect(pending.isCellModified(rowID: .existing(4), columnIndex: 1)) + #expect(pending.change(forRow: .existing(4), type: .update)?.cellChanges.first?.newValue == "Bea") + #expect(pending.changes.count == 1) + } + + @Test("An existing row and an inserted row never share a key") + func existingAndInsertedRowsAreDistinct() { + var pending = PendingChanges() + let inserted = RowID.inserted(UUID()) + pending.recordRowDeletion(rowID: .existing(0), originalRow: ["1"]) + pending.recordRowInsertion(rowID: inserted, values: ["2"]) + + #expect(pending.isRowDeleted(.existing(0))) + #expect(!pending.isRowDeleted(inserted)) + #expect(pending.isRowInserted(inserted)) + #expect(!pending.isRowInserted(.existing(0))) + } + + @Test("The returned values are the whole row, not only the columns that were typed into") + func partialBatchUndoReturnsWholeRow() { + var pending = PendingChanges() + let inserted = RowID.inserted(UUID()) + pending.recordRowInsertion(rowID: inserted, values: [.null, .null, .null, .null]) + pending.recordCellChange( + rowID: inserted, columnIndex: 2, columnName: "name", + oldValue: .null, newValue: "Bob" + ) + + let removed = pending.undoBatchRowInsertion(rowIDs: [inserted], columnCount: 4) + + #expect(removed.first?.count == 4) + #expect(removed.first?[2] == "Bob") + #expect(removed.first?[0] == .null) + } + + @Test("A restored batch comes back with the values it had, not a compacted version of them") + func undoThenRedoRoundTrips() { + var pending = PendingChanges() + let inserted = RowID.inserted(UUID()) + pending.recordRowInsertion(rowID: inserted, values: [.null, .null, .null]) + pending.recordCellChange( + rowID: inserted, columnIndex: 1, columnName: "name", + oldValue: .null, newValue: "Bob" + ) + + let removed = pending.undoBatchRowInsertion(rowIDs: [inserted], columnCount: 3) + pending.reinsertBatch(rowIDs: [inserted], rowValues: removed, columns: ["id", "name", "note"]) + + #expect(pending.savedInsertedValues(forRow: inserted)?.count == 3) + #expect(pending.savedInsertedValues(forRow: inserted)?[1] == "Bob") + } +} + +@Suite("PendingChanges - change order") +struct PendingChangesSequenceTests { + @Test("Every recorded change gets a rising sequence number") + func sequenceRises() { + var pending = PendingChanges() + pending.recordRowDeletion(rowID: .existing(0), originalRow: ["a"]) + pending.recordRowInsertion(rowID: .inserted(UUID()), values: ["b"]) + + let sequences = pending.changes.map(\.sequence) + #expect(sequences == sequences.sorted()) + #expect(Set(sequences).count == sequences.count) + } + + /// A cancelled change is removed by swapping the last element into its slot, so array order + /// stops matching edit order. The sequence number is what survives that. + @Test("Cancelling a change does not disturb the order of the ones that remain") + func cancellingKeepsOrder() { + var pending = PendingChanges() + pending.recordCellChange( + rowID: .existing(0), columnIndex: 0, columnName: "a", + oldValue: "before", newValue: "after", originalRow: ["before"] + ) + pending.recordRowDeletion(rowID: .existing(1), originalRow: ["b"]) + pending.recordRowInsertion(rowID: .inserted(UUID()), values: ["c"]) + + let deleteSequence = pending.changes.first { $0.type == .delete }?.sequence + let insertSequence = pending.changes.first { $0.type == .insert }?.sequence + + pending.recordCellChange( + rowID: .existing(0), columnIndex: 0, columnName: "a", + oldValue: "after", newValue: "before", originalRow: ["before"] + ) + + #expect(pending.changes.contains { $0.type == .delete && $0.sequence == deleteSequence }) + #expect(pending.changes.contains { $0.type == .insert && $0.sequence == insertSequence }) + #expect(deleteSequence.map { seq in insertSequence.map { $0 > seq } ?? false } == true) + } +} diff --git a/TableProTests/Core/ChangeTracking/PendingChangesTests.swift b/TableProTests/Core/ChangeTracking/PendingChangesTests.swift index 0a06ad6301..3b2cb5b1a4 100644 --- a/TableProTests/Core/ChangeTracking/PendingChangesTests.swift +++ b/TableProTests/Core/ChangeTracking/PendingChangesTests.swift @@ -21,21 +21,21 @@ struct PendingChangesRecordTests { func recordCellCreatesUpdate() { var pending = PendingChanges() let recorded = pending.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "a", newValue: "b" ) #expect(recorded == true) #expect(pending.changes.count == 1) #expect(pending.changes[0].type == .update) - #expect(pending.isCellModified(rowIndex: 0, columnIndex: 1)) - #expect(pending.modifiedColumns(forRow: 0) == [1]) + #expect(pending.isCellModified(rowID: .existing(0), columnIndex: 1)) + #expect(pending.modifiedColumns(forRow: .existing(0)) == [1]) } @Test("No-op edit when oldValue equals newValue and no prior change") func noOpEdit() { var pending = PendingChanges() let recorded = pending.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "a", newValue: "a" ) #expect(recorded == false) @@ -46,23 +46,23 @@ struct PendingChangesRecordTests { func revertToOriginalCollapses() { var pending = PendingChanges() pending.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "a", newValue: "b" ) let collapsed = pending.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "b", newValue: "a" ) #expect(collapsed == true) #expect(pending.isEmpty) - #expect(!pending.isCellModified(rowIndex: 0, columnIndex: 1)) + #expect(!pending.isCellModified(rowID: .existing(0), columnIndex: 1)) } @Test("Recording row deletion adds delete change and marks row deleted") func recordRowDeletion() { var pending = PendingChanges() - pending.recordRowDeletion(rowIndex: 5, originalRow: ["a", "b"]) - #expect(pending.isRowDeleted(5)) + pending.recordRowDeletion(rowID: .existing(5), originalRow: ["a", "b"]) + #expect(pending.isRowDeleted(.existing(5))) #expect(pending.changes.count == 1) #expect(pending.changes[0].type == .delete) } @@ -71,40 +71,40 @@ struct PendingChangesRecordTests { func deletionRemovesUpdate() { var pending = PendingChanges() pending.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "a", newValue: "b" ) - pending.recordRowDeletion(rowIndex: 0, originalRow: ["a", nil]) + pending.recordRowDeletion(rowID: .existing(0), originalRow: ["a", nil]) #expect(pending.changes.count == 1) #expect(pending.changes[0].type == .delete) - #expect(!pending.isCellModified(rowIndex: 0, columnIndex: 1)) + #expect(!pending.isCellModified(rowID: .existing(0), columnIndex: 1)) } @Test("Recording row insertion marks row inserted") func recordRowInsertion() { var pending = PendingChanges() - pending.recordRowInsertion(rowIndex: 3, values: ["x", "y"]) - #expect(pending.isRowInserted(3)) - #expect(pending.savedInsertedValues(forRow: 3) == ["x", "y"]) + pending.recordRowInsertion(rowID: insertedID(3), values: ["x", "y"]) + #expect(pending.isRowInserted(insertedID(3))) + #expect(pending.savedInsertedValues(forRow: insertedID(3)) == ["x", "y"]) } @Test("Double deletion of the same row is idempotent") func doubleDeletionIsIdempotent() { var pending = PendingChanges() - pending.recordRowDeletion(rowIndex: 5, originalRow: ["a"]) - pending.recordRowDeletion(rowIndex: 5, originalRow: ["a"]) + pending.recordRowDeletion(rowID: .existing(5), originalRow: ["a"]) + pending.recordRowDeletion(rowID: .existing(5), originalRow: ["a"]) #expect(pending.changes.count == 1) - #expect(pending.isRowDeleted(5)) + #expect(pending.isRowDeleted(.existing(5))) } @Test("Double insertion of the same row updates stored values without duplicating") func doubleInsertionIsIdempotent() { var pending = PendingChanges() - pending.recordRowInsertion(rowIndex: 3, values: ["x"]) - pending.recordRowInsertion(rowIndex: 3, values: ["y"]) + pending.recordRowInsertion(rowID: insertedID(3), values: ["x"]) + pending.recordRowInsertion(rowID: insertedID(3), values: ["y"]) #expect(pending.changes.count == 1) - #expect(pending.isRowInserted(3)) - #expect(pending.savedInsertedValues(forRow: 3) == ["y"]) + #expect(pending.isRowInserted(insertedID(3))) + #expect(pending.savedInsertedValues(forRow: insertedID(3)) == ["y"]) } } @@ -113,46 +113,53 @@ struct PendingChangesUndoTests { @Test("Undo row deletion clears delete state") func undoRowDeletion() { var pending = PendingChanges() - pending.recordRowDeletion(rowIndex: 0, originalRow: ["a"]) - let undone = pending.undoRowDeletion(rowIndex: 0) + pending.recordRowDeletion(rowID: .existing(0), originalRow: ["a"]) + let undone = pending.undoRowDeletion(rowID: .existing(0)) #expect(undone == true) - #expect(!pending.isRowDeleted(0)) + #expect(!pending.isRowDeleted(.existing(0))) #expect(pending.isEmpty) } - @Test("Undo row insertion shifts later inserted rows down") - func undoRowInsertionShiftsOthers() { + @Test("Undo row insertion leaves the other inserted rows and their values alone") + func undoRowInsertionLeavesOthers() { var pending = PendingChanges() - pending.recordRowInsertion(rowIndex: 1, values: ["a"]) - pending.recordRowInsertion(rowIndex: 2, values: ["b"]) - pending.recordRowInsertion(rowIndex: 3, values: ["c"]) + let first = RowID.inserted(UUID()) + let second = RowID.inserted(UUID()) + let third = RowID.inserted(UUID()) + pending.recordRowInsertion(rowID: first, values: ["a"]) + pending.recordRowInsertion(rowID: second, values: ["b"]) + pending.recordRowInsertion(rowID: third, values: ["c"]) - let undone = pending.undoRowInsertion(rowIndex: 2) + let undone = pending.undoRowInsertion(rowID: second) #expect(undone == true) - #expect(pending.isRowInserted(1)) - #expect(pending.isRowInserted(2)) - #expect(!pending.isRowInserted(3)) + #expect(pending.isRowInserted(first)) + #expect(!pending.isRowInserted(second)) + #expect(pending.isRowInserted(third)) + #expect(pending.savedInsertedValues(forRow: first) == ["a"]) + #expect(pending.savedInsertedValues(forRow: third) == ["c"]) } @Test("Undo on row that was not inserted is a no-op") func undoNonexistentInsertion() { var pending = PendingChanges() - let undone = pending.undoRowInsertion(rowIndex: 99) + let undone = pending.undoRowInsertion(rowID: .existing(99)) #expect(undone == false) } @Test("Undo batch row insertion returns saved values in order") func undoBatchRowInsertion() { var pending = PendingChanges() - pending.recordRowInsertion(rowIndex: 1, values: ["a"]) - pending.recordRowInsertion(rowIndex: 2, values: ["b"]) - pending.recordRowInsertion(rowIndex: 3, values: ["c"]) + pending.recordRowInsertion(rowID: insertedID(1), values: ["a"]) + pending.recordRowInsertion(rowID: insertedID(2), values: ["b"]) + pending.recordRowInsertion(rowID: insertedID(3), values: ["c"]) - let restored = pending.undoBatchRowInsertion(rowIndices: [1, 2, 3], columnCount: 1) + let restored = pending.undoBatchRowInsertion( + rowIDs: [insertedID(1), insertedID(2), insertedID(3)], columnCount: 1 + ) #expect(restored.count == 3) - #expect(!pending.isRowInserted(1)) - #expect(!pending.isRowInserted(2)) - #expect(!pending.isRowInserted(3)) + #expect(!pending.isRowInserted(insertedID(1))) + #expect(!pending.isRowInserted(insertedID(2))) + #expect(!pending.isRowInserted(insertedID(3))) } } @@ -162,10 +169,10 @@ struct PendingChangesReplayTests { func reapplyCellWithoutExisting() { var pending = PendingChanges() pending.reapplyCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", originalDBValue: "orig", newValue: "x", originalRow: nil ) - #expect(pending.isCellModified(rowIndex: 0, columnIndex: 1)) + #expect(pending.isCellModified(rowID: .existing(0), columnIndex: 1)) #expect(pending.changes[0].cellChanges[0].oldValue == "orig") } @@ -173,7 +180,7 @@ struct PendingChangesReplayTests { func reapplyCellPreservesOriginalDBValue() { var pending = PendingChanges() pending.reapplyCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", originalDBValue: "Alice", newValue: "Bob", originalRow: nil ) let cellChange = pending.changes[0].cellChanges[0] @@ -184,16 +191,16 @@ struct PendingChangesReplayTests { @Test("Reinsert row creates insert change with saved values") func reinsertRowFromUndo() { var pending = PendingChanges() - pending.reinsertRow(rowIndex: 2, columns: ["a", "b"], savedValues: ["x", "y"]) - #expect(pending.isRowInserted(2)) - #expect(pending.savedInsertedValues(forRow: 2) == ["x", "y"]) + pending.reinsertRow(rowID: .existing(2), columns: ["a", "b"], savedValues: ["x", "y"]) + #expect(pending.isRowInserted(.existing(2))) + #expect(pending.savedInsertedValues(forRow: .existing(2)) == ["x", "y"]) } @Test("Reapply row deletion adds delete change") func reapplyDeletion() { var pending = PendingChanges() - pending.reapplyRowDeletion(rowIndex: 0, originalRow: ["a", "b"]) - #expect(pending.isRowDeleted(0)) + pending.reapplyRowDeletion(rowID: .existing(0), originalRow: ["a", "b"]) + #expect(pending.isRowDeleted(.existing(0))) } } @@ -203,11 +210,11 @@ struct PendingChangesSnapshotTests { func snapshotRoundTrip() { var pending = PendingChanges() pending.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "a", newValue: "b" ) - pending.recordRowDeletion(rowIndex: 5, originalRow: ["x"]) - pending.recordRowInsertion(rowIndex: 7, values: ["new"]) + pending.recordRowDeletion(rowID: .existing(5), originalRow: ["x"]) + pending.recordRowInsertion(rowID: insertedID(7), values: ["new"]) let snapshot = pending.snapshot(primaryKeyColumns: ["id"], columns: ["id", "name"]) @@ -215,9 +222,9 @@ struct PendingChangesSnapshotTests { restored.restore(from: snapshot) #expect(restored.changes.count == pending.changes.count) - #expect(restored.isRowDeleted(5)) - #expect(restored.isRowInserted(7)) - #expect(restored.isCellModified(rowIndex: 0, columnIndex: 1)) + #expect(restored.isRowDeleted(.existing(5))) + #expect(restored.isRowInserted(insertedID(7))) + #expect(restored.isCellModified(rowID: .existing(0), columnIndex: 1)) } } @@ -227,16 +234,20 @@ struct PendingChangesLifecycleTests { func clearResets() { var pending = PendingChanges() pending.recordCellChange( - rowIndex: 0, columnIndex: 1, columnName: "name", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "a", newValue: "b" ) - pending.recordRowDeletion(rowIndex: 5, originalRow: ["x"]) + pending.recordRowDeletion(rowID: .existing(5), originalRow: ["x"]) pending.clear() #expect(pending.isEmpty) #expect(pending.changes.isEmpty) - #expect(!pending.isRowDeleted(5)) - #expect(!pending.isCellModified(rowIndex: 0, columnIndex: 1)) + #expect(!pending.isRowDeleted(.existing(5))) + #expect(!pending.isCellModified(rowID: .existing(0), columnIndex: 1)) } } + +private func insertedID(_ seed: Int) -> RowID { + .inserted(UUID(uuidString: String(format: "00000000-0000-0000-0000-%012d", seed)) ?? UUID()) +} diff --git a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorBatchDeleteScaleTests.swift b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorBatchDeleteScaleTests.swift index f3b1e143ab..16b1458d5c 100644 --- a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorBatchDeleteScaleTests.swift +++ b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorBatchDeleteScaleTests.swift @@ -31,7 +31,7 @@ struct SQLStatementGeneratorBatchDeleteScaleTests { private func deleteChanges(count: Int, columns: [String]) -> [RowChange] { (0.. RowChange { RowChange( - rowIndex: rowIndex, + rowID: rowID, type: .update, cellChanges: [CellChange( columnIndex: columnIndex, @@ -50,21 +50,21 @@ struct SQLStatementGeneratorCompositePKTests { } private func makeMultiCellUpdateChange( - rowIndex: Int = 0, + rowID: RowID = .existing(0), cellChanges: [CellChange], originalRow: [String?] ) -> RowChange { RowChange( - rowIndex: rowIndex, + rowID: rowID, type: .update, cellChanges: cellChanges, originalRow: originalRow.map(PluginCellValue.fromOptional) ) } - private func makeDeleteChange(rowIndex: Int = 0, originalRow: [String?]) -> RowChange { + private func makeDeleteChange(rowID: RowID = .existing(0), originalRow: [String?]) -> RowChange { RowChange( - rowIndex: rowIndex, type: .delete, cellChanges: [], + rowID: rowID, type: .delete, cellChanges: [], originalRow: originalRow.map(PluginCellValue.fromOptional) ) } @@ -72,14 +72,14 @@ struct SQLStatementGeneratorCompositePKTests { private func generate( _ changes: [RowChange], generator: SQLStatementGenerator, - deletedRowIndices: Set = [], - insertedRowIndices: Set = [] + deletedRowIDs: Set = [], + insertedRowIDs: Set = [] ) -> [ParameterizedStatement] { generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: deletedRowIndices, - insertedRowIndices: insertedRowIndices + deletedRowIDs: deletedRowIDs, + insertedRowIDs: insertedRowIDs ) } @@ -189,12 +189,12 @@ struct SQLStatementGeneratorCompositePKTests { let gen = try makeGenerator() let stmts = generate([ makeUpdateChange( - rowIndex: 0, columnIndex: 2, columnName: "quantity", + rowID: .existing(0), columnIndex: 2, columnName: "quantity", oldValue: "5", newValue: "10", originalRow: ["1", "42", "5", "9.99"] ), makeUpdateChange( - rowIndex: 1, columnIndex: 2, columnName: "quantity", + rowID: .existing(1), columnIndex: 2, columnName: "quantity", oldValue: "3", newValue: "7", originalRow: ["1", "43", "3", "4.99"] ), @@ -252,9 +252,9 @@ struct SQLStatementGeneratorCompositePKTests { func deleteSingleRowCompositePK() throws { let gen = try makeGenerator() let stmts = generate( - [makeDeleteChange(rowIndex: 0, originalRow: ["1", "42", "5", "9.99"])], + [makeDeleteChange(rowID: .existing(0), originalRow: ["1", "42", "5", "9.99"])], generator: gen, - deletedRowIndices: [0] + deletedRowIDs: [.existing(0)] ) #expect(stmts.count == 1) @@ -273,12 +273,12 @@ struct SQLStatementGeneratorCompositePKTests { let gen = try makeGenerator() let stmts = generate( [ - makeDeleteChange(rowIndex: 0, originalRow: ["1", "42", "5", "9.99"]), - makeDeleteChange(rowIndex: 1, originalRow: ["1", "43", "3", "4.99"]), - makeDeleteChange(rowIndex: 2, originalRow: ["2", "42", "1", "7.50"]), + makeDeleteChange(rowID: .existing(0), originalRow: ["1", "42", "5", "9.99"]), + makeDeleteChange(rowID: .existing(1), originalRow: ["1", "43", "3", "4.99"]), + makeDeleteChange(rowID: .existing(2), originalRow: ["2", "42", "1", "7.50"]), ], generator: gen, - deletedRowIndices: [0, 1, 2] + deletedRowIDs: [.existing(0), .existing(1), .existing(2)] ) #expect(stmts.count == 1) @@ -294,11 +294,11 @@ struct SQLStatementGeneratorCompositePKTests { let gen = try makeGenerator(databaseType: .postgresql) let stmts = generate( [ - makeDeleteChange(rowIndex: 0, originalRow: ["1", "42", "5", "9.99"]), - makeDeleteChange(rowIndex: 1, originalRow: ["1", "43", "3", "4.99"]), + makeDeleteChange(rowID: .existing(0), originalRow: ["1", "42", "5", "9.99"]), + makeDeleteChange(rowID: .existing(1), originalRow: ["1", "43", "3", "4.99"]), ], generator: gen, - deletedRowIndices: [0, 1] + deletedRowIDs: [.existing(0), .existing(1)] ) #expect(stmts.count == 1) @@ -341,11 +341,11 @@ struct SQLStatementGeneratorCompositePKTests { ) let stmts = generate( [ - makeDeleteChange(rowIndex: 0, originalRow: ["1", "John", "john@test.com"]), - makeDeleteChange(rowIndex: 1, originalRow: ["2", "Jane", "jane@test.com"]), + makeDeleteChange(rowID: .existing(0), originalRow: ["1", "John", "john@test.com"]), + makeDeleteChange(rowID: .existing(1), originalRow: ["2", "Jane", "jane@test.com"]), ], generator: gen, - deletedRowIndices: [0, 1] + deletedRowIDs: [.existing(0), .existing(1)] ) #expect(stmts.count == 1) @@ -389,11 +389,11 @@ struct SQLStatementGeneratorCompositePKTests { ) let stmts = generate( [ - makeDeleteChange(rowIndex: 0, originalRow: ["2024-01-01", "hello", "info"]), - makeDeleteChange(rowIndex: 1, originalRow: ["2024-01-02", "world", "warn"]), + makeDeleteChange(rowID: .existing(0), originalRow: ["2024-01-01", "hello", "info"]), + makeDeleteChange(rowID: .existing(1), originalRow: ["2024-01-02", "world", "warn"]), ], generator: gen, - deletedRowIndices: [0, 1] + deletedRowIDs: [.existing(0), .existing(1)] ) #expect(stmts.count == 1) @@ -448,11 +448,11 @@ struct SQLStatementGeneratorCompositePKTests { let gen = try makeGenerator() let stmts = generate( [ - makeDeleteChange(rowIndex: 0, originalRow: ["1", nil, "5", "9.99"]), - makeDeleteChange(rowIndex: 1, originalRow: ["1", "43", "3", "4.99"]), + makeDeleteChange(rowID: .existing(0), originalRow: ["1", nil, "5", "9.99"]), + makeDeleteChange(rowID: .existing(1), originalRow: ["1", "43", "3", "4.99"]), ], generator: gen, - deletedRowIndices: [0, 1] + deletedRowIDs: [.existing(0), .existing(1)] ) // Row 0 has NULL PK → skipped in batch, only row 1 survives @@ -464,7 +464,7 @@ struct SQLStatementGeneratorCompositePKTests { func updateWithoutOriginalRowUsesCellChanges() throws { let gen = try makeGenerator() let change = RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 0, columnName: "order_id", oldValue: "1", newValue: "1"), @@ -485,7 +485,7 @@ struct SQLStatementGeneratorCompositePKTests { func updateWithoutOriginalRowMissingPKSkipped() throws { let gen = try makeGenerator() let change = RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 2, columnName: "quantity", oldValue: "5", newValue: "10"), @@ -502,19 +502,19 @@ struct SQLStatementGeneratorCompositePKTests { func mixedOperationsCompositePK() throws { let gen = try makeGenerator() - let insertChange = RowChange(rowIndex: 3, type: .insert, cellChanges: []) + let insertChange = RowChange(rowID: .existing(3), type: .insert, cellChanges: []) let updateChange = makeUpdateChange( - rowIndex: 0, columnIndex: 2, columnName: "quantity", + rowID: .existing(0), columnIndex: 2, columnName: "quantity", oldValue: "5", newValue: "10", originalRow: ["1", "42", "5", "9.99"] ) - let deleteChange = makeDeleteChange(rowIndex: 1, originalRow: ["1", "43", "3", "4.99"]) + let deleteChange = makeDeleteChange(rowID: .existing(1), originalRow: ["1", "43", "3", "4.99"]) let stmts = gen.generateStatements( from: [insertChange, updateChange, deleteChange], - insertedRowData: [3: ["2", "99", "1", "5.00"]], - deletedRowIndices: [1], - insertedRowIndices: [3] + insertedRowData: [.existing(3): ["2", "99", "1", "5.00"]], + deletedRowIDs: [.existing(1)], + insertedRowIDs: [.existing(3)] ) // INSERT + UPDATE + DELETE = 3 statements diff --git a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorGeneratedColumnTests.swift b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorGeneratedColumnTests.swift index 79a45d4837..2435f22728 100644 --- a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorGeneratedColumnTests.swift +++ b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorGeneratedColumnTests.swift @@ -30,14 +30,14 @@ struct SQLStatementGeneratorGeneratedColumnTests { func insertFromStoredDataOmitsGeneratedColumn() throws { let generator = try makeGenerator() let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, - insertedRowData: [0: ["1", "John", "John Doe"]], - deletedRowIndices: [], - insertedRowIndices: [0] + insertedRowData: [.existing(0): ["1", "John", "John Doe"]], + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) let statement = try #require(statements.first) @@ -51,7 +51,7 @@ struct SQLStatementGeneratorGeneratedColumnTests { let generator = try makeGenerator() let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .insert, cellChanges: [ CellChange(columnIndex: 1, columnName: "name", oldValue: .null, newValue: "John"), @@ -69,8 +69,8 @@ struct SQLStatementGeneratorGeneratedColumnTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) let statement = try #require(statements.first) @@ -83,7 +83,7 @@ struct SQLStatementGeneratorGeneratedColumnTests { let generator = try makeGenerator() let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "name", oldValue: "John", newValue: "Johnny"), @@ -101,8 +101,8 @@ struct SQLStatementGeneratorGeneratedColumnTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) let statement = try #require(statements.first) @@ -115,7 +115,7 @@ struct SQLStatementGeneratorGeneratedColumnTests { let generator = try makeGenerator() let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange( @@ -132,8 +132,8 @@ struct SQLStatementGeneratorGeneratedColumnTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.isEmpty) @@ -143,14 +143,14 @@ struct SQLStatementGeneratorGeneratedColumnTests { func tableWithoutGeneratedColumnsIsUnaffected() throws { let generator = try makeGenerator(generatedColumns: []) let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, - insertedRowData: [0: ["1", "John", "John Doe"]], - deletedRowIndices: [], - insertedRowIndices: [0] + insertedRowData: [.existing(0): ["1", "John", "John Doe"]], + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) let statement = try #require(statements.first) diff --git a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorMSSQLTests.swift b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorMSSQLTests.swift index fa493046a1..577bfe1781 100644 --- a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorMSSQLTests.swift +++ b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorMSSQLTests.swift @@ -28,19 +28,19 @@ struct SQLStatementGeneratorMSSQLTests { ) } - private func makeInsertChange(rowIndex: Int = 0) -> RowChange { - RowChange(rowIndex: rowIndex, type: .insert, cellChanges: [], originalRow: nil) + private func makeInsertChange(rowID: RowID = .existing(0)) -> RowChange { + RowChange(rowID: rowID, type: .insert, cellChanges: [], originalRow: nil) } private func makeUpdateChange( - rowIndex: Int = 0, + rowID: RowID = .existing(0), columnName: String = "name", oldValue: String? = "old", newValue: String? = "new", originalRow: [String?]? = ["1", "old", "a@b.com"] ) -> RowChange { RowChange( - rowIndex: rowIndex, + rowID: rowID, type: .update, cellChanges: [ CellChange( @@ -55,11 +55,11 @@ struct SQLStatementGeneratorMSSQLTests { } private func makeDeleteChange( - rowIndex: Int = 0, + rowID: RowID = .existing(0), originalRow: [String?]? = ["1", "John", "john@example.com"] ) -> RowChange { RowChange( - rowIndex: rowIndex, type: .delete, cellChanges: [], + rowID: rowID, type: .delete, cellChanges: [], originalRow: originalRow.map { row in row.map(PluginCellValue.fromOptional) } ) } @@ -69,12 +69,12 @@ struct SQLStatementGeneratorMSSQLTests { @Test("INSERT statement uses question mark placeholders") func insertUsesQuestionMarkPlaceholders() throws { let generator = try makeGenerator() - let insertedRowData: [Int: [PluginCellValue]] = [0: ["1", "John", "john@example.com"]] + let insertedRowData: [RowID: [PluginCellValue]] = [.existing(0): ["1", "John", "john@example.com"]] let statements = generator.generateStatements( from: [makeInsertChange()], insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -88,8 +88,8 @@ struct SQLStatementGeneratorMSSQLTests { let statements = generator.generateStatements( from: [makeUpdateChange()], insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -102,12 +102,12 @@ struct SQLStatementGeneratorMSSQLTests { @Test("INSERT uses bracket-quoted table and column names") func insertBracketQuoting() throws { let generator = try makeGenerator() - let insertedRowData: [Int: [PluginCellValue]] = [0: ["1", "John", "john@example.com"]] + let insertedRowData: [RowID: [PluginCellValue]] = [.existing(0): ["1", "John", "john@example.com"]] let statements = generator.generateStatements( from: [makeInsertChange()], insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -121,12 +121,12 @@ struct SQLStatementGeneratorMSSQLTests { @Test("INSERT with multiple columns produces correct number of placeholders") func insertMultipleColumnsPlaceholders() throws { let generator = try makeGenerator(columns: ["id", "name", "email"]) - let insertedRowData: [Int: [PluginCellValue]] = [0: ["1", "John", "john@example.com"]] + let insertedRowData: [RowID: [PluginCellValue]] = [.existing(0): ["1", "John", "john@example.com"]] let statements = generator.generateStatements( from: [makeInsertChange()], insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -144,8 +144,8 @@ struct SQLStatementGeneratorMSSQLTests { let statements = generator.generateStatements( from: [makeUpdateChange()], insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -159,8 +159,8 @@ struct SQLStatementGeneratorMSSQLTests { let statements = generator.generateStatements( from: [makeUpdateChange()], insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -176,8 +176,8 @@ struct SQLStatementGeneratorMSSQLTests { let statements = generator.generateStatements( from: [makeDeleteChange()], insertedRowData: [:], - deletedRowIndices: [0], - insertedRowIndices: [] + deletedRowIDs: [.existing(0)], + insertedRowIDs: [] ) #expect(statements.count == 1) diff --git a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorNoPKTests.swift b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorNoPKTests.swift index d397784a0b..241324199b 100644 --- a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorNoPKTests.swift +++ b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorNoPKTests.swift @@ -36,7 +36,7 @@ struct SQLStatementGeneratorNoPKTests { let generator = try makeGenerator() let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "name", oldValue: "John", newValue: "Johnny") @@ -48,8 +48,8 @@ struct SQLStatementGeneratorNoPKTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -68,7 +68,7 @@ struct SQLStatementGeneratorNoPKTests { let generator = try makeGenerator() let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "name", oldValue: nil, newValue: "Johnny") @@ -80,8 +80,8 @@ struct SQLStatementGeneratorNoPKTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -95,7 +95,7 @@ struct SQLStatementGeneratorNoPKTests { let generator = try makeGenerator() let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "name", oldValue: "John", newValue: "Johnny") @@ -107,8 +107,8 @@ struct SQLStatementGeneratorNoPKTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.isEmpty) @@ -119,7 +119,7 @@ struct SQLStatementGeneratorNoPKTests { let generator = try makeGenerator() let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "name", oldValue: "John", newValue: "Johnny"), @@ -132,8 +132,8 @@ struct SQLStatementGeneratorNoPKTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -149,15 +149,15 @@ struct SQLStatementGeneratorNoPKTests { func testDeleteNoPKMultipleRows() throws { let generator = try makeGenerator() let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .delete, cellChanges: [], originalRow: ["1", "John", "john@example.com"]), - RowChange(rowIndex: 1, type: .delete, cellChanges: [], originalRow: ["2", "Jane", "jane@example.com"]) + RowChange(rowID: .existing(0), type: .delete, cellChanges: [], originalRow: ["1", "John", "john@example.com"]), + RowChange(rowID: .existing(1), type: .delete, cellChanges: [], originalRow: ["2", "Jane", "jane@example.com"]) ] let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [0, 1], - insertedRowIndices: [] + deletedRowIDs: [.existing(0), .existing(1)], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -175,7 +175,7 @@ struct SQLStatementGeneratorNoPKTests { let generator = try makeGenerator() let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .delete, cellChanges: [], originalRow: [nil, nil, nil] @@ -185,8 +185,8 @@ struct SQLStatementGeneratorNoPKTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [0], - insertedRowIndices: [] + deletedRowIDs: [.existing(0)], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -202,7 +202,7 @@ struct SQLStatementGeneratorNoPKTests { let generator = try makeGenerator() let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .delete, cellChanges: [], originalRow: nil @@ -212,8 +212,8 @@ struct SQLStatementGeneratorNoPKTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [0], - insertedRowIndices: [] + deletedRowIDs: [.existing(0)], + insertedRowIDs: [] ) #expect(statements.isEmpty) @@ -226,7 +226,7 @@ struct SQLStatementGeneratorNoPKTests { let generator = try makeGenerator() let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "name", oldValue: "John", newValue: "Johnny") @@ -234,7 +234,7 @@ struct SQLStatementGeneratorNoPKTests { originalRow: ["1", "John", "john@example.com"] ), RowChange( - rowIndex: 1, + rowID: .existing(1), type: .delete, cellChanges: [], originalRow: ["2", "Jane", "jane@example.com"] @@ -244,8 +244,8 @@ struct SQLStatementGeneratorNoPKTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [1], - insertedRowIndices: [] + deletedRowIDs: [.existing(1)], + insertedRowIDs: [] ) #expect(statements.count == 2) @@ -256,13 +256,13 @@ struct SQLStatementGeneratorNoPKTests { @Test("INSERT + DELETE without PK — INSERT unaffected") func testInsertDeleteNoPK() throws { let generator = try makeGenerator() - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["3", "Bob", "bob@example.com"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["3", "Bob", "bob@example.com"] ] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil), + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil), RowChange( - rowIndex: 1, + rowID: .existing(1), type: .delete, cellChanges: [], originalRow: ["2", "Jane", "jane@example.com"] @@ -272,8 +272,8 @@ struct SQLStatementGeneratorNoPKTests { let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [1], - insertedRowIndices: [0] + deletedRowIDs: [.existing(1)], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 2) diff --git a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorOrderingTests.swift b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorOrderingTests.swift index 1f2d425a6b..c8ca8510cb 100644 --- a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorOrderingTests.swift +++ b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorOrderingTests.swift @@ -28,7 +28,7 @@ struct SQLStatementGeneratorOrderingTests { private func update(row: Int, sequence: Int) -> RowChange { RowChange( - rowIndex: row, + rowID: .existing(row), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "email", oldValue: "old@b.com", newValue: "new@b.com"), @@ -39,11 +39,11 @@ struct SQLStatementGeneratorOrderingTests { } private func delete(row: Int, sequence: Int) -> RowChange { - RowChange(rowIndex: row, type: .delete, originalRow: [.text("\(row)"), "a@b.com"], sequence: sequence) + RowChange(rowID: .existing(row), type: .delete, originalRow: [.text("\(row)"), "a@b.com"], sequence: sequence) } private func insert(row: Int, sequence: Int) -> RowChange { - RowChange(rowIndex: row, type: .insert, sequence: sequence) + RowChange(rowID: .existing(row), type: .insert, sequence: sequence) } private func verbs(_ statements: [AttributedStatement]) -> [String] { @@ -54,9 +54,9 @@ struct SQLStatementGeneratorOrderingTests { func deleteBeforeInsert() throws { let statements = try makeGenerator().generateAttributedStatements( from: [delete(row: 0, sequence: 0), insert(row: 1, sequence: 1)], - insertedRowData: [1: ["9", "a@b.com"]], - deletedRowIndices: [0], - insertedRowIndices: [1] + insertedRowData: [.existing(1): ["9", "a@b.com"]], + deletedRowIDs: [.existing(0)], + insertedRowIDs: [.existing(1)] ) #expect(verbs(statements) == ["DELETE", "INSERT"]) @@ -66,9 +66,9 @@ struct SQLStatementGeneratorOrderingTests { func mixedOrderIsPreserved() throws { let statements = try makeGenerator().generateAttributedStatements( from: [update(row: 0, sequence: 0), delete(row: 1, sequence: 1), insert(row: 2, sequence: 2)], - insertedRowData: [2: ["9", "c@b.com"]], - deletedRowIndices: [1], - insertedRowIndices: [2] + insertedRowData: [.existing(2): ["9", "c@b.com"]], + deletedRowIDs: [.existing(1)], + insertedRowIDs: [.existing(2)] ) #expect(verbs(statements) == ["UPDATE", "DELETE", "INSERT"]) @@ -78,9 +78,9 @@ struct SQLStatementGeneratorOrderingTests { func arrayOrderIsNotTrusted() throws { let statements = try makeGenerator().generateAttributedStatements( from: [insert(row: 2, sequence: 5), delete(row: 1, sequence: 1)], - insertedRowData: [2: ["9", "c@b.com"]], - deletedRowIndices: [1], - insertedRowIndices: [2] + insertedRowData: [.existing(2): ["9", "c@b.com"]], + deletedRowIDs: [.existing(1)], + insertedRowIDs: [.existing(2)] ) #expect(verbs(statements) == ["DELETE", "INSERT"]) @@ -91,8 +91,8 @@ struct SQLStatementGeneratorOrderingTests { let statements = try makeGenerator().generateAttributedStatements( from: [delete(row: 0, sequence: 0), delete(row: 1, sequence: 1), delete(row: 2, sequence: 2)], insertedRowData: [:], - deletedRowIndices: [0, 1, 2], - insertedRowIndices: [] + deletedRowIDs: [.existing(0), .existing(1), .existing(2)], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -108,8 +108,8 @@ struct SQLStatementGeneratorOrderingTests { delete(row: 1, sequence: 2), ], insertedRowData: [:], - deletedRowIndices: [0, 1], - insertedRowIndices: [] + deletedRowIDs: [.existing(0), .existing(1)], + insertedRowIDs: [] ) #expect(verbs(statements) == ["DELETE", "UPDATE", "DELETE"]) diff --git a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorPKRegressionTests.swift b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorPKRegressionTests.swift index 945db12ca0..1436bedfdf 100644 --- a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorPKRegressionTests.swift +++ b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorPKRegressionTests.swift @@ -27,9 +27,9 @@ struct SQLStatementGeneratorPKRegressionTests { ) } - private func makeDeleteChange(rowIndex: Int, originalRow: [String?]) -> RowChange { + private func makeDeleteChange(rowID: RowID, originalRow: [String?]) -> RowChange { RowChange( - rowIndex: rowIndex, + rowID: rowID, type: .delete, cellChanges: [], originalRow: originalRow.map(PluginCellValue.fromOptional) @@ -37,7 +37,7 @@ struct SQLStatementGeneratorPKRegressionTests { } private func makeUpdateChange( - rowIndex: Int, + rowID: RowID, columnIndex: Int, columnName: String, oldValue: String?, @@ -45,7 +45,7 @@ struct SQLStatementGeneratorPKRegressionTests { originalRow: [String?] ) -> RowChange { RowChange( - rowIndex: rowIndex, + rowID: rowID, type: .update, cellChanges: [CellChange(columnIndex: columnIndex, columnName: columnName, oldValue: PluginCellValue.fromOptional(oldValue), newValue: PluginCellValue.fromOptional(newValue))], originalRow: originalRow.map(PluginCellValue.fromOptional) @@ -57,13 +57,13 @@ struct SQLStatementGeneratorPKRegressionTests { @Test("PostgreSQL delete with PK uses $N placeholder and PK-only WHERE") func testPostgreSQLDeleteWithPK() throws { let generator = try makeGenerator(databaseType: .postgresql) - let changes = [makeDeleteChange(rowIndex: 0, originalRow: ["1", "John", "john@test.com"])] + let changes = [makeDeleteChange(rowID: .existing(0), originalRow: ["1", "John", "john@test.com"])] let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [0], - insertedRowIndices: [] + deletedRowIDs: [.existing(0)], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -81,15 +81,15 @@ struct SQLStatementGeneratorPKRegressionTests { func testPostgreSQLBatchDeleteWithPK() throws { let generator = try makeGenerator(databaseType: .postgresql) let changes = [ - makeDeleteChange(rowIndex: 0, originalRow: ["1", "John", "john@test.com"]), - makeDeleteChange(rowIndex: 1, originalRow: ["2", "Jane", "jane@test.com"]) + makeDeleteChange(rowID: .existing(0), originalRow: ["1", "John", "john@test.com"]), + makeDeleteChange(rowID: .existing(1), originalRow: ["2", "Jane", "jane@test.com"]) ] let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [0, 1], - insertedRowIndices: [] + deletedRowIDs: [.existing(0), .existing(1)], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -106,13 +106,13 @@ struct SQLStatementGeneratorPKRegressionTests { @Test("MSSQL delete with PK uses ? placeholder and PK-only WHERE") func testMSSQLDeleteWithPK() throws { let generator = try makeGenerator(databaseType: .mssql) - let changes = [makeDeleteChange(rowIndex: 0, originalRow: ["1", "John", "john@test.com"])] + let changes = [makeDeleteChange(rowID: .existing(0), originalRow: ["1", "John", "john@test.com"])] let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [0], - insertedRowIndices: [] + deletedRowIDs: [.existing(0)], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -133,15 +133,15 @@ struct SQLStatementGeneratorPKRegressionTests { func testPostgreSQLUpdateWithPK() throws { let generator = try makeGenerator(databaseType: .postgresql) let changes = [makeUpdateChange( - rowIndex: 0, columnIndex: 1, columnName: "name", oldValue: "John", newValue: "Jane", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "John", newValue: "Jane", originalRow: ["1", "John", "john@test.com"] )] let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -156,15 +156,15 @@ struct SQLStatementGeneratorPKRegressionTests { func testMSSQLUpdateWithPK() throws { let generator = try makeGenerator(databaseType: .mssql) let changes = [makeUpdateChange( - rowIndex: 0, columnIndex: 1, columnName: "name", oldValue: "John", newValue: "Jane", + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "John", newValue: "Jane", originalRow: ["1", "John", "john@test.com"] )] let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -180,13 +180,13 @@ struct SQLStatementGeneratorPKRegressionTests { @Test("Redshift delete with PK uses $N placeholder and PK-only WHERE") func testRedshiftDeleteWithPK() throws { let generator = try makeGenerator(databaseType: .redshift) - let changes = [makeDeleteChange(rowIndex: 0, originalRow: ["1", "John", "john@test.com"])] + let changes = [makeDeleteChange(rowID: .existing(0), originalRow: ["1", "John", "john@test.com"])] let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [0], - insertedRowIndices: [] + deletedRowIDs: [.existing(0)], + insertedRowIDs: [] ) #expect(statements.count == 1) diff --git a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorParameterStyleTests.swift b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorParameterStyleTests.swift index 559ccab7c5..e48fae3fc4 100644 --- a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorParameterStyleTests.swift +++ b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorParameterStyleTests.swift @@ -37,14 +37,14 @@ struct SQLStatementGeneratorParameterStyleTests { @Test("PostgreSQL defaults to dollar style") func testPostgreSQLDefaultsDollar() throws { let generator = try makeGenerator(databaseType: .postgresql) - let insertedRowData: [Int: [PluginCellValue]] = [0: ["1", "John", "john@example.com"]] + let insertedRowData: [RowID: [PluginCellValue]] = [.existing(0): ["1", "John", "john@example.com"]] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], insertedRowIndices: [0] + deletedRowIDs: [], insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -57,14 +57,14 @@ struct SQLStatementGeneratorParameterStyleTests { @Test("Redshift defaults to dollar style") func testRedshiftDefaultsDollar() throws { let generator = try makeGenerator(databaseType: .redshift) - let insertedRowData: [Int: [PluginCellValue]] = [0: ["1", "John", "john@example.com"]] + let insertedRowData: [RowID: [PluginCellValue]] = [.existing(0): ["1", "John", "john@example.com"]] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], insertedRowIndices: [0] + deletedRowIDs: [], insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -74,14 +74,14 @@ struct SQLStatementGeneratorParameterStyleTests { @Test("DuckDB defaults to dollar style") func testDuckDBDefaultsDollar() throws { let generator = try makeGenerator(databaseType: .duckdb) - let insertedRowData: [Int: [PluginCellValue]] = [0: ["1", "John", "john@example.com"]] + let insertedRowData: [RowID: [PluginCellValue]] = [.existing(0): ["1", "John", "john@example.com"]] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], insertedRowIndices: [0] + deletedRowIDs: [], insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -91,14 +91,14 @@ struct SQLStatementGeneratorParameterStyleTests { @Test("MySQL defaults to questionMark style") func testMySQLDefaultsQuestionMark() throws { let generator = try makeGenerator(databaseType: .mysql) - let insertedRowData: [Int: [PluginCellValue]] = [0: ["1", "John", "john@example.com"]] + let insertedRowData: [RowID: [PluginCellValue]] = [.existing(0): ["1", "John", "john@example.com"]] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], insertedRowIndices: [0] + deletedRowIDs: [], insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -109,14 +109,14 @@ struct SQLStatementGeneratorParameterStyleTests { @Test("SQLite defaults to questionMark style") func testSQLiteDefaultsQuestionMark() throws { let generator = try makeGenerator(databaseType: .sqlite) - let insertedRowData: [Int: [PluginCellValue]] = [0: ["1", "John", "john@example.com"]] + let insertedRowData: [RowID: [PluginCellValue]] = [.existing(0): ["1", "John", "john@example.com"]] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], insertedRowIndices: [0] + deletedRowIDs: [], insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -127,14 +127,14 @@ struct SQLStatementGeneratorParameterStyleTests { @Test("MSSQL defaults to questionMark style") func testMSSQLDefaultsQuestionMark() throws { let generator = try makeGenerator(databaseType: .mssql) - let insertedRowData: [Int: [PluginCellValue]] = [0: ["1", "John", "john@example.com"]] + let insertedRowData: [RowID: [PluginCellValue]] = [.existing(0): ["1", "John", "john@example.com"]] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], insertedRowIndices: [0] + deletedRowIDs: [], insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -147,14 +147,14 @@ struct SQLStatementGeneratorParameterStyleTests { @Test("Dollar style generates $1, $2 placeholders for INSERT") func testDollarStyleInsert() throws { let generator = try makeGenerator(parameterStyle: .dollar) - let insertedRowData: [Int: [PluginCellValue]] = [0: ["1", "John", "john@example.com"]] + let insertedRowData: [RowID: [PluginCellValue]] = [.existing(0): ["1", "John", "john@example.com"]] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], insertedRowIndices: [0] + deletedRowIDs: [], insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -167,14 +167,14 @@ struct SQLStatementGeneratorParameterStyleTests { @Test("QuestionMark style generates ? placeholders for INSERT") func testQuestionMarkStyleInsert() throws { let generator = try makeGenerator(parameterStyle: .questionMark) - let insertedRowData: [Int: [PluginCellValue]] = [0: ["1", "John", "john@example.com"]] + let insertedRowData: [RowID: [PluginCellValue]] = [.existing(0): ["1", "John", "john@example.com"]] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], insertedRowIndices: [0] + deletedRowIDs: [], insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -188,7 +188,7 @@ struct SQLStatementGeneratorParameterStyleTests { let generator = try makeGenerator(databaseType: .postgresql, parameterStyle: .dollar) let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "name", oldValue: "John", newValue: "Jane") @@ -199,7 +199,7 @@ struct SQLStatementGeneratorParameterStyleTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], insertedRowIndices: [] + deletedRowIDs: [], insertedRowIDs: [] ) #expect(statements.count == 1) @@ -213,7 +213,7 @@ struct SQLStatementGeneratorParameterStyleTests { let generator = try makeGenerator(databaseType: .postgresql, parameterStyle: .dollar) let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .delete, cellChanges: [], originalRow: ["1", "John", "john@example.com"] @@ -222,7 +222,7 @@ struct SQLStatementGeneratorParameterStyleTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [0], insertedRowIndices: [] + deletedRowIDs: [.existing(0)], insertedRowIDs: [] ) #expect(statements.count == 1) diff --git a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorRowMatchTests.swift b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorRowMatchTests.swift index 2b697693b0..e0cfba36df 100644 --- a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorRowMatchTests.swift +++ b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorRowMatchTests.swift @@ -28,7 +28,7 @@ struct SQLStatementGeneratorRowMatchTests { @Test("An update matches on every column the engine can compare, and none it cannot") func updateLeavesExcludedColumnsOut() throws { let change = RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [CellChange(columnIndex: 1, columnName: "name", oldValue: "a", newValue: "b")], originalRow: originalRow @@ -40,9 +40,9 @@ struct SQLStatementGeneratorRowMatchTests { @Test("A delete matches the same way") func deleteLeavesExcludedColumnsOut() throws { - let change = RowChange(rowIndex: 0, type: .delete, cellChanges: [], originalRow: originalRow) + let change = RowChange(rowID: .existing(0), type: .delete, cellChanges: [], originalRow: originalRow) let statements = try generator(excluding: ["payload", "tags"]).generateStatements( - from: [change], insertedRowData: [:], deletedRowIndices: [0], insertedRowIndices: [] + from: [change], insertedRowData: [:], deletedRowIDs: [.existing(0)], insertedRowIDs: [] ) #expect(statements.map(\.sql) == ["DELETE FROM `t` WHERE (`id` = ? AND `name` = ?)"]) } @@ -51,11 +51,11 @@ struct SQLStatementGeneratorRowMatchTests { func keylessDeletesAreNotBatched() throws { let other: [PluginCellValue] = ["2", "b", "{}", "[]"] let changes = [ - RowChange(rowIndex: 0, type: .delete, cellChanges: [], originalRow: originalRow), - RowChange(rowIndex: 1, type: .delete, cellChanges: [], originalRow: other) + RowChange(rowID: .existing(0), type: .delete, cellChanges: [], originalRow: originalRow), + RowChange(rowID: .existing(1), type: .delete, cellChanges: [], originalRow: other) ] let statements = try generator(excluding: ["payload", "tags"]).generateAttributedStatements( - from: changes, insertedRowData: [:], deletedRowIndices: [0, 1], insertedRowIndices: [] + from: changes, insertedRowData: [:], deletedRowIDs: [.existing(0), .existing(1)], insertedRowIDs: [] ) #expect(statements.count == 2) #expect(statements.allSatisfy { $0.rowCount == 1 && !$0.statement.sql.contains(" OR ") }) @@ -63,21 +63,21 @@ struct SQLStatementGeneratorRowMatchTests { @Test("A Databend row left entirely on defaults names one column with DEFAULT") func databendAllDefaultsInsert() throws { - let change = RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + let change = RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) let statements = try generator(excluding: []).generateStatements( from: [change], - insertedRowData: [0: [.text("__DEFAULT__"), .text("__DEFAULT__"), .text("__DEFAULT__"), .text("__DEFAULT__")]], - deletedRowIndices: [], - insertedRowIndices: [0] + insertedRowData: [.existing(0): [.text("__DEFAULT__"), .text("__DEFAULT__"), .text("__DEFAULT__"), .text("__DEFAULT__")]], + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.map(\.sql) == ["INSERT INTO `t` (`id`) VALUES (DEFAULT)"]) } @Test("With nothing excluded, every column still identifies the row") func noExclusionsKeepsEveryColumn() throws { - let change = RowChange(rowIndex: 0, type: .delete, cellChanges: [], originalRow: originalRow) + let change = RowChange(rowID: .existing(0), type: .delete, cellChanges: [], originalRow: originalRow) let statements = try generator(excluding: []).generateStatements( - from: [change], insertedRowData: [:], deletedRowIndices: [0], insertedRowIndices: [] + from: [change], insertedRowData: [:], deletedRowIDs: [.existing(0)], insertedRowIDs: [] ) #expect(statements.first?.sql.contains("`payload` = ?") == true) #expect(statements.first?.sql.contains("`tags` = ?") == true) @@ -94,9 +94,9 @@ struct SQLStatementGeneratorRowMatchTests { databaseType: .mysql, pluginDriver: nil ) - let change = RowChange(rowIndex: 0, type: .delete, cellChanges: [], originalRow: ["{}", "[]"]) + let change = RowChange(rowID: .existing(0), type: .delete, cellChanges: [], originalRow: ["{}", "[]"]) #expect(throws: DataWriteError.self) { - _ = try factory.statements(for: [change], deletedRowIndices: [0]) + _ = try factory.statements(for: [change], deletedRowIDs: [.existing(0)]) } } diff --git a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorTests.swift b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorTests.swift index af9b232530..3a040746f7 100644 --- a/TableProTests/Core/ChangeTracking/SQLStatementGeneratorTests.swift +++ b/TableProTests/Core/ChangeTracking/SQLStatementGeneratorTests.swift @@ -35,12 +35,12 @@ struct SQLStatementGeneratorTests { @Test("Simple insert from insertedRowData (MySQL)") func testSimpleInsertMySQL() throws { let generator = try makeGenerator() - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["1", "John", "john@example.com"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["1", "John", "john@example.com"] ] let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil @@ -50,8 +50,8 @@ struct SQLStatementGeneratorTests { let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -71,18 +71,18 @@ struct SQLStatementGeneratorTests { @Test("Insert with NULL value") func testInsertWithNullValue() throws { let generator = try makeGenerator() - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["1", "John", nil] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["1", "John", nil] ] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -93,18 +93,18 @@ struct SQLStatementGeneratorTests { @Test("Insert skips __DEFAULT__ columns") func testInsertSkipsDefaultColumns() throws { let generator = try makeGenerator() - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["__DEFAULT__", "John", "john@example.com"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["__DEFAULT__", "John", "john@example.com"] ] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -128,18 +128,18 @@ struct SQLStatementGeneratorTests { ) func testInsertAllDefaultNamesNoColumn(databaseType: DatabaseType, expected: String) throws { let generator = try makeGenerator(databaseType: databaseType) - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["__DEFAULT__", "__DEFAULT__", "__DEFAULT__"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["__DEFAULT__", "__DEFAULT__", "__DEFAULT__"] ] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -153,7 +153,7 @@ struct SQLStatementGeneratorTests { let generator = try makeGenerator() let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .insert, cellChanges: [ CellChange(columnIndex: 0, columnName: "id", oldValue: nil, newValue: "1"), @@ -167,8 +167,8 @@ struct SQLStatementGeneratorTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -178,18 +178,18 @@ struct SQLStatementGeneratorTests { @Test("Insert with SQL function is inlined") func testInsertWithSQLFunction() throws { let generator = try makeGenerator() - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["1", "John", "NOW()"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["1", "John", "NOW()"] ] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -201,18 +201,18 @@ struct SQLStatementGeneratorTests { @Test("PostgreSQL insert uses $1, $2 placeholders") func testInsertPostgreSQLPlaceholders() throws { let generator = try makeGenerator(databaseType: .postgresql) - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["1", "John", "john@example.com"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["1", "John", "john@example.com"] ] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -224,18 +224,18 @@ struct SQLStatementGeneratorTests { @Test("Table name is quoted with identifier quote") func testTableNameQuoted() throws { let generator = try makeGenerator(tableName: "my_table") - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["1", "John", "john@example.com"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["1", "John", "john@example.com"] ] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -245,18 +245,18 @@ struct SQLStatementGeneratorTests { @Test("Column names are quoted") func testColumnNamesQuoted() throws { let generator = try makeGenerator(columns: ["user_id", "full_name", "email_address"]) - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["1", "John", "john@example.com"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["1", "John", "john@example.com"] ] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -269,20 +269,20 @@ struct SQLStatementGeneratorTests { @Test("Insert multiple rows generates separate statements") func testInsertMultipleRows() throws { let generator = try makeGenerator() - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["1", "John", "john@example.com"], - 1: ["2", "Jane", "jane@example.com"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["1", "John", "john@example.com"], + .existing(1): ["2", "Jane", "jane@example.com"] ] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil), - RowChange(rowIndex: 1, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil), + RowChange(rowID: .existing(1), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0, 1] + deletedRowIDs: [], + insertedRowIDs: [.existing(0), .existing(1)] ) #expect(statements.count == 2) @@ -297,7 +297,7 @@ struct SQLStatementGeneratorTests { let generator = try makeGenerator() let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "name", oldValue: "John", newValue: "Johnny") @@ -309,8 +309,8 @@ struct SQLStatementGeneratorTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -330,7 +330,7 @@ struct SQLStatementGeneratorTests { let generator = try makeGenerator() let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "name", oldValue: "John", newValue: "Johnny"), @@ -343,8 +343,8 @@ struct SQLStatementGeneratorTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -359,7 +359,7 @@ struct SQLStatementGeneratorTests { let generator = try makeGenerator() let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 2, columnName: "email", oldValue: "john@example.com", newValue: nil) @@ -371,8 +371,8 @@ struct SQLStatementGeneratorTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -384,7 +384,7 @@ struct SQLStatementGeneratorTests { let generator = try makeGenerator() let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "name", oldValue: "John", newValue: "__DEFAULT__") @@ -396,8 +396,8 @@ struct SQLStatementGeneratorTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -411,7 +411,7 @@ struct SQLStatementGeneratorTests { let generator = try makeGenerator() let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 2, columnName: "email", oldValue: "old@example.com", newValue: "CURRENT_TIMESTAMP()") @@ -423,8 +423,8 @@ struct SQLStatementGeneratorTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -438,7 +438,7 @@ struct SQLStatementGeneratorTests { let generator = try makeGenerator(databaseType: .postgresql) let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "name", oldValue: "John", newValue: "Johnny") @@ -450,8 +450,8 @@ struct SQLStatementGeneratorTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -465,7 +465,7 @@ struct SQLStatementGeneratorTests { let generator = try makeGenerator() let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "name", oldValue: "John", newValue: "Johnny") @@ -477,8 +477,8 @@ struct SQLStatementGeneratorTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -492,7 +492,7 @@ struct SQLStatementGeneratorTests { let generator = try makeGenerator() let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .delete, cellChanges: [], originalRow: ["1", "John", "john@example.com"] @@ -502,8 +502,8 @@ struct SQLStatementGeneratorTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [0], - insertedRowIndices: [] + deletedRowIDs: [.existing(0)], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -517,15 +517,15 @@ struct SQLStatementGeneratorTests { func testBatchDeleteMultipleRows() throws { let generator = try makeGenerator() let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .delete, cellChanges: [], originalRow: ["1", "John", "john@example.com"]), - RowChange(rowIndex: 1, type: .delete, cellChanges: [], originalRow: ["2", "Jane", "jane@example.com"]) + RowChange(rowID: .existing(0), type: .delete, cellChanges: [], originalRow: ["1", "John", "john@example.com"]), + RowChange(rowID: .existing(1), type: .delete, cellChanges: [], originalRow: ["2", "Jane", "jane@example.com"]) ] let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [0, 1], - insertedRowIndices: [] + deletedRowIDs: [.existing(0), .existing(1)], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -541,7 +541,7 @@ struct SQLStatementGeneratorTests { let generator = try makeGenerator(primaryKeyColumns: []) let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .delete, cellChanges: [], originalRow: ["1", "John", "john@example.com"] @@ -551,8 +551,8 @@ struct SQLStatementGeneratorTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [0], - insertedRowIndices: [] + deletedRowIDs: [.existing(0)], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -569,7 +569,7 @@ struct SQLStatementGeneratorTests { let generator = try makeGenerator(primaryKeyColumns: []) let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .delete, cellChanges: [], originalRow: ["1", "John", nil] @@ -579,8 +579,8 @@ struct SQLStatementGeneratorTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [0], - insertedRowIndices: [] + deletedRowIDs: [.existing(0)], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -593,15 +593,15 @@ struct SQLStatementGeneratorTests { func testDeletePostgreSQLPlaceholders() throws { let generator = try makeGenerator(databaseType: .postgresql) let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .delete, cellChanges: [], originalRow: ["1", "John", "john@example.com"]), - RowChange(rowIndex: 1, type: .delete, cellChanges: [], originalRow: ["2", "Jane", "jane@example.com"]) + RowChange(rowID: .existing(0), type: .delete, cellChanges: [], originalRow: ["1", "John", "john@example.com"]), + RowChange(rowID: .existing(1), type: .delete, cellChanges: [], originalRow: ["2", "Jane", "jane@example.com"]) ] let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [0, 1], - insertedRowIndices: [] + deletedRowIDs: [.existing(0), .existing(1)], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -614,14 +614,14 @@ struct SQLStatementGeneratorTests { func testDeleteRequiresOriginalRow() throws { let generator = try makeGenerator() let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .delete, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .delete, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [0], - insertedRowIndices: [] + deletedRowIDs: [.existing(0)], + insertedRowIDs: [] ) #expect(statements.isEmpty) @@ -634,8 +634,8 @@ struct SQLStatementGeneratorTests { let statements = generator.generateStatements( from: [], insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.isEmpty) @@ -645,26 +645,26 @@ struct SQLStatementGeneratorTests { func testMixedOperations() throws { let generator = try makeGenerator() let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil), + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil), RowChange( - rowIndex: 1, + rowID: .existing(1), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "name", oldValue: "John", newValue: "Johnny") ], originalRow: ["1", "John", "john@example.com"] ), - RowChange(rowIndex: 2, type: .delete, cellChanges: [], originalRow: ["2", "Jane", "jane@example.com"]) + RowChange(rowID: .existing(2), type: .delete, cellChanges: [], originalRow: ["2", "Jane", "jane@example.com"]) ] - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["3", "Bob", "bob@example.com"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["3", "Bob", "bob@example.com"] ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [2], - insertedRowIndices: [0] + deletedRowIDs: [.existing(2)], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 3) @@ -675,18 +675,18 @@ struct SQLStatementGeneratorTests { @Test("MySQL uses ? for all placeholders") func testMySQLPlaceholders() throws { let generator = try makeGenerator(databaseType: .mysql) - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["1", "John", "john@example.com"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["1", "John", "john@example.com"] ] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -698,18 +698,18 @@ struct SQLStatementGeneratorTests { @Test("PostgreSQL uses $1, $2, $3 sequentially") func testPostgreSQLSequentialPlaceholders() throws { let generator = try makeGenerator(databaseType: .postgresql) - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["1", "John", "john@example.com"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["1", "John", "john@example.com"] ] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -723,18 +723,18 @@ struct SQLStatementGeneratorTests { @Test("SQLite uses ? placeholders") func testSQLitePlaceholders() throws { let generator = try makeGenerator(databaseType: .sqlite) - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["1", "John", "john@example.com"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["1", "John", "john@example.com"] ] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -745,18 +745,18 @@ struct SQLStatementGeneratorTests { @Test("MariaDB uses ? placeholders") func testMariaDBPlaceholders() throws { let generator = try makeGenerator(databaseType: .mariadb) - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["1", "John", "john@example.com"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["1", "John", "john@example.com"] ] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -766,42 +766,42 @@ struct SQLStatementGeneratorTests { // MARK: - Safety Tests - @Test("Insert only processes rows in insertedRowIndices set") + @Test("Insert only processes rows in insertedRowIDs set") func testInsertOnlyProcessesInsertedRows() throws { let generator = try makeGenerator() - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["1", "John", "john@example.com"], - 1: ["2", "Jane", "jane@example.com"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["1", "John", "john@example.com"], + .existing(1): ["2", "Jane", "jane@example.com"] ] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil), - RowChange(rowIndex: 1, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil), + RowChange(rowID: .existing(1), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) #expect(statements[0].parameters[1] as? String == "John") } - @Test("Delete only processes rows in deletedRowIndices set") + @Test("Delete only processes rows in deletedRowIDs set") func testDeleteOnlyProcessesDeletedRows() throws { let generator = try makeGenerator() let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .delete, cellChanges: [], originalRow: ["1", "John", "john@example.com"]), - RowChange(rowIndex: 1, type: .delete, cellChanges: [], originalRow: ["2", "Jane", "jane@example.com"]) + RowChange(rowID: .existing(0), type: .delete, cellChanges: [], originalRow: ["1", "John", "john@example.com"]), + RowChange(rowID: .existing(1), type: .delete, cellChanges: [], originalRow: ["2", "Jane", "jane@example.com"]) ] let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [0], - insertedRowIndices: [] + deletedRowIDs: [.existing(0)], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -809,38 +809,38 @@ struct SQLStatementGeneratorTests { #expect(statements[0].parameters[0] as? String == "1") } - @Test("Row not in insertedRowIndices is skipped") + @Test("Row not in insertedRowIDs is skipped") func testRowNotInInsertedRowIndicesSkipped() throws { let generator = try makeGenerator() - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["1", "John", "john@example.com"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["1", "John", "john@example.com"] ] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.isEmpty) } - @Test("Row not in deletedRowIndices is skipped") + @Test("Row not in deletedRowIDs is skipped") func testRowNotInDeletedRowIndicesSkipped() throws { let generator = try makeGenerator() let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .delete, cellChanges: [], originalRow: ["1", "John", "john@example.com"]) + RowChange(rowID: .existing(0), type: .delete, cellChanges: [], originalRow: ["1", "John", "john@example.com"]) ] let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.isEmpty) @@ -852,26 +852,26 @@ struct SQLStatementGeneratorTests { func testFullWorkflowIntegration() throws { let generator = try makeGenerator() let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil), + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil), RowChange( - rowIndex: 1, + rowID: .existing(1), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "name", oldValue: "John", newValue: "Johnny") ], originalRow: ["1", "John", "john@example.com"] ), - RowChange(rowIndex: 2, type: .delete, cellChanges: [], originalRow: ["2", "Jane", "jane@example.com"]) + RowChange(rowID: .existing(2), type: .delete, cellChanges: [], originalRow: ["2", "Jane", "jane@example.com"]) ] - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["3", "Bob", "bob@example.com"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["3", "Bob", "bob@example.com"] ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [2], - insertedRowIndices: [0] + deletedRowIDs: [.existing(2)], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 3) @@ -885,7 +885,7 @@ struct SQLStatementGeneratorTests { let generator = try makeGenerator(databaseType: .postgresql) let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "name", oldValue: "John", newValue: "Johnny"), @@ -898,8 +898,8 @@ struct SQLStatementGeneratorTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -923,18 +923,18 @@ struct SQLStatementGeneratorTests { @Test("Redshift insert uses $1, $2 placeholders") func testInsertRedshiftPlaceholders() throws { let generator = try makeGenerator(databaseType: .redshift) - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["1", "John", "john@example.com"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["1", "John", "john@example.com"] ] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -948,18 +948,18 @@ struct SQLStatementGeneratorTests { @Test("Redshift insert uses double-quote identifier quoting") func testInsertRedshiftQuoting() throws { let generator = try makeGenerator(databaseType: .redshift) - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["1", "John", "john@example.com"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["1", "John", "john@example.com"] ] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -976,7 +976,7 @@ struct SQLStatementGeneratorTests { let generator = try makeGenerator(databaseType: .redshift) let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "name", oldValue: "John", newValue: "Johnny") @@ -988,8 +988,8 @@ struct SQLStatementGeneratorTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -1003,15 +1003,15 @@ struct SQLStatementGeneratorTests { func testDeleteRedshiftPlaceholders() throws { let generator = try makeGenerator(databaseType: .redshift) let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .delete, cellChanges: [], originalRow: ["1", "John", "john@example.com"]), - RowChange(rowIndex: 1, type: .delete, cellChanges: [], originalRow: ["2", "Jane", "jane@example.com"]) + RowChange(rowID: .existing(0), type: .delete, cellChanges: [], originalRow: ["1", "John", "john@example.com"]), + RowChange(rowID: .existing(1), type: .delete, cellChanges: [], originalRow: ["2", "Jane", "jane@example.com"]) ] let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [0, 1], - insertedRowIndices: [] + deletedRowIDs: [.existing(0), .existing(1)], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -1024,18 +1024,18 @@ struct SQLStatementGeneratorTests { @Test("Redshift uses $1, $2, $3 sequentially for insert") func testRedshiftSequentialPlaceholders() throws { let generator = try makeGenerator(databaseType: .redshift) - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["1", "John", "john@example.com"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["1", "John", "john@example.com"] ] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -1051,7 +1051,7 @@ struct SQLStatementGeneratorTests { let generator = try makeGenerator(databaseType: .redshift) let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "name", oldValue: "John", newValue: "Johnny"), @@ -1064,8 +1064,8 @@ struct SQLStatementGeneratorTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -1091,7 +1091,7 @@ struct SQLStatementGeneratorTests { ) let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "database", oldValue: "old_db", newValue: "new_db") @@ -1103,8 +1103,8 @@ struct SQLStatementGeneratorTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -1121,18 +1121,18 @@ struct SQLStatementGeneratorTests { columns: ["id", "database", "order"], primaryKeyColumns: ["id"] ) - let insertedRowData: [Int: [PluginCellValue]] = [ - 0: ["1", "mydb", "5"] + let insertedRowData: [RowID: [PluginCellValue]] = [ + .existing(0): ["1", "mydb", "5"] ] let changes: [RowChange] = [ - RowChange(rowIndex: 0, type: .insert, cellChanges: [], originalRow: nil) + RowChange(rowID: .existing(0), type: .insert, cellChanges: [], originalRow: nil) ] let statements = generator.generateStatements( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: [], - insertedRowIndices: [0] + deletedRowIDs: [], + insertedRowIDs: [.existing(0)] ) #expect(statements.count == 1) @@ -1152,7 +1152,7 @@ struct SQLStatementGeneratorTests { ) let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .delete, cellChanges: [], originalRow: ["1", "mydb", "foo"] @@ -1162,8 +1162,8 @@ struct SQLStatementGeneratorTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [0], - insertedRowIndices: [] + deletedRowIDs: [.existing(0)], + insertedRowIDs: [] ) #expect(statements.count == 1) @@ -1182,7 +1182,7 @@ struct SQLStatementGeneratorTests { ) let changes: [RowChange] = [ RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: 1, columnName: "database", oldValue: "old_db", newValue: "new_db") @@ -1194,8 +1194,8 @@ struct SQLStatementGeneratorTests { let statements = generator.generateStatements( from: changes, insertedRowData: [:], - deletedRowIndices: [], - insertedRowIndices: [] + deletedRowIDs: [], + insertedRowIDs: [] ) #expect(statements.count == 1) diff --git a/TableProTests/Core/Coordinators/RowEditingCoordinatorJsonModeTests.swift b/TableProTests/Core/Coordinators/RowEditingCoordinatorJsonModeTests.swift index 8e6f682e36..8fb7a7eb0b 100644 --- a/TableProTests/Core/Coordinators/RowEditingCoordinatorJsonModeTests.swift +++ b/TableProTests/Core/Coordinators/RowEditingCoordinatorJsonModeTests.swift @@ -79,7 +79,7 @@ struct RowEditingCoordinatorJsonModeTests { coordinator.deleteSelectedRows(indices: [0]) - #expect(coordinator.selectionState.indices == [0]) + #expect(coordinator.selectionState.indices == [1]) } @Test("duplicating in JSON mode leaves the selection alone") diff --git a/TableProTests/Core/Coordinators/RowEditingCoordinatorValueFilterTests.swift b/TableProTests/Core/Coordinators/RowEditingCoordinatorValueFilterTests.swift new file mode 100644 index 0000000000..f071e73068 --- /dev/null +++ b/TableProTests/Core/Coordinators/RowEditingCoordinatorValueFilterTests.swift @@ -0,0 +1,149 @@ +// +// RowEditingCoordinatorValueFilterTests.swift +// TableProTests +// + +import Foundation +import TableProPluginKit +import Testing + +@testable import TablePro + +@Suite("RowEditingCoordinator under a value filter") +@MainActor +struct RowEditingCoordinatorValueFilterTests { + private func makeCoordinator() -> MainContentCoordinator { + let tabManager = QueryTabManager() + let coordinator = MainContentCoordinator( + connection: TestFixtures.makeConnection(), + tabManager: tabManager, + changeManager: DataChangeManager(), + toolbarState: ConnectionToolbarState() + ) + var tab = QueryTab(title: "users", query: "SELECT * FROM users", tabType: .table, tableName: "users") + tab.execution.lastExecutedAt = Date() + tab.display.resultsViewMode = .data + tabManager.tabs.append(tab) + tabManager.selectedTabId = tab.id + + coordinator.setActiveTableRows( + TableRows.from( + queryRows: [ + [.text("1"), .text("Alice")], + [.text("2"), .text("Bob")], + [.text("3"), .text("Cleo")], + [.text("4"), .text("Bob")] + ], + columns: ["id", "name"], + columnTypes: [.text(rawType: nil), .text(rawType: nil)], + hasAuthoritativeSchema: true + ), + for: tab.id + ) + coordinator.changeManager.configureForTable( + tableName: "users", + columns: ["id", "name"], + primaryKeyColumns: ["id"], + databaseType: .mysql, + generatedColumns: [] + ) + + var filter = GridValueFilterState() + filter.set( + ColumnValueFilter(selectedValues: ["Bob"], includesNull: false), + columnName: "name", + forColumn: 1 + ) + coordinator.setValueFilter(filter, forTab: tab.id) + return coordinator + } + + private func tableRows(of coordinator: MainContentCoordinator) -> TableRows { + guard let tabId = coordinator.tabManager.selectedTab?.id else { return TableRows() } + return coordinator.tabSessionRegistry.tableRows(for: tabId) + } + + @Test("The filter shows the two Bobs, so display positions are not storage indices") + func filterNarrowsTheDisplay() { + let coordinator = makeCoordinator() + + #expect(coordinator.activeGridDisplayIDs == [.existing(1), .existing(3)]) + } + + @Test("Deleting the second shown row marks id 4, and the DELETE names id 4") + func deleteMarksTheShownRow() throws { + let coordinator = makeCoordinator() + + coordinator.deleteSelectedRows(indices: [1]) + + #expect(coordinator.changeManager.isRowDeleted(.existing(3))) + #expect(!coordinator.changeManager.isRowDeleted(.existing(1))) + let statements = try coordinator.changeManager.generateSQL() + #expect(statements.count == 1) + #expect(statements.first?.parameters.first.flatMap { $0 as? String } == "4") + } + + @Test("A new row is selected at the position the filter shows it") + func addRowSelectsItsDisplayPosition() { + let coordinator = makeCoordinator() + + coordinator.addNewRow() + + let displayIDs = coordinator.activeGridDisplayIDs ?? [] + #expect(displayIDs.count == 3) + #expect(displayIDs.last?.isInserted == true) + #expect(coordinator.selectionState.indices == [2]) + } + + @Test("A duplicated row is selected at the position the filter shows it") + func duplicateSelectsItsDisplayPosition() { + let coordinator = makeCoordinator() + + coordinator.duplicateSelectedRow(index: 1) + + let rows = tableRows(of: coordinator) + #expect(rows.count == 5) + #expect(rows.rows.last?.values[1] == "Bob") + #expect(coordinator.selectionState.indices == [2]) + } + + @Test("Discard puts back the row that was edited, not the one at the same storage offset") + func discardRestoresTheEditedRow() { + let coordinator = makeCoordinator() + guard let tabId = coordinator.tabManager.selectedTab?.id else { + Issue.record("No selected tab") + return + } + coordinator.changeManager.recordCellChange( + rowID: .existing(3), + columnIndex: 1, + columnName: "name", + oldValue: "Bob", + newValue: "Robert", + originalRow: ["4", "Bob"] + ) + coordinator.mutateActiveTableRows(for: tabId) { rows in + rows.edit(row: 3, column: 1, value: "Robert") + } + + coordinator.rowEditingCoordinator.restoreRowBufferToOriginals() + + let rows = tableRows(of: coordinator) + #expect(rows.rows[3].values[1] == "Bob") + #expect(rows.rows[1].values[1] == "Bob") + #expect(rows.rows[2].values[1] == "Cleo") + } + + @Test("Discard removes rows added under the filter") + func discardRemovesInsertedRows() { + let coordinator = makeCoordinator() + coordinator.addNewRow() + #expect(tableRows(of: coordinator).count == 5) + + coordinator.rowEditingCoordinator.restoreRowBufferToOriginals() + + let rows = tableRows(of: coordinator) + #expect(rows.count == 4) + #expect(!rows.rows.contains { $0.id.isInserted }) + } +} diff --git a/TableProTests/Core/DataWrite/PluginKeyedChangesTests.swift b/TableProTests/Core/DataWrite/PluginKeyedChangesTests.swift new file mode 100644 index 0000000000..c6c82f4a3d --- /dev/null +++ b/TableProTests/Core/DataWrite/PluginKeyedChangesTests.swift @@ -0,0 +1,73 @@ +// +// PluginKeyedChangesTests.swift +// TableProTests +// + +import Foundation +import TableProPluginKit +@testable import TablePro +import Testing + +@Suite("Plugin keyed changes") +struct PluginKeyedChangesTests { + @Test("Every row gets its own key, and the key agrees across the changes and the sets") + func keysAgreeAcrossCollections() { + let insertedA = RowID.inserted(UUID()) + let insertedB = RowID.inserted(UUID()) + let changes = [ + RowChange(rowID: .existing(40), type: .delete, originalRow: ["40"]), + RowChange(rowID: insertedA, type: .insert), + RowChange(rowID: .existing(7), type: .update, originalRow: ["7"]), + RowChange(rowID: insertedB, type: .insert) + ] + + let keyed = PluginKeyedChanges( + changes: changes, + insertedRowData: [insertedA: ["a"], insertedB: ["b"]], + deletedRowIDs: [.existing(40)], + insertedRowIDs: [insertedA, insertedB] + ) + + let keys = keyed.changes.map(\.rowIndex) + #expect(Set(keys).count == 4) + #expect(keyed.deletedRowIndices == [keys[0]]) + #expect(keyed.insertedRowIndices == [keys[1], keys[3]]) + #expect(keyed.insertedRowData[keys[1]] == ["a"]) + #expect(keyed.insertedRowData[keys[3]] == ["b"]) + #expect(keyed.insertedRowData[keys[2]] == nil) + } + + @Test("A row marked in a set but carried by no change is left out") + func rowsWithoutAChangeAreDropped() { + let orphan = RowID.inserted(UUID()) + let keyed = PluginKeyedChanges( + changes: [RowChange(rowID: .existing(1), type: .delete, originalRow: ["1"])], + insertedRowData: [orphan: ["x"]], + deletedRowIDs: [.existing(1), .existing(2)], + insertedRowIDs: [orphan] + ) + + #expect(keyed.changes.count == 1) + #expect(keyed.deletedRowIndices.count == 1) + #expect(keyed.insertedRowIndices.isEmpty) + #expect(keyed.insertedRowData.isEmpty) + } + + @Test("The change keeps its type, cells and original row across the boundary") + func changeContentCrossesUnchanged() { + let change = RowChange( + rowID: .existing(3), + type: .update, + cellChanges: [CellChange(columnIndex: 1, columnName: "name", oldValue: "a", newValue: "b")], + originalRow: ["3", "a"] + ) + + let keyed = PluginKeyedChanges(changes: [change], insertedRowData: [:], deletedRowIDs: [], insertedRowIDs: []) + + let crossed = keyed.changes.first + #expect(crossed?.type == .update) + #expect(crossed?.cellChanges.first?.columnName == "name") + #expect(crossed?.cellChanges.first?.newValue == "b") + #expect(crossed?.originalRow == ["3", "a"]) + } +} diff --git a/TableProTests/Core/DataWrite/RowWriteOperationBuilderTests.swift b/TableProTests/Core/DataWrite/RowWriteOperationBuilderTests.swift index 34a2ae1567..7d1e075d67 100644 --- a/TableProTests/Core/DataWrite/RowWriteOperationBuilderTests.swift +++ b/TableProTests/Core/DataWrite/RowWriteOperationBuilderTests.swift @@ -15,9 +15,9 @@ struct RowWriteOperationBuilderTests { private func operations( changes: [RowChange], - insertedRowData: [Int: [PluginCellValue]] = [:], - deletedRowIndices: Set = [], - insertedRowIndices: Set = [], + insertedRowData: [RowID: [PluginCellValue]] = [:], + deletedRowIDs: Set = [], + insertedRowIDs: Set = [], primaryKeyColumns: [String] = ["id"], generatedColumns: Set = [], containsTableOperation: Bool = false @@ -25,8 +25,8 @@ struct RowWriteOperationBuilderTests { RowWriteOperationBuilder.operations( from: changes, insertedRowData: insertedRowData, - deletedRowIndices: deletedRowIndices, - insertedRowIndices: insertedRowIndices, + deletedRowIDs: deletedRowIDs, + insertedRowIDs: insertedRowIDs, target: target, columns: columns, primaryKeyColumns: primaryKeyColumns, @@ -37,7 +37,7 @@ struct RowWriteOperationBuilderTests { private func cellEdit(column: String, index: Int, from old: PluginCellValue, to new: PluginCellValue) -> RowChange { RowChange( - rowIndex: 0, + rowID: .existing(0), type: .update, cellChanges: [ CellChange(columnIndex: index, columnName: column, oldValue: old, newValue: new), @@ -110,8 +110,8 @@ struct RowWriteOperationBuilderTests { @Test("A delete keeps the whole row") func deleteCapturesTheRow() { - let change = RowChange(rowIndex: 0, type: .delete, originalRow: ["7", "Ada", "2026-01-01"]) - let result = operations(changes: [change], deletedRowIndices: [0]) + let change = RowChange(rowID: .existing(0), type: .delete, originalRow: ["7", "Ada", "2026-01-01"]) + let result = operations(changes: [change], deletedRowIDs: [.existing(0)]) #expect(result.first?.kind == .delete) #expect(result.first?.preImage == ["7", "Ada", "2026-01-01"]) @@ -121,18 +121,18 @@ struct RowWriteOperationBuilderTests { @Test("An insert whose key the server chooses cannot be taken back") func serverAssignedKeyIsRefused() { - let change = RowChange(rowIndex: 0, type: .insert) + let change = RowChange(rowID: .existing(0), type: .insert) let withMarker = operations( changes: [change], - insertedRowData: [0: [.text(PluginCellValue.defaultMarkerText), "Ada", "2026-01-01"]], - insertedRowIndices: [0] + insertedRowData: [.existing(0): [.text(PluginCellValue.defaultMarkerText), "Ada", "2026-01-01"]], + insertedRowIDs: [.existing(0)] ) #expect(withMarker.first?.refusal == .serverAssignedKey) let withNull = operations( changes: [change], - insertedRowData: [0: [.null, "Ada", "2026-01-01"]], - insertedRowIndices: [0] + insertedRowData: [.existing(0): [.null, "Ada", "2026-01-01"]], + insertedRowIDs: [.existing(0)] ) #expect(withNull.first?.refusal == .serverAssignedKey) } @@ -140,9 +140,9 @@ struct RowWriteOperationBuilderTests { @Test("An insert carrying its own key is reversible") func userSuppliedKeyIsReversible() { let result = operations( - changes: [RowChange(rowIndex: 0, type: .insert)], - insertedRowData: [0: ["7", "Ada", "2026-01-01"]], - insertedRowIndices: [0] + changes: [RowChange(rowID: .existing(0), type: .insert)], + insertedRowData: [.existing(0): ["7", "Ada", "2026-01-01"]], + insertedRowIDs: [.existing(0)] ) #expect(result.first?.refusal == nil) #expect(result.first?.postImage == ["7", "Ada", "2026-01-01"]) diff --git a/TableProTests/Core/Services/RowOperationsManagerTests.swift b/TableProTests/Core/Services/RowOperationsManagerTests.swift index dd4854fff3..be1327effe 100644 --- a/TableProTests/Core/Services/RowOperationsManagerTests.swift +++ b/TableProTests/Core/Services/RowOperationsManagerTests.swift @@ -65,7 +65,7 @@ struct RowOperationsManagerTests { #expect(tableRows.count == originalCount + 1) } - @Test("addNewRow returns correct row index and inserted delta") + @Test("addNewRow appends the row it names and reports an inserted delta") func addNewRowReturnsCorrectIndex() { let (manager, _) = makeManager() var tableRows = makeTableRows(rowCount: 5) @@ -73,7 +73,7 @@ struct RowOperationsManagerTests { let result = manager.addNewRow(tableRows: &tableRows) #expect(result != nil) - #expect(result?.rowIndex == 5) + #expect(result.flatMap { tableRows.index(of: $0.rowID) } == 5) if case .rowsInserted(let indices) = result?.delta { #expect(indices == IndexSet(integer: 5)) } else { @@ -88,9 +88,8 @@ struct RowOperationsManagerTests { let result = manager.addNewRow(tableRows: &tableRows) - #expect(result != nil) - let newIndex = result!.rowIndex - #expect(tableRows.rows[newIndex].id.isInserted) + #expect(result?.rowID.isInserted == true) + #expect(tableRows.rows.last?.id == result?.rowID) } @Test("addNewRow uses DEFAULT marker for columns with defaults") @@ -166,7 +165,7 @@ struct RowOperationsManagerTests { #expect(result != nil) #expect(changeManager.hasChanges) - #expect(changeManager.isRowInserted(result!.rowIndex)) + #expect(result.map { changeManager.isRowInserted($0.rowID) } == true) } @Test("addNewRow increments change manager reload version") @@ -199,9 +198,9 @@ struct RowOperationsManagerTests { let r3 = manager.addNewRow(tableRows: &tableRows) #expect(tableRows.count == 5) - #expect(r1?.rowIndex == 2) - #expect(r2?.rowIndex == 3) - #expect(r3?.rowIndex == 4) + #expect(r1.flatMap { tableRows.index(of: $0.rowID) } == 2) + #expect(r2.flatMap { tableRows.index(of: $0.rowID) } == 3) + #expect(r3.flatMap { tableRows.index(of: $0.rowID) } == 4) } @Test("duplicateRow copies source row values") @@ -277,8 +276,8 @@ struct RowOperationsManagerTests { ) #expect(changeManager.hasChanges) - #expect(changeManager.isRowDeleted(1)) - #expect(changeManager.isRowDeleted(3)) + #expect(changeManager.isRowDeleted(.existing(1))) + #expect(changeManager.isRowDeleted(.existing(3))) } @Test("deleteSelectedRows removes inserted rows from tableRows and reports delta") @@ -286,17 +285,17 @@ struct RowOperationsManagerTests { let (manager, _) = makeManager() var tableRows = makeTableRows(rowCount: 3) - let addResult = manager.addNewRow(tableRows: &tableRows) + _ = manager.addNewRow(tableRows: &tableRows) #expect(tableRows.count == 4) let result = manager.deleteSelectedRows( - selectedIndices: [addResult!.rowIndex], + selectedIndices: [3], tableRows: &tableRows ) #expect(tableRows.count == 3) if case .rowsRemoved(let indices) = result.delta { - #expect(indices == IndexSet(integer: addResult!.rowIndex)) + #expect(indices == IndexSet(integer: 3)) } else { Issue.record("Expected .rowsRemoved delta") } @@ -319,6 +318,33 @@ struct RowOperationsManagerTests { #expect(result.nextRowToSelect < tableRows.count) } + @Test("deleteSelectedRows selects the row after the block, or the one before it at the end") + func deleteSelectedRowsNextSelection() { + let (manager, _) = makeManager() + + var fourRows = makeTableRows(rowCount: 4) + #expect(manager.deleteSelectedRows(selectedIndices: [1], tableRows: &fourRows).nextRowToSelect == 2) + + var fromTheEnd = makeTableRows(rowCount: 4) + #expect(manager.deleteSelectedRows(selectedIndices: [3], tableRows: &fromTheEnd).nextRowToSelect == 2) + + var block = makeTableRows(rowCount: 6) + #expect(manager.deleteSelectedRows(selectedIndices: [1, 2, 3], tableRows: &block).nextRowToSelect == 4) + } + + @Test("deleteSelectedRows counts the rows the removal took out before choosing the next one") + func deleteSelectedRowsNextSelectionAfterRemovals() { + let (manager, _) = makeManager() + var tableRows = makeTableRows(rowCount: 2) + _ = manager.addNewRow(tableRows: &tableRows) + _ = manager.addNewRow(tableRows: &tableRows) + + let result = manager.deleteSelectedRows(selectedIndices: [2, 3], tableRows: &tableRows) + + #expect(tableRows.count == 2) + #expect(result.nextRowToSelect == 1) + } + @Test("deleteSelectedRows returns empty result for empty selection") func deleteSelectedRowsEmptySelection() { let (manager, _) = makeManager() @@ -379,60 +405,89 @@ struct RowOperationsManagerTests { #expect(tableRows.count == 3) } - @Test("deleteRows marks an existing row deleted at its display index with the given values") - func deleteRowsMarksExistingByDisplayIndex() { + @Test("Under a value filter, a selected position deletes the row shown there") + func deleteSelectedRowsUnderFilterMarksTheShownRow() { let (manager, changeManager) = makeManager() var tableRows = makeTableRows(rowCount: 4) - let resolvedRow: [PluginCellValue] = [.text("42"), .text("Zoe"), .text("zoe@test.com")] + let displayIDs: [RowID] = [.existing(3), .existing(1)] + let shownRow = Array(tableRows.rows[1].values) - _ = manager.deleteRows( - existingRows: [(displayIndex: 1, originalRow: resolvedRow)], - insertedStorageIndices: [], - tableRows: &tableRows - ) + _ = manager.deleteSelectedRows(selectedIndices: [1], displayIDs: displayIDs, tableRows: &tableRows) - #expect(changeManager.isRowDeleted(1)) + #expect(changeManager.isRowDeleted(.existing(1))) + #expect(!changeManager.isRowDeleted(.existing(3))) #expect(tableRows.count == 4) - let deleteChange = changeManager.rowChanges.first { $0.type == .delete && $0.rowIndex == 1 } - #expect(deleteChange?.originalRow == resolvedRow) + let deleteChange = changeManager.rowChanges.first { $0.type == .delete } + #expect(deleteChange?.rowID == .existing(1)) + #expect(deleteChange?.originalRow == shownRow) } - @Test("deleteRows physically removes inserted rows by storage index") - func deleteRowsRemovesInsertedByStorageIndex() { - let (manager, _) = makeManager() + @Test("Under a value filter, a selected inserted row is removed from its storage position") + func deleteSelectedRowsUnderFilterRemovesInsertedRow() { + let (manager, changeManager) = makeManager() var tableRows = makeTableRows(rowCount: 3) guard let addResult = manager.addNewRow(tableRows: &tableRows) else { Issue.record("addNewRow returned nil") return } - #expect(tableRows.count == 4) + let displayIDs: [RowID] = [.existing(2), addResult.rowID] - let result = manager.deleteRows( - existingRows: [], - insertedStorageIndices: [addResult.rowIndex], - tableRows: &tableRows - ) + let result = manager.deleteSelectedRows(selectedIndices: [1], displayIDs: displayIDs, tableRows: &tableRows) #expect(tableRows.count == 3) - #expect(result.physicallyRemovedIndices == [addResult.rowIndex]) + #expect(tableRows.index(of: addResult.rowID) == nil) + #expect(!changeManager.isRowInserted(addResult.rowID)) + #expect(result.physicallyRemovedIndices == [3]) if case .rowsRemoved(let indices) = result.delta { - #expect(indices == IndexSet(integer: addResult.rowIndex)) + #expect(indices == IndexSet(integer: 3)) } else { Issue.record("Expected .rowsRemoved delta") } } + @Test("Undoing the removal of inserted rows puts them back where they were, with their identity") + func undoRemovedInsertedRowsRestoresThem() { + let (manager, changeManager) = makeManager() + let undoManager = UndoManager() + undoManager.groupsByEvent = false + changeManager.undoManagerProvider = { undoManager } + var captured: UndoResult? + changeManager.onUndoApplied = { captured = $0 } + var tableRows = makeTableRows(rowCount: 2) + guard let first = manager.addNewRow(tableRows: &tableRows), + let second = manager.addNewRow(tableRows: &tableRows) else { + Issue.record("addNewRow returned nil") + return + } + + _ = manager.deleteSelectedRows(selectedIndices: [2, 3], tableRows: &tableRows) + #expect(tableRows.count == 2) + + undoManager.undo() + guard let captured else { + Issue.record("No undo result") + return + } + _ = manager.applyUndoResult(captured, tableRows: &tableRows) + + #expect(tableRows.index(of: first.rowID) == 2) + #expect(tableRows.index(of: second.rowID) == 3) + #expect(changeManager.isRowInserted(first.rowID)) + #expect(changeManager.isRowInserted(second.rowID)) + } + @Test("addNewRow then edit cell preserves insertion state") func addNewRowThenEditPreservesInsertion() { let (manager, changeManager) = makeManager() var tableRows = makeTableRows(rowCount: 2) - let result = manager.addNewRow(tableRows: &tableRows) - #expect(result != nil) - let newIndex = result!.rowIndex + guard let result = manager.addNewRow(tableRows: &tableRows) else { + Issue.record("addNewRow returned nil") + return + } changeManager.recordCellChange( - rowIndex: newIndex, + rowID: result.rowID, columnIndex: 1, columnName: "name", oldValue: nil, @@ -440,8 +495,8 @@ struct RowOperationsManagerTests { ) #expect(changeManager.hasChanges) - #expect(changeManager.isRowInserted(newIndex)) + #expect(changeManager.isRowInserted(result.rowID)) #expect(tableRows.count == 3) - #expect(tableRows.rows[newIndex].id.isInserted) + #expect(tableRows.row(withID: result.rowID) != nil) } } diff --git a/TableProTests/Core/Services/UndoRowIndexTests.swift b/TableProTests/Core/Services/UndoRowIdentityTests.swift similarity index 55% rename from TableProTests/Core/Services/UndoRowIndexTests.swift rename to TableProTests/Core/Services/UndoRowIdentityTests.swift index a0e972eef0..e2d19956ff 100644 --- a/TableProTests/Core/Services/UndoRowIndexTests.swift +++ b/TableProTests/Core/Services/UndoRowIdentityTests.swift @@ -1,12 +1,7 @@ // -// UndoRowIndexTests.swift +// UndoRowIdentityTests.swift // TableProTests // -// A cell edit is tracked by its display row, the same as the modified marks the grid draws, but -// TableRows is indexed by storage position. Undo used to write straight through with the display -// number, so with a value filter narrowing the grid it reverted whichever row happened to sit at -// that storage offset. -// import Foundation import TableProPluginKit @@ -14,8 +9,8 @@ import TableProPluginKit import Testing @MainActor -@Suite("Undo row indices") -struct UndoRowIndexTests { +@Suite("Undo row identity") +struct UndoRowIdentityTests { private static let columns = ["id", "name"] private func makeTableRows() -> TableRows { @@ -42,10 +37,10 @@ struct UndoRowIndexTests { return RowOperationsManager(changeManager: changeManager) } - private func cellEditUndo(displayRow: Int, previous: PluginCellValue) -> UndoResult { + private func cellEditUndo(rowID: RowID, previous: PluginCellValue) -> UndoResult { UndoResult( action: .cellEdit( - rowIndex: displayRow, + rowID: rowID, columnIndex: 1, columnName: "name", previousValue: previous, @@ -58,16 +53,13 @@ struct UndoRowIndexTests { ) } - /// Display 1 is storage 2 once the middle row is filtered out. - @Test("Undoing a cell edit under a value filter reverts the row that was edited") - func undoResolvesThroughTheFilter() { + @Test("Undoing a cell edit reverts the row that was edited") + func undoRevertsTheEditedRow() { var tableRows = makeTableRows() - let displayIDs = [tableRows.rows[0].id, tableRows.rows[2].id] tableRows.rows[2].values[1] = "edited" _ = makeManager().applyUndoResult( - cellEditUndo(displayRow: 1, previous: "keep"), - displayIDs: displayIDs, + cellEditUndo(rowID: tableRows.rows[2].id, previous: "keep"), tableRows: &tableRows ) @@ -75,33 +67,42 @@ struct UndoRowIndexTests { #expect(tableRows.rows[1].values[1] == "drop") } - @Test("With no filter the display row is the storage row, and nothing changes") - func undoWithoutFilterIsUnchanged() { + @Test("A row that is no longer loaded reverts nothing rather than the wrong row") + func undoForAMissingRowIsANoOp() { var tableRows = makeTableRows() - tableRows.rows[1].values[1] = "edited" + let before = tableRows.rows.map { $0.values } - _ = makeManager().applyUndoResult( - cellEditUndo(displayRow: 1, previous: "drop"), - displayIDs: nil, + let result = makeManager().applyUndoResult( + cellEditUndo(rowID: .existing(99), previous: "keep"), tableRows: &tableRows ) - #expect(tableRows.rows[1].values[1] == "drop") + #expect(result.delta == .none) + #expect(tableRows.rows.map { $0.values } == before) } - @Test("A display row the filter no longer shows reverts nothing rather than the wrong row") - func undoForAHiddenRowIsANoOp() { + @Test("Undoing an insertion removes that row, and redoing it restores the same row") + func insertionUndoRedoKeepsIdentity() { var tableRows = makeTableRows() - let displayIDs = [tableRows.rows[0].id] - let before = tableRows.rows.map { $0.values } + let rowID = RowID.inserted(UUID()) + _ = tableRows.appendInsertedRow(id: rowID, values: ["4", "new"]) + let manager = makeManager() - let result = makeManager().applyUndoResult( - cellEditUndo(displayRow: 5, previous: "keep"), - displayIDs: displayIDs, - tableRows: &tableRows + let removal = UndoResult( + action: .rowInsertion(rowID: rowID), needsRowRemoval: true, needsRowRestore: false, restoreRow: nil ) + let removed = manager.applyUndoResult(removal, tableRows: &tableRows) - #expect(result.delta == .none) - #expect(tableRows.rows.map { $0.values } == before) + #expect(tableRows.index(of: rowID) == nil) + #expect(removed.delta == .rowsRemoved(IndexSet(integer: 3))) + + let restore = UndoResult( + action: .rowInsertion(rowID: rowID), needsRowRemoval: false, needsRowRestore: true, + restoreRow: ["4", "new"] + ) + _ = manager.applyUndoResult(restore, tableRows: &tableRows) + + #expect(tableRows.index(of: rowID) == 3) + #expect(tableRows.row(withID: rowID)?.values == ["4", "new"]) } } diff --git a/TableProTests/Core/Utilities/DisplayedResultReaderTests.swift b/TableProTests/Core/Utilities/DisplayedResultReaderTests.swift index 6b710b526f..7c0050c902 100644 --- a/TableProTests/Core/Utilities/DisplayedResultReaderTests.swift +++ b/TableProTests/Core/Utilities/DisplayedResultReaderTests.swift @@ -33,14 +33,14 @@ struct DisplayedResultReaderTests { private func read( displayIDs: [RowID]? = nil, selected: Set = [], - deleted: Set = [], + deleted: Set = [], columns: VisibleColumnProjection = .identity ) -> DisplayedResultReader.Output { DisplayedResultReader.read( tableRows: makeTableRows(), displayIDs: displayIDs, selectedDisplayIndices: selected, - deletedDisplayIndices: deleted, + deletedRowIDs: deleted, columns: columns ) } @@ -83,12 +83,20 @@ struct DisplayedResultReaderTests { @Test("A row marked for deletion is left out and counted") func deletedRowsAreSkipped() { - let output = read(deleted: [1]) + let output = read(deleted: [.existing(1)]) #expect(texts(output) == [["a", "1"], ["c", "3"]]) #expect(output.skippedDeletedCount == 1) } + @Test("A deletion is matched by the row it was made to, whatever position the filter gives it") + func deletedRowsFollowTheirRowUnderAFilter() { + let output = read(displayIDs: [.existing(2), .existing(0)], deleted: [.existing(0)]) + + #expect(texts(output) == [["c", "3"]]) + #expect(output.skippedDeletedCount == 1) + } + @Test("Hidden and reordered columns follow the grid") func columnProjectionIsApplied() { let output = read(columns: VisibleColumnProjection(indices: [1])) diff --git a/TableProTests/Core/Utilities/ResultJsonSerializerTests.swift b/TableProTests/Core/Utilities/ResultJsonSerializerTests.swift index 03658d5dff..01b875e11c 100644 --- a/TableProTests/Core/Utilities/ResultJsonSerializerTests.swift +++ b/TableProTests/Core/Utilities/ResultJsonSerializerTests.swift @@ -26,7 +26,7 @@ struct ResultJsonSerializerTests { private func serialize( displayIDs: [RowID]? = nil, selected: Set = [], - deleted: Set? = nil + deleted: Set? = nil ) -> ResultJsonSerializer.Output { guard let deleted else { return ResultJsonSerializer.serialize( @@ -40,7 +40,7 @@ struct ResultJsonSerializerTests { tableRows: makeTableRows(), displayIDs: displayIDs, selectedDisplayIndices: selected, - deletedDisplayIndices: deleted, + deletedRowIDs: deleted, columns: .identity ) } @@ -55,9 +55,9 @@ struct ResultJsonSerializerTests { #expect(withoutParameter.json.contains("\"b\"")) } - @Test("a supplied deleted position is skipped") - func deletedPositionIsSkipped() { - let output = serialize(deleted: [1]) + @Test("a supplied deleted row is skipped") + func deletedRowIsSkipped() { + let output = serialize(deleted: [.existing(1)]) #expect(output.rowCount == 2) #expect(output.json.contains("\"a\"")) @@ -65,9 +65,9 @@ struct ResultJsonSerializerTests { #expect(output.json.contains("\"c\"")) } - @Test("deleted positions are display positions, not storage indices") - func deletedPositionsAreDisplayPositions() { - let output = serialize(displayIDs: [.existing(2), .existing(1)], deleted: [0]) + @Test("a deletion names a row, not the position a value filter gives it") + func deletionsNameRowsNotPositions() { + let output = serialize(displayIDs: [.existing(2), .existing(1)], deleted: [.existing(2)]) #expect(output.rowCount == 1) #expect(output.json.contains("\"b\"")) @@ -76,7 +76,7 @@ struct ResultJsonSerializerTests { @Test("deleting every displayed row leaves an empty array") func deletingEverythingLeavesAnEmptyArray() { - let output = serialize(deleted: [0, 1, 2]) + let output = serialize(deleted: [.existing(0), .existing(1), .existing(2)]) #expect(output.rowCount == 0) #expect(output.json == "[]") diff --git a/TableProTests/Helpers/TestFixtures.swift b/TableProTests/Helpers/TestFixtures.swift index 56423273f5..e286e915ec 100644 --- a/TableProTests/Helpers/TestFixtures.swift +++ b/TableProTests/Helpers/TestFixtures.swift @@ -72,7 +72,7 @@ enum TestFixtures { originalRow: [String?]? = nil ) -> RowChange { return RowChange( - rowIndex: row, + rowID: .existing(row), type: type, cellChanges: cells, originalRow: originalRow.map { row in row.map(PluginCellValue.fromOptional) } diff --git a/TableProTests/Views/Main/CommandActionsBulkCloseTests.swift b/TableProTests/Views/Main/CommandActionsBulkCloseTests.swift index 976309a591..212b0e01b2 100644 --- a/TableProTests/Views/Main/CommandActionsBulkCloseTests.swift +++ b/TableProTests/Views/Main/CommandActionsBulkCloseTests.swift @@ -268,7 +268,7 @@ struct CommandActionsBulkCloseTests { tab.content.sourceFileURL = URL(fileURLWithPath: "/tmp/tablepro-mixed.sql") tab.content.savedFileContent = "SELECT 1" tab.content.query = "SELECT 2" - tab.pendingChanges.deletedRowIndices = [0] + tab.pendingChanges.deletedRowIDs = [.existing(0)] } let mixed = try #require(current.coordinator.tabManager.tabs.first) diff --git a/TableProTests/Views/Main/CoordinatorColumnVisibilityTests.swift b/TableProTests/Views/Main/CoordinatorColumnVisibilityTests.swift index fce1b2dc3c..2ada5371aa 100644 --- a/TableProTests/Views/Main/CoordinatorColumnVisibilityTests.swift +++ b/TableProTests/Views/Main/CoordinatorColumnVisibilityTests.swift @@ -52,7 +52,7 @@ struct CoordinatorColumnVisibilityTests { triggerReload: false ) coordinator.changeManager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", diff --git a/TableProTests/Views/Main/EvictionTests.swift b/TableProTests/Views/Main/EvictionTests.swift index 521bdf0149..ed824077a7 100644 --- a/TableProTests/Views/Main/EvictionTests.swift +++ b/TableProTests/Views/Main/EvictionTests.swift @@ -91,7 +91,7 @@ struct EvictionTests { let (coordinator, tabManager) = makeCoordinator() try addLoadedTab(to: coordinator, tabManager: tabManager, tableName: "users") - tabManager.tabs[0].pendingChanges.deletedRowIndices = [0] + tabManager.tabs[0].pendingChanges.deletedRowIDs = [.existing(0)] let loadEpoch = tabManager.tabs[0].loadEpoch try addLoadedTab(to: coordinator, tabManager: tabManager, tableName: "orders") diff --git a/TableProTests/Views/Main/MainContentCoordinatorLazyLoadTests.swift b/TableProTests/Views/Main/MainContentCoordinatorLazyLoadTests.swift index e84e86ab66..3aef26c4f0 100644 --- a/TableProTests/Views/Main/MainContentCoordinatorLazyLoadTests.swift +++ b/TableProTests/Views/Main/MainContentCoordinatorLazyLoadTests.swift @@ -131,7 +131,7 @@ struct MainContentCoordinatorLazyLoadTests { Issue.record("expected tab to exist") return } - tabManager.tabs[idx].pendingChanges.deletedRowIndices = [0] + tabManager.tabs[idx].pendingChanges.deletedRowIDs = [.existing(0)] coordinator.lazyLoadCurrentTabIfNeeded() #expect(coordinator.pendingLoadTrigger == nil) diff --git a/TableProTests/Views/Main/MainContentCoordinatorTabSwitchTests.swift b/TableProTests/Views/Main/MainContentCoordinatorTabSwitchTests.swift index 96e4d4d4f5..b1616e6282 100644 --- a/TableProTests/Views/Main/MainContentCoordinatorTabSwitchTests.swift +++ b/TableProTests/Views/Main/MainContentCoordinatorTabSwitchTests.swift @@ -350,7 +350,7 @@ struct MainContentCoordinatorTabSwitchTests { triggerReload: false ) coordinator.changeManager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", @@ -388,7 +388,7 @@ struct MainContentCoordinatorTabSwitchTests { triggerReload: false ) coordinator.changeManager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", @@ -572,7 +572,7 @@ struct MainContentCoordinatorTabSwitchTests { triggerReload: false ) coordinator.changeManager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "total", oldValue: "10", @@ -895,7 +895,7 @@ struct MainContentCoordinatorTabSwitchTests { triggerReload: false ) manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: "Alice", diff --git a/TableProTests/Views/Main/QueryFailureReportingTests.swift b/TableProTests/Views/Main/QueryFailureReportingTests.swift index 8b824f33ba..5dfcf26ab9 100644 --- a/TableProTests/Views/Main/QueryFailureReportingTests.swift +++ b/TableProTests/Views/Main/QueryFailureReportingTests.swift @@ -202,7 +202,7 @@ struct QueryFailureReportingTests { tabManager.selectedTabId = selectedTabId coordinator.changeManager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 1, columnName: "name", oldValue: nil, diff --git a/TableProTests/Views/Main/TabCloseProtectionTests.swift b/TableProTests/Views/Main/TabCloseProtectionTests.swift index ad72a7f3f9..50f99b13b0 100644 --- a/TableProTests/Views/Main/TabCloseProtectionTests.swift +++ b/TableProTests/Views/Main/TabCloseProtectionTests.swift @@ -33,7 +33,7 @@ struct TabCloseProtectionTests { databaseType: .mysql, generatedColumns: [] ) - coordinator.changeManager.recordRowDeletion(rowIndex: 0, originalRow: Self.originalRow) + coordinator.changeManager.recordRowDeletion(rowID: .existing(0), originalRow: Self.originalRow) } // MARK: - The reported bug diff --git a/TableProTests/Views/Results/DataGridCellFactoryPerfTests.swift b/TableProTests/Views/Results/DataGridCellFactoryPerfTests.swift index 1647eedafa..8a6c4a6f84 100644 --- a/TableProTests/Views/Results/DataGridCellFactoryPerfTests.swift +++ b/TableProTests/Views/Results/DataGridCellFactoryPerfTests.swift @@ -409,7 +409,7 @@ struct ChangeReapplyVersionTests { let initialVersion = manager.reloadVersion manager.recordCellChange( - rowIndex: 0, + rowID: .existing(0), columnIndex: 0, columnName: "name", oldValue: "old", diff --git a/TableProTests/Views/Results/Extensions/FillColumnTests.swift b/TableProTests/Views/Results/Extensions/FillColumnTests.swift index 35d0fcba7d..ebd34fe1ad 100644 --- a/TableProTests/Views/Results/Extensions/FillColumnTests.swift +++ b/TableProTests/Views/Results/Extensions/FillColumnTests.swift @@ -117,21 +117,21 @@ struct FillColumnTests { coordinator.applyFillColumn(columnIndex: 0, value: .text("X")) for row in 0..<4 { - #expect(manager.pending.isCellModified(rowIndex: row, columnIndex: 0)) + #expect(manager.pending.isCellModified(rowID: .existing(row), columnIndex: 0)) } - #expect(manager.pending.isCellModified(rowIndex: 0, columnIndex: 1) == false) + #expect(manager.pending.isCellModified(rowID: .existing(0), columnIndex: 1) == false) } @Test("Does not touch rows marked for deletion") func skipsDeletedRowsOnApply() { let manager = DataChangeManager() let coordinator = makeCoordinator(columns: ["a"], rowCount: 4, manager: manager) - manager.recordRowDeletion(rowIndex: 2, originalRow: [.text("r2c0")]) + manager.recordRowDeletion(rowID: .existing(2), originalRow: [.text("r2c0")]) coordinator.applyFillColumn(columnIndex: 0, value: .text("X")) - #expect(manager.pending.isCellModified(rowIndex: 0, columnIndex: 0)) - #expect(manager.pending.isCellModified(rowIndex: 2, columnIndex: 0) == false) + #expect(manager.pending.isCellModified(rowID: .existing(0), columnIndex: 0)) + #expect(manager.pending.isCellModified(rowID: .existing(2), columnIndex: 0) == false) } @Test("Records nothing on a read-only result set") @@ -151,7 +151,7 @@ struct FillColumnTests { coordinator.applyFillColumn(columnIndex: 0, value: .null) - let change = manager.pending.change(forRow: 0, type: .update) + let change = manager.pending.change(forRow: .existing(0), type: .update) #expect(change?.cellChanges.first?.newValue == .null) } @@ -162,7 +162,7 @@ struct FillColumnTests { coordinator.applyFillColumn(columnIndex: 0, value: .text("r0c0")) - #expect(manager.pending.isCellModified(rowIndex: 0, columnIndex: 0) == false) - #expect(manager.pending.isCellModified(rowIndex: 1, columnIndex: 0)) + #expect(manager.pending.isCellModified(rowID: .existing(0), columnIndex: 0) == false) + #expect(manager.pending.isCellModified(rowID: .existing(1), columnIndex: 0)) } } diff --git a/TableProTests/Views/Results/ResultsJsonViewTests.swift b/TableProTests/Views/Results/ResultsJsonViewTests.swift index 3d49723d58..abdb136211 100644 --- a/TableProTests/Views/Results/ResultsJsonViewTests.swift +++ b/TableProTests/Views/Results/ResultsJsonViewTests.swift @@ -32,14 +32,14 @@ struct ResultsJsonViewTests { private func compute( displayIDs: [RowID]? = nil, selectedIndices: Set, - deletedIndices: Set = [], + deletedRowIDs: Set = [], columnLayout: ColumnLayoutState = ColumnLayoutState() ) -> ResultsJsonView.RenderedJson { ResultsJsonView.computeJson( tableRows: makeTableRows(), displayIDs: displayIDs, selectedIndices: selectedIndices, - deletedIndices: deletedIndices, + deletedRowIDs: deletedRowIDs, columnLayout: columnLayout ) } @@ -78,7 +78,7 @@ struct ResultsJsonViewTests { @Test("a row marked for deletion is left out of the document") func pendingDeletionIsExcluded() { - let result = compute(selectedIndices: [], deletedIndices: [1]) + let result = compute(selectedIndices: [], deletedRowIDs: [.existing(1)]) #expect(result.resolvedCount == 3) #expect(!result.json.contains("\"b\"")) @@ -88,16 +88,18 @@ struct ResultsJsonViewTests { @Test("a row marked for deletion is left out even when it is part of the selection") func pendingDeletionIsExcludedFromASelection() { - let result = compute(selectedIndices: [0, 1], deletedIndices: [1]) + let result = compute(selectedIndices: [0, 1], deletedRowIDs: [.existing(1)]) #expect(result.resolvedCount == 1) #expect(result.json.contains("\"a\"")) #expect(!result.json.contains("\"b\"")) } - @Test("deletion positions are display positions, resolved through the display order") - func pendingDeletionUsesDisplayPositions() { - let result = compute(displayIDs: [.existing(2), .existing(0)], selectedIndices: [], deletedIndices: [0]) + @Test("a deletion stays on its row whatever position the display order gives it") + func pendingDeletionFollowsItsRow() { + let result = compute( + displayIDs: [.existing(2), .existing(0)], selectedIndices: [], deletedRowIDs: [.existing(2)] + ) #expect(result.resolvedCount == 1) #expect(result.json.contains("\"a\"")) diff --git a/TableProTests/Views/Results/RowVisualIndexTests.swift b/TableProTests/Views/Results/RowVisualIndexTests.swift index 43165366cf..a9126c82d7 100644 --- a/TableProTests/Views/Results/RowVisualIndexTests.swift +++ b/TableProTests/Views/Results/RowVisualIndexTests.swift @@ -4,35 +4,87 @@ // import Foundation +import TableProPluginKit import Testing @testable import TablePro -@Suite("RowVisualIndex display-order mapping") +@Suite("RowVisualIndex row identity") @MainActor struct RowVisualIndexTests { - @Test("an inserted row is marked at its display index, not its model index") - func insertedRowMarkedAtDisplayIndex() { + private func makeManager() -> DataChangeManager { + let manager = DataChangeManager() + manager.configureForTable( + tableName: "users", + columns: ["id", "name"], + primaryKeyColumns: ["id"], + databaseType: .mysql, + generatedColumns: [] + ) + return manager + } + + @Test("An inserted row is marked on its own row id") + func insertedRowMarkedOnItsID() { + let manager = makeManager() + let inserted = RowID.inserted(UUID()) + manager.recordRowInsertion(rowID: inserted, values: [.null, .null]) + let index = RowVisualIndex() + + index.rebuild(from: AnyChangeManager(manager)) + + #expect(index.visualState(for: inserted).isInserted) + #expect(!index.visualState(for: .existing(0)).isInserted) + } + + @Test("Edits and deletions are marked on the rows they were made to") + func editsAndDeletionsFollowTheirRows() { + let manager = makeManager() + manager.recordCellChange( + rowID: .existing(7), columnIndex: 1, columnName: "name", + oldValue: "Ann", newValue: "Bea", originalRow: ["7", "Ann"] + ) + manager.recordRowDeletion(rowID: .existing(3), originalRow: ["3", "Cy"]) let index = RowVisualIndex() - let changeManager = AnyChangeManager(DataChangeManager()) - let displayIDs: [RowID] = [.existing(0), .inserted(UUID()), .existing(2)] - index.rebuild(from: changeManager, displayIDs: displayIDs) + index.rebuild(from: AnyChangeManager(manager)) + + #expect(index.visualState(for: .existing(7)).modifiedColumns == [1]) + #expect(!index.visualState(for: .existing(7)).isDeleted) + #expect(index.visualState(for: .existing(3)).isDeleted) + #expect(index.visualState(for: .existing(0)) == .empty) + } + + @Test("Updating one row picks up its latest state and leaves the others alone") + func updateRowRefreshesOneRow() { + let manager = makeManager() + let changeManager = AnyChangeManager(manager) + manager.recordRowDeletion(rowID: .existing(1), originalRow: ["1", "A"]) + let index = RowVisualIndex() + index.rebuild(from: changeManager) + + manager.recordCellChange( + rowID: .existing(2), columnIndex: 1, columnName: "name", + oldValue: "B", newValue: "C", originalRow: ["2", "B"] + ) + index.updateRow(.existing(2), from: changeManager) + + #expect(index.visualState(for: .existing(2)).modifiedColumns == [1]) + #expect(index.visualState(for: .existing(1)).isDeleted) + + manager.undoRowDeletion(rowID: .existing(1)) + index.updateRow(.existing(1), from: changeManager) - #expect(index.visualState(for: 1).isInserted) - #expect(!index.visualState(for: 0).isInserted) - #expect(!index.visualState(for: 2).isInserted) + #expect(index.visualState(for: .existing(1)) == .empty) } - @Test("no inserted rows leaves every display index clean") - func noInsertedRowsLeavesStateEmpty() { + @Test("No changes leaves every row clean") + func noChangesLeavesStateEmpty() { let index = RowVisualIndex() - let changeManager = AnyChangeManager(DataChangeManager()) - let displayIDs: [RowID] = [.existing(0), .existing(1)] - index.rebuild(from: changeManager, displayIDs: displayIDs) + index.rebuild(from: AnyChangeManager(makeManager())) - #expect(index.visualState(for: 0) == .empty) - #expect(index.visualState(for: 1) == .empty) + #expect(index.visualState(for: .existing(0)) == .empty) + #expect(index.visualState(for: .inserted(UUID())) == .empty) } } diff --git a/TableProTests/Views/Results/TableViewCoordinatorRowIdentityTests.swift b/TableProTests/Views/Results/TableViewCoordinatorRowIdentityTests.swift new file mode 100644 index 0000000000..779d4ed2a4 --- /dev/null +++ b/TableProTests/Views/Results/TableViewCoordinatorRowIdentityTests.swift @@ -0,0 +1,177 @@ +// +// TableViewCoordinatorRowIdentityTests.swift +// TableProTests +// + +import AppKit +import SwiftUI +import TableProPluginKit +import Testing + +@testable import TablePro + +@MainActor +private final class NoopRowIdentityLayoutPersister: ColumnLayoutPersisting { + func load(for key: ColumnLayoutTableKey) -> ColumnLayoutState? { nil } + func save(_ layout: ColumnLayoutState, for key: ColumnLayoutTableKey) {} + func clear(for key: ColumnLayoutTableKey) {} +} + +@MainActor +private final class RowStore { + var tableRows: TableRows + + init(_ tableRows: TableRows) { + self.tableRows = tableRows + } +} + +@Suite("TableViewCoordinator row identity") +@MainActor +struct TableViewCoordinatorRowIdentityTests { + private func makeManager() -> DataChangeManager { + let manager = DataChangeManager() + manager.configureForTable( + tableName: "users", + columns: ["id", "status"], + primaryKeyColumns: ["id"], + databaseType: .mysql, + generatedColumns: [] + ) + return manager + } + + private func makeCoordinator(manager: DataChangeManager) -> (TableViewCoordinator, RowStore) { + let coordinator = TableViewCoordinator( + changeManager: AnyChangeManager(manager), + isEditable: true, + selectedRowIndices: .constant([]), + delegate: nil, + layoutPersister: NoopRowIdentityLayoutPersister() + ) + let store = RowStore(TableRows.from( + queryRows: [ + [.text("1"), .text("active")], + [.text("2"), .text("inactive")], + [.text("3"), .text("active")], + [.text("4"), .text("inactive")] + ], + columns: ["id", "status"], + columnTypes: [.text(rawType: nil), .text(rawType: nil)] + )) + coordinator.tableRowsProvider = { store.tableRows } + coordinator.tableRowsMutator = { mutation in mutation(&store.tableRows) } + coordinator.updateCache() + return (coordinator, store) + } + + private func filterToInactive(_ coordinator: TableViewCoordinator) { + coordinator.applyValueFilter( + ColumnValueFilter(selectedValues: ["inactive"], includesNull: false), + columnName: "status", + forColumn: 1 + ) + } + + @Test("An edit under a value filter is recorded on the row shown, and only that row changes") + func editUnderFilterLandsOnTheShownRow() throws { + let manager = makeManager() + let (coordinator, store) = makeCoordinator(manager: manager) + filterToInactive(coordinator) + #expect(coordinator.displayIDs == [.existing(1), .existing(3)]) + + coordinator.recordCellEdit(row: 1, columnIndex: 1, newValue: .text("archived")) + + #expect(manager.isCellModified(rowID: .existing(3), columnIndex: 1)) + #expect(!manager.isCellModified(rowID: .existing(1), columnIndex: 1)) + #expect(store.tableRows.rows[3].values[1] == "archived") + #expect(store.tableRows.rows[1].values[1] == "inactive") + + let statements = try manager.generateSQL() + let parameters = statements.first?.parameters ?? [] + #expect(statements.count == 1) + #expect(parameters.count == 2) + #expect(parameters.last.flatMap { $0 as? String } == "4") + } + + @Test("An edit keeps its row when the filter is cleared and positions move") + func editFollowsItsRowAcrossADisplayOrderChange() { + let manager = makeManager() + let (coordinator, _) = makeCoordinator(manager: manager) + filterToInactive(coordinator) + + coordinator.recordCellEdit(row: 0, columnIndex: 1, newValue: .text("archived")) + coordinator.clearAllValueFilters() + + #expect(coordinator.displayIDs == nil) + #expect(coordinator.visualState(for: 1).modifiedColumns == [1]) + #expect(coordinator.visualState(for: 0).modifiedColumns.isEmpty) + } + + @Test("Undoing an edit made under a value filter reverts the row that was edited") + func undoUnderFilterRevertsTheEditedRow() { + let manager = makeManager() + let undoManager = UndoManager() + undoManager.groupsByEvent = false + manager.undoManagerProvider = { undoManager } + var captured: UndoResult? + manager.onUndoApplied = { captured = $0 } + let (coordinator, store) = makeCoordinator(manager: manager) + filterToInactive(coordinator) + + coordinator.recordCellEdit(row: 1, columnIndex: 0, newValue: .text("9")) + #expect(store.tableRows.rows[3].values[0] == "9") + + undoManager.undo() + guard let captured else { + Issue.record("The undo produced no result") + return + } + _ = RowOperationsManager(changeManager: manager).applyUndoResult(captured, tableRows: &store.tableRows) + + #expect(store.tableRows.rows[3].values[0] == "4") + #expect(store.tableRows.rows[1].values[0] == "2") + #expect(!manager.isCellModified(rowID: .existing(3), columnIndex: 0)) + } + + @Test("A deleted row is recognised at whatever position the filter shows it") + func deletedRowIsFoundByIdentity() { + let manager = makeManager() + let (coordinator, _) = makeCoordinator(manager: manager) + manager.recordRowDeletion(rowID: .existing(3), originalRow: ["4", "inactive"]) + filterToInactive(coordinator) + + #expect(coordinator.isRowDeleted(displayRow: 1)) + #expect(!coordinator.isRowDeleted(displayRow: 0)) + #expect(coordinator.visualState(for: 1).isDeleted) + } + + @Test("Fill Column under a filter writes the shown rows and skips a deleted one") + func fillColumnUnderFilterTargetsShownRows() { + let manager = makeManager() + let (coordinator, _) = makeCoordinator(manager: manager) + filterToInactive(coordinator) + manager.recordRowDeletion(rowID: .existing(3), originalRow: ["4", "inactive"]) + + coordinator.applyFillColumn(columnIndex: 1, value: .text("gone")) + + #expect(manager.isCellModified(rowID: .existing(1), columnIndex: 1)) + #expect(!manager.isCellModified(rowID: .existing(3), columnIndex: 1)) + #expect(!manager.isCellModified(rowID: .existing(0), columnIndex: 1)) + #expect(!manager.isCellModified(rowID: .existing(2), columnIndex: 1)) + } + + @Test("Undo Delete from the row menu clears the row shown at that position") + func undoDeleteUnderFilterClearsTheShownRow() { + let manager = makeManager() + let (coordinator, _) = makeCoordinator(manager: manager) + manager.recordRowDeletion(rowID: .existing(1), originalRow: ["2", "inactive"]) + manager.recordRowDeletion(rowID: .existing(3), originalRow: ["4", "inactive"]) + filterToInactive(coordinator) + + coordinator.undoDeleteRow(at: 1) + + #expect(!manager.isRowDeleted(.existing(3))) + #expect(manager.isRowDeleted(.existing(1))) + } +} diff --git a/TableProTests/Views/Results/ValueFilterChangeGuardTests.swift b/TableProTests/Views/Results/ValueFilterChangeGuardTests.swift index 835ee70ba3..62defb8771 100644 --- a/TableProTests/Views/Results/ValueFilterChangeGuardTests.swift +++ b/TableProTests/Views/Results/ValueFilterChangeGuardTests.swift @@ -2,9 +2,8 @@ // ValueFilterChangeGuardTests.swift // TableProTests // -// A pending cell edit is recorded against a display row, so anything that changes which row a -// position names re-points it. Sort, pagination and the WHERE filter already confirm before doing -// that; the per-column value filter did not. (#2667) +// Sort, pagination and the WHERE filter confirm before changing the display order while edits +// are pending, and the per-column value filter does the same. (#2667) // import AppKit diff --git a/TableProUITests/ValueFilterEditUITests.swift b/TableProUITests/ValueFilterEditUITests.swift new file mode 100644 index 0000000000..70eeabf857 --- /dev/null +++ b/TableProUITests/ValueFilterEditUITests.swift @@ -0,0 +1,155 @@ +// +// ValueFilterEditUITests.swift +// TableProUITests +// + +import AppKit +import XCTest + +final class ValueFilterEditUITests: UITestCase { + private static let table = "Employee" + private static let filteredColumn = "Title" + private static let keptTitle = "IT Staff" + private static let editedColumnPosition = 2 + private static let editedValue = "Edited Under Filter" + + func testDiscardingAnEditMadeUnderAValueFilterRestoresTheEditedRow() throws { + let app = try launchWithSampleDatabase() + let window = app.windows.matching(NSPredicate(format: "identifier != %@", "welcome")).firstMatch + let grid = openTable(in: window) + + let secondRowBefore = try cellValue(row: 2, in: grid) + let lastRowBefore = try cellValue(row: 8, in: grid) + + rightClickHeader(Self.filteredColumn, in: grid) + let filterValues = contextMenuItem("Filter Values…", in: app) + XCTAssertTrue(filterValues.waitToExist(timeout: 10), "The header menu must offer Filter Values…") + filterValues.click() + keepOnly(Self.keptTitle, in: window) + + XCTAssertTrue( + waitForPredicate(timeout: 20) { self.currentCellValue(row: 2, in: grid) == lastRowBefore }, + "Under the filter the table's last row must be shown second" + ) + + editCell(row: 2, in: grid, app: app, to: Self.editedValue) + XCTAssertTrue( + waitForPredicate(timeout: 10) { self.currentCellValue(row: 2, in: grid) == Self.editedValue }, + "The edit must land on the row shown second" + ) + + rightClickHeader(Self.filteredColumn, in: grid) + let clearFilter = contextMenuItem("Clear Value Filter", in: app) + XCTAssertTrue(clearFilter.waitToExist(timeout: 10), "A filtered column's menu must offer Clear Value Filter") + clearFilter.click() + + guard let discard = discardButton(in: app, of: window) else { + XCTFail("Clearing the filter over a pending edit must ask first") + return + } + discard.click() + + XCTAssertTrue( + waitForPredicate(timeout: 20) { self.currentCellValue(row: 8, in: grid) == lastRowBefore }, + "Discard must put back the value of the row that was edited" + ) + XCTAssertEqual( + currentCellValue(row: 2, in: grid), + secondRowBefore, + "Discard must not write the edited row's value into the row that shared its position" + ) + } + + // MARK: - Helpers + + private func openTable(in window: XCUIElement) -> XCUIElement { + XCTAssertTrue(window.waitToExist(timeout: 60), "The sample database produced no window") + let row = objectBrowserRow(Self.table, in: window) + XCTAssertTrue(row.waitToExist(timeout: 30), "The object browser must list \(Self.table)") + row.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).doubleClick() + + let grid = window.tables.matching(identifier: "data-grid").firstMatch + XCTAssertTrue(waitForClickableRows(in: grid, timeout: 30), "\(Self.table) must load its rows") + return grid + } + + private func rightClickHeader(_ column: String, in grid: XCUIElement) { + let header = grid.buttons + .matching(NSPredicate(format: "label BEGINSWITH %@", "Column: \(column)")) + .firstMatch + XCTAssertTrue(header.waitToExist(timeout: 30), "The grid must publish a \(column) header") + point(at: header.frame, in: grid).rightClick() + } + + private func keepOnly(_ value: String, in window: XCUIElement) { + let popover = window.popovers.firstMatch + let search = popover.searchFields["value-filter-search"].firstMatch + XCTAssertTrue(search.waitToExist(timeout: 10), "Filter Values… must open the value filter") + search.typeText(value) + + let selectAll = popover.checkBoxes.matching(NSPredicate(format: "label == %@", "Select All")).firstMatch + XCTAssertTrue(waitUntilHittable(selectAll, timeout: 10), "The value filter must offer Select All") + selectAll.click() + + let valueToggle = popover.checkBoxes.matching(identifier: "value-filter-value").firstMatch + XCTAssertTrue(waitUntilHittable(valueToggle, timeout: 10), "The search must leave \(value) in the list") + valueToggle.click() + + let apply = popover.buttons["Apply"].firstMatch + XCTAssertTrue(waitUntilHittable(apply, timeout: 10), "The value filter must offer Apply") + apply.click() + XCTAssertTrue(popover.waitForNonExistence(timeout: 10), "Apply must close the value filter") + } + + /// Asked of the sheet and then of the app's own windows, never of `app.buttons`: the runner + /// publishes the Touch Bar's copy of a button under the application element, and XCUITest + /// refuses to click that one. + private func discardButton(in app: XCUIApplication, of window: XCUIElement) -> XCUIElement? { + let queries = [ + window.sheets.buttons["Discard"], + app.dialogs.buttons["Discard"], + app.windows.buttons["Discard"] + ] + for query in queries { + let button = query.firstMatch + if waitUntilHittable(button, timeout: 5) { return button } + } + return nil + } + + private func editCell(row: Int, in grid: XCUIElement, app: XCUIApplication, to value: String) { + let cell = cellElement(row: row, in: grid) + XCTAssertTrue(cell.waitToExist(timeout: 10), "Row \(row) must publish its cells") + point(at: cell.frame, in: grid).click() + app.typeKey(XCUIKeyboardKey.return.rawValue, modifierFlags: []) + app.typeKey("a", modifierFlags: .command) + app.typeText(value) + app.typeKey(XCUIKeyboardKey.return.rawValue, modifierFlags: []) + } + + private func point(at frame: CGRect, in grid: XCUIElement) -> XCUICoordinate { + let origin = grid.frame.origin + return grid.coordinate(withNormalizedOffset: .zero) + .withOffset(CGVector(dx: frame.midX - origin.x, dy: frame.midY - origin.y)) + } + + private func cellElement(row: Int, in grid: XCUIElement) -> XCUIElement { + grid.staticTexts + .matching(NSPredicate( + format: "label BEGINSWITH %@", + "Row \(row), column \(Self.editedColumnPosition): " + )) + .firstMatch + } + + private func currentCellValue(row: Int, in grid: XCUIElement) -> String? { + let cell = cellElement(row: row, in: grid) + guard cell.exists else { return nil } + return cell.value as? String + } + + private func cellValue(row: Int, in grid: XCUIElement) throws -> String { + _ = waitForPredicate(timeout: 20) { self.currentCellValue(row: row, in: grid) != nil } + return try XCTUnwrap(currentCellValue(row: row, in: grid), "The grid must publish row \(row)'s cells") + } +} From 2c62b1577892c4bb75a99978ec43a807bbe1b26b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 08:02:49 +0700 Subject: [PATCH 25/54] feat(datagrid): mark a pending change on the value, not only behind it (#2766) --- CHANGELOG.md | 1 + .../Cells/DataGridCellAccessibilityView.swift | 34 ++- .../Cells/DataGridCellAppearance.swift | 4 + .../Results/Cells/DataGridCellRenderer.swift | 21 +- .../Results/Cells/DataGridCellTextMark.swift | 55 ++++ .../DataGridView+RowDecoration.swift | 4 + .../DataGridPendingChangeMarkTests.swift | 241 ++++++++++++++++++ docs/features/change-tracking.mdx | 2 + 8 files changed, 342 insertions(+), 20 deletions(-) create mode 100644 TablePro/Views/Results/Cells/DataGridCellTextMark.swift create mode 100644 TableProTests/Views/Results/DataGridPendingChangeMarkTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 364e0d84c1..f611d7811a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Strikethrough on a row queued for deletion, and an underline on a new row or an edited value. - Google Cloud Spanner as a registry plugin over the REST API. (#1226, #2480) - TiDB and Databend connection types on the MySQL driver. (#1066, #2514) - Empty state in the inspector and the assistant for a connection that is not up. diff --git a/TablePro/Views/Results/Cells/DataGridCellAccessibilityView.swift b/TablePro/Views/Results/Cells/DataGridCellAccessibilityView.swift index 1d5ba6d736..b8c2bed0e1 100644 --- a/TablePro/Views/Results/Cells/DataGridCellAccessibilityView.swift +++ b/TablePro/Views/Results/Cells/DataGridCellAccessibilityView.swift @@ -87,22 +87,32 @@ internal final class DataGridCellAccessibilityView: NSView { override internal func accessibilityValue() -> Any? { text } + /// Every combination is its own format string rather than pieces joined at run time, so a + /// translator sees a whole sentence and can order its parts. The pending change comes before the + /// highlight rule, because it is the one the reader is about to save. override internal func accessibilityLabel() -> String? { - guard let highlight = coordinator?.highlightDescription(row: row, columnIndex: dataColumn) else { + let pendingChange = coordinator?.pendingChangeDescription(row: row, columnIndex: dataColumn) + let highlight = coordinator?.highlightDescription(row: row, columnIndex: dataColumn) + + if let pendingChange, let highlight { + return String( + format: String(localized: "Row %d, column %d: %@, %@, highlighted where %@"), + row + 1, dataColumn + 1, text, pendingChange, highlight + ) + } + if let pendingChange { + return String( + format: String(localized: "Row %d, column %d: %@, %@"), + row + 1, dataColumn + 1, text, pendingChange + ) + } + if let highlight { return String( - format: String(localized: "Row %d, column %d: %@"), - row + 1, - dataColumn + 1, - text + format: String(localized: "Row %d, column %d: %@, highlighted where %@"), + row + 1, dataColumn + 1, text, highlight ) } - return String( - format: String(localized: "Row %d, column %d: %@, highlighted where %@"), - row + 1, - dataColumn + 1, - text, - highlight - ) + return String(format: String(localized: "Row %d, column %d: %@"), row + 1, dataColumn + 1, text) } /// Read through rather than stored, so an edit, an undo or a display-format change is spoken diff --git a/TablePro/Views/Results/Cells/DataGridCellAppearance.swift b/TablePro/Views/Results/Cells/DataGridCellAppearance.swift index d140ec35f0..2e8fd93207 100644 --- a/TablePro/Views/Results/Cells/DataGridCellAppearance.swift +++ b/TablePro/Views/Results/Cells/DataGridCellAppearance.swift @@ -17,6 +17,9 @@ struct DataGridCellAppearance: Equatable { let textColor: NSColor /// Painted behind the text, for a find match, a modified value or a highlight rule. let backgroundTint: NSColor? + /// The line a pending change draws through or under the text. Unlike the tint, it survives a + /// selection, which is what makes it the cue rather than a decoration on one. + let textMark: DataGridCellTextMark? let accessory: DataGridCellAccessory /// Which symbol the accessory draws, resolved here because it follows the row's state rather /// than anything the renderer can see. @@ -94,6 +97,7 @@ struct DataGridCellAppearance: Equatable { font: font, textColor: textColor, backgroundTint: backgroundTint, + textMark: DataGridCellTextMark.resolve(state: state.visualState, columnIndex: state.columnIndex), accessory: accessory, accessoryRole: DataGridCellAccessoryGlyph.Role( accessory: accessory, diff --git a/TablePro/Views/Results/Cells/DataGridCellRenderer.swift b/TablePro/Views/Results/Cells/DataGridCellRenderer.swift index d17d8f47f4..fa3a071897 100644 --- a/TablePro/Views/Results/Cells/DataGridCellRenderer.swift +++ b/TablePro/Views/Results/Cells/DataGridCellRenderer.swift @@ -20,6 +20,7 @@ final class DataGridCellRenderer { let text: String let font: NSFont let color: NSColor + let mark: DataGridCellTextMark? } /// A viewport holds a few hundred cells and a scroll reuses them, so this only has to outlive a @@ -64,9 +65,9 @@ final class DataGridCellRenderer { let availableWidth = appearance.accessory.availableTextWidth(in: rect) guard availableWidth > 0, let context = NSGraphicsContext.current?.cgContext else { return } - let fullLine = line(for: appearance.text, font: appearance.font, color: appearance.textColor) + let fullLine = line(for: appearance.text, appearance: appearance) let typographicWidth = CTLineGetTypographicBounds(fullLine, nil, nil, nil) - let ellipsis = line(for: "\u{2026}", font: appearance.font, color: appearance.textColor) + let ellipsis = line(for: "\u{2026}", appearance: appearance) let ellipsisWidth = CTLineGetTypographicBounds(ellipsis, nil, nil, nil) guard Double(availableWidth) >= ellipsisWidth else { return } @@ -87,18 +88,22 @@ final class DataGridCellRenderer { context.restoreGState() } - private func line(for text: String, font: NSFont, color: NSColor) -> CTLine { - let key = LineKey(text: text, font: font, color: color) + /// Built with the mark's own attribute so `CTLineDraw` draws the line from the font's metrics, + /// and so `CTLineCreateTruncatedLine` carries it onto a truncated line and its ellipsis. The + /// mark is part of the key because two cells holding the same value in the same font and colour + /// are two different drawings once one of them is struck through. + private func line(for text: String, appearance: DataGridCellAppearance) -> CTLine { + let font = appearance.font + let key = LineKey(text: text, font: font, color: appearance.textColor, mark: appearance.textMark) if let cached = lineCache[key] { return cached } let source = text as NSString let laidOut = source.length > Self.maximumLaidOutCharacters ? source.substring(to: Self.maximumLaidOutCharacters) + "\u{2026}" : text - let attributed = NSAttributedString( - string: laidOut, - attributes: [.font: font, .foregroundColor: color] - ) + var attributes: [NSAttributedString.Key: Any] = [.font: font, .foregroundColor: appearance.textColor] + appearance.textMark?.attributes.forEach { attributes[$0.key] = $0.value } + let attributed = NSAttributedString(string: laidOut, attributes: attributes) let created = CTLineCreateWithAttributedString(attributed as CFAttributedString) if lineCache.count >= Self.lineCacheLimit { diff --git a/TablePro/Views/Results/Cells/DataGridCellTextMark.swift b/TablePro/Views/Results/Cells/DataGridCellTextMark.swift new file mode 100644 index 0000000000..9a4502b17a --- /dev/null +++ b/TablePro/Views/Results/Cells/DataGridCellTextMark.swift @@ -0,0 +1,55 @@ +// +// DataGridCellTextMark.swift +// TablePro +// + +import AppKit + +/// The line a pending change draws through or under a cell's own text, the way Pages marks tracked +/// changes. +/// +/// The tints alone could not carry this. A selected row paints over them, so a reader who selects +/// the rows they are about to save loses every mark at once, and a tint says nothing to a reader +/// who cannot see colour or is using a client that reads the grid rather than looking at it. The +/// line is drawn in the text's own colour, so it survives selection, Dark Mode, grayscale and +/// Increase Contrast, and the tints stay as the second cue. +enum DataGridCellTextMark: Equatable { + /// A row staged for deletion, struck through as Pages strikes deleted text. + case struckThrough + /// A new row, or an edited cell, underlined as Pages underlines inserted text. + case underlined + + /// What a pending change makes of a cell, or nil when nothing is staged for it. + /// + /// A staged delete outranks the rest: the row is going away whatever was typed into it first. + static func resolve(state: RowVisualState, columnIndex: Int) -> DataGridCellTextMark? { + if state.isDeleted { return .struckThrough } + if state.isInserted { return .underlined } + return state.isModified(columnIndex: columnIndex) ? .underlined : nil + } + + /// Read by `CTLineDraw` itself, which draws both lines from the font's own metrics. Measured on + /// macOS 27: a `CTLine` built from an attributed string carrying `.underlineStyle` or + /// `.strikethroughStyle` draws that line, in the run's foreground colour, and + /// `CTLineCreateTruncatedLine` carries it onto the truncated line. So the renderer never + /// computes a line's position, thickness or width, and a cell that truncates is marked to + /// exactly where its text ends. + var attributes: [NSAttributedString.Key: Any] { + switch self { + case .struckThrough: + return [.strikethroughStyle: NSUnderlineStyle.single.rawValue] + case .underlined: + return [.underlineStyle: NSUnderlineStyle.single.rawValue] + } + } + + /// What a client reading the grid is told, since a line it cannot see is no cue at all. + /// + /// Resolved from the state rather than from the mark, because one line covers two changes a + /// reader needs told apart: a whole row that is new, and one edited value in a row that is not. + static func accessibilityDescription(state: RowVisualState, columnIndex: Int) -> String? { + if state.isDeleted { return String(localized: "marked for deletion") } + if state.isInserted { return String(localized: "new row") } + return state.isModified(columnIndex: columnIndex) ? String(localized: "edited") : nil + } +} diff --git a/TablePro/Views/Results/Extensions/DataGridView+RowDecoration.swift b/TablePro/Views/Results/Extensions/DataGridView+RowDecoration.swift index 138f2b52ed..5f3e5a6fab 100644 --- a/TablePro/Views/Results/Extensions/DataGridView+RowDecoration.swift +++ b/TablePro/Views/Results/Extensions/DataGridView+RowDecoration.swift @@ -45,6 +45,10 @@ extension TableViewCoordinator { return resolved } + func pendingChangeDescription(row: Int, columnIndex: Int) -> String? { + DataGridCellTextMark.accessibilityDescription(state: visualState(for: row), columnIndex: columnIndex) + } + func highlightDescription(row: Int, columnIndex: Int) -> String? { guard let rule = visualState(for: row).drawnHighlightRule(forColumn: columnIndex) else { return nil } return HighlightRuleDescription.condition(of: rule, valueLimit: HighlightRuleDescription.menuValueLimit) diff --git a/TableProTests/Views/Results/DataGridPendingChangeMarkTests.swift b/TableProTests/Views/Results/DataGridPendingChangeMarkTests.swift new file mode 100644 index 0000000000..9e3961df6e --- /dev/null +++ b/TableProTests/Views/Results/DataGridPendingChangeMarkTests.swift @@ -0,0 +1,241 @@ +// +// DataGridPendingChangeMarkTests.swift +// TableProTests +// +// A pending change used to show as a tint and nothing else, so selecting the rows about to be +// saved hid every mark at once and a client reading the grid was told nothing at all. These cover +// the line the cell draws instead, which selection cannot paint over. +// + +import AppKit +import CoreText +import Testing + +@testable import TablePro + +@Suite("Pending change marks") +@MainActor +struct DataGridPendingChangeMarkTests { + private let palette = DataGridCellPalette( + regularFont: .monospacedSystemFont(ofSize: 13, weight: .regular), + italicFont: .monospacedSystemFont(ofSize: 13, weight: .regular), + mediumFont: .monospacedSystemFont(ofSize: 13, weight: .medium), + text: .labelColor, + placeholderText: .secondaryLabelColor, + booleanTrueText: nil, + booleanFalseText: nil, + rowNumberText: .secondaryLabelColor, + deletedRowText: .systemRed, + modifiedColumnTint: .systemYellow, + findMatchTint: .systemOrange + ) + + private static let deleted = RowVisualState(isDeleted: true, isInserted: false, modifiedColumns: []) + private static let inserted = RowVisualState(isDeleted: false, isInserted: true, modifiedColumns: []) + private static let modified = RowVisualState(isDeleted: false, isInserted: false, modifiedColumns: [1]) + + private func resolve( + text: String = "value", + visualState: RowVisualState = .empty, + columnIndex: Int = 0, + isCurrentFindMatch: Bool = false, + onEmphasizedSelection: Bool = false + ) -> DataGridCellAppearance { + DataGridCellAppearance.resolve( + kind: .text, + content: DataGridCellContent(displayText: text, rawValue: text, placeholder: nil), + state: DataGridCellState( + visualState: visualState, + isFocused: false, + isEditable: true, + isLargeDataset: false, + isCurrentFindMatch: isCurrentFindMatch, + row: 0, + columnIndex: columnIndex + ), + palette: palette, + nullDisplayString: "NULL", + onEmphasizedSelection: onEmphasizedSelection, + hasOverlay: false + ) + } + + // MARK: - Which mark a state carries + + @Test("A row staged for deletion is struck through, a new row underlined") + func rowMarks() { + #expect(resolve(visualState: Self.deleted).textMark == .struckThrough) + #expect(resolve(visualState: Self.inserted).textMark == .underlined) + #expect(resolve().textMark == nil) + } + + @Test("Only the edited cell of an edited row is underlined") + func modifiedColumnOnly() { + #expect(resolve(visualState: Self.modified, columnIndex: 1).textMark == .underlined) + #expect(resolve(visualState: Self.modified, columnIndex: 0).textMark == nil) + } + + /// The row is going away whatever was typed into it first, so one line wins rather than two + /// crossing each other. + @Test("A deleted row that was edited first keeps the strike alone") + func deleteOutranksTheEdit() { + let state = RowVisualState(isDeleted: true, isInserted: false, modifiedColumns: [1]) + + #expect(resolve(visualState: state, columnIndex: 1).textMark == .struckThrough) + } + + /// The whole point: the tint stands down under a selection and the find highlight, and the mark + /// does not. + @Test("The mark survives a selection and a find match, where the tint does not") + func markSurvivesWhatHidesTheTint() { + let selected = resolve(visualState: Self.modified, columnIndex: 1, onEmphasizedSelection: true) + let found = resolve(visualState: Self.modified, columnIndex: 1, isCurrentFindMatch: true) + let deletedAndSelected = resolve(visualState: Self.deleted, onEmphasizedSelection: true) + + #expect(selected.backgroundTint == nil) + #expect(selected.textMark == .underlined) + #expect(found.backgroundTint == palette.findMatchTint) + #expect(found.textMark == .underlined) + #expect(deletedAndSelected.textMark == .struckThrough) + } + + // MARK: - What a client is told + + @Test("A pending change names itself, and distinguishes a new row from an edited value") + func accessibilityDescriptions() { + #expect(DataGridCellTextMark.accessibilityDescription(state: Self.deleted, columnIndex: 0) != nil) + #expect( + DataGridCellTextMark.accessibilityDescription(state: Self.inserted, columnIndex: 0) + != DataGridCellTextMark.accessibilityDescription(state: Self.modified, columnIndex: 1) + ) + #expect(DataGridCellTextMark.accessibilityDescription(state: Self.modified, columnIndex: 0) == nil) + #expect(DataGridCellTextMark.accessibilityDescription(state: .empty, columnIndex: 0) == nil) + } + + // MARK: - What is actually drawn + + /// `CTLineDraw` draws both lines itself from the font's metrics, so these rasterise a cell and + /// read the pixels rather than trusting the attribute to have any effect. + /// + /// Drawn over mid grey, not white: a selected cell's text is + /// `alternateSelectedControlTextColor`, which is white, and a white-on-white cell rasterises + /// blank whatever it drew. Ink is any pixel that differs from the ground. + private func inkedColumns(of appearance: DataGridCellAppearance, in rect: NSRect) throws -> [[Int]] { + let host = CellHost(frame: rect) + host.cellAppearance = appearance + let rep = try #require(host.bitmapImageRepForCachingDisplay(in: host.bounds)) + NSAppearance(named: .aqua)?.performAsCurrentDrawingAppearance { + host.cacheDisplay(in: host.bounds, to: rep) + } + + let scale = rep.pixelsWide / Int(rect.width) + return (0 ..< rep.pixelsHigh).map { y in + (0 ..< rep.pixelsWide).filter { x in + guard let pixel = rep.colorAt(x: x, y: y)?.usingColorSpace(.sRGB) else { return false } + return abs(pixel.redComponent - 0.5) > 0.1 + || abs(pixel.greenComponent - 0.5) > 0.1 + || abs(pixel.blueComponent - 0.5) > 0.1 + }.map { $0 / max(scale, 1) } + } + } + + /// Flipped, because the grid's own cell surface is and the renderer positions its baseline from + /// the top edge. Rasterising into an unflipped context draws the cell upside down, which is how + /// a first pass at these tests came to read the underline as sitting above the strike. + /// + /// Mid grey, not white: a selected cell's text is `alternateSelectedControlTextColor`, which is + /// white, and a white-on-white cell rasterises blank whatever it drew. + private final class CellHost: NSView { + var cellAppearance: DataGridCellAppearance? + + override var isFlipped: Bool { true } + + static let ground = NSColor(calibratedWhite: 0.5, alpha: 1) + + override func draw(_ dirtyRect: NSRect) { + Self.ground.setFill() + bounds.fill() + guard let cellAppearance else { return } + MainActor.assumeIsolated { DataGridCellRenderer().draw(cellAppearance, in: bounds) } + } + } + + private static let cell = NSRect(x: 0, y: 0, width: 160, height: 24) + + /// Where the mark landed: the row whose ink the mark adds over the same cell drawn unmarked, how + /// much it added, and how far right its own ink reaches. A glyph row gains nothing, so the + /// largest gain is the rule itself. The gain undercounts the rule's length wherever it crosses a + /// glyph the plain cell already inked, which is why reach is measured separately. + private func markedRow( + _ marked: DataGridCellAppearance, + against plain: DataGridCellAppearance, + in rect: NSRect = DataGridPendingChangeMarkTests.cell + ) throws -> (row: Int, gain: Int, reach: Int) { + let markedRows = try inkedColumns(of: marked, in: rect) + let plainRows = try inkedColumns(of: plain, in: rect) + let gains = zip(markedRows, plainRows).map { $0.count - $1.count } + let row = try #require(gains.indices.max(by: { gains[$0] < gains[$1] })) + return (row, gains[row], markedRows[row].max() ?? 0) + } + + @Test("A struck-through cell draws a rule its plain twin does not, selected or not") + func strikeIsDrawn() throws { + let text = "0123456789" + let textWidth = Int(text.size(withAttributes: [.font: palette.regularFont]).width) + + let struck = try markedRow(resolve(text: text, visualState: Self.deleted), against: resolve(text: text)) + let selected = try markedRow( + resolve(text: text, visualState: Self.deleted, onEmphasizedSelection: true), + against: resolve(text: text, onEmphasizedSelection: true) + ) + + #expect(struck.gain > textWidth / 2) + #expect(selected.gain > textWidth / 2) + } + + /// The two lines have to land in different places, or they are the same cue twice. + @Test("The underline sits below the strike") + func underlineSitsBelowTheStrike() throws { + let text = "0123456789" + let plain = resolve(text: text) + let struck = try markedRow(resolve(text: text, visualState: Self.deleted), against: plain) + let underlined = try markedRow(resolve(text: text, visualState: Self.inserted), against: plain) + + #expect(underlined.row > struck.row) + } + + /// A cell too narrow for its value truncates, and the mark has to stop where the text does + /// rather than run on across the rest of the cell. + @Test("The mark reaches as far as the text and no further, truncated or not") + func markStopsWithTheText() throws { + let short = "0123" + let inset = DataGridMetrics.cellHorizontalInset + let textEnd = inset + short.size(withAttributes: [.font: palette.regularFont]).width + let roomy = NSRect(x: 0, y: 0, width: 300, height: 24) + let shortMark = try markedRow( + resolve(text: short, visualState: Self.deleted), + against: resolve(text: short), + in: roomy + ) + + #expect(CGFloat(shortMark.reach) <= textEnd + 2) + #expect(CGFloat(shortMark.reach) > textEnd - 4) + + let long = String(repeating: "0123456789", count: 8) + let narrow = NSRect(x: 0, y: 0, width: 120, height: 24) + let truncatedMark = try markedRow( + resolve(text: long, visualState: Self.deleted), + against: resolve(text: long), + in: narrow + ) + + #expect(CGFloat(truncatedMark.reach) <= narrow.width) + #expect(truncatedMark.reach > shortMark.reach) + + /// Reach alone cannot see this: the glyphs of a truncated value already run to the cell's + /// edge, so a line that lost its mark reaches just as far. Only the gain separates them, + /// measured at 158 with the rule against 67 without it, beside the short cell's 50. So the + /// rule carried onto the truncated line is asserted where a regression would actually show. + #expect(truncatedMark.gain > shortMark.gain * 2) + } +} diff --git a/docs/features/change-tracking.mdx b/docs/features/change-tracking.mdx index 3dcc3b07d0..3efb7c2ec0 100644 --- a/docs/features/change-tracking.mdx +++ b/docs/features/change-tracking.mdx @@ -9,6 +9,8 @@ import StagedUntilSave from "/snippets/staged-until-save.mdx"; Modified cells stay highlighted, `Cmd+Shift+P` shows the statements the queue will produce, and `Cmd+S` runs them. The queue belongs to the tab, so switching tabs leaves it alone. +A queued change also marks the value itself, so it stays legible once the row is selected and reads aloud to VoiceOver. An edited value and a new row are underlined, and a row queued for deletion is struck through. + Pending edits, inserts, and deletions highlighted in the data grid Pending edits, inserts, and deletions highlighted in the data grid From b5d7bdb5dbf4efb89080e8e4a8154c7bec53cbbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 08:03:13 +0700 Subject: [PATCH 26/54] test(storage): stop the preference key guard flagging dictionary and layer keys (#2770) --- .../Storage/PreferenceKeysGuardTests.swift | 59 ++++++++++++++++--- 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/TableProTests/Core/Storage/PreferenceKeysGuardTests.swift b/TableProTests/Core/Storage/PreferenceKeysGuardTests.swift index 08ff42797c..a4a0232bf2 100644 --- a/TableProTests/Core/Storage/PreferenceKeysGuardTests.swift +++ b/TableProTests/Core/Storage/PreferenceKeysGuardTests.swift @@ -20,7 +20,7 @@ struct PreferenceKeysGuardTests { @Test("No off-namespace forKey: literals outside the frozen baseline") func noNewRawForKeyLiterals() throws { - let offenders = try Self.scan(pattern: #"forKey:\s*"([^"\\]+)""#) + let offenders = try Self.scan(pattern: #"forKey:\s*"([^"\\]+)""#, ignoringCalls: Self.nonPreferenceCalls) .filter { !$0.hasPrefix("com.TablePro") && Self.grandfatheredForKey[$0] == nil } #expect(offenders.isEmpty, "Route new UserDefaults keys through PreferenceKeys: \(offenders.sorted())") } @@ -32,12 +32,19 @@ struct PreferenceKeysGuardTests { #expect(offenders.isEmpty, "Route new @AppStorage keys through the preferences layer: \(offenders.sorted())") } + /// `forKey:` is not UserDefaults' label alone: `Dictionary.removeValue(forKey:)` and + /// `CALayer.add(_:forKey:)` spell it the same way, and a text scan cannot tell them apart. The + /// baseline grew one entry per dictionary key instead, three of its five, and the fourth arrived + /// as `removeValue(forKey: "LC_ALL")` in the dump environment (#2747), which failed this suite on + /// main for a value no preference has ever read. Naming the calls that are not preferences keeps + /// the baseline for the keys that genuinely are. + private static let nonPreferenceCalls: Set = [ + "removeValue", "updateValue", "add", "animation", "removeAnimation", + ] + private static let grandfatheredForKey: [String: String] = [ "AppleLanguages": "Apple system default written when switching app language", "NSTableViewDefaultSizeMode": "Apple system default read by the workspace rail for Sidebar icon size, never written", - "blink": "CALayer animation key in VimCursorManager, not a preference", - "extensions": "MCP capabilities field stripped by BridgeProxy for legacy clients, not a preference", - "preConnectScript": "additionalFields dictionary key in ConnectionFormCoordinator, not a preference", ] private static let grandfatheredAppStorage: [String: String] = [ @@ -46,7 +53,7 @@ struct PreferenceKeysGuardTests { "structureCodeFontSize": "legacy structure font size, migrates to PreferenceKeys in a later phase", ] - private static func scan(pattern: String) throws -> Set { + private static func scan(pattern: String, ignoringCalls ignored: Set = []) throws -> Set { let sourceRoot = try repoRoot().appendingPathComponent("TablePro") let regex = try NSRegularExpression(pattern: pattern) guard let enumerator = FileManager.default.enumerator( @@ -59,14 +66,50 @@ struct PreferenceKeysGuardTests { let text = try String(contentsOf: url, encoding: .utf8) let range = NSRange(text.startIndex..., in: text) for match in regex.matches(in: text, range: range) where match.numberOfRanges > 1 { - if let captured = Range(match.range(at: 1), in: text) { - matches.insert(String(text[captured])) - } + guard let captured = Range(match.range(at: 1), in: text), + let start = Range(match.range, in: text)?.lowerBound + else { continue } + if let call = enclosingCall(in: text, at: start), ignored.contains(call) { continue } + matches.insert(String(text[captured])) } } return matches } + /// The function whose argument list the match sits in, found by walking back to the innermost + /// unmatched `(`. Nested parentheses in an earlier argument are skipped, so + /// `layer.add(makeBlinkAnimation(), forKey: "blink")` reports `add` rather than + /// `makeBlinkAnimation`. + private static func enclosingCall(in text: String, at index: String.Index) -> String? { + var depth = 0 + var cursor = index + while cursor > text.startIndex { + cursor = text.index(before: cursor) + let character = text[cursor] + if character == ")" { + depth += 1 + } else if character == "(" { + if depth == 0 { return identifier(in: text, endingBefore: cursor) } + depth -= 1 + } else if character == "\n", depth == 0 { + continue + } + } + return nil + } + + private static func identifier(in text: String, endingBefore index: String.Index) -> String? { + var end = index + while end > text.startIndex { + let previous = text.index(before: end) + let character = text[previous] + guard character.isLetter || character.isNumber || character == "_" else { break } + end = previous + } + guard end < index else { return nil } + return String(text[end ..< index]) + } + private static func repoRoot() throws -> URL { var directory = URL(fileURLWithPath: #filePath).deletingLastPathComponent() for _ in 0 ..< 12 { From 4d8daca721e2d2f1f6cffee1193cc3de29763be8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 08:03:26 +0700 Subject: [PATCH 27/54] fix(plugin-mssql): write every SQL Server string literal the app builds as N'...' (#2767) --- CHANGELOG.md | 1 + TablePro/Core/Compare/CompareSQLLiteral.swift | 10 ++++++- .../Database/ForeignKeyPreviewQuery.swift | 4 ++- .../Services/Query/ForeignKeyRowFetcher.swift | 1 + .../Utilities/SQL/InClauseConverter.swift | 7 ++++- .../SQL/SQLRowToStatementConverter.swift | 2 +- .../Results/DataGridView+RowActions.swift | 3 +- .../Extensions/DataGridView+Click.swift | 2 ++ .../FieldEditors/ValuePickerFieldView.swift | 12 ++++++++ .../Structure/CustomValueContentView.swift | 15 ++++++++-- .../Core/Compare/CompareSQLLiteralTests.swift | 15 ++++++++++ .../ForeignKeyPreviewQueryTests.swift | 17 +++++++++++ .../Utilities/InClauseConverterTests.swift | 29 +++++++++++++++++-- .../SQLRowToStatementConverterTests.swift | 17 +++++++++-- 14 files changed, 123 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f611d7811a..e4a9877b8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -177,6 +177,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Non-ASCII SQL Server filter values turned into `?` and matching the wrong rows on non-Unicode collations. - Empty structure, missing indexes and failed renames for non-ASCII SQL Server object names on non-Unicode collations. - Changing a defaulted SQL Server column failing when a name contains a quote or non-ASCII text. +- Non-ASCII text turned into `?` by Copy as INSERT, Copy as IN, Preview Referenced Row, compare scripts and column defaults on SQL Server. ### Security diff --git a/TablePro/Core/Compare/CompareSQLLiteral.swift b/TablePro/Core/Compare/CompareSQLLiteral.swift index 5d5118e68c..e4a27a7ea7 100644 --- a/TablePro/Core/Compare/CompareSQLLiteral.swift +++ b/TablePro/Core/Compare/CompareSQLLiteral.swift @@ -22,12 +22,20 @@ internal enum CompareSQLLiteral { driver: any PluginDatabaseDriver ) -> String { guard case .bytes(let data) = value else { - return driver.sqlLiteral(for: value) + return prefixed(driver.sqlLiteral(for: value), databaseType: databaseType) } return binaryLiteral(for: data, databaseType: databaseType) ?? driver.sqlLiteral(for: value) } + /// The prefix belongs to a quoted literal and to nothing else. `sqlLiteral(for:)` answers + /// `NULL` for a null and passes a number through unquoted, and `N` in front of either is a + /// syntax error, so the opening quote is what decides. + internal static func prefixed(_ literal: String, databaseType: DatabaseType) -> String { + guard literal.hasPrefix("'") else { return literal } + return SQLStringLiteralPrefix.forDatabaseType(databaseType) + literal + } + internal static func binaryLiteral(for data: Data, databaseType: DatabaseType) -> String? { let hex = data.map { String(format: "%02X", $0) }.joined() switch binaryStyle(for: databaseType) { diff --git a/TablePro/Core/Database/ForeignKeyPreviewQuery.swift b/TablePro/Core/Database/ForeignKeyPreviewQuery.swift index 9f2af3f015..c94fc7b8e1 100644 --- a/TablePro/Core/Database/ForeignKeyPreviewQuery.swift +++ b/TablePro/Core/Database/ForeignKeyPreviewQuery.swift @@ -17,9 +17,11 @@ enum ForeignKeyPreviewQuery { quotedTable: String, quotedColumn: String, escapedValue: String, + stringLiteralPrefix: String, dialect: SQLDialectDescriptor? ) -> String { - "SELECT * FROM \(quotedTable) WHERE \(quotedColumn) = '\(escapedValue)' \(limitClause(dialect: dialect))" + let literal = "\(stringLiteralPrefix)'\(escapedValue)'" + return "SELECT * FROM \(quotedTable) WHERE \(quotedColumn) = \(literal) \(limitClause(dialect: dialect))" } /// OFFSET/FETCH is part of ORDER BY in T-SQL and Oracle, so the dialect's filler clause travels diff --git a/TablePro/Core/Services/Query/ForeignKeyRowFetcher.swift b/TablePro/Core/Services/Query/ForeignKeyRowFetcher.swift index cb9fb53a4f..1f799d133c 100644 --- a/TablePro/Core/Services/Query/ForeignKeyRowFetcher.swift +++ b/TablePro/Core/Services/Query/ForeignKeyRowFetcher.swift @@ -52,6 +52,7 @@ enum ForeignKeyRowFetcher { quotedTable: quotedTable, quotedColumn: driver.quoteIdentifier(reference.referencedColumn), escapedValue: driver.escapeStringLiteral(value), + stringLiteralPrefix: SQLStringLiteralPrefix.forDatabaseType(databaseType), dialect: PluginManager.shared.sqlDialect(for: databaseType) ) diff --git a/TablePro/Core/Utilities/SQL/InClauseConverter.swift b/TablePro/Core/Utilities/SQL/InClauseConverter.swift index 5967b86eb5..771d1d213b 100644 --- a/TablePro/Core/Utilities/SQL/InClauseConverter.swift +++ b/TablePro/Core/Utilities/SQL/InClauseConverter.swift @@ -11,6 +11,11 @@ internal struct InClauseConverter { internal let columnTypes: [ColumnType] internal let escapeStringLiteral: ((String) -> String)? + /// What the engine puts in front of a string literal. SQL Server's `N` is the only one, and + /// without it an `IN` list pasted into a query on a non-Unicode collation matches the rows + /// whose text was already damaged rather than the rows the user copied. + internal var stringLiteralPrefix: String = "" + private static let maxRows = 50_000 func generateInClause(rows: [[PluginCellValue]]) -> String { @@ -55,6 +60,6 @@ internal struct InClauseConverter { private func quoted(_ value: String) -> String { let escaped = escapeStringLiteral?(value) ?? value.replacingOccurrences(of: "'", with: "''") - return "'\(escaped)'" + return "\(stringLiteralPrefix)'\(escaped)'" } } diff --git a/TablePro/Core/Utilities/SQL/SQLRowToStatementConverter.swift b/TablePro/Core/Utilities/SQL/SQLRowToStatementConverter.swift index 2614db22a2..731938876d 100644 --- a/TablePro/Core/Utilities/SQL/SQLRowToStatementConverter.swift +++ b/TablePro/Core/Utilities/SQL/SQLRowToStatementConverter.swift @@ -117,7 +117,7 @@ internal struct SQLRowToStatementConverter { case .null: return "NULL" case .text(let s): - return "'\(escapeStringFn(s))'" + return "\(SQLStringLiteralPrefix.forDatabaseType(databaseType))'\(escapeStringFn(s))'" case .bytes(let data): return formatBinaryLiteral(data) } diff --git a/TablePro/Views/Results/DataGridView+RowActions.swift b/TablePro/Views/Results/DataGridView+RowActions.swift index 24b602aaa1..b73873df6e 100644 --- a/TablePro/Views/Results/DataGridView+RowActions.swift +++ b/TablePro/Views/Results/DataGridView+RowActions.swift @@ -207,7 +207,8 @@ extension TableViewCoordinator { let converter = InClauseConverter( columnIndex: columnIndex, columnTypes: tableRows.columnTypes, - escapeStringLiteral: driver?.escapeStringLiteral + escapeStringLiteral: driver?.escapeStringLiteral, + stringLiteralPrefix: SQLStringLiteralPrefix.forDatabaseType(databaseType) ) ClipboardService.shared.writeText(converter.generateInClause(rows: rows)) } diff --git a/TablePro/Views/Results/Extensions/DataGridView+Click.swift b/TablePro/Views/Results/Extensions/DataGridView+Click.swift index 3e5bc37280..26c89e7d0d 100644 --- a/TablePro/Views/Results/Extensions/DataGridView+Click.swift +++ b/TablePro/Views/Results/Extensions/DataGridView+Click.swift @@ -197,6 +197,7 @@ extension TableViewCoordinator { let currentValue = cellValue(at: row, column: columnIndex) ?? "" let escape = resolveDriver()?.escapeStringLiteral ?? SQLEscaping.escapeStringLiteral + let literalPrefix = SQLStringLiteralPrefix.forDatabaseType(databaseType) let cellRect = tableView.rect(ofRow: row).intersection(tableView.rect(ofColumn: column)) dismissActiveCellEditorPopover() @@ -207,6 +208,7 @@ extension TableViewCoordinator { CustomValueContentView( initialValue: currentValue, escapeStringLiteral: escape, + stringLiteralPrefix: literalPrefix, onCommit: { newValue in guard let self else { return } self.commitPopoverEdit(row: row, columnIndex: columnIndex, newValue: newValue) diff --git a/TablePro/Views/RowInspector/FieldEditors/ValuePickerFieldView.swift b/TablePro/Views/RowInspector/FieldEditors/ValuePickerFieldView.swift index dc41a30a68..76c2bc2a95 100644 --- a/TablePro/Views/RowInspector/FieldEditors/ValuePickerFieldView.swift +++ b/TablePro/Views/RowInspector/FieldEditors/ValuePickerFieldView.swift @@ -43,6 +43,7 @@ internal struct ValuePickerFieldView: View { CustomValueContentView( initialValue: context.value.wrappedValue, escapeStringLiteral: escapeStringLiteral, + stringLiteralPrefix: stringLiteralPrefix, onCommit: { context.value.wrappedValue = $0 }, onDismiss: { isCustomPresented = false } ) @@ -84,4 +85,15 @@ internal struct ValuePickerFieldView: View { } return driver.escapeStringLiteral } + + /// From the same connection the escaping comes from, so a default typed here is written the + /// way the engine reads it back. No connection means no prefix, which is what every engine but + /// SQL Server wants anyway. + private var stringLiteralPrefix: String { + guard let connectionId = context.userDefinedTypeScope?.connectionId, + let driver = DatabaseManager.shared.driver(for: connectionId) else { + return "" + } + return SQLStringLiteralPrefix.forDatabaseType(driver.connection.type) + } } diff --git a/TablePro/Views/Structure/CustomValueContentView.swift b/TablePro/Views/Structure/CustomValueContentView.swift index e5eed728bb..91ef215f13 100644 --- a/TablePro/Views/Structure/CustomValueContentView.swift +++ b/TablePro/Views/Structure/CustomValueContentView.swift @@ -22,6 +22,10 @@ internal struct CustomValueContentView: View { /// The connected driver's own escaping, so a value is escaped the way the engine reads it. /// MySQL doubles backslashes as well as quotes, which the shared helper does not. internal let escapeStringLiteral: (String) -> String + /// What the engine puts in front of a string literal, `N` on SQL Server and nothing anywhere + /// else. A default written without it is a `varchar` literal, so a non-Unicode collation turns + /// every character outside its code page into `?` as it parses the `ALTER TABLE`. + internal let stringLiteralPrefix: String internal let onCommit: (String) -> Void internal let onDismiss: () -> Void @@ -32,15 +36,20 @@ internal struct CustomValueContentView: View { internal init( initialValue: String, escapeStringLiteral: @escaping (String) -> String, + stringLiteralPrefix: String = "", onCommit: @escaping (String) -> Void, onDismiss: @escaping () -> Void ) { self.initialValue = initialValue self.escapeStringLiteral = escapeStringLiteral + self.stringLiteralPrefix = stringLiteralPrefix self.onCommit = onCommit self.onDismiss = onDismiss - if let text = SQLStringLiteral.unquoted(initialValue), - initialValue == "'\(escapeStringLiteral(text))'" { + let quotedPart = stringLiteralPrefix.isEmpty || !initialValue.hasPrefix(stringLiteralPrefix) + ? initialValue + : String(initialValue.dropFirst(stringLiteralPrefix.count)) + if let text = SQLStringLiteral.unquoted(quotedPart), + initialValue == "\(stringLiteralPrefix)'\(escapeStringLiteral(text))'" { _mode = State(initialValue: .text) _text = State(initialValue: text) } else { @@ -97,7 +106,7 @@ internal struct CustomValueContentView: View { private var resolvedSQL: String { switch mode { - case .text: "'\(escapeStringLiteral(text))'" + case .text: "\(stringLiteralPrefix)'\(escapeStringLiteral(text))'" case .expression: text } } diff --git a/TableProTests/Core/Compare/CompareSQLLiteralTests.swift b/TableProTests/Core/Compare/CompareSQLLiteralTests.swift index 0cb4a9d813..dfbaa716aa 100644 --- a/TableProTests/Core/Compare/CompareSQLLiteralTests.swift +++ b/TableProTests/Core/Compare/CompareSQLLiteralTests.swift @@ -21,6 +21,21 @@ final class CompareSQLLiteralTests: XCTestCase { } } + /// A compare script runs its own statements, so a plain literal on a SQL Server database with + /// a non-Unicode collation writes `?` into the target rather than the text it compared. + func testTextLiteralsCarryTheSQLServerPrefix() { + XCTAssertEqual(CompareSQLLiteral.prefixed("'日本語'", databaseType: .mssql), "N'日本語'") + XCTAssertEqual(CompareSQLLiteral.prefixed("'abc'", databaseType: .mysql), "'abc'") + } + + /// `sqlLiteral(for:)` answers `NULL` for a null and passes a number through unquoted. `N` in + /// front of either is a syntax error. + func testOnlyQuotedLiteralsTakeThePrefix() { + XCTAssertEqual(CompareSQLLiteral.prefixed("NULL", databaseType: .mssql), "NULL") + XCTAssertEqual(CompareSQLLiteral.prefixed("42", databaseType: .mssql), "42") + XCTAssertEqual(CompareSQLLiteral.prefixed("0x89504E47", databaseType: .mssql), "0x89504E47") + } + func testPostgresFamilyUsesAByteaCast() throws { for type in [DatabaseType.postgresql, .cockroachdb, .redshift, .pglite] { let literal = try XCTUnwrap(CompareSQLLiteral.binaryLiteral(for: png, databaseType: type)) diff --git a/TableProTests/Core/Database/ForeignKeyPreviewQueryTests.swift b/TableProTests/Core/Database/ForeignKeyPreviewQueryTests.swift index dec854a6e0..d6db671339 100644 --- a/TableProTests/Core/Database/ForeignKeyPreviewQueryTests.swift +++ b/TableProTests/Core/Database/ForeignKeyPreviewQueryTests.swift @@ -52,6 +52,7 @@ struct ForeignKeyPreviewQueryTests { quotedTable: "[dbo].[customers]", quotedColumn: "[id]", escapedValue: "42", + stringLiteralPrefix: "", dialect: dialect(paginationStyle: .offsetFetch) ) #expect( @@ -66,8 +67,24 @@ struct ForeignKeyPreviewQueryTests { quotedTable: "\"users\"", quotedColumn: "\"name\"", escapedValue: "O''Brien", + stringLiteralPrefix: "", dialect: dialect(paginationStyle: .limit) ) #expect(sql == "SELECT * FROM \"users\" WHERE \"name\" = 'O''Brien' LIMIT 1") } + + /// A plain literal is a `varchar` on SQL Server, so a key holding non-Latin text matched the + /// row whose own text the server had already damaged, and the popover reported the real row as + /// missing. + @Test("The key literal carries the engine's prefix") + func keyLiteralCarriesThePrefix() { + let sql = ForeignKeyPreviewQuery.singleRow( + quotedTable: "[dbo].[customers]", + quotedColumn: "[name]", + escapedValue: "日本語", + stringLiteralPrefix: SQLStringLiteralPrefix.forDatabaseType(.mssql), + dialect: dialect(paginationStyle: .offsetFetch) + ) + #expect(sql.contains("[name] = N'日本語'")) + } } diff --git a/TableProTests/Core/Utilities/InClauseConverterTests.swift b/TableProTests/Core/Utilities/InClauseConverterTests.swift index 6c906b8083..47218b5f38 100644 --- a/TableProTests/Core/Utilities/InClauseConverterTests.swift +++ b/TableProTests/Core/Utilities/InClauseConverterTests.swift @@ -14,9 +14,34 @@ struct InClauseConverterTests { private func makeConverter( columnIndex: Int, columnTypes: [ColumnType], - escape: ((String) -> String)? = nil + escape: ((String) -> String)? = nil, + stringLiteralPrefix: String = "" ) -> InClauseConverter { - InClauseConverter(columnIndex: columnIndex, columnTypes: columnTypes, escapeStringLiteral: escape) + InClauseConverter( + columnIndex: columnIndex, + columnTypes: columnTypes, + escapeStringLiteral: escape, + stringLiteralPrefix: stringLiteralPrefix + ) + } + + /// An `IN` list pasted into a query on a SQL Server database with a non-Unicode collation + /// matched the rows whose text the server had already damaged, never the rows copied. + @Test("A text value carries the engine's literal prefix, and a number does not") + func textValuesCarryThePrefix() { + let converter = makeConverter( + columnIndex: 0, + columnTypes: [.text(rawType: nil)], + stringLiteralPrefix: SQLStringLiteralPrefix.forDatabaseType(.mssql) + ) + #expect(converter.generateInClause(rows: [[.text("日本語")], [.text("b")]]) == "(N'日本語', N'b')") + + let numbers = makeConverter( + columnIndex: 0, + columnTypes: [.integer(rawType: nil)], + stringLiteralPrefix: SQLStringLiteralPrefix.forDatabaseType(.mssql) + ) + #expect(numbers.generateInClause(rows: [[.text("1")], [.text("2")]]) == "(1, 2)") } @Test("Empty rows yields empty parens") diff --git a/TableProTests/Core/Utilities/SQLRowToStatementConverterTests.swift b/TableProTests/Core/Utilities/SQLRowToStatementConverterTests.swift index 9a32963ab2..d7361a3292 100644 --- a/TableProTests/Core/Utilities/SQLRowToStatementConverterTests.swift +++ b/TableProTests/Core/Utilities/SQLRowToStatementConverterTests.swift @@ -152,11 +152,24 @@ struct SQLRowToStatementConverterTests { #expect(result == "UPDATE `users` SET `name` = 'Alice', `email` = 'alice@example.com' WHERE `id` = '1';") } - @Test("MSSQL uses bracket quoting") + /// The `N` is not decoration: a plain `'…'` is a `varchar` literal, so pasting these + /// statements into a database with a non-Unicode collation stores `?` for every character + /// outside its code page, whatever the column type is. + @Test("MSSQL uses bracket quoting and N-prefixed literals") func mssqlUsesBracketQuoting() throws { let converter = try makeConverter(databaseType: .mssql, dialect: Self.mssqlDialect) let result = converter.generateInserts(rows: [["1", "Alice", "alice@example.com"]]) - #expect(result == "INSERT INTO [users] ([id], [name], [email]) VALUES ('1', 'Alice', 'alice@example.com');") + #expect(result == "INSERT INTO [users] ([id], [name], [email]) VALUES (N'1', N'Alice', N'alice@example.com');") + } + + @Test("MSSQL: non-Latin text survives a copied INSERT and UPDATE") + func mssqlKeepsNonLatinText() throws { + let converter = try makeConverter(databaseType: .mssql, dialect: Self.mssqlDialect) + let inserts = converter.generateInserts(rows: [["1", "日本語", "a@b.c"]]) + #expect(inserts.contains("N'日本語'")) + let updates = converter.generateUpdates(rows: [["1", "日本語", "a@b.c"]]) + #expect(updates.contains("[name] = N'日本語'")) + #expect(updates.contains("WHERE [id] = N'1'")) } @Test("PostgreSQL uses double-quote quoting") From 49b3ee8abec64a1d34957261b0839eeef6db097d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 08:07:03 +0700 Subject: [PATCH 28/54] fix(plugin-mssql): send a binary parameter as binary and keep a bracketed identifier out of the placeholder scan (#2771) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ngô Quốc Đạt --- CHANGELOG.md | 3 + .../MSSQLParameterBatch.swift | 146 ++++++++++++++++++ .../MSSQLStringLiteral.swift | 5 + .../MSSQLParameterBatchTests.swift | 105 +++++++++++++ .../MSSQLStringLiteralTests.swift | 9 ++ Plugins/MSSQLDriverPlugin/MSSQLPlugin.swift | 73 ++------- 6 files changed, 283 insertions(+), 58 deletions(-) create mode 100644 Packages/TableProCore/Sources/TableProMSSQLCore/MSSQLParameterBatch.swift create mode 100644 Packages/TableProCore/Tests/TableProMSSQLCoreTests/MSSQLParameterBatchTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index e4a9877b8f..a52b6788a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -177,6 +177,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Non-ASCII SQL Server filter values turned into `?` and matching the wrong rows on non-Unicode collations. - Empty structure, missing indexes and failed renames for non-ASCII SQL Server object names on non-Unicode collations. - Changing a defaulted SQL Server column failing when a name contains a quote or non-ASCII text. +- SQL Server edits and deletes matching no row when the row is identified by a binary column. +- SQL Server parameters sent to the wrong placeholders when a column name holds a question mark. +- `[` in a SQL Server filter value read as a wildcard. - Non-ASCII text turned into `?` by Copy as INSERT, Copy as IN, Preview Referenced Row, compare scripts and column defaults on SQL Server. ### Security diff --git a/Packages/TableProCore/Sources/TableProMSSQLCore/MSSQLParameterBatch.swift b/Packages/TableProCore/Sources/TableProMSSQLCore/MSSQLParameterBatch.swift new file mode 100644 index 0000000000..98998fad79 --- /dev/null +++ b/Packages/TableProCore/Sources/TableProMSSQLCore/MSSQLParameterBatch.swift @@ -0,0 +1,146 @@ +import Foundation + +/// One value bound to a `?` placeholder, in the three shapes a cell can arrive in. +public enum MSSQLParameter: Equatable, Sendable { + case null + case text(String) + case bytes(Data) +} + +/// Rewrites a `?`-placeholder query into the `EXEC sp_executesql` form SQL Server takes, and +/// declares each parameter as the type its value actually is. +/// +/// Every parameter used to be declared `NVARCHAR(MAX)` and assigned from the value's text. A +/// binary value has no text, so it was assigned `NULL`: a row matched on a `VARBINARY` column +/// found nothing, and the delete or update that followed reported success having touched no row. +/// A `VARBINARY(MAX)` parameter assigned a `0x…` literal is what that value is. +public enum MSSQLParameterBatch { + public struct Statement: Equatable, Sendable { + public let query: String + public let declarations: String + public let assignments: String + + public var isEmpty: Bool { declarations.isEmpty } + } + + public static func spExecuteSql(query: String, parameters: [MSSQLParameter]) -> Statement { + let replaced = replacePlaceholders(in: query, limit: parameters.count) + guard replaced.count > 0 else { + return Statement(query: replaced.query, declarations: "", assignments: "") + } + let used = parameters.prefix(replaced.count) + let declarations = used.enumerated() + .map { "@p\($0.offset + 1) \(declaredType(of: $0.element))" } + .joined(separator: ", ") + let assignments = used.enumerated() + .map { "@p\($0.offset + 1) = \(literal(for: $0.element))" } + .joined(separator: ", ") + return Statement(query: replaced.query, declarations: declarations, assignments: assignments) + } + + private static func declaredType(of parameter: MSSQLParameter) -> String { + switch parameter { + case .bytes: + return "VARBINARY(MAX)" + case .text, .null: + return "NVARCHAR(MAX)" + } + } + + private static func literal(for parameter: MSSQLParameter) -> String { + switch parameter { + case .null: + return "NULL" + case .text(let value): + return MSSQLStringLiteral.quoted(value) + case .bytes(let data): + return hexLiteral(data) + } + } + + /// `0x` on its own is the empty binary, which is what SQL Server writes for one and what it + /// reads back. There is no zero-length form to special-case. + private static func hexLiteral(_ data: Data) -> String { + var literal = "0x" + literal.reserveCapacity(2 + data.count * 2) + for byte in data { + literal.append(String(format: "%02X", byte)) + } + return literal + } + + /// A `?` inside a string literal or a quoted identifier is data, not a placeholder, and the + /// doubled `''`, `""` and `]]` that carry one have to be stepped over rather than read as the + /// end of the literal. + /// + /// The bracket is the one T-SQL spells differently from everything else, and it was missing: + /// a column named `[we?ird]` took `@p1`, which shifted every parameter after it by one and + /// sent the values to the wrong placeholders. + private static func replacePlaceholders(in query: String, limit: Int) -> (query: String, count: Int) { + var converted = "" + var count = 0 + var quoting = Quoting.code + let characters = Array(query) + + var index = 0 + while index < characters.count { + let character = characters[index] + let next = index + 1 < characters.count ? characters[index + 1] : nil + + if let doubled = quoting.doubledDelimiter, character == doubled, next == doubled { + converted.append(doubled) + converted.append(doubled) + index += 2 + continue + } + + quoting = quoting.after(character) + + if character == "?", quoting == .code, count < limit { + count += 1 + converted.append("@p\(count)") + } else { + converted.append(character) + } + index += 1 + } + + return (converted, count) + } + + private enum Quoting { + case code + case singleQuote + case doubleQuote + case bracket + + /// What a doubled occurrence of this state's own delimiter escapes. A bracket identifier + /// escapes its closing `]`, not the `[` that opened it. + var doubledDelimiter: Character? { + switch self { + case .code: return nil + case .singleQuote: return "'" + case .doubleQuote: return "\"" + case .bracket: return "]" + } + } + + func after(_ character: Character) -> Quoting { + switch self { + case .code: + switch character { + case "'": return .singleQuote + case "\"": return .doubleQuote + case "[": return .bracket + default: return .code + } + case .singleQuote: + return character == "'" ? .code : self + case .doubleQuote: + return character == "\"" ? .code : self + case .bracket: + return character == "]" ? .code : self + } + } + } +} diff --git a/Packages/TableProCore/Sources/TableProMSSQLCore/MSSQLStringLiteral.swift b/Packages/TableProCore/Sources/TableProMSSQLCore/MSSQLStringLiteral.swift index 346f5317f5..df9a8f3a02 100644 --- a/Packages/TableProCore/Sources/TableProMSSQLCore/MSSQLStringLiteral.swift +++ b/Packages/TableProCore/Sources/TableProMSSQLCore/MSSQLStringLiteral.swift @@ -29,12 +29,17 @@ public enum MSSQLStringLiteral { return "N'\(pattern)' ESCAPE '\\'" } + /// `[` opens a character class in a T-SQL `LIKE` pattern, which no other engine this app + /// speaks to does, so a value holding one matched by its contents instead of by itself: a + /// search for `a[bc]` found `ab` and `ac` and never the text the user typed. `]` outside a + /// class is an ordinary character and stays as it is. public static func escapeForLike(_ value: String) -> String { escaped( value .replacingOccurrences(of: "\\", with: "\\\\") .replacingOccurrences(of: "%", with: "\\%") .replacingOccurrences(of: "_", with: "\\_") + .replacingOccurrences(of: "[", with: "\\[") ) } diff --git a/Packages/TableProCore/Tests/TableProMSSQLCoreTests/MSSQLParameterBatchTests.swift b/Packages/TableProCore/Tests/TableProMSSQLCoreTests/MSSQLParameterBatchTests.swift new file mode 100644 index 0000000000..f0eee1e56b --- /dev/null +++ b/Packages/TableProCore/Tests/TableProMSSQLCoreTests/MSSQLParameterBatchTests.swift @@ -0,0 +1,105 @@ +import Foundation +import Testing + +@testable import TableProMSSQLCore + +@Suite("MSSQL parameter batch") +struct MSSQLParameterBatchTests { + /// Every parameter used to be declared `NVARCHAR(MAX)` and assigned from the value's text, and + /// a binary value has none: it was sent as `NULL`, so a row matched on a `VARBINARY` column + /// found nothing and the update or delete reported success having touched no row. + @Test("A binary parameter is declared and sent as binary") + func binaryParameterKeepsItsBytes() { + let statement = MSSQLParameterBatch.spExecuteSql( + query: "DELETE FROM [t] WHERE [payload] = ?", + parameters: [.bytes(Data([0xDE, 0xAD, 0xBE, 0xEF]))] + ) + #expect(statement.query == "DELETE FROM [t] WHERE [payload] = @p1") + #expect(statement.declarations == "@p1 VARBINARY(MAX)") + #expect(statement.assignments == "@p1 = 0xDEADBEEF") + } + + @Test("An empty binary is still binary") + func emptyBinaryIsStillBinary() { + let statement = MSSQLParameterBatch.spExecuteSql( + query: "SELECT ?", parameters: [.bytes(Data())] + ) + #expect(statement.declarations == "@p1 VARBINARY(MAX)") + #expect(statement.assignments == "@p1 = 0x") + } + + @Test("Text is an nvarchar literal and null stays null") + func textAndNullKeepTheirTypes() { + let statement = MSSQLParameterBatch.spExecuteSql( + query: "SELECT ?, ?", parameters: [.text("O'Brien"), .null] + ) + #expect(statement.declarations == "@p1 NVARCHAR(MAX), @p2 NVARCHAR(MAX)") + #expect(statement.assignments == "@p1 = N'O''Brien', @p2 = NULL") + } + + /// Non-Latin text in a parameter is the same problem the literals have: a plain `'…'` is a + /// `varchar` and a non-Unicode collation turns it into question marks. + @Test("Text parameters carry the N prefix") + func textParametersAreNvarcharLiterals() { + let statement = MSSQLParameterBatch.spExecuteSql( + query: "SELECT ?", parameters: [.text("日本語")] + ) + #expect(statement.assignments == "@p1 = N'日本語'") + } + + @Test("Each parameter is declared as the type its own value is") + func typesArePerParameter() { + let statement = MSSQLParameterBatch.spExecuteSql( + query: "SELECT ?, ?, ?", + parameters: [.text("a"), .bytes(Data([0x01])), .null] + ) + #expect(statement.declarations == "@p1 NVARCHAR(MAX), @p2 VARBINARY(MAX), @p3 NVARCHAR(MAX)") + #expect(statement.assignments == "@p1 = N'a', @p2 = 0x01, @p3 = NULL") + } + + /// A `?` inside a literal or a quoted identifier is data. Reading one as a placeholder shifts + /// every parameter after it by one. + @Test("A question mark inside a literal or an identifier is not a placeholder") + func questionMarksInsideLiteralsAreData() { + let statement = MSSQLParameterBatch.spExecuteSql( + query: "SELECT '?', [we?ird], ? FROM [t] WHERE [a] = ?", + parameters: [.text("x"), .text("y")] + ) + #expect(statement.query == "SELECT '?', [we?ird], @p1 FROM [t] WHERE [a] = @p2") + #expect(statement.declarations == "@p1 NVARCHAR(MAX), @p2 NVARCHAR(MAX)") + } + + @Test("A doubled closing bracket does not end an identifier") + func doubledBracketsStayInsideTheIdentifier() { + let statement = MSSQLParameterBatch.spExecuteSql( + query: "SELECT [a]]?b], ? FROM [t]", parameters: [.text("x")] + ) + #expect(statement.query == "SELECT [a]]?b], @p1 FROM [t]") + } + + @Test("A doubled quote inside a literal does not end it") + func doubledQuotesStayInsideTheLiteral() { + let statement = MSSQLParameterBatch.spExecuteSql( + query: "SELECT 'it''s ?', ?", parameters: [.text("x")] + ) + #expect(statement.query == "SELECT 'it''s ?', @p1") + } + + @Test("A query with no placeholder declares nothing") + func noPlaceholdersDeclaresNothing() { + let statement = MSSQLParameterBatch.spExecuteSql( + query: "SELECT 1", parameters: [.text("unused")] + ) + #expect(statement.isEmpty) + #expect(statement.query == "SELECT 1") + } + + @Test("More placeholders than parameters leaves the extra ones alone") + func extraPlaceholdersAreLeftAlone() { + let statement = MSSQLParameterBatch.spExecuteSql( + query: "SELECT ?, ?", parameters: [.text("a")] + ) + #expect(statement.query == "SELECT @p1, ?") + #expect(statement.declarations == "@p1 NVARCHAR(MAX)") + } +} diff --git a/Packages/TableProCore/Tests/TableProMSSQLCoreTests/MSSQLStringLiteralTests.swift b/Packages/TableProCore/Tests/TableProMSSQLCoreTests/MSSQLStringLiteralTests.swift index 31c5e5d18d..e8d0a1aa53 100644 --- a/Packages/TableProCore/Tests/TableProMSSQLCoreTests/MSSQLStringLiteralTests.swift +++ b/Packages/TableProCore/Tests/TableProMSSQLCoreTests/MSSQLStringLiteralTests.swift @@ -46,6 +46,15 @@ final class MSSQLStringLiteralTests: XCTestCase { ) } + /// `[` opens a character class in T-SQL and in no other engine this app speaks to, so a + /// filter for `a[bc]` matched `ab` and `ac` and never the text the user typed. + func testLikePatternEscapesBracketWildcards() { + XCTAssertEqual( + MSSQLStringLiteral.likePattern("a[bc]", prefixWildcard: true, suffixWildcard: true), + "N'%a\\[bc]%' ESCAPE '\\'" + ) + } + func testLikePatternEscapesBackslashBeforeWildcards() { XCTAssertEqual( MSSQLStringLiteral.likePattern("a\\b", prefixWildcard: false, suffixWildcard: false), diff --git a/Plugins/MSSQLDriverPlugin/MSSQLPlugin.swift b/Plugins/MSSQLDriverPlugin/MSSQLPlugin.swift index 2b92c2c854..d665270492 100644 --- a/Plugins/MSSQLDriverPlugin/MSSQLPlugin.swift +++ b/Plugins/MSSQLDriverPlugin/MSSQLPlugin.swift @@ -670,15 +670,16 @@ final class MSSQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { return try await execute(query: query) } - let (convertedQuery, paramDecls, paramAssigns) = Self.buildSpExecuteSql( - query: query, parameters: parameters.map { $0.asText } + let statement = MSSQLParameterBatch.spExecuteSql( + query: query, parameters: parameters.map(Self.parameter) ) - guard !paramDecls.isEmpty else { + guard !statement.isEmpty else { return try await execute(query: query) } - let sql = "EXEC sp_executesql N'\(Self.escapeNString(convertedQuery))', N'\(paramDecls)', \(paramAssigns)" + let sql = "EXEC sp_executesql N'\(Self.escapeNString(statement.query))', " + + "N'\(statement.declarations)', \(statement.assignments)" return try await execute(query: sql) } @@ -831,61 +832,17 @@ final class MSSQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { /// Convert `?` placeholders to `@p1, @p2, ...` and build sp_executesql components. /// Returns: (convertedQuery, paramDeclarations, paramAssignments) - private static func buildSpExecuteSql( - query: String, - parameters: [String?] - ) -> (String, String, String) { - var converted = "" - var paramIndex = 0 - var inSingleQuote = false - var inDoubleQuote = false - let chars = Array(query) - let length = chars.count - - var i = 0 - while i < length { - let char = chars[i] - - // Handle doubled quotes (T-SQL escape: '' inside strings, "" inside identifiers) - if char == "'" && inSingleQuote && i + 1 < length && chars[i + 1] == "'" { - converted.append("''") - i += 2 - continue - } - if char == "\"" && inDoubleQuote && i + 1 < length && chars[i + 1] == "\"" { - converted.append("\"\"") - i += 2 - continue - } - - if char == "'" && !inDoubleQuote { - inSingleQuote.toggle() - } else if char == "\"" && !inSingleQuote { - inDoubleQuote.toggle() - } - - if char == "?" && !inSingleQuote && !inDoubleQuote && paramIndex < parameters.count { - paramIndex += 1 - converted.append("@p\(paramIndex)") - } else { - converted.append(char) - } - i += 1 - } - - let count = paramIndex - guard count > 0 else { - return (converted, "", "") + /// A binary cell has no text, and asking it for some is how every one of them reached the + /// server as `NULL`. + private static func parameter(_ value: PluginCellValue) -> MSSQLParameter { + switch value { + case .null: + return .null + case .text(let text): + return .text(text) + case .bytes(let data): + return .bytes(data) } - let decls = (1...count).map { "@p\($0) NVARCHAR(MAX)" }.joined(separator: ", ") - let assigns = (1...count).map { i -> String in - if let value = parameters[i - 1] { - return "@p\(i) = N'\(escapeNString(value))'" - } - return "@p\(i) = NULL" - }.joined(separator: ", ") - - return (converted, decls, assigns) } /// Escape single quotes for N'...' string literals in SQL Server. From 0b0720c98e1da5c3109d321b4247213734b2e3c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 08:24:38 +0700 Subject: [PATCH 29/54] fix(plugin-postgresql): support PostgreSQL 9.1 and later in catalog reads (#2762) * fix(plugin-postgresql): support PostgreSQL 9.1 and later in catalog reads * fix(plugin-postgresql): keep the routine listing internal after the merge --- CHANGELOG.md | 15 + .../CockroachPluginDriver.swift | 9 +- .../LibPQDriverCore.swift | 2 +- .../LibPQPluginConnection.swift | 112 +++- .../PostGISSpatialRewrite.swift | 33 +- .../PostgreSQLCapabilities.swift | 13 +- .../PostgreSQLCatalogBoolean.swift | 15 + .../PostgreSQLForeignKeyQueries.swift | 88 +++ .../PostgreSQLIndexQueries.swift | 54 ++ .../PostgreSQLObjectQueries.swift | 68 +- .../PostgreSQLPluginDriver+BulkMetadata.swift | 50 +- ...PostgreSQLPluginDriver+ColumnReorder.swift | 11 +- .../PostgreSQLPluginDriver+Columns.swift | 13 +- .../PostgreSQLPluginDriver+Principals.swift | 19 +- .../PostgreSQLPluginDriver+Routines.swift | 4 +- .../PostgreSQLPluginDriver+Sequences.swift | 54 ++ .../PostgreSQLPluginDriver+Types.swift | 6 +- .../PostgreSQLPluginDriver.swift | 287 +------- .../PostgreSQLPrincipalQueries.swift | 72 +- .../PostgreSQLSchemaQueries.swift | 82 ++- .../PostgreSQLSequenceQueries.swift | 160 +++++ .../PostgreSQLTextArray.swift | 21 + .../PostgreSQLTypeDefinition.swift | 47 +- .../PostgreSQLViewDefinition.swift | 21 +- .../RedshiftPluginDriver.swift | 2 +- .../Plugins/ObjectCatalogQueryTests.swift | 28 +- .../Plugins/PostGISSpatialRewriteTests.swift | 68 +- .../PostgreSQLCatalogCompatibilityTests.swift | 10 +- ...PostgreSQLDefaultSchemaFallbackTests.swift | 2 +- .../PostgreSQLFetchTablesCommentTests.swift | 49 +- .../PostgreSQLLegacyCatalogQueryTests.swift | 427 ++++++++++++ .../PostgreSQLPartitionFilterTests.swift | 6 +- .../PostgreSQLTypeDefinitionTests.swift | 73 +- .../Plugins/PostgreSQLTypeQueryTests.swift | 56 +- .../PostgreSQLViewDefinitionTests.swift | 31 +- docs/databases/postgresql.mdx | 7 +- project.yml | 6 + scripts/check-postgres-object-queries.sh | 149 ---- scripts/check-postgresql-compat.sh | 634 ++++++++++++++++++ 39 files changed, 2036 insertions(+), 768 deletions(-) create mode 100644 Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogBoolean.swift create mode 100644 Plugins/PostgreSQLDriverPlugin/PostgreSQLForeignKeyQueries.swift create mode 100644 Plugins/PostgreSQLDriverPlugin/PostgreSQLIndexQueries.swift create mode 100644 Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Sequences.swift create mode 100644 Plugins/PostgreSQLDriverPlugin/PostgreSQLSequenceQueries.swift create mode 100644 Plugins/PostgreSQLDriverPlugin/PostgreSQLTextArray.swift create mode 100644 TableProTests/Plugins/PostgreSQLLegacyCatalogQueryTests.swift delete mode 100755 scripts/check-postgres-object-queries.sh create mode 100755 scripts/check-postgresql-compat.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index a52b6788a2..30b7f89f25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Crash opening a MySQL result whose column has no name on iPhone and iPad. - Wrong SQLSTATE code in PostgreSQL, Redshift, CockroachDB and PGlite error messages. - Read-only write explanation never shown on PostgreSQL servers. +- Table list, foreign keys, triggers, check constraints, types and grants failing on PostgreSQL 9.1 to 9.5. (#2734) +- Wrong index column order on PostgreSQL 9.4 and earlier. +- Sequences missing from SQL dumps of PostgreSQL 9.6 and earlier. +- Create Database failing on PostgreSQL 9.6 and earlier. +- PostgreSQL unique and primary key indexes shown as plain indexes. +- PostgreSQL triggers shown as disabled. +- PostgreSQL `NOT VALID` check constraints shown as validated. +- Redshift `DISTKEY` missing from a table's indexes. +- `CYCLE` dropped from PostgreSQL sequences in SQL dumps. +- PostgreSQL index columns and enum labels containing a comma or a space split apart. +- Foreign keys to a partitioned table listed once per partition on PostgreSQL 12 and later. +- PostGIS values left as hex after switching schema. +- Open transaction aborted when a PostGIS value could not be converted. +- PostgreSQL all-tables metadata failing for a mixed-case table name. +- Default PostgreSQL schema taken from the schema list rather than the search path. - Safe Mode minimum from a configuration profile missing from the toolbar, the Database menu and the connection form. (#2030) - PostgreSQL connection hanging after running `COPY FROM STDIN` or `COPY TO STDOUT` in the query editor and on iOS. - Stop not ending queries on MySQL and MariaDB servers without TLS. diff --git a/Plugins/PostgreSQLDriverPlugin/CockroachPluginDriver.swift b/Plugins/PostgreSQLDriverPlugin/CockroachPluginDriver.swift index 9a89bb138f..ff7bb84970 100644 --- a/Plugins/PostgreSQLDriverPlugin/CockroachPluginDriver.swift +++ b/Plugins/PostgreSQLDriverPlugin/CockroachPluginDriver.swift @@ -116,14 +116,14 @@ final class CockroachPluginDriver: LibPQBackedDriver, @unchecked Sendable { let columnName = row[columnIndex].asText else { continue } if let implicitIndex, implicitIndex < row.count, - row[implicitIndex].asText.map(Self.isTruthy) == true { + PostgreSQLCatalogBoolean.isTrue(row[implicitIndex].asText) { continue } if columnsByIndex[indexName] == nil { order.append(indexName) if let nonUniqueIndex, nonUniqueIndex < row.count { - uniqueByIndex[indexName] = row[nonUniqueIndex].asText.map(Self.isTruthy) == false + uniqueByIndex[indexName] = row[nonUniqueIndex].asText.map { !PostgreSQLCatalogBoolean.isTrue($0) } ?? false } else { uniqueByIndex[indexName] = false } @@ -306,9 +306,4 @@ final class CockroachPluginDriver: LibPQBackedDriver, @unchecked Sendable { guard createIndex < row.count, let ddl = row[createIndex].asText, !ddl.isEmpty else { return nil } return ddl } - - private static func isTruthy(_ value: String) -> Bool { - let lowered = value.lowercased() - return lowered == "t" || lowered == "true" - } } diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift b/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift index 36a40a59cb..038784fd62 100644 --- a/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift +++ b/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift @@ -186,7 +186,7 @@ final class LibPQDriverCore: @unchecked Sendable { libpqConnection?.cancelCurrentQuery() } - func setPostgisOidMap(_ map: [UInt32: String]) { + func setPostgisOidMap(_ map: [UInt32: PostGISType]) { libpqConnection?.setPostgisOidMap(map) } diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift b/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift index 676cd6be24..eb09b9abb2 100644 --- a/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift +++ b/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift @@ -117,7 +117,7 @@ final class LibPQPluginConnection: @unchecked Sendable { private var _cachedServerVersion: String? private var _cachedServerVersionNumber: Int32 = 0 private var _isConnectCancelled: Bool = false - private var _postgisOidMap: [UInt32: String] = [:] + private var _postgisOidMap: [UInt32: PostGISType] = [:] private var _catalogTypeNames: [UInt32: String] = [:] private var _standardConformingStrings = true @@ -411,13 +411,13 @@ final class LibPQPluginConnection: @unchecked Sendable { // MARK: - PostGIS OID Map - func setPostgisOidMap(_ map: [UInt32: String]) { + func setPostgisOidMap(_ map: [UInt32: PostGISType]) { stateLock.lock() _postgisOidMap = map stateLock.unlock() } - private var postgisOidMap: [UInt32: String] { + private var postgisOidMap: [UInt32: PostGISType] { stateLock.lock() defer { stateLock.unlock() } return _postgisOidMap @@ -1138,9 +1138,9 @@ final class LibPQPluginConnection: @unchecked Sendable { let oidMap = postgisOidMap guard !oidMap.isEmpty else { return result } - let spatialColumns = result.columnOids.enumerated().compactMap { index, oid -> (index: Int, typeName: String)? in - guard let typeName = oidMap[oid] else { return nil } - return (index, typeName) + let spatialColumns = result.columnOids.enumerated().compactMap { index, oid -> (index: Int, type: PostGISType)? in + guard let type = oidMap[oid] else { return nil } + return (index, type) } guard !spatialColumns.isEmpty else { return result } @@ -1177,34 +1177,41 @@ final class LibPQPluginConnection: @unchecked Sendable { private func renderSpatialColumns( _ result: LibPQPluginQueryResult, - spatialColumns: [(index: Int, typeName: String)] + spatialColumns: [(index: Int, type: PostGISType)] ) -> LibPQPluginQueryResult { var rows = result.rows var columnTypeNames = result.columnTypeNames + var pending: [(index: Int, query: String, hexValues: [String?])] = [] for column in spatialColumns { if column.index < columnTypeNames.count { - columnTypeNames[column.index] = column.typeName + columnTypeNames[column.index] = column.type.name } - guard let query = PostGISSpatialRewrite.conversionQuery(forTypeName: column.typeName) else { continue } + guard let query = PostGISSpatialRewrite.conversionQuery(for: column.type) else { continue } let hexValues: [String?] = rows.map { row in guard column.index < row.count, case let .text(hex) = row[column.index] else { return nil } return hex } guard hexValues.contains(where: { $0 != nil }) else { continue } + pending.append((index: column.index, query: query, hexValues: hexValues)) + } - guard let converted = convertSpatialValues(hexValues, query: query), - converted.count == hexValues.count else { - logger.warning("PostGIS value conversion failed for column \(column.index); keeping raw hex") - continue - } + if !pending.isEmpty, let scope = SpatialRenderScope(connection: self) { + for column in pending { + guard let converted = scope.convert(column.hexValues, query: column.query), + converted.count == column.hexValues.count else { + logger.warning("PostGIS value conversion failed for column \(column.index); keeping raw hex") + continue + } - for (rowIndex, value) in converted.enumerated() - where hexValues[rowIndex] != nil && column.index < rows[rowIndex].count { - rows[rowIndex][column.index] = value + for (rowIndex, value) in converted.enumerated() + where column.hexValues[rowIndex] != nil && column.index < rows[rowIndex].count { + rows[rowIndex][column.index] = value + } } + scope.finish() } return LibPQPluginQueryResult( @@ -1219,27 +1226,62 @@ final class LibPQPluginConnection: @unchecked Sendable { ) } - private func convertSpatialValues(_ hexValues: [String?], query: String) -> [PluginCellValue]? { - stateLock.lock() - let conn = self.conn - stateLock.unlock() - guard let conn else { return nil } + /// One savepoint for a whole rendering pass rather than one per column: the conversion is a + /// side query on the user's own session, and an open transaction must survive a PostGIS error + /// (an older server has no ST_AsEWKT at all) without costing three round trips per column. + private final class SpatialRenderScope { + private let conn: OpaquePointer + private let isInsideTransaction: Bool + + init?(connection: LibPQPluginConnection) { + connection.stateLock.lock() + let handle = connection.conn + connection.stateLock.unlock() + guard let handle else { return nil } + self.conn = handle + switch PQtransactionStatus(handle) { + case PQTRANS_IDLE: + isInsideTransaction = false + case PQTRANS_INTRANS: + guard LibPQPluginConnection.runCommand(PostGISSpatialRewrite.savepoint, on: handle) else { + return nil + } + isInsideTransaction = true + default: + return nil + } + } - let arrayLiteral = PostGISSpatialRewrite.arrayLiteral(from: hexValues) - guard let paramCStr = strdup(arrayLiteral) else { return nil } - defer { free(paramCStr) } + func convert(_ hexValues: [String?], query: String) -> [PluginCellValue]? { + let arrayLiteral = PostGISSpatialRewrite.arrayLiteral(from: hexValues) + guard let paramCStr = strdup(arrayLiteral) else { return nil } + defer { free(paramCStr) } - let paramValues: [UnsafePointer?] = [UnsafePointer(paramCStr)] - let result: OpaquePointer? = query.withCString { queryPtr in - PQexecParams(conn, queryPtr, 1, nil, paramValues, nil, nil, 0) + let paramValues: [UnsafePointer?] = [UnsafePointer(paramCStr)] + let result = query.withCString { queryPtr in + PQexecParams(conn, queryPtr, 1, nil, paramValues, nil, nil, 0) + } + guard let result, PQresultStatus(result) == PGRES_TUPLES_OK else { + if let result { PQclear(result) } + rollback() + return nil + } + defer { PQclear(result) } + return LibPQPluginConnection.textColumn(from: result) } - guard let result, PQresultStatus(result) == PGRES_TUPLES_OK else { - if let result { PQclear(result) } - return nil + func finish() { + guard isInsideTransaction else { return } + _ = LibPQPluginConnection.runCommand(PostGISSpatialRewrite.releaseSavepoint, on: conn) } - defer { PQclear(result) } + private func rollback() { + guard isInsideTransaction else { return } + _ = LibPQPluginConnection.runCommand(PostGISSpatialRewrite.rollbackToSavepoint, on: conn) + } + } + + private static func textColumn(from result: OpaquePointer) -> [PluginCellValue] { let rowCount = Int(PQntuples(result)) var converted: [PluginCellValue] = [] converted.reserveCapacity(rowCount) @@ -1257,6 +1299,12 @@ final class LibPQPluginConnection: @unchecked Sendable { return converted } + private static func runCommand(_ command: String, on conn: OpaquePointer) -> Bool { + guard let result = command.withCString({ PQexec(conn, $0) }) else { return false } + defer { PQclear(result) } + return PQresultStatus(result) == PGRES_COMMAND_OK + } + private static func decodeCell( from result: OpaquePointer, row: Int32, diff --git a/Plugins/PostgreSQLDriverPlugin/PostGISSpatialRewrite.swift b/Plugins/PostgreSQLDriverPlugin/PostGISSpatialRewrite.swift index 1085ba8917..f17fb6cfbb 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostGISSpatialRewrite.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostGISSpatialRewrite.swift @@ -14,20 +14,31 @@ import Foundation +struct PostGISType: Equatable, Sendable { + let name: String + let schema: String +} + enum PostGISSpatialRewrite { - static let probeQuery = "SELECT oid, typname FROM pg_type WHERE typname IN ('geometry', 'geography')" + static let probeQuery = """ + SELECT t.oid, t.typname, n.nspname + FROM pg_catalog.pg_type t + JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace + WHERE t.typname IN ('geometry', 'geography') + """ - static let geometryConversionQuery = - "SELECT ST_AsEWKT(t::geometry) FROM unnest($1::text[]) WITH ORDINALITY AS x(t, ord) ORDER BY ord" - static let geographyConversionQuery = - "SELECT ST_AsEWKT(t::geography) FROM unnest($1::text[]) WITH ORDINALITY AS x(t, ord) ORDER BY ord" + /// A user savepoint of the same name is safe: PostgreSQL resolves a repeated savepoint name to + /// the newest one, so this RELEASE removes only the savepoint the rendering pass opened. + static let savepoint = "SAVEPOINT tablepro_spatial_render" + static let releaseSavepoint = "RELEASE SAVEPOINT tablepro_spatial_render" + static let rollbackToSavepoint = "ROLLBACK TO SAVEPOINT tablepro_spatial_render" - static func conversionQuery(forTypeName typeName: String) -> String? { - switch typeName { - case "geometry": return geometryConversionQuery - case "geography": return geographyConversionQuery - default: return nil - } + static func conversionQuery(for type: PostGISType) -> String? { + guard type.name == "geometry" || type.name == "geography" else { return nil } + let schema = PostgreSQLObjectQueries.quoteIdentifier(type.schema) + let qualifiedType = PostgreSQLObjectQueries.qualifiedName(schema: type.schema, name: type.name) + return "SELECT \(schema).ST_AsEWKT(($1::text[])[i]::\(qualifiedType)) " + + "FROM pg_catalog.generate_subscripts($1::text[], 1) AS i ORDER BY i" } static func arrayLiteral(from values: [String?]) -> String { diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift index 9ae3b4ae29..58a6483e7f 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift @@ -8,8 +8,6 @@ import Foundation struct PostgreSQLCapabilities: Sendable, Equatable { let serverVersion: Int32 - static let unknown = PostgreSQLCapabilities(serverVersion: 0) - /// libpq answers 0 for a handle it has not connected. A catalog query built for that has to /// assume a current server, or it emits the legacy projection on every server that exists. static func assumingModernWhenUnknown(_ serverVersion: Int32) -> PostgreSQLCapabilities { @@ -18,7 +16,6 @@ struct PostgreSQLCapabilities: Sendable, Equatable { var hasMaterializedViewsCatalog: Bool { serverVersion >= 90_300 } var hasRangeTypes: Bool { serverVersion >= 90_200 } - var hasJsonBuildObject: Bool { serverVersion >= 90_400 } var hasEnumLabelPlacement: Bool { serverVersion >= 90_100 } /// ADD VALUE IF NOT EXISTS landed in 9.3. With it an add is idempotent, which is what makes /// the driver's one reconnect-and-resend safe for a label that already landed. @@ -28,8 +25,9 @@ struct PostgreSQLCapabilities: Sendable, Equatable { /// Every range gained a companion multirange in 14, with a name the creator may choose. var hasMultirangeTypes: Bool { serverVersion >= 140_000 } var hasForeignTablesCatalog: Bool { serverVersion >= 90_100 } - var hasSequencesCatalog: Bool { serverVersion >= 90_500 } + var hasSequencesCatalog: Bool { serverVersion >= 100_000 } var hasBypassRLS: Bool { serverVersion >= 90_500 } + var hasProcedureKind: Bool { serverVersion >= 110_000 } var hasIdentityColumns: Bool { serverVersion >= 100_000 } var hasGeneratedColumns: Bool { serverVersion >= 120_000 } @@ -39,9 +37,10 @@ struct PostgreSQLCapabilities: Sendable, Equatable { /// Virtual generated columns landed in 18; VIRTUAL is a syntax error on every earlier server. var hasVirtualGeneratedColumns: Bool { serverVersion >= 180_000 } var hasDeclarativePartitioning: Bool { serverVersion >= 100_000 } - - var hasArrayPosition: Bool { serverVersion >= 90_500 } - var hasOrderedAggregates: Bool { serverVersion >= 90_000 } + /// A foreign key that reaches a partitioned table is stored once per partition from PostgreSQL + /// 12, and each clone points at the constraint it was cloned from through `conparentid`, a + /// column that exists from 11. + var hasConstraintParent: Bool { serverVersion >= 110_000 } var hasCollationProvider: Bool { serverVersion >= 100_000 } diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogBoolean.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogBoolean.swift new file mode 100644 index 0000000000..4e1ed30ef8 --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogBoolean.swift @@ -0,0 +1,15 @@ +// +// PostgreSQLCatalogBoolean.swift +// PostgreSQLDriverPlugin +// + +import Foundation + +enum PostgreSQLCatalogBoolean { + private static let trueSpellings: Set = ["t", "true", "yes", "on", "1"] + + static func isTrue(_ text: String?) -> Bool { + guard let text else { return false } + return trueSpellings.contains(text.lowercased()) + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLForeignKeyQueries.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLForeignKeyQueries.swift new file mode 100644 index 0000000000..456773a432 --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLForeignKeyQueries.swift @@ -0,0 +1,88 @@ +// +// PostgreSQLForeignKeyQueries.swift +// PostgreSQLDriverPlugin +// + +import Foundation +import TableProPluginKit + +enum PostgreSQLForeignKeyQueries { + static func foreignKeyList(schema: String, table: String?, capabilities: PostgreSQLCapabilities) -> String { + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(schema) + let tablePredicate = table.map { "\n AND src.relname = \(PostgreSQLObjectQueries.quoteLiteral($0))" } ?? "" + let clonePredicate = capabilities.hasConstraintParent ? """ + + AND NOT EXISTS ( + SELECT 1 + FROM pg_catalog.pg_constraint parent + WHERE parent.oid = c.conparentid + AND parent.conrelid = c.conrelid + ) + """ : "" + return """ + SELECT + src_cl.relname AS table_name, + con.conname, + src_col.attname, + ref_cl.relname AS referenced_table, + ref_col.attname AS referenced_column, + ref_ns.nspname AS referenced_schema, + \(referentialAction("con.confdeltype")) AS delete_rule, + \(referentialAction("con.confupdtype")) AS update_rule + FROM ( + SELECT c.conname, c.conrelid, c.confrelid, c.confdeltype, c.confupdtype, c.conkey, c.confkey, + pg_catalog.generate_subscripts(c.conkey, 1) AS ord + FROM pg_catalog.pg_constraint c + JOIN pg_catalog.pg_class src ON src.oid = c.conrelid + JOIN pg_catalog.pg_namespace ns ON ns.oid = src.relnamespace + WHERE c.contype = 'f' + AND ns.nspname = \(schemaLiteral)\(tablePredicate)\(clonePredicate) + ) con + JOIN pg_catalog.pg_class src_cl ON src_cl.oid = con.conrelid + JOIN pg_catalog.pg_class ref_cl ON ref_cl.oid = con.confrelid + JOIN pg_catalog.pg_namespace ref_ns ON ref_ns.oid = ref_cl.relnamespace + JOIN pg_catalog.pg_attribute src_col + ON src_col.attrelid = con.conrelid AND src_col.attnum = con.conkey[con.ord] + JOIN pg_catalog.pg_attribute ref_col + ON ref_col.attrelid = con.confrelid AND ref_col.attnum = con.confkey[con.ord] + ORDER BY src_cl.relname, con.conname, con.ord + """ + } + + private static func referentialAction(_ column: String) -> String { + """ + CASE \(column) + WHEN 'c' THEN 'CASCADE' + WHEN 'n' THEN 'SET NULL' + WHEN 'd' THEN 'SET DEFAULT' + WHEN 'r' THEN 'RESTRICT' + ELSE 'NO ACTION' + END + """ + } +} + +struct PostgreSQLForeignKeyRow { + let table: String + let foreignKey: PluginForeignKeyInfo + + init?(_ row: [PluginCellValue]) { + guard row.count >= 8, + let table = row[0].asText, + let name = row[1].asText, + let column = row[2].asText, + let referencedTable = row[3].asText, + let referencedColumn = row[4].asText + else { return nil } + self.table = table + self.foreignKey = PluginForeignKeyInfo( + name: name, + column: column, + referencedTable: referencedTable, + referencedColumn: referencedColumn, + referencedSchema: row[5].asText, + onDelete: row[6].asText ?? "NO ACTION", + onUpdate: row[7].asText ?? "NO ACTION" + ) + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLIndexQueries.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLIndexQueries.swift new file mode 100644 index 0000000000..81e44ce28b --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLIndexQueries.swift @@ -0,0 +1,54 @@ +// +// PostgreSQLIndexQueries.swift +// PostgreSQLDriverPlugin +// + +import Foundation +import TableProPluginKit + +enum PostgreSQLIndexQueries { + static func indexList(schema: String, table: String?) -> String { + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(schema) + let tablePredicate = table.map { " AND t.relname = \(PostgreSQLObjectQueries.quoteLiteral($0))" } ?? "" + return """ + SELECT + t.relname AS table_name, + i.relname AS index_name, + ARRAY_AGG(a.attname ORDER BY ( + SELECT min(k) + FROM pg_catalog.generate_subscripts(ix.indkey, 1) AS k + WHERE ix.indkey[k] = a.attnum + ))::text AS columns, + ix.indisunique AS is_unique, + ix.indisprimary AS is_primary, + am.amname AS index_type, + pg_catalog.pg_get_expr(ix.indpred, ix.indrelid) AS predicate + FROM pg_catalog.pg_index ix + JOIN pg_catalog.pg_class i ON i.oid = ix.indexrelid + JOIN pg_catalog.pg_class t ON t.oid = ix.indrelid + JOIN pg_catalog.pg_namespace n ON n.oid = t.relnamespace + JOIN pg_catalog.pg_am am ON am.oid = i.relam + JOIN pg_catalog.pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey) + WHERE n.nspname = \(schemaLiteral)\(tablePredicate) + GROUP BY t.relname, i.relname, ix.indisunique, ix.indisprimary, am.amname, ix.indpred, ix.indrelid + ORDER BY t.relname, ix.indisprimary DESC, i.relname + """ + } +} + +enum PostgreSQLIndexRow { + static func index(from row: [PluginCellValue]) -> (table: String, index: PluginIndexInfo)? { + guard let table = row[safe: 0]?.asText, + let name = row[safe: 1]?.asText, + let columnsText = row[safe: 2]?.asText else { return nil } + let index = PluginIndexInfo( + name: name, + columns: PostgreSQLTextArray.values(columnsText), + isUnique: PostgreSQLCatalogBoolean.isTrue(row[safe: 3]?.asText), + isPrimary: PostgreSQLCatalogBoolean.isTrue(row[safe: 4]?.asText), + type: row[safe: 5]?.asText?.uppercased() ?? "BTREE", + whereClause: row[safe: 6]?.asText + ) + return (table, index) + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift index 80af3410f0..2ef04833a5 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift @@ -34,16 +34,6 @@ public enum PostgreSQLObjectQueries { "\(quoteIdentifier(schema)).\(quoteIdentifier(name))" } - /// `prokind` arrived in PostgreSQL 11, which is also the first release with procedures. - public static let prokindMinimumServerVersion: Int32 = 110_000 - - /// libpq answers 0 for a handle it has not connected, so an unknown version has to read as - /// modern. Reading it as ancient emits `proisagg`, a column PostgreSQL 11 removed, and the - /// whole routine list fails on every current server. - public static func usesProkind(serverVersionNumber: Int32) -> Bool { - serverVersionNumber <= 0 || serverVersionNumber >= prokindMinimumServerVersion - } - /// Reads pg_proc rather than information_schema.routines. information_schema shows only what /// the current user has a privilege on, and its routine_name repeats across overloads with no /// column that separates them; pg_proc has one row per routine and an oid that does. @@ -51,9 +41,9 @@ public enum PostgreSQLObjectQueries { /// Aggregates (prokind 'a') and window functions ('w') are excluded because /// pg_get_functiondef raises on them, which would fail the whole listing over one object the /// viewer could not have shown anyway. - public static func routineList(schema: String, serverVersionNumber: Int32) -> String { + static func routineList(schema: String, capabilities: PostgreSQLCapabilities) -> String { let schemaLiteral = quoteLiteral(schema) - let modern = usesProkind(serverVersionNumber: serverVersionNumber) + let modern = capabilities.hasProcedureKind let kindColumn = modern ? "p.prokind" : "CASE WHEN p.proisagg THEN 'a' WHEN p.proiswindow THEN 'w' ELSE 'f' END" @@ -124,12 +114,12 @@ public enum PostgreSQLObjectQueries { CASE WHEN (t.tgtype & 64) != 0 THEN 'INSTEAD OF' WHEN (t.tgtype & 2) != 0 THEN 'BEFORE' ELSE 'AFTER' END AS timing, - array_to_string(array_remove(ARRAY[ + concat_ws(' OR ', CASE WHEN (t.tgtype & 4) != 0 THEN 'INSERT' END, CASE WHEN (t.tgtype & 8) != 0 THEN 'DELETE' END, CASE WHEN (t.tgtype & 16) != 0 THEN 'UPDATE' END, CASE WHEN (t.tgtype & 32) != 0 THEN 'TRUNCATE' END - ], NULL), ' OR ') AS event, + ) AS event, CASE WHEN (t.tgtype & 1) != 0 THEN 'ROW' ELSE 'STATEMENT' END AS orientation, t.tgenabled <> 'D' AS enabled, pg_catalog.pg_get_triggerdef(t.oid) AS definition, @@ -155,26 +145,14 @@ public enum PostgreSQLObjectQueries { /// /// A listing names a schema; a reload names an oid and no schema, because a type keeps its oid /// when it is moved. Naming neither would list the whole database, so a caller passes one. - public static func userDefinedTypeList(schema: String?, identity: String?, serverVersionNumber: Int32) -> String { - let capabilities = PostgreSQLCapabilities.assumingModernWhenUnknown(serverVersionNumber) + static func userDefinedTypeList(schema: String?, identity: String?, capabilities: PostgreSQLCapabilities) -> String { let schemaPredicate = schema.map { "AND n.nspname = \(quoteLiteral($0))" } ?? "" let identityPredicate = identity.flatMap { UInt32($0) }.map { "AND t.oid = \($0)::oid" } ?? "" let kinds = capabilities.hasRangeTypes ? "('e', 'c', 'd', 'r')" : "('e', 'c', 'd')" - let fields = capabilities.hasJsonBuildObject ? """ - (SELECT json_agg(json_build_object( - 'name', a.attname, - 'type', pg_catalog.format_type(a.atttypid, a.atttypmod), - 'collation', CASE WHEN a.attcollation <> 0 AND a.attcollation <> ty.typcollation - THEN \(collationName("a.attcollation")) END) ORDER BY a.attnum) - FROM pg_catalog.pg_attribute a - JOIN pg_catalog.pg_type ty ON ty.oid = a.atttypid - WHERE a.attrelid = t.typrelid AND a.attnum > 0 AND NOT a.attisdropped)::text - """ : "NULL::text" - let constraints = capabilities.hasJsonBuildObject ? """ - (SELECT json_agg(json_build_object('name', con.conname, 'definition', pg_catalog.pg_get_constraintdef(con.oid)) ORDER BY con.conname) - FROM pg_catalog.pg_constraint con - WHERE con.contypid = t.oid AND con.contype = 'c')::text - """ : "NULL::text" + let fieldCollation = """ + CASE WHEN a.attcollation <> 0 AND a.attcollation <> ty.typcollation + THEN \(collationName("a.attcollation")) END + """ let rangeJoin = capabilities.hasRangeTypes ? "LEFT JOIN pg_catalog.pg_range r ON r.rngtypid = t.oid" : "" let rangeSubtype = capabilities.hasRangeTypes ? "CASE WHEN t.typtype = 'r' THEN pg_catalog.format_type(r.rngsubtype, NULL) END" @@ -215,9 +193,11 @@ public enum PostgreSQLObjectQueries { t.typtype::text AS kind, pg_catalog.pg_get_userbyid(t.typowner) AS owner, pg_catalog.obj_description(t.oid, 'pg_type') AS comment, - (SELECT json_agg(e.enumlabel ORDER BY e.enumsortorder) + (SELECT array_agg(e.enumlabel ORDER BY e.enumsortorder) FROM pg_catalog.pg_enum e WHERE e.enumtypid = t.oid)::text AS enum_labels, - \(fields) AS fields, + \(compositeFieldArray("a.attname")) AS field_names, + \(compositeFieldArray("pg_catalog.format_type(a.atttypid, a.atttypmod)")) AS field_types, + \(compositeFieldArray(fieldCollation, joinsType: true)) AS field_collations, CASE WHEN t.typtype = 'd' THEN pg_catalog.format_type(t.typbasetype, t.typtypmod) END AS base_type, CASE WHEN t.typtype = 'd' AND t.typcollation <> 0 AND t.typcollation <> (SELECT b.typcollation FROM pg_catalog.pg_type b WHERE b.oid = t.typbasetype) @@ -225,7 +205,8 @@ public enum PostgreSQLObjectQueries { END AS collation, t.typnotnull::text AS not_null, t.typdefault AS default_value, - \(constraints) AS constraints, + \(domainCheckArray("con.conname")) AS constraint_names, + \(domainCheckArray("pg_catalog.pg_get_constraintdef(con.oid)")) AS constraint_definitions, \(rangeSubtype) AS range_subtype, \(rangeCanonical) AS range_canonical, \(rangeSubtypeDiff) AS range_subtype_diff, @@ -249,6 +230,25 @@ public enum PostgreSQLObjectQueries { """ } + /// The three field arrays are zipped by position, so each one orders by `attnum` over exactly + /// the same rows. Only the collation expression reads `pg_type`, and it joins it itself. + private static func compositeFieldArray(_ expression: String, joinsType: Bool = false) -> String { + let typeJoin = joinsType ? "\n JOIN pg_catalog.pg_type ty ON ty.oid = a.atttypid" : "" + return """ + (SELECT array_agg(\(expression) ORDER BY a.attnum) + FROM pg_catalog.pg_attribute a\(typeJoin) + WHERE a.attrelid = t.typrelid AND a.attnum > 0 AND NOT a.attisdropped)::text + """ + } + + private static func domainCheckArray(_ expression: String) -> String { + """ + (SELECT array_agg(\(expression) ORDER BY con.conname) + FROM pg_catalog.pg_constraint con + WHERE con.contypid = t.oid AND con.contype = 'c')::text + """ + } + /// The qualified, quoted name of a collation oid, spelled the way a COLLATE clause takes it. private static func collationName(_ oidExpression: String) -> String { """ diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+BulkMetadata.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+BulkMetadata.swift index 6ed075d857..bc49f251a6 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+BulkMetadata.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+BulkMetadata.swift @@ -21,36 +21,13 @@ extension PostgreSQLPluginDriver { var providesBulkIndexFetch: Bool { true } func fetchAllIndexes(schema: String?) async throws -> [String: [PluginIndexInfo]] { - let schemaLiteral = escapeLiteral(schema ?? core.currentSchema) - let columnOrdering = versionedCapabilities.hasArrayPosition - ? "ORDER BY array_position(ix.indkey, a.attnum)" - : "ORDER BY a.attnum" - let query = """ - SELECT - t.relname AS table_name, - i.relname AS index_name, - ARRAY_AGG(a.attname \(columnOrdering)) AS columns, - ix.indisunique AS is_unique, - ix.indisprimary AS is_primary, - am.amname AS index_type, - pg_get_expr(ix.indpred, ix.indrelid) AS predicate - FROM pg_index ix - JOIN pg_class i ON i.oid = ix.indexrelid - JOIN pg_class t ON t.oid = ix.indrelid - JOIN pg_namespace n ON n.oid = t.relnamespace - JOIN pg_am am ON am.oid = i.relam - JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey) - WHERE n.nspname = '\(schemaLiteral)' - GROUP BY t.relname, i.relname, ix.indisunique, ix.indisprimary, am.amname, ix.indpred, ix.indrelid - ORDER BY t.relname, ix.indisprimary DESC, i.relname - """ + let query = PostgreSQLIndexQueries.indexList(schema: schema ?? core.currentSchema, table: nil) let result = try await execute(query: query) var indexes: [String: [PluginIndexInfo]] = [:] for row in result.rows { - guard row.count >= 6, let table = row[0].asText, - let index = PostgreSQLIndexRow.index(from: row) else { continue } - indexes[table, default: []].append(index) + guard let decoded = PostgreSQLIndexRow.index(from: row) else { continue } + indexes[decoded.table, default: []].append(decoded.index) } return indexes } @@ -91,24 +68,3 @@ extension PostgreSQLPluginDriver { return metadata } } - -enum PostgreSQLIndexRow { - /// The shared shaping for a `pg_index` row, so the per-table and whole-schema reads cannot - /// disagree about how an index is named, ordered or typed. The row's first field is the table - /// name in the bulk form and the index name in the per-table form, so the offset is passed in. - static func index(from row: [PluginCellValue], offset: Int = 1) -> PluginIndexInfo? { - guard let name = row[safe: offset]?.asText, - let columnsText = row[safe: offset + 1]?.asText else { return nil } - let columns = columnsText - .trimmingCharacters(in: CharacterSet(charactersIn: "{}")) - .components(separatedBy: ",") - return PluginIndexInfo( - name: name, - columns: columns, - isUnique: row[safe: offset + 2]?.asText == "t", - isPrimary: row[safe: offset + 3]?.asText == "t", - type: row[safe: offset + 4]?.asText?.uppercased() ?? "BTREE", - whereClause: row[safe: offset + 5]?.asText - ) - } -} diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+ColumnReorder.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+ColumnReorder.swift index 399a4b5b47..a312bad9c3 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+ColumnReorder.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+ColumnReorder.swift @@ -192,9 +192,9 @@ extension PostgreSQLPluginDriver { guard let name = row[safe: 0]?.asText, let definition = row[safe: 1]?.asText else { continue } parts.columnNames.append(name) parts.columnDefinitions[name] = definition - if isTrue(row[safe: 2]?.asText) { parts.identityColumns.append(name) } + if PostgreSQLCatalogBoolean.isTrue(row[safe: 2]?.asText) { parts.identityColumns.append(name) } /// A generated column is computed, never written, so `INSERT` refuses it by name. - if !isTrue(row[safe: 3]?.asText) { parts.copyableColumns.append(name) } + if !PostgreSQLCatalogBoolean.isTrue(row[safe: 3]?.asText) { parts.copyableColumns.append(name) } } /// Named, and added after the staging table is gone. Declared inline instead, PostgreSQL @@ -345,11 +345,4 @@ extension PostgreSQLPluginDriver { private func textRows(_ query: String) async throws -> [String] { try await execute(query: query).rows.compactMap { $0[safe: 0]?.asText } } - - /// libpq reports a boolean as `t` on the text protocol and the driver may hand it back either - /// way, so both spellings are accepted rather than one being assumed. - private func isTrue(_ value: String?) -> Bool { - guard let value else { return false } - return value == "t" || value.lowercased() == "true" - } } diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift index 11ace592c8..2e49910fb8 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift @@ -43,23 +43,18 @@ extension PostgreSQLPluginDriver { func fetchCheckConstraints(table: String, schema: String?) async throws -> [PluginCheckConstraintInfo] { let query = PostgreSQLSchemaQueries.checkConstraintsQuery( - schemaLiteral: escapeStringLiteral(schema ?? core.currentSchema), - tableLiteral: escapeStringLiteral(table) + schema: schema ?? core.currentSchema, + table: table ) let result = try await execute(query: query) return result.rows.compactMap { row in guard let name = row[safe: 0]?.asText, let definition = row[safe: 1]?.asText else { return nil } - // JSON rather than a comma-joined string: a quoted PostgreSQL identifier may itself - // contain a comma, which splitting would turn into two column names. - let columns = (row[safe: 3]?.asText?.nilIfEmpty) - .flatMap { $0.data(using: .utf8) } - .flatMap { try? JSONDecoder().decode([String].self, from: $0) } ?? [] return PluginCheckConstraintInfo( name: name, expression: PostgreSQLCheckConstraintDefinition.expression(fromConstraintDef: definition), - columns: columns, - isValidated: row[safe: 2]?.asText?.lowercased() != "f" + columns: PostgreSQLTextArray.values(row[safe: 3]?.asText), + isValidated: PostgreSQLCatalogBoolean.isTrue(row[safe: 2]?.asText) ) } } diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Principals.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Principals.swift index bc7c32c1ca..c4aee02f1b 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Principals.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Principals.swift @@ -49,7 +49,7 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { return result.rows.compactMap { row -> PluginPrincipalInfo? in guard let name = row[safe: 0]?.asText else { return nil } - let canLogin = Self.decodeBoolean(row[safe: 1]?.asText) + let canLogin = PostgreSQLCatalogBoolean.isTrue(row[safe: 1]?.asText) let attributes = Self.decodeAttributes(row: row) let connectionLimit = row[safe: 8]?.asText.flatMap(Int.init) @@ -152,7 +152,7 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { return PluginGrantInfo( privilege: privilege, scope: .column(database: database, schema: schema, table: table, column: column), - isGrantable: Self.decodeBoolean(row[safe: 4]?.asText) + isGrantable: PostgreSQLCatalogBoolean.isTrue(row[safe: 4]?.asText) ) } } @@ -168,7 +168,7 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { roleLiteral: escapeStringLiteral(principal.name) ) let result = try await execute(query: query) - return Self.decodeBoolean(result.rows.first?[safe: 0]?.asText) + return PostgreSQLCatalogBoolean.isTrue(result.rows.first?[safe: 0]?.asText) } private func fetchMemberships() async throws -> [String: [String]] { @@ -196,7 +196,7 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { return PluginGrantInfo( privilege: privilege, scope: .database(database), - isGrantable: Self.decodeBoolean(row[safe: 2]?.asText) + isGrantable: PostgreSQLCatalogBoolean.isTrue(row[safe: 2]?.asText) ) } } @@ -210,7 +210,7 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { return PluginGrantInfo( privilege: privilege, scope: .schema(database: database, schema: schema), - isGrantable: Self.decodeBoolean(row[safe: 2]?.asText) + isGrantable: PostgreSQLCatalogBoolean.isTrue(row[safe: 2]?.asText) ) } } @@ -225,7 +225,7 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { return PluginGrantInfo( privilege: privilege, scope: .table(database: database, schema: schema, table: table), - isGrantable: Self.decodeBoolean(row[safe: 3]?.asText) + isGrantable: PostgreSQLCatalogBoolean.isTrue(row[safe: 3]?.asText) ) } } @@ -243,13 +243,8 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { PluginPrincipalAttribute( key: attribute.rawValue, label: attribute.label, - isEnabled: decodeBoolean(row[safe: offset]?.asText) + isEnabled: PostgreSQLCatalogBoolean.isTrue(row[safe: offset]?.asText) ) } } - - private static func decodeBoolean(_ value: String?) -> Bool { - guard let value else { return false } - return value == "t" || value == "true" || value == "1" - } } diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Routines.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Routines.swift index d2d49a526a..991e30a951 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Routines.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Routines.swift @@ -11,7 +11,7 @@ extension PostgreSQLPluginDriver { let resolvedSchema = schema ?? currentSchema ?? "public" let query = PostgreSQLObjectQueries.routineList( schema: resolvedSchema, - serverVersionNumber: serverVersionNumber + capabilities: catalogCapabilities ) let result = try await execute(query: query) return result.rows.compactMap { row -> PluginRoutineInfo? in @@ -89,7 +89,7 @@ extension PostgreSQLPluginDriver { orientation: row[safe: 5]?.asText, statement: definition, definition: definition, - enabled: row[safe: 6]?.asText == "t", + enabled: PostgreSQLCatalogBoolean.isTrue(row[safe: 6]?.asText), attributes: attributes ) } diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Sequences.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Sequences.swift new file mode 100644 index 0000000000..9a0c428aa9 --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Sequences.swift @@ -0,0 +1,54 @@ +// +// PostgreSQLPluginDriver+Sequences.swift +// PostgreSQLDriverPlugin +// + +import Foundation +import os +import TableProPluginKit + +extension PostgreSQLPluginDriver { + static let sequenceLogger = Logger(subsystem: "com.TablePro.PostgreSQLDriver", category: "Sequences") + + func fetchDependentSequences(table: String, schema: String?) async throws -> [(name: String, ddl: String)] { + let definitions = try await sequenceDefinitions(schema: schema ?? core.currentSchema, dependentOnTable: table) + return definitions.map { (name: $0.name, ddl: $0.ddl) } + } + + func fetchSequences(schema: String?) async throws -> [PluginSequenceInfo] { + let schemaName = schema ?? core.currentSchema + let definitions = try await sequenceDefinitions(schema: schemaName, dependentOnTable: nil) + return definitions.map { PluginSequenceInfo(name: $0.name, ddl: $0.ddl, schema: schemaName) } + } + + private func sequenceDefinitions( + schema: String, + dependentOnTable table: String? + ) async throws -> [PostgreSQLSequenceDefinition] { + let source = PostgreSQLSequenceQueries.source(hasSequencesCatalog: includesSequencesCatalog()) + let listing = try await execute( + query: PostgreSQLSequenceQueries.sequenceList(schema: schema, dependentOnTable: table, source: source) + ) + var definitions: [PostgreSQLSequenceDefinition] = [] + for definition in PostgreSQLSequenceQueries.definitions(from: listing.rows) { + guard definition.needsLastValueRead else { + definitions.append(definition) + continue + } + definitions.append(definition.withLastValue(await lastValue(schema: schema, sequence: definition.name))) + } + return definitions + } + + private func lastValue(schema: String, sequence: String) async -> String? { + do { + let query = PostgreSQLSequenceQueries.lastValue(schema: schema, sequence: sequence) + return try await execute(query: query).rows.first?[safe: 0]?.asText + } catch { + Self.sequenceLogger.debug( + "Sequence last value unavailable for \(sequence, privacy: .public): \(error.localizedDescription)" + ) + return nil + } + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Types.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Types.swift index 121ed60f43..792316dac9 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Types.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Types.swift @@ -12,7 +12,7 @@ extension PostgreSQLPluginDriver { let query = PostgreSQLObjectQueries.userDefinedTypeList( schema: resolvedSchema, identity: nil, - serverVersionNumber: serverVersionNumber + capabilities: catalogCapabilities ) let result = try await execute(query: query) return result.rows @@ -30,7 +30,7 @@ extension PostgreSQLPluginDriver { let query = PostgreSQLObjectQueries.userDefinedTypeList( schema: nil, identity: String(oid), - serverVersionNumber: serverVersionNumber + capabilities: catalogCapabilities ) let result = try await execute(query: query) let match = result.rows @@ -43,7 +43,7 @@ extension PostgreSQLPluginDriver { let query = PostgreSQLObjectQueries.userDefinedTypeList( schema: resolvedSchema, identity: nil, - serverVersionNumber: serverVersionNumber + capabilities: catalogCapabilities ) let result = try await execute(query: query) let match = result.rows diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift index 62322c1d18..61a8a0bd42 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift @@ -24,6 +24,9 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { var versionedCapabilities: PostgreSQLCapabilities { PostgreSQLCapabilities(serverVersion: core.serverVersionNumber) } + var catalogCapabilities: PostgreSQLCapabilities { + .assumingModernWhenUnknown(core.serverVersionNumber) + } var capabilities: PluginCapabilities { [ @@ -71,13 +74,14 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { private func probePostgisOids() async { do { let result = try await core.execute(query: PostGISSpatialRewrite.probeQuery) - var map: [UInt32: String] = [:] + var map: [UInt32: PostGISType] = [:] for row in result.rows { - guard row.count >= 2, + guard row.count >= 3, let oidText = row[0].asText, let oid = UInt32(oidText), - let typname = row[1].asText else { continue } - map[oid] = typname + let typname = row[1].asText, + let schema = row[2].asText else { continue } + map[oid] = PostGISType(name: typname, schema: schema) } core.setPostgisOidMap(map) } catch { @@ -93,7 +97,7 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { catalogPresence?.hasForeignTables ?? versionedCapabilities.hasForeignTablesCatalog } - private func includesSequencesCatalog() -> Bool { + func includesSequencesCatalog() -> Bool { catalogPresence?.hasSequences ?? versionedCapabilities.hasSequencesCatalog } @@ -164,10 +168,10 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { // MARK: - Schema func fetchTables(schema: String?) async throws -> [PluginTableInfo] { - let schemaLiteral = escapeLiteral(schema ?? core.currentSchema) + let schemaName = schema ?? core.currentSchema func query(_ attempt: PostgreSQLTableListingAttempt) -> String { PostgreSQLSchemaQueries.fetchTables( - schemaLiteral: schemaLiteral, + schema: schemaName, includeMaterializedViews: attempt.includeOptionalCatalogs && includesMaterializedViews(), includeForeignTables: attempt.includeOptionalCatalogs && includesForeignTables(), includeComments: attempt.includeComments, @@ -229,90 +233,19 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { /// schemas holding a table of the same name returned each other's indexes merged into one list, /// which a comparison between those two schemas reports as neither side differing. func fetchIndexes(table: String, schema: String?) async throws -> [PluginIndexInfo] { - let schemaLiteral = escapeLiteral(schema ?? core.currentSchema) - let columnOrdering = versionedCapabilities.hasArrayPosition - ? "ORDER BY array_position(ix.indkey, a.attnum)" - : "ORDER BY a.attnum" - let query = """ - SELECT - i.relname AS index_name, - ARRAY_AGG(a.attname \(columnOrdering)) AS columns, - ix.indisunique AS is_unique, - ix.indisprimary AS is_primary, - am.amname AS index_type, - pg_get_expr(ix.indpred, ix.indrelid) AS predicate - FROM pg_index ix - JOIN pg_class i ON i.oid = ix.indexrelid - JOIN pg_class t ON t.oid = ix.indrelid - JOIN pg_namespace n ON n.oid = t.relnamespace - JOIN pg_am am ON am.oid = i.relam - JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey) - WHERE t.relname = '\(escapeLiteral(table))' AND n.nspname = '\(schemaLiteral)' - GROUP BY i.relname, ix.indisunique, ix.indisprimary, am.amname, ix.indpred, ix.indrelid - ORDER BY ix.indisprimary DESC, i.relname - """ + let query = PostgreSQLIndexQueries.indexList(schema: schema ?? core.currentSchema, table: table) let result = try await execute(query: query) - return result.rows.compactMap { PostgreSQLIndexRow.index(from: $0, offset: 0) } + return result.rows.compactMap { PostgreSQLIndexRow.index(from: $0)?.index } } func fetchForeignKeys(table: String, schema: String?) async throws -> [PluginForeignKeyInfo] { - let schemaLiteral = escapeLiteral(schema ?? core.currentSchema) - let query = """ - SELECT - con.conname, - src_col.attname, - ref_cl.relname AS referenced_table, - ref_col.attname AS referenced_column, - ref_ns.nspname AS referenced_schema, - CASE con.confdeltype - WHEN 'c' THEN 'CASCADE' - WHEN 'n' THEN 'SET NULL' - WHEN 'd' THEN 'SET DEFAULT' - WHEN 'r' THEN 'RESTRICT' - ELSE 'NO ACTION' - END AS delete_rule, - CASE con.confupdtype - WHEN 'c' THEN 'CASCADE' - WHEN 'n' THEN 'SET NULL' - WHEN 'd' THEN 'SET DEFAULT' - WHEN 'r' THEN 'RESTRICT' - ELSE 'NO ACTION' - END AS update_rule - FROM pg_catalog.pg_constraint con - JOIN pg_catalog.pg_class src_cl ON src_cl.oid = con.conrelid - JOIN pg_catalog.pg_namespace src_ns ON src_ns.oid = src_cl.relnamespace - JOIN pg_catalog.pg_class ref_cl ON ref_cl.oid = con.confrelid - JOIN pg_catalog.pg_namespace ref_ns ON ref_ns.oid = ref_cl.relnamespace - CROSS JOIN LATERAL unnest(con.conkey, con.confkey) - WITH ORDINALITY AS cols(src_attnum, ref_attnum, ord) - JOIN pg_catalog.pg_attribute src_col - ON src_col.attrelid = con.conrelid AND src_col.attnum = cols.src_attnum - JOIN pg_catalog.pg_attribute ref_col - ON ref_col.attrelid = con.confrelid AND ref_col.attnum = cols.ref_attnum - WHERE con.contype = 'f' - AND src_cl.relname = '\(escapeLiteral(table))' - AND src_ns.nspname = '\(schemaLiteral)' - ORDER BY con.conname, cols.ord - """ + let resolvedSchema = schema ?? core.currentSchema + let query = PostgreSQLForeignKeyQueries.foreignKeyList( + schema: resolvedSchema, table: table, capabilities: catalogCapabilities + ) let result = try await execute(query: query) - let foreignKeys: [PluginForeignKeyInfo] = result.rows.compactMap { row -> PluginForeignKeyInfo? in - guard row.count >= 7, - let name = row[0].asText, - let column = row[1].asText, - let refTable = row[2].asText, - let refColumn = row[3].asText - else { return nil } - return PluginForeignKeyInfo( - name: name, - column: column, - referencedTable: refTable, - referencedColumn: refColumn, - referencedSchema: row[4].asText, - onDelete: row[5].asText ?? "NO ACTION", - onUpdate: row[6].asText ?? "NO ACTION" - ) - } - Self.logger.info("[fk] postgres fetchForeignKeys schema=\(schema ?? self.core.currentSchema, privacy: .public) table=\(table, privacy: .public) rows=\(result.rows.count) parsed=\(foreignKeys.count)") + let foreignKeys = result.rows.compactMap { PostgreSQLForeignKeyRow($0)?.foreignKey } + Self.logger.info("[fk] postgres fetchForeignKeys schema=\(resolvedSchema, privacy: .public) table=\(table, privacy: .public) rows=\(result.rows.count) parsed=\(foreignKeys.count)") return foreignKeys } @@ -409,64 +342,14 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { var providesBulkForeignKeyFetch: Bool { true } func fetchAllForeignKeys(schema: String?) async throws -> [String: [PluginForeignKeyInfo]] { - let schemaLiteral = escapeLiteral(schema ?? core.currentSchema) - let query = """ - SELECT - src_cl.relname AS table_name, - con.conname, - src_col.attname, - ref_cl.relname AS referenced_table, - ref_col.attname AS referenced_column, - ref_ns.nspname AS referenced_schema, - CASE con.confdeltype - WHEN 'c' THEN 'CASCADE' - WHEN 'n' THEN 'SET NULL' - WHEN 'd' THEN 'SET DEFAULT' - WHEN 'r' THEN 'RESTRICT' - ELSE 'NO ACTION' - END AS delete_rule, - CASE con.confupdtype - WHEN 'c' THEN 'CASCADE' - WHEN 'n' THEN 'SET NULL' - WHEN 'd' THEN 'SET DEFAULT' - WHEN 'r' THEN 'RESTRICT' - ELSE 'NO ACTION' - END AS update_rule - FROM pg_catalog.pg_constraint con - JOIN pg_catalog.pg_class src_cl ON src_cl.oid = con.conrelid - JOIN pg_catalog.pg_namespace src_ns ON src_ns.oid = src_cl.relnamespace - JOIN pg_catalog.pg_class ref_cl ON ref_cl.oid = con.confrelid - JOIN pg_catalog.pg_namespace ref_ns ON ref_ns.oid = ref_cl.relnamespace - CROSS JOIN LATERAL unnest(con.conkey, con.confkey) - WITH ORDINALITY AS cols(src_attnum, ref_attnum, ord) - JOIN pg_catalog.pg_attribute src_col - ON src_col.attrelid = con.conrelid AND src_col.attnum = cols.src_attnum - JOIN pg_catalog.pg_attribute ref_col - ON ref_col.attrelid = con.confrelid AND ref_col.attnum = cols.ref_attnum - WHERE con.contype = 'f' - AND src_ns.nspname = '\(schemaLiteral)' - ORDER BY src_cl.relname, con.conname, cols.ord - """ + let query = PostgreSQLForeignKeyQueries.foreignKeyList( + schema: schema ?? core.currentSchema, table: nil, capabilities: catalogCapabilities + ) let result = try await execute(query: query) var grouped: [String: [PluginForeignKeyInfo]] = [:] for row in result.rows { - guard row.count >= 8, - let tableName = row[0].asText, - let name = row[1].asText, - let column = row[2].asText, - let refTable = row[3].asText, - let refColumn = row[4].asText - else { continue } - let fk = PluginForeignKeyInfo( - name: name, - column: column, - referencedTable: refTable, - referencedColumn: refColumn, - referencedSchema: row[5].asText, - onDelete: row[6].asText ?? "NO ACTION", - onUpdate: row[7].asText ?? "NO ACTION" - ) - grouped[tableName, default: []].append(fk) + guard let decoded = PostgreSQLForeignKeyRow(row) else { continue } + grouped[decoded.table, default: []].append(decoded.foreignKey) } return grouped } @@ -718,7 +601,7 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { let schemaLiteral = escapeLiteral(schema ?? core.currentSchema) let query = """ SELECT DISTINCT t.typname, - array_agg(e.enumlabel ORDER BY e.enumsortorder) + array_agg(e.enumlabel ORDER BY e.enumsortorder)::text FROM pg_attribute a JOIN pg_class c ON c.oid = a.attrelid JOIN pg_namespace n ON n.oid = c.relnamespace @@ -735,105 +618,7 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { let result = try await execute(query: query) return result.rows.compactMap { row -> (name: String, labels: [String])? in guard let typeName = row[0].asText, let labelsStr = row[1].asText else { return nil } - let labels = labelsStr - .trimmingCharacters(in: CharacterSet(charactersIn: "{}")) - .components(separatedBy: ",") - return (name: typeName, labels: labels) - } - } - - func fetchDependentSequences(table: String, schema: String?) async throws -> [(name: String, ddl: String)] { - guard includesSequencesCatalog() else { return [] } - let safeTable = escapeLiteral(table) - let schemaName = schema ?? core.currentSchema - let schemaLiteral = escapeLiteral(schemaName) - let query = """ - SELECT s.sequencename, - s.start_value, - s.min_value, - s.max_value, - s.increment_by, - s.cycle, - s.last_value - FROM pg_attrdef ad - JOIN pg_class c ON c.oid = ad.adrelid - JOIN pg_namespace n ON n.oid = c.relnamespace - JOIN pg_sequences s ON s.schemaname = n.nspname - AND pg_get_expr(ad.adbin, ad.adrelid) LIKE '%' || quote_ident(s.sequencename) || '%' - WHERE c.relname = '\(safeTable)' - AND n.nspname = '\(schemaLiteral)' - AND c.relkind IN \(Self.relkindsCreatedByTableDDL) - AND pg_get_expr(ad.adbin, ad.adrelid) LIKE '%nextval%' - """ - let result = try await execute(query: query) - return result.rows.compactMap { row -> (name: String, ddl: String)? in - guard let seqName = row[0].asText else { return nil } - let startVal = row[1].asText ?? "1" - let minVal = row[2].asText ?? "1" - let maxVal = row[3].asText ?? "9223372036854775807" - let incrementBy = row[4].asText ?? "1" - let cycle = row[5].asText == "t" ? " CYCLE" : "" - let lastValue = row.count > 6 ? row[6].asText : nil - let quotedSeqName = quoteIdentifier(seqName) - let escapedSeqForLiteral = escapeStringLiteral(seqName) - var ddl = "CREATE SEQUENCE \(quotedSeqName) INCREMENT BY \(incrementBy)" - + " MINVALUE \(minVal) MAXVALUE \(maxVal)" - + " START WITH \(startVal)\(cycle);" - /// Unqualified, so it names the sequence the line above created rather than the one it - /// was read from. `setval` takes a `regclass`, which resolves through `search_path`, and - /// the `CREATE SEQUENCE` beside it is already schema-relative. Spelling the source's own - /// schema here made the pair disagree: run against another schema it repositioned the - /// original sequence, and against another database it named one that was not there. - if let last = lastValue, !last.isEmpty, Int64(last) != nil { - ddl += "\nSELECT pg_catalog.setval('\"\(escapedSeqForLiteral)\"', \(last), true);" - } - return (name: seqName, ddl: ddl) - } - } - - /// Every sequence in the schema, including the ones no column defaults from. - /// - /// `fetchDependentSequences` answers only those a table's `nextval` default reaches, which is - /// what a table dump needs. A sequence a routine or the application advances by hand belongs to - /// nothing, so it is invisible to that query and a dump built only from it restores a database - /// whose sequence is gone. - func fetchSequences(schema: String?) async throws -> [PluginSequenceInfo] { - guard includesSequencesCatalog() else { return [] } - let schemaName = schema ?? core.currentSchema - let schemaLiteral = escapeLiteral(schemaName) - let query = """ - SELECT s.sequencename, - s.start_value, - s.min_value, - s.max_value, - s.increment_by, - s.cycle, - s.last_value, - d.refobjid IS NOT NULL AS owned - FROM pg_sequences s - JOIN pg_class c ON c.relname = s.sequencename - JOIN pg_namespace n ON n.oid = c.relnamespace AND n.nspname = s.schemaname - LEFT JOIN pg_depend d ON d.objid = c.oid AND d.deptype = 'a' - WHERE s.schemaname = '\(schemaLiteral)' - ORDER BY s.sequencename - """ - let result = try await execute(query: query) - return result.rows.compactMap { row -> PluginSequenceInfo? in - guard let name = row[0].asText else { return nil } - let start = row[1].asText ?? "1" - let minValue = row[2].asText ?? "1" - let maxValue = row[3].asText ?? "9223372036854775807" - let increment = row[4].asText ?? "1" - let cycle = row[5].asText == "t" ? " CYCLE" : "" - let lastValue = row.count > 6 ? row[6].asText : nil - let quoted = quoteIdentifier(name) - var ddl = "CREATE SEQUENCE \(quoted) INCREMENT BY \(increment)" - + " MINVALUE \(minValue) MAXVALUE \(maxValue)" - + " START WITH \(start)\(cycle);" - if let last = lastValue, !last.isEmpty, Int64(last) != nil { - ddl += "\nSELECT pg_catalog.setval('\"\(escapeStringLiteral(name))\"', \(last), true);" - } - return PluginSequenceInfo(name: name, ddl: ddl, schema: schemaName) + return (name: typeName, labels: PostgreSQLTextArray.values(labelsStr)) } } @@ -1064,9 +849,7 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { private func fetchCollations() async -> (libc: [String], icu: [String]) { do { - let result = try await execute( - query: "SELECT collname, collprovider FROM pg_collation WHERE collprovider IN ('b', 'c', 'i') ORDER BY collname" - ) + let result = try await execute(query: PostgreSQLSchemaQueries.collationList(capabilities: catalogCapabilities)) var libc: [String] = [] var icu: [String] = [] for row in result.rows { @@ -1092,21 +875,7 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { // MARK: - All Tables Metadata func allTablesMetadataSQL(schema: String?) -> String? { - let s = schema ?? currentSchema ?? "public" - return """ - SELECT - schemaname as schema, - relname as name, - 'TABLE' as kind, - n_live_tup as estimated_rows, - pg_size_pretty(pg_total_relation_size(schemaname||'.'||relname)) as total_size, - pg_size_pretty(pg_relation_size(schemaname||'.'||relname)) as data_size, - pg_size_pretty(pg_indexes_size(schemaname||'.'||relname)) as index_size, - obj_description((schemaname||'.'||relname)::regclass) as comment - FROM pg_stat_user_tables - WHERE schemaname = '\(s)' - ORDER BY relname - """ + PostgreSQLSchemaQueries.allTablesMetadata(schema: schema ?? currentSchema ?? "public") } // MARK: - Create Table DDL diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPrincipalQueries.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPrincipalQueries.swift index 542d3d9620..c6fb94fd0a 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPrincipalQueries.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPrincipalQueries.swift @@ -124,17 +124,20 @@ enum PostgreSQLPrincipalQueries { static func columnGrants(roleLiteral: String) -> String { """ - SELECT n.nspname, c.relname, a.attname, acl.privilege_type, acl.is_grantable - FROM pg_attribute a - JOIN pg_class c ON c.oid = a.attrelid - JOIN pg_namespace n ON n.oid = c.relnamespace - CROSS JOIN LATERAL aclexplode(a.attacl) AS acl - JOIN pg_roles r ON r.oid = acl.grantee + SELECT s.nspname, s.relname, s.attname, (s.acl).privilege_type, (s.acl).is_grantable + FROM ( + SELECT n.nspname, c.relname, a.attname, pg_catalog.aclexplode(a.attacl) AS acl + FROM pg_attribute a + JOIN pg_class c ON c.oid = a.attrelid + JOIN pg_namespace n ON n.oid = c.relnamespace + WHERE a.attacl IS NOT NULL + AND a.attnum > 0 + AND NOT a.attisdropped + AND n.nspname NOT IN ('pg_catalog', 'information_schema') + ) s + JOIN pg_roles r ON r.oid = (s.acl).grantee WHERE r.rolname = '\(roleLiteral)' - AND a.attnum > 0 - AND NOT a.attisdropped - AND n.nspname NOT IN ('pg_catalog', 'information_schema') - ORDER BY n.nspname, c.relname, a.attname, acl.privilege_type + ORDER BY s.nspname, s.relname, s.attname, (s.acl).privilege_type """ } @@ -167,39 +170,48 @@ enum PostgreSQLPrincipalQueries { static func databaseGrants(roleLiteral: String) -> String { """ - SELECT d.datname, a.privilege_type, a.is_grantable - FROM pg_database d - CROSS JOIN LATERAL aclexplode(d.datacl) AS a - JOIN pg_roles r ON r.oid = a.grantee + SELECT s.datname, (s.acl).privilege_type, (s.acl).is_grantable + FROM ( + SELECT d.datname, pg_catalog.aclexplode(d.datacl) AS acl + FROM pg_database d + WHERE d.datacl IS NOT NULL + AND NOT d.datistemplate + ) s + JOIN pg_roles r ON r.oid = (s.acl).grantee WHERE r.rolname = '\(roleLiteral)' - AND NOT d.datistemplate - ORDER BY d.datname, a.privilege_type + ORDER BY s.datname, (s.acl).privilege_type """ } static func schemaGrants(roleLiteral: String) -> String { """ - SELECT n.nspname, a.privilege_type, a.is_grantable - FROM pg_namespace n - CROSS JOIN LATERAL aclexplode(n.nspacl) AS a - JOIN pg_roles r ON r.oid = a.grantee + SELECT s.nspname, (s.acl).privilege_type, (s.acl).is_grantable + FROM ( + SELECT n.nspname, pg_catalog.aclexplode(n.nspacl) AS acl + FROM pg_namespace n + WHERE n.nspacl IS NOT NULL + AND n.nspname NOT IN ('pg_catalog', 'information_schema') + ) s + JOIN pg_roles r ON r.oid = (s.acl).grantee WHERE r.rolname = '\(roleLiteral)' - AND n.nspname NOT IN ('pg_catalog', 'information_schema') - ORDER BY n.nspname, a.privilege_type + ORDER BY s.nspname, (s.acl).privilege_type """ } static func tableGrants(roleLiteral: String) -> String { """ - SELECT n.nspname, c.relname, a.privilege_type, a.is_grantable - FROM pg_class c - JOIN pg_namespace n ON n.oid = c.relnamespace - CROSS JOIN LATERAL aclexplode(c.relacl) AS a - JOIN pg_roles r ON r.oid = a.grantee + SELECT s.nspname, s.relname, (s.acl).privilege_type, (s.acl).is_grantable + FROM ( + SELECT n.nspname, c.relname, pg_catalog.aclexplode(c.relacl) AS acl + FROM pg_class c + JOIN pg_namespace n ON n.oid = c.relnamespace + WHERE c.relacl IS NOT NULL + AND c.relkind IN ('r', 'v', 'm', 'p', 'f') + AND n.nspname NOT IN ('pg_catalog', 'information_schema') + ) s + JOIN pg_roles r ON r.oid = (s.acl).grantee WHERE r.rolname = '\(roleLiteral)' - AND c.relkind IN ('r', 'v', 'm', 'p', 'f') - AND n.nspname NOT IN ('pg_catalog', 'information_schema') - ORDER BY n.nspname, c.relname, a.privilege_type + ORDER BY s.nspname, s.relname, (s.acl).privilege_type """ } diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLSchemaQueries.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLSchemaQueries.swift index 15bb6e2bcb..7207b26136 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLSchemaQueries.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLSchemaQueries.swift @@ -23,7 +23,7 @@ enum PostgreSQLSchemaQueries { /// Like `current_schema()`, but resolves via `current_schemas(false)`, /// which omits search path entries that do not correspond to existing, /// searchable schemas. - static let firstSearchPathSchema = "SELECT current_schemas(false)[1]" + static let firstSearchPathSchema = "SELECT (current_schemas(false))[1]" /// Queries tried in order when `current_schema()` resolves to NULL, so a /// database without a `public` schema still gets a usable default schema @@ -73,9 +73,10 @@ enum PostgreSQLSchemaQueries { /// implement; the caller passes `false` when those catalogs are absent so /// the whole query does not fail with `relation does not exist`. /// - /// `includeComments` projects each table's comment via `obj_description` / - /// `to_regclass`. Engines that lack those functions fail the whole listing, - /// so the caller passes `false` to fall back to a comment-free listing. + /// `includeComments` projects each table's comment via `obj_description` + /// over the relation's oid. Engines that lack that function fail the whole + /// listing, so the caller passes `false` to fall back to a comment-free + /// listing. /// /// `includePartitionAwareness` labels a declarative partition parent as /// `PARTITIONED TABLE` and drops its partition children, which @@ -95,17 +96,18 @@ enum PostgreSQLSchemaQueries { /// ordinary table (`relkind = 'r'`), and they are independently useful /// tables rather than an implementation detail of one parent. static func fetchTables( - schemaLiteral: String, + schema: String, includeMaterializedViews: Bool, includeForeignTables: Bool, includeComments: Bool = true, includePartitionAwareness: Bool = true ) -> String { - func commentColumn(_ expression: String) -> String { - includeComments ? expression : "NULL::text" + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(schema) + func commentColumn(_ oidExpression: String) -> String { + includeComments ? "obj_description(\(oidExpression), 'pg_class')" : "NULL::text" } - let partitionJoin = includePartitionAwareness ? """ + let classJoin = (includeComments || includePartitionAwareness) ? """ LEFT JOIN pg_catalog.pg_namespace pn ON pn.nspname = t.table_schema LEFT JOIN pg_catalog.pg_class pc ON pc.relnamespace = pn.oid AND pc.relname = t.table_name @@ -128,20 +130,25 @@ enum PostgreSQLSchemaQueries { var unions: [String] = [ """ SELECT t.table_name, \(tableTypeColumn) AS table_type, - \(commentColumn("obj_description(to_regclass(quote_ident(t.table_schema) || '.' || quote_ident(t.table_name)), 'pg_class')")) AS table_comment - FROM information_schema.tables t\(partitionJoin) - WHERE t.table_schema = '\(schemaLiteral)' + \(commentColumn("pc.oid")) AS table_comment + FROM information_schema.tables t\(classJoin) + WHERE t.table_schema = \(schemaLiteral) AND t.table_type IN ('BASE TABLE', 'VIEW')\(partitionFilter) """ ] if includeMaterializedViews { + let matviewJoin = includeComments ? """ + + LEFT JOIN pg_catalog.pg_namespace mn ON mn.nspname = m.schemaname + LEFT JOIN pg_catalog.pg_class mc ON mc.relnamespace = mn.oid AND mc.relname = m.matviewname + """ : "" unions.append( """ SELECT m.matviewname AS table_name, 'MATERIALIZED VIEW' AS table_type, - \(commentColumn("obj_description(to_regclass(quote_ident(m.schemaname) || '.' || quote_ident(m.matviewname)), 'pg_class')")) AS table_comment - FROM pg_matviews m - WHERE m.schemaname = '\(schemaLiteral)' + \(commentColumn("mc.oid")) AS table_comment + FROM pg_matviews m\(matviewJoin) + WHERE m.schemaname = \(schemaLiteral) """ ) } @@ -150,11 +157,11 @@ enum PostgreSQLSchemaQueries { unions.append( """ SELECT c.relname AS table_name, 'FOREIGN TABLE' AS table_type, - \(commentColumn("obj_description(c.oid, 'pg_class')")) AS table_comment + \(commentColumn("c.oid")) AS table_comment FROM pg_foreign_table ft JOIN pg_class c ON c.oid = ft.ftrelid JOIN pg_namespace n ON n.oid = c.relnamespace - WHERE n.nspname = '\(schemaLiteral)' + WHERE n.nspname = \(schemaLiteral) """ ) } @@ -188,6 +195,30 @@ enum PostgreSQLSchemaQueries { return "SET search_path TO \(quotedIdentifier)" } + static func collationList(capabilities: PostgreSQLCapabilities) -> String { + guard capabilities.hasCollationProvider else { + return "SELECT collname, 'c' FROM pg_catalog.pg_collation WHERE oid <> 100 ORDER BY collname" + } + return "SELECT collname, collprovider FROM pg_catalog.pg_collation WHERE collprovider IN ('b', 'c', 'i') ORDER BY collname" + } + + static func allTablesMetadata(schema: String) -> String { + """ + SELECT + schemaname as schema, + relname as name, + 'TABLE' as kind, + n_live_tup as estimated_rows, + pg_size_pretty(pg_total_relation_size(relid)) as total_size, + pg_size_pretty(pg_relation_size(relid)) as data_size, + pg_size_pretty(pg_indexes_size(relid)) as index_size, + obj_description(relid, 'pg_class') as comment + FROM pg_stat_user_tables + WHERE schemaname = \(PostgreSQLObjectQueries.quoteLiteral(schema)) + ORDER BY relname + """ + } + /// Column introspection for one schema. Passing `tableLiteral` restricts the /// result to a single table; passing `nil` returns every table's columns and /// prefixes each row with `table_name`. `schemaLiteral` is the only schema @@ -224,24 +255,25 @@ enum PostgreSQLSchemaQueries { /// `conkey` carries the attribute numbers the constraint touches, so the columns involved come /// from the catalog rather than from parsing the expression. `pg_get_constraintdef` is the only /// supported way to read the text: `consrc` was removed in PostgreSQL 12. - static func checkConstraintsQuery(schemaLiteral: String, tableLiteral: String) -> String { - """ + static func checkConstraintsQuery(schema: String, table: String) -> String { + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(schema) + let tableLiteral = PostgreSQLObjectQueries.quoteLiteral(table) + return """ SELECT con.conname, pg_get_constraintdef(con.oid), con.convalidated, COALESCE(( - SELECT to_json(array_agg(att.attname ORDER BY att.attnum))::text - FROM unnest(con.conkey) AS k(attnum) - JOIN pg_catalog.pg_attribute att - ON att.attrelid = con.conrelid AND att.attnum = k.attnum - ), \'[]\') + SELECT array_agg(att.attname ORDER BY att.attnum)::text + FROM pg_catalog.pg_attribute att + WHERE att.attrelid = con.conrelid AND att.attnum = ANY (con.conkey) + ), \'{}\') FROM pg_catalog.pg_constraint con JOIN pg_catalog.pg_class cls ON cls.oid = con.conrelid JOIN pg_catalog.pg_namespace ns ON ns.oid = cls.relnamespace WHERE con.contype = \'c\' - AND ns.nspname = \'\(schemaLiteral)\' - AND cls.relname = \'\(tableLiteral)\' + AND ns.nspname = \(schemaLiteral) + AND cls.relname = \(tableLiteral) ORDER BY con.conname """ } diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLSequenceQueries.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLSequenceQueries.swift new file mode 100644 index 0000000000..35dbb6ef07 --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLSequenceQueries.swift @@ -0,0 +1,160 @@ +// +// PostgreSQLSequenceQueries.swift +// PostgreSQLDriverPlugin +// + +import Foundation +import TableProPluginKit + +struct PostgreSQLSequenceDefinition: Equatable, Sendable { + let name: String + let startValue: String? + let minValue: String? + let maxValue: String? + let increment: String? + let cycles: Bool + let lastValue: String? + let needsLastValueRead: Bool + + func withLastValue(_ value: String?) -> PostgreSQLSequenceDefinition { + PostgreSQLSequenceDefinition( + name: name, + startValue: startValue, + minValue: minValue, + maxValue: maxValue, + increment: increment, + cycles: cycles, + lastValue: value, + needsLastValueRead: false + ) + } + + var ddl: String { + let quotedName = PostgreSQLObjectQueries.quoteIdentifier(name) + let parameters = [startValue, minValue, maxValue, increment] + var statement: String + if parameters.allSatisfy({ $0 == nil }) { + statement = "CREATE SEQUENCE \(quotedName);" + } else { + statement = "CREATE SEQUENCE \(quotedName) INCREMENT BY \(increment ?? "1")" + + " MINVALUE \(minValue ?? "1") MAXVALUE \(maxValue ?? "9223372036854775807")" + + " START WITH \(startValue ?? "1")\(cycles ? " CYCLE" : "");" + } + guard let lastValue, Int64(lastValue) != nil else { return statement } + let target = PostgreSQLObjectQueries.quoteLiteral(quotedName) + statement += "\nSELECT pg_catalog.setval(\(target), \(lastValue), true);" + return statement + } +} + +enum PostgreSQLSequenceQueries { + enum Source: Equatable { + case sequencesView + case sequenceParameters + } + + /// `pg_sequence_parameters` answers on every supported release, so a server whose version + /// promises `pg_sequences` but whose catalog does not carry it still lists its sequences. + static func source(hasSequencesCatalog: Bool) -> Source { + hasSequencesCatalog ? .sequencesView : .sequenceParameters + } + + static func sequenceList(schema: String, dependentOnTable table: String?, source: Source) -> String { + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(schema) + let dependency = table.map { dependencyPredicate(schemaLiteral: schemaLiteral, table: $0) } ?? "" + switch source { + case .sequencesView: + return """ + SELECT s.sequencename, + s.start_value, + s.min_value, + s.max_value, + s.increment_by, + s.cycle, + s.last_value, + false AS needs_last_value_read + FROM pg_catalog.pg_sequences s + JOIN pg_catalog.pg_namespace n ON n.nspname = s.schemaname + JOIN pg_catalog.pg_class c ON c.relnamespace = n.oid AND c.relname = s.sequencename + WHERE s.schemaname = \(schemaLiteral)\(dependency) + ORDER BY s.sequencename + """ + case .sequenceParameters: + return """ + SELECT s.relname, + \(parameter("start_value")), + \(parameter("minimum_value")), + \(parameter("maximum_value")), + \(parameter("increment")), + \(parameter("cycle_option")), + NULL::bigint AS last_value, + s.readable + FROM ( + SELECT c.oid, + c.relname, + pg_catalog.has_sequence_privilege(c.oid, 'SELECT,USAGE,UPDATE') AS can_read_parameters, + pg_catalog.has_sequence_privilege(c.oid, 'SELECT') AS readable + FROM pg_catalog.pg_class c + JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace + WHERE c.relkind = 'S' + AND n.nspname = \(schemaLiteral)\(dependency) + OFFSET 0 + ) s + ORDER BY s.relname + """ + } + } + + /// The privilege test runs once per sequence in the fenced derived table (`OFFSET 0` stops it + /// being flattened back into every CASE). The parameters cannot be read once the same way: + /// `pg_sequence_parameters` returns an anonymous record that loses its type in a derived-table + /// column (9.1 and 9.3 answer "record type has not been registered"), and moving the privilege + /// test into WHERE lets the server run it against relations that are not sequences. + private static func parameter(_ field: String) -> String { + """ + CASE WHEN s.can_read_parameters + THEN (pg_catalog.pg_sequence_parameters(s.oid)).\(field) END + """ + } + + /// One statement per sequence. A sequence dropped or revoked between the listing and this read + /// then costs its own `setval` line rather than the whole listing. + static func lastValue(schema: String, sequence: String) -> String { + let relation = PostgreSQLObjectQueries.qualifiedName(schema: schema, name: sequence) + return "SELECT CASE WHEN is_called THEN last_value END FROM \(relation)" + } + + static func definitions(from rows: [[PluginCellValue]]) -> [PostgreSQLSequenceDefinition] { + rows.compactMap { row in + guard let name = row[safe: 0]?.asText else { return nil } + return PostgreSQLSequenceDefinition( + name: name, + startValue: row[safe: 1]?.asText, + minValue: row[safe: 2]?.asText, + maxValue: row[safe: 3]?.asText, + increment: row[safe: 4]?.asText, + cycles: PostgreSQLCatalogBoolean.isTrue(row[safe: 5]?.asText), + lastValue: row[safe: 6]?.asText, + needsLastValueRead: PostgreSQLCatalogBoolean.isTrue(row[safe: 7]?.asText) + ) + } + } + + private static func dependencyPredicate(schemaLiteral: String, table: String) -> String { + """ + + AND EXISTS ( + SELECT 1 + FROM pg_catalog.pg_attrdef ad + JOIN pg_catalog.pg_depend d + ON d.classid = 'pg_catalog.pg_attrdef'::pg_catalog.regclass + AND d.objid = ad.oid + AND d.refclassid = 'pg_catalog.pg_class'::pg_catalog.regclass + AND d.refobjid = c.oid + JOIN pg_catalog.pg_class t ON t.oid = ad.adrelid + JOIN pg_catalog.pg_namespace tn ON tn.oid = t.relnamespace + WHERE t.relname = \(PostgreSQLObjectQueries.quoteLiteral(table)) + AND tn.nspname = \(schemaLiteral)) + """ + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLTextArray.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLTextArray.swift new file mode 100644 index 0000000000..90b946e985 --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLTextArray.swift @@ -0,0 +1,21 @@ +// +// PostgreSQLTextArray.swift +// PostgreSQLDriverPlugin +// + +import Foundation +import TableProPluginKit + +enum PostgreSQLTextArray { + static func elements(_ text: String?) -> [String?] { + guard let text, let parsed = PostgresArrayLiteralCodec.parse(text) else { return [] } + return parsed.map { element in + guard case .value(let value) = element else { return nil } + return value + } + } + + static func values(_ text: String?) -> [String] { + elements(text).compactMap { $0 } + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLTypeDefinition.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLTypeDefinition.swift index 397b9661a9..e8613a649f 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLTypeDefinition.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLTypeDefinition.swift @@ -114,12 +114,15 @@ public enum PostgreSQLTypeDefinition { case owner case comment case enumLabels - case fields + case fieldNames + case fieldTypes + case fieldCollations case baseType case collation case isNotNull case defaultValue - case constraints + case constraintNames + case constraintDefinitions case rangeSubtype case rangeCanonical case rangeSubtypeDiff @@ -142,19 +145,13 @@ public enum PostgreSQLTypeDefinition { kind: kind, owner: text(row, .owner), comment: text(row, .comment), - enumLabels: jsonStrings(text(row, .enumLabels)), - fields: jsonObjects(text(row, .fields)).compactMap { object in - guard let name = object["name"], let type = object["type"] else { return nil } - return PluginUserDefinedTypeField(name: name, type: type, collation: object["collation"]) - }, + enumLabels: PostgreSQLTextArray.values(text(row, .enumLabels)), + fields: fields(in: row), baseType: text(row, .baseType), collation: text(row, .collation), - isNotNull: text(row, .isNotNull) == "t" || text(row, .isNotNull) == "true", + isNotNull: PostgreSQLCatalogBoolean.isTrue(text(row, .isNotNull)), defaultValue: text(row, .defaultValue), - constraints: jsonObjects(text(row, .constraints)).compactMap { object in - guard let name = object["name"], let definition = object["definition"] else { return nil } - return PostgreSQLDomainConstraint(name: name, definition: definition) - }, + constraints: constraints(in: row), rangeSubtype: text(row, .rangeSubtype), rangeCanonical: text(row, .rangeCanonical), rangeSubtypeDiff: text(row, .rangeSubtypeDiff), @@ -298,19 +295,23 @@ public enum PostgreSQLTypeDefinition { return value } - private static func jsonStrings(_ json: String?) -> [String] { - guard let data = json?.data(using: .utf8), - let array = try? JSONSerialization.jsonObject(with: data) as? [Any] - else { return [] } - return array.compactMap { $0 as? String } + private static func fields(in row: [PluginCellValue]) -> [PluginUserDefinedTypeField] { + let names = PostgreSQLTextArray.elements(text(row, .fieldNames)) + let types = PostgreSQLTextArray.elements(text(row, .fieldTypes)) + let collations = PostgreSQLTextArray.elements(text(row, .fieldCollations)) + return names.indices.compactMap { index in + guard let name = names[index], let type = types[safe: index] ?? nil else { return nil } + let collation = collations[safe: index] ?? nil + return PluginUserDefinedTypeField(name: name, type: type, collation: collation) + } } - private static func jsonObjects(_ json: String?) -> [[String: String]] { - guard let data = json?.data(using: .utf8), - let array = try? JSONSerialization.jsonObject(with: data) as? [[String: Any]] - else { return [] } - return array.map { object in - object.compactMapValues { $0 as? String } + private static func constraints(in row: [PluginCellValue]) -> [PostgreSQLDomainConstraint] { + let names = PostgreSQLTextArray.elements(text(row, .constraintNames)) + let definitions = PostgreSQLTextArray.elements(text(row, .constraintDefinitions)) + return names.indices.compactMap { index in + guard let name = names[index], let definition = definitions[safe: index] ?? nil else { return nil } + return PostgreSQLDomainConstraint(name: name, definition: definition) } } } diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLViewDefinition.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLViewDefinition.swift index bdb9656201..f53ce9235e 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLViewDefinition.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLViewDefinition.swift @@ -33,7 +33,7 @@ public enum PostgreSQLViewDefinition { } } - /// Run with `search_path` emptied first (see `qualifiedReadPrefix`). `pg_get_viewdef` writes a + /// Run with `search_path` narrowed first (see `qualifiedReadPrefix`). `pg_get_viewdef` writes a /// table name bare whenever the reading session could resolve it without its schema, and the /// scoped connection this runs on has its path set to the view's own schema, so the body came /// back naming `orders` rather than `sales.orders`. Run anywhere else, that text silently bound @@ -43,7 +43,7 @@ public enum PostgreSQLViewDefinition { SELECT c.relkind::text, pg_catalog.pg_get_viewdef(c.oid, true), - pg_catalog.array_to_json(c.reloptions)::text, + c.reloptions::text, am.amname::text, ts.spcname::text FROM pg_catalog.pg_class c @@ -60,7 +60,11 @@ public enum PostgreSQLViewDefinition { /// as the read, the pair is one implicit transaction, so the path is back to what it was as /// soon as the read returns. Inside a transaction the caller already holds, it would last until /// that transaction ends, which is why the driver wraps the read in a savepoint there. - public static let qualifiedReadPrefix = "SET LOCAL search_path = ''; " + /// + /// `pg_catalog` rather than an empty path: PostgreSQL 9.1 rejects `''` ("schema "" does not + /// exist"), and `pg_catalog` is searched implicitly anyway, so every user relation is still + /// written with its schema. Measured identical output on 9.2, 9.3, 9.6 and 17. + public static let qualifiedReadPrefix = "SET LOCAL search_path = pg_catalog; " public static func parse(row: [String?]) -> CatalogRow? { guard row.count >= 5, @@ -71,7 +75,7 @@ public enum PostgreSQLViewDefinition { return CatalogRow( kind: kind, query: query, - options: options(fromJSON: row[2]), + options: PostgreSQLTextArray.values(row[2]), accessMethod: row[3]?.nilIfBlank, tablespace: row[4]?.nilIfBlank ) @@ -85,15 +89,6 @@ public enum PostgreSQLViewDefinition { } } - /// Read as JSON rather than as array text, because an option value may itself hold a comma or - /// a quote and splitting `{a=1,b=2}` on commas would cut it in two. - public static func options(fromJSON json: String?) -> [String] { - guard let data = json?.data(using: .utf8), - let decoded = try? JSONDecoder().decode([String].self, from: data) - else { return [] } - return decoded - } - public static func statement(name: String, schema: String, row: CatalogRow) -> String { let target = PostgreSQLObjectQueries.qualifiedName(schema: schema, name: name) let body = trimmedQuery(row.query) diff --git a/Plugins/PostgreSQLDriverPlugin/RedshiftPluginDriver.swift b/Plugins/PostgreSQLDriverPlugin/RedshiftPluginDriver.swift index 675b55994e..a49821e5bc 100644 --- a/Plugins/PostgreSQLDriverPlugin/RedshiftPluginDriver.swift +++ b/Plugins/PostgreSQLDriverPlugin/RedshiftPluginDriver.swift @@ -346,7 +346,7 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { var sortkeyCols: [String] = [] for row in result.rows { guard let colName = row[0].asText else { continue } - let isDistkey = row[2].asText == "t" + let isDistkey = PostgreSQLCatalogBoolean.isTrue(row[2].asText) let sortKeyVal = Int(row[3].asText ?? "0") ?? 0 if isDistkey { distkeyCols.append(colName) } if sortKeyVal != 0 { sortkeyCols.append(colName) } diff --git a/TableProTests/Plugins/ObjectCatalogQueryTests.swift b/TableProTests/Plugins/ObjectCatalogQueryTests.swift index fb9c286d18..d19786e212 100644 --- a/TableProTests/Plugins/ObjectCatalogQueryTests.swift +++ b/TableProTests/Plugins/ObjectCatalogQueryTests.swift @@ -16,7 +16,7 @@ struct PostgreSQLObjectQueryTests { /// name once per overload, which is what produced duplicate rows and an arbitrary definition. @Test("Routine listing reads pg_proc, never information_schema") func routineListReadsPgProc() { - let sql = PostgreSQLObjectQueries.routineList(schema: "public", serverVersionNumber: 160_000) + let sql = PostgreSQLObjectQueries.routineList(schema: "public", capabilities: .assumingModernWhenUnknown(160_000)) #expect(sql.contains("pg_catalog.pg_proc")) #expect(!sql.contains("information_schema")) #expect(sql.contains("p.oid::text")) @@ -27,19 +27,19 @@ struct PostgreSQLObjectQueryTests { /// `proisagg`, which PostgreSQL 11 dropped, and failed the listing on every current server. @Test("An unknown server version reads as modern, not ancient") func unknownVersionIsModern() { - #expect(PostgreSQLObjectQueries.usesProkind(serverVersionNumber: 0)) - #expect(PostgreSQLObjectQueries.usesProkind(serverVersionNumber: 170_000)) - #expect(!PostgreSQLObjectQueries.usesProkind(serverVersionNumber: 100_000)) - #expect(!PostgreSQLObjectQueries.routineList(schema: "public", serverVersionNumber: 0) + #expect(PostgreSQLCapabilities.assumingModernWhenUnknown(0).hasProcedureKind) + #expect(PostgreSQLCapabilities(serverVersion: 170_000).hasProcedureKind) + #expect(!PostgreSQLCapabilities(serverVersion: 100_000).hasProcedureKind) + #expect(!PostgreSQLObjectQueries.routineList(schema: "public", capabilities: .assumingModernWhenUnknown(0)) .contains("proisagg")) } @Test("Aggregates and window functions are excluded because pg_get_functiondef raises on them") func aggregatesExcluded() { - let modern = PostgreSQLObjectQueries.routineList(schema: "public", serverVersionNumber: 160_000) + let modern = PostgreSQLObjectQueries.routineList(schema: "public", capabilities: .assumingModernWhenUnknown(160_000)) #expect(modern.contains("p.prokind IN ('f', 'p')")) - let legacy = PostgreSQLObjectQueries.routineList(schema: "public", serverVersionNumber: 100_000) + let legacy = PostgreSQLObjectQueries.routineList(schema: "public", capabilities: .assumingModernWhenUnknown(100_000)) #expect(legacy.contains("NOT p.proisagg AND NOT p.proiswindow")) #expect(!legacy.contains("prokind IN")) } @@ -70,9 +70,17 @@ struct PostgreSQLObjectQueryTests { #expect(one.contains("pg_catalog.pg_get_triggerdef")) } + @Test("Trigger events are joined with concat_ws, which 9.1 has and array_remove does not") + func triggerEventsUseConcatWs() { + let sql = PostgreSQLObjectQueries.triggerList(schema: "public", table: nil) + #expect(sql.contains("concat_ws(' OR ',")) + #expect(!sql.contains("array_remove")) + #expect(!sql.contains("array_to_string")) + } + @Test("A quote in a name or schema is escaped in every query") func literalsAreEscaped() { - let list = PostgreSQLObjectQueries.routineList(schema: "it's", serverVersionNumber: 160_000) + let list = PostgreSQLObjectQueries.routineList(schema: "it's", capabilities: .assumingModernWhenUnknown(160_000)) #expect(list.contains("'it''s'")) let byName = PostgreSQLObjectQueries.routineDefinitionByName( @@ -89,7 +97,9 @@ struct PostgreSQLObjectQueryTests { let hostile = "a\\'; DROP TABLE victim; --" let expected = "E'a\\\\''; DROP TABLE victim; --'" - let list = PostgreSQLObjectQueries.routineList(schema: hostile, serverVersionNumber: 160_000) + let list = PostgreSQLObjectQueries.routineList( + schema: hostile, capabilities: .assumingModernWhenUnknown(160_000) + ) #expect(list.contains("n.nspname = \(expected)")) let byName = PostgreSQLObjectQueries.routineDefinitionByName( diff --git a/TableProTests/Plugins/PostGISSpatialRewriteTests.swift b/TableProTests/Plugins/PostGISSpatialRewriteTests.swift index c636b9a1ae..9ff84c21e0 100644 --- a/TableProTests/Plugins/PostGISSpatialRewriteTests.swift +++ b/TableProTests/Plugins/PostGISSpatialRewriteTests.swift @@ -8,44 +8,62 @@ import Testing @Suite("PostGISSpatialRewrite.conversionQuery") struct PostGISConversionQueryTests { - @Test("geometry maps to the geometry conversion query") - func geometry() { - #expect(PostGISSpatialRewrite.conversionQuery(forTypeName: "geometry") - == PostGISSpatialRewrite.geometryConversionQuery) + private let geometry = PostGISType(name: "geometry", schema: "public") + private let geography = PostGISType(name: "geography", schema: "gis") + + @Test("geometry casts each element to the probed geometry type") + func geometryQuery() throws { + let query = try #require(PostGISSpatialRewrite.conversionQuery(for: geometry)) + #expect(query.contains("\"public\".ST_AsEWKT(($1::text[])[i]::\"public\".\"geometry\")")) } - @Test("geography maps to the geography conversion query") - func geography() { - #expect(PostGISSpatialRewrite.conversionQuery(forTypeName: "geography") - == PostGISSpatialRewrite.geographyConversionQuery) + @Test("geography casts each element to the probed geography type") + func geographyQuery() throws { + let query = try #require(PostGISSpatialRewrite.conversionQuery(for: geography)) + #expect(query.contains("\"gis\".ST_AsEWKT(($1::text[])[i]::\"gis\".\"geography\")")) } @Test("Unknown type name returns nil") func unknown() { - #expect(PostGISSpatialRewrite.conversionQuery(forTypeName: "text") == nil) - #expect(PostGISSpatialRewrite.conversionQuery(forTypeName: "raster") == nil) - #expect(PostGISSpatialRewrite.conversionQuery(forTypeName: "") == nil) + #expect(PostGISSpatialRewrite.conversionQuery(for: PostGISType(name: "text", schema: "public")) == nil) + #expect(PostGISSpatialRewrite.conversionQuery(for: PostGISType(name: "raster", schema: "public")) == nil) + #expect(PostGISSpatialRewrite.conversionQuery(for: PostGISType(name: "", schema: "public")) == nil) } - @Test("geometry query applies ST_AsEWKT over a text array parameter cast per element") - func geometryQueryShape() { - let query = PostGISSpatialRewrite.geometryConversionQuery - #expect(query.contains("ST_AsEWKT(t::geometry)")) - #expect(query.contains("unnest($1::text[])")) - #expect(query.contains("ORDER BY ord")) + @Test("Elements are walked by generate_subscripts, which 9.1 has, in array order") + func portableOrdering() throws { + let query = try #require(PostGISSpatialRewrite.conversionQuery(for: geometry)) + #expect(query.contains("pg_catalog.generate_subscripts($1::text[], 1) AS i ORDER BY i")) + #expect(!query.contains("WITH ORDINALITY")) + #expect(!query.contains("unnest")) } - @Test("geography query casts each element to geography") - func geographyQueryShape() { - let query = PostGISSpatialRewrite.geographyConversionQuery - #expect(query.contains("ST_AsEWKT(t::geography)")) - #expect(query.contains("unnest($1::text[])")) + @Test("A schema name is quoted as an identifier, not interpolated") + func schemaIsQuoted() throws { + let query = try #require( + PostGISSpatialRewrite.conversionQuery(for: PostGISType(name: "geometry", schema: "we\"ird")) + ) + #expect(query.contains("\"we\"\"ird\".\"geometry\"")) } @Test("Conversion query reads a single bound parameter, never the user statement") - func singleParameter() { - #expect(PostGISSpatialRewrite.geometryConversionQuery.contains("$1")) - #expect(!PostGISSpatialRewrite.geometryConversionQuery.contains("$2")) + func singleParameter() throws { + let query = try #require(PostGISSpatialRewrite.conversionQuery(for: geometry)) + #expect(query.contains("$1")) + #expect(!query.contains("$2")) + } + + @Test("The savepoint that isolates the conversion inside a transaction is released on both paths") + func savepointStatements() { + #expect(PostGISSpatialRewrite.savepoint == "SAVEPOINT tablepro_spatial_render") + #expect(PostGISSpatialRewrite.rollbackToSavepoint == "ROLLBACK TO SAVEPOINT tablepro_spatial_render") + #expect(PostGISSpatialRewrite.releaseSavepoint == "RELEASE SAVEPOINT tablepro_spatial_render") + } + + @Test("The probe reads each spatial type's namespace") + func probeReadsNamespace() { + #expect(PostGISSpatialRewrite.probeQuery.contains("n.nspname")) + #expect(PostGISSpatialRewrite.probeQuery.contains("JOIN pg_catalog.pg_namespace n")) } } diff --git a/TableProTests/Plugins/PostgreSQLCatalogCompatibilityTests.swift b/TableProTests/Plugins/PostgreSQLCatalogCompatibilityTests.swift index cdb0db3e8d..db8b1fbf10 100644 --- a/TableProTests/Plugins/PostgreSQLCatalogCompatibilityTests.swift +++ b/TableProTests/Plugins/PostgreSQLCatalogCompatibilityTests.swift @@ -17,7 +17,7 @@ struct PostgreSQLFetchTablesQueryTests { @Test("Always selects base tables and views from information_schema") func alwaysIncludesBaseTables() { let query = PostgreSQLSchemaQueries.fetchTables( - schemaLiteral: "public", + schema: "public", includeMaterializedViews: true, includeForeignTables: true ) @@ -27,7 +27,7 @@ struct PostgreSQLFetchTablesQueryTests { @Test("Omits the pg_matviews union when materialized views are unavailable") func omitsMatviewsWhenAbsent() { let query = PostgreSQLSchemaQueries.fetchTables( - schemaLiteral: "public", + schema: "public", includeMaterializedViews: false, includeForeignTables: true ) @@ -37,7 +37,7 @@ struct PostgreSQLFetchTablesQueryTests { @Test("Includes the pg_matviews union when materialized views are available") func includesMatviewsWhenPresent() { let query = PostgreSQLSchemaQueries.fetchTables( - schemaLiteral: "public", + schema: "public", includeMaterializedViews: true, includeForeignTables: false ) @@ -47,7 +47,7 @@ struct PostgreSQLFetchTablesQueryTests { @Test("Omits the pg_foreign_table union when foreign tables are unavailable") func omitsForeignTablesWhenAbsent() { let query = PostgreSQLSchemaQueries.fetchTables( - schemaLiteral: "public", + schema: "public", includeMaterializedViews: true, includeForeignTables: false ) @@ -57,7 +57,7 @@ struct PostgreSQLFetchTablesQueryTests { @Test("With no optional catalogs, only the base query remains") func baseOnlyWhenNoOptionalCatalogs() { let query = PostgreSQLSchemaQueries.fetchTables( - schemaLiteral: "public", + schema: "public", includeMaterializedViews: false, includeForeignTables: false ) diff --git a/TableProTests/Plugins/PostgreSQLDefaultSchemaFallbackTests.swift b/TableProTests/Plugins/PostgreSQLDefaultSchemaFallbackTests.swift index a45d5a547e..6c3b3e126c 100644 --- a/TableProTests/Plugins/PostgreSQLDefaultSchemaFallbackTests.swift +++ b/TableProTests/Plugins/PostgreSQLDefaultSchemaFallbackTests.swift @@ -16,7 +16,7 @@ struct PostgreSQLDefaultSchemaFallbackTests { @Test("resolves the first existing search path entry, omitting missing schemas") func firstSearchPathSchemaQuery() { - #expect(PostgreSQLSchemaQueries.firstSearchPathSchema == "SELECT current_schemas(false)[1]") + #expect(PostgreSQLSchemaQueries.firstSearchPathSchema == "SELECT (current_schemas(false))[1]") } @Test("falls back to the effective search path before the alphabetical schema list") diff --git a/TableProTests/Plugins/PostgreSQLFetchTablesCommentTests.swift b/TableProTests/Plugins/PostgreSQLFetchTablesCommentTests.swift index a8e84e30b9..2c19101357 100644 --- a/TableProTests/Plugins/PostgreSQLFetchTablesCommentTests.swift +++ b/TableProTests/Plugins/PostgreSQLFetchTablesCommentTests.swift @@ -7,18 +7,57 @@ struct PostgreSQLFetchTablesCommentTests { @Test("Base query selects the table comment via obj_description") func baseQuerySelectsComment() { let query = PostgreSQLSchemaQueries.fetchTables( - schemaLiteral: "public", + schema: "public", includeMaterializedViews: false, includeForeignTables: false ) #expect(query.contains("table_comment")) - #expect(query.contains("obj_description")) + #expect(query.contains("obj_description(pc.oid, 'pg_class')")) + } + + @Test("No rung reads to_regclass, whose text form exists only from PostgreSQL 9.6") + func noRungUsesToRegclass() { + let attempts = PostgreSQLTableListingLadder.degradableAttempts + [PostgreSQLTableListingLadder.leastCapableAttempt] + for attempt in attempts { + let query = PostgreSQLSchemaQueries.fetchTables( + schema: "public", + includeMaterializedViews: attempt.includeOptionalCatalogs, + includeForeignTables: attempt.includeOptionalCatalogs, + includeComments: attempt.includeComments, + includePartitionAwareness: attempt.includePartitionAwareness + ) + #expect(!query.contains("to_regclass"), "\(attempt.label)") + } + } + + @Test("Comments without partition awareness still join pg_class for the relation oid") + func commentsWithoutPartitionsKeepTheClassJoin() { + let query = PostgreSQLSchemaQueries.fetchTables( + schema: "public", + includeMaterializedViews: false, + includeForeignTables: false, + includeComments: true, + includePartitionAwareness: false + ) + #expect(query.contains("LEFT JOIN pg_catalog.pg_class pc")) + #expect(!query.contains("pg_catalog.pg_inherits")) + } + + @Test("A materialized view's comment comes from its own relation oid") + func matviewCommentUsesItsOid() { + let query = PostgreSQLSchemaQueries.fetchTables( + schema: "public", + includeMaterializedViews: true, + includeForeignTables: false + ) + #expect(query.contains("obj_description(mc.oid, 'pg_class')")) + #expect(query.contains("JOIN pg_catalog.pg_class mc ON mc.relnamespace = mn.oid AND mc.relname = m.matviewname")) } @Test("Fully degraded query does not reference pg_class/pg_namespace so the portability fallback stays minimal") func fallbackQueryStaysPortable() { let query = PostgreSQLSchemaQueries.fetchTables( - schemaLiteral: "public", + schema: "public", includeMaterializedViews: false, includeForeignTables: false, includeComments: false, @@ -32,7 +71,7 @@ struct PostgreSQLFetchTablesCommentTests { @Test("Every union branch projects a comment column so columns stay aligned") func allBranchesProjectComment() { let query = PostgreSQLSchemaQueries.fetchTables( - schemaLiteral: "public", + schema: "public", includeMaterializedViews: true, includeForeignTables: true ) @@ -44,7 +83,7 @@ struct PostgreSQLFetchTablesCommentTests { @Test("Comment-free fallback omits obj_description but keeps the aligned comment column") func commentFreeFallbackOmitsObjDescription() { let query = PostgreSQLSchemaQueries.fetchTables( - schemaLiteral: "public", + schema: "public", includeMaterializedViews: true, includeForeignTables: true, includeComments: false diff --git a/TableProTests/Plugins/PostgreSQLLegacyCatalogQueryTests.swift b/TableProTests/Plugins/PostgreSQLLegacyCatalogQueryTests.swift new file mode 100644 index 0000000000..339254e523 --- /dev/null +++ b/TableProTests/Plugins/PostgreSQLLegacyCatalogQueryTests.swift @@ -0,0 +1,427 @@ +// +// PostgreSQLLegacyCatalogQueryTests.swift +// TableProTests +// + +import Foundation +import TableProPluginKit +import Testing + +@Suite("PostgreSQL catalog reads that PostgreSQL 9.1 accepts") +struct PostgreSQLLegacyCatalogQueryTests { + private static let constructsMissingBefore96 = [ + "to_regclass", "LATERAL", "WITH ORDINALITY", "json", "array_remove", "array_position", "FILTER (", + "unnest(" + ] + + static let legacy = PostgreSQLCapabilities(serverVersion: 90_124) + + private static func unavailableConstructs(in sql: String) -> [String] { + constructsMissingBefore96.filter { sql.contains($0) } + } + + @Test("Every rewritten read stays inside what PostgreSQL 9.1 parses") + func rewrittenReadsArePortable() { + let legacy = Self.legacy + let queries = [ + PostgreSQLForeignKeyQueries.foreignKeyList(schema: "public", table: "orders", capabilities: legacy), + PostgreSQLForeignKeyQueries.foreignKeyList(schema: "public", table: nil, capabilities: legacy), + PostgreSQLIndexQueries.indexList(schema: "public", table: "orders"), + PostgreSQLIndexQueries.indexList(schema: "public", table: nil), + PostgreSQLObjectQueries.triggerList(schema: "public", table: nil), + PostgreSQLObjectQueries.userDefinedTypeList(schema: "public", identity: nil, capabilities: legacy), + PostgreSQLSchemaQueries.checkConstraintsQuery(schema: "public", table: "t"), + PostgreSQLSchemaQueries.collationList(capabilities: legacy), + PostgreSQLSchemaQueries.allTablesMetadata(schema: "public"), + PostgreSQLPrincipalQueries.databaseGrants(roleLiteral: "r"), + PostgreSQLPrincipalQueries.schemaGrants(roleLiteral: "r"), + PostgreSQLPrincipalQueries.tableGrants(roleLiteral: "r"), + PostgreSQLPrincipalQueries.columnGrants(roleLiteral: "r"), + PostgreSQLSequenceQueries.sequenceList(schema: "public", dependentOnTable: "orders", source: .sequenceParameters), + PostgreSQLSchemaQueries.fetchTables(schema: "public", includeMaterializedViews: true, includeForeignTables: true), + PostgreSQLViewDefinition.catalogQuery(name: "v", schema: "public") + ] + for sql in queries { + #expect(Self.unavailableConstructs(in: sql).isEmpty, "\(sql)") + } + } + + @Test("Every name reaching these reads is quoted so standard_conforming_strings cannot change it") + func namesAreQuotedInEveryRead() { + let hostile = "a\\b'c" + let queries = [ + PostgreSQLObjectQueries.triggerList(schema: hostile, table: hostile), + PostgreSQLObjectQueries.routineList(schema: hostile, capabilities: Self.legacy), + PostgreSQLSchemaQueries.checkConstraintsQuery(schema: hostile, table: hostile), + PostgreSQLSchemaQueries.fetchTables( + schema: hostile, includeMaterializedViews: true, includeForeignTables: true + ) + ] + for sql in queries { + #expect(sql.contains("E'a\\\\b''c'"), "\(sql)") + #expect(!sql.contains("'a\\b'c'")) + } + } + + @Test("The search-path fallback parenthesises the function before subscripting it") + func searchPathFallbackParses() { + #expect(PostgreSQLSchemaQueries.firstSearchPathSchema == "SELECT (current_schemas(false))[1]") + } +} + +@Suite("PostgreSQL foreign key catalog read") +struct PostgreSQLForeignKeyQueryTests { + private static let modern = PostgreSQLCapabilities(serverVersion: 170_011) + private static let beforeConstraintParent = PostgreSQLCapabilities(serverVersion: 100_021) + + @Test("Schema and table predicates sit inside the derived table, before the key positions expand") + func predicatesAreInsideTheDerivedTable() throws { + let sql = PostgreSQLForeignKeyQueries.foreignKeyList(schema: "public", table: "orders", capabilities: Self.modern) + let derivedEnd = try #require(sql.range(of: ") con")) + let inside = sql[.. (100)::numeric)") + ] + let decoded = try #require(PostgreSQLIndexRow.index(from: row)) + #expect(decoded.index.columns == ["amount"]) + #expect(decoded.index.isUnique) + #expect(!decoded.index.isPrimary) + #expect(decoded.index.whereClause == "(amount > (100)::numeric)") + } +} + +@Suite("PostgreSQL check constraint columns") +struct PostgreSQLCheckConstraintColumnTests { + @Test("Column names come back whole from the array literal the server prints") + func hostileNames() { + let columns = PostgreSQLTextArray.values( #"{"a b","c,d","q\"t","x{y}"}"#) + #expect(columns == ["a b", "c,d", "q\"t", "x{y}"]) + } + + @Test("A constraint that names no column reads as an empty list") + func noColumns() { + #expect(PostgreSQLTextArray.values( "{}").isEmpty) + #expect(PostgreSQLTextArray.values( nil).isEmpty) + } + + @Test("The query aggregates names with array_agg and defaults to an empty array") + func queryShape() { + let sql = PostgreSQLSchemaQueries.checkConstraintsQuery(schema: "public", table: "t") + #expect(sql.contains("array_agg(att.attname ORDER BY att.attnum)::text")) + #expect(sql.contains("att.attnum = ANY (con.conkey)")) + #expect(sql.contains("'{}'")) + } +} + +@Suite("PostgreSQL sequence reads") +struct PostgreSQLSequenceQueryTests { + @Test("pg_sequences is read wherever it exists, and every other server reads the sequences one by one") + func sourceSelection() { + #expect(PostgreSQLSequenceQueries.source(hasSequencesCatalog: true) == .sequencesView) + #expect(PostgreSQLSequenceQueries.source(hasSequencesCatalog: false) == .sequenceParameters) + } + + @Test("pg_sequences arrived in PostgreSQL 10, not 9.5") + func sequencesCatalogThreshold() { + #expect(!PostgreSQLCapabilities(serverVersion: 90_500).hasSequencesCatalog) + #expect(!PostgreSQLCapabilities(serverVersion: 90_624).hasSequencesCatalog) + #expect(PostgreSQLCapabilities(serverVersion: 100_000).hasSequencesCatalog) + } + + @Test("A sequence the role cannot read reports no parameters instead of failing the listing") + func legacyListingIsPrivilegeGuarded() { + let sql = PostgreSQLSequenceQueries.sequenceList(schema: "public", dependentOnTable: nil, source: .sequenceParameters) + #expect(sql.contains("pg_catalog.has_sequence_privilege(c.oid, 'SELECT,USAGE,UPDATE') AS can_read_parameters")) + #expect(sql.contains("(pg_catalog.pg_sequence_parameters(s.oid)).start_value")) + #expect(sql.contains("pg_catalog.has_sequence_privilege(c.oid, 'SELECT') AS readable")) + #expect(!sql.contains("pg_sequences")) + } + + @Test("A table's sequences are the ones its column defaults depend on, in either source") + func dependencyComesFromPgDepend() { + for source in [PostgreSQLSequenceQueries.Source.sequencesView, .sequenceParameters] { + let sql = PostgreSQLSequenceQueries.sequenceList(schema: "public", dependentOnTable: "orders", source: source) + #expect(sql.contains("d.classid = 'pg_catalog.pg_attrdef'::pg_catalog.regclass")) + #expect(sql.contains("d.refobjid = c.oid")) + #expect(sql.contains("t.relname = 'orders'")) + #expect(!sql.contains("LIKE")) + } + } + + @Test("Each sequence's last value is its own statement, qualified and quoted") + func lastValueIsPerSequence() { + let sql = PostgreSQLSequenceQueries.lastValue(schema: "app", sequence: "we\"ird's") + #expect(sql == "SELECT CASE WHEN is_called THEN last_value END FROM \"app\".\"we\"\"ird's\"") + #expect(!sql.contains("UNION ALL")) + } + + @Test("A server that reports 10 but carries no pg_sequences still lists its sequences") + func missingCatalogFallsBackToParameters() { + #expect(PostgreSQLSequenceQueries.source(hasSequencesCatalog: false) == .sequenceParameters) + #expect(PostgreSQLSequenceQueries.source(hasSequencesCatalog: true) == .sequencesView) + } + + @Test("The pre-10 listing tests each sequence's privileges once, in a derived table the planner cannot flatten") + func privilegesReadOncePerSequence() { + let sql = PostgreSQLSequenceQueries.sequenceList( + schema: "public", dependentOnTable: nil, source: .sequenceParameters + ) + #expect(sql.components(separatedBy: "has_sequence_privilege").count - 1 == 2) + #expect(sql.contains("OFFSET 0")) + #expect(sql.contains("CASE WHEN s.can_read_parameters")) + #expect(!sql.contains("AS parameters")) + } + + @Test("Rows decode with booleans in any of the server's spellings") + func definitionsDecode() { + let rows: [[PluginCellValue]] = [ + [.text("we,ird_seq"), .text("7"), .text("5"), .text("50"), .text("1"), .text("t"), .null, .text("true")], + [.text("hidden"), .null, .null, .null, .null, .null, .null, .text("f")] + ] + let definitions = PostgreSQLSequenceQueries.definitions(from: rows) + #expect(definitions.count == 2) + #expect(definitions[0].cycles) + #expect(definitions[0].needsLastValueRead) + #expect(!definitions[1].cycles) + #expect(!definitions[1].needsLastValueRead) + } + + @Test("A sequence with known parameters restores with them and its position") + func fullDefinition() { + let definition = PostgreSQLSequenceDefinition( + name: "invoice_seq", startValue: "1000", minValue: "1", maxValue: "9223372036854775807", + increment: "5", cycles: false, lastValue: "1005", needsLastValueRead: false + ) + #expect(definition.ddl == """ + CREATE SEQUENCE "invoice_seq" INCREMENT BY 5 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1000; + SELECT pg_catalog.setval('"invoice_seq"', 1005, true); + """) + } + + @Test("A sequence whose parameters the role could not read is still created, with defaults") + func unknownParameters() { + let definition = PostgreSQLSequenceDefinition( + name: "hidden", startValue: nil, minValue: nil, maxValue: nil, increment: nil, + cycles: false, lastValue: nil, needsLastValueRead: false + ) + #expect(definition.ddl == "CREATE SEQUENCE \"hidden\";") + } + + @Test("The setval target is an identifier inside a literal, so a quote in the name cannot break either") + func hostileNameInSetval() { + let definition = PostgreSQLSequenceDefinition( + name: "we\"ird's", startValue: "7", minValue: "5", maxValue: "50", increment: "1", + cycles: true, lastValue: "8", needsLastValueRead: false + ) + #expect(definition.ddl.hasPrefix("CREATE SEQUENCE \"we\"\"ird's\" INCREMENT BY 1 MINVALUE 5 MAXVALUE 50 START WITH 7 CYCLE;")) + #expect(definition.ddl.hasSuffix("SELECT pg_catalog.setval('\"we\"\"ird''s\"', 8, true);")) + } + + @Test("A last value that is not a number is left out rather than interpolated") + func nonNumericLastValue() { + let definition = PostgreSQLSequenceDefinition( + name: "s", startValue: "1", minValue: "1", maxValue: "10", increment: "1", + cycles: false, lastValue: "1); DROP TABLE t; --", needsLastValueRead: false + ) + #expect(!definition.ddl.contains("setval")) + } + + @Test("Reading a last value clears the pending read") + func withLastValue() { + let definition = PostgreSQLSequenceDefinition( + name: "s", startValue: "1", minValue: "1", maxValue: "10", increment: "1", + cycles: false, lastValue: nil, needsLastValueRead: true + ) + let read = definition.withLastValue("4") + #expect(read.lastValue == "4") + #expect(!read.needsLastValueRead) + } +} + +@Suite("PostgreSQL collation and table metadata reads") +struct PostgreSQLCollationAndMetadataQueryTests { + @Test("Before PostgreSQL 10 every collation but the default is a libc one") + func legacyCollations() { + let sql = PostgreSQLSchemaQueries.collationList(capabilities: PostgreSQLCapabilities(serverVersion: 90_624)) + #expect(!sql.contains("collprovider")) + #expect(sql.contains("WHERE oid <> 100")) + let modern = PostgreSQLSchemaQueries.collationList(capabilities: PostgreSQLCapabilities(serverVersion: 170_000)) + #expect(modern.contains("collprovider IN ('b', 'c', 'i')")) + } + + @Test("Table sizes and comments are read by relation oid, so a mixed-case name resolves") + func allTablesMetadataUsesRelid() { + let sql = PostgreSQLSchemaQueries.allTablesMetadata(schema: "app") + #expect(sql.contains("pg_total_relation_size(relid)")) + #expect(sql.contains("obj_description(relid, 'pg_class')")) + #expect(!sql.contains("::regclass")) + #expect(!sql.contains("||'.'||")) + } + + @Test("The schema is quoted as a literal") + func allTablesMetadataQuotesSchema() { + #expect(PostgreSQLSchemaQueries.allTablesMetadata(schema: "o'brien").contains("schemaname = 'o''brien'")) + #expect(PostgreSQLSchemaQueries.allTablesMetadata(schema: "a\\b").contains("schemaname = E'a\\\\b'")) + } +} + +@Suite("PostgreSQL grant reads") +struct PostgreSQLGrantQueryTests { + @Test("aclexplode runs in a subquery's select list, which PostgreSQL 9.1 accepts") + func grantsAvoidLateral() { + let queries = [ + PostgreSQLPrincipalQueries.databaseGrants(roleLiteral: "reader"), + PostgreSQLPrincipalQueries.schemaGrants(roleLiteral: "reader"), + PostgreSQLPrincipalQueries.tableGrants(roleLiteral: "reader"), + PostgreSQLPrincipalQueries.columnGrants(roleLiteral: "reader") + ] + for sql in queries { + #expect(!sql.contains("LATERAL")) + #expect(sql.contains("pg_catalog.aclexplode(")) + #expect(sql.contains("JOIN pg_roles r ON r.oid = (s.acl).grantee")) + #expect(sql.contains("r.rolname = 'reader'")) + } + } +} + +@Suite("PostgreSQL catalog booleans") +struct PostgreSQLCatalogBooleanTests { + @Test("The driver hands a boolean column over as true or false, and a text cast may say t or f") + func spellings() { + #expect(PostgreSQLCatalogBoolean.isTrue("true")) + #expect(PostgreSQLCatalogBoolean.isTrue("t")) + #expect(PostgreSQLCatalogBoolean.isTrue("TRUE")) + #expect(PostgreSQLCatalogBoolean.isTrue("YES")) + #expect(PostgreSQLCatalogBoolean.isTrue("on")) + #expect(PostgreSQLCatalogBoolean.isTrue("1")) + #expect(!PostgreSQLCatalogBoolean.isTrue("false")) + #expect(!PostgreSQLCatalogBoolean.isTrue("f")) + #expect(!PostgreSQLCatalogBoolean.isTrue("no")) + #expect(!PostgreSQLCatalogBoolean.isTrue("off")) + #expect(!PostgreSQLCatalogBoolean.isTrue("0")) + #expect(!PostgreSQLCatalogBoolean.isTrue("")) + #expect(!PostgreSQLCatalogBoolean.isTrue(nil)) + } + + @Test("A primary key index decoded from the driver's boolean text is unique and primary") + func primaryKeyIndexKeepsItsFlags() throws { + let row: [PluginCellValue] = [ + .text("orders"), .text("orders_pkey"), .text("{id}"), .text("true"), .text("true"), .text("btree"), .null + ] + let decoded = try #require(PostgreSQLIndexRow.index(from: row)) + #expect(decoded.index.isUnique) + #expect(decoded.index.isPrimary) + } +} diff --git a/TableProTests/Plugins/PostgreSQLPartitionFilterTests.swift b/TableProTests/Plugins/PostgreSQLPartitionFilterTests.swift index 87956a55b1..b4ed54fc60 100644 --- a/TableProTests/Plugins/PostgreSQLPartitionFilterTests.swift +++ b/TableProTests/Plugins/PostgreSQLPartitionFilterTests.swift @@ -6,7 +6,7 @@ import Testing struct PostgreSQLPartitionFilterTests { private func awareQuery() -> String { PostgreSQLSchemaQueries.fetchTables( - schemaLiteral: "public", + schema: "public", includeMaterializedViews: false, includeForeignTables: false ) @@ -42,7 +42,7 @@ struct PostgreSQLPartitionFilterTests { @Test("Partition awareness degrades independently of the optional catalogs") func partitionAwarenessDegradesIndependently() { let query = PostgreSQLSchemaQueries.fetchTables( - schemaLiteral: "public", + schema: "public", includeMaterializedViews: true, includeForeignTables: true, includePartitionAwareness: false @@ -56,7 +56,7 @@ struct PostgreSQLPartitionFilterTests { @Test("Every union branch still projects three aligned columns when partition aware") func unionBranchesStayAligned() { let query = PostgreSQLSchemaQueries.fetchTables( - schemaLiteral: "public", + schema: "public", includeMaterializedViews: true, includeForeignTables: true ) diff --git a/TableProTests/Plugins/PostgreSQLTypeDefinitionTests.swift b/TableProTests/Plugins/PostgreSQLTypeDefinitionTests.swift index e2b042486a..2c0da383df 100644 --- a/TableProTests/Plugins/PostgreSQLTypeDefinitionTests.swift +++ b/TableProTests/Plugins/PostgreSQLTypeDefinitionTests.swift @@ -193,7 +193,7 @@ struct PostgreSQLTypeDefinitionTests { #expect(ddl.hasPrefix("CREATE TYPE \"my schema\".\"Weird \"\"Name\"\"\" AS ENUM (")) } - @Test("A catalog row parses by projection position, JSON columns included") + @Test("A catalog row parses by projection position, array columns included") func rowParsing() throws { var row = [PluginCellValue](repeating: .null, count: PostgreSQLTypeDefinition.Column.allCases.count) row[PostgreSQLTypeDefinition.Column.identity.rawValue] = .text("16397") @@ -206,8 +206,9 @@ struct PostgreSQLTypeDefinitionTests { row[PostgreSQLTypeDefinition.Column.collation.rawValue] = .text("pg_catalog.\"C\"") row[PostgreSQLTypeDefinition.Column.isNotNull.rawValue] = .text("true") row[PostgreSQLTypeDefinition.Column.defaultValue.rawValue] = .text("'x'::text") - row[PostgreSQLTypeDefinition.Column.constraints.rawValue] = .text( - #"[{"name" : "email_check", "definition" : "CHECK ((VALUE ~ '@'::text))"}]"# + row[PostgreSQLTypeDefinition.Column.constraintNames.rawValue] = .text("{email_check}") + row[PostgreSQLTypeDefinition.Column.constraintDefinitions.rawValue] = .text( + #"{"CHECK ((VALUE ~ '@'::text))"}"# ) let parsed = try #require(PostgreSQLTypeDefinition.record(from: row)) @@ -222,23 +223,23 @@ struct PostgreSQLTypeDefinitionTests { #expect(parsed.comment == "Mail") } - @Test("Enum labels and composite fields parse from their JSON aggregates in order") - func jsonAggregatesParse() throws { + @Test("Enum labels and composite fields parse from their array aggregates in order") + func arrayAggregatesParse() throws { var enumRow = [PluginCellValue](repeating: .null, count: PostgreSQLTypeDefinition.Column.allCases.count) enumRow[PostgreSQLTypeDefinition.Column.identity.rawValue] = .text("1") enumRow[PostgreSQLTypeDefinition.Column.name.rawValue] = .text("mood") enumRow[PostgreSQLTypeDefinition.Column.schema.rawValue] = .text("app") enumRow[PostgreSQLTypeDefinition.Column.kind.rawValue] = .text("e") - enumRow[PostgreSQLTypeDefinition.Column.enumLabels.rawValue] = .text(#"["sad", "ok", "it's"]"#) + enumRow[PostgreSQLTypeDefinition.Column.enumLabels.rawValue] = .text("{sad,ok,it's}") let parsedEnum = try #require(PostgreSQLTypeDefinition.record(from: enumRow)) #expect(parsedEnum.enumLabels == ["sad", "ok", "it's"]) var compositeRow = enumRow compositeRow[PostgreSQLTypeDefinition.Column.kind.rawValue] = .text("c") compositeRow[PostgreSQLTypeDefinition.Column.enumLabels.rawValue] = .null - compositeRow[PostgreSQLTypeDefinition.Column.fields.rawValue] = .text( - #"[{"name" : "x", "type" : "text", "collation" : "pg_catalog.\"C\""}, {"name" : "y", "type" : "integer", "collation" : null}]"# - ) + compositeRow[PostgreSQLTypeDefinition.Column.fieldNames.rawValue] = .text("{x,y}") + compositeRow[PostgreSQLTypeDefinition.Column.fieldTypes.rawValue] = .text("{text,integer}") + compositeRow[PostgreSQLTypeDefinition.Column.fieldCollations.rawValue] = .text(#"{"pg_catalog.\"C\"",NULL}"#) compositeRow[PostgreSQLTypeDefinition.Column.spelling.rawValue] = .text("app.\"Mood\"") let parsedComposite = try #require(PostgreSQLTypeDefinition.record(from: compositeRow)) #expect(parsedComposite.fields == [ @@ -249,6 +250,60 @@ struct PostgreSQLTypeDefinitionTests { #expect(PostgreSQLTypeDefinition.info(from: parsedComposite).columnTypeSpelling == "app.\"Mood\"") } + @Test("Labels, field names and constraint names survive the characters an array literal quotes") + func hostileNamesSurviveArrayDecoding() throws { + var enumRow = [PluginCellValue](repeating: .null, count: PostgreSQLTypeDefinition.Column.allCases.count) + enumRow[PostgreSQLTypeDefinition.Column.identity.rawValue] = .text("1") + enumRow[PostgreSQLTypeDefinition.Column.name.rawValue] = .text("lbl") + enumRow[PostgreSQLTypeDefinition.Column.schema.rawValue] = .text("public") + enumRow[PostgreSQLTypeDefinition.Column.kind.rawValue] = .text("e") + enumRow[PostgreSQLTypeDefinition.Column.enumLabels.rawValue] = .text( + #"{"very happy","sad,ish","NULL","q\"t","back\\\\slash",""}"# + ) + let parsedEnum = try #require(PostgreSQLTypeDefinition.record(from: enumRow)) + #expect(parsedEnum.enumLabels == ["very happy", "sad,ish", "NULL", "q\"t", "back\\\\slash", ""]) + + var compositeRow = enumRow + compositeRow[PostgreSQLTypeDefinition.Column.kind.rawValue] = .text("c") + compositeRow[PostgreSQLTypeDefinition.Column.enumLabels.rawValue] = .null + compositeRow[PostgreSQLTypeDefinition.Column.fieldNames.rawValue] = .text(#"{"first name","q\"t","NULL"}"#) + compositeRow[PostgreSQLTypeDefinition.Column.fieldTypes.rawValue] = .text("{text,integer,text}") + compositeRow[PostgreSQLTypeDefinition.Column.fieldCollations.rawValue] = .text(#"{"pg_catalog.\"C\"",NULL,NULL}"#) + let parsedComposite = try #require(PostgreSQLTypeDefinition.record(from: compositeRow)) + #expect(parsedComposite.fields == [ + PluginUserDefinedTypeField(name: "first name", type: "text", collation: "pg_catalog.\"C\""), + PluginUserDefinedTypeField(name: "q\"t", type: "integer"), + PluginUserDefinedTypeField(name: "NULL", type: "text") + ]) + + var domainRow = enumRow + domainRow[PostgreSQLTypeDefinition.Column.kind.rawValue] = .text("d") + domainRow[PostgreSQLTypeDefinition.Column.enumLabels.rawValue] = .null + domainRow[PostgreSQLTypeDefinition.Column.baseType.rawValue] = .text("text") + domainRow[PostgreSQLTypeDefinition.Column.constraintNames.rawValue] = .text(#"{b_len,"has,comma"}"#) + domainRow[PostgreSQLTypeDefinition.Column.constraintDefinitions.rawValue] = .text( + #"{"CHECK ((length(VALUE) < 10))","CHECK ((VALUE <> ''::text))"}"# + ) + let parsedDomain = try #require(PostgreSQLTypeDefinition.record(from: domainRow)) + #expect(parsedDomain.constraints == [ + PostgreSQLDomainConstraint(name: "b_len", definition: "CHECK ((length(VALUE) < 10))"), + PostgreSQLDomainConstraint(name: "has,comma", definition: "CHECK ((VALUE <> ''::text))") + ]) + } + + @Test("A type with no fields, labels or constraints reads NULL aggregates as empty") + func nullAggregatesAreEmpty() throws { + var row = [PluginCellValue](repeating: .null, count: PostgreSQLTypeDefinition.Column.allCases.count) + row[PostgreSQLTypeDefinition.Column.identity.rawValue] = .text("1") + row[PostgreSQLTypeDefinition.Column.name.rawValue] = .text("empty") + row[PostgreSQLTypeDefinition.Column.schema.rawValue] = .text("public") + row[PostgreSQLTypeDefinition.Column.kind.rawValue] = .text("c") + let parsed = try #require(PostgreSQLTypeDefinition.record(from: row)) + #expect(parsed.fields.isEmpty) + #expect(parsed.enumLabels.isEmpty) + #expect(parsed.constraints.isEmpty) + } + @Test("A row of an unknown kind is skipped rather than mislabelled") func unknownKindIsSkipped() { var row = [PluginCellValue](repeating: .null, count: PostgreSQLTypeDefinition.Column.allCases.count) diff --git a/TableProTests/Plugins/PostgreSQLTypeQueryTests.swift b/TableProTests/Plugins/PostgreSQLTypeQueryTests.swift index 7573b9a321..4132156878 100644 --- a/TableProTests/Plugins/PostgreSQLTypeQueryTests.swift +++ b/TableProTests/Plugins/PostgreSQLTypeQueryTests.swift @@ -15,7 +15,7 @@ import Testing struct PostgreSQLTypeQueryTests { @Test("The listing reads pg_type for enums, composites, domains and ranges in one schema") func listReadsPgType() { - let sql = PostgreSQLObjectQueries.userDefinedTypeList(schema: "app", identity: nil, serverVersionNumber: 170_000) + let sql = PostgreSQLObjectQueries.userDefinedTypeList(schema: "app", identity: nil, capabilities: .assumingModernWhenUnknown(170_000)) #expect(sql.contains("FROM pg_catalog.pg_type t")) #expect(sql.contains("t.typtype IN ('e', 'c', 'd', 'r')")) #expect(sql.contains("AND n.nspname = 'app'")) @@ -26,7 +26,7 @@ struct PostgreSQLTypeQueryTests { /// the extension. Neither is a type the user created. @Test("Table row types and extension members are excluded") func excludesRowTypesAndExtensionMembers() { - let sql = PostgreSQLObjectQueries.userDefinedTypeList(schema: "app", identity: nil, serverVersionNumber: 170_000) + let sql = PostgreSQLObjectQueries.userDefinedTypeList(schema: "app", identity: nil, capabilities: .assumingModernWhenUnknown(170_000)) #expect(sql.contains("(t.typtype <> 'c' OR c.relkind = 'c')")) #expect(sql.contains("d.deptype = 'e'")) } @@ -35,16 +35,17 @@ struct PostgreSQLTypeQueryTests { /// would state the same thing twice in the definition. @Test("Only CHECK constraints are collected for a domain") func domainConstraintsAreChecksOnly() { - let sql = PostgreSQLObjectQueries.userDefinedTypeList(schema: "app", identity: nil, serverVersionNumber: 170_000) + let sql = PostgreSQLObjectQueries.userDefinedTypeList(schema: "app", identity: nil, capabilities: .assumingModernWhenUnknown(170_000)) #expect(sql.contains("con.contype = 'c'")) } @Test("The projection matches the parser's column order") func projectionOrderMatchesParser() { - let sql = PostgreSQLObjectQueries.userDefinedTypeList(schema: "app", identity: nil, serverVersionNumber: 170_000) + let sql = PostgreSQLObjectQueries.userDefinedTypeList(schema: "app", identity: nil, capabilities: .assumingModernWhenUnknown(170_000)) let aliases = [ "AS identity", "AS name", "AS schema", "AS kind", "AS owner", "AS comment", "AS enum_labels", - "AS fields", "AS base_type", "AS collation", "AS not_null", "AS default_value", "AS constraints", + "AS field_names", "AS field_types", "AS field_collations", "AS base_type", "AS collation", + "AS not_null", "AS default_value", "AS constraint_names", "AS constraint_definitions", "AS range_subtype", "AS range_canonical", "AS range_subtype_diff", "AS range_opclass", "AS range_collation", "AS range_multirange", "AS spelling" ] @@ -63,7 +64,7 @@ struct PostgreSQLTypeQueryTests { @Test("A reload addresses one oid and nothing else") func identityPredicate() { let sql = PostgreSQLObjectQueries.userDefinedTypeList( - schema: nil, identity: "16387", serverVersionNumber: 170_000 + schema: nil, identity: "16387", capabilities: .assumingModernWhenUnknown(170_000) ) #expect(sql.contains("AND t.oid = 16387::oid")) #expect(!sql.contains("n.nspname =")) @@ -72,7 +73,7 @@ struct PostgreSQLTypeQueryTests { @Test("A listing escapes the schema literal") func schemaLiteral() { let sql = PostgreSQLObjectQueries.userDefinedTypeList( - schema: "o'brien", identity: nil, serverVersionNumber: 170_000 + schema: "o'brien", identity: nil, capabilities: .assumingModernWhenUnknown(170_000) ) #expect(sql.contains("AND n.nspname = 'o''brien'")) #expect(!sql.contains("AND t.oid = ")) @@ -82,16 +83,16 @@ struct PostgreSQLTypeQueryTests { /// knows its own reserved words and folding, is what quotes it. @Test("The listing carries the server's own quoted, qualified spelling of each type") func listingCarriesSpelling() { - let sql = PostgreSQLObjectQueries.userDefinedTypeList(schema: "app", identity: nil, serverVersionNumber: 170_000) + let sql = PostgreSQLObjectQueries.userDefinedTypeList(schema: "app", identity: nil, capabilities: .assumingModernWhenUnknown(170_000)) #expect(sql.contains("pg_catalog.quote_ident(n.nspname) || '.' || pg_catalog.quote_ident(t.typname) AS spelling")) } @Test("A server before 14 has no multirange to report") func legacyServerSkipsMultirange() { - let sql = PostgreSQLObjectQueries.userDefinedTypeList(schema: "app", identity: nil, serverVersionNumber: 130_000) + let sql = PostgreSQLObjectQueries.userDefinedTypeList(schema: "app", identity: nil, capabilities: .assumingModernWhenUnknown(130_000)) #expect(sql.contains("NULL::text AS range_multirange")) #expect(!sql.contains("rngmultitypid")) - let modern = PostgreSQLObjectQueries.userDefinedTypeList(schema: "app", identity: nil, serverVersionNumber: 140_000) + let modern = PostgreSQLObjectQueries.userDefinedTypeList(schema: "app", identity: nil, capabilities: .assumingModernWhenUnknown(140_000)) #expect(modern.contains("rngmultitypid")) } @@ -100,7 +101,7 @@ struct PostgreSQLTypeQueryTests { @Test("A non-numeric identity is ignored rather than interpolated") func nonNumericIdentityIsIgnored() { let sql = PostgreSQLObjectQueries.userDefinedTypeList( - schema: "app", identity: "1 OR 1=1", serverVersionNumber: 170_000 + schema: "app", identity: "1 OR 1=1", capabilities: .assumingModernWhenUnknown(170_000) ) #expect(!sql.contains("AND t.oid = ")) #expect(!sql.contains("OR 1=1")) @@ -117,7 +118,7 @@ struct PostgreSQLTypeQueryTests { #expect(PostgreSQLObjectQueries.quoteLiteral("\\'; DROP TYPE x; --") == "E'\\\\''; DROP TYPE x; --'") let sql = PostgreSQLObjectQueries.userDefinedTypeList( - schema: "a\\'b", identity: nil, serverVersionNumber: 170_000 + schema: "a\\'b", identity: nil, capabilities: .assumingModernWhenUnknown(170_000) ) #expect(sql.contains("AND n.nspname = E'a\\\\''b'")) #expect( @@ -129,26 +130,41 @@ struct PostgreSQLTypeQueryTests { @Test("A server before 9.2 has no pg_range and lists no ranges") func legacyServerSkipsRanges() { - let sql = PostgreSQLObjectQueries.userDefinedTypeList(schema: "app", identity: nil, serverVersionNumber: 90_100) + let sql = PostgreSQLObjectQueries.userDefinedTypeList(schema: "app", identity: nil, capabilities: .assumingModernWhenUnknown(90_100)) #expect(!sql.contains("pg_range")) #expect(sql.contains("t.typtype IN ('e', 'c', 'd')")) #expect(sql.contains("NULL::text AS range_subtype")) } - @Test("A server before 9.4 has no json_build_object and reports no fields or constraints") - func legacyServerSkipsJsonObjects() { - let sql = PostgreSQLObjectQueries.userDefinedTypeList(schema: "app", identity: nil, serverVersionNumber: 90_300) - #expect(!sql.contains("json_build_object")) - #expect(sql.contains("NULL::text AS fields")) + @Test("A server before 9.4 still reports composite fields and domain CHECK constraints") + func legacyServerReportsFieldsAndConstraints() { + for version: Int32 in [90_124, 90_300] { + let sql = PostgreSQLObjectQueries.userDefinedTypeList( + schema: "app", identity: nil, capabilities: PostgreSQLCapabilities(serverVersion: version) + ) + #expect(!sql.contains("NULL::text AS field_names")) + #expect(sql.contains("array_agg(a.attname ORDER BY a.attnum)")) + #expect(sql.contains("array_agg(pg_catalog.pg_get_constraintdef(con.oid) ORDER BY con.conname)")) + } + } + + @Test("No server version reads a JSON function or type, which 9.1 does not have") + func listingNeverUsesJson() { + for version: Int32 in [90_124, 90_300, 90_400, 170_000] { + let sql = PostgreSQLObjectQueries.userDefinedTypeList( + schema: "app", identity: nil, capabilities: PostgreSQLCapabilities(serverVersion: version) + ) + #expect(!sql.lowercased().contains("json")) + } } /// libpq answers 0 for a handle it has not connected, and reading that as ancient would emit /// the legacy projection on every current server. @Test("An unknown server version reads as modern") func unknownVersionIsModern() { - let sql = PostgreSQLObjectQueries.userDefinedTypeList(schema: "app", identity: nil, serverVersionNumber: 0) + let sql = PostgreSQLObjectQueries.userDefinedTypeList(schema: "app", identity: nil, capabilities: .assumingModernWhenUnknown(0)) #expect(sql.contains("pg_range")) - #expect(sql.contains("json_build_object")) + #expect(sql.contains("rngmultitypid")) } @Test("Adding a label appends by default and places beside a neighbour when asked") diff --git a/TableProTests/Plugins/PostgreSQLViewDefinitionTests.swift b/TableProTests/Plugins/PostgreSQLViewDefinitionTests.swift index f60efcbf34..5eba57e5b1 100644 --- a/TableProTests/Plugins/PostgreSQLViewDefinitionTests.swift +++ b/TableProTests/Plugins/PostgreSQLViewDefinitionTests.swift @@ -134,22 +134,23 @@ struct PostgreSQLViewDefinitionTests { } } - /// Read as JSON rather than by splitting the array text, because an option value may hold a - /// comma or a quote of its own. - @Test("Options are parsed from JSON, commas inside a value included") - func optionsParsedFromJSON() { - #expect(PostgreSQLViewDefinition.options(fromJSON: #"["security_barrier=true"]"#) == ["security_barrier=true"]) - #expect(PostgreSQLViewDefinition.options(fromJSON: #"["toast.autovacuum_enabled=false","fillfactor=70"]"#) - == ["toast.autovacuum_enabled=false", "fillfactor=70"]) - #expect(PostgreSQLViewDefinition.options(fromJSON: #"["note=a, b"]"#) == ["note=a, b"]) - #expect(PostgreSQLViewDefinition.options(fromJSON: nil).isEmpty) - #expect(PostgreSQLViewDefinition.options(fromJSON: "").isEmpty) + /// `reloptions` is read as array text: `array_to_json` does not exist on PostgreSQL 9.1. The + /// array decoder honours quoting, so a value holding a comma or a quote stays one option. + @Test("Options are decoded from the array text, commas and quotes inside a value included") + func optionsDecodedFromArrayText() { + let options: (String?) -> [String]? = { text in + PostgreSQLViewDefinition.parse(row: ["v", "SELECT 1", text, nil, nil])?.options + } + #expect(options("{security_barrier=true}") == ["security_barrier=true"]) + #expect(options("{fillfactor=70,autovacuum_enabled=false}") == ["fillfactor=70", "autovacuum_enabled=false"]) + #expect(options(#"{"note=a, b","q=\"x\""}"#) == ["note=a, b", #"q="x""#]) + #expect(options(nil)?.isEmpty == true) } @Test("A catalog row parses into the kind, query, options and storage") func parseRow() { let parsed = PostgreSQLViewDefinition.parse(row: [ - "m", body, #"["fillfactor=70"]"#, "heap", "fast" + "m", body, "{fillfactor=70}", "heap", "fast" ]) #expect(parsed?.kind == .materializedView) @@ -166,17 +167,19 @@ struct PostgreSQLViewDefinitionTests { #expect(PostgreSQLViewDefinition.parse(row: ["v", body]) == nil) } - /// The body is read with `search_path` emptied, so every name in it is qualified and the text + /// The body is read with `search_path` narrowed to `pg_catalog`, so every name in it is qualified and the text /// binds to the same tables wherever it is run. - @Test("The catalog query empties the search path and addresses the view by schema and name") + @Test("The catalog query narrows the search path and addresses the view by schema and name") func catalogQueryIsQualifiedAndScoped() { let query = PostgreSQLViewDefinition.catalogQuery(name: "vw", schema: "sales") - #expect(PostgreSQLViewDefinition.qualifiedReadPrefix == "SET LOCAL search_path = ''; ") + #expect(PostgreSQLViewDefinition.qualifiedReadPrefix == "SET LOCAL search_path = pg_catalog; ") #expect(query.contains("pg_catalog.pg_get_viewdef(c.oid, true)")) #expect(query.contains("n.nspname = 'sales'")) #expect(query.contains("c.relname = 'vw'")) #expect(query.contains("c.relkind IN ('v', 'm')")) + #expect(query.contains("c.reloptions::text")) + #expect(!query.contains("json")) } @Test("A name that needs quoting is quoted, and a literal that needs escaping is escaped") diff --git a/docs/databases/postgresql.mdx b/docs/databases/postgresql.mdx index d8029a760f..7eddaf1d26 100644 --- a/docs/databases/postgresql.mdx +++ b/docs/databases/postgresql.mdx @@ -1,6 +1,6 @@ --- title: PostgreSQL -description: Connect to PostgreSQL 12 and later with the libpq driver, including PostGIS display, AWS IAM auth, and pg_dump backups +description: Connect to PostgreSQL with the libpq driver, including PostGIS display, AWS IAM auth, and pg_dump backups --- Unlike MySQL, PostgreSQL will not connect without a **Database**, and it changes database only by reconnecting. Everything else on the form is ordinary. The libpq driver ships inside the app and also serves [Amazon Redshift](/databases/redshift), [CockroachDB](/databases/cockroachdb), and [PGlite](/databases/pglite). @@ -16,7 +16,7 @@ Unlike MySQL, PostgreSQL will not connect without a **Database**, and it changes Fill in the form and click **Save & Connect**. For remote servers use [SSH tunneling](/connections/ssh-tunneling); Google Cloud SQL instances can connect through the [Cloud SQL Auth Proxy](/connections/cloud-sql-proxy). -Support starts at 12. An older server still connects, with whatever its catalogs carry: generated columns need 12, declarative partitioning and identity columns need 10. +The sidebar, the structure view, Users & Roles privileges and SQL export work from PostgreSQL 9.1. Generated columns need 12, declarative partitioning and identity columns need 10, and materialized views need 9.3. Some editing still needs a newer server; see [Limitations](#limitations). PostgreSQL connection form @@ -94,7 +94,8 @@ New connections default to **Preferred** (libpq `sslmode=prefer`): TLS first, pl - Columns cannot be reordered. The structure editor adds, renames, retypes, and drops; changing the order of existing columns means recreating the table. - A cross-database tab cannot share session state with the main connection. Statements that depend on a temp table or an open transaction have to run on one database. -- Backup and restore need `pg_dump` and `pg_restore` on your Mac. Neither is bundled; install them with Homebrew. +- Backup and restore need `pg_dump` and `pg_restore` on your Mac. Neither is bundled; install them with Homebrew. `pg_dump` 15 and later refuse PostgreSQL 9.1, so back one up with `pg_dump` 14 or earlier. +- Some edits fail with a syntax error on older servers: editing or creating a trigger before 14, creating a role or changing its attributes before 9.5, and copying objects into a schema that does not exist yet before 9.3. Run the statement from the query editor instead, with `DROP TRIGGER` then `CREATE TRIGGER`, or without `BYPASSRLS` and `IF NOT EXISTS`. ## Troubleshooting diff --git a/project.yml b/project.yml index 72d83f9240..4484ae98b2 100644 --- a/project.yml +++ b/project.yml @@ -519,16 +519,22 @@ targets: - Plugins/PostgreSQLDriverPlugin/LibPQStringConformance.swift - Plugins/PostgreSQLDriverPlugin/PostGISSpatialRewrite.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift + - Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogBoolean.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogForeignKeys.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogPresence.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogTypeNames.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLCheckConstraintDefinition.swift + - Plugins/PostgreSQLDriverPlugin/PostgreSQLForeignKeyQueries.swift + - Plugins/PostgreSQLDriverPlugin/PostgreSQLIndexQueries.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift + - Plugins/PostgreSQLDriverPlugin/PostgreSQLPrincipalQueries.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLRelationSQL.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLViewDefinition.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLSchemaQueries.swift + - Plugins/PostgreSQLDriverPlugin/PostgreSQLSequenceQueries.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLSystemDatabases.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLTableListingLadder.swift + - Plugins/PostgreSQLDriverPlugin/PostgreSQLTextArray.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLTransactionStatement.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLTypeDefinition.swift - Plugins/PostgreSQLDriverPlugin/RedshiftExternalSchemaQueries.swift diff --git a/scripts/check-postgres-object-queries.sh b/scripts/check-postgres-object-queries.sh deleted file mode 100755 index f0f2b873d6..0000000000 --- a/scripts/check-postgres-object-queries.sh +++ /dev/null @@ -1,149 +0,0 @@ -#!/usr/bin/env bash -# -# Run the PostgreSQL routine and trigger catalog queries against a live server and check the -# answers, so a hand-written query cannot drift from what the server actually returns. -# -# The queries in Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift are hand-written and -# nothing at runtime checks them. Three of the things they get right are only visible with real -# overloads in the catalog: -# - one row per routine, not one per pairing of a name with itself -# - a distinct oid per overload, which is what makes the DDL fetch address the right one -# - aggregates excluded, because pg_get_functiondef raises on them and would fail the whole list -# -# Usage: -# scripts/check-postgres-object-queries.sh [database] [schema] -# -# Defaults to the `postgres` database and a scratch schema it creates and drops. - -set -euo pipefail - -DATABASE="${1:-postgres}" -SCHEMA="${2:-tablepro_object_query_check}" - -if ! command -v psql > /dev/null 2>&1; then - echo "psql not found" >&2 - exit 2 -fi - -if ! psql -d "$DATABASE" -Atc 'SELECT 1' > /dev/null 2>&1; then - echo "cannot connect to database '$DATABASE'" >&2 - exit 2 -fi - -cleanup() { - psql -d "$DATABASE" -q -c "DROP SCHEMA IF EXISTS $SCHEMA CASCADE" > /dev/null 2>&1 || true -} -trap cleanup EXIT - -failures=0 - -fail() { - echo "FAIL: $1" >&2 - failures=$((failures + 1)) -} - -psql -d "$DATABASE" -q -v ON_ERROR_STOP=1 > /dev/null << SQL -DROP SCHEMA IF EXISTS $SCHEMA CASCADE; -CREATE SCHEMA $SCHEMA; -CREATE FUNCTION $SCHEMA.transform(a integer) RETURNS integer LANGUAGE sql IMMUTABLE AS \$\$ SELECT \$1 \$\$; -CREATE FUNCTION $SCHEMA.transform(a text) RETURNS integer LANGUAGE sql AS \$\$ SELECT 2 \$\$; -CREATE FUNCTION $SCHEMA.transform(a date, b int) RETURNS integer LANGUAGE sql AS \$\$ SELECT 3 \$\$; -CREATE PROCEDURE $SCHEMA.sync_orders() LANGUAGE plpgsql AS \$\$ BEGIN NULL; END \$\$; -CREATE AGGREGATE $SCHEMA.my_sum(int) (SFUNC = int4pl, STYPE = int); -CREATE TABLE $SCHEMA.orders(id int primary key, total numeric); -CREATE TABLE $SCHEMA.customers(id int primary key); -CREATE FUNCTION $SCHEMA.audit_fn() RETURNS trigger LANGUAGE plpgsql AS \$\$ BEGIN RETURN NEW; END \$\$; -CREATE TRIGGER audit BEFORE INSERT OR UPDATE ON $SCHEMA.orders - FOR EACH ROW WHEN (NEW.total > 0) EXECUTE FUNCTION $SCHEMA.audit_fn(); -CREATE TRIGGER audit AFTER DELETE ON $SCHEMA.customers - FOR EACH STATEMENT EXECUTE FUNCTION $SCHEMA.audit_fn(); -SQL - -ROUTINE_LIST=" -SELECT p.oid::text, p.proname, '(' || pg_catalog.pg_get_function_identity_arguments(p.oid) || ')', p.prokind -FROM pg_catalog.pg_proc p -JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace -JOIN pg_catalog.pg_language l ON l.oid = p.prolang -WHERE n.nspname = '$SCHEMA' - AND p.prokind IN ('f', 'p') - AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend d WHERE d.objid = p.oid AND d.deptype = 'e') -" - -rows=$(psql -d "$DATABASE" -Atc "$ROUTINE_LIST" | wc -l | tr -d ' ') -[ "$rows" = "5" ] || fail "routine list returned $rows rows, expected 5 (3 overloads, 1 procedure, 1 trigger function)" - -transform_rows=$(psql -d "$DATABASE" -Atc "$ROUTINE_LIST AND p.proname = 'transform'" | wc -l | tr -d ' ') -[ "$transform_rows" = "3" ] || fail "three overloads returned $transform_rows rows, expected 3" - -distinct_oids=$(psql -d "$DATABASE" -Atc "SELECT count(DISTINCT p.oid) FROM pg_catalog.pg_proc p - JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace - WHERE n.nspname = '$SCHEMA' AND p.proname = 'transform'") -[ "$distinct_oids" = "3" ] || fail "three overloads share $distinct_oids oids, expected 3 distinct" - -distinct_args=$(psql -d "$DATABASE" -Atc "SELECT count(DISTINCT pg_catalog.pg_get_function_identity_arguments(p.oid)) - FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace - WHERE n.nspname = '$SCHEMA' AND p.proname = 'transform'") -[ "$distinct_args" = "3" ] || fail "three overloads share $distinct_args argument signatures, expected 3 distinct" - -aggregates=$(psql -d "$DATABASE" -Atc "$ROUTINE_LIST AND p.proname = 'my_sum'" | wc -l | tr -d ' ') -[ "$aggregates" = "0" ] || fail "an aggregate reached the routine list; pg_get_functiondef raises on it" - -if psql -d "$DATABASE" -Atc "SELECT pg_catalog.pg_get_functiondef(p.oid) FROM pg_catalog.pg_proc p - JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace - WHERE n.nspname = '$SCHEMA' AND p.proname = 'my_sum'" > /dev/null 2>&1; then - echo "note: pg_get_functiondef no longer raises on an aggregate on this server version" -fi - -for oid in $(psql -d "$DATABASE" -Atc "SELECT p.oid FROM pg_catalog.pg_proc p - JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace - WHERE n.nspname = '$SCHEMA' AND p.proname = 'transform' ORDER BY p.oid"); do - args=$(psql -d "$DATABASE" -Atc "SELECT pg_catalog.pg_get_function_identity_arguments($oid)") - definition=$(psql -d "$DATABASE" -Atc "SELECT pg_catalog.pg_get_functiondef($oid::oid)" | head -1) - case "$definition" in - *"($args)"*) ;; - *) fail "pg_get_functiondef($oid) returned a definition for a different overload: $definition" ;; - esac -done - -TRIGGER_LIST=" -SELECT t.tgname, c.relname, - CASE WHEN (t.tgtype & 64) != 0 THEN 'INSTEAD OF' - WHEN (t.tgtype & 2) != 0 THEN 'BEFORE' ELSE 'AFTER' END, - array_to_string(array_remove(ARRAY[ - CASE WHEN (t.tgtype & 4) != 0 THEN 'INSERT' END, - CASE WHEN (t.tgtype & 8) != 0 THEN 'DELETE' END, - CASE WHEN (t.tgtype & 16) != 0 THEN 'UPDATE' END, - CASE WHEN (t.tgtype & 32) != 0 THEN 'TRUNCATE' END], NULL), ' OR '), - CASE WHEN (t.tgtype & 1) != 0 THEN 'ROW' ELSE 'STATEMENT' END -FROM pg_catalog.pg_trigger t -JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid -JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace -WHERE n.nspname = '$SCHEMA' AND NOT t.tgisinternal -ORDER BY c.relname, t.tgname -" - -trigger_rows=$(psql -d "$DATABASE" -Atc "$TRIGGER_LIST") -expected=$'audit|customers|AFTER|DELETE|STATEMENT\naudit|orders|BEFORE|INSERT OR UPDATE|ROW' -if [ "$trigger_rows" != "$expected" ]; then - fail "trigger list disagreed" - echo "expected:" >&2 - echo "$expected" >&2 - echo "got:" >&2 - echo "$trigger_rows" >&2 -fi - -definition=$(psql -d "$DATABASE" -Atc "SELECT pg_catalog.pg_get_triggerdef(t.oid) FROM pg_catalog.pg_trigger t - JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid - JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace - WHERE n.nspname = '$SCHEMA' AND c.relname = 'orders' AND t.tgname = 'audit'") -case "$definition" in - *"WHEN"*) ;; - *) fail "pg_get_triggerdef dropped the WHEN clause: $definition" ;; -esac - -if [ "$failures" -gt 0 ]; then - echo "$failures check(s) failed" >&2 - exit 1 -fi - -echo "PostgreSQL object catalog queries agree with $(psql -d "$DATABASE" -Atc 'SHOW server_version')" diff --git a/scripts/check-postgresql-compat.sh b/scripts/check-postgresql-compat.sh new file mode 100755 index 0000000000..77192673a2 --- /dev/null +++ b/scripts/check-postgresql-compat.sh @@ -0,0 +1,634 @@ +#!/bin/bash +# +# Runs the real PostgreSQL driver against one live server and checks what its catalog reads return. +# +# The driver's catalog SQL is hand-written, and a construct a newer server added fails at parse time +# on an older one, even inside a CASE branch that never runs. Nothing at runtime notices until a +# user on that server opens the sidebar. Every read below failed or answered wrongly on some +# PostgreSQL release before it was rewritten (#2734): to_regclass(text) is 9.6, LATERAL is 9.3, +# unnest WITH ORDINALITY and json_build_object are 9.4, to_json and json_agg are 9.3, pg_sequences +# and collprovider are 10, and array_position is 9.5. +# +# Builds TableProPluginKit and every PostgreSQL driver source with swiftc, loads a fixture into a +# scratch database, prints one canonical line per object each read returns, and diffs that against +# the answers below. A second pass connects as a role that owns nothing, because a read that works +# for the owner can still fail for a reader (a sequence the role cannot SELECT, for one). Overloads, +# aggregates and trigger WHEN clauses are in the fixture because the routine and trigger reads only +# go wrong with them present. +# +# Run it against each server you care about, oldest first. Docker has images from 9.1 on: +# docker run -d --rm -e POSTGRES_PASSWORD=probe -p 127.0.0.1:54091:5432 postgres:9.1 +# PGPASSWORD=probe scripts/check-postgresql-compat.sh 127.0.0.1 54091 +# +# Usage: scripts/check-postgresql-compat.sh [host] [port] [--keep] +# Environment: PGUSER (default postgres, must be a superuser), PGPASSWORD, PSQL. +# +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +HOST="${1:-127.0.0.1}" +PORT="${2:-5432}" +KEEP=0 +[[ "${3:-}" == "--keep" ]] && KEEP=1 +OWNER="${PGUSER:-postgres}" +DATABASE="tablepro_compat_check" +READER="tablepro_compat_reader" +READER_PASSWORD="tablepro_compat_reader" + +WORK="$(mktemp -d)" +[[ "$KEEP" == "1" ]] && echo "Working directory: $WORK" + +PSQL="${PSQL:-$(command -v psql || true)}" +if [[ -z "$PSQL" ]]; then + echo "FAIL: psql not found; set PSQL" >&2 + exit 2 +fi + +run_psql() { + "$PSQL" -X -q -v ON_ERROR_STOP=1 -h "$HOST" -p "$PORT" -U "$OWNER" "$@" +} + +if ! run_psql -d postgres -Atc 'SELECT 1' > /dev/null 2>&1; then + echo "FAIL: cannot connect to $HOST:$PORT as $OWNER" >&2 + exit 2 +fi +SERVER_VERSION="$(run_psql -d postgres -Atc "SELECT current_setting('server_version_num')")" +echo "Checking against PostgreSQL $(run_psql -d postgres -Atc 'SHOW server_version') ($SERVER_VERSION) at $HOST:$PORT" + +# Reports why it could not drop rather than hiding it: the CREATE DATABASE that follows would fail +# with "already exists", which names neither the leftover fixture nor the session still holding it. +drop_fixture() { + local output + if ! output="$(run_psql -d postgres -c "DROP DATABASE IF EXISTS $DATABASE" 2>&1)"; then + echo "$output" >&2 + return 1 + fi + if ! output="$(run_psql -d postgres -c "DROP ROLE IF EXISTS $READER" 2>&1)"; then + echo "$output" >&2 + return 1 + fi +} +cleanup() { + drop_fixture || echo "warning: fixture left behind; drop $DATABASE and $READER by hand" >&2 + [[ "$KEEP" == "1" ]] || rm -rf "$WORK" +} +trap cleanup EXIT + +if [[ -z "${DEVELOPER_DIR:-}" ]]; then + for candidate in /Applications/Xcode-beta.app/Contents/Developer /Applications/Xcode.app/Contents/Developer; do + if [[ -d "$candidate/usr/bin" ]]; then + export DEVELOPER_DIR="$candidate" + break + fi + done +fi + +KIT_DIR="$REPO_ROOT/Plugins/TableProPluginKit" +DRIVER_DIR="$REPO_ROOT/Plugins/PostgreSQLDriverPlugin" +LIBS="$REPO_ROOT/Libs" +for required in "$LIBS/libpq.a" "$LIBS/libpgcommon.a" "$LIBS/libpgport.a" "$LIBS/dylibs/libssl.3.dylib"; do + if [[ ! -e "$required" ]]; then + echo "FAIL: missing $required; run scripts/download-libs.sh" >&2 + exit 2 + fi +done + +# The driver class reaches every file in its folder, so the folder is the unit rather than a list. +KIT_SOURCES=() +while IFS= read -r file; do KIT_SOURCES+=("$file"); done < <(find "$KIT_DIR" -name '*.swift' | sort) +DRIVER_SOURCES=() +while IFS= read -r file; do DRIVER_SOURCES+=("$file"); done < <(find "$DRIVER_DIR" -maxdepth 1 -name '*.swift' | sort) + +cat > "$WORK/harness.swift" <<'SWIFT' +import Foundation +import TableProPluginKit + +@main +enum CompatHarness { + static func main() async { + let arguments = CommandLine.arguments + guard arguments.count >= 7 else { + FileHandle.standardError.write(Data("usage: harness host port user password database owner|reader\n".utf8)) + exit(2) + } + let config = DriverConnectionConfig( + host: arguments[1], + port: Int(arguments[2]) ?? 5432, + username: arguments[3], + password: arguments[4], + database: arguments[5] + ) + let driver = PostgreSQLPluginDriver(config: config) + do { + try await driver.connect() + } catch { + print("error|connect|\(error.localizedDescription)") + exit(1) + } + if arguments[6] == "reader" { + await readerPass(driver) + } else { + await ownerPass(driver) + } + driver.disconnect() + } + + static func line(_ fields: [String]) { + print(fields.map { $0.replacingOccurrences(of: "\n", with: "\\n") }.joined(separator: "|")) + } + + static func attempt(_ label: String, _ body: () async throws -> Void) async { + do { + try await body() + } catch { + line(["error", label, error.localizedDescription]) + } + } + + static func ownerPass(_ driver: PostgreSQLPluginDriver) async { + await attempt("fetchTables") { + for table in try await driver.fetchTables(schema: "public") { + line(["table", table.name, table.type, table.comment ?? "-"]) + } + } + await attempt("fetchAllForeignKeys") { + let all = try await driver.fetchAllForeignKeys(schema: "public") + for (table, keys) in all.sorted(by: { $0.key < $1.key }) { + for (name, pairs) in foreignKeyPairs(keys) { + line(["fk", table, name, pairs]) + } + } + } + await attempt("fetchForeignKeys") { + for (name, pairs) in foreignKeyPairs(try await driver.fetchForeignKeys(table: "fk_child", schema: "public")) { + line(["fk-table", "fk_child", name, pairs]) + } + for (name, pairs) in foreignKeyPairs(try await driver.fetchForeignKeys(table: "part_child", schema: "public")) { + line(["fk-table", "part_child", name, pairs]) + } + } + await attempt("fetchColumns") { + for column in try await driver.fetchColumns(table: "orders", schema: "public") { + line([ + "column", "orders", column.name, column.dataType, + column.isNullable ? "null" : "not-null", column.isPrimaryKey ? "pk" : "-", + column.defaultValue ?? "-", column.comment ?? "-", + column.isIdentity ? "identity" : "-", column.isGenerated ? "generated" : "-" + ]) + } + } + await attempt("fetchAllColumns") { + let all = try await driver.fetchAllColumns(schema: "public") + for (table, columns) in all.sorted(by: { $0.key < $1.key }) { + line(["columns", table, columns.map(\.name).joined(separator: ";")]) + } + } + await attempt("fetchTableDDL") { + for table in ["orders", "Mixed Case", "we,ird"] { + let ddl = try await driver.fetchTableDDL(table: table, schema: "public") + let columns = try await driver.fetchColumns(table: table, schema: "public") + line(["ddl", table, ddlShape(ddl, columns: columns)]) + } + } + await attempt("fetchAllIndexes") { + let all = try await driver.fetchAllIndexes(schema: "public") + for (table, indexes) in all.sorted(by: { $0.key < $1.key }) { + for index in indexes { + line([ + "index", table, index.name, index.columns.joined(separator: ";"), + index.isUnique ? "unique" : "-", index.isPrimary ? "primary" : "-", index.type, + index.whereClause ?? "-" + ]) + } + } + } + await attempt("fetchIndexes") { + for index in try await driver.fetchIndexes(table: "idx_t", schema: "public") { + line(["index-table", "idx_t", index.name, index.columns.joined(separator: ";")]) + } + } + await attempt("fetchCheckConstraints") { + for check in try await driver.fetchCheckConstraints(table: "we,ird", schema: "public") { + line([ + "check", "we,ird", check.name, check.expression, check.columns.joined(separator: ";"), + check.isValidated ? "validated" : "not-validated" + ]) + } + } + await attempt("fetchAllTriggers") { + for trigger in try await driver.fetchTriggers(table: "orders", schema: "public") { + line([ + "trigger", trigger.table ?? "-", trigger.name, trigger.timing, trigger.event, + trigger.orientation ?? "-", trigger.enabled == true ? "enabled" : "disabled" + ]) + if trigger.name == "orders_touch" { + line(["trigger-when", trigger.name, (trigger.definition ?? "").contains(" WHEN ") ? "yes" : "no"]) + } + } + } + await attempt("fetchUserDefinedTypes") { + for type in try await driver.fetchUserDefinedTypes(schema: "public") { + line(["type", type.name, type.definition ?? "-"]) + } + } + await attempt("fetchRoutines") { + for routine in try await driver.fetchRoutines(schema: "public") { + line(["routine", routine.name, routine.argumentSignature ?? "-"]) + guard routine.name == "transform", let signature = routine.argumentSignature else { continue } + let ddl = try await driver.fetchRoutineDDL(routine) + line(["routine-ddl", signature, ddl.contains("transform\(signature)") ? "yes" : "no"]) + } + } + await attempt("fetchSequences") { + for sequence in try await driver.fetchSequences(schema: "public") { + line(["sequence", sequence.name, sequence.ddl]) + } + } + await attempt("fetchDependentSequences") { + for sequence in try await driver.fetchDependentSequences(table: "orders", schema: "public") { + line(["dependent-sequence", "orders", sequence.name, sequence.ddl]) + } + } + await attempt("fetchGrants") { + let grants = try await driver.fetchGrants(for: PluginPrincipalRef(name: "tablepro_compat_reader")) + for grant in grants.map({ "\($0.scope)|\($0.privilege)" }).sorted() { + print("grant|\(grant)") + } + } + await attempt("createDatabaseFormSpec") { + let template = try await driver.execute(query: "SELECT datcollate FROM pg_database WHERE datname = 'template1'") + let collate = template.rows.first?.first?.asText ?? "" + let spec = try await driver.createDatabaseFormSpec() + var hasTemplateCollation = false + if let field = spec?.fields.first(where: { $0.id == "collation" }), + case .searchable(let options, _) = field.kind { + hasTemplateCollation = options.contains { $0.value == collate } + } + line(["collations-include-template1", hasTemplateCollation ? "yes" : "no"]) + } + await attempt("allTablesMetadataSQL") { + guard let sql = driver.allTablesMetadataSQL(schema: "public") else { return } + let result = try await driver.execute(query: sql) + for row in result.rows where row[safe: 1]?.asText == "Mixed Case" { + line(["all-tables", "Mixed Case", row[safe: 7]?.asText ?? "-"]) + } + } + await attempt("fetchTableMetadata") { + let metadata = try await driver.fetchTableMetadata(table: "Mixed Case", schema: "public") + line(["metadata", "Mixed Case", metadata.comment ?? "-"]) + } + await attempt("fetchViewDefinition") { + let ddl = try await driver.fetchViewDefinition(view: "order_view", schema: "public") + line(["view", (ddl.components(separatedBy: "\n").first ?? "-").trimmingCharacters(in: .whitespaces)]) + } + await attempt("fetchViewDefinition(materialized)") { + let tables = try await driver.fetchTables(schema: "public") + guard tables.contains(where: { $0.name == "order_totals" }) else { return } + let ddl = try await driver.fetchViewDefinition(view: "order_totals", schema: "public") + line(["view", (ddl.components(separatedBy: "\n").first ?? "-").trimmingCharacters(in: .whitespaces)]) + } + } + + static func readerPass(_ driver: PostgreSQLPluginDriver) async { + await attempt("fetchTables") { + line(["reader-tables", "\(try await driver.fetchTables(schema: "public").count > 0)"]) + } + await attempt("fetchAllForeignKeys") { + line(["reader-fks", "\(try await driver.fetchAllForeignKeys(schema: "public").count > 0)"]) + } + await attempt("fetchUserDefinedTypes") { + line(["reader-types", "\(try await driver.fetchUserDefinedTypes(schema: "public").count > 0)"]) + } + await attempt("fetchSequences") { + for sequence in try await driver.fetchSequences(schema: "public") { + line(["reader-sequence", sequence.name, sequence.ddl]) + } + } + } + + /// The statement text differs by release (serial versus identity, how defaults print), so the + /// check pins what every release must produce: a terminated CREATE TABLE naming every column + /// the column read returned, with the primary key carried over. + static func ddlShape(_ ddl: String, columns: [PluginColumnInfo]) -> String { + let named = columns.allSatisfy { column in + let quoted = "\"\(column.name.replacingOccurrences(of: "\"", with: "\"\""))\"" + return ddl.contains("\n \(quoted) ") || ddl.contains("\n \(column.name) ") + } + return [ + ddl.hasPrefix("CREATE TABLE ") ? "create" : "no-create", + named ? "names-all-columns" : "misses-a-column", + columns.contains(where: \.isPrimaryKey) == ddl.contains("PRIMARY KEY") ? "pk-consistent" : "pk-lost", + ddl.contains(";") ? "terminated" : "unterminated" + ].joined(separator: " ") + } + + static func foreignKeyPairs(_ keys: [PluginForeignKeyInfo]) -> [(String, String)] { + var order: [String] = [] + var pairs: [String: [String]] = [:] + for key in keys { + if pairs[key.name] == nil { order.append(key.name) } + pairs[key.name, default: []].append("\(key.column)>\(key.referencedTable).\(key.referencedColumn) \(key.onDelete)/\(key.onUpdate)") + } + return order.sorted().map { ($0, pairs[$0, default: []].joined(separator: ",")) } + } +} +SWIFT + +echo "Building the harness from the shipping sources..." +BUILD="$WORK/build" +mkdir -p "$BUILD" +if ! xcrun swiftc -emit-library -emit-module -module-name TableProPluginKit -parse-as-library -swift-version 6 \ + -enable-library-evolution -Xlinker -install_name -Xlinker @rpath/libTableProPluginKit.dylib \ + -emit-module-path "$BUILD/TableProPluginKit.swiftmodule" -o "$BUILD/libTableProPluginKit.dylib" \ + "${KIT_SOURCES[@]}" > "$WORK/build-kit.log" 2>&1; then + echo "FAIL: TableProPluginKit did not build" >&2 + grep -E "error" "$WORK/build-kit.log" | head -20 >&2 + exit 2 +fi +if ! xcrun swiftc -parse-as-library -swift-version 6 -module-name PostgreSQLCompatHarness \ + -I "$BUILD" -L "$BUILD" -lTableProPluginKit \ + -I "$DRIVER_DIR/CLibPQ" -Xcc -I"$DRIVER_DIR/CLibPQ/include" \ + -Xlinker -force_load -Xlinker "$LIBS/libpq.a" "$LIBS/libpgcommon.a" "$LIBS/libpgport.a" \ + -L "$LIBS/dylibs" -lssl.3 -lcrypto.3 -lz \ + -Xlinker -rpath -Xlinker "$BUILD" -Xlinker -rpath -Xlinker "$LIBS/dylibs" \ + -o "$BUILD/harness" "${DRIVER_SOURCES[@]}" "$WORK/harness.swift" > "$WORK/build-harness.log" 2>&1; then + echo "FAIL: the driver harness did not build" >&2 + grep -E "error" "$WORK/build-harness.log" | head -20 >&2 + exit 2 +fi + +if ! drop_fixture; then + echo "FAIL: a leftover fixture could not be dropped; another session is probably connected to $DATABASE" >&2 + exit 2 +fi +run_psql -d postgres -c "CREATE DATABASE $DATABASE" > /dev/null +run_psql -d postgres -c "CREATE ROLE $READER LOGIN PASSWORD '$READER_PASSWORD'" > /dev/null + +run_psql -d "$DATABASE" > "$WORK/fixture.log" 2>&1 <= 90200 AS pg92, + current_setting('server_version_num')::int >= 90300 AS pg93, + current_setting('server_version_num')::int >= 100000 AS pg10, + current_setting('server_version_num')::int >= 110000 AS pg11, + current_setting('server_version_num')::int >= 120000 AS pg12 \gset + +CREATE TYPE mood AS ENUM ('very happy', 'sad,ish', 'NULL', 'q"t', ''); +CREATE TYPE "odd,type" AS ("first name" text COLLATE "C", "q""t" integer, zip varchar(10)); +CREATE DOMAIN checked AS text CONSTRAINT "has,comma" CHECK (VALUE <> '') CONSTRAINT b_len CHECK (length(VALUE) < 10); + +CREATE TABLE customers (id bigserial PRIMARY KEY, email text NOT NULL UNIQUE); +COMMENT ON TABLE customers IS 'Customer accounts'; +CREATE TABLE orders ( + id bigserial PRIMARY KEY, + customer_id bigint NOT NULL REFERENCES customers (id) ON DELETE CASCADE, + qty integer, + status mood +); +COMMENT ON TABLE orders IS 'Orders'; +INSERT INTO customers (email) VALUES ('a@x'), ('b@x'); +INSERT INTO orders (customer_id, qty) VALUES (1, 150), (2, 5); +CREATE INDEX orders_big_qty ON orders (qty) WHERE qty > 100; +CREATE INDEX orders_multi ON orders (qty, customer_id); + +CREATE TABLE fk_parent (a integer, b integer, PRIMARY KEY (a, b)); +CREATE TABLE fk_child (x integer, y integer, CONSTRAINT fk_rev FOREIGN KEY (y, x) REFERENCES fk_parent (b, a) ON UPDATE CASCADE); + +CREATE TABLE idx_t (a integer, b text, c integer, "d,e" integer); +CREATE INDEX idx_dup ON idx_t (a, a); +CREATE INDEX idx_mixed ON idx_t (c, lower(b), a); +CREATE INDEX idx_rev ON idx_t (c, a); +CREATE INDEX idx_weird ON idx_t ("d,e", b); + +CREATE TABLE "we,ird" ("a b" integer, "c,d" integer, "q""t" integer, + CONSTRAINT "we,ird_chk" CHECK ("a b" + "c,d" + "q""t" > 0), CONSTRAINT constant_chk CHECK (1 > 0)); + +CREATE TABLE "Mixed Case" ("Id" integer PRIMARY KEY); +COMMENT ON TABLE "Mixed Case" IS 'Mixed comment'; + +CREATE VIEW order_view AS SELECT id, qty FROM orders; +COMMENT ON VIEW order_view IS 'Order view'; + +CREATE SEQUENCE compat_seq INCREMENT 2 MINVALUE 5 MAXVALUE 50 START 7 CYCLE; +SELECT nextval('compat_seq'); +CREATE SEQUENCE hidden_seq MAXVALUE 99; + +CREATE FUNCTION transform(a integer) RETURNS integer LANGUAGE sql IMMUTABLE AS 'SELECT \$1'; +CREATE FUNCTION transform(a text) RETURNS integer LANGUAGE sql AS 'SELECT 2'; +CREATE AGGREGATE my_sum(integer) (SFUNC = int4pl, STYPE = integer); +CREATE FUNCTION touch() RETURNS trigger LANGUAGE plpgsql AS \$\$ BEGIN RETURN NEW; END \$\$; +CREATE TRIGGER orders_touch BEFORE INSERT OR UPDATE ON orders FOR EACH ROW WHEN (NEW.qty > 0) EXECUTE PROCEDURE touch(); +CREATE TRIGGER orders_audit AFTER DELETE OR TRUNCATE ON orders FOR EACH STATEMENT EXECUTE PROCEDURE touch(); +ALTER TABLE orders DISABLE TRIGGER orders_audit; + +CREATE FOREIGN DATA WRAPPER compat_fdw; +CREATE SERVER compat_srv FOREIGN DATA WRAPPER compat_fdw; +CREATE FOREIGN TABLE remote_things (id integer) SERVER compat_srv; +COMMENT ON FOREIGN TABLE remote_things IS 'Remote comment'; + +GRANT CONNECT ON DATABASE $DATABASE TO $READER; +GRANT USAGE ON SCHEMA public TO $READER; +GRANT SELECT ON customers TO $READER; +GRANT SELECT (qty), UPDATE (qty) ON orders TO $READER; +GRANT USAGE ON SEQUENCE compat_seq TO $READER; + +\if :pg92 +ALTER TABLE "we,ird" ADD CONSTRAINT late_chk CHECK ("a b" > 0) NOT VALID; +\endif + +\if :pg93 +CREATE MATERIALIZED VIEW order_totals AS SELECT customer_id, sum(qty) AS total FROM orders GROUP BY customer_id; +COMMENT ON MATERIALIZED VIEW order_totals IS 'Totals'; +\endif + +\if :pg10 +CREATE TABLE events (happened date NOT NULL) PARTITION BY RANGE (happened); +CREATE TABLE events_2024 PARTITION OF events FOR VALUES FROM ('2024-01-01') TO ('2025-01-01'); +\endif + +\if :pg11 +CREATE PROCEDURE reset_qty() LANGUAGE sql AS 'UPDATE orders SET qty = 0'; +\endif + +\if :pg12 +CREATE TABLE part_ref (id integer PRIMARY KEY) PARTITION BY RANGE (id); +CREATE TABLE part_ref_lo PARTITION OF part_ref FOR VALUES FROM (1) TO (100); +CREATE TABLE part_ref_hi PARTITION OF part_ref FOR VALUES FROM (100) TO (200); +CREATE TABLE part_child (ref_id integer REFERENCES part_ref (id)); +CREATE TABLE part_src (id integer NOT NULL, cust bigint REFERENCES customers (id)) PARTITION BY RANGE (id); +CREATE TABLE part_src_1 PARTITION OF part_src FOR VALUES FROM (1) TO (10); +\endif +SQL + +# One expected line per object. A leading "min-max|" limits a line to servers in that range of +# server_version_num; "-" leaves an end open. +cat > "$WORK/expected.txt" <<'EXPECTED' +-|table|Mixed Case|TABLE|Mixed comment +-|table|customers|TABLE|Customer accounts +-|table|fk_child|TABLE|- +-|table|fk_parent|TABLE|- +-|table|idx_t|TABLE|- +-|table|order_view|VIEW|Order view +-|table|orders|TABLE|Orders +-|table|remote_things|FOREIGN TABLE|Remote comment +-|table|we,ird|TABLE|- +90300-|table|order_totals|MATERIALIZED VIEW|Totals +100000-|table|events|PARTITIONED TABLE|- +120000-|table|part_child|TABLE|- +120000-|table|part_ref|PARTITIONED TABLE|- +120000-|table|part_src|PARTITIONED TABLE|- +-|fk|fk_child|fk_rev|y>fk_parent.b NO ACTION/CASCADE,x>fk_parent.a NO ACTION/CASCADE +-|fk|orders|orders_customer_id_fkey|customer_id>customers.id CASCADE/NO ACTION +120000-|fk|part_child|part_child_ref_id_fkey|ref_id>part_ref.id NO ACTION/NO ACTION +120000-|fk|part_src|part_src_cust_fkey|cust>customers.id NO ACTION/NO ACTION +120000-|fk|part_src_1|part_src_cust_fkey|cust>customers.id NO ACTION/NO ACTION +-|fk-table|fk_child|fk_rev|y>fk_parent.b NO ACTION/CASCADE,x>fk_parent.a NO ACTION/CASCADE +120000-|fk-table|part_child|part_child_ref_id_fkey|ref_id>part_ref.id NO ACTION/NO ACTION +-|index|Mixed Case|Mixed Case_pkey|Id|unique|primary|BTREE|- +-|index|customers|customers_pkey|id|unique|primary|BTREE|- +-|index|customers|customers_email_key|email|unique|-|BTREE|- +-|index|fk_parent|fk_parent_pkey|a;b|unique|primary|BTREE|- +-|index|idx_t|idx_dup|a|-|-|BTREE|- +-|column|orders|customer_id|BIGINT|not-null|-|-|-|-|- +-|column|orders|id|BIGINT|not-null|pk|nextval('orders_id_seq'::regclass)|-|-|- +-|column|orders|qty|INTEGER|null|-|-|-|-|- +-|column|orders|status|ENUM|null|-|-|-|-|- +-|columns|Mixed Case|Id +-|columns|customers|id;email +-|columns|fk_child|x;y +-|columns|fk_parent|a;b +-|columns|idx_t|a;b;c;d,e +-|columns|order_view|id;qty +-|columns|orders|id;customer_id;qty;status +-|columns|remote_things|id +-|columns|we,ird|a b;c,d;q"t +100000-|columns|events|happened +100000-|columns|events_2024|happened +120000-|columns|part_child|ref_id +120000-|columns|part_ref|id +120000-|columns|part_ref_hi|id +120000-|columns|part_ref_lo|id +120000-|columns|part_src|id;cust +120000-|columns|part_src_1|id;cust +-|ddl|Mixed Case|create names-all-columns pk-consistent terminated +-|ddl|orders|create names-all-columns pk-consistent terminated +-|ddl|we,ird|create names-all-columns pk-consistent terminated +120000-|index|part_ref|part_ref_pkey|id|unique|primary|BTREE|- +120000-|index|part_ref_hi|part_ref_hi_pkey|id|unique|primary|BTREE|- +120000-|index|part_ref_lo|part_ref_lo_pkey|id|unique|primary|BTREE|- +-|index|idx_t|idx_mixed|c;a|-|-|BTREE|- +-|index|idx_t|idx_rev|c;a|-|-|BTREE|- +-|index|idx_t|idx_weird|d,e;b|-|-|BTREE|- +-|index|orders|orders_pkey|id|unique|primary|BTREE|- +-|index|orders|orders_big_qty|qty|-|-|BTREE|(qty > 100) +-|index|orders|orders_multi|qty;customer_id|-|-|BTREE|- +-|index-table|idx_t|idx_dup|a +-|index-table|idx_t|idx_mixed|c;a +-|index-table|idx_t|idx_rev|c;a +-|index-table|idx_t|idx_weird|d,e;b +-|check|we,ird|constant_chk|1 > 0||validated +-|check|we,ird|we,ird_chk|(("a b" + "c,d") + "q""t") > 0|a b;c,d;q"t|validated +90200-|check|we,ird|late_chk|"a b" > 0|a b|not-validated +-|trigger|orders|orders_audit|AFTER|DELETE OR TRUNCATE|STATEMENT|disabled +-|trigger|orders|orders_touch|BEFORE|INSERT OR UPDATE|ROW|enabled +-|type|checked|CREATE DOMAIN "public"."checked" AS text\n CONSTRAINT "b_len" CHECK ((length(VALUE) < 10))\n CONSTRAINT "has,comma" CHECK ((VALUE <> ''::text)); +-|type|mood|CREATE TYPE "public"."mood" AS ENUM (\n 'very happy',\n 'sad,ish',\n 'NULL',\n 'q"t',\n ''\n); +-|type|odd,type|CREATE TYPE "public"."odd,type" AS (\n "first name" text COLLATE pg_catalog."C",\n "q""t" integer,\n "zip" character varying(10)\n); +-|routine|touch|() +-|routine-ddl|(a integer)|yes +-|routine-ddl|(a text)|yes +-|trigger-when|orders_touch|yes +-|routine|transform|(a integer) +-|routine|transform|(a text) +110000-|routine|reset_qty|() +-|sequence|compat_seq|CREATE SEQUENCE "compat_seq" INCREMENT BY 2 MINVALUE 5 MAXVALUE 50 START WITH 7 CYCLE;\nSELECT pg_catalog.setval('"compat_seq"', 7, true); +-|sequence|customers_id_seq|CREATE SEQUENCE "customers_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1;\nSELECT pg_catalog.setval('"customers_id_seq"', 2, true); +-|sequence|hidden_seq|CREATE SEQUENCE "hidden_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 99 START WITH 1; +-|sequence|orders_id_seq|CREATE SEQUENCE "orders_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1;\nSELECT pg_catalog.setval('"orders_id_seq"', 2, true); +-|dependent-sequence|orders|orders_id_seq|CREATE SEQUENCE "orders_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1;\nSELECT pg_catalog.setval('"orders_id_seq"', 2, true); +-|grant|column(database: "tablepro_compat_check", schema: Optional("public"), table: "orders", column: "qty")|SELECT +-|grant|column(database: "tablepro_compat_check", schema: Optional("public"), table: "orders", column: "qty")|UPDATE +-|grant|database("tablepro_compat_check")|CONNECT +-|grant|schema(database: "tablepro_compat_check", schema: "public")|USAGE +-|grant|table(database: "tablepro_compat_check", schema: Optional("public"), table: "customers")|SELECT +-|collations-include-template1|yes +-|all-tables|Mixed Case|Mixed comment +-|metadata|Mixed Case|Mixed comment +-|view|CREATE OR REPLACE VIEW "public"."order_view" AS +90300-|view|CREATE MATERIALIZED VIEW "public"."order_totals" AS +EXPECTED + +cat > "$WORK/expected-reader.txt" <<'EXPECTED' +-|reader-tables|true +-|reader-fks|true +-|reader-types|true +-99999|reader-sequence|customers_id_seq|CREATE SEQUENCE "customers_id_seq"; +-99999|reader-sequence|orders_id_seq|CREATE SEQUENCE "orders_id_seq"; +-99999|reader-sequence|hidden_seq|CREATE SEQUENCE "hidden_seq"; +100000-|reader-sequence|customers_id_seq|CREATE SEQUENCE "customers_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1; +100000-|reader-sequence|orders_id_seq|CREATE SEQUENCE "orders_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1; +100000-|reader-sequence|hidden_seq|CREATE SEQUENCE "hidden_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 99 START WITH 1; +-99999|reader-sequence|compat_seq|CREATE SEQUENCE "compat_seq" INCREMENT BY 2 MINVALUE 5 MAXVALUE 50 START WITH 7 CYCLE; +100000-|reader-sequence|compat_seq|CREATE SEQUENCE "compat_seq" INCREMENT BY 2 MINVALUE 5 MAXVALUE 50 START WITH 7 CYCLE;\nSELECT pg_catalog.setval('"compat_seq"', 7, true); +EXPECTED + +select_for_version() { + awk -F'|' -v version="$SERVER_VERSION" '{ + range = $1 + split(range, bounds, "-") + low = bounds[1] == "" ? 0 : bounds[1] + 0 + high = bounds[2] == "" ? 999999999 : bounds[2] + 0 + if (range == "-") { low = 0; high = 999999999 } + if (version + 0 >= low && version + 0 <= high) { + sub(/^[^|]*\|/, "") + print + } + }' "$1" | LC_ALL=C sort +} + +failures=0 +compare() { + local label="$1" expected="$2" actual="$3" + if ! diff -u "$expected" "$actual" > "$WORK/$label.diff"; then + echo "FAIL: $label reads disagree with the expected answers (- expected, + driver):" >&2 + tail -n +3 "$WORK/$label.diff" >&2 + failures=$((failures + 1)) + fi +} + +# The harness prints one line per object and exits non-zero when it cannot even connect. Piping it +# straight into sort would let pipefail end the run through the EXIT trap, which deletes the working +# directory: the script whose job is diagnosis would print nothing to diagnose with. +run_pass() { + local pass="$1" user="$2" password="$3" out="$4" status=0 + "$BUILD/harness" "$HOST" "$PORT" "$user" "$password" "$DATABASE" "$pass" \ + > "$WORK/$pass.raw" 2> "$WORK/$pass.err" || status=$? + if [[ "$status" -ne 0 ]]; then + echo "FAIL: the $pass harness pass exited $status" >&2 + tail -n 20 "$WORK/$pass.err" >&2 + tail -n 5 "$WORK/$pass.raw" >&2 + KEEP=1 + echo "Working directory kept for diagnosis: $WORK" >&2 + return 1 + fi + LC_ALL=C sort "$WORK/$pass.raw" > "$out" +} + +PGPASSWORD_OWNER="${PGPASSWORD:-}" +if run_pass owner "$OWNER" "$PGPASSWORD_OWNER" "$WORK/actual.txt"; then + select_for_version "$WORK/expected.txt" > "$WORK/expected-selected.txt" + compare owner "$WORK/expected-selected.txt" "$WORK/actual.txt" +else + failures=$((failures + 1)) +fi + +if run_pass reader "$READER" "$READER_PASSWORD" "$WORK/actual-reader.txt"; then + select_for_version "$WORK/expected-reader.txt" > "$WORK/expected-reader-selected.txt" + compare reader "$WORK/expected-reader-selected.txt" "$WORK/actual-reader.txt" +else + failures=$((failures + 1)) +fi + +if [[ "$failures" -gt 0 ]]; then + echo "$failures pass(es) disagreed on PostgreSQL $SERVER_VERSION" >&2 + exit 1 +fi +echo "PostgreSQL driver catalog reads agree on PostgreSQL $SERVER_VERSION" From 5bb3af6bedb902aced1ad8c3bdb5066d64e08cf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 08:24:50 +0700 Subject: [PATCH 30/54] fix: follow the PostgreSQL server version in the dashboard, backup, plans and JSON types (#2763) * fix: follow the PostgreSQL server version in the dashboard, backup, plans and JSON types * refactor(export): name the locale variables the dump tools inherit --- CHANGELOG.md | 6 + .../CrossEngineStructureTranslator.swift | 10 +- .../SQLTypeRenderer+BundledFamilies.swift | 27 ++- .../Core/CrossEngine/SQLTypeRenderer.swift | 8 +- .../Core/Database/NativeDumpDescriptor.swift | 6 + .../Core/Database/NativeDumpRegistry.swift | 17 +- .../Core/Database/NativeDumpService.swift | 94 +++++++-- .../Database/NativeDumpToolSelection.swift | 16 ++ .../PostgreSQLDumpToolCompatibility.swift | 108 +++++++++++ .../Database/PostgreSQLDumpToolLocator.swift | 164 ++++++++++++++++ .../Database/PostgreSQLServerVersion.swift | 85 ++++++++ .../Core/MCP/MCPConnectionBridge+Server.swift | 114 +++++++---- .../Core/MCP/Protocol/Tools/ServerTools.swift | 9 + .../Core/ObjectCopy/ObjectCopyPlanner.swift | 2 + .../ObjectCopy/ObjectCopyTableDraft.swift | 6 +- TablePro/Core/Plugins/ImportTypeMapper.swift | 17 +- .../Providers/PostgreSQLActivityCatalog.swift | 159 +++++++++++++++ .../PostgreSQLDashboardProvider.swift | 183 ++++++++++-------- .../ServerDashboardQueryProviderFactory.swift | 13 +- .../Core/Services/Query/QueryPlanParser.swift | 2 +- .../ViewModels/ServerDashboardViewModel.swift | 20 +- TablePro/Views/Import/RowImportSheet.swift | 7 +- .../CrossEngineStructureTranslatorTests.swift | 26 +++ .../CrossEngine/SQLTypeRendererTests.swift | 32 +++ .../PostgreSQLDumpToolLocatorTests.swift | 177 +++++++++++++++++ .../PostgreSQLServerVersionTests.swift | 154 +++++++++++++++ .../MCP/MCPServerDashboardPayloadTests.swift | 62 ++++++ .../Core/Plugins/ImportTypeMapperTests.swift | 23 +++ .../PostgreSQLDashboardProviderTests.swift | 144 ++++++++++++++ .../Query/PostgreSQLPlanParserTests.swift | 28 +++ .../Database/NativeDumpRegistryTests.swift | 18 ++ docs/external-api/mcp-tools.mdx | 4 +- docs/features/backup-restore.mdx | 2 + docs/features/copy-objects.mdx | 8 +- docs/features/import-export.mdx | 2 +- docs/features/server-dashboard.mdx | 5 +- 36 files changed, 1597 insertions(+), 161 deletions(-) create mode 100644 TablePro/Core/Database/NativeDumpToolSelection.swift create mode 100644 TablePro/Core/Database/PostgreSQLDumpToolCompatibility.swift create mode 100644 TablePro/Core/Database/PostgreSQLDumpToolLocator.swift create mode 100644 TablePro/Core/Database/PostgreSQLServerVersion.swift create mode 100644 TablePro/Core/ServerDashboard/Providers/PostgreSQLActivityCatalog.swift create mode 100644 TableProTests/Core/Database/PostgreSQLDumpToolLocatorTests.swift create mode 100644 TableProTests/Core/Database/PostgreSQLServerVersionTests.swift create mode 100644 TableProTests/Core/MCP/MCPServerDashboardPayloadTests.swift create mode 100644 TableProTests/Core/ServerDashboard/PostgreSQLDashboardProviderTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 30b7f89f25..8992cb5755 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -192,6 +192,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Non-ASCII SQL Server filter values turned into `?` and matching the wrong rows on non-Unicode collations. - Empty structure, missing indexes and failed renames for non-ASCII SQL Server object names on non-Unicode collations. - Changing a defaulted SQL Server column failing when a name contains a quote or non-ASCII text. +- Server Dashboard sessions, metrics and slow queries failing on PostgreSQL 9.6 and earlier. +- One unanswered metric emptying the whole Server Dashboard metrics panel on PostgreSQL, Redshift and CockroachDB. +- MCP `get_server_dashboard` reporting a panel the server could not read as an empty list. +- Backup and restore failing on PostgreSQL 9.1 when the `pg_dump` or `pg_restore` found first is version 15 or later. +- Missing execution time in query plans on PostgreSQL 9.3 and earlier. +- Cross-engine copy and JSON import creating `jsonb` columns on PostgreSQL 9.3 and earlier. - SQL Server edits and deletes matching no row when the row is identified by a binary column. - SQL Server parameters sent to the wrong placeholders when a column name holds a question mark. - `[` in a SQL Server filter value read as a wildcard. diff --git a/TablePro/Core/CrossEngine/CrossEngineStructureTranslator.swift b/TablePro/Core/CrossEngine/CrossEngineStructureTranslator.swift index 4088c08648..dfa8ef8c6b 100644 --- a/TablePro/Core/CrossEngine/CrossEngineStructureTranslator.swift +++ b/TablePro/Core/CrossEngine/CrossEngineStructureTranslator.swift @@ -46,7 +46,8 @@ internal enum CrossEngineStructureTranslator { internal static func translate( _ snapshot: TableStructureSnapshot, from source: DatabaseType, - to target: DatabaseType + to target: DatabaseType, + targetServerVersion: String? = nil ) -> Result { let targetFamily = SQLTypeFamily.of(target) guard SQLTypeFamily.needsTranslation(from: source, to: target) else { @@ -61,6 +62,9 @@ internal enum CrossEngineStructureTranslator { } let sourceFamily = SQLTypeFamily.of(source) + let jsonColumnType = PostgreSQLServerVersion.jsonColumnType( + for: target, serverVersion: targetServerVersion + ) var notes: [CrossEngineConversionNote] = [] var sourceKindsByColumn: [String: CanonicalTypeKind] = [:] var kindsByColumn: [String: CanonicalTypeKind] = [:] @@ -76,6 +80,7 @@ internal enum CrossEngineStructureTranslator { table: snapshot.name, from: sourceFamily, to: targetFamily, + jsonColumnType: jsonColumnType, isKeyColumn: keyColumns.contains(column.name.lowercased()) ) columns.append(outcome.column) @@ -145,10 +150,11 @@ internal enum CrossEngineStructureTranslator { table: String, from sourceFamily: SQLTypeFamily, to targetFamily: SQLTypeFamily, + jsonColumnType: PostgreSQLJSONColumnType, isKeyColumn: Bool ) -> ColumnOutcome { let canonical = SQLTypeParser.parse(column.dataType, family: sourceFamily) - var rendered = SQLTypeRenderer.render(canonical, family: targetFamily) + var rendered = SQLTypeRenderer.render(canonical, family: targetFamily, jsonColumnType: jsonColumnType) var notes: [CrossEngineConversionNote] = [] if isKeyColumn, let bounded = boundedKeyType(rendered, kind: canonical.kind, family: targetFamily) { diff --git a/TablePro/Core/CrossEngine/SQLTypeRenderer+BundledFamilies.swift b/TablePro/Core/CrossEngine/SQLTypeRenderer+BundledFamilies.swift index 8be0499f10..d125c792a4 100644 --- a/TablePro/Core/CrossEngine/SQLTypeRenderer+BundledFamilies.swift +++ b/TablePro/Core/CrossEngine/SQLTypeRenderer+BundledFamilies.swift @@ -149,7 +149,10 @@ internal extension SQLTypeRenderer { // MARK: - PostgreSQL - static func postgres(_ type: CanonicalColumnType) -> RenderedColumnType { + static func postgres( + _ type: CanonicalColumnType, + jsonColumnType: PostgreSQLJSONColumnType = .jsonb + ) -> RenderedColumnType { switch type.kind { case .boolean: return RenderedColumnType(spelling: "BOOLEAN") @@ -183,7 +186,7 @@ internal extension SQLTypeRenderer { case .uuid: return RenderedColumnType(spelling: "UUID") case .json: - return RenderedColumnType(spelling: "JSONB") + return postgresJSON(type, jsonColumnType: jsonColumnType) case .xml: return RenderedColumnType(spelling: "XML") case .enumeration(let values): @@ -206,9 +209,10 @@ internal extension SQLTypeRenderer { reason: noEquivalent(type.sourceSpelling, as: String(localized: "text")) ) case .array(let element): - let inner = postgres(CanonicalColumnType( - kind: element, isUnsigned: type.isUnsigned, sourceSpelling: type.sourceSpelling - )) + let inner = postgres( + CanonicalColumnType(kind: element, isUnsigned: type.isUnsigned, sourceSpelling: type.sourceSpelling), + jsonColumnType: jsonColumnType + ) return RenderedColumnType(spelling: "\(inner.spelling)[]", fidelity: inner.fidelity, reason: inner.reason) case .unsupported: return RenderedColumnType( @@ -218,6 +222,19 @@ internal extension SQLTypeRenderer { } } + private static func postgresJSON( + _ type: CanonicalColumnType, + jsonColumnType: PostgreSQLJSONColumnType + ) -> RenderedColumnType { + guard jsonColumnType == .text else { + return RenderedColumnType(spelling: jsonColumnType.rawValue) + } + return RenderedColumnType( + spelling: jsonColumnType.rawValue, fidelity: .approximated, + reason: noEquivalent(type.sourceSpelling, as: String(localized: "text")) + ) + } + /// PostgreSQL has no unsigned integers, so an unsigned source widens by one step and the widest /// becomes a `NUMERIC`. Kept as the same width, a `BIGINT UNSIGNED` above 2^63 fails on the row /// that first exceeds it, which on a long copy is minutes in. diff --git a/TablePro/Core/CrossEngine/SQLTypeRenderer.swift b/TablePro/Core/CrossEngine/SQLTypeRenderer.swift index c5a97e6dcb..a25ea2cdd6 100644 --- a/TablePro/Core/CrossEngine/SQLTypeRenderer.swift +++ b/TablePro/Core/CrossEngine/SQLTypeRenderer.swift @@ -20,10 +20,14 @@ import Foundation internal enum SQLTypeRenderer { - internal static func render(_ type: CanonicalColumnType, family: SQLTypeFamily) -> RenderedColumnType { + internal static func render( + _ type: CanonicalColumnType, + family: SQLTypeFamily, + jsonColumnType: PostgreSQLJSONColumnType = .jsonb + ) -> RenderedColumnType { switch family { case .mysql: return mysql(type) - case .postgres: return postgres(type) + case .postgres: return postgres(type, jsonColumnType: jsonColumnType) case .sqlite: return sqlite(type) case .mssql: return mssql(type) case .oracle: return oracle(type) diff --git a/TablePro/Core/Database/NativeDumpDescriptor.swift b/TablePro/Core/Database/NativeDumpDescriptor.swift index 1de349bf9f..88c354e7b1 100644 --- a/TablePro/Core/Database/NativeDumpDescriptor.swift +++ b/TablePro/Core/Database/NativeDumpDescriptor.swift @@ -126,6 +126,10 @@ struct NativeDumpDescriptor: Sendable { internal let requiresUntranslatedMessages: Bool + /// Picks the binary to run for a known server version, when the engine's tools refuse + /// some servers. Nil leaves the plain PATH lookup in place. + let toolForServer: (@Sendable (_ binary: String, _ serverVersion: String?) -> NativeDumpToolSelection)? + let backupArguments: @Sendable (Request) -> [String] let restoreArguments: @Sendable (Request) -> [String] let environment: @Sendable (Request) -> [String: String] @@ -140,6 +144,7 @@ struct NativeDumpDescriptor: Sendable { needsCredentialsFile: Bool = false, restoreExitPolicy: NativeDumpExitPolicy = .zeroExitOnly, requiresUntranslatedMessages: Bool = false, + toolForServer: (@Sendable (_ binary: String, _ serverVersion: String?) -> NativeDumpToolSelection)? = nil, backupArguments: @escaping @Sendable (Request) -> [String], restoreArguments: @escaping @Sendable (Request) -> [String], environment: @escaping @Sendable (Request) -> [String: String] = { _ in [:] } @@ -153,6 +158,7 @@ struct NativeDumpDescriptor: Sendable { self.needsCredentialsFile = needsCredentialsFile self.restoreExitPolicy = restoreExitPolicy self.requiresUntranslatedMessages = requiresUntranslatedMessages + self.toolForServer = toolForServer self.backupArguments = backupArguments self.restoreArguments = restoreArguments self.environment = environment diff --git a/TablePro/Core/Database/NativeDumpRegistry.swift b/TablePro/Core/Database/NativeDumpRegistry.swift index 9cfec8cfe6..fe48df12b2 100644 --- a/TablePro/Core/Database/NativeDumpRegistry.swift +++ b/TablePro/Core/Database/NativeDumpRegistry.swift @@ -34,8 +34,10 @@ enum NativeDumpRegistry { formatId: String? = nil ) -> NativeDumpDescriptor? { switch type { - case .postgresql, .redshift: - return postgres + case .postgresql: + return postgres(toolForServer: postgresToolForServer) + case .redshift: + return postgres(toolForServer: nil) case .mysql, .mariadb: return mysql case .mongodb: @@ -70,7 +72,15 @@ enum NativeDumpRegistry { // MARK: - PostgreSQL - private static var postgres: NativeDumpDescriptor { + /// Redshift reports 8.0.2, which no `pg_dump` release claims to support, so only PostgreSQL + /// itself is matched to the server. + static let postgresToolForServer: @Sendable (String, String?) -> NativeDumpToolSelection = { binary, serverVersion in + PostgreSQLDumpToolLocator.select(binary: binary, serverVersion: serverVersion) + } + + private static func postgres( + toolForServer: (@Sendable (String, String?) -> NativeDumpToolSelection)? + ) -> NativeDumpDescriptor { NativeDumpDescriptor( mechanism: .commandLineTool( NativeDumpDescriptor.CommandLineTool( @@ -81,6 +91,7 @@ enum NativeDumpRegistry { restoreDelivery: .toolWritesFile, restoreExitPolicy: .toleratesUnrecognizedSessionSettings, requiresUntranslatedMessages: true, + toolForServer: toolForServer, backupArguments: { request in connectionFlags(request) + ["-Fc", "-d", request.database] diff --git a/TablePro/Core/Database/NativeDumpService.swift b/TablePro/Core/Database/NativeDumpService.swift index fb80e616f6..190a9fcf6b 100644 --- a/TablePro/Core/Database/NativeDumpService.swift +++ b/TablePro/Core/Database/NativeDumpService.swift @@ -41,6 +41,7 @@ enum NativeDumpError: LocalizedError, Equatable { case alreadyRunning case sourceUnreadable case engineStatementUnavailable + case incompatibleTool(message: String) var errorDescription: String? { switch self { @@ -60,6 +61,8 @@ enum NativeDumpError: LocalizedError, Equatable { return String(localized: "The selected backup file is not readable.") case .engineStatementUnavailable: return String(localized: "TablePro could not read the database's own name from the connection.") + case .incompatibleTool(let message): + return message } } } @@ -271,17 +274,11 @@ final class NativeDumpService { switch descriptor.mechanism { case .commandLineTool(let tool): - let candidates = tool.binaries(for: kind) - guard let resolved = candidates.lazy.compactMap({ name -> (String, String)? in - guard let path = CLIExecutableFinder.findExecutable(name) else { return nil } - return (name, path) - }).first else { - throw NativeDumpError.binaryNotFound( - name: candidates.formatted(.list(type: .or)), - installHint: tool.installHint - ) - } - let (binaryName, resolvedPath) = resolved + let (binaryName, resolvedPath) = try await Self.resolveExecutable( + tool: tool, + kind: kind, + serverVersion: session?.driver?.serverVersion + ) toolName = binaryName let command = try Self.buildCommand( kind: kind, @@ -351,6 +348,62 @@ final class NativeDumpService { // MARK: - Resolution + private static func resolveExecutable( + tool: NativeDumpDescriptor.CommandLineTool, + kind: NativeDumpKind, + serverVersion: String? + ) async throws -> (name: String, path: String) { + let candidates = tool.binaries(for: kind) + let selector = tool.toolForServer + let resolved = await Task.detached { + resolve(candidates: candidates, serverVersion: serverVersion, selector: selector) + }.value + switch resolved { + case .found(let name, let path): + return (name, path) + case .incompatible(let message): + throw NativeDumpError.incompatibleTool(message: message) + case .missing: + throw NativeDumpError.binaryNotFound( + name: candidates.formatted(.list(type: .or)), + installHint: tool.installHint + ) + } + } + + private enum ExecutableResolution: Sendable { + case found(name: String, path: String) + case incompatible(String) + case missing + } + + nonisolated private static func resolve( + candidates: [String], + serverVersion: String?, + selector: (@Sendable (String, String?) -> NativeDumpToolSelection)? + ) -> ExecutableResolution { + guard let selector else { + for name in candidates { + guard let path = CLIExecutableFinder.findExecutable(name) else { continue } + return .found(name: name, path: path) + } + return .missing + } + + var refusal: String? + for name in candidates { + switch selector(name, serverVersion) { + case .found(let path): + return .found(name: name, path: path) + case .incompatible(let message): + refusal = refusal ?? message + case .missing: + continue + } + } + return refusal.map { .incompatible($0) } ?? .missing + } + /// The path a file-backed driver actually opens, read from wherever that driver keeps it. /// SQLite uses `database`; DuckDB and libSQL use a plugin-declared additional field. static func localFilePath(for connection: DatabaseConnection) -> String? { @@ -466,18 +519,29 @@ final class NativeDumpService { return "\"\(escaped)\"" } + /// The locale variables a spawned tool reads, named rather than spelled at each use site. The + /// preference-key guard scans this target's sources for a quoted string passed to a `forKey:` + /// label and reports anything outside the `com.TablePro` namespace, so a locale variable + /// written that way reads as a stray `UserDefaults` key. Comments are scanned too. + nonisolated internal enum LocaleEnvironmentKey { + static let everyCategory = "LC_ALL" + static let characterHandling = "LC_CTYPE" + static let messages = "LC_MESSAGES" + } + nonisolated private static let inheritedEnvironmentKeys: [String] = [ - "PATH", "HOME", "USER", "LOGNAME", "SHELL", "TMPDIR", "LANG", "LC_ALL" + "PATH", "HOME", "USER", "LOGNAME", "SHELL", "TMPDIR", "LANG", LocaleEnvironmentKey.everyCategory ] nonisolated internal static let untranslatedMessagesLocale = "C" nonisolated internal static func untranslatedMessagesEnvironment(_ environment: [String: String]) -> [String: String] { var result = environment - if let everyCategory = result.removeValue(forKey: "LC_ALL"), result["LC_CTYPE"] == nil { - result["LC_CTYPE"] = everyCategory + let everyCategory = result.removeValue(forKey: LocaleEnvironmentKey.everyCategory) + if let everyCategory, result[LocaleEnvironmentKey.characterHandling] == nil { + result[LocaleEnvironmentKey.characterHandling] = everyCategory } - result["LC_MESSAGES"] = untranslatedMessagesLocale + result[LocaleEnvironmentKey.messages] = untranslatedMessagesLocale return result } diff --git a/TablePro/Core/Database/NativeDumpToolSelection.swift b/TablePro/Core/Database/NativeDumpToolSelection.swift new file mode 100644 index 0000000000..29d9217775 --- /dev/null +++ b/TablePro/Core/Database/NativeDumpToolSelection.swift @@ -0,0 +1,16 @@ +// +// NativeDumpToolSelection.swift +// TablePro +// + +import Foundation + +/// Which binary a tool-driven dump or restore should run, once the server it talks to is known. +/// +/// `incompatible` is not `missing`: the tool is installed and cannot reach this server, so the +/// message names the version to install rather than the package that provides the command. +enum NativeDumpToolSelection: Equatable, Sendable { + case found(path: String) + case incompatible(String) + case missing +} diff --git a/TablePro/Core/Database/PostgreSQLDumpToolCompatibility.swift b/TablePro/Core/Database/PostgreSQLDumpToolCompatibility.swift new file mode 100644 index 0000000000..332ec4bc45 --- /dev/null +++ b/TablePro/Core/Database/PostgreSQLDumpToolCompatibility.swift @@ -0,0 +1,108 @@ +// +// PostgreSQLDumpToolCompatibility.swift +// TablePro +// + +import Foundation + +enum PostgreSQLDumpToolCompatibility { + struct Candidate: Equatable, Sendable { + let path: String + let version: PostgreSQLServerVersion + } + + /// `pg_dump` learned `-d` in 9.3, and every argument list here names the database with it. + /// Measured: 9.2.23 answers `invalid option -- 'd'`, 9.3.25 runs. + static let oldestUsableTool = PostgreSQLServerVersion(number: 90_300) + + private static let toolsDroppingPreNinePointTwoServers = PostgreSQLServerVersion(number: 150_000) + private static let toolsDroppingPreEightServers = PostgreSQLServerVersion(number: 100_000) + + static func oldestServer(for tool: PostgreSQLServerVersion) -> PostgreSQLServerVersion { + if tool >= toolsDroppingPreNinePointTwoServers { + return PostgreSQLServerVersion(number: 90_200) + } + if tool >= toolsDroppingPreEightServers { + return PostgreSQLServerVersion(number: 80_000) + } + return PostgreSQLServerVersion(number: 70_000) + } + + static func canDump(server: PostgreSQLServerVersion, with tool: PostgreSQLServerVersion) -> Bool { + guard tool >= oldestUsableTool else { return false } + guard server.majorReleaseNumber <= tool.majorReleaseNumber else { return false } + return server >= oldestServer(for: tool) + } + + /// The newest tool release that still reaches this server, or nil when every later release does. + /// `pg_dump` 10 dropped servers before 8.0 and 15 dropped servers before 9.2, so a 7.x server + /// needs 9.6 or earlier and an 8.x or 9.1 server needs 14 or earlier. + static func newestUsableTool(for server: PostgreSQLServerVersion) -> PostgreSQLServerVersion? { + let ceilings = [ + (dropsServersBelow: 80_000, newestTool: 90_600), + (dropsServersBelow: 90_200, newestTool: 140_000) + ] + for ceiling in ceilings where server.number < ceiling.dropsServersBelow { + return PostgreSQLServerVersion(number: ceiling.newestTool) + } + return nil + } + + static func choose( + for server: PostgreSQLServerVersion, + preferred: Candidate?, + others: [Candidate] + ) -> Candidate? { + if let preferred, canDump(server: server, with: preferred.version) { + return preferred + } + return others + .filter { canDump(server: server, with: $0.version) } + .max { $0.version < $1.version } + } + + private static func installHint(newestUsableTool: PostgreSQLServerVersion?) -> String { + guard let newestUsableTool else { return String(localized: "Install it with `brew install libpq`.") } + guard newestUsableTool >= PostgreSQLServerVersion(number: 100_000) else { + return String( + format: String(localized: "Install one from PostgreSQL %@ or earlier."), + newestUsableTool.majorReleaseName + ) + } + return String( + format: String(localized: "Install one with `brew install postgresql@%@`."), + newestUsableTool.majorReleaseName + ) + } + + static func refusal( + for server: PostgreSQLServerVersion, + found: [Candidate], + toolName: String + ) -> String { + let oldest = PostgreSQLServerVersion.release( + max(oldestUsableTool.majorReleaseNumber, server.majorReleaseNumber) + ) + let oldestName = oldest.majorReleaseName + let requirement: String + if let newest = newestUsableTool(for: server) { + requirement = String( + format: String(localized: "PostgreSQL %1$@ needs %2$@ %3$@ to %4$@."), + server.majorReleaseName, toolName, oldestName, newest.majorReleaseName + ) + } else { + requirement = String( + format: String(localized: "PostgreSQL %1$@ needs %2$@ %3$@ or later."), + server.majorReleaseName, toolName, oldestName + ) + } + let install = installHint(newestUsableTool: newestUsableTool(for: server)) + let versions = Array(Set(found.map { $0.version })).sorted() + guard !versions.isEmpty else { return "\(requirement) \(install)" } + let foundList = versions.map(\.fullName).formatted(.list(type: .and)) + let foundSentence = String( + format: String(localized: "Found %1$@ %2$@."), toolName, foundList + ) + return "\(requirement) \(install) \(foundSentence)" + } +} diff --git a/TablePro/Core/Database/PostgreSQLDumpToolLocator.swift b/TablePro/Core/Database/PostgreSQLDumpToolLocator.swift new file mode 100644 index 0000000000..4a2f002b7d --- /dev/null +++ b/TablePro/Core/Database/PostgreSQLDumpToolLocator.swift @@ -0,0 +1,164 @@ +// +// PostgreSQLDumpToolLocator.swift +// TablePro +// + +import Foundation +import os + +enum PostgreSQLDumpToolLocator { + private static let logger = Logger(subsystem: "com.TablePro", category: "PostgreSQLDumpToolLocator") + + static let versionProbeTimeout: TimeInterval = 3 + + static let searchRoots = [ + "/opt/homebrew/opt", + "/usr/local/opt", + "/Applications/Postgres.app/Contents/Versions", + "/Library/PostgreSQL" + ] + + /// What a probed binary reported. A binary whose `--version` cannot be read or parsed is + /// `unknown`: it is used when nothing better is found, because refusing it would hide a tool + /// that worked before any of this existed. + enum ProbedVersion: Equatable, Sendable { + case known(PostgreSQLServerVersion) + case unknown + } + + static func select( + binary: String, + serverVersion: String?, + roots: [String] = searchRoots, + fileManager: FileManager = .default, + pathBinary: (String) -> String? = { CLIExecutableFinder.findExecutable($0) }, + probe: (String) -> ProbedVersion = { probeVersion(of: $0) } + ) -> NativeDumpToolSelection { + let preferredPath = pathBinary(binary) + guard let server = PostgreSQLServerVersion(serverVersion) else { + return preferredPath.map { .found(path: $0) } ?? .missing + } + + var preferred: PostgreSQLDumpToolCompatibility.Candidate? + var unknownVersionPaths: [String] = [] + if let preferredPath { + switch probe(preferredPath) { + case .known(let version): + preferred = .init(path: preferredPath, version: version) + case .unknown: + unknownVersionPaths.append(preferredPath) + } + } + if let preferred, PostgreSQLDumpToolCompatibility.canDump(server: server, with: preferred.version) { + return chosen(path: preferred.path, version: preferred.version, server: server, binary: binary) + } + + let preferredResolved = preferredPath.map { resolvedPath($0) } + var others: [PostgreSQLDumpToolCompatibility.Candidate] = [] + for path in installedPaths(binary: binary, roots: roots, fileManager: fileManager) + where resolvedPath(path) != preferredResolved { + switch probe(path) { + case .known(let version): + others.append(.init(path: path, version: version)) + case .unknown: + unknownVersionPaths.append(path) + } + } + + if let choice = PostgreSQLDumpToolCompatibility.choose(for: server, preferred: nil, others: others) { + return chosen(path: choice.path, version: choice.version, server: server, binary: binary) + } + if let fallback = unknownVersionPaths.first { + logger.warning( + """ + \(binary, privacy: .public) at \(fallback, privacy: .public) reports no readable version; \ + using it for a \(server.majorReleaseName, privacy: .public) server + """ + ) + return .found(path: fallback) + } + + let found = ([preferred].compactMap { $0 }) + others + guard !found.isEmpty else { return .missing } + return .incompatible( + PostgreSQLDumpToolCompatibility.refusal(for: server, found: found, toolName: binary) + ) + } + + static func installedPaths( + binary: String, + roots: [String] = searchRoots, + fileManager: FileManager = .default + ) -> [String] { + var paths: [String] = [] + var seen = Set() + for root in roots { + guard let entries = try? fileManager.contentsOfDirectory(atPath: root) else { continue } + for entry in entries.sorted() where isPostgreSQLInstall(entry, under: root) { + let path = "\(root)/\(entry)/bin/\(binary)" + guard fileManager.isExecutableFile(atPath: path) else { continue } + guard seen.insert(resolvedPath(path)).inserted else { continue } + paths.append(path) + } + } + return paths + } + + static func probeVersion(of path: String, timeout: TimeInterval = versionProbeTimeout) -> ProbedVersion { + guard let output = versionOutput(of: path, timeout: timeout), + let version = PostgreSQLServerVersion(output) else { + return .unknown + } + return .known(version) + } + + private static func chosen( + path: String, + version: PostgreSQLServerVersion, + server: PostgreSQLServerVersion, + binary: String + ) -> NativeDumpToolSelection { + logger.info( + """ + \(binary, privacy: .public) \(version.fullName, privacy: .public) at \(path, privacy: .public) \ + for a PostgreSQL \(server.fullName, privacy: .public) server + """ + ) + return .found(path: path) + } + + private static func isPostgreSQLInstall(_ entry: String, under root: String) -> Bool { + guard root.hasSuffix("/opt") else { return true } + return entry.hasPrefix("postgresql") || entry.hasPrefix("libpq") + } + + private static func resolvedPath(_ path: String) -> String { + URL(fileURLWithPath: path).resolvingSymlinksInPath().path + } + + private static func versionOutput(of path: String, timeout: TimeInterval) -> String? { + let process = Process() + process.executableURL = URL(fileURLWithPath: path) + process.arguments = ["--version"] + process.environment = CLIToolEnvironment.augmented() + let pipe = Pipe() + process.standardOutput = pipe + process.standardError = FileHandle.nullDevice + let finished = DispatchSemaphore(value: 0) + process.terminationHandler = { _ in finished.signal() } + do { + try process.run() + } catch { + return nil + } + + if finished.wait(timeout: .now() + timeout) == .timedOut { + process.terminate() + logger.warning("\(path, privacy: .public) did not answer --version within \(timeout, privacy: .public)s") + return nil + } + guard process.terminationStatus == 0 else { return nil } + let data = pipe.fileHandleForReading.readDataToEndOfFile() + return String(data: data, encoding: .utf8) + } +} diff --git a/TablePro/Core/Database/PostgreSQLServerVersion.swift b/TablePro/Core/Database/PostgreSQLServerVersion.swift new file mode 100644 index 0000000000..8d6b40db15 --- /dev/null +++ b/TablePro/Core/Database/PostgreSQLServerVersion.swift @@ -0,0 +1,85 @@ +// +// PostgreSQLServerVersion.swift +// TablePro +// + +import Foundation + +enum PostgreSQLJSONColumnType: String, Sendable { + case jsonb = "JSONB" + case json = "JSON" + case text = "TEXT" +} + +struct PostgreSQLServerVersion: Comparable, Hashable, Sendable { + typealias JSONColumnType = PostgreSQLJSONColumnType + + static let stateColumns = PostgreSQLServerVersion(number: 90_200) + static let jsonType = PostgreSQLServerVersion(number: 90_200) + static let jsonbType = PostgreSQLServerVersion(number: 90_400) + static let backendTypeColumn = PostgreSQLServerVersion(number: 100_000) + + let number: Int + + init(number: Int) { + self.number = number + } + + init?(_ text: String?) { + guard let text, let components = Self.leadingVersionComponents(in: text) else { return nil } + let major = components[0] + let second = components.count > 1 ? components[1] : 0 + let third = components.count > 2 ? components[2] : 0 + self.number = major >= 10 + ? major * 10_000 + second + : major * 10_000 + second * 100 + third + } + + static func release(_ majorReleaseNumber: Int) -> PostgreSQLServerVersion { + PostgreSQLServerVersion(number: majorReleaseNumber * 100) + } + + var majorReleaseNumber: Int { + number / 100 + } + + var majorReleaseName: String { + let major = number / 10_000 + guard major < 10 else { return String(major) } + return "\(major).\((number / 100) % 100)" + } + + var fullName: String { + let major = number / 10_000 + guard major < 10 else { return "\(major).\(number % 10_000)" } + return "\(major).\((number / 100) % 100).\(number % 100)" + } + + /// The richest JSON column type a target holds. + /// + /// Only `.postgresql` is read from the reported version. Redshift reports 8.0.2 and CockroachDB + /// reports 13.0.0, and neither number describes the JSON support that engine actually has. + static func jsonColumnType(for databaseType: DatabaseType, serverVersion: String?) -> JSONColumnType { + guard databaseType == .postgresql, let version = PostgreSQLServerVersion(serverVersion) else { + return .jsonb + } + if version >= .jsonbType { return .jsonb } + return version >= .jsonType ? .json : .text + } + + static func < (lhs: PostgreSQLServerVersion, rhs: PostgreSQLServerVersion) -> Bool { + lhs.number < rhs.number + } + + private static func leadingVersionComponents(in text: String) -> [Int]? { + let tokens = text.split(whereSeparator: { $0 == " " || $0 == "\t" || $0 == "\n" }) + for token in tokens { + guard let first = token.first, first.isASCII, first.isNumber else { continue } + let numeric = token.prefix { $0.isASCII && ($0.isNumber || $0 == ".") } + let components = numeric.split(separator: ".").compactMap { Int($0) } + guard let major = components.first, major > 0 else { continue } + return components + } + return nil + } +} diff --git a/TablePro/Core/MCP/MCPConnectionBridge+Server.swift b/TablePro/Core/MCP/MCPConnectionBridge+Server.swift index f3f930b9eb..93516df545 100644 --- a/TablePro/Core/MCP/MCPConnectionBridge+Server.swift +++ b/TablePro/Core/MCP/MCPConnectionBridge+Server.swift @@ -93,7 +93,10 @@ extension MCPConnectionBridge { } return try await DatabaseManager.shared.withMetadataDriver(scope: scope) { driver in - guard let provider = ServerDashboardQueryProviderFactory.provider(for: databaseType) else { + guard let provider = ServerDashboardQueryProviderFactory.provider( + for: databaseType, + serverVersion: driver.serverVersion + ) else { throw DatabaseAccessError.dataSourceError( String(localized: "TablePro has no server dashboard for this engine.") ) @@ -102,45 +105,90 @@ extension MCPConnectionBridge { try await driver.execute(query: sql) } var result: [String: JsonValue] = [:] + var failures: [String: String] = [:] if panels.contains("sessions") { - let sessions = (try? await provider.fetchSessions(execute: execute)) ?? [] - result["sessions"] = .array(sessions.map { session in - .object([ - "id": .string(session.id), - "user": .string(session.user), - "database": .string(session.database), - "state": .string(session.state), - "duration_seconds": .int(session.durationSeconds), - "query": .string(session.query), - "can_kill": .bool(session.canKill), - "can_cancel": .bool(session.canCancel) - ]) - }) + do { + let sessions = try await provider.fetchSessions(execute: execute) + result["sessions"] = .array(sessions.map { session in + .object([ + "id": .string(session.id), + "user": .string(session.user), + "database": .string(session.database), + "state": .string(session.state), + "duration_seconds": .int(session.durationSeconds), + "query": .string(session.query), + "can_kill": .bool(session.canKill), + "can_cancel": .bool(session.canCancel) + ]) + }) + } catch { + failures["sessions"] = Self.dashboardPanelFailure(panel: "sessions", error: error) + } } if panels.contains("metrics") { - let metrics = (try? await provider.fetchMetrics(execute: execute)) ?? [] - result["metrics"] = .array(metrics.map { metric in - .object([ - "id": .string(metric.id), - "label": .string(metric.label), - "value": .string(metric.value), - "unit": .string(metric.unit) - ]) - }) + do { + let metrics = try await provider.fetchMetrics(execute: execute) + result["metrics"] = .array(metrics.map { metric in + .object([ + "id": .string(metric.id), + "label": .string(metric.label), + "value": .string(metric.value), + "unit": .string(metric.unit) + ]) + }) + } catch { + failures["metrics"] = Self.dashboardPanelFailure(panel: "metrics", error: error) + } } if panels.contains("slow_queries") { - let slow = (try? await provider.fetchSlowQueries(execute: execute)) ?? [] - result["slow_queries"] = .array(slow.map { entry in - .object([ - "duration": .string(entry.duration), - "query": .string(entry.query), - "user": .string(entry.user), - "database": .string(entry.database) - ]) - }) + do { + let slow = try await provider.fetchSlowQueries(execute: execute) + result["slow_queries"] = .array(slow.map { entry in + .object([ + "duration": .string(entry.duration), + "query": .string(entry.query), + "user": .string(entry.user), + "database": .string(entry.database) + ]) + }) + } catch { + failures["slow_queries"] = Self.dashboardPanelFailure(panel: "slow_queries", error: error) + } } - return .object(result) + return try Self.dashboardPayload(panels: result, failures: failures) + } + } + + /// The paired client is told which panel the server refused, never what the server said. The + /// server's own text can name a role, a database, a column or a statement, and this reply + /// leaves the user's Mac; the full message stays in the log for the user to read. + static func dashboardPanelFailure(panel: String, error: Error) -> String { + logger.warning( + """ + Server dashboard panel \(panel, privacy: .public) failed: \ + \(error.localizedDescription, privacy: .private) + """ + ) + return String( + format: String(localized: "The server did not answer the %@ panel."), + panel.replacingOccurrences(of: "_", with: " ") + ) + } + + static func dashboardPayload( + panels: [String: JsonValue], + failures: [String: String] + ) throws -> JsonValue { + guard !failures.isEmpty else { return .object(panels) } + guard !panels.isEmpty else { + let message = failures.keys.sorted() + .compactMap { failures[$0] } + .joined(separator: " ") + throw DatabaseAccessError.dataSourceError(message) } + var payload = panels + payload["errors"] = .object(failures.mapValues { .string($0) }) + return .object(payload) } func sessionControlStatement( diff --git a/TablePro/Core/MCP/Protocol/Tools/ServerTools.swift b/TablePro/Core/MCP/Protocol/Tools/ServerTools.swift index ca3d0701a4..3968c0e6cb 100644 --- a/TablePro/Core/MCP/Protocol/Tools/ServerTools.swift +++ b/TablePro/Core/MCP/Protocol/Tools/ServerTools.swift @@ -72,6 +72,15 @@ public struct ServerDashboardTool: MCPToolImplementation { ], required: ["duration", "query", "user", "database"] ) + ), + "errors": MCPToolSchema.object( + properties: [ + "sessions": MCPToolSchema.string(String(localized: "Why the sessions panel could not be read")), + "metrics": MCPToolSchema.string(String(localized: "Why the metrics panel could not be read")), + "slow_queries": MCPToolSchema.string( + String(localized: "Why the slow queries panel could not be read") + ) + ] ) ] ) diff --git a/TablePro/Core/ObjectCopy/ObjectCopyPlanner.swift b/TablePro/Core/ObjectCopy/ObjectCopyPlanner.swift index 54ff2d98e7..ede0a85817 100644 --- a/TablePro/Core/ObjectCopy/ObjectCopyPlanner.swift +++ b/TablePro/Core/ObjectCopy/ObjectCopyPlanner.swift @@ -298,6 +298,7 @@ internal struct ObjectCopyPlanner { /// different tie-break on every launch: the approved script, the progress order and the /// outcome list were all shuffled differently for the same copy. var drafts: [ObjectCopyTableDraft] = [] + let targetServerVersion = manager.driver(for: request.target.connectionId)?.serverVersion for selection in Self.orderedByDependency( scope.objects.filter { reads[$0] != nil }, reads: reads, effectiveSchema: sourceNamespace ) { @@ -325,6 +326,7 @@ internal struct ObjectCopyPlanner { existsInTarget: existsInTarget, sourceSchema: sourceEndpoint.schema ?? read.table.schema, targetSchema: targetEndpoint.schema, + targetServerVersion: targetServerVersion, request: request )) } diff --git a/TablePro/Core/ObjectCopy/ObjectCopyTableDraft.swift b/TablePro/Core/ObjectCopy/ObjectCopyTableDraft.swift index d1685d4af6..d6c40b7609 100644 --- a/TablePro/Core/ObjectCopy/ObjectCopyTableDraft.swift +++ b/TablePro/Core/ObjectCopy/ObjectCopyTableDraft.swift @@ -49,6 +49,7 @@ internal struct ObjectCopyTableDraft { existsInTarget: Bool, sourceSchema: String?, targetSchema: String?, + targetServerVersion: String?, request: ObjectCopyRequest ) { self.selection = selection @@ -70,7 +71,10 @@ internal struct ObjectCopyTableDraft { self.targetTable = (writesStructure ? nil : targetSnapshot?.name) ?? snapshot.name let translation = CrossEngineStructureTranslator.translate( - snapshot, from: request.source.databaseType, to: request.target.databaseType + snapshot, + from: request.source.databaseType, + to: request.target.databaseType, + targetServerVersion: targetServerVersion ) self.targetStructure = translation.snapshot self.isCrossEngine = translation.translated diff --git a/TablePro/Core/Plugins/ImportTypeMapper.swift b/TablePro/Core/Plugins/ImportTypeMapper.swift index 14e5f3455a..780f84988c 100644 --- a/TablePro/Core/Plugins/ImportTypeMapper.swift +++ b/TablePro/Core/Plugins/ImportTypeMapper.swift @@ -7,10 +7,19 @@ import Foundation import TableProPluginKit enum ImportTypeMapper { - static func sqlType(for type: PluginImportFieldType, databaseType: DatabaseType) -> String { + static func sqlType( + for type: PluginImportFieldType, + databaseType: DatabaseType, + serverVersion: String? = nil + ) -> String { switch databaseType { case .postgresql, .redshift, .cockroachdb: - return postgresType(type) + return postgresType( + type, + jsonColumnType: PostgreSQLServerVersion.jsonColumnType( + for: databaseType, serverVersion: serverVersion + ) + ) case .mysql, .mariadb, .tidb: return mysqlType(type) case .sqlite: @@ -22,12 +31,12 @@ enum ImportTypeMapper { } } - private static func postgresType(_ type: PluginImportFieldType) -> String { + private static func postgresType(_ type: PluginImportFieldType, jsonColumnType: PostgreSQLJSONColumnType) -> String { switch type { case .integer: return "BIGINT" case .real: return "DOUBLE PRECISION" case .boolean: return "BOOLEAN" - case .json: return "JSONB" + case .json: return jsonColumnType.rawValue case .text: return "TEXT" @unknown default: return "TEXT" } diff --git a/TablePro/Core/ServerDashboard/Providers/PostgreSQLActivityCatalog.swift b/TablePro/Core/ServerDashboard/Providers/PostgreSQLActivityCatalog.swift new file mode 100644 index 0000000000..8b0152eb1c --- /dev/null +++ b/TablePro/Core/ServerDashboard/Providers/PostgreSQLActivityCatalog.swift @@ -0,0 +1,159 @@ +// +// PostgreSQLActivityCatalog.swift +// TablePro +// + +import Foundation + +/// Which of the five metrics an engine can answer. +/// +/// CockroachDB reports a PostgreSQL version and `pg_stat_activity`, but `pg_size_pretty()`, +/// `pg_database_size()` and `pg_postmaster_start_time()` are unknown functions there (measured on +/// v26.2), so asking for them every tick is three failed statements per refresh. +enum PostgreSQLDashboardMetricSet: Equatable, Sendable { + case full + case activityOnly + + init(databaseType: DatabaseType) { + self = databaseType == .cockroachdb ? .activityOnly : .full + } + + var identifiers: Set { + switch self { + case .full: + return ["connections", "cache_hit", "db_size", "uptime", "active_queries"] + case .activityOnly: + return ["connections", "active_queries"] + } + } +} + +enum PostgreSQLActivityCatalog: Equatable, Sendable { + case current + case withoutBackendType + case procpid + + init(serverVersion: PostgreSQLServerVersion?) { + guard let serverVersion else { + self = .current + return + } + if serverVersion >= .backendTypeColumn { + self = .current + } else if serverVersion >= .stateColumns { + self = .withoutBackendType + } else { + self = .procpid + } + } + + private static let idleSentinels = [ + "", + " in transaction", + " in transaction (aborted)" + ] + + private static let hiddenSentinels = idleSentinels + [ + "", + "" + ] + + private static func literalList(_ values: [String]) -> String { + values.map { "'\($0)'" }.joined(separator: ", ") + } + + var sessionsQuery: String { + switch self { + case .current: + return """ + SELECT pid, usename, datname, state, + EXTRACT(EPOCH FROM (now() - query_start))::int AS duration_secs, + left(query, 1000) AS query + FROM pg_stat_activity + WHERE pid <> pg_backend_pid() + AND backend_type = 'client backend' + ORDER BY query_start NULLS LAST + """ + case .withoutBackendType: + return """ + SELECT pid, usename, datname, state, + EXTRACT(EPOCH FROM (now() - query_start))::int AS duration_secs, + left(query, 1000) AS query + FROM pg_stat_activity + WHERE pid <> pg_backend_pid() + ORDER BY query_start NULLS LAST + """ + case .procpid: + return """ + SELECT procpid AS pid, usename, datname, + CASE current_query + WHEN '' THEN 'idle' + WHEN ' in transaction' THEN 'idle in transaction' + WHEN ' in transaction (aborted)' THEN 'idle in transaction (aborted)' + WHEN '' THEN 'disabled' + WHEN '' THEN NULL + ELSE 'active' + END AS state, + EXTRACT(EPOCH FROM (now() - query_start))::int AS duration_secs, + CASE WHEN current_query IN (\(Self.literalList(Self.idleSentinels))) THEN '' + ELSE left(current_query, 1000) + END AS query + FROM pg_stat_activity + WHERE procpid <> pg_backend_pid() + ORDER BY query_start NULLS LAST + """ + } + } + + var connectionCountQuery: String { + switch self { + case .current: + return "SELECT count(*) FROM pg_stat_activity WHERE backend_type = 'client backend'" + case .withoutBackendType, .procpid: + return "SELECT count(*) FROM pg_stat_activity" + } + } + + var activeQueryCountQuery: String { + switch self { + case .current, .withoutBackendType: + return """ + SELECT count(*) FROM pg_stat_activity + WHERE state = 'active' AND pid <> pg_backend_pid() + """ + case .procpid: + return """ + SELECT count(*) FROM pg_stat_activity + WHERE current_query NOT IN (\(Self.literalList(Self.hiddenSentinels))) + AND procpid <> pg_backend_pid() + """ + } + } + + var slowQueriesQuery: String { + switch self { + case .current, .withoutBackendType: + return """ + SELECT pid, usename, datname, + EXTRACT(EPOCH FROM (now() - query_start))::int AS duration_secs, + left(query, 1000) AS query + FROM pg_stat_activity + WHERE state = 'active' + AND now() - query_start > interval '1 second' + AND pid <> pg_backend_pid() + ORDER BY query_start + """ + case .procpid: + return """ + SELECT procpid AS pid, usename, datname, + EXTRACT(EPOCH FROM (now() - query_start))::int AS duration_secs, + left(current_query, 1000) AS query + FROM pg_stat_activity + WHERE current_query NOT IN (\(Self.literalList(Self.hiddenSentinels))) + AND now() - query_start > interval '1 second' + AND procpid <> pg_backend_pid() + ORDER BY query_start + """ + } + } +} diff --git a/TablePro/Core/ServerDashboard/Providers/PostgreSQLDashboardProvider.swift b/TablePro/Core/ServerDashboard/Providers/PostgreSQLDashboardProvider.swift index 5595db563f..b86fde235a 100644 --- a/TablePro/Core/ServerDashboard/Providers/PostgreSQLDashboardProvider.swift +++ b/TablePro/Core/ServerDashboard/Providers/PostgreSQLDashboardProvider.swift @@ -4,22 +4,26 @@ // import Foundation +import os import TableProPluginKit struct PostgreSQLDashboardProvider: ServerDashboardQueryProvider { + private static let logger = Logger(subsystem: "com.TablePro", category: "PostgreSQLDashboardProvider") + let supportedPanels: Set = [.activeSessions, .serverMetrics, .slowQueries] + let activityCatalog: PostgreSQLActivityCatalog + let metricSet: PostgreSQLDashboardMetricSet + + init( + activityCatalog: PostgreSQLActivityCatalog = .current, + metricSet: PostgreSQLDashboardMetricSet = .full + ) { + self.activityCatalog = activityCatalog + self.metricSet = metricSet + } func fetchSessions(execute: (String) async throws -> QueryResult) async throws -> [DashboardSession] { - let sql = """ - SELECT pid, usename, datname, state, - EXTRACT(EPOCH FROM (now() - query_start))::int AS duration_secs, - left(query, 1000) AS query - FROM pg_stat_activity - WHERE pid <> pg_backend_pid() - AND backend_type = 'client backend' - ORDER BY query_start NULLS LAST - """ - let result = try await execute(sql) + let result = try await execute(activityCatalog.sessionsQuery) let col = columnIndex(from: result.columns) return result.rows.map { row in let pid = value(row, at: col["pid"]) @@ -38,87 +42,37 @@ struct PostgreSQLDashboardProvider: ServerDashboardQueryProvider { func fetchMetrics(execute: (String) async throws -> QueryResult) async throws -> [DashboardMetric] { var metrics: [DashboardMetric] = [] - - let connections = try await execute("SELECT count(*) FROM pg_stat_activity WHERE backend_type = 'client backend'") - if let row = connections.rows.first { - metrics.append(DashboardMetric( - id: "connections", - label: String(localized: "Connections"), - value: value(row, at: 0), - unit: "", - icon: "person.2" - )) + var firstFailure: Error? + + for definition in metricDefinitions { + do { + let result = try await execute(definition.query) + guard let row = result.rows.first else { continue } + metrics.append(DashboardMetric( + id: definition.id, + label: definition.label, + value: value(row, at: 0), + unit: definition.unit, + icon: definition.icon + )) + } catch is CancellationError { + throw CancellationError() + } catch { + Self.logger.warning( + "Metric \(definition.id, privacy: .public) failed: \(error.localizedDescription, privacy: .public)" + ) + if firstFailure == nil { firstFailure = error } + } } - let cacheHit = try await execute(""" - SELECT CASE WHEN blks_hit + blks_read = 0 THEN '0' - ELSE round(blks_hit::numeric / (blks_hit + blks_read) * 100, 1)::text - END - FROM pg_stat_database WHERE datname = current_database() - """) - if let row = cacheHit.rows.first { - metrics.append(DashboardMetric( - id: "cache_hit", - label: String(localized: "Cache Hit Ratio"), - value: value(row, at: 0), - unit: "%", - icon: "bolt" - )) + if metrics.isEmpty, let firstFailure { + throw firstFailure } - - let dbSize = try await execute("SELECT pg_size_pretty(pg_database_size(current_database()))") - if let row = dbSize.rows.first { - metrics.append(DashboardMetric( - id: "db_size", - label: String(localized: "Database Size"), - value: value(row, at: 0), - unit: "", - icon: "internaldrive" - )) - } - - let uptime = try await execute( - "SELECT date_trunc('second', now() - pg_postmaster_start_time())::text" - ) - if let row = uptime.rows.first { - metrics.append(DashboardMetric( - id: "uptime", - label: String(localized: "Uptime"), - value: value(row, at: 0), - unit: "", - icon: "clock" - )) - } - - let activeQueries = try await execute(""" - SELECT count(*) FROM pg_stat_activity - WHERE state = 'active' AND pid <> pg_backend_pid() - """) - if let row = activeQueries.rows.first { - metrics.append(DashboardMetric( - id: "active_queries", - label: String(localized: "Active Queries"), - value: value(row, at: 0), - unit: "", - icon: "bolt.horizontal" - )) - } - return metrics } func fetchSlowQueries(execute: (String) async throws -> QueryResult) async throws -> [DashboardSlowQuery] { - let sql = """ - SELECT pid, usename, datname, - EXTRACT(EPOCH FROM (now() - query_start))::int AS duration_secs, - left(query, 1000) AS query - FROM pg_stat_activity - WHERE state = 'active' - AND now() - query_start > interval '1 second' - AND pid <> pg_backend_pid() - ORDER BY query_start - """ - let result = try await execute(sql) + let result = try await execute(activityCatalog.slowQueriesQuery) let col = columnIndex(from: result.columns) return result.rows.map { row in let secs = Int(value(row, at: col["duration_secs"])) ?? 0 @@ -142,6 +96,67 @@ struct PostgreSQLDashboardProvider: ServerDashboardQueryProvider { } } +// MARK: - Metrics + +private extension PostgreSQLDashboardProvider { + struct MetricDefinition { + let id: String + let label: String + let unit: String + let icon: String + let query: String + } + + var metricDefinitions: [MetricDefinition] { + allMetricDefinitions.filter { metricSet.identifiers.contains($0.id) } + } + + var allMetricDefinitions: [MetricDefinition] { + [ + MetricDefinition( + id: "connections", + label: String(localized: "Connections"), + unit: "", + icon: "person.2", + query: activityCatalog.connectionCountQuery + ), + MetricDefinition( + id: "cache_hit", + label: String(localized: "Cache Hit Ratio"), + unit: "%", + icon: "bolt", + query: """ + SELECT CASE WHEN blks_hit + blks_read = 0 THEN '0' + ELSE round(blks_hit::numeric / (blks_hit + blks_read) * 100, 1)::text + END + FROM pg_stat_database WHERE datname = current_database() + """ + ), + MetricDefinition( + id: "db_size", + label: String(localized: "Database Size"), + unit: "", + icon: "internaldrive", + query: "SELECT pg_size_pretty(pg_database_size(current_database()))" + ), + MetricDefinition( + id: "uptime", + label: String(localized: "Uptime"), + unit: "", + icon: "clock", + query: "SELECT date_trunc('second', now() - pg_postmaster_start_time())::text" + ), + MetricDefinition( + id: "active_queries", + label: String(localized: "Active Queries"), + unit: "", + icon: "bolt.horizontal", + query: activityCatalog.activeQueryCountQuery + ) + ] + } +} + // MARK: - Helpers private extension PostgreSQLDashboardProvider { diff --git a/TablePro/Core/ServerDashboard/ServerDashboardQueryProviderFactory.swift b/TablePro/Core/ServerDashboard/ServerDashboardQueryProviderFactory.swift index 06c4bd8b98..459da99224 100644 --- a/TablePro/Core/ServerDashboard/ServerDashboardQueryProviderFactory.swift +++ b/TablePro/Core/ServerDashboard/ServerDashboardQueryProviderFactory.swift @@ -6,10 +6,17 @@ import Foundation enum ServerDashboardQueryProviderFactory { - static func provider(for databaseType: DatabaseType) -> ServerDashboardQueryProvider? { + static func provider(for databaseType: DatabaseType, serverVersion: String? = nil) -> ServerDashboardQueryProvider? { switch databaseType { - case .postgresql, .redshift, .cockroachdb: - return PostgreSQLDashboardProvider() + case .postgresql: + return PostgreSQLDashboardProvider( + activityCatalog: PostgreSQLActivityCatalog(serverVersion: PostgreSQLServerVersion(serverVersion)), + metricSet: PostgreSQLDashboardMetricSet(databaseType: databaseType) + ) + case .redshift, .cockroachdb: + return PostgreSQLDashboardProvider( + metricSet: PostgreSQLDashboardMetricSet(databaseType: databaseType) + ) case .mysql, .mariadb: return MySQLDashboardProvider() case .mssql: diff --git a/TablePro/Core/Services/Query/QueryPlanParser.swift b/TablePro/Core/Services/Query/QueryPlanParser.swift index c8d17bcacb..7c249aaa62 100644 --- a/TablePro/Core/Services/Query/QueryPlanParser.swift +++ b/TablePro/Core/Services/Query/QueryPlanParser.swift @@ -31,7 +31,7 @@ struct PostgreSQLPlanParser: QueryPlanParser { } let planningTime = planDict["Planning Time"] as? Double - let executionTime = planDict["Execution Time"] as? Double + let executionTime = (planDict["Execution Time"] ?? planDict["Total Runtime"]) as? Double let rootNode = parseNode(plan) var queryPlan = QueryPlan( diff --git a/TablePro/ViewModels/ServerDashboardViewModel.swift b/TablePro/ViewModels/ServerDashboardViewModel.swift index 239e408cfc..18308c80d3 100644 --- a/TablePro/ViewModels/ServerDashboardViewModel.swift +++ b/TablePro/ViewModels/ServerDashboardViewModel.swift @@ -52,6 +52,8 @@ final class ServerDashboardViewModel { @ObservationIgnored nonisolated(unsafe) private var refreshTask: Task? @ObservationIgnored private let services: AppServices + @ObservationIgnored private var providerServerVersion: String? + @ObservationIgnored private var hasAdoptedServerVersion = false // MARK: - Computed Properties @@ -115,14 +117,28 @@ final class ServerDashboardViewModel { // MARK: - Data Fetching + /// The provider is built once per server version, because it also answers `supportedPanels`, + /// `canKillSessions` and `canCancelQueries` for the toolbar between refreshes. + private func adoptProvider(forServerVersion serverVersion: String?) { + guard serverVersion != providerServerVersion || !hasAdoptedServerVersion else { return } + providerServerVersion = serverVersion + hasAdoptedServerVersion = true + guard let resolved = ServerDashboardQueryProviderFactory.provider( + for: databaseType, serverVersion: serverVersion + ) else { return } + provider = resolved + } + func refreshNow() async { guard !isRefreshing else { return } - guard let provider else { + guard provider != nil else { Self.logger.warning("No query provider available for \(self.databaseType.rawValue)") return } - guard services.databaseManager.driver(for: connectionId) != nil else { return } + guard let liveDriver = services.databaseManager.driver(for: connectionId) else { return } + adoptProvider(forServerVersion: liveDriver.serverVersion) + guard let provider else { return } isRefreshing = true defer { isRefreshing = false } diff --git a/TablePro/Views/Import/RowImportSheet.swift b/TablePro/Views/Import/RowImportSheet.swift index f82000f538..85fbb6cfe5 100644 --- a/TablePro/Views/Import/RowImportSheet.swift +++ b/TablePro/Views/Import/RowImportSheet.swift @@ -724,12 +724,17 @@ struct RowImportSheet: View { defer { isLoadingContext = false } do { let fields = try await Self.detectFields(plugin: plugin, at: fileURL, targetTable: nil) + let serverVersion = DatabaseManager.shared.driver(for: connection.id)?.serverVersion newColumns = fields.map { field in NewColumn( field: field, include: true, name: field.name, - type: ImportTypeMapper.sqlType(for: field.inferredType, databaseType: connection.type), + type: ImportTypeMapper.sqlType( + for: field.inferredType, + databaseType: connection.type, + serverVersion: serverVersion + ), isPrimaryKey: false, isNullable: true, defaultValue: "" diff --git a/TableProTests/Core/CrossEngine/CrossEngineStructureTranslatorTests.swift b/TableProTests/Core/CrossEngine/CrossEngineStructureTranslatorTests.swift index 97624f41b0..66fae2eb00 100644 --- a/TableProTests/Core/CrossEngine/CrossEngineStructureTranslatorTests.swift +++ b/TableProTests/Core/CrossEngine/CrossEngineStructureTranslatorTests.swift @@ -281,6 +281,32 @@ final class CrossEngineStructureTranslatorTests: XCTestCase { // MARK: - Value kinds + func testAJSONColumnCopiedToAPostgresServerWithoutJSONArrivesAsTextWithANote() { + let source = snapshot(columns: [column("payload", "JSON")]) + let result = CrossEngineStructureTranslator.translate( + source, from: .mysql, to: .postgresql, targetServerVersion: "9.1.24" + ) + XCTAssertEqual(result.snapshot.columns.map(\.dataType), ["TEXT"]) + XCTAssertTrue(result.notes.contains { $0.subject == "payload" }) + } + + func testAJSONColumnCopiedToAPostgresServerWithoutJSONBArrivesAsJSON() { + let source = snapshot(columns: [column("payload", "JSON")]) + let result = CrossEngineStructureTranslator.translate( + source, from: .mysql, to: .postgresql, targetServerVersion: "9.3.25" + ) + XCTAssertEqual(result.snapshot.columns.map(\.dataType), ["JSON"]) + XCTAssertTrue(result.notes.isEmpty) + } + + func testAJSONColumnCopiedIntoRedshiftKeepsJSONBWhateverVersionItReports() { + let source = snapshot(columns: [column("payload", "JSON")]) + let result = CrossEngineStructureTranslator.translate( + source, from: .mysql, to: .redshift, targetServerVersion: "8.0.2" + ) + XCTAssertEqual(result.snapshot.columns.map(\.dataType), ["JSONB"]) + } + func testTheTargetKindsDescribeEveryColumn() { let source = snapshot(columns: [column("flag", "TINYINT(1)"), column("made", "DATETIME")]) let result = CrossEngineStructureTranslator.translate(source, from: .mysql, to: .postgresql) diff --git a/TableProTests/Core/CrossEngine/SQLTypeRendererTests.swift b/TableProTests/Core/CrossEngine/SQLTypeRendererTests.swift index 58d1a5f2a9..68128999d2 100644 --- a/TableProTests/Core/CrossEngine/SQLTypeRendererTests.swift +++ b/TableProTests/Core/CrossEngine/SQLTypeRendererTests.swift @@ -37,6 +37,38 @@ final class SQLTypeRendererTests: XCTestCase { XCTAssertEqual(spelling("DOUBLE", from: .mysql, to: .postgres), "DOUBLE PRECISION") } + func testJSONForAPostgresTargetFollowsTheServerVersion() { + let json = SQLTypeParser.parse("JSON", family: .mysql) + XCTAssertEqual(SQLTypeRenderer.render(json, family: .postgres).spelling, "JSONB") + XCTAssertEqual(SQLTypeRenderer.render(json, family: .postgres, jsonColumnType: .jsonb).spelling, "JSONB") + XCTAssertEqual(SQLTypeRenderer.render(json, family: .postgres, jsonColumnType: .json).spelling, "JSON") + + let preJSON = SQLTypeRenderer.render(json, family: .postgres, jsonColumnType: .text) + XCTAssertEqual(preJSON.spelling, "TEXT") + XCTAssertEqual(preJSON.fidelity, .approximated) + XCTAssertNotNil(preJSON.reason) + } + + func testAJSONArrayForAPostgresTargetFollowsTheServerVersion() { + let array = CanonicalColumnType(kind: .array(element: .json), isUnsigned: false, sourceSpelling: "jsonb[]") + XCTAssertEqual(SQLTypeRenderer.render(array, family: .postgres, jsonColumnType: .json).spelling, "JSON[]") + XCTAssertEqual(SQLTypeRenderer.render(array, family: .postgres).spelling, "JSONB[]") + } + + /// Redshift reports 8.0.2 and CockroachDB reports 13.0.0. Reading either as a PostgreSQL + /// version turned a `JSONB` column into `TEXT` on a target that holds `JSONB` perfectly well. + func testOnlyPostgreSQLItselfReadsTheReportedVersion() { + XCTAssertEqual( + PostgreSQLServerVersion.jsonColumnType(for: .postgresql, serverVersion: "9.1.24"), .text + ) + XCTAssertEqual( + PostgreSQLServerVersion.jsonColumnType(for: .redshift, serverVersion: "8.0.2"), .jsonb + ) + XCTAssertEqual( + PostgreSQLServerVersion.jsonColumnType(for: .cockroachdb, serverVersion: "13.0.0"), .jsonb + ) + } + func testPostgresToMySQL() { XCTAssertEqual(spelling("boolean", from: .postgres, to: .mysql), "TINYINT(1)") XCTAssertEqual(spelling("int4", from: .postgres, to: .mysql), "INT") diff --git a/TableProTests/Core/Database/PostgreSQLDumpToolLocatorTests.swift b/TableProTests/Core/Database/PostgreSQLDumpToolLocatorTests.swift new file mode 100644 index 0000000000..a782e5e7ad --- /dev/null +++ b/TableProTests/Core/Database/PostgreSQLDumpToolLocatorTests.swift @@ -0,0 +1,177 @@ +// +// PostgreSQLDumpToolLocatorTests.swift +// TableProTests +// + +import Foundation +@testable import TablePro +import Testing + +@Suite("PostgreSQLDumpToolLocator") +struct PostgreSQLDumpToolLocatorTests { + private func makeInstall(root: URL, name: String, binary: String, fileManager: FileManager) throws { + let bin = root.appendingPathComponent("\(name)/bin", isDirectory: true) + try fileManager.createDirectory(at: bin, withIntermediateDirectories: true) + let tool = bin.appendingPathComponent(binary) + try Data("#!/bin/sh\n".utf8).write(to: tool) + try fileManager.setAttributes([.posixPermissions: 0o755], ofItemAtPath: tool.path) + } + + private func temporaryRoot() throws -> URL { + let root = URL(fileURLWithPath: NSTemporaryDirectory()) + .appendingPathComponent("pg-locator-\(UUID().uuidString)", isDirectory: true) + try FileManager.default.createDirectory(at: root, withIntermediateDirectories: true) + return root + } + + @Test("Only postgresql and libpq installs count under an opt root") + func filtersOptRootEntries() throws { + let base = try temporaryRoot() + defer { try? FileManager.default.removeItem(at: base) } + let optRoot = base.appendingPathComponent("opt", isDirectory: true) + for name in ["postgresql@14", "libpq", "libpq@18", "mysql-client", "redis"] { + try makeInstall(root: optRoot, name: name, binary: "pg_dump", fileManager: .default) + } + + let found = PostgreSQLDumpToolLocator.installedPaths(binary: "pg_dump", roots: [optRoot.path]) + #expect(found.map { URL(fileURLWithPath: $0).pathComponents.dropLast(2).last } == ["libpq", "libpq@18", "postgresql@14"]) + } + + @Test("Every entry counts under a versioned root that is not an opt directory") + func keepsVersionedRootEntries() throws { + let base = try temporaryRoot() + defer { try? FileManager.default.removeItem(at: base) } + let versions = base.appendingPathComponent("Versions", isDirectory: true) + for name in ["13", "17"] { + try makeInstall(root: versions, name: name, binary: "pg_dump", fileManager: .default) + } + + let found = PostgreSQLDumpToolLocator.installedPaths(binary: "pg_dump", roots: [versions.path]) + #expect(found.count == 2) + } + + @Test("Roots are searched in order and a symlinked duplicate is listed once") + func dedupesSymlinkedInstall() throws { + let base = try temporaryRoot() + defer { try? FileManager.default.removeItem(at: base) } + let first = base.appendingPathComponent("opt", isDirectory: true) + let second = base.appendingPathComponent("Versions", isDirectory: true) + try makeInstall(root: first, name: "postgresql@17", binary: "pg_dump", fileManager: .default) + try FileManager.default.createDirectory(at: second, withIntermediateDirectories: true) + try FileManager.default.createSymbolicLink( + at: second.appendingPathComponent("latest"), + withDestinationURL: first.appendingPathComponent("postgresql@17") + ) + + let found = PostgreSQLDumpToolLocator.installedPaths(binary: "pg_dump", roots: [first.path, second.path]) + #expect(found.count == 1) + #expect(found.first?.hasPrefix(first.path) == true) + } + + @Test("With no server version the PATH binary is taken as it always was") + func unknownServerTakesPathBinary() { + let selection = PostgreSQLDumpToolLocator.select( + binary: "pg_dump", + serverVersion: nil, + roots: [], + pathBinary: { _ in "/usr/bin/pg_dump" }, + probe: { _ in .known(PostgreSQLServerVersion(number: 170_011)) } + ) + #expect(selection == .found(path: "/usr/bin/pg_dump")) + } + + @Test("Nothing installed is missing, not incompatible") + func nothingInstalledIsMissing() { + let selection = PostgreSQLDumpToolLocator.select( + binary: "pg_dump", + serverVersion: "9.1.24", + roots: [], + pathBinary: { _ in nil }, + probe: { _ in .unknown } + ) + #expect(selection == .missing) + } + + @Test("An installed tool that cannot reach the server is incompatible, and the message names both") + func incompatibleNamesTheVersions() { + let selection = PostgreSQLDumpToolLocator.select( + binary: "pg_dump", + serverVersion: "9.1.24", + roots: [], + pathBinary: { _ in "/opt/homebrew/bin/pg_dump" }, + probe: { _ in .known(PostgreSQLServerVersion(number: 170_011)) } + ) + guard case .incompatible(let message) = selection else { + Issue.record("expected an incompatible selection, got \(selection)") + return + } + #expect(message.contains("PostgreSQL 9.1")) + #expect(message.contains("pg_dump 9.3 to 14")) + #expect(message.contains("17.11")) + } + + @Test("A binary whose version cannot be read is used rather than hidden") + func unreadableVersionIsStillUsed() { + let selection = PostgreSQLDumpToolLocator.select( + binary: "pg_dump", + serverVersion: "9.1.24", + roots: [], + pathBinary: { _ in "/usr/local/bin/pg_dump" }, + probe: { _ in .unknown } + ) + #expect(selection == .found(path: "/usr/local/bin/pg_dump")) + } + + @Test("A compatible install beats both the PATH binary and an unreadable one") + func compatibleInstallWins() throws { + let base = try temporaryRoot() + defer { try? FileManager.default.removeItem(at: base) } + let optRoot = base.appendingPathComponent("opt", isDirectory: true) + try makeInstall(root: optRoot, name: "postgresql@14", binary: "pg_dump", fileManager: .default) + try makeInstall(root: optRoot, name: "postgresql@12", binary: "pg_dump", fileManager: .default) + + let selection = PostgreSQLDumpToolLocator.select( + binary: "pg_dump", + serverVersion: "9.1.24", + roots: [optRoot.path], + pathBinary: { _ in "/opt/homebrew/bin/pg_dump" }, + probe: { path in + if path.contains("postgresql@14") { return .known(PostgreSQLServerVersion(number: 140_013)) } + if path.contains("postgresql@12") { return .known(PostgreSQLServerVersion(number: 120_022)) } + return .known(PostgreSQLServerVersion(number: 170_011)) + } + ) + #expect(selection == .found(path: "\(optRoot.path)/postgresql@14/bin/pg_dump")) + } + + @Test("pg_restore is matched to the server by the same rule as pg_dump") + func restoreBinaryFollowsTheSameRule() { + let selection = PostgreSQLDumpToolLocator.select( + binary: "pg_restore", + serverVersion: "9.1.24", + roots: [], + pathBinary: { _ in "/opt/homebrew/bin/pg_restore" }, + probe: { _ in .known(PostgreSQLServerVersion(number: 170_011)) } + ) + guard case .incompatible(let message) = selection else { + Issue.record("expected an incompatible selection, got \(selection)") + return + } + #expect(message.contains("pg_restore")) + #expect(!message.contains("pg_dump")) + } + + @Test("A probe that never answers is abandoned rather than left to hang") + func versionProbeTimesOut() throws { + let base = try temporaryRoot() + defer { try? FileManager.default.removeItem(at: base) } + let script = base.appendingPathComponent("hang.sh") + try Data("#!/bin/sh\nsleep 30\n".utf8).write(to: script) + try FileManager.default.setAttributes([.posixPermissions: 0o755], ofItemAtPath: script.path) + + let started = Date() + let probed = PostgreSQLDumpToolLocator.probeVersion(of: script.path, timeout: 0.5) + #expect(probed == .unknown) + #expect(Date().timeIntervalSince(started) < 5) + } +} diff --git a/TableProTests/Core/Database/PostgreSQLServerVersionTests.swift b/TableProTests/Core/Database/PostgreSQLServerVersionTests.swift new file mode 100644 index 0000000000..84935ad085 --- /dev/null +++ b/TableProTests/Core/Database/PostgreSQLServerVersionTests.swift @@ -0,0 +1,154 @@ +// +// PostgreSQLServerVersionTests.swift +// TableProTests +// + +import Foundation +@testable import TablePro +import Testing + +@Suite("PostgreSQLServerVersion") +struct PostgreSQLServerVersionTests { + @Test( + "Parses the strings drivers and tools report into server_version_num form", + arguments: [ + ("9.1.24", 90_124), + ("9.2.23", 90_223), + ("9.6.24", 90_624), + ("10.21", 100_021), + ("17.11", 170_011), + ("17.11 (Homebrew)", 170_011), + ("pg_dump (PostgreSQL) 17.11 (Homebrew)", 170_011), + ("pg_dump (PostgreSQL) 9.1.24", 90_124), + ("pg_dump (PostgreSQL) 12.22 (Debian 12.22-1.pgdg120+1)", 120_022), + ("10beta2", 100_000), + ("13.0.0", 130_000), + ("8.0.2", 80_002), + ("9.1", 90_100) + ] + ) + func parses(text: String, number: Int) { + #expect(PostgreSQLServerVersion(text)?.number == number) + } + + @Test("Text with no version number is not a version", arguments: ["", "PostgreSQL", "pg_dump (PostgreSQL)", "0.0"]) + func rejects(text: String) { + #expect(PostgreSQLServerVersion(text) == nil) + } + + @Test("A nil version string is not a version") + func rejectsNil() { + #expect(PostgreSQLServerVersion(nil) == nil) + } + + @Test("Major release names follow PostgreSQL's two numbering schemes") + func majorReleaseNames() { + #expect(PostgreSQLServerVersion(number: 90_124).majorReleaseName == "9.1") + #expect(PostgreSQLServerVersion(number: 170_011).majorReleaseName == "17") + #expect(PostgreSQLServerVersion(number: 90_124).fullName == "9.1.24") + #expect(PostgreSQLServerVersion(number: 170_011).fullName == "17.11") + } + + @Test("Major release numbers compare the release, not the patch level") + func majorReleaseNumbers() { + #expect(PostgreSQLServerVersion(number: 90_124).majorReleaseNumber == 901) + #expect(PostgreSQLServerVersion(number: 170_011).majorReleaseNumber == 1_700) + #expect(PostgreSQLServerVersion(number: 170_002).majorReleaseNumber == 1_700) + } +} + +@Suite("PostgreSQLDumpToolCompatibility") +struct PostgreSQLDumpToolCompatibilityTests { + private func version(_ text: String) throws -> PostgreSQLServerVersion { + try #require(PostgreSQLServerVersion(text)) + } + + @Test( + "pg_dump refuses servers newer than itself and, from 15, servers older than 9.2", + arguments: [ + ("9.1.24", "17.11", false), + ("9.1.24", "18.6", false), + ("9.1.24", "14.13", true), + ("9.1.24", "12.22", true), + ("9.2.23", "17.11", true), + ("9.6.24", "18.6", true), + ("17.11", "17.2", true), + ("17.11", "16.4", false), + ("12.22", "9.6.24", false), + ("9.1.24", "9.2.23", false), + ("9.1.24", "9.3.25", true) + ] + ) + func canDump(server: String, tool: String, expected: Bool) throws { + #expect(PostgreSQLDumpToolCompatibility.canDump(server: try version(server), with: try version(tool)) == expected) + } + + @Test("The tool found on PATH wins when it can dump the server") + func prefersPathTool() throws { + let preferred = PostgreSQLDumpToolCompatibility.Candidate(path: "/opt/homebrew/bin/pg_dump", version: try version("17.11")) + let other = PostgreSQLDumpToolCompatibility.Candidate(path: "/opt/homebrew/opt/libpq/bin/pg_dump", version: try version("18.6")) + let chosen = PostgreSQLDumpToolCompatibility.choose(for: try version("12.22"), preferred: preferred, others: [other]) + #expect(chosen == preferred) + } + + @Test("An older installed tool is chosen when the PATH tool refuses the server") + func fallsBackToOlderTool() throws { + let preferred = PostgreSQLDumpToolCompatibility.Candidate(path: "/opt/homebrew/bin/pg_dump", version: try version("17.11")) + let fourteen = PostgreSQLDumpToolCompatibility.Candidate( + path: "/opt/homebrew/opt/postgresql@14/bin/pg_dump", version: try version("14.13") + ) + let twelve = PostgreSQLDumpToolCompatibility.Candidate( + path: "/Applications/Postgres.app/Contents/Versions/12/bin/pg_dump", version: try version("12.22") + ) + let chosen = PostgreSQLDumpToolCompatibility.choose( + for: try version("9.1.24"), preferred: preferred, others: [twelve, fourteen] + ) + #expect(chosen == fourteen) + } + + @Test("Nothing is chosen when no installed tool can dump the server") + func noCompatibleTool() throws { + let preferred = PostgreSQLDumpToolCompatibility.Candidate(path: "/opt/homebrew/bin/pg_dump", version: try version("17.11")) + #expect(PostgreSQLDumpToolCompatibility.choose(for: try version("9.1.24"), preferred: preferred, others: []) == nil) + } + + @Test("The refusal for a 9.1 server names the tool, the 9.3 to 14 range and what was found") + func refusalForOldServer() throws { + let found = [ + PostgreSQLDumpToolCompatibility.Candidate(path: "/a", version: try version("18.6")), + PostgreSQLDumpToolCompatibility.Candidate(path: "/b", version: try version("17.11")) + ] + let server = try version("9.1.24") + let message = PostgreSQLDumpToolCompatibility.refusal(for: server, found: found, toolName: "pg_dump") + #expect(message.contains("PostgreSQL 9.1 needs pg_dump 9.3 to 14.")) + #expect(message.contains("brew install postgresql@14")) + #expect(message.contains("Found pg_dump 17.11 and 18.6.")) + } + + @Test("The refusal for a 7.x server stops at 9.6, the newest tool that reaches it") + func refusalForPreEightServer() throws { + let found = [PostgreSQLDumpToolCompatibility.Candidate(path: "/a", version: try version("17.11"))] + let server = try version("7.4.30") + let message = PostgreSQLDumpToolCompatibility.refusal(for: server, found: found, toolName: "pg_dump") + #expect(message.contains("PostgreSQL 7.4 needs pg_dump 9.3 to 9.6.")) + #expect(!message.contains("postgresql@14")) + } + + @Test("The refusal names pg_restore when it is pg_restore that cannot reach the server") + func refusalNamesTheRestoreTool() throws { + let found = [PostgreSQLDumpToolCompatibility.Candidate(path: "/a", version: try version("17.11"))] + let server = try version("9.1.24") + let message = PostgreSQLDumpToolCompatibility.refusal(for: server, found: found, toolName: "pg_restore") + #expect(message.contains("PostgreSQL 9.1 needs pg_restore 9.3 to 14.")) + #expect(message.contains("Found pg_restore 17.11.")) + } + + @Test("The refusal for a server newer than every tool names that release") + func refusalForNewServer() throws { + let found = [PostgreSQLDumpToolCompatibility.Candidate(path: "/a", version: try version("17.11"))] + let server = try version("19.0") + let message = PostgreSQLDumpToolCompatibility.refusal(for: server, found: found, toolName: "pg_dump") + #expect(message.contains("PostgreSQL 19 needs pg_dump 19 or later.")) + #expect(message.contains("brew install libpq")) + } +} diff --git a/TableProTests/Core/MCP/MCPServerDashboardPayloadTests.swift b/TableProTests/Core/MCP/MCPServerDashboardPayloadTests.swift new file mode 100644 index 0000000000..f1eb5e854d --- /dev/null +++ b/TableProTests/Core/MCP/MCPServerDashboardPayloadTests.swift @@ -0,0 +1,62 @@ +// +// MCPServerDashboardPayloadTests.swift +// TableProTests +// + +import Foundation +@testable import TablePro +import Testing + +@Suite("get_server_dashboard payload") +struct MCPServerDashboardPayloadTests { + @Test("Panels that all read come back without an errors object") + func noFailures() throws { + let payload = try MCPConnectionBridge.dashboardPayload( + panels: ["sessions": .array([]), "metrics": .array([])], + failures: [:] + ) + #expect(payload == .object(["sessions": .array([]), "metrics": .array([])])) + } + + @Test("A panel that failed is reported under errors instead of as an empty list") + func partialFailure() throws { + let payload = try MCPConnectionBridge.dashboardPayload( + panels: ["slow_queries": .array([])], + failures: ["sessions": MCPConnectionBridge.dashboardPanelFailure( + panel: "sessions", error: DatabaseAccessError.dataSourceError("column \"pid\" does not exist") + )] + ) + let errors = payload["errors"]?["sessions"]?.stringValue + #expect(errors == "The server did not answer the sessions panel.") + #expect(errors?.contains("pid") == false) + #expect(payload["slow_queries"] == .array([])) + } + + @Test("A panel failure never carries the server's own words to the client") + func panelFailureIsFixedText() { + let message = MCPConnectionBridge.dashboardPanelFailure( + panel: "slow_queries", + error: DatabaseAccessError.dataSourceError("permission denied for table secrets") + ) + #expect(message == "The server did not answer the slow queries panel.") + #expect(!message.contains("secrets")) + } + + @Test("The output schema declares the errors object, one message per panel") + func outputSchemaDeclaresErrors() { + let errors = ServerDashboardTool.outputSchema?["properties"]?["errors"]?["properties"] + for panel in ServerDashboardTool.panelNames { + #expect(errors?[panel]?["type"]?.stringValue == "string") + } + } + + @Test("When every requested panel fails the call fails") + func everyPanelFails() { + #expect(throws: DatabaseAccessError.self) { + _ = try MCPConnectionBridge.dashboardPayload( + panels: [:], + failures: ["sessions": "boom", "metrics": "bang"] + ) + } + } +} diff --git a/TableProTests/Core/Plugins/ImportTypeMapperTests.swift b/TableProTests/Core/Plugins/ImportTypeMapperTests.swift index 6c09bba6b8..72c028dbd5 100644 --- a/TableProTests/Core/Plugins/ImportTypeMapperTests.swift +++ b/TableProTests/Core/Plugins/ImportTypeMapperTests.swift @@ -19,6 +19,29 @@ struct ImportTypeMapperTests { #expect(ImportTypeMapper.sqlType(for: .text, databaseType: .postgresql) == "TEXT") } + @Test( + "A JSON field on PostgreSQL takes the richest type the server has", + arguments: [ + (Optional.none, "JSONB"), + (Optional("17.11"), "JSONB"), + (Optional("9.4.26"), "JSONB"), + (Optional("9.3.25"), "JSON"), + (Optional("9.2.23"), "JSON"), + (Optional("9.1.24"), "TEXT") + ] + ) + func postgresJSONFollowsServerVersion(serverVersion: String?, expected: String) { + #expect( + ImportTypeMapper.sqlType(for: .json, databaseType: .postgresql, serverVersion: serverVersion) == expected + ) + } + + @Test("Redshift and CockroachDB keep their JSON mapping whatever version they report") + func postgresForksKeepJSONMapping() { + #expect(ImportTypeMapper.sqlType(for: .json, databaseType: .redshift, serverVersion: "8.0.2") == "JSONB") + #expect(ImportTypeMapper.sqlType(for: .json, databaseType: .cockroachdb, serverVersion: "13.0.0") == "JSONB") + } + @Test("MySQL maps inferred types to native SQL types") func testMySQL() { #expect(ImportTypeMapper.sqlType(for: .integer, databaseType: .mysql) == "BIGINT") diff --git a/TableProTests/Core/ServerDashboard/PostgreSQLDashboardProviderTests.swift b/TableProTests/Core/ServerDashboard/PostgreSQLDashboardProviderTests.swift new file mode 100644 index 0000000000..11f3799e87 --- /dev/null +++ b/TableProTests/Core/ServerDashboard/PostgreSQLDashboardProviderTests.swift @@ -0,0 +1,144 @@ +// +// PostgreSQLDashboardProviderTests.swift +// TableProTests +// + +import Foundation +@testable import TablePro +import TableProPluginKit +import Testing + +@Suite("PostgreSQL server dashboard across server versions") +struct PostgreSQLDashboardProviderTests { + private struct QueryFailure: Error {} + + private func catalog(for databaseType: DatabaseType, serverVersion: String?) throws -> PostgreSQLActivityCatalog { + let provider = ServerDashboardQueryProviderFactory.provider(for: databaseType, serverVersion: serverVersion) + let postgres = try #require(provider as? PostgreSQLDashboardProvider) + return postgres.activityCatalog + } + + private func result(columns: [String], rows: [[String?]]) -> QueryResult { + QueryResult( + columns: columns, + columnTypes: [], + rows: rows.map { row in row.map { $0.map { PluginCellValue.text($0) } ?? .null } }, + rowsAffected: 0, + executionTime: 0, + error: nil + ) + } + + @Test( + "PostgreSQL picks the pg_stat_activity shape its server version has", + arguments: [ + ("9.1.24", PostgreSQLActivityCatalog.procpid), + ("9.2.23", .withoutBackendType), + ("9.6.24", .withoutBackendType), + ("10.21", .current), + ("17.11", .current) + ] + ) + func postgresCatalogFollowsVersion(serverVersion: String, expected: PostgreSQLActivityCatalog) throws { + #expect(try catalog(for: .postgresql, serverVersion: serverVersion) == expected) + } + + @Test("An unknown PostgreSQL version keeps the current catalog") + func unknownVersionKeepsCurrent() throws { + #expect(try catalog(for: .postgresql, serverVersion: nil) == .current) + #expect(try catalog(for: .postgresql, serverVersion: "unparsable") == .current) + } + + @Test("Redshift and CockroachDB keep the current catalog whatever version they report") + func forksKeepCurrent() throws { + #expect(try catalog(for: .redshift, serverVersion: "8.0.2") == .current) + #expect(try catalog(for: .cockroachdb, serverVersion: "13.0.0") == .current) + } + + @Test("Servers before 10 never ask for backend_type") + func legacyCatalogsSkipBackendType() { + for catalog in [PostgreSQLActivityCatalog.withoutBackendType, .procpid] { + let queries = [ + catalog.sessionsQuery, catalog.connectionCountQuery, + catalog.activeQueryCountQuery, catalog.slowQueriesQuery + ] + #expect(queries.allSatisfy { !$0.contains("backend_type") }) + } + } + + @Test("Servers before 9.2 read procpid and current_query, never pid, state or query") + func procpidCatalogUsesPreNinePointTwoColumns() { + let catalog = PostgreSQLActivityCatalog.procpid + let queries = [catalog.sessionsQuery, catalog.activeQueryCountQuery, catalog.slowQueriesQuery] + #expect(queries.allSatisfy { $0.contains("procpid <> pg_backend_pid()") && $0.contains("current_query") }) + #expect(queries.allSatisfy { !$0.contains("left(query") }) + #expect(catalog.sessionsQuery.contains("SELECT procpid AS pid")) + #expect(catalog.slowQueriesQuery.contains("SELECT procpid AS pid")) + #expect(!catalog.slowQueriesQuery.contains("state =")) + #expect(!catalog.activeQueryCountQuery.contains("state =")) + } + + @Test("The current catalog is the SQL the dashboard has always sent") + func currentCatalogIsUnchanged() { + let catalog = PostgreSQLActivityCatalog.current + #expect(catalog.connectionCountQuery == "SELECT count(*) FROM pg_stat_activity WHERE backend_type = 'client backend'") + #expect(catalog.sessionsQuery.contains("AND backend_type = 'client backend'")) + #expect(catalog.slowQueriesQuery.contains("WHERE state = 'active'")) + } + + @Test("CockroachDB is asked only for the metrics it has") + func cockroachMetricSet() throws { + let provider = ServerDashboardQueryProviderFactory.provider(for: .cockroachdb, serverVersion: "13.0.0") + let postgres = try #require(provider as? PostgreSQLDashboardProvider) + #expect(postgres.metricSet == .activityOnly) + #expect(PostgreSQLDashboardMetricSet(databaseType: .postgresql) == .full) + #expect(PostgreSQLDashboardMetricSet(databaseType: .redshift) == .full) + } + + @Test("The CockroachDB metric set runs two statements, not five") + func cockroachRunsTwoStatements() async throws { + let provider = PostgreSQLDashboardProvider(activityCatalog: .current, metricSet: .activityOnly) + var asked: [String] = [] + let metrics = try await provider.fetchMetrics { sql in + asked.append(sql) + return result(columns: ["value"], rows: [["2"]]) + } + #expect(asked.count == 2) + #expect(metrics.map(\.id) == ["connections", "active_queries"]) + #expect(!asked.contains { $0.contains("pg_size_pretty") || $0.contains("pg_postmaster_start_time") }) + } + + @Test("One failing metric leaves the others on the panel") + func metricFailureIsIsolated() async throws { + let provider = PostgreSQLDashboardProvider(activityCatalog: .current) + let metrics = try await provider.fetchMetrics { sql in + if sql.contains("backend_type") { throw QueryFailure() } + return result(columns: ["value"], rows: [["7"]]) + } + #expect(metrics.map(\.id) == ["cache_hit", "db_size", "uptime", "active_queries"]) + } + + @Test("The metrics panel fails only when every metric fails") + func metricsFailWhenAllFail() async { + let provider = PostgreSQLDashboardProvider(activityCatalog: .current) + await #expect(throws: QueryFailure.self) { + _ = try await provider.fetchMetrics { _ in throw QueryFailure() } + } + } + + @Test("Sessions map pid, state and query from the procpid catalog's aliases") + func procpidSessionsMap() async throws { + let provider = PostgreSQLDashboardProvider(activityCatalog: .procpid) + let sessions = try await provider.fetchSessions { _ in + result( + columns: ["pid", "usename", "datname", "state", "duration_secs", "query"], + rows: [["1733", "postgres", "app", "active", "3", "SELECT pg_sleep(12)"]] + ) + } + let session = try #require(sessions.first) + #expect(session.id == "1733") + #expect(session.state == "active") + #expect(session.durationSeconds == 3) + #expect(session.query == "SELECT pg_sleep(12)") + } +} diff --git a/TableProTests/Core/Services/Query/PostgreSQLPlanParserTests.swift b/TableProTests/Core/Services/Query/PostgreSQLPlanParserTests.swift index 2a845abd1a..15b68f13fa 100644 --- a/TableProTests/Core/Services/Query/PostgreSQLPlanParserTests.swift +++ b/TableProTests/Core/Services/Query/PostgreSQLPlanParserTests.swift @@ -123,6 +123,34 @@ struct PostgreSQLPlanParserTests { #expect(plan.rootNode.actualLoops == 1) } + @Test("PostgreSQL 9.3 and earlier report the run time as Total Runtime") + func readsTotalRuntimeFromOlderServers() throws { + let legacyPlan = """ + [ + { + "Plan": { + "Node Type": "Result", + "Startup Cost": 0.00, + "Total Cost": 0.01, + "Plan Rows": 1, + "Plan Width": 0, + "Actual Startup Time": 0.191, + "Actual Total Time": 0.193, + "Actual Rows": 1, + "Actual Loops": 1 + }, + "Triggers": [], + "Total Runtime": 1.464 + } + ] + """ + + let plan = try #require(parser.parse(rawText: legacyPlan)) + + #expect(plan.executionTime == 1.464) + #expect(plan.planningTime == nil) + } + @Test("Rejects malformed and non-plan input") func rejectsMalformedInput() { #expect(parser.parse(rawText: "") == nil) diff --git a/TableProTests/Database/NativeDumpRegistryTests.swift b/TableProTests/Database/NativeDumpRegistryTests.swift index ebc5e0a6eb..9790dbb39e 100644 --- a/TableProTests/Database/NativeDumpRegistryTests.swift +++ b/TableProTests/Database/NativeDumpRegistryTests.swift @@ -73,6 +73,24 @@ struct NativeDumpRegistryTests { } } + @Test("PostgreSQL matches its tools to the server, Redshift and MySQL keep the plain lookup") + func postgresToolsFollowTheServer() throws { + let postgres = try #require(NativeDumpRegistry.descriptor(for: .postgresql)?.commandLineTool) + let redshift = try #require(NativeDumpRegistry.descriptor(for: .redshift)?.commandLineTool) + let mysql = try #require(NativeDumpRegistry.descriptor(for: .mysql)?.commandLineTool) + #expect(postgres.toolForServer != nil) + #expect(redshift.toolForServer == nil) + #expect(mysql.toolForServer == nil) + } + + @Test("One selector covers both directions, so a restore is matched to the server too") + func postgresRestoreUsesTheSameSelector() throws { + let postgres = try #require(NativeDumpRegistry.descriptor(for: .postgresql)?.commandLineTool) + #expect(postgres.binaries(for: .backup) == ["pg_dump"]) + #expect(postgres.binaries(for: .restore) == ["pg_restore"]) + #expect(postgres.toolForServer != nil) + } + @Test("Each engine offers its own archive extension") func archiveExtensions() throws { #expect(try #require(NativeDumpRegistry.descriptor(for: .postgresql)).archiveFormat.fileExtension == "dump") diff --git a/docs/external-api/mcp-tools.mdx b/docs/external-api/mcp-tools.mdx index 2b78be43f6..32360635e0 100644 --- a/docs/external-api/mcp-tools.mdx +++ b/docs/external-api/mcp-tools.mdx @@ -157,13 +157,13 @@ Formats are `csv`, `json` and `sql`; pass exactly one of `query` or `tables[]`. | Tool | Arguments | Returns | |------|-----------|---------| -| `get_server_dashboard` | `connection_id` (`panels`) | The requested panels: `sessions`, `metrics`, `slow_queries` | +| `get_server_dashboard` | `connection_id` (`panels`) | The requested panels: `sessions`, `metrics`, `slow_queries`, plus `errors` for any the server could not answer | | `stop_server_session` | `connection_id`, `process_id` (`mode`) | The result set the engine produced | | `list_principals` | `connection_id` | `principals[]` (`name`, `host`, `is_role`, `can_login`, `member_of[]`, `connection_limit`, `comment`, and `attributes[]` of `{ key, label, is_enabled }`), sorted by name | | `list_grants` | `connection_id`, `principal` (`host`) | `principal`, `grants[]` (`privilege`, `scope`, `is_grantable`). `scope` is a dotted path, `*` for a server-wide grant | | `list_session_contexts` | `connection_id` | `is_supported`, `contexts[]` (`id`, `label`, `value`, `options[]`) | -`get_server_dashboard` reads the live panels TablePro shows, and runs on PostgreSQL, MySQL, SQL Server, ClickHouse, DuckDB and SQLite. Name the panels in `panels[]` or omit it for all three. A session carries `id` (the process id `stop_server_session` takes), `user`, `database`, `state`, `duration_seconds`, `query`, `can_kill` and `can_cancel`; a metric carries `id`, `label`, `value`, `unit`; a slow query carries `duration`, `query`, `user`, `database`. +`get_server_dashboard` reads the live panels TablePro shows, and runs on PostgreSQL, MySQL, SQL Server, ClickHouse, DuckDB and SQLite. Name the panels in `panels[]` or omit it for all three. A session carries `id` (the process id `stop_server_session` takes), `user`, `database`, `state`, `duration_seconds`, `query`, `can_kill` and `can_cancel`; a metric carries `id`, `label`, `value`, `unit`; a slow query carries `duration`, `query`, `user`, `database`. A panel the server could not answer is left out, and `errors` names it: one fixed sentence per panel, keyed by panel name. The server's own message is not sent to the client; it goes to the app's log, where the user can read it. When every requested panel fails, the call fails. `stop_server_session` takes `mode` as `cancel` (default) to stop the running query or `kill` to end the session. The user always approves this one, whatever Safe Mode says. diff --git a/docs/features/backup-restore.mdx b/docs/features/backup-restore.mdx index 8a4c069236..9e1b0599e7 100644 --- a/docs/features/backup-restore.mdx +++ b/docs/features/backup-restore.mdx @@ -18,6 +18,8 @@ MariaDB 11.0 renamed its clients, so `mariadb-dump` and `mariadb` are accepted i The lookup takes the first match from `/usr/bin/which`, then `/opt/homebrew/bin`, `/usr/local/bin`, and Postgres.app's latest version. That path decides which client version does the work. +On PostgreSQL that match is checked against the server first, for both directions. `pg_dump` and `pg_restore` refuse a server newer than themselves, 15 and later refuse servers older than 9.2, and TablePro names the database with `-d`, which arrived in 9.3. When the first match cannot reach the server, the newest one that can is taken from the Homebrew `postgresql@…` and `libpq` installs, every Postgres.app version, and `/Library/PostgreSQL`. When none can, the run stops before it starts and names the version to install: PostgreSQL 9.1 needs `pg_dump` 9.3 to 14, so `brew install postgresql@14`. A binary that does not answer `--version` is used anyway. + DuckDB is the exception: its dump is a statement the engine already in front of TablePro runs, over the connection that is already open. **File > Backup Dump…** is dimmed on an engine that is not in the table, and on a libSQL connection pointed at a Turso URL rather than a local file, which `sqlite3` cannot reach. For those, use a SQL export from [Import & Export](/features/import-export). diff --git a/docs/features/copy-objects.mdx b/docs/features/copy-objects.mdx index 3663de3e42..bc7b4b8e30 100644 --- a/docs/features/copy-objects.mdx +++ b/docs/features/copy-objects.mdx @@ -92,7 +92,9 @@ reshaped where the source and the target spell a value differently. `TINYINT(1)` `TINYINT(1)` as `1`. Nothing is dropped for want of a type. A type the target does not have becomes its widest text -column, so the values arrive as text rather than the column going missing. +column, so the values arrive as text rather than the column going missing. The target server's +version counts too: a JSON column crossing into PostgreSQL arrives as `jsonb` from 9.4, `json` on 9.2 +and 9.3, and `text` on 9.1. The review step lists every column and index the crossing changed, one line each. It is the only place those conversions appear, and it is shown before **Copy** does anything. @@ -195,6 +197,10 @@ into it is treated as one engine and passes its types through, so a `jsonb`, `uu is refused by the server with its own error. Change those columns to `varchar` on the source, or create the target table first and use **Add rows to it**. +A copy from PostgreSQL into an older PostgreSQL passes its types through the same way, so a `jsonb` +column is refused by a server before 9.4. Create the target table first with `json` or `text`, then +use **Add rows to it**. + Duplicate Database needs a driver that creates one. Where it does not, the command still appears and the sheet names the engine that cannot rather than failing part way in. diff --git a/docs/features/import-export.mdx b/docs/features/import-export.mdx index 00f37f1f1b..eaa2c74533 100644 --- a/docs/features/import-export.mdx +++ b/docs/features/import-export.mdx @@ -306,7 +306,7 @@ The sheet accepts an array of objects `[{…}, {…}]`, newline-delimited JSON s The proposed name drops the extension, turns spaces and punctuation into underscores, and lowercases the result. Letters from any script are kept as they are. On Oracle the name comes through in upper case instead, and is cut to 30 bytes rather than 63. A name an existing table or view already holds gains a numeric suffix, so re-importing `users.csv` next to a `users` table proposes `users_2`. Whatever you type over it is held to the same rules: a name already taken, one longer than the engine allows, or one starting with a prefix the engine keeps for itself is reported in the sheet, with **Import** off until it changes. -Rows insert through parameterized statements, so a JSON value is never concatenated into SQL. Nested objects and arrays are stored as JSON text. +Rows insert through parameterized statements, so a JSON value is never concatenated into SQL. Nested objects and arrays are stored as JSON text. In a new PostgreSQL table their column is `jsonb`, or `json` on 9.2 and 9.3, and `text` on 9.1, which has no JSON type. ### Import XLSX diff --git a/docs/features/server-dashboard.mdx b/docs/features/server-dashboard.mdx index c21ef8d762..93b975a73a 100644 --- a/docs/features/server-dashboard.mdx +++ b/docs/features/server-dashboard.mdx @@ -34,6 +34,8 @@ Every connection to the server except this one, sortable, one row each. | Duration | How long the current operation has been running | | Query | The statement, truncated at 1,000 characters. Hover for the full text | +On PostgreSQL 9.1 an idle session shows an empty Query: that server keeps only the running statement, not the last one. + Two buttons sit on each row. **Cancel Query** stops the running statement and leaves the connection up: `pg_cancel_backend` on PostgreSQL, `KILL QUERY` on MySQL. **Terminate Session** ends the connection itself with `pg_terminate_backend` or `KILL`, and the server rolls back any transaction that session had open. Both confirm first, and a refusal from the server comes back as an **Action Failed** alert. ## Slow Queries @@ -50,7 +52,8 @@ The interval menu offers 1s, 2s, 5s (the default), 10s, 30s, and Off. **Pause** | Database | Sessions | Metrics | Slow queries | Cancel | Terminate | |----------|:--------:|---------|:------------:|:------:|:---------:| -| PostgreSQL / Redshift / CockroachDB | Yes | Connections, cache hit ratio, database size, uptime, active queries | Yes | Yes | Yes | +| PostgreSQL / Redshift | Yes | Connections, cache hit ratio, database size, uptime, active queries | Yes | Yes | Yes | +| CockroachDB | Yes | Connections, active queries | Yes | Yes | Yes | | MySQL / MariaDB | Yes | Connected threads, running threads, uptime, total queries, slow queries, max connections, bytes received, bytes sent | Yes | Yes | Yes | | SQL Server | Yes | User sessions, uptime, database size | Yes | - | Yes | | ClickHouse | Yes | Active queries, active merges, part mutations, disk usage | Yes | - | Yes | From b700347d00bb6d51a0975a0cf6d5cfc42eeff7ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 08:25:34 +0700 Subject: [PATCH 31/54] fix(plugin-postgresql): detect a lost connection from libpq, not the error text (#2765) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ngô Quốc Đạt --- CHANGELOG.md | 2 + Plugins/BeancountDriverPlugin/Info.plist | 2 +- Plugins/BigQueryDriverPlugin/Info.plist | 2 +- Plugins/CSVExportPlugin/Info.plist | 2 +- Plugins/CSVImportPlugin/Info.plist | 2 +- Plugins/CassandraDriverPlugin/Info.plist | 2 +- Plugins/ClickHouseDriverPlugin/Info.plist | 2 +- Plugins/CloudflareD1DriverPlugin/Info.plist | 2 +- .../CloudflareR2SQLDriverPlugin/Info.plist | 2 +- .../DamengPluginDriver+Session.swift | 5 +- Plugins/DamengDriverPlugin/Info.plist | 2 +- Plugins/DuckDBDriverPlugin/Info.plist | 2 +- Plugins/DynamoDBDriverPlugin/Info.plist | 2 +- Plugins/ElasticsearchDriverPlugin/Info.plist | 2 +- Plugins/EtcdDriverPlugin/Info.plist | 2 +- Plugins/HTMLExportPlugin/Info.plist | 2 +- Plugins/JSONExportPlugin/Info.plist | 2 +- Plugins/JSONImportPlugin/Info.plist | 2 +- Plugins/KafkaDriverPlugin/Info.plist | 2 +- Plugins/LibSQLDriverPlugin/Info.plist | 2 +- Plugins/MQLExportPlugin/Info.plist | 2 +- Plugins/MSSQLDriverPlugin/Info.plist | 2 +- Plugins/MarkdownExportPlugin/Info.plist | 2 +- Plugins/MongoDBDriverPlugin/Info.plist | 2 +- Plugins/MySQLDriverPlugin/Info.plist | 2 +- Plugins/OracleDriverPlugin/Info.plist | 2 +- Plugins/ParquetExportPlugin/Info.plist | 2 +- Plugins/PostgreSQLDriverPlugin/Info.plist | 2 +- .../LibPQConnectionLoss.swift | 86 +++++++++++ .../LibPQDriverCore.swift | 141 +++++++----------- .../LibPQPluginConnection.swift | 115 +++++++++++++- .../LibPQServerMessageSink.swift | 58 +++++++ Plugins/RedisDriverPlugin/Info.plist | 2 +- Plugins/SQLExportPlugin/Info.plist | 2 +- Plugins/SQLImportPlugin/Info.plist | 2 +- Plugins/SQLiteDriverPlugin/Info.plist | 2 +- Plugins/SnowflakeDriverPlugin/Info.plist | 2 +- Plugins/SpannerDriverPlugin/Info.plist | 2 +- Plugins/SurrealDBDriverPlugin/Info.plist | 2 +- .../PluginDatabaseDriver.swift | 3 + Plugins/TeradataDriverPlugin/Info.plist | 2 +- Plugins/TrinoDriverPlugin/Info.plist | 2 +- Plugins/TypesenseDriverPlugin/Info.plist | 2 +- Plugins/XLSXExportPlugin/Info.plist | 2 +- Plugins/XLSXImportPlugin/Info.plist | 2 +- Plugins/XMLExportPlugin/Info.plist | 2 +- TablePro/Core/Database/DatabaseDriver.swift | 4 + .../DatabaseManager+Verification.swift | 8 +- .../Core/Plugins/PluginDriverAdapter.swift | 4 + TablePro/Core/Plugins/PluginManager.swift | 2 +- .../Query/MetadataConnectionPool.swift | 14 +- .../Autocomplete/SQLSchemaProviderTests.swift | 1 + .../ConnectionVerificationTests.swift | 13 ++ .../LostConnectionReportingTests.swift | 59 ++++++++ .../Query/MetadataConnectionPoolTests.swift | 14 +- TableProTests/Helpers/FakeMSSQLPlugin.swift | 6 +- .../Plugins/LibPQConnectionLossTests.swift | 139 +++++++++++++++++ docs/development/plugin-development.mdx | 2 +- docs/development/plugin-registry.mdx | 4 +- project.yml | 1 + 60 files changed, 614 insertions(+), 145 deletions(-) create mode 100644 Plugins/PostgreSQLDriverPlugin/LibPQConnectionLoss.swift create mode 100644 Plugins/PostgreSQLDriverPlugin/LibPQServerMessageSink.swift create mode 100644 TableProTests/Core/Database/LostConnectionReportingTests.swift create mode 100644 TableProTests/Plugins/LibPQConnectionLossTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 8992cb5755..fceccdd9e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -192,6 +192,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Non-ASCII SQL Server filter values turned into `?` and matching the wrong rows on non-Unicode collations. - Empty structure, missing indexes and failed renames for non-ASCII SQL Server object names on non-Unicode collations. - Changing a defaulted SQL Server column failing when a name contains a quote or non-ASCII text. +- Silent replay of a PostgreSQL statement on a new connection after a drop, a lost `COMMIT` reported as saved included. +- Query timeout and startup commands missing after the PostgreSQL driver reconnected on its own. - Server Dashboard sessions, metrics and slow queries failing on PostgreSQL 9.6 and earlier. - One unanswered metric emptying the whole Server Dashboard metrics panel on PostgreSQL, Redshift and CockroachDB. - MCP `get_server_dashboard` reporting a panel the server could not read as an empty list. diff --git a/Plugins/BeancountDriverPlugin/Info.plist b/Plugins/BeancountDriverPlugin/Info.plist index 506f627671..f2092a8740 100644 --- a/Plugins/BeancountDriverPlugin/Info.plist +++ b/Plugins/BeancountDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesDatabaseTypeIds Beancount diff --git a/Plugins/BigQueryDriverPlugin/Info.plist b/Plugins/BigQueryDriverPlugin/Info.plist index 9747423174..832b49a1ce 100644 --- a/Plugins/BigQueryDriverPlugin/Info.plist +++ b/Plugins/BigQueryDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 26 + 27 diff --git a/Plugins/CSVExportPlugin/Info.plist b/Plugins/CSVExportPlugin/Info.plist index 5ae5323703..f3fd1d096d 100644 --- a/Plugins/CSVExportPlugin/Info.plist +++ b/Plugins/CSVExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesExportFormatIds csv diff --git a/Plugins/CSVImportPlugin/Info.plist b/Plugins/CSVImportPlugin/Info.plist index 377e920221..3193aefa9f 100644 --- a/Plugins/CSVImportPlugin/Info.plist +++ b/Plugins/CSVImportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesImportFormatIds csv diff --git a/Plugins/CassandraDriverPlugin/Info.plist b/Plugins/CassandraDriverPlugin/Info.plist index d4199c62eb..2401c48616 100644 --- a/Plugins/CassandraDriverPlugin/Info.plist +++ b/Plugins/CassandraDriverPlugin/Info.plist @@ -21,6 +21,6 @@ NSPrincipalClass $(PRODUCT_MODULE_NAME).CassandraPlugin TableProPluginKitVersion - 26 + 27 diff --git a/Plugins/ClickHouseDriverPlugin/Info.plist b/Plugins/ClickHouseDriverPlugin/Info.plist index 5fd3dd4c61..8ce272816c 100644 --- a/Plugins/ClickHouseDriverPlugin/Info.plist +++ b/Plugins/ClickHouseDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesDatabaseTypeIds ClickHouse diff --git a/Plugins/CloudflareD1DriverPlugin/Info.plist b/Plugins/CloudflareD1DriverPlugin/Info.plist index 9747423174..832b49a1ce 100644 --- a/Plugins/CloudflareD1DriverPlugin/Info.plist +++ b/Plugins/CloudflareD1DriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 26 + 27 diff --git a/Plugins/CloudflareR2SQLDriverPlugin/Info.plist b/Plugins/CloudflareR2SQLDriverPlugin/Info.plist index 158b1c8cb3..b46ca19179 100644 --- a/Plugins/CloudflareR2SQLDriverPlugin/Info.plist +++ b/Plugins/CloudflareR2SQLDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesDatabaseTypeIds Cloudflare R2 SQL diff --git a/Plugins/DamengDriverPlugin/DamengPluginDriver+Session.swift b/Plugins/DamengDriverPlugin/DamengPluginDriver+Session.swift index 8f12a3c6f2..4f5e7a4ad8 100644 --- a/Plugins/DamengDriverPlugin/DamengPluginDriver+Session.swift +++ b/Plugins/DamengDriverPlugin/DamengPluginDriver+Session.swift @@ -22,9 +22,8 @@ extension DamengPluginDriver { /// Runs a statement, and when the connection died under it, rebuilds the connection and /// runs it once more. /// - /// This is the shape MySQL (`MySQLPluginDriver.executeWithReconnect`) and PostgreSQL - /// (`LibPQDriverCore.executeWithReconnect`) already ship, and it is what the Dameng - /// driver's own documentation has always claimed to do. A stop is never retried: the user + /// This is the shape MySQL (`MySQLPluginDriver.executeWithReconnect`) already ships, and it + /// is what the Dameng driver's own documentation has always claimed to do. A stop is never retried: the user /// asked for the statement to end. func executeWithReconnect( query: String, diff --git a/Plugins/DamengDriverPlugin/Info.plist b/Plugins/DamengDriverPlugin/Info.plist index 6880e4bcd5..492ba91715 100644 --- a/Plugins/DamengDriverPlugin/Info.plist +++ b/Plugins/DamengDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesDatabaseTypeIds Dameng diff --git a/Plugins/DuckDBDriverPlugin/Info.plist b/Plugins/DuckDBDriverPlugin/Info.plist index 9954682bff..fd30d5aac1 100644 --- a/Plugins/DuckDBDriverPlugin/Info.plist +++ b/Plugins/DuckDBDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 26 + 27 diff --git a/Plugins/DynamoDBDriverPlugin/Info.plist b/Plugins/DynamoDBDriverPlugin/Info.plist index 9747423174..832b49a1ce 100644 --- a/Plugins/DynamoDBDriverPlugin/Info.plist +++ b/Plugins/DynamoDBDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 26 + 27 diff --git a/Plugins/ElasticsearchDriverPlugin/Info.plist b/Plugins/ElasticsearchDriverPlugin/Info.plist index 97d99a21be..31731eb0ce 100644 --- a/Plugins/ElasticsearchDriverPlugin/Info.plist +++ b/Plugins/ElasticsearchDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.53.0 TableProPluginKitVersion - 26 + 27 diff --git a/Plugins/EtcdDriverPlugin/Info.plist b/Plugins/EtcdDriverPlugin/Info.plist index 9747423174..832b49a1ce 100644 --- a/Plugins/EtcdDriverPlugin/Info.plist +++ b/Plugins/EtcdDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 26 + 27 diff --git a/Plugins/HTMLExportPlugin/Info.plist b/Plugins/HTMLExportPlugin/Info.plist index 0e74ce63e0..66625c5083 100644 --- a/Plugins/HTMLExportPlugin/Info.plist +++ b/Plugins/HTMLExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesExportFormatIds html diff --git a/Plugins/JSONExportPlugin/Info.plist b/Plugins/JSONExportPlugin/Info.plist index a32f0751e6..614d123511 100644 --- a/Plugins/JSONExportPlugin/Info.plist +++ b/Plugins/JSONExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesExportFormatIds json diff --git a/Plugins/JSONImportPlugin/Info.plist b/Plugins/JSONImportPlugin/Info.plist index 595fe71df8..5077345493 100644 --- a/Plugins/JSONImportPlugin/Info.plist +++ b/Plugins/JSONImportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesImportFormatIds json diff --git a/Plugins/KafkaDriverPlugin/Info.plist b/Plugins/KafkaDriverPlugin/Info.plist index be82099e32..79f552256f 100644 --- a/Plugins/KafkaDriverPlugin/Info.plist +++ b/Plugins/KafkaDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesDatabaseTypeIds Kafka diff --git a/Plugins/LibSQLDriverPlugin/Info.plist b/Plugins/LibSQLDriverPlugin/Info.plist index 9747423174..832b49a1ce 100644 --- a/Plugins/LibSQLDriverPlugin/Info.plist +++ b/Plugins/LibSQLDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 26 + 27 diff --git a/Plugins/MQLExportPlugin/Info.plist b/Plugins/MQLExportPlugin/Info.plist index 6e2ff052e2..c5d88098f7 100644 --- a/Plugins/MQLExportPlugin/Info.plist +++ b/Plugins/MQLExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesExportFormatIds mql diff --git a/Plugins/MSSQLDriverPlugin/Info.plist b/Plugins/MSSQLDriverPlugin/Info.plist index 9954682bff..fd30d5aac1 100644 --- a/Plugins/MSSQLDriverPlugin/Info.plist +++ b/Plugins/MSSQLDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 26 + 27 diff --git a/Plugins/MarkdownExportPlugin/Info.plist b/Plugins/MarkdownExportPlugin/Info.plist index e14571be83..11dd85dc4b 100644 --- a/Plugins/MarkdownExportPlugin/Info.plist +++ b/Plugins/MarkdownExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesExportFormatIds md diff --git a/Plugins/MongoDBDriverPlugin/Info.plist b/Plugins/MongoDBDriverPlugin/Info.plist index 9954682bff..fd30d5aac1 100644 --- a/Plugins/MongoDBDriverPlugin/Info.plist +++ b/Plugins/MongoDBDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 26 + 27 diff --git a/Plugins/MySQLDriverPlugin/Info.plist b/Plugins/MySQLDriverPlugin/Info.plist index 94c4002f25..1ed41cbaf3 100644 --- a/Plugins/MySQLDriverPlugin/Info.plist +++ b/Plugins/MySQLDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesDatabaseTypeIds MySQL diff --git a/Plugins/OracleDriverPlugin/Info.plist b/Plugins/OracleDriverPlugin/Info.plist index 9954682bff..fd30d5aac1 100644 --- a/Plugins/OracleDriverPlugin/Info.plist +++ b/Plugins/OracleDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 26 + 27 diff --git a/Plugins/ParquetExportPlugin/Info.plist b/Plugins/ParquetExportPlugin/Info.plist index a3dbea458f..1ae4446c1a 100644 --- a/Plugins/ParquetExportPlugin/Info.plist +++ b/Plugins/ParquetExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesExportFormatIds parquet diff --git a/Plugins/PostgreSQLDriverPlugin/Info.plist b/Plugins/PostgreSQLDriverPlugin/Info.plist index 1a62532486..fd4040f800 100644 --- a/Plugins/PostgreSQLDriverPlugin/Info.plist +++ b/Plugins/PostgreSQLDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesDatabaseTypeIds PostgreSQL diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQConnectionLoss.swift b/Plugins/PostgreSQLDriverPlugin/LibPQConnectionLoss.swift new file mode 100644 index 0000000000..2d655bf50e --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/LibPQConnectionLoss.swift @@ -0,0 +1,86 @@ +// +// LibPQConnectionLoss.swift +// PostgreSQLDriverPlugin +// + +import Foundation +import TableProPluginKit + +enum LibPQTransactionState: Sendable, Equatable { + case idle + case active + case inTransaction + case inError + case unknown + + var mayHoldTransaction: Bool { + self != .idle + } +} + +enum LibPQServerMessage { + private static let sessionEndingSeverities: Set = ["FATAL", "PANIC"] + private static let sessionEndingClasses: Set = ["08", "57"] + + static func endsSession(severity: String?, sqlState: String?) -> Bool { + if let severity { + return sessionEndingSeverities.contains(severity) + } + guard let sqlState, sqlState.count == 5 else { return false } + return sessionEndingClasses.contains(sqlState.prefix(2)) + } +} + +enum LibPQConnectionLoss: Sendable, Equatable { + case beforeSending(transactionMayBeOpen: Bool) + case afterSending + + init(sent: Bool, recordedState: LibPQTransactionState) { + self = sent ? .afterSending : .beforeSending(transactionMayBeOpen: recordedState.mayHoldTransaction) + } +} + +struct LibPQConnectionLostError: PluginDriverError { + let loss: LibPQConnectionLoss + let underlying: LibPQPluginError + + /// The server's own text stays in front of the explanation. Everything that reads an error + /// reads this string: `DatabaseManager.isAuthenticationFailure` matches "authentication + /// failed" in it, because PostgreSQL sends `28P01` rather than the `28000` its SQLSTATE arm + /// looks for, and `DatabaseWriteRejectionDiagnosis` quotes it back to the user. + var pluginErrorMessage: String { + let parts = [underlying.message, explanation].filter { !$0.isEmpty } + return parts.joined(separator: " ") + } + + private var explanation: String { + switch loss { + case .beforeSending(transactionMayBeOpen: false): + return String( + localized: "The connection to the server was closed before the statement was sent. It was not run." + ) + case .beforeSending(transactionMayBeOpen: true): + return String( + localized: """ + The connection to the server was closed before the statement was sent. It was not run, and \ + any open transaction was rolled back. + """ + ) + case .afterSending: + return String( + localized: """ + Lost the connection to the server while the statement was running. It may or may not have \ + completed. If a transaction was open, it was rolled back unless this statement committed it. + """ + ) + } + } + + var pluginSqlState: String? { + underlying.sqlState + } + + var pluginErrorDetail: String? { + underlying.detail + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift b/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift index 038784fd62..f7c7a527d1 100644 --- a/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift +++ b/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift @@ -13,7 +13,13 @@ final class LibPQDriverCore: @unchecked Sendable { private let config: DriverConnectionConfig private let schemaFallbackQueries: [String] private let singleConnectionMode: Bool - private var libpqConnection: LibPQPluginConnection? + private let connectionLock = NSLock() + private var _libpqConnection: LibPQPluginConnection? + private var _lostConnection = false + + private var libpqConnection: LibPQPluginConnection? { + connectionLock.withLock { _libpqConnection } + } var currentSchema: String = "public" private var selectedSchema: String? @@ -26,6 +32,17 @@ final class LibPQDriverCore: @unchecked Sendable { var stageReporter: ConnectionStageReporter? var serverVersion: String? { libpqConnection?.serverVersion() } + /// Latched, because `disconnect()` drops the connection object that knew it and the app asks + /// this question of the driver it is still holding: the pool closes a lost entry, and the + /// before-use check pings one, both after something disconnected it. + var hasLostConnection: Bool { + connectionLock.withLock { + if _libpqConnection?.hasLostConnection == true { + _lostConnection = true + } + return _lostConnection + } + } var serverVersionNumber: Int32 { libpqConnection?.serverVersionNumber() ?? 0 } var standardConformingStrings: Bool { libpqConnection?.standardConformingStrings ?? true } var isInsideTransactionBlock: Bool { libpqConnection?.isInsideTransactionBlock ?? false } @@ -55,7 +72,10 @@ final class LibPQDriverCore: @unchecked Sendable { ) try await pqConn.connect(reportingStage: stageReporter ?? { _ in }) - libpqConnection = pqConn + connectionLock.withLock { + _libpqConnection = pqConn + _lostConnection = false + } switch await probeSchema(pqConn, query: PostgreSQLSchemaQueries.currentSchema) { case .schema(let schema): @@ -98,18 +118,16 @@ final class LibPQDriverCore: @unchecked Sendable { } func disconnect() { - libpqConnection?.disconnect() - libpqConnection = nil + let pqConn = connectionLock.withLock { () -> LibPQPluginConnection? in + defer { _libpqConnection = nil } + if _libpqConnection?.hasLostConnection == true { + _lostConnection = true + } + return _libpqConnection + } + pqConn?.disconnect() } - /// Non-reconnecting on purpose, which is what makes the answer mean anything. - /// - /// `execute` recovers a dropped connection privately, and that recovery restores none of the - /// session state the app put there: the startup commands, the query timeout, the database and - /// the schema all belong to `DatabaseManager.reconnectDriver`. A ping that healed itself that - /// way would report success into a server session reset behind the user's back, and the next - /// statement would run without the role, search path or time zone their startup SQL set. - /// Failing instead routes recovery through the manager, which restores all of it. func ping() async throws { guard let pqConn = libpqConnection else { throw LibPQPluginError.notConnected @@ -120,13 +138,21 @@ final class LibPQDriverCore: @unchecked Sendable { // MARK: - Query Execution func execute(query: String) async throws -> PluginQueryResult { - try await executeWithReconnect(query: query, isRetry: false) + let pqConn = try connection() + let startTime = Date() + let result = try await pqConn.executeQuery(query) + return PluginQueryResult( + columns: result.columns, + columnTypeNames: result.columnTypeNames, + rows: result.rows, + rowsAffected: result.affectedRows, + executionTime: Date().timeIntervalSince(startTime), + isTruncated: result.isTruncated + ) } func executeParameterized(query: String, parameters: [PluginCellValue]) async throws -> PluginQueryResult { - guard let pqConn = libpqConnection else { - throw LibPQPluginError.notConnected - } + let pqConn = try connection() let startTime = Date() let result = try await pqConn.executeParameterizedQuery(query, parameters: parameters) return PluginQueryResult( @@ -140,39 +166,20 @@ final class LibPQDriverCore: @unchecked Sendable { } func executeBoundedQuery(query: String, rowCap: Int) async throws -> PluginQueryResult? { - try await boundedQueryWithReconnect(query: query, rowCap: rowCap, isRetry: false) - } - - /// A bounded read only ever runs a statement the host classified as a read, so retrying it after - /// a dropped connection is safe, the same way the buffered path retries. - private func boundedQueryWithReconnect( - query: String, - rowCap: Int, - isRetry: Bool - ) async throws -> PluginQueryResult { - guard let pqConn = libpqConnection else { - throw LibPQPluginError.notConnected - } - + let pqConn = try connection() let startTime = Date() - - do { - let result = try await pqConn.boundedQuery(query, rowCap: rowCap) - return PluginQueryResult( - columns: result.columns, - columnTypeNames: result.columnTypeNames, - rows: result.rows, - rowsAffected: result.affectedRows, - timing: PluginQueryTiming( - total: Date().timeIntervalSince(startTime), - firstRow: result.firstRowTime - ), - isTruncated: result.isTruncated - ) - } catch let error as NSError where !isRetry && Self.isConnectionLostError(error) { - try await reconnect() - return try await boundedQueryWithReconnect(query: query, rowCap: rowCap, isRetry: true) - } + let result = try await pqConn.boundedQuery(query, rowCap: rowCap) + return PluginQueryResult( + columns: result.columns, + columnTypeNames: result.columnTypeNames, + rows: result.rows, + rowsAffected: result.affectedRows, + timing: PluginQueryTiming( + total: Date().timeIntervalSince(startTime), + firstRow: result.firstRowTime + ), + isTruncated: result.isTruncated + ) } func streamRows(query: String) -> AsyncThrowingStream { @@ -199,44 +206,11 @@ final class LibPQDriverCore: @unchecked Sendable { _ = try await execute(query: "SET statement_timeout = '\(ms)'") } - // MARK: - Reconnect - - private func executeWithReconnect(query: String, isRetry: Bool) async throws -> PluginQueryResult { + private func connection() throws -> LibPQPluginConnection { guard let pqConn = libpqConnection else { throw LibPQPluginError.notConnected } - - let startTime = Date() - - do { - let result = try await pqConn.executeQuery(query) - return PluginQueryResult( - columns: result.columns, - columnTypeNames: result.columnTypeNames, - rows: result.rows, - rowsAffected: result.affectedRows, - executionTime: Date().timeIntervalSince(startTime), - isTruncated: result.isTruncated - ) - } catch let error as NSError where !isRetry && Self.isConnectionLostError(error) { - try await reconnect() - return try await executeWithReconnect(query: query, isRetry: true) - } - } - - private func reconnect() async throws { - libpqConnection?.disconnect() - libpqConnection = nil - try await connect() - } - - private static func isConnectionLostError(_ error: NSError) -> Bool { - let errorMessage = error.localizedDescription.lowercased() - return errorMessage.contains("connection") && - (errorMessage.contains("lost") || - errorMessage.contains("closed") || - errorMessage.contains("no connection") || - errorMessage.contains("could not send")) + return pqConn } } @@ -333,6 +307,7 @@ extension LibPQBackedDriver { } var serverVersion: String? { core.serverVersion } + var hasLostConnection: Bool { core.hasLostConnection } var parameterStyle: ParameterStyle { .dollar } func escapeStringLiteral(_ value: String) -> String { diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift b/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift index eb09b9abb2..7e334fdbbd 100644 --- a/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift +++ b/Plugins/PostgreSQLDriverPlugin/LibPQPluginConnection.swift @@ -119,6 +119,9 @@ final class LibPQPluginConnection: @unchecked Sendable { private var _isConnectCancelled: Bool = false private var _postgisOidMap: [UInt32: PostGISType] = [:] private var _catalogTypeNames: [UInt32: String] = [:] + private var _lastTransactionState: LibPQTransactionState = .idle + private var _hasLostConnection = false + private var serverMessages: Unmanaged? private var _standardConformingStrings = true var isConnected: Bool { @@ -166,11 +169,14 @@ final class LibPQPluginConnection: @unchecked Sendable { deinit { let handle = conn + let sink = serverMessages let cleanupQueue = queue conn = nil + serverMessages = nil if let handle = handle { cleanupQueue.async { PQfinish(handle) + sink?.release() } } } @@ -220,9 +226,13 @@ final class LibPQPluginConnection: @unchecked Sendable { try pollUntilConnected(connection, reportingStage: report) configureEstablishedConnection(connection) + let sink = LibPQServerMessageSink.install(on: connection) stateLock.lock() conn = connection + serverMessages = sink + _lastTransactionState = .idle + _hasLostConnection = false _isConnected = true stateLock.unlock() adopted = true @@ -396,7 +406,9 @@ final class LibPQPluginConnection: @unchecked Sendable { _isConnected = false _isConnectCancelled = true let handle = conn + let sink = serverMessages conn = nil + serverMessages = nil stateLock.unlock() _cachedServerVersion = nil @@ -405,6 +417,7 @@ final class LibPQPluginConnection: @unchecked Sendable { if let handle { queue.async { PQfinish(handle) + sink?.release() } } } @@ -603,14 +616,17 @@ final class LibPQPluginConnection: @unchecked Sendable { defer { refreshStandardConformingStrings(from: conn) } let cancelsOutput = cancelsAbandonedOutput(conn) + if let ended = sessionEndedBeforeSending(conn) { throw ended } + let localQuery = String(query) let result: OpaquePointer? = localQuery.withCString { queryPtr in PQexec(conn, queryPtr) } guard let result = result else { - throw getError(from: conn) + throw lostConnection(getError(from: conn), on: conn, sent: true) } + recordTransactionState(of: conn) let status = PQresultStatus(result) @@ -642,7 +658,7 @@ final class LibPQPluginConnection: @unchecked Sendable { let error = getResultError(from: result) PQclear(result) if cancellationGate.isCancelled(generation) { throw CancellationError() } - throw error + throw lostConnection(error, on: conn, sent: true) } } @@ -677,12 +693,15 @@ final class LibPQPluginConnection: @unchecked Sendable { let cancelsOutput = cancelsAbandonedOutput(conn) let suppressCancel = !cancelsOutput _ = finishPendingResults(conn, cancellingOutput: cancelsOutput) + if let ended = sessionEndedBeforeSending(conn) { throw ended } let localQuery = String(query) let sendOk = localQuery.withCString { queryPtr in PQsendQuery(conn, queryPtr) } - guard sendOk != 0 else { throw getError(from: conn) } + guard sendOk != 0 else { + throw lostConnection(getError(from: conn), on: conn, sent: false) + } guard PQsetSingleRowMode(conn) != 0 else { _ = cancelAndDrain(conn, suppressCancel: suppressCancel) @@ -697,6 +716,7 @@ final class LibPQPluginConnection: @unchecked Sendable { var truncated = false var pendingError: Error? var firstRowTime: TimeInterval? + var failedStatement: LibPQPluginError? while let result = PQgetResult(conn) { let status = PQresultStatus(result) @@ -749,7 +769,7 @@ final class LibPQPluginConnection: @unchecked Sendable { break } - pendingError = getResultError(from: result) + failedStatement = getResultError(from: result) PQclear(result) break } @@ -757,7 +777,12 @@ final class LibPQPluginConnection: @unchecked Sendable { let outcome = truncated ? cancelAndDrain(conn, suppressCancel: suppressCancel) : finishPendingResults(conn, cancellingOutput: cancelsOutput) + recordTransactionState(of: conn) + if let failedStatement { + if cancellationGate.isCancelled(generation) { throw CancellationError() } + throw lostConnection(failedStatement, on: conn, sent: true) + } if let pendingError { if cancellationGate.isCancelled(generation) { throw CancellationError() } throw pendingError @@ -840,6 +865,8 @@ final class LibPQPluginConnection: @unchecked Sendable { } } + if let ended = sessionEndedBeforeSending(conn) { throw ended } + let localQuery = String(query) let result: OpaquePointer? = localQuery.withCString { queryPtr in paramLengths.withUnsafeBufferPointer { lengthsBuf in @@ -859,8 +886,9 @@ final class LibPQPluginConnection: @unchecked Sendable { } guard let result = result else { - throw getError(from: conn) + throw lostConnection(getError(from: conn), on: conn, sent: true) } + recordTransactionState(of: conn) let status = PQresultStatus(result) @@ -892,7 +920,7 @@ final class LibPQPluginConnection: @unchecked Sendable { let error = getResultError(from: result) PQclear(result) if cancellationGate.isCancelled(generation) { throw CancellationError() } - throw error + throw lostConnection(error, on: conn, sent: true) } } @@ -935,6 +963,7 @@ final class LibPQPluginConnection: @unchecked Sendable { logger.fault( "libpq stayed in \(String(describing: stuck.direction), privacy: .public); dropping the connection" ) + stateLock.withLock { _hasLostConnection = true } disconnect() return outcome } @@ -986,13 +1015,17 @@ final class LibPQPluginConnection: @unchecked Sendable { let cancelsOutput = cancelsAbandonedOutput(conn) let suppressCancel = !cancelsOutput _ = finishPendingResults(conn, cancellingOutput: cancelsOutput) + if let ended = sessionEndedBeforeSending(conn) { + continuation.finish(throwing: ended) + return + } let sendOk = queryToRun.withCString { queryPtr in PQsendQuery(conn, queryPtr) } if sendOk == 0 { - continuation.finish(throwing: getError(from: conn)) + continuation.finish(throwing: lostConnection(getError(from: conn), on: conn, sent: false)) return } @@ -1085,11 +1118,12 @@ final class LibPQPluginConnection: @unchecked Sendable { let error = getResultError(from: result) PQclear(result) _ = finishPendingResults(conn, cancellingOutput: cancelsOutput) + recordTransactionState(of: conn) if cancellationGate.isCancelled(generation) { continuation.finish(throwing: CancellationError()) return } - continuation.finish(throwing: error) + continuation.finish(throwing: lostConnection(error, on: conn, sent: true)) return } } @@ -1099,6 +1133,7 @@ final class LibPQPluginConnection: @unchecked Sendable { } let outcome = finishPendingResults(conn, cancellingOutput: cancelsOutput) + recordTransactionState(of: conn) /// The header went out with the first row, so this stream keeps what it said; /// the lookup is for the results that follow. let missing = unresolvedOids(in: columnOids) @@ -1373,6 +1408,70 @@ final class LibPQPluginConnection: @unchecked Sendable { // MARK: - Private Helpers + var hasLostConnection: Bool { + stateLock.withLock { _hasLostConnection } + } + + private var lastTransactionState: LibPQTransactionState { + stateLock.withLock { _lastTransactionState } + } + + private var sessionEndingMessage: LibPQPluginError? { + stateLock.withLock { serverMessages }?.takeUnretainedValue().sessionEndingMessage + } + + private func recordTransactionState(of conn: OpaquePointer) { + guard PQstatus(conn) == CONNECTION_OK else { return } + let state = Self.transactionState(PQtransactionStatus(conn)) + stateLock.withLock { _lastTransactionState = state } + } + + private func sessionEndedBeforeSending(_ conn: OpaquePointer) -> LibPQConnectionLostError? { + recordTransactionState(of: conn) + /// All three calls earn their place, measured against a terminated backend on 9.1.24 and + /// 17.11. One `PQconsumeInput` leaves the status `CONNECTION_OK`, so a single read never + /// sees the loss; the second one turns it `CONNECTION_BAD`. `PQisBusy` never moves the + /// status, but it is what parses the buffered message: without it every closed-session + /// case loses the server's FATAL and its SQLSTATE and reports libpq's own "server closed + /// the connection unexpectedly" instead. + if PQstatus(conn) == CONNECTION_OK { + _ = PQconsumeInput(conn) + _ = PQisBusy(conn) + _ = PQconsumeInput(conn) + } + guard PQstatus(conn) == CONNECTION_BAD else { + stateLock.withLock { serverMessages }?.takeUnretainedValue().clearIfHealthy() + return nil + } + let serverMessage = sessionEndingMessage + let loss = LibPQConnectionLoss(sent: false, recordedState: lastTransactionState) + stateLock.withLock { _hasLostConnection = true } + logger.info("Server closed the session before a statement was sent") + return LibPQConnectionLostError(loss: loss, underlying: serverMessage ?? getError(from: conn)) + } + + private func lostConnection(_ error: LibPQPluginError, on conn: OpaquePointer, sent: Bool) -> Error { + guard PQstatus(conn) == CONNECTION_BAD else { return error } + let loss = LibPQConnectionLoss(sent: sent, recordedState: lastTransactionState) + stateLock.withLock { + if sent { _lastTransactionState = .unknown } + _hasLostConnection = true + } + let phase = sent ? "while a statement was running" : "while sending a statement" + logger.warning("Connection lost \(phase, privacy: .public)") + return LibPQConnectionLostError(loss: loss, underlying: sessionEndingMessage ?? error) + } + + private static func transactionState(_ status: PGTransactionStatusType) -> LibPQTransactionState { + switch status { + case PQTRANS_IDLE: return .idle + case PQTRANS_ACTIVE: return .active + case PQTRANS_INTRANS: return .inTransaction + case PQTRANS_INERROR: return .inError + default: return .unknown + } + } + private func getError(from conn: OpaquePointer) -> LibPQPluginError { var message = "Unknown error" if let msgPtr = PQerrorMessage(conn) { diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQServerMessageSink.swift b/Plugins/PostgreSQLDriverPlugin/LibPQServerMessageSink.swift new file mode 100644 index 0000000000..4f93b98886 --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/LibPQServerMessageSink.swift @@ -0,0 +1,58 @@ +// +// LibPQServerMessageSink.swift +// PostgreSQLDriverPlugin +// + +import CLibPQ +import Foundation + +final class LibPQServerMessageSink: @unchecked Sendable { + private static let severityField = Int32(UInt8(ascii: "V")) + + private let lock = NSLock() + private var sessionEnding: LibPQPluginError? + private var forwardedReceiver: PQnoticeReceiver? + + static func install(on connection: OpaquePointer) -> Unmanaged { + let retained = Unmanaged.passRetained(LibPQServerMessageSink()) + let previous = PQsetNoticeReceiver(connection, libpqServerMessageReceiver, retained.toOpaque()) + retained.takeUnretainedValue().lock.withLock { + retained.takeUnretainedValue().forwardedReceiver = previous + } + return retained + } + + var sessionEndingMessage: LibPQPluginError? { + lock.withLock { sessionEnding } + } + + /// Only ever called for a connection libpq still reports as `CONNECTION_OK`. A server before + /// 9.6 sends no non-localized severity, so a `RAISE WARNING ... ERRCODE '08006'` on a healthy + /// session reaches `receive` looking exactly like the real thing; a session that ended cannot + /// be healthy, so the healthy case is the one that must not keep the message. + func clearIfHealthy() { + lock.withLock { sessionEnding = nil } + } + + fileprivate func receive(_ result: OpaquePointer) { + let message = PQresultErrorMessage(result).map { + String(cString: $0).trimmingCharacters(in: .whitespacesAndNewlines) + } ?? "" + let received = LibPQPluginError(message: message) { field in + PQresultErrorField(result, field).map { String(cString: $0) } + } + let severity = PQresultErrorField(result, Self.severityField).map { String(cString: $0) } + let forward = lock.withLock { () -> PQnoticeReceiver? in + if LibPQServerMessage.endsSession(severity: severity, sqlState: received.sqlState) { + sessionEnding = received + } + return forwardedReceiver + } + forward?(nil, result) + } +} + +private func libpqServerMessageReceiver(_ context: UnsafeMutableRawPointer?, _ result: OpaquePointer?) { + guard let context, let result else { return } + Unmanaged.fromOpaque(context).takeUnretainedValue().receive(result) +} diff --git a/Plugins/RedisDriverPlugin/Info.plist b/Plugins/RedisDriverPlugin/Info.plist index 4a492e698e..f02bf31c1c 100644 --- a/Plugins/RedisDriverPlugin/Info.plist +++ b/Plugins/RedisDriverPlugin/Info.plist @@ -21,7 +21,7 @@ NSPrincipalClass $(PRODUCT_MODULE_NAME).RedisPlugin TableProPluginKitVersion - 26 + 27 TableProProvidesDatabaseTypeIds Redis diff --git a/Plugins/SQLExportPlugin/Info.plist b/Plugins/SQLExportPlugin/Info.plist index 68e02581a9..abd1a7dfdb 100644 --- a/Plugins/SQLExportPlugin/Info.plist +++ b/Plugins/SQLExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesExportFormatIds sql diff --git a/Plugins/SQLImportPlugin/Info.plist b/Plugins/SQLImportPlugin/Info.plist index 09e7f15ffc..6d943056e4 100644 --- a/Plugins/SQLImportPlugin/Info.plist +++ b/Plugins/SQLImportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesImportFormatIds sql diff --git a/Plugins/SQLiteDriverPlugin/Info.plist b/Plugins/SQLiteDriverPlugin/Info.plist index b925ecd541..abf2a2ff1b 100644 --- a/Plugins/SQLiteDriverPlugin/Info.plist +++ b/Plugins/SQLiteDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesDatabaseTypeIds SQLite diff --git a/Plugins/SnowflakeDriverPlugin/Info.plist b/Plugins/SnowflakeDriverPlugin/Info.plist index c329f1bc3b..285dd606a8 100644 --- a/Plugins/SnowflakeDriverPlugin/Info.plist +++ b/Plugins/SnowflakeDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.48.0 TableProPluginKitVersion - 26 + 27 diff --git a/Plugins/SpannerDriverPlugin/Info.plist b/Plugins/SpannerDriverPlugin/Info.plist index 8085ee8319..cd7bdb6246 100644 --- a/Plugins/SpannerDriverPlugin/Info.plist +++ b/Plugins/SpannerDriverPlugin/Info.plist @@ -5,7 +5,7 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 26 + 27 TableProProvidesDatabaseTypeIds Spanner diff --git a/Plugins/SurrealDBDriverPlugin/Info.plist b/Plugins/SurrealDBDriverPlugin/Info.plist index c01f11f50c..29d097761f 100644 --- a/Plugins/SurrealDBDriverPlugin/Info.plist +++ b/Plugins/SurrealDBDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesDatabaseTypeIds SurrealDB diff --git a/Plugins/TableProPluginKit/PluginDatabaseDriver.swift b/Plugins/TableProPluginKit/PluginDatabaseDriver.swift index a386a7c258..f82eab21ec 100644 --- a/Plugins/TableProPluginKit/PluginDatabaseDriver.swift +++ b/Plugins/TableProPluginKit/PluginDatabaseDriver.swift @@ -177,6 +177,7 @@ public protocol PluginDatabaseDriver: AnyObject, Sendable { /// it and say so. Throwing is reserved for a release that was attempted and failed. func releaseIdleResource() async throws -> PluginResourceRelease var serverVersion: String? { get } + var hasLostConnection: Bool { get } var parameterStyle: ParameterStyle { get } func resolveQueryCompletionProfile( databaseTypeId: String, @@ -559,6 +560,8 @@ public extension PluginDatabaseDriver { var serverVersion: String? { nil } + var hasLostConnection: Bool { false } + var parameterStyle: ParameterStyle { .questionMark } func resolveQueryCompletionProfile( diff --git a/Plugins/TeradataDriverPlugin/Info.plist b/Plugins/TeradataDriverPlugin/Info.plist index 9954682bff..fd30d5aac1 100644 --- a/Plugins/TeradataDriverPlugin/Info.plist +++ b/Plugins/TeradataDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 26 + 27 diff --git a/Plugins/TrinoDriverPlugin/Info.plist b/Plugins/TrinoDriverPlugin/Info.plist index 9954682bff..fd30d5aac1 100644 --- a/Plugins/TrinoDriverPlugin/Info.plist +++ b/Plugins/TrinoDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 26 + 27 diff --git a/Plugins/TypesenseDriverPlugin/Info.plist b/Plugins/TypesenseDriverPlugin/Info.plist index 693b19d340..6be544d69e 100644 --- a/Plugins/TypesenseDriverPlugin/Info.plist +++ b/Plugins/TypesenseDriverPlugin/Info.plist @@ -5,7 +5,7 @@ TableProMinAppVersion 0.73.0 TableProPluginKitVersion - 26 + 27 TableProProvidesDatabaseTypeIds Typesense diff --git a/Plugins/XLSXExportPlugin/Info.plist b/Plugins/XLSXExportPlugin/Info.plist index c598c94a4e..af15eb0527 100644 --- a/Plugins/XLSXExportPlugin/Info.plist +++ b/Plugins/XLSXExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesExportFormatIds xlsx diff --git a/Plugins/XLSXImportPlugin/Info.plist b/Plugins/XLSXImportPlugin/Info.plist index 0777cf21ff..7ecc3428a5 100644 --- a/Plugins/XLSXImportPlugin/Info.plist +++ b/Plugins/XLSXImportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesImportFormatIds xlsx diff --git a/Plugins/XMLExportPlugin/Info.plist b/Plugins/XMLExportPlugin/Info.plist index 38b44294d9..62d5b9037f 100644 --- a/Plugins/XMLExportPlugin/Info.plist +++ b/Plugins/XMLExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 26 + 27 TableProProvidesExportFormatIds xml diff --git a/TablePro/Core/Database/DatabaseDriver.swift b/TablePro/Core/Database/DatabaseDriver.swift index bb06d0cdcf..376d4f1545 100644 --- a/TablePro/Core/Database/DatabaseDriver.swift +++ b/TablePro/Core/Database/DatabaseDriver.swift @@ -19,6 +19,8 @@ protocol DatabaseDriver: AnyObject, Sendable { /// Current connection status var status: ConnectionStatus { get } + var hasLostConnection: Bool { get } + /// Server version string (e.g., "8.0.35" for MySQL) /// Optional - not all drivers may implement this var serverVersion: String? { get } @@ -621,6 +623,8 @@ extension DatabaseDriver { var supportsTransactions: Bool { true } + var hasLostConnection: Bool { false } + func cancelQuery() throws { } diff --git a/TablePro/Core/Database/DatabaseManager+Verification.swift b/TablePro/Core/Database/DatabaseManager+Verification.swift index ff3b722db4..e33c3ef870 100644 --- a/TablePro/Core/Database/DatabaseManager+Verification.swift +++ b/TablePro/Core/Database/DatabaseManager+Verification.swift @@ -71,7 +71,13 @@ extension DatabaseManager { /// No record means no answer, which is a reason to ask rather than a reason to assume. /// That is also what makes waking from sleep work: it throws every answer away, and the /// next thing anyone does pays for one check. - if let last = lastVerifiedAt[connectionId], ConnectionHealthCheck.isFresh(last) { return } + /// A driver that reported a lost connection has already answered the question a ping + /// would ask, so its stamp says nothing about the socket it is holding now. + if let last = lastVerifiedAt[connectionId], + ConnectionHealthCheck.isFresh(last), + !driver.hasLostConnection { + return + } try? await verificationDedup.execute(key: connectionId) { await self.runVerification(connectionId, driver: driver) diff --git a/TablePro/Core/Plugins/PluginDriverAdapter.swift b/TablePro/Core/Plugins/PluginDriverAdapter.swift index 4bd0fd4be6..b40f7da280 100644 --- a/TablePro/Core/Plugins/PluginDriverAdapter.swift +++ b/TablePro/Core/Plugins/PluginDriverAdapter.swift @@ -23,6 +23,10 @@ final class PluginDriverAdapter: DatabaseDriver, SchemaSwitchable, DatabaseRepor state.withLock { $0.status } } + var hasLostConnection: Bool { + pluginDriver.hasLostConnection + } + var serverVersion: String? { pluginDriver.serverVersion } var parameterStyle: ParameterStyle { pluginDriver.parameterStyle } diff --git a/TablePro/Core/Plugins/PluginManager.swift b/TablePro/Core/Plugins/PluginManager.swift index a883efcaa7..e7624f75be 100644 --- a/TablePro/Core/Plugins/PluginManager.swift +++ b/TablePro/Core/Plugins/PluginManager.swift @@ -41,7 +41,7 @@ final class PluginManager { /// rebuilt CassandraDriver for the v20 requirements it implements none of. Left at 20, such a /// plugin passes `validateBundleVersions` in a shipped v20 app and then fails /// `Bundle.loadAndReturnError`; at 21 that app refuses it and says to update. - nonisolated static let currentPluginKitVersion = 26 + nonisolated static let currentPluginKitVersion = 27 /// Still 19, so every plugin already published for the previous release keeps loading. nonisolated static let minimumCompatiblePluginKitVersion = 19 diff --git a/TablePro/Core/Services/Query/MetadataConnectionPool.swift b/TablePro/Core/Services/Query/MetadataConnectionPool.swift index 575b8c220b..67997c4015 100644 --- a/TablePro/Core/Services/Query/MetadataConnectionPool.swift +++ b/TablePro/Core/Services/Query/MetadataConnectionPool.swift @@ -146,6 +146,18 @@ final class MetadataConnectionPool { internal var hasSweeper: Bool { sweeper != nil } + + /// The sweeper is started by opening a pooled connection, which a test with no plugin cannot + /// do, so a test that wants to watch it stop has to start it the way `openEntry` does. + internal func startSweeperForTesting() { + startSweeperIfNeeded() + } + + /// A pool of its own, so a test that moves the clock or empties the pool cannot close the + /// entries another test injected into the shared one. + internal static func isolatedForTesting() -> MetadataConnectionPool { + MetadataConnectionPool() + } #endif private func releaseEntry(_ entry: Entry) { @@ -173,7 +185,7 @@ final class MetadataConnectionPool { /// closed. The old entry is closed rather than left behind: overwriting `entries[key]` /// with a fresh one used to leak the driver it replaced. if let entry = entries[key] { - if entry.driver.status == .connected, !Self.isStale(entry.lastUsed) { + if entry.driver.status == .connected, !entry.driver.hasLostConnection, !Self.isStale(entry.lastUsed) { return entry } closeOrDeferEntry(forKey: key) diff --git a/TableProTests/Core/Autocomplete/SQLSchemaProviderTests.swift b/TableProTests/Core/Autocomplete/SQLSchemaProviderTests.swift index 64cdfec3bf..a9a4b10742 100644 --- a/TableProTests/Core/Autocomplete/SQLSchemaProviderTests.swift +++ b/TableProTests/Core/Autocomplete/SQLSchemaProviderTests.swift @@ -15,6 +15,7 @@ import Testing final class MockDatabaseDriver: DatabaseDriver, SchemaSwitchable, @unchecked Sendable { let connection: DatabaseConnection var status: ConnectionStatus = .connected + var hasLostConnection = false var serverVersion: String? { nil } var currentSchema: String? diff --git a/TableProTests/Core/Database/ConnectionVerificationTests.swift b/TableProTests/Core/Database/ConnectionVerificationTests.swift index 60c518a1be..8458c8c027 100644 --- a/TableProTests/Core/Database/ConnectionVerificationTests.swift +++ b/TableProTests/Core/Database/ConnectionVerificationTests.swift @@ -47,6 +47,19 @@ struct ConnectionVerificationTests { await cleanUp(connection.id) } + @Test("a driver that reported a lost connection is checked even though it answered recently") + func lostDriverIgnoresTheFreshStamp() async { + let driver = MockDatabaseDriver() + driver.hasLostConnection = true + let connection = makeSession(driver: driver) + DatabaseManager.shared.markSessionVerified(connection.id) + + await DatabaseManager.shared.verifyBeforeUse(connection.id) + + #expect(driver.pingCallCount == 1) + await cleanUp(connection.id) + } + @Test("a connection that has been silent too long is checked once") func staleConnectionIsPingedOnce() async { let driver = MockDatabaseDriver() diff --git a/TableProTests/Core/Database/LostConnectionReportingTests.swift b/TableProTests/Core/Database/LostConnectionReportingTests.swift new file mode 100644 index 0000000000..ba532338b1 --- /dev/null +++ b/TableProTests/Core/Database/LostConnectionReportingTests.swift @@ -0,0 +1,59 @@ +// +// LostConnectionReportingTests.swift +// TableProTests +// + +import Foundation +@testable import TablePro +import TableProPluginKit +import Testing + +@Suite("Plugin driver adapter and a lost connection") +struct PluginDriverAdapterLostConnectionTests { + @Test("the adapter forwards the driver's lost connection and leaves its own status alone") + func forwardsTheFactWithoutRewritingStatus() async throws { + let plugin = FakeMSSQLPluginDriver() + let adapter = PluginDriverAdapter(connection: TestFixtures.makeConnection(), pluginDriver: plugin) + try await adapter.connect() + + plugin.hasLostConnection = true + + #expect(adapter.hasLostConnection) + #expect(adapter.status == .connected) + } +} + +@Suite("Metadata pool and a lost connection", .serialized) +@MainActor +struct MetadataConnectionPoolLostEntryTests { + /// The shared pool on purpose: this is the one production uses, and opening a real entry on it + /// is what starts its sweeper. + @Test("a pooled driver that reported a lost connection is replaced instead of reused") + func lostEntryIsRebuilt() async throws { + FakeMSSQLPluginRegistration.registerIfNeeded() + var connection = TestFixtures.makeConnection(name: "Prod") + connection.type = DatabaseType(rawValue: FakeMSSQLPlugin.databaseTypeId) + var session = ConnectionSession(connection: connection) + session.status = .connected + session.driver = MockDatabaseDriver(connection: connection) + DatabaseManager.shared.injectSession(session, for: connection.id) + let pool = MetadataConnectionPool.shared + defer { + pool.closeAll(connectionId: connection.id) + DatabaseManager.shared.removeSession(for: connection.id) + } + + let scope = DatabaseScope(connectionId: connection.id, database: connection.database, schema: nil) + let plugin = FakeMSSQLPluginDriver() + let lost = PluginDriverAdapter(connection: connection, pluginDriver: plugin) + try await lost.connect() + pool.injectEntry(lost, scope: scope) + plugin.hasLostConnection = true + + let reused = try await pool.withDriver(scope: scope) { driver in driver === lost } + + #expect(!reused) + #expect(plugin.disconnectCallCount == 1) + #expect(pool.hasSweeper) + } +} diff --git a/TableProTests/Core/Services/Query/MetadataConnectionPoolTests.swift b/TableProTests/Core/Services/Query/MetadataConnectionPoolTests.swift index 50a80029fa..ca6a434c27 100644 --- a/TableProTests/Core/Services/Query/MetadataConnectionPoolTests.swift +++ b/TableProTests/Core/Services/Query/MetadataConnectionPoolTests.swift @@ -162,7 +162,7 @@ struct MetadataConnectionPoolIdleEvictionTests { func sweepClosesIdleEntries() { let connectionId = UUID() let driver = MockDatabaseDriver() - let pool = MetadataConnectionPool.shared + let pool = MetadataConnectionPool.isolatedForTesting() defer { pool.closeAll(connectionId: connectionId) } pool.injectEntry(driver, scope: scope(connectionId, database: "shop")) @@ -176,7 +176,7 @@ struct MetadataConnectionPoolIdleEvictionTests { func sweepSparesRecentEntries() { let connectionId = UUID() let driver = MockDatabaseDriver() - let pool = MetadataConnectionPool.shared + let pool = MetadataConnectionPool.isolatedForTesting() defer { pool.closeAll(connectionId: connectionId) } pool.injectEntry(driver, scope: scope(connectionId, database: "shop")) @@ -190,7 +190,7 @@ struct MetadataConnectionPoolIdleEvictionTests { func sweepSparesEntriesWithWorkInFlight() { let connectionId = UUID() let driver = MockDatabaseDriver() - let pool = MetadataConnectionPool.shared + let pool = MetadataConnectionPool.isolatedForTesting() defer { pool.closeAll(connectionId: connectionId) } pool.injectEntry(driver, scope: scope(connectionId, database: "shop")) @@ -206,7 +206,7 @@ struct MetadataConnectionPoolIdleEvictionTests { let connectionId = UUID() let stale = MockDatabaseDriver() let fresh = MockDatabaseDriver() - let pool = MetadataConnectionPool.shared + let pool = MetadataConnectionPool.isolatedForTesting() defer { pool.closeAll(connectionId: connectionId) } let now = Date() @@ -227,12 +227,16 @@ struct MetadataConnectionPoolIdleEvictionTests { @Test("a sweep that empties the pool stops the sweeper") func sweepStopsWhenThePoolEmpties() { let connectionId = UUID() - let pool = MetadataConnectionPool.shared + let pool = MetadataConnectionPool.isolatedForTesting() defer { pool.closeAll(connectionId: connectionId) } pool.injectEntry(MockDatabaseDriver(), scope: scope(connectionId, database: "shop")) + pool.startSweeperForTesting() + #expect(pool.hasSweeper) + pool.sweepIdleEntries(now: Date().addingTimeInterval(MetadataConnectionPool.idleTimeout + 1)) + #expect(pool.pooledDriverCount(for: connectionId) == 0) #expect(!pool.hasSweeper) } diff --git a/TableProTests/Helpers/FakeMSSQLPlugin.swift b/TableProTests/Helpers/FakeMSSQLPlugin.swift index 91e54aac83..022cecdc3a 100644 --- a/TableProTests/Helpers/FakeMSSQLPlugin.swift +++ b/TableProTests/Helpers/FakeMSSQLPlugin.swift @@ -53,8 +53,12 @@ final class FakeMSSQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { var currentSchema: String? { "dbo" } var parameterStyle: ParameterStyle { .questionMark } + /// The one fact a driver reports about a connection the server has closed under it. + var hasLostConnection = false + private(set) var disconnectCallCount = 0 + func connect() async throws {} - func disconnect() {} + func disconnect() { disconnectCallCount += 1 } func execute(query: String) async throws -> PluginQueryResult { PluginQueryResult(columns: [], columnTypeNames: [], rows: [], rowsAffected: 0, executionTime: 0) diff --git a/TableProTests/Plugins/LibPQConnectionLossTests.swift b/TableProTests/Plugins/LibPQConnectionLossTests.swift new file mode 100644 index 0000000000..b7ab0cb124 --- /dev/null +++ b/TableProTests/Plugins/LibPQConnectionLossTests.swift @@ -0,0 +1,139 @@ +// +// LibPQConnectionLossTests.swift +// TableProTests +// + +import Foundation +@testable import TablePro +import TableProPluginKit +import Testing + +@Suite("libpq connection loss") +struct LibPQConnectionLossTests { + private static let serverMessage = LibPQPluginError( + message: "FATAL: terminating connection due to idle-session timeout", + sqlState: "57P05", + detail: nil + ) + + private static func error(_ loss: LibPQConnectionLoss) -> LibPQConnectionLostError { + LibPQConnectionLostError(loss: loss, underlying: serverMessage) + } + + @Test("Only a known idle session counts as holding no transaction") + func unknownCountsAsOpen() { + #expect(!LibPQTransactionState.idle.mayHoldTransaction) + #expect(LibPQTransactionState.unknown.mayHoldTransaction) + #expect(LibPQTransactionState.active.mayHoldTransaction) + #expect(LibPQTransactionState.inTransaction.mayHoldTransaction) + #expect(LibPQTransactionState.inError.mayHoldTransaction) + } + + @Test("A statement never sent is reported as not run, behind the server's own message") + func notSentIsNotRun() { + let error = Self.error(.beforeSending(transactionMayBeOpen: false)) + #expect(error.pluginErrorMessage.hasPrefix(Self.serverMessage.message)) + #expect(error.pluginErrorMessage.contains("It was not run.")) + #expect(!error.pluginErrorMessage.contains("rolled back")) + } + + @Test("A statement never sent while a transaction may be open says the transaction was rolled back") + func notSentInsideTransaction() { + let error = Self.error(.beforeSending(transactionMayBeOpen: true)) + #expect(error.pluginErrorMessage.contains("It was not run, and any open transaction was rolled back.")) + } + + @Test("A statement lost after it was sent may or may not have run, whatever it was") + func sentHasUnknownOutcome() { + let error = Self.error(.afterSending) + #expect(error.pluginErrorMessage.hasPrefix(Self.serverMessage.message)) + #expect(error.pluginErrorMessage.contains("may or may not have completed")) + #expect(error.pluginErrorMessage.contains("rolled back unless this statement committed it")) + } + + @Test("A statement libpq never sent keeps the recorded transaction state; one it sent does not need it") + func sendStageDecidesThePhase() { + func loss(sent: Bool, _ state: LibPQTransactionState) -> LibPQConnectionLoss { + LibPQConnectionLoss(sent: sent, recordedState: state) + } + + #expect(loss(sent: false, .idle) == .beforeSending(transactionMayBeOpen: false)) + #expect(loss(sent: false, .inTransaction) == .beforeSending(transactionMayBeOpen: true)) + #expect(loss(sent: false, .unknown) == .beforeSending(transactionMayBeOpen: true)) + #expect(loss(sent: true, .idle) == .afterSending) + #expect(loss(sent: true, .inTransaction) == .afterSending) + } + + @Test("A server message ends the session on FATAL or PANIC severity") + func severityDecides() { + #expect(LibPQServerMessage.endsSession(severity: "FATAL", sqlState: "57P05")) + #expect(LibPQServerMessage.endsSession(severity: "PANIC", sqlState: "XX000")) + #expect(!LibPQServerMessage.endsSession(severity: "NOTICE", sqlState: "42P07")) + #expect(!LibPQServerMessage.endsSession(severity: "WARNING", sqlState: "25P01")) + #expect(!LibPQServerMessage.endsSession(severity: "ERROR", sqlState: "08003")) + } + + /// A server before 9.6 sends no non-localized severity, so the class is all there is to go on + /// when choosing which message to attach. It decides nothing on its own: the caller reads the + /// sink only once libpq reports `CONNECTION_BAD`, and clears it while the session is healthy. + @Test("Without a severity field, only connection and operator-intervention classes are kept") + func classFallbackForOldServers() { + #expect(LibPQServerMessage.endsSession(severity: nil, sqlState: "57P01")) + #expect(LibPQServerMessage.endsSession(severity: nil, sqlState: "08006")) + #expect(!LibPQServerMessage.endsSession(severity: nil, sqlState: "42P07")) + #expect(!LibPQServerMessage.endsSession(severity: nil, sqlState: "25P01")) + #expect(!LibPQServerMessage.endsSession(severity: nil, sqlState: nil)) + } + + @Test("The server's message and SQLSTATE stay on the error") + func keepsServerMessage() { + let error = Self.error(.beforeSending(transactionMayBeOpen: false)) + #expect(error.pluginSqlState == "57P05") + #expect(error.pluginErrorDetail == nil) + } + + @Test("The server's own detail stays the detail") + func keepsServerDetail() { + let underlying = LibPQPluginError( + message: "server closed the connection unexpectedly", sqlState: nil, detail: "hint" + ) + let error = LibPQConnectionLostError(loss: .afterSending, underlying: underlying) + #expect(error.pluginSqlState == nil) + #expect(error.pluginErrorDetail == "hint") + } +} + +/// The app reads a driver error's message to tell an authentication failure from a refusal, and +/// PostgreSQL sends those as a FATAL, which is exactly the shape that now carries an explanation +/// as well. Both classifiers have to keep working through it. +@Suite("libpq connection loss and the app's error classifiers") +@MainActor +struct LibPQConnectionLossClassifierTests { + @Test("an authentication FATAL lost with the connection is still an authentication failure") + func authenticationFailureStillFires() { + let underlying = LibPQPluginError( + message: "FATAL: password authentication failed for user \"app\"", + sqlState: "28P01", + detail: nil + ) + let error = LibPQConnectionLostError( + loss: .beforeSending(transactionMayBeOpen: false), underlying: underlying + ) + + #expect(DatabaseManager.shared.isAuthenticationFailure(error)) + } + + @Test("a read-only refusal lost with the connection is still classified, with the server's words") + func readOnlyRefusalStillFires() { + let underlying = LibPQPluginError( + message: "ERROR: cannot execute INSERT in a read-only transaction", + sqlState: "25006", + detail: nil + ) + let error = LibPQConnectionLostError(loss: .afterSending, underlying: underlying) + + let diagnosis = DatabaseWriteRejectionDiagnosis.classify(error) + #expect(diagnosis != nil) + #expect(diagnosis?.serverMessage.contains("read-only transaction") == true) + } +} diff --git a/docs/development/plugin-development.mdx b/docs/development/plugin-development.mdx index 91c89bc9b8..2f4e2101c4 100644 --- a/docs/development/plugin-development.mdx +++ b/docs/development/plugin-development.mdx @@ -13,7 +13,7 @@ A plugin is a macOS loadable bundle target with `WRAPPER_EXTENSION = tableplugin | Key | Type | Required | Purpose | |-----|------|----------|---------| -| `TableProPluginKitVersion` | integer | Yes | The PluginKit ABI the plugin was built against. Current value: 26 | +| `TableProPluginKitVersion` | integer | Yes | The PluginKit ABI the plugin was built against. Current value: 27 | | `TableProProvidesDatabaseTypeIds` | array of strings | Recommended | Database type IDs the plugin serves, which is what makes lazy loading possible | | `CFBundleShortVersionString` | string | Yes | Plugin version, read by registry update checks | | `TableProMinAppVersion` | string | No | The loader rejects the plugin on an older app | diff --git a/docs/development/plugin-registry.mdx b/docs/development/plugin-registry.mdx index 316ed240f8..da9ef7a492 100644 --- a/docs/development/plugin-registry.mdx +++ b/docs/development/plugin-registry.mdx @@ -68,13 +68,13 @@ Themes carry no native code, so they match on architecture alone. "binaries": [ { "architecture": "arm64", - "pluginKitVersion": 26, + "pluginKitVersion": 27, "downloadURL": "https://github.com/TableProApp/TablePro/releases/download/plugin-oracle-v1.0.26/OracleDriver-arm64.zip", "sha256": "" }, { "architecture": "x86_64", - "pluginKitVersion": 26, + "pluginKitVersion": 27, "downloadURL": "https://github.com/TableProApp/TablePro/releases/download/plugin-oracle-v1.0.26/OracleDriver-x86_64.zip", "sha256": "" } diff --git a/project.yml b/project.yml index 4484ae98b2..e76f79b317 100644 --- a/project.yml +++ b/project.yml @@ -511,6 +511,7 @@ targets: - Plugins/PostgreSQLDriverPlugin/ColumnQueryShape.swift - Plugins/PostgreSQLDriverPlugin/LibPQByteaDecoder.swift - Plugins/PostgreSQLDriverPlugin/LibPQCellDecoding.swift + - Plugins/PostgreSQLDriverPlugin/LibPQConnectionLoss.swift - Plugins/PostgreSQLDriverPlugin/LibPQConnectionString.swift - Plugins/PostgreSQLDriverPlugin/LibPQCopyDirection+UnsupportedMessage.swift - Plugins/PostgreSQLDriverPlugin/LibPQPendingResultDrain.swift From af95320f01cbc32076a58a61568e876ed5ddc9fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 08:28:05 +0700 Subject: [PATCH 32/54] fix(plugin-postgresql): generate DDL older PostgreSQL servers accept (#2764) * fix(plugin-postgresql): generate DDL older PostgreSQL servers accept Claude-Session: https://claude.ai/code/session_01X1ejXbmyPqUziRWVxJ5cu8 * docs(changelog): drop a stray merge marker --- CHANGELOG.md | 5 + .../PostgreSQLCapabilities.swift | 8 + ...PostgreSQLPluginDriver+ColumnReorder.swift | 13 +- .../PostgreSQLPluginDriver+PrincipalSQL.swift | 16 +- .../PostgreSQLPluginDriver+Principals.swift | 10 +- ...PostgreSQLPluginDriver+ServerSupport.swift | 42 +++ ...ostgreSQLPluginDriver+TriggerEditing.swift | 55 ++++ .../PostgreSQLPluginDriver.swift | 107 ++----- .../PostgreSQLVersionedStatements.swift | 181 +++++++++++ .../PluginDatabaseDriver.swift | 8 + .../PluginSchemaOperation.swift | 12 + .../Compare/SchemaSyncScriptBuilder.swift | 7 + TablePro/Core/Database/DatabaseDriver.swift | 6 + .../Core/Plugins/PluginDriverAdapter.swift | 4 + .../CreateTableStatementComposer.swift | 14 +- .../SchemaOperationRefusal.swift | 36 +++ .../SchemaStatementGenerator.swift | 4 + .../CreateTableGridDelegate+Inspector.swift | 3 +- .../Structure/CreateTableGridDelegate.swift | 1 + .../Views/Structure/CreateTableView.swift | 13 +- .../Structure/StructureEditingSession.swift | 1 + .../Structure/StructureGridDelegate.swift | 13 +- .../Structure/StructureRowProvider.swift | 17 +- .../Structure/StructureServerSupport.swift | 45 +++ .../TableStructureView+DataLoading.swift | 1 + .../Views/Structure/TableStructureView.swift | 2 + .../Plugins/PluginKitABIResilienceTests.swift | 3 + .../SchemaOperationRefusalTests.swift | 238 ++++++++++++++ .../PostgreSQLVersionedStatementsTests.swift | 299 ++++++++++++++++++ ...tructureColumnFieldRegistrationTests.swift | 4 +- .../StructureGeneratedColumnFieldTests.swift | 3 +- .../StructureGridDelegateInspectorTests.swift | 4 +- .../StructureInspectorRowBuilderTests.swift | 1 + ...uctureRowProviderBooleanOptionsTests.swift | 1 + .../Structure/StructureRowProviderTests.swift | 2 + .../StructureServerSupportTests.swift | 177 +++++++++++ docs/databases/postgresql.mdx | 13 +- docs/features/table-structure.mdx | 4 +- project.yml | 1 + 39 files changed, 1263 insertions(+), 111 deletions(-) create mode 100644 Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+ServerSupport.swift create mode 100644 Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+TriggerEditing.swift create mode 100644 Plugins/PostgreSQLDriverPlugin/PostgreSQLVersionedStatements.swift create mode 100644 Plugins/TableProPluginKit/PluginSchemaOperation.swift create mode 100644 TablePro/Core/SchemaTracking/SchemaOperationRefusal.swift create mode 100644 TablePro/Views/Structure/StructureServerSupport.swift create mode 100644 TableProTests/Core/SchemaTracking/SchemaOperationRefusalTests.swift create mode 100644 TableProTests/Plugins/PostgreSQLVersionedStatementsTests.swift create mode 100644 TableProTests/Views/Structure/StructureServerSupportTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index fceccdd9e1..e0040b4c0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - First-launch tour replaced by a one-page welcome sheet, shown again from Help > Getting Started. - Beancount connections held at Safe Mode Read-Only. (#2030) - MySQL sessions on the server's default `utf8mb4` collation. +- Structure editor options the connected PostgreSQL server does not support left out: generated columns before 12, BRIN before 9.5, and the MySQL-only FULLTEXT and SPATIAL index types. ### Removed @@ -58,6 +59,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Crash opening a MySQL result whose column has no name on iPhone and iPad. - Wrong SQLSTATE code in PostgreSQL, Redshift, CockroachDB and PGlite error messages. - Read-only write explanation never shown on PostgreSQL servers. +- Trigger editing and the New Trigger template failing on PostgreSQL 13 and earlier. +- Reindexing a whole PostgreSQL database failing before PostgreSQL 16. +- Schema copy, check constraint rename, column reorder and role editing failing on older PostgreSQL servers. +- FULLTEXT and SPATIAL index types creating a plain B-tree index on PostgreSQL. - Table list, foreign keys, triggers, check constraints, types and grants failing on PostgreSQL 9.1 to 9.5. (#2734) - Wrong index column order on PostgreSQL 9.4 and earlier. - Sequences missing from SQL dumps of PostgreSQL 9.6 and earlier. diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift index 58a6483e7f..c69aefabd0 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift @@ -47,4 +47,12 @@ struct PostgreSQLCapabilities: Sendable, Equatable { var hasDatabaseICULocale: Bool { serverVersion >= 150_000 } var hasDatabaseLocale: Bool { serverVersion >= 170_000 } var hasModernICUSyntax: Bool { serverVersion >= 160_000 } + + var hasRenameConstraint: Bool { serverVersion >= 90_200 } + var hasCreateSchemaIfNotExists: Bool { serverVersion >= 90_300 } + var hasBrinIndexes: Bool { serverVersion >= 90_500 } + var hasExecuteFunctionTriggerSyntax: Bool { serverVersion >= 110_000 } + var hasReindexConcurrently: Bool { serverVersion >= 120_000 } + var hasCreateOrReplaceTrigger: Bool { serverVersion >= 140_000 } + var hasUnnamedReindexDatabase: Bool { serverVersion >= 160_000 } } diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+ColumnReorder.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+ColumnReorder.swift index a312bad9c3..791a577acd 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+ColumnReorder.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+ColumnReorder.swift @@ -47,13 +47,12 @@ extension PostgreSQLPluginDriver { var statements: [String] = [] statements.append("ALTER TABLE \(qualified) RENAME TO \(quoteIdentifier("\(table)_tablepro_reorder"))") statements.append("CREATE TABLE \(qualified) (\n " + body.joined(separator: ",\n ") + "\n)") - /// `OVERRIDING SYSTEM VALUE` unconditionally. A `GENERATED ALWAYS AS IDENTITY` column - /// refuses a written value without it and takes the whole rebuild down; measured, the - /// clause is accepted and does nothing on a `BY DEFAULT` identity and on a table that has - /// no identity column at all. - statements.append(""" - INSERT INTO \(qualified) (\(copyList)) OVERRIDING SYSTEM VALUE SELECT \(copyList) FROM \(staging) - """) + statements.append(PostgreSQLVersionedStatements.copyRows( + into: qualified, + from: staging, + columnList: copyList, + capabilities: versionedCapabilities + )) statements.append(contentsOf: parts.identityResets(qualified: qualified, quote: quoteIdentifier)) statements.append(contentsOf: parts.inboundForeignKeyDrops) /// A `serial` column's default still calls the sequence the staging table owns, so `DROP diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+PrincipalSQL.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+PrincipalSQL.swift index f1b84061e2..1f05e90f7f 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+PrincipalSQL.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+PrincipalSQL.swift @@ -117,9 +117,16 @@ extension PostgreSQLPluginDriver { } } + private var supportedRoleAttributes: Set { + PostgreSQLVersionedStatements.roleAttributes(capabilities: versionedCapabilities) + } + private func attributeKeywords(_ attributes: [PluginPrincipalAttribute]) -> [String] { - attributes.compactMap { attribute in - guard let known = PostgreSQLRoleAttribute(rawValue: attribute.key) else { return nil } + let supported = supportedRoleAttributes + return attributes.compactMap { attribute in + guard let known = PostgreSQLRoleAttribute(rawValue: attribute.key), supported.contains(known) else { + return nil + } return known.keyword(isEnabled: attribute.isEnabled) } } @@ -129,8 +136,11 @@ extension PostgreSQLPluginDriver { new: [PluginPrincipalAttribute] ) -> [String] { let oldByKey = Dictionary(uniqueKeysWithValues: old.map { ($0.key, $0.isEnabled) }) + let supported = supportedRoleAttributes return new.compactMap { attribute in - guard let known = PostgreSQLRoleAttribute(rawValue: attribute.key) else { return nil } + guard let known = PostgreSQLRoleAttribute(rawValue: attribute.key), supported.contains(known) else { + return nil + } guard oldByKey[attribute.key] != attribute.isEnabled else { return nil } return known.keyword(isEnabled: attribute.isEnabled) } diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Principals.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Principals.swift index c4aee02f1b..a22d646375 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Principals.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Principals.swift @@ -42,6 +42,7 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { func fetchPrincipals() async throws -> [PluginPrincipalInfo] { let memberships = try await fetchMemberships() + let supportedAttributes = PostgreSQLVersionedStatements.roleAttributes(capabilities: versionedCapabilities) let query = PostgreSQLPrincipalQueries.principals( includeBypassRLS: versionedCapabilities.hasBypassRLS ) @@ -50,7 +51,7 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { return result.rows.compactMap { row -> PluginPrincipalInfo? in guard let name = row[safe: 0]?.asText else { return nil } let canLogin = PostgreSQLCatalogBoolean.isTrue(row[safe: 1]?.asText) - let attributes = Self.decodeAttributes(row: row) + let attributes = Self.decodeAttributes(row: row, supported: supportedAttributes) let connectionLimit = row[safe: 8]?.asText.flatMap(Int.init) return PluginPrincipalInfo( @@ -230,7 +231,10 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { } } - private static func decodeAttributes(row: [PluginCellValue]) -> [PluginPrincipalAttribute] { + private static func decodeAttributes( + row: [PluginCellValue], + supported: Set + ) -> [PluginPrincipalAttribute] { let columnOffsets: [(PostgreSQLRoleAttribute, Int)] = [ (.superuser, 2), (.createdb, 3), @@ -239,7 +243,7 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { (.bypassrls, 6), (.inherit, 7) ] - return columnOffsets.map { attribute, offset in + return columnOffsets.filter { supported.contains($0.0) }.map { attribute, offset in PluginPrincipalAttribute( key: attribute.rawValue, label: attribute.label, diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+ServerSupport.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+ServerSupport.swift new file mode 100644 index 0000000000..8f66c2fe66 --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+ServerSupport.swift @@ -0,0 +1,42 @@ +// +// PostgreSQLPluginDriver+ServerSupport.swift +// PostgreSQLDriverPlugin +// + +import Foundation +import os +import TableProPluginKit + +internal extension PostgreSQLPluginDriver { + private static let sessionLogger = Logger(subsystem: "com.TablePro.PostgreSQLDriver", category: "PostgreSQLSession") + + var connectedDatabase: String? { + sessionFacts.withLock { $0.database } + } + + var unsupportedStructureColumnFields: Set { + PostgreSQLVersionedStatements.unsupportedStructureColumnFields(capabilities: versionedCapabilities) + } + + var unsupportedIndexTypes: Set { + PostgreSQLVersionedStatements.unsupportedIndexTypes(capabilities: versionedCapabilities) + } + + func schemaOperationRefusal(_ operation: PluginSchemaOperation) -> String? { + PostgreSQLVersionedStatements.refusal(for: operation, capabilities: versionedCapabilities) + } + + func probeSessionFacts() async { + do { + let result = try await core.execute(query: PostgreSQLSessionFacts.probeQuery) + let row = result.rows.first?.map(\.asText) ?? [] + let facts = PostgreSQLSessionFacts(probeRow: row) + sessionFacts.withLock { $0 = facts } + } catch { + sessionFacts.withLock { $0 = .unknown } + Self.sessionLogger.error( + "Session probe failed; DDL falls back to forms every server accepts: \(error.localizedDescription, privacy: .public)" + ) + } + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+TriggerEditing.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+TriggerEditing.swift new file mode 100644 index 0000000000..f969299e77 --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+TriggerEditing.swift @@ -0,0 +1,55 @@ +// +// PostgreSQLPluginDriver+TriggerEditing.swift +// PostgreSQLDriverPlugin +// + +import Foundation +import TableProPluginKit + +internal extension PostgreSQLPluginDriver { + var triggerEditUsesReplace: Bool { versionedCapabilities.hasCreateOrReplaceTrigger } + + var supportsTransactionalDDL: Bool { true } + + func qualifiedTable(_ table: String, schema: String?) -> String { + let resolved = schema ?? core.currentSchema + return "\(quoteIdentifier(resolved)).\(quoteIdentifier(table))" + } + + func createTriggerTemplate(table: String, schema: String?) -> String? { + PostgreSQLVersionedStatements.triggerTemplate( + qualifiedTable: qualifiedTable(table, schema: schema), + qualifiedFunction: qualifiedTable("trigger_function", schema: schema), + capabilities: versionedCapabilities + ) + } + + func fetchTriggerDefinition(name: String, table: String, schema: String?) async throws -> String? { + let resolvedSchema = schema ?? core.currentSchema + let query = """ + SELECT pg_get_functiondef(t.tgfoid), pg_get_triggerdef(t.oid) + FROM pg_catalog.pg_trigger t + JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid + JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace + WHERE t.tgname = '\(escapeLiteral(name))' + AND c.relname = '\(escapeLiteral(table))' + AND n.nspname = '\(escapeLiteral(resolvedSchema))' + AND NOT t.tgisinternal + LIMIT 1 + """ + let result = try await execute(query: query) + guard let row = result.rows.first, row.count >= 2, + let functionDef = row[0].asText, + let triggerDef = row[1].asText else { return nil } + return PostgreSQLVersionedStatements.editableTriggerDefinition( + functionDefinition: functionDef, + triggerDefinition: triggerDef, + dropStatement: generateDropTriggerSQL(name: name, table: table, schema: schema), + capabilities: versionedCapabilities + ) + } + + func generateDropTriggerSQL(name: String, table: String, schema: String?) -> String? { + "DROP TRIGGER IF EXISTS \(quoteIdentifier(name)) ON \(qualifiedTable(table, schema: schema))" + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift index 61a8a0bd42..fb23f60492 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift @@ -19,10 +19,15 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { private static let undefinedFunctionSQLState = PostgreSQLTableListingLadder.undefinedFunctionSQLState private var catalogPresence: PostgreSQLCatalogPresence? + let sessionFacts = OSAllocatedUnfairLock(initialState: PostgreSQLSessionFacts.unknown) + + var serverVersionNumber: Int32 { + let reported = core.serverVersionNumber + return sessionFacts.withLock { $0.resolvedServerVersion(reported: reported) } + } - var serverVersionNumber: Int32 { core.serverVersionNumber } var versionedCapabilities: PostgreSQLCapabilities { - PostgreSQLCapabilities(serverVersion: core.serverVersionNumber) + PostgreSQLCapabilities(serverVersion: serverVersionNumber) } var catalogCapabilities: PostgreSQLCapabilities { .assumingModernWhenUnknown(core.serverVersionNumber) @@ -54,6 +59,7 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { func connect() async throws { core.onPostConnect = { [weak self] in + await self?.probeSessionFacts() await self?.probeCatalogPresence() await self?.probePostgisOids() await self?.probeEnumOids() @@ -120,7 +126,7 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { /// A duplicated database arrives with `public` alone, so every other schema its tables are /// qualified with has to be made before the first `CREATE TABLE` names one. func createSchemaStatement(name: String) -> String? { - "CREATE SCHEMA IF NOT EXISTS \(quoteIdentifier(name))" + PostgreSQLVersionedStatements.createSchema(name, capabilities: versionedCapabilities) } // MARK: - Maintenance @@ -142,7 +148,11 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { case "ANALYZE": return [target.map { "ANALYZE \($0)" } ?? "ANALYZE"] case "REINDEX": - return [target.map { "REINDEX TABLE \($0)" } ?? "REINDEX DATABASE CONCURRENTLY"] + if let target { return ["REINDEX TABLE \(target)"] } + return PostgreSQLVersionedStatements.reindexDatabase( + currentDatabase: connectedDatabase, + capabilities: versionedCapabilities + ).map { [$0] } case "CLUSTER": return target.map { ["CLUSTER \($0)"] } default: @@ -262,70 +272,6 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { return triggers } - var triggerEditUsesReplace: Bool { true } - - var supportsTransactionalDDL: Bool { true } - - private func qualifiedTable(_ table: String, schema: String?) -> String { - let resolved = schema ?? core.currentSchema - return "\(quoteIdentifier(resolved)).\(quoteIdentifier(table))" - } - - func createTriggerTemplate(table: String, schema: String?) -> String? { - let qualified = qualifiedTable(table, schema: schema) - let fn = qualifiedTable("trigger_function", schema: schema) - return """ - CREATE OR REPLACE FUNCTION \(fn)() - RETURNS trigger - LANGUAGE plpgsql - AS $function$ - BEGIN - -- NEW.updated_at := now(); - RETURN NEW; - END; - $function$; - - CREATE OR REPLACE TRIGGER \(quoteIdentifier("trigger_name")) - BEFORE INSERT ON \(qualified) - FOR EACH ROW - EXECUTE FUNCTION \(fn)(); - """ - } - - func fetchTriggerDefinition(name: String, table: String, schema: String?) async throws -> String? { - let resolvedSchema = schema ?? core.currentSchema - let query = """ - SELECT pg_get_functiondef(t.tgfoid), pg_get_triggerdef(t.oid) - FROM pg_catalog.pg_trigger t - JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid - JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace - WHERE t.tgname = '\(escapeLiteral(name))' - AND c.relname = '\(escapeLiteral(table))' - AND n.nspname = '\(escapeLiteral(resolvedSchema))' - AND NOT t.tgisinternal - LIMIT 1 - """ - let result = try await execute(query: query) - guard let row = result.rows.first, row.count >= 2, - let functionDef = row[0].asText, - let triggerDef = row[1].asText else { return nil } - let editableTrigger: String - if triggerDef.range(of: "CREATE CONSTRAINT TRIGGER", options: .caseInsensitive) != nil { - let drop = generateDropTriggerSQL(name: name, table: table, schema: schema) ?? "" - editableTrigger = "\(drop);\n\(triggerDef)" - } else { - editableTrigger = triggerDef.replacingOccurrences( - of: "CREATE TRIGGER ", - with: "CREATE OR REPLACE TRIGGER " - ) - } - return "\(functionDef);\n\n\(editableTrigger);" - } - - func generateDropTriggerSQL(name: String, table: String, schema: String?) -> String? { - "DROP TRIGGER IF EXISTS \(quoteIdentifier(name)) ON \(qualifiedTable(table, schema: schema))" - } - /// PostgreSQL allows `f(integer)` and `f(text)` in one schema, so a drop that names only `f` /// is ambiguous and the server refuses it. func generateDropRoutineSQL( @@ -760,7 +706,7 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { case "icu": guard supportsProvider else { throw LibPQPluginError( - message: String(localized: "ICU provider requires PostgreSQL 15 or newer"), + message: String(localized: "ICU provider requires PostgreSQL 15 or later"), sqlState: nil, detail: nil ) @@ -881,7 +827,9 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { // MARK: - Create Table DDL func generateCreateTableSQL(definition: PluginCreateTableDefinition) -> String? { - guard !definition.columns.isEmpty else { return nil } + guard !definition.columns.isEmpty, + PostgreSQLVersionedStatements.refusal(for: definition, capabilities: versionedCapabilities) == nil + else { return nil } let schema = core.currentSchema let qualifiedTable = "\(quoteIdentifier(schema)).\(quoteIdentifier(definition.tableName))" @@ -979,7 +927,7 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { let unique = index.isUnique ? "UNIQUE " : "" var def = "CREATE \(unique)INDEX \(quoteIdentifier(index.name)) ON \(qualifiedTable)" if let type = index.indexType?.uppercased(), - ["BTREE", "HASH", "GIN", "GIST", "BRIN"].contains(type) { + PostgreSQLVersionedStatements.postgreSQLIndexMethods.contains(type) { def += " USING \(type.lowercased())" } def += " (\(cols))" @@ -1015,10 +963,12 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { // MARK: - Definition SQL (clipboard copy) func generateColumnDefinitionSQL(column: PluginColumnDefinition) -> String? { - pgColumnDefinition(column, inlinePK: false) + guard schemaOperationRefusal(.addColumn(column)) == nil else { return nil } + return pgColumnDefinition(column, inlinePK: false) } func generateIndexDefinitionSQL(index: PluginIndexDefinition, tableName: String?) -> String? { + guard schemaOperationRefusal(.addIndex(index)) == nil else { return nil } let qualifiedTable = tableName.map { quoteIdentifier($0) } ?? "\"table\"" return pgIndexDefinition(index, qualifiedTable: qualifiedTable) } @@ -1034,6 +984,7 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { } func generateAddColumnSQL(table: String, column: PluginColumnDefinition) -> String? { + guard schemaOperationRefusal(.addColumn(column)) == nil else { return nil } let qt = qualifiedTableName(table) let colDef = pgColumnDefinition(column, inlinePK: false) return "ALTER TABLE \(qt) ADD COLUMN \(colDef)" @@ -1084,7 +1035,8 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { } func generateAddIndexSQL(table: String, index: PluginIndexDefinition) -> String? { - pgIndexDefinition(index, qualifiedTable: qualifiedTableName(table)) + guard schemaOperationRefusal(.addIndex(index)) == nil else { return nil } + return pgIndexDefinition(index, qualifiedTable: qualifiedTableName(table)) } func generateDropIndexSQL(table: String, indexName: String) -> String? { @@ -1112,9 +1064,12 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { } func generateRenameCheckConstraintSQL(table: String, from oldName: String, to newName: String) -> String? { - guard !oldName.isEmpty, !newName.isEmpty else { return nil } - return "ALTER TABLE \(qualifiedTableName(table)) RENAME CONSTRAINT " - + "\(quoteIdentifier(oldName)) TO \(quoteIdentifier(newName))" + PostgreSQLVersionedStatements.renameConstraint( + qualifiedTable: qualifiedTableName(table), + from: oldName, + to: newName, + capabilities: versionedCapabilities + ) } func generateModifyPrimaryKeySQL(table: String, oldColumns: [String], newColumns: [String], constraintName: String?) -> [String]? { diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLVersionedStatements.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLVersionedStatements.swift new file mode 100644 index 0000000000..24c7fbd9e6 --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLVersionedStatements.swift @@ -0,0 +1,181 @@ +// +// PostgreSQLVersionedStatements.swift +// PostgreSQLDriverPlugin +// + +import Foundation +import TableProPluginKit + +internal struct PostgreSQLSessionFacts: Sendable, Equatable { + static let probeQuery = "SELECT pg_catalog.current_database(), pg_catalog.current_setting('server_version_num')" + static let unknown = PostgreSQLSessionFacts(database: nil, serverVersion: nil) + + let database: String? + let serverVersion: Int32? + + init(database: String?, serverVersion: Int32?) { + self.database = database + self.serverVersion = serverVersion + } + + init(probeRow row: [String?]) { + let database = row.first.flatMap { $0 }.flatMap { $0.isEmpty ? nil : $0 } + let versionText = row.count > 1 ? row[1]?.trimmingCharacters(in: .whitespaces) : nil + let version = versionText.flatMap { Int32($0) }.flatMap { $0 > 0 ? $0 : nil } + self.init(database: database, serverVersion: version) + } + + func resolvedServerVersion(reported: Int32) -> Int32 { + guard reported <= 0 else { return reported } + return serverVersion ?? 0 + } +} + +internal enum PostgreSQLVersionedStatements { + static let postgreSQLIndexMethods: Set = ["BTREE", "HASH", "GIN", "GIST", "BRIN"] + static let mySQLOnlyIndexTypes: Set = ["FULLTEXT", "SPATIAL"] + + static func createSchema(_ name: String, capabilities: PostgreSQLCapabilities) -> String { + let identifier = PostgreSQLObjectQueries.quoteIdentifier(name) + guard !capabilities.hasCreateSchemaIfNotExists else { + return "CREATE SCHEMA IF NOT EXISTS \(identifier)" + } + let nameLiteral = PostgreSQLObjectQueries.quoteLiteral(name) + let createLiteral = PostgreSQLObjectQueries.quoteLiteral("CREATE SCHEMA \(identifier)") + let body = "BEGIN IF NOT EXISTS (SELECT 1 FROM pg_catalog.pg_namespace WHERE nspname = \(nameLiteral)) " + + "THEN EXECUTE \(createLiteral); END IF; END" + let tag = dollarQuoteTag(avoiding: body) + return "DO \(tag) \(body) \(tag)" + } + + static func reindexDatabase(currentDatabase: String?, capabilities: PostgreSQLCapabilities) -> String? { + guard !capabilities.hasUnnamedReindexDatabase else { return "REINDEX DATABASE CONCURRENTLY" } + guard let currentDatabase, !currentDatabase.isEmpty else { return nil } + let identifier = PostgreSQLObjectQueries.quoteIdentifier(currentDatabase) + guard capabilities.hasReindexConcurrently else { return "REINDEX DATABASE \(identifier)" } + return "REINDEX DATABASE CONCURRENTLY \(identifier)" + } + + static func triggerTemplate( + qualifiedTable: String, + qualifiedFunction: String, + capabilities: PostgreSQLCapabilities + ) -> String { + let trigger = PostgreSQLObjectQueries.quoteIdentifier("trigger_name") + let executeKeyword = capabilities.hasExecuteFunctionTriggerSyntax ? "EXECUTE FUNCTION" : "EXECUTE PROCEDURE" + let createKeyword = capabilities.hasCreateOrReplaceTrigger ? "CREATE OR REPLACE TRIGGER" : "CREATE TRIGGER" + return """ + CREATE OR REPLACE FUNCTION \(qualifiedFunction)() + RETURNS trigger + LANGUAGE plpgsql + AS $function$ + BEGIN + -- NEW.updated_at := now(); + RETURN NEW; + END; + $function$; + + \(createKeyword) \(trigger) + BEFORE INSERT ON \(qualifiedTable) + FOR EACH ROW + \(executeKeyword) \(qualifiedFunction)(); + """ + } + + static func editableTriggerDefinition( + functionDefinition: String, + triggerDefinition: String, + dropStatement: String?, + capabilities: PostgreSQLCapabilities + ) -> String { + guard capabilities.hasCreateOrReplaceTrigger else { + return "\(functionDefinition);\n\n\(triggerDefinition);" + } + guard triggerDefinition.range(of: "CREATE CONSTRAINT TRIGGER", options: .caseInsensitive) == nil else { + return "\(functionDefinition);\n\n\(dropStatement ?? "");\n\(triggerDefinition);" + } + let replaceable = triggerDefinition.replacingOccurrences( + of: "CREATE TRIGGER ", + with: "CREATE OR REPLACE TRIGGER " + ) + return "\(functionDefinition);\n\n\(replaceable);" + } + + static func renameConstraint( + qualifiedTable: String, + from oldName: String, + to newName: String, + capabilities: PostgreSQLCapabilities + ) -> String? { + guard capabilities.hasRenameConstraint, !oldName.isEmpty, !newName.isEmpty else { return nil } + return "ALTER TABLE \(qualifiedTable) RENAME CONSTRAINT " + + "\(PostgreSQLObjectQueries.quoteIdentifier(oldName)) TO \(PostgreSQLObjectQueries.quoteIdentifier(newName))" + } + + static func copyRows( + into qualifiedTable: String, + from stagingTable: String, + columnList: String, + capabilities: PostgreSQLCapabilities + ) -> String { + let overriding = capabilities.hasIdentityColumns ? " OVERRIDING SYSTEM VALUE" : "" + return "INSERT INTO \(qualifiedTable) (\(columnList))\(overriding) SELECT \(columnList) FROM \(stagingTable)" + } + + static func refusal(for operation: PluginSchemaOperation, capabilities: PostgreSQLCapabilities) -> String? { + switch operation { + case .addColumn(let column): + return columnRefusal(column, capabilities: capabilities) + case .addIndex(let index): + return indexRefusal(index, capabilities: capabilities) + case .renameCheckConstraint: + guard !capabilities.hasRenameConstraint else { return nil } + return String(localized: "Renaming a check constraint needs PostgreSQL 9.2 or later.") + @unknown default: + return nil + } + } + + static func refusal(for definition: PluginCreateTableDefinition, capabilities: PostgreSQLCapabilities) -> String? { + let operations = definition.columns.map(PluginSchemaOperation.addColumn) + + definition.indexes.map(PluginSchemaOperation.addIndex) + return operations.lazy.compactMap { refusal(for: $0, capabilities: capabilities) }.first + } + + static func columnRefusal(_ column: PluginColumnDefinition, capabilities: PostgreSQLCapabilities) -> String? { + guard column.isGenerated, !capabilities.hasGeneratedColumns else { return nil } + return String( + format: String(localized: "Column %@ is a generated column, which needs PostgreSQL 12 or later."), + column.name + ) + } + + static func indexRefusal(_ index: PluginIndexDefinition, capabilities: PostgreSQLCapabilities) -> String? { + guard let type = index.indexType?.uppercased(), !type.isEmpty else { return nil } + if mySQLOnlyIndexTypes.contains(type) { + return String(format: String(localized: "PostgreSQL has no %@ index type."), type) + } + guard type == "BRIN", !capabilities.hasBrinIndexes else { return nil } + return String(localized: "BRIN indexes need PostgreSQL 9.5 or later.") + } + + static func unsupportedStructureColumnFields(capabilities: PostgreSQLCapabilities) -> Set { + capabilities.hasGeneratedColumns ? [] : [.generated, .generationExpression] + } + + static func unsupportedIndexTypes(capabilities: PostgreSQLCapabilities) -> Set { + capabilities.hasBrinIndexes ? mySQLOnlyIndexTypes : mySQLOnlyIndexTypes.union(["BRIN"]) + } + + static func roleAttributes(capabilities: PostgreSQLCapabilities) -> Set { + Set(PostgreSQLRoleAttribute.allCases.filter { $0 != .bypassrls || capabilities.hasBypassRLS }) + } + + private static func dollarQuoteTag(avoiding body: String) -> String { + var label = "tablepro" + while body.contains("$\(label)$") { + label += "_" + } + return "$\(label)$" + } +} diff --git a/Plugins/TableProPluginKit/PluginDatabaseDriver.swift b/Plugins/TableProPluginKit/PluginDatabaseDriver.swift index f82eab21ec..a75fc3dde5 100644 --- a/Plugins/TableProPluginKit/PluginDatabaseDriver.swift +++ b/Plugins/TableProPluginKit/PluginDatabaseDriver.swift @@ -316,6 +316,10 @@ public protocol PluginDatabaseDriver: AnyObject, Sendable { /// answer, which stands the check down for an engine TablePro never runs a rebuild on anyway. func columnReorderSchemaFingerprint(table: String, schema: String?) async throws -> String? + var unsupportedStructureColumnFields: Set { get } + var unsupportedIndexTypes: Set { get } + func schemaOperationRefusal(_ operation: PluginSchemaOperation) -> String? + func generateCreateTableSQL(definition: PluginCreateTableDefinition) -> String? // Definition SQL for clipboard copy (optional — return nil if not supported) @@ -785,6 +789,10 @@ public extension PluginDatabaseDriver { func columnReorderSchemaFingerprint(table: String, schema: String?) async throws -> String? { nil } + var unsupportedStructureColumnFields: Set { [] } + var unsupportedIndexTypes: Set { [] } + func schemaOperationRefusal(_ operation: PluginSchemaOperation) -> String? { nil } + func generateCreateTableSQL(definition: PluginCreateTableDefinition) -> String? { nil } func generateColumnDefinitionSQL(column: PluginColumnDefinition) -> String? { nil } diff --git a/Plugins/TableProPluginKit/PluginSchemaOperation.swift b/Plugins/TableProPluginKit/PluginSchemaOperation.swift new file mode 100644 index 0000000000..30f9136d97 --- /dev/null +++ b/Plugins/TableProPluginKit/PluginSchemaOperation.swift @@ -0,0 +1,12 @@ +// +// PluginSchemaOperation.swift +// TableProPluginKit +// + +import Foundation + +public enum PluginSchemaOperation: Sendable { + case addColumn(PluginColumnDefinition) + case addIndex(PluginIndexDefinition) + case renameCheckConstraint(from: String, to: String) +} diff --git a/TablePro/Core/Compare/SchemaSyncScriptBuilder.swift b/TablePro/Core/Compare/SchemaSyncScriptBuilder.swift index 25e83de1ee..7dc76c44cd 100644 --- a/TablePro/Core/Compare/SchemaSyncScriptBuilder.swift +++ b/TablePro/Core/Compare/SchemaSyncScriptBuilder.swift @@ -96,6 +96,13 @@ internal struct SchemaSyncScriptBuilder { charset: snapshot.charset, collation: snapshot.collation ) + if let reason = SchemaOperationRefusal.reason(for: definition, driver: targetDriver) { + throw CompareSyncError.unsupportedOperation(String( + format: String(localized: "Cannot create table %@: %@"), + snapshot.name, + reason + )) + } guard let sql = targetDriver.generateCreateTableSQL(definition: definition) else { throw CompareSyncError.unsupportedOperation(String( format: String(localized: "The target does not support creating table %@."), diff --git a/TablePro/Core/Database/DatabaseDriver.swift b/TablePro/Core/Database/DatabaseDriver.swift index 376d4f1545..d0a1fab0cc 100644 --- a/TablePro/Core/Database/DatabaseDriver.swift +++ b/TablePro/Core/Database/DatabaseDriver.swift @@ -130,6 +130,9 @@ protocol DatabaseDriver: AnyObject, Sendable { var triggerEditUsesReplace: Bool { get } var supportsTransactionalDDL: Bool { get } + var unsupportedStructureColumnFields: Set { get } + var unsupportedIndexTypes: Set { get } + /// Fetch foreign keys for all tables in the current database/schema in bulk. /// Default implementation falls back to per-table fetchForeignKeys. func fetchAllForeignKeys() async throws -> [String: [ForeignKeyInfo]] @@ -392,6 +395,9 @@ extension DatabaseDriver { var triggerEditUsesReplace: Bool { false } var supportsTransactionalDDL: Bool { false } + var unsupportedStructureColumnFields: Set { [] } + var unsupportedIndexTypes: Set { [] } + func ping() async throws { _ = try await execute(query: "SELECT 1") } diff --git a/TablePro/Core/Plugins/PluginDriverAdapter.swift b/TablePro/Core/Plugins/PluginDriverAdapter.swift index b40f7da280..cfd613970a 100644 --- a/TablePro/Core/Plugins/PluginDriverAdapter.swift +++ b/TablePro/Core/Plugins/PluginDriverAdapter.swift @@ -393,6 +393,10 @@ final class PluginDriverAdapter: DatabaseDriver, SchemaSwitchable, DatabaseRepor var supportsTransactionalDDL: Bool { pluginDriver.supportsTransactionalDDL } + var unsupportedStructureColumnFields: Set { pluginDriver.unsupportedStructureColumnFields } + + var unsupportedIndexTypes: Set { pluginDriver.unsupportedIndexTypes } + func fetchApproximateRowCount(table: String) async throws -> Int? { try await pluginDriver.fetchApproximateRowCount(table: table, schema: pluginDriver.currentSchema) } diff --git a/TablePro/Core/SchemaTracking/CreateTableStatementComposer.swift b/TablePro/Core/SchemaTracking/CreateTableStatementComposer.swift index 8e79933783..893fff192a 100644 --- a/TablePro/Core/SchemaTracking/CreateTableStatementComposer.swift +++ b/TablePro/Core/SchemaTracking/CreateTableStatementComposer.swift @@ -36,6 +36,18 @@ enum CreateTableStatementComposer { } var issues = plan.issues + let columnRefusals = definition.columns.compactMap { driver.schemaOperationRefusal(.addColumn($0)) } + issues += columnRefusals.map { SchemaDraftIssue(tab: .columns, row: nil, message: $0) } + var refusedIndexRows: Set = [] + for (row, index) in plan.indexes.enumerated() { + guard let reason = driver.schemaOperationRefusal(.addIndex(index)) else { continue } + refusedIndexRows.insert(row) + issues.append(SchemaDraftIssue(tab: .indexes, row: row, message: reason)) + } + guard columnRefusals.isEmpty else { + return CreateTableStatements(statements: [], issues: issues, tableName: definition.tableName) + } + guard let createTable = driver.generateCreateTableSQL(definition: definition) else { issues.append(SchemaDraftIssue( tab: .columns, row: nil, @@ -45,7 +57,7 @@ enum CreateTableStatementComposer { } var statements = [createTable] - for (row, index) in plan.indexes.enumerated() { + for (row, index) in plan.indexes.enumerated() where !refusedIndexRows.contains(row) { guard let sql = driver.generateAddIndexSQL(table: definition.tableName, index: index) else { issues.append(SchemaDraftIssue( tab: .indexes, row: row, diff --git a/TablePro/Core/SchemaTracking/SchemaOperationRefusal.swift b/TablePro/Core/SchemaTracking/SchemaOperationRefusal.swift new file mode 100644 index 0000000000..c7bd17f96f --- /dev/null +++ b/TablePro/Core/SchemaTracking/SchemaOperationRefusal.swift @@ -0,0 +1,36 @@ +// +// SchemaOperationRefusal.swift +// TablePro +// + +import Foundation +import TableProPluginKit + +internal struct SchemaOperationRefusedError: LocalizedError, Equatable { + let reason: String + + var errorDescription: String? { reason } +} + +internal enum SchemaOperationRefusal { + static func reason(for change: SchemaChange, driver: any PluginDatabaseDriver) -> String? { + switch change { + case .addColumn(let column): + return driver.schemaOperationRefusal(.addColumn(column.toPlugin())) + case .addIndex(let index), .modifyIndex(_, let index): + return driver.schemaOperationRefusal(.addIndex(index.toPlugin())) + case .modifyCheckConstraint(let old, let new): + guard old.expression == new.expression, old.name != new.name else { return nil } + return driver.schemaOperationRefusal(.renameCheckConstraint(from: old.name, to: new.name)) + case .modifyColumn, .deleteColumn, .deleteIndex, .addForeignKey, .modifyForeignKey, + .deleteForeignKey, .modifyPrimaryKey, .addCheckConstraint, .deleteCheckConstraint: + return nil + } + } + + static func reason(for definition: PluginCreateTableDefinition, driver: any PluginDatabaseDriver) -> String? { + let operations = definition.columns.map(PluginSchemaOperation.addColumn) + + definition.indexes.map(PluginSchemaOperation.addIndex) + return operations.lazy.compactMap { driver.schemaOperationRefusal($0) }.first + } +} diff --git a/TablePro/Core/SchemaTracking/SchemaStatementGenerator.swift b/TablePro/Core/SchemaTracking/SchemaStatementGenerator.swift index a8e3e238d4..3e9d8191d2 100644 --- a/TablePro/Core/SchemaTracking/SchemaStatementGenerator.swift +++ b/TablePro/Core/SchemaTracking/SchemaStatementGenerator.swift @@ -45,6 +45,10 @@ struct SchemaStatementGenerator { var statements: [SchemaStatement] = [] let sortedChanges = sortByDependency(changes) + let refusals = sortedChanges.lazy.compactMap { SchemaOperationRefusal.reason(for: $0, driver: pluginDriver) } + if let reason = refusals.first { + throw SchemaOperationRefusedError(reason: reason) + } for change in sortedChanges { let stmts = try generateStatements(for: change) diff --git a/TablePro/Views/Structure/CreateTableGridDelegate+Inspector.swift b/TablePro/Views/Structure/CreateTableGridDelegate+Inspector.swift index 47d4900105..bb238635e0 100644 --- a/TablePro/Views/Structure/CreateTableGridDelegate+Inspector.swift +++ b/TablePro/Views/Structure/CreateTableGridDelegate+Inspector.swift @@ -18,7 +18,8 @@ extension CreateTableGridDelegate: InspectorRowSource { changeManager: structureChangeManager, tab: structureTab, databaseType: connection.type, - additionalFields: [.primaryKey] + additionalFields: [.primaryKey], + serverSupport: serverSupport ), canEditSchema: true, rowOptions: { dataGridMenuOptions(forRow: displayRow, columnIndex: $0) } diff --git a/TablePro/Views/Structure/CreateTableGridDelegate.swift b/TablePro/Views/Structure/CreateTableGridDelegate.swift index 0afab81d7b..57e04c9e7a 100644 --- a/TablePro/Views/Structure/CreateTableGridDelegate.swift +++ b/TablePro/Views/Structure/CreateTableGridDelegate.swift @@ -16,6 +16,7 @@ final class CreateTableGridDelegate: DataGridViewDelegate { let connection: DatabaseConnection var onSelectedRowsChanged: ((Set) -> Void)? var orderedFields: [StructureColumnField] = [] + var serverSupport = StructureServerSupport.unrestricted /// The lists behind the Foreign Keys grid's reference cells. Held per delegate, so the column /// cache dies with the tab rather than outliving every connection. let referenceMenus: ForeignKeyReferenceMenus diff --git a/TablePro/Views/Structure/CreateTableView.swift b/TablePro/Views/Structure/CreateTableView.swift index 58b02b5266..1131978c7c 100644 --- a/TablePro/Views/Structure/CreateTableView.swift +++ b/TablePro/Views/Structure/CreateTableView.swift @@ -56,6 +56,7 @@ struct CreateTableView: View { @State private var selectedRows: Set = [] @State private var sortState = SortState() @State private var columnLayout = ColumnLayoutState() + @State private var serverSupport = StructureServerSupport.unrestricted init( connection: DatabaseConnection, @@ -91,6 +92,7 @@ struct CreateTableView: View { coordinator?.inspectorRowSource = gridDelegate gridDelegate.onSelectedRowsChanged = { self.selectedRows = $0 } gridDelegate.onReferenceListsChanged = { coordinator?.inspectorRowSourceRevision += 1 } + serverSupport = StructureServerSupport.forConnection(connection.id) updateGridDelegate() if structureChangeManager.workingColumns.isEmpty { structureChangeManager.addNewColumn() @@ -300,9 +302,11 @@ struct CreateTableView: View { changeManager: structureChangeManager, tab: structureTab, databaseType: connection.type, - additionalFields: [.primaryKey] + additionalFields: [.primaryKey], + serverSupport: serverSupport ) gridDelegate.structureTab = structureTab + gridDelegate.serverSupport = serverSupport gridDelegate.orderedFields = provider.orderedColumnFields gridDelegate.schemaName = coordinator?.toolbarState.currentSchema coordinator?.inspectorRowSourceRevision += 1 @@ -313,7 +317,8 @@ struct CreateTableView: View { changeManager: structureChangeManager, tab: structureTab, databaseType: connection.type, - additionalFields: [.primaryKey] + additionalFields: [.primaryKey], + serverSupport: serverSupport ) // Rebuild the row snapshot fresh on every call so cell edits made @@ -323,13 +328,15 @@ struct CreateTableView: View { let manager = structureChangeManager let tab = structureTab let dbType = connection.type + let support = serverSupport return DataGridView( tableRowsProvider: { StructureRowProvider( changeManager: manager, tab: tab, databaseType: dbType, - additionalFields: [.primaryKey] + additionalFields: [.primaryKey], + serverSupport: support ).asTableRows() }, changeManager: wrappedChangeManager, diff --git a/TablePro/Views/Structure/StructureEditingSession.swift b/TablePro/Views/Structure/StructureEditingSession.swift index b1b7ed654c..fb6b307492 100644 --- a/TablePro/Views/Structure/StructureEditingSession.swift +++ b/TablePro/Views/Structure/StructureEditingSession.swift @@ -73,6 +73,7 @@ internal final class StructureEditingSession { internal var sortState = SortState() internal var sortDescriptor: StructureSortDescriptor? internal var columnLayouts: [StructureTab: ColumnLayoutState] = [:] + internal var serverSupport = StructureServerSupport.unrestricted /// What the bottom bar offers while this tab is showing its structure. /// diff --git a/TablePro/Views/Structure/StructureGridDelegate.swift b/TablePro/Views/Structure/StructureGridDelegate.swift index 319a9d5f5c..9edc44ca7e 100644 --- a/TablePro/Views/Structure/StructureGridDelegate.swift +++ b/TablePro/Views/Structure/StructureGridDelegate.swift @@ -43,6 +43,7 @@ final class StructureGridDelegate: DataGridViewDelegate { // Ordered fields for column editing (updated when currentProvider is set) var orderedFields: [StructureColumnField] = [] + var serverSupport = StructureServerSupport.unrestricted // Stored when DataGridView calls `dataGridAttach(tableViewCoordinator:)` on // every updateNSView. Lets us tell `NSTableView` which rows to reload after @@ -285,7 +286,8 @@ final class StructureGridDelegate: DataGridViewDelegate { } let displayProvider = currentProvider ?? StructureRowProvider( - changeManager: structureChangeManager, tab: selectedTab, databaseType: connection.type + changeManager: structureChangeManager, tab: selectedTab, databaseType: connection.type, + serverSupport: serverSupport ) var lines: [String] = [] for row in indices.sorted() { @@ -603,7 +605,8 @@ final class StructureGridDelegate: DataGridViewDelegate { private func handleCopyName(_ indices: Set) { let provider = StructureRowProvider( - changeManager: structureChangeManager, tab: selectedTab, databaseType: connection.type + changeManager: structureChangeManager, tab: selectedTab, databaseType: connection.type, + serverSupport: serverSupport ) let names = indices.sorted().compactMap { provider.row(at: $0)?.first ?? nil } guard !names.isEmpty else { return } @@ -655,7 +658,8 @@ final class StructureGridDelegate: DataGridViewDelegate { private func handleCopyAsCSV(_ indices: Set) { let provider = StructureRowProvider( changeManager: structureChangeManager, tab: selectedTab, - databaseType: connection.type, additionalFields: [.primaryKey] + databaseType: connection.type, additionalFields: [.primaryKey], + serverSupport: serverSupport ) let headers = provider.columns guard !headers.isEmpty else { return } @@ -681,7 +685,8 @@ final class StructureGridDelegate: DataGridViewDelegate { private func handleCopyAsJSON(_ indices: Set) { let provider = StructureRowProvider( changeManager: structureChangeManager, tab: selectedTab, - databaseType: connection.type, additionalFields: [.primaryKey] + databaseType: connection.type, additionalFields: [.primaryKey], + serverSupport: serverSupport ) let headers = provider.columns guard !headers.isEmpty else { return } diff --git a/TablePro/Views/Structure/StructureRowProvider.swift b/TablePro/Views/Structure/StructureRowProvider.swift index 6c399342bf..9553ef639c 100644 --- a/TablePro/Views/Structure/StructureRowProvider.swift +++ b/TablePro/Views/Structure/StructureRowProvider.swift @@ -30,6 +30,7 @@ final class StructureRowProvider { private let tab: StructureTab private let databaseType: DatabaseType private let additionalFields: Set + private let serverSupport: StructureServerSupport let orderedColumnFields: [StructureColumnField] private let filterText: String? private let sortDescriptor: StructureSortDescriptor? @@ -122,7 +123,8 @@ final class StructureRowProvider { 6: GridMenuOption.values(updateActions.map(\.rawValue)) ] case .indexes: - let types = EditableIndexDefinition.IndexType.allCases.map(\.rawValue) + let offered = serverSupport.offeredIndexTypes(from: EditableIndexDefinition.IndexType.allCases) + let types = offered.map(\.rawValue) return [2: GridMenuOption.values(types), 3: GridMenuOption.values(Self.booleanOptions)] case .columns: var result: [Int: [GridMenuOption]] = [:] @@ -170,6 +172,7 @@ final class StructureRowProvider { tab: StructureTab, databaseType: DatabaseType = .mysql, additionalFields: Set = [], + serverSupport: StructureServerSupport, filterText: String? = nil, sortDescriptor: StructureSortDescriptor? = nil ) { @@ -177,9 +180,14 @@ final class StructureRowProvider { self.tab = tab self.databaseType = databaseType self.additionalFields = additionalFields + self.serverSupport = serverSupport self.filterText = filterText self.sortDescriptor = sortDescriptor - self.orderedColumnFields = Self.orderedFields(for: databaseType, additionalFields: additionalFields) + self.orderedColumnFields = Self.orderedFields( + for: databaseType, + additionalFields: additionalFields, + serverSupport: serverSupport + ) let allRows = Self.buildAllRows( tab: tab, changeManager: changeManager, orderedColumnFields: self.orderedColumnFields @@ -191,11 +199,12 @@ final class StructureRowProvider { static func orderedFields( for databaseType: DatabaseType, - additionalFields: Set = [] + additionalFields: Set = [], + serverSupport: StructureServerSupport ) -> [StructureColumnField] { let pluginFields = Set(PluginManager.shared.structureColumnFields(for: databaseType)) let fields = pluginFields.union(additionalFields) - return canonicalFieldOrder.filter { fields.contains($0) } + return canonicalFieldOrder.filter { fields.contains($0) && serverSupport.offers($0) } } // MARK: - Row Access diff --git a/TablePro/Views/Structure/StructureServerSupport.swift b/TablePro/Views/Structure/StructureServerSupport.swift new file mode 100644 index 0000000000..f5b26384a6 --- /dev/null +++ b/TablePro/Views/Structure/StructureServerSupport.swift @@ -0,0 +1,45 @@ +// +// StructureServerSupport.swift +// TablePro +// + +import Foundation +import TableProPluginKit + +struct StructureServerSupport: Equatable, Sendable { + let unsupportedColumnFields: Set + let unsupportedIndexTypes: Set + + static let unrestricted = StructureServerSupport(unsupportedColumnFields: [], unsupportedIndexTypes: []) + + init(unsupportedColumnFields: Set, unsupportedIndexTypes: Set) { + self.unsupportedColumnFields = unsupportedColumnFields + self.unsupportedIndexTypes = Set(unsupportedIndexTypes.map { $0.uppercased() }) + } + + init(driver: (any DatabaseDriver)?) { + guard let driver else { + self = .unrestricted + return + } + self.init( + unsupportedColumnFields: driver.unsupportedStructureColumnFields, + unsupportedIndexTypes: driver.unsupportedIndexTypes + ) + } + + @MainActor + static func forConnection(_ connectionId: UUID) -> StructureServerSupport { + StructureServerSupport(driver: DatabaseManager.shared.driver(for: connectionId)) + } + + func offers(_ field: StructureColumnField) -> Bool { + !unsupportedColumnFields.contains(field) + } + + func offeredIndexTypes( + from types: [EditableIndexDefinition.IndexType] + ) -> [EditableIndexDefinition.IndexType] { + types.filter { !unsupportedIndexTypes.contains($0.rawValue.uppercased()) } + } +} diff --git a/TablePro/Views/Structure/TableStructureView+DataLoading.swift b/TablePro/Views/Structure/TableStructureView+DataLoading.swift index 6aab7f1449..390702d411 100644 --- a/TablePro/Views/Structure/TableStructureView+DataLoading.swift +++ b/TablePro/Views/Structure/TableStructureView+DataLoading.swift @@ -90,6 +90,7 @@ extension TableStructureView { } func loadSchemaForEditing() { + session.serverSupport = StructureServerSupport.forConnection(connection.id) let pkFromIndexes = indexes.first(where: { $0.isPrimary })?.columns ?? [] let pkFromColumns = columns.filter { $0.isPrimaryKey }.map { $0.name } let primaryKey = pkFromIndexes.isEmpty ? pkFromColumns : pkFromIndexes diff --git a/TablePro/Views/Structure/TableStructureView.swift b/TablePro/Views/Structure/TableStructureView.swift index 838c349340..5e290f0e43 100644 --- a/TablePro/Views/Structure/TableStructureView.swift +++ b/TablePro/Views/Structure/TableStructureView.swift @@ -501,6 +501,7 @@ struct TableStructureView: View { tab: selectedTab, databaseType: connection.type, additionalFields: [.primaryKey], + serverSupport: session.serverSupport, filterText: searchText.isEmpty ? nil : searchText, sortDescriptor: structureSortDescriptor ) @@ -517,6 +518,7 @@ struct TableStructureView: View { let provider = makeCurrentProvider() gridDelegate.selectedTab = selectedTab + gridDelegate.serverSupport = session.serverSupport gridDelegate.currentProvider = provider gridDelegate.orderedFields = provider.orderedColumnFields coordinator?.inspectorRowSourceRevision += 1 diff --git a/TableProTests/Core/Plugins/PluginKitABIResilienceTests.swift b/TableProTests/Core/Plugins/PluginKitABIResilienceTests.swift index 39c8841cab..1e8588b170 100644 --- a/TableProTests/Core/Plugins/PluginKitABIResilienceTests.swift +++ b/TableProTests/Core/Plugins/PluginKitABIResilienceTests.swift @@ -36,6 +36,9 @@ struct PluginKitABIResilienceTests { #expect(driver.defaultExportQuery(table: "users") == nil) #expect(driver.createViewTemplate() == nil) #expect(driver.generateCreateTableSQL(definition: .init(tableName: "users", columns: [], primaryKeyColumns: [])) == nil) + #expect(driver.unsupportedStructureColumnFields.isEmpty) + #expect(driver.unsupportedIndexTypes.isEmpty) + #expect(driver.schemaOperationRefusal(.renameCheckConstraint(from: "a", to: "b")) == nil) } @Test("A driver that omits defaulted requirements falls back to the documented asynchronous defaults") diff --git a/TableProTests/Core/SchemaTracking/SchemaOperationRefusalTests.swift b/TableProTests/Core/SchemaTracking/SchemaOperationRefusalTests.swift new file mode 100644 index 0000000000..7994b5dbec --- /dev/null +++ b/TableProTests/Core/SchemaTracking/SchemaOperationRefusalTests.swift @@ -0,0 +1,238 @@ +// +// SchemaOperationRefusalTests.swift +// TableProTests +// + +import Foundation +@testable import TablePro +import TableProPluginKit +import Testing + +private final class RefusingDDLDriver: PluginDatabaseDriver, @unchecked Sendable { + var refuse: (PluginSchemaOperation) -> String? = { _ in nil } + + var currentSchema: String? { "public" } + + func connect() async throws {} + func disconnect() {} + func ping() async throws {} + func execute(query: String) async throws -> PluginQueryResult { + PluginQueryResult(columns: [], columnTypeNames: [], rows: [], rowsAffected: 0, executionTime: 0) + } + func fetchTables(schema: String?) async throws -> [PluginTableInfo] { [] } + func fetchColumns(table: String, schema: String?) async throws -> [PluginColumnInfo] { [] } + func fetchIndexes(table: String, schema: String?) async throws -> [PluginIndexInfo] { [] } + func fetchForeignKeys(table: String, schema: String?) async throws -> [PluginForeignKeyInfo] { [] } + func fetchTableDDL(table: String, schema: String?) async throws -> String { "" } + func fetchViewDefinition(view: String, schema: String?) async throws -> String { "" } + func fetchTableMetadata(table: String, schema: String?) async throws -> PluginTableMetadata { + PluginTableMetadata(tableName: table) + } + func fetchDatabases() async throws -> [String] { [] } + func fetchDatabaseMetadata(_ database: String) async throws -> PluginDatabaseMetadata { + PluginDatabaseMetadata(name: database) + } + + func schemaOperationRefusal(_ operation: PluginSchemaOperation) -> String? { refuse(operation) } + + func generateCreateTableSQL(definition: PluginCreateTableDefinition) -> String? { + "CREATE TABLE \(definition.tableName) (...)" + } + func generateAddColumnSQL(table: String, column: PluginColumnDefinition) -> String? { + "ALTER TABLE \(table) ADD COLUMN \(column.name)" + } + func generateAddIndexSQL(table: String, index: PluginIndexDefinition) -> String? { + "CREATE INDEX \(index.name) ON \(table)" + } + func generateAddCheckConstraintSQL(table: String, constraint: PluginCheckConstraintDefinition) -> String? { + "ALTER TABLE \(table) ADD CONSTRAINT \(constraint.name) CHECK (\(constraint.expression))" + } + func generateDropCheckConstraintSQL(table: String, constraintName: String) -> String? { + "ALTER TABLE \(table) DROP CONSTRAINT \(constraintName)" + } +} + +private enum RefusalReason { + static let generated = "Column total is a generated column, which needs PostgreSQL 12 or later." + static let brin = "BRIN indexes need PostgreSQL 9.5 or later." + static let rename = "Renaming a check constraint needs PostgreSQL 9.2 or later." +} + +@MainActor @Suite("Schema operation refusal") +struct SchemaOperationRefusalTests { + private static let generatedReason = RefusalReason.generated + private static let brinReason = RefusalReason.brin + private static let renameReason = RefusalReason.rename + + private func legacyDriver() -> RefusingDDLDriver { + let driver = RefusingDDLDriver() + driver.refuse = { operation in + switch operation { + case .addColumn(let column): + return column.isGenerated ? RefusalReason.generated : nil + case .addIndex(let index): + return index.indexType == "BRIN" ? RefusalReason.brin : nil + case .renameCheckConstraint: + return RefusalReason.rename + @unknown default: + return nil + } + } + return driver + } + + private func column(_ name: String, generated: Bool) -> EditableColumnDefinition { + var column = EditableColumnDefinition.placeholder() + column.name = name + column.dataType = "integer" + if generated { + column.generationKind = .stored + column.generationExpression = "qty * price" + } + return column + } + + private func index(_ name: String, type: EditableIndexDefinition.IndexType) -> EditableIndexDefinition { + var index = EditableIndexDefinition.placeholder() + index.name = name + index.columns = ["qty"] + index.type = type + return index + } + + private func constraint(_ name: String, _ expression: String) -> EditableCheckConstraintDefinition { + EditableCheckConstraintDefinition(id: UUID(), name: name, expression: expression, columns: [], isValidated: true) + } + + private func refusal(of change: SchemaChange, driver: RefusingDDLDriver) -> String? { + do { + _ = try SchemaStatementGenerator(tableName: "orders", pluginDriver: driver).generate(changes: [change]) + return nil + } catch let error as SchemaOperationRefusedError { + return error.reason + } catch { + return "unexpected: \(error.localizedDescription)" + } + } + + private func refusalOfBatch(_ changes: [SchemaChange], driver: RefusingDDLDriver) -> String? { + do { + _ = try SchemaStatementGenerator(tableName: "orders", pluginDriver: driver).generate(changes: changes) + return nil + } catch let error as SchemaOperationRefusedError { + return error.reason + } catch { + return "unexpected: \(error.localizedDescription)" + } + } + + @Test("A refused column is reported with the driver's reason, not a generic unsupported message") + func refusedColumnSurfacesReason() { + #expect(refusal(of: .addColumn(column("total", generated: true)), driver: legacyDriver()) == Self.generatedReason) + #expect(refusal(of: .addColumn(column("qty", generated: false)), driver: legacyDriver()) == nil) + } + + @Test("A refused index is reported whether it is added or modified") + func refusedIndexSurfacesReason() { + let driver = legacyDriver() + #expect(refusal(of: .addIndex(index("ix_brin", type: .brin)), driver: driver) == Self.brinReason) + let modify = SchemaChange.modifyIndex(old: index("ix", type: .btree), new: index("ix", type: .brin)) + #expect(refusal(of: modify, driver: driver) == Self.brinReason) + #expect(refusal(of: .addIndex(index("ix_btree", type: .btree)), driver: driver) == nil) + } + + @Test("A refusal is reported ahead of a change in the same save that the driver cannot generate") + func refusalWinsOverUngeneratableChange() { + let unsupportedDrop = SchemaChange.deleteIndex(index("ix_old", type: .btree)) + let refusedAdd = SchemaChange.addIndex(index("ix_brin", type: .brin)) + #expect(refusal(of: unsupportedDrop, driver: legacyDriver())?.hasPrefix("unexpected:") == true) + #expect(refusalOfBatch([unsupportedDrop, refusedAdd], driver: legacyDriver()) == Self.brinReason) + } + + @Test("A refused rename stays refused and never turns into a drop and re-add") + func refusedRenameIsNotDroppedAndReAdded() { + let rename = SchemaChange.modifyCheckConstraint(old: constraint("ck_a", "qty > 0"), new: constraint("ck_b", "qty > 0")) + #expect(refusal(of: rename, driver: legacyDriver()) == Self.renameReason) + } + + @Test("An expression change is a drop and re-add, which a rename refusal does not block") + func expressionChangeIsNotARename() throws { + let change = SchemaChange.modifyCheckConstraint(old: constraint("ck_a", "qty > 0"), new: constraint("ck_a", "qty > 1")) + let statements = try SchemaStatementGenerator(tableName: "orders", pluginDriver: legacyDriver()) + .generate(changes: [change]) + #expect(statements.map(\.sql) == [ + "ALTER TABLE orders DROP CONSTRAINT ck_a;", + "ALTER TABLE orders ADD CONSTRAINT ck_a CHECK (qty > 1);" + ]) + } + + @Test("A driver that never refuses generates as before") + func defaultDriverRefusesNothing() throws { + let statements = try SchemaStatementGenerator(tableName: "orders", pluginDriver: RefusingDDLDriver()) + .generate(changes: [.addColumn(column("total", generated: true))]) + #expect(statements.map(\.sql) == ["ALTER TABLE orders ADD COLUMN total;"]) + } + + @Test("Create Table names a refused column instead of saying the database cannot create tables") + func createTableNamesRefusedColumn() { + let plan = CreateTablePlan( + definition: PluginCreateTableDefinition( + tableName: "orders", + columns: [column("qty", generated: false).toPlugin(), column("total", generated: true).toPlugin()], + primaryKeyColumns: [] + ), + indexes: [], + issues: [] + ) + let composed = CreateTableStatementComposer.compose(plan: plan, driver: legacyDriver()) + #expect(composed.statements.isEmpty) + #expect(composed.issues.map(\.message) == [Self.generatedReason]) + #expect(composed.issues.first?.tab == .columns) + } + + @Test("Create Table flags a refused index on its own row and still creates the table") + func createTableFlagsRefusedIndexRow() { + let plan = CreateTablePlan( + definition: PluginCreateTableDefinition( + tableName: "orders", + columns: [column("qty", generated: false).toPlugin()], + primaryKeyColumns: [] + ), + indexes: [index("ix_btree", type: .btree).toPlugin(), index("ix_brin", type: .brin).toPlugin()], + issues: [] + ) + let composed = CreateTableStatementComposer.compose(plan: plan, driver: legacyDriver()) + #expect(composed.statements == ["CREATE TABLE orders (...)", "CREATE INDEX ix_btree ON orders"]) + #expect(composed.issues.count == 1) + #expect(composed.issues.first?.tab == .indexes) + #expect(composed.issues.first?.row == 1) + #expect(composed.issues.first?.message == Self.brinReason) + } + + @Test("Schema sync refuses to create a table the target cannot hold, naming table and reason") + func schemaSyncRefusesCreateTable() { + let snapshot = TableStructureSnapshot(name: "orders", columns: [column("total", generated: true)]) + let builder = SchemaSyncScriptBuilder(targetDriver: legacyDriver()) + do { + _ = try builder.build(operations: [.createTable(snapshot)], foreignKeysByTable: [:]) + Issue.record("expected a refusal") + } catch { + #expect(error.localizedDescription.contains("orders")) + #expect(error.localizedDescription.contains(Self.generatedReason)) + } + } + + @Test("Schema sync refuses to add a column the target cannot hold") + func schemaSyncRefusesAlterTable() { + let builder = SchemaSyncScriptBuilder(targetDriver: legacyDriver()) + do { + _ = try builder.build( + operations: [.alterTable(name: "orders", schema: nil, changes: [.addColumn(column("total", generated: true))])], + foreignKeysByTable: [:] + ) + Issue.record("expected a refusal") + } catch { + #expect(error.localizedDescription == Self.generatedReason) + } + } +} diff --git a/TableProTests/Plugins/PostgreSQLVersionedStatementsTests.swift b/TableProTests/Plugins/PostgreSQLVersionedStatementsTests.swift new file mode 100644 index 0000000000..eb5896a20e --- /dev/null +++ b/TableProTests/Plugins/PostgreSQLVersionedStatementsTests.swift @@ -0,0 +1,299 @@ +// +// PostgreSQLVersionedStatementsTests.swift +// TableProTests +// + +import Foundation +import TableProPluginKit +import Testing + +@Suite("PostgreSQLVersionedStatements") +struct PostgreSQLVersionedStatementsTests { + private static let v91 = PostgreSQLCapabilities(serverVersion: 90_124) + private static let v92 = PostgreSQLCapabilities(serverVersion: 90_223) + private static let v96 = PostgreSQLCapabilities(serverVersion: 90_600) + private static let v10 = PostgreSQLCapabilities(serverVersion: 100_000) + private static let v11 = PostgreSQLCapabilities(serverVersion: 110_000) + private static let v12 = PostgreSQLCapabilities(serverVersion: 120_000) + private static let v13 = PostgreSQLCapabilities(serverVersion: 130_000) + private static let v14 = PostgreSQLCapabilities(serverVersion: 140_000) + private static let v15 = PostgreSQLCapabilities(serverVersion: 150_000) + private static let v16 = PostgreSQLCapabilities(serverVersion: 160_000) + private static let v17 = PostgreSQLCapabilities(serverVersion: 170_000) + + @Test("DDL thresholds match the versions measured against live servers") + func thresholds() { + #expect(!Self.v91.hasRenameConstraint) + #expect(Self.v92.hasRenameConstraint) + #expect(!Self.v92.hasCreateSchemaIfNotExists) + #expect(PostgreSQLCapabilities(serverVersion: 90_300).hasCreateSchemaIfNotExists) + #expect(!PostgreSQLCapabilities(serverVersion: 90_426).hasBrinIndexes) + #expect(PostgreSQLCapabilities(serverVersion: 90_500).hasBrinIndexes) + #expect(!Self.v10.hasExecuteFunctionTriggerSyntax) + #expect(Self.v11.hasExecuteFunctionTriggerSyntax) + #expect(!Self.v11.hasReindexConcurrently) + #expect(Self.v12.hasReindexConcurrently) + #expect(!Self.v13.hasCreateOrReplaceTrigger) + #expect(Self.v14.hasCreateOrReplaceTrigger) + #expect(!Self.v15.hasUnnamedReindexDatabase) + #expect(Self.v16.hasUnnamedReindexDatabase) + } + + @Test("An unknown version takes the conservative form of every gated statement") + func unknownVersionIsConservative() { + let unknown = PostgreSQLCapabilities(serverVersion: 0) + #expect(!unknown.hasBypassRLS) + #expect(!unknown.hasIdentityColumns) + #expect(!unknown.hasGeneratedColumns) + #expect(!unknown.hasSetGeneratedExpression) + #expect(!unknown.hasVirtualGeneratedColumns) + #expect(!unknown.hasDatabaseICULocale) + #expect(!unknown.hasModernICUSyntax) + #expect(PostgreSQLVersionedStatements.createSchema("s", capabilities: unknown).hasPrefix("DO ")) + #expect(PostgreSQLVersionedStatements.reindexDatabase(currentDatabase: "app", capabilities: unknown) + == "REINDEX DATABASE \"app\"") + let template = PostgreSQLVersionedStatements.triggerTemplate( + qualifiedTable: "t", qualifiedFunction: "f", capabilities: unknown + ) + #expect(template.contains("\nCREATE TRIGGER \"trigger_name\"")) + #expect(template.contains("EXECUTE PROCEDURE f();")) + #expect(PostgreSQLVersionedStatements.copyRows(into: "t", from: "s", columnList: "a", capabilities: unknown) + == "INSERT INTO t (a) SELECT a FROM s") + #expect(!PostgreSQLVersionedStatements.roleAttributes(capabilities: unknown).contains(.bypassrls)) + } + + @Test("The session probe row parses into a database and a version") + func sessionFactsParsing() { + let facts = PostgreSQLSessionFacts(probeRow: ["app", "90124"]) + #expect(facts == PostgreSQLSessionFacts(database: "app", serverVersion: 90_124)) + #expect(PostgreSQLSessionFacts(probeRow: ["app", " 170011 "]).serverVersion == 170_011) + #expect(PostgreSQLSessionFacts(probeRow: ["", "0"]) == .unknown) + #expect(PostgreSQLSessionFacts(probeRow: [nil, "9.1.24"]) == .unknown) + #expect(PostgreSQLSessionFacts(probeRow: []) == .unknown) + } + + @Test("libpq's own version wins; the probed one fills in only when libpq reports none") + func resolvedServerVersion() { + let facts = PostgreSQLSessionFacts(database: "app", serverVersion: 90_124) + #expect(facts.resolvedServerVersion(reported: 170_011) == 170_011) + #expect(facts.resolvedServerVersion(reported: 0) == 90_124) + #expect(PostgreSQLSessionFacts.unknown.resolvedServerVersion(reported: 0) == 0) + } + + @Test("9.3 and later create a schema with IF NOT EXISTS") + func createSchemaModern() { + let statement = PostgreSQLVersionedStatements.createSchema("sales", capabilities: Self.v96) + #expect(statement == "CREATE SCHEMA IF NOT EXISTS \"sales\"") + } + + @Test("Before 9.3 a schema is created from a DO block guarded by pg_namespace") + func createSchemaLegacy() { + let statement = PostgreSQLVersionedStatements.createSchema("sales", capabilities: Self.v91) + #expect(statement.hasPrefix("DO $tablepro$ ")) + #expect(statement.hasSuffix(" $tablepro$")) + #expect(statement.contains("WHERE nspname = 'sales'")) + #expect(statement.contains("EXECUTE 'CREATE SCHEMA \"sales\"'")) + #expect(!statement.contains("IF NOT EXISTS \"")) + } + + @Test("A legacy schema name with quotes and backslashes stays inside its literals") + func createSchemaLegacyEscapesName() { + let statement = PostgreSQLVersionedStatements.createSchema(#"o'b\"x"#, capabilities: Self.v91) + #expect(statement.contains(#"nspname = E'o''b\\"x'"#)) + #expect(statement.contains(#"EXECUTE E'CREATE SCHEMA "o''b\\""x"'"#)) + } + + @Test("A name that contains the dollar-quote tag gets a tag it cannot close") + func createSchemaLegacyAvoidsTagCollision() { + let statement = PostgreSQLVersionedStatements.createSchema("x$tablepro$y", capabilities: Self.v91) + #expect(statement.hasPrefix("DO $tablepro_$ ")) + #expect(statement.hasSuffix(" $tablepro_$")) + } + + @Test("REINDEX DATABASE names the current database where the server requires it") + func reindexDatabase() { + #expect(PostgreSQLVersionedStatements.reindexDatabase(currentDatabase: "app", capabilities: Self.v91) + == "REINDEX DATABASE \"app\"") + #expect(PostgreSQLVersionedStatements.reindexDatabase(currentDatabase: "app", capabilities: Self.v11) + == "REINDEX DATABASE \"app\"") + #expect(PostgreSQLVersionedStatements.reindexDatabase(currentDatabase: "app", capabilities: Self.v12) + == "REINDEX DATABASE CONCURRENTLY \"app\"") + #expect(PostgreSQLVersionedStatements.reindexDatabase(currentDatabase: "app", capabilities: Self.v15) + == "REINDEX DATABASE CONCURRENTLY \"app\"") + #expect(PostgreSQLVersionedStatements.reindexDatabase(currentDatabase: "app", capabilities: Self.v16) + == "REINDEX DATABASE CONCURRENTLY") + } + + @Test("Without a known database a pre-16 server gets no REINDEX DATABASE at all") + func reindexDatabaseWithoutName() { + #expect(PostgreSQLVersionedStatements.reindexDatabase(currentDatabase: nil, capabilities: Self.v12) == nil) + #expect(PostgreSQLVersionedStatements.reindexDatabase(currentDatabase: "", capabilities: Self.v91) == nil) + #expect(PostgreSQLVersionedStatements.reindexDatabase(currentDatabase: nil, capabilities: Self.v17) + == "REINDEX DATABASE CONCURRENTLY") + } + + @Test("The new-trigger template uses the syntax each server accepts") + func triggerTemplate() { + func template(_ capabilities: PostgreSQLCapabilities) -> String { + PostgreSQLVersionedStatements.triggerTemplate( + qualifiedTable: "\"public\".\"t\"", + qualifiedFunction: "\"public\".\"trigger_function\"", + capabilities: capabilities + ) + } + let legacy = template(Self.v91) + #expect(legacy.contains("\nCREATE TRIGGER \"trigger_name\"")) + #expect(legacy.contains("EXECUTE PROCEDURE \"public\".\"trigger_function\"();")) + #expect(!legacy.contains("OR REPLACE TRIGGER")) + #expect(!legacy.contains("DROP TRIGGER")) + + let eleven = template(Self.v11) + #expect(eleven.contains("EXECUTE FUNCTION")) + #expect(!eleven.contains("DROP TRIGGER")) + + let thirteen = template(Self.v13) + #expect(!thirteen.contains("OR REPLACE TRIGGER")) + + let modern = template(Self.v14) + #expect(modern.contains("CREATE OR REPLACE TRIGGER \"trigger_name\"")) + #expect(modern.contains("EXECUTE FUNCTION")) + #expect(!modern.contains("DROP TRIGGER")) + #expect(modern.hasPrefix("CREATE OR REPLACE FUNCTION \"public\".\"trigger_function\"()")) + } + + @Test("Before 14 an edited trigger keeps its plain CREATE TRIGGER, since the app drops it first") + func editableTriggerLegacy() { + let definition = PostgreSQLVersionedStatements.editableTriggerDefinition( + functionDefinition: "CREATE OR REPLACE FUNCTION f() RETURNS trigger AS $$ BEGIN RETURN NEW; END $$", + triggerDefinition: "CREATE TRIGGER t BEFORE INSERT ON x FOR EACH ROW EXECUTE PROCEDURE f()", + dropStatement: "DROP TRIGGER IF EXISTS \"t\" ON \"public\".\"x\"", + capabilities: Self.v13 + ) + #expect(definition.hasSuffix("\n\nCREATE TRIGGER t BEFORE INSERT ON x FOR EACH ROW EXECUTE PROCEDURE f();")) + #expect(!definition.contains("OR REPLACE TRIGGER")) + #expect(!definition.contains("DROP TRIGGER")) + } + + @Test("From 14 an edited trigger is replaced in place") + func editableTriggerModern() { + let definition = PostgreSQLVersionedStatements.editableTriggerDefinition( + functionDefinition: "CREATE OR REPLACE FUNCTION f()", + triggerDefinition: "CREATE TRIGGER t BEFORE INSERT ON x FOR EACH ROW EXECUTE FUNCTION f()", + dropStatement: "DROP TRIGGER IF EXISTS \"t\" ON \"public\".\"x\"", + capabilities: Self.v14 + ) + #expect(definition == "CREATE OR REPLACE FUNCTION f();\n\nCREATE OR REPLACE TRIGGER t BEFORE INSERT ON x FOR EACH ROW EXECUTE FUNCTION f();") + } + + @Test("A constraint trigger has no OR REPLACE form, so it is dropped and recreated") + func editableConstraintTrigger() { + let definition = PostgreSQLVersionedStatements.editableTriggerDefinition( + functionDefinition: "CREATE OR REPLACE FUNCTION f()", + triggerDefinition: "CREATE CONSTRAINT TRIGGER t AFTER INSERT ON x FOR EACH ROW EXECUTE FUNCTION f()", + dropStatement: "DROP TRIGGER IF EXISTS \"t\" ON \"public\".\"x\"", + capabilities: Self.v17 + ) + #expect(definition.contains("DROP TRIGGER IF EXISTS \"t\" ON \"public\".\"x\";\nCREATE CONSTRAINT TRIGGER t")) + } + + @Test("RENAME CONSTRAINT exists from 9.2; on 9.1 the rename falls back to drop and re-add") + func renameConstraint() { + #expect(PostgreSQLVersionedStatements.renameConstraint( + qualifiedTable: "\"public\".\"t\"", from: "a", to: "b", capabilities: Self.v91 + ) == nil) + #expect(PostgreSQLVersionedStatements.renameConstraint( + qualifiedTable: "\"public\".\"t\"", from: "a", to: "b", capabilities: Self.v92 + ) == "ALTER TABLE \"public\".\"t\" RENAME CONSTRAINT \"a\" TO \"b\"") + #expect(PostgreSQLVersionedStatements.renameConstraint( + qualifiedTable: "\"public\".\"t\"", from: "", to: "b", capabilities: Self.v17 + ) == nil) + } + + @Test("The column reorder copy carries OVERRIDING SYSTEM VALUE only where identity columns exist") + func copyRows() { + let legacy = PostgreSQLVersionedStatements.copyRows( + into: "\"public\".\"t\"", from: "\"public\".\"t_old\"", columnList: "\"a\", \"b\"", capabilities: Self.v96 + ) + #expect(legacy == "INSERT INTO \"public\".\"t\" (\"a\", \"b\") SELECT \"a\", \"b\" FROM \"public\".\"t_old\"") + let modern = PostgreSQLVersionedStatements.copyRows( + into: "\"public\".\"t\"", from: "\"public\".\"t_old\"", columnList: "\"a\"", capabilities: Self.v10 + ) + #expect(modern == "INSERT INTO \"public\".\"t\" (\"a\") OVERRIDING SYSTEM VALUE SELECT \"a\" FROM \"public\".\"t_old\"") + } + + @Test("A generated column is refused before 12 with the version it needs") + func generatedColumnRefusal() { + let plain = PluginColumnDefinition(name: "a", dataType: "int", generationExpression: nil, generationKind: nil) + let generated = PluginColumnDefinition( + name: "b", dataType: "int", generationExpression: "a * 2", generationKind: .stored + ) + let blankExpression = PluginColumnDefinition( + name: "c", dataType: "int", generationExpression: "", generationKind: nil + ) + #expect(PostgreSQLVersionedStatements.refusal(for: .addColumn(plain), capabilities: Self.v91) == nil) + #expect(PostgreSQLVersionedStatements.refusal(for: .addColumn(blankExpression), capabilities: Self.v91) == nil) + let reason = PostgreSQLVersionedStatements.refusal(for: .addColumn(generated), capabilities: Self.v11) + #expect(reason?.contains("b") == true) + #expect(reason?.contains("PostgreSQL 12 or later") == true) + #expect(PostgreSQLVersionedStatements.refusal(for: .addColumn(generated), capabilities: Self.v12) == nil) + } + + @Test("BRIN is refused before 9.5; FULLTEXT and SPATIAL are refused on every version") + func indexRefusal() { + func index(_ type: String?) -> PluginIndexDefinition { + PluginIndexDefinition(name: "ix", columns: ["a"], indexType: type) + } + let brinOld = PostgreSQLVersionedStatements.refusal( + for: .addIndex(index("brin")), capabilities: PostgreSQLCapabilities(serverVersion: 90_426) + ) + #expect(brinOld?.contains("9.5 or later") == true) + #expect(PostgreSQLVersionedStatements.refusal( + for: .addIndex(index("BRIN")), capabilities: PostgreSQLCapabilities(serverVersion: 90_500) + ) == nil) + for type in ["FULLTEXT", "spatial"] { + let reason = PostgreSQLVersionedStatements.refusal(for: .addIndex(index(type)), capabilities: Self.v17) + #expect(reason?.contains(type.uppercased()) == true) + } + for type in [nil, "", "BTREE", "HASH", "GIN", "GIST"] { + #expect(PostgreSQLVersionedStatements.refusal(for: .addIndex(index(type)), capabilities: Self.v91) == nil) + } + } + + @Test("Renaming a check constraint is refused on 9.1 only") + func renameRefusal() { + let rename = PluginSchemaOperation.renameCheckConstraint(from: "a", to: "b") + #expect(PostgreSQLVersionedStatements.refusal(for: rename, capabilities: Self.v91)?.contains("9.2 or later") == true) + #expect(PostgreSQLVersionedStatements.refusal(for: rename, capabilities: Self.v92) == nil) + } + + @Test("A table definition is refused by its first refused column or index") + func createTableRefusal() { + let definition = PluginCreateTableDefinition( + tableName: "t", + columns: [PluginColumnDefinition(name: "a", dataType: "int", generationExpression: nil, generationKind: nil)], + indexes: [PluginIndexDefinition(name: "ix", columns: ["a"], indexType: "BRIN")] + ) + #expect(PostgreSQLVersionedStatements.refusal( + for: definition, capabilities: PostgreSQLCapabilities(serverVersion: 90_426) + )?.contains("BRIN") == true) + #expect(PostgreSQLVersionedStatements.refusal(for: definition, capabilities: Self.v96) == nil) + } + + @Test("The structure editor hides generated fields before 12, BRIN before 9.5 and MySQL index types always") + func unsupportedStructureOptions() { + #expect(PostgreSQLVersionedStatements.unsupportedStructureColumnFields(capabilities: Self.v11) + == [.generated, .generationExpression]) + #expect(PostgreSQLVersionedStatements.unsupportedStructureColumnFields(capabilities: Self.v12).isEmpty) + #expect(PostgreSQLVersionedStatements.unsupportedIndexTypes(capabilities: Self.v91) == ["BRIN", "FULLTEXT", "SPATIAL"]) + #expect(PostgreSQLVersionedStatements.unsupportedIndexTypes(capabilities: Self.v96) == ["FULLTEXT", "SPATIAL"]) + } + + @Test("BYPASSRLS is a role attribute only from 9.5") + func roleAttributes() { + let legacy = PostgreSQLVersionedStatements.roleAttributes(capabilities: Self.v91) + #expect(!legacy.contains(.bypassrls)) + #expect(legacy.contains(.replication)) + #expect(legacy.count == PostgreSQLRoleAttribute.allCases.count - 1) + #expect(PostgreSQLVersionedStatements.roleAttributes(capabilities: Self.v96) == Set(PostgreSQLRoleAttribute.allCases)) + } +} diff --git a/TableProTests/Views/Structure/StructureColumnFieldRegistrationTests.swift b/TableProTests/Views/Structure/StructureColumnFieldRegistrationTests.swift index f530ce4ade..9b03167019 100644 --- a/TableProTests/Views/Structure/StructureColumnFieldRegistrationTests.swift +++ b/TableProTests/Views/Structure/StructureColumnFieldRegistrationTests.swift @@ -31,7 +31,7 @@ struct StructureColumnFieldRegistrationTests { @Test("On update is ordered next to the default it complements") func onUpdateFollowsDefaultValue() { - let fields = StructureRowProvider.orderedFields(for: .mysql) + let fields = StructureRowProvider.orderedFields(for: .mysql, serverSupport: .unrestricted) guard let defaultIndex = fields.firstIndex(of: .defaultValue), let onUpdateIndex = fields.firstIndex(of: .onUpdate) else { Issue.record("MySQL is missing the default or on update field") @@ -79,7 +79,7 @@ struct StructureColumnFieldRegistrationTests { arguments: [DatabaseType.postgresql, .mysql, .sqlite, .cockroachdb, .pglite] ) func declaredBooleanFieldsResolve(databaseType: DatabaseType) { - let ordered = StructureRowProvider.orderedFields(for: databaseType) + let ordered = StructureRowProvider.orderedFields(for: databaseType, serverSupport: .unrestricted) let declared = Set(PluginManager.shared.structureColumnFields(for: databaseType)) for field in [StructureColumnField.nullable, .autoIncrement, .onUpdate] where declared.contains(field) { #expect(ordered.contains(field), "\(databaseType.rawValue) declares \(field) but cannot order it") diff --git a/TableProTests/Views/Structure/StructureGeneratedColumnFieldTests.swift b/TableProTests/Views/Structure/StructureGeneratedColumnFieldTests.swift index a0d9853bfa..ba1bd02b4c 100644 --- a/TableProTests/Views/Structure/StructureGeneratedColumnFieldTests.swift +++ b/TableProTests/Views/Structure/StructureGeneratedColumnFieldTests.swift @@ -25,7 +25,8 @@ struct StructureGeneratedColumnFieldTests { func canonicalOrderCoversEveryField() { let ordered = StructureRowProvider.orderedFields( for: .mysql, - additionalFields: Set(StructureColumnField.allCases) + additionalFields: Set(StructureColumnField.allCases), + serverSupport: .unrestricted ) let missing = StructureColumnField.allCases.filter { !ordered.contains($0) } #expect(missing.isEmpty, "Fields absent from canonicalFieldOrder are discarded: \(missing)") diff --git a/TableProTests/Views/Structure/StructureGridDelegateInspectorTests.swift b/TableProTests/Views/Structure/StructureGridDelegateInspectorTests.swift index 74b1218cd4..db5a696fed 100644 --- a/TableProTests/Views/Structure/StructureGridDelegateInspectorTests.swift +++ b/TableProTests/Views/Structure/StructureGridDelegateInspectorTests.swift @@ -54,6 +54,7 @@ struct StructureGridDelegateInspectorTests { tab: .columns, databaseType: .mysql, additionalFields: [.primaryKey], + serverSupport: .unrestricted, filterText: filterText ) delegate.currentProvider = provider @@ -144,7 +145,8 @@ struct StructureGridDelegateInspectorTests { changeManager: manager, tab: .columns, databaseType: .mysql, - additionalFields: [.primaryKey] + additionalFields: [.primaryKey], + serverSupport: .unrestricted ) delegate.orderedFields = provider.orderedColumnFields diff --git a/TableProTests/Views/Structure/StructureInspectorRowBuilderTests.swift b/TableProTests/Views/Structure/StructureInspectorRowBuilderTests.swift index c6bae88932..b96f4f9753 100644 --- a/TableProTests/Views/Structure/StructureInspectorRowBuilderTests.swift +++ b/TableProTests/Views/Structure/StructureInspectorRowBuilderTests.swift @@ -38,6 +38,7 @@ struct StructureInspectorRowBuilderTests { tab: tab, databaseType: .mysql, additionalFields: [.primaryKey], + serverSupport: .unrestricted, filterText: filterText, sortDescriptor: sortDescriptor ) diff --git a/TableProTests/Views/Structure/StructureRowProviderBooleanOptionsTests.swift b/TableProTests/Views/Structure/StructureRowProviderBooleanOptionsTests.swift index c6afd019ad..9d99647fcb 100644 --- a/TableProTests/Views/Structure/StructureRowProviderBooleanOptionsTests.swift +++ b/TableProTests/Views/Structure/StructureRowProviderBooleanOptionsTests.swift @@ -42,6 +42,7 @@ struct StructureRowProviderBooleanOptionsTests { tab: tab, databaseType: .postgresql, additionalFields: [.primaryKey, .onUpdate], + serverSupport: .unrestricted, filterText: nil, sortDescriptor: nil ) diff --git a/TableProTests/Views/Structure/StructureRowProviderTests.swift b/TableProTests/Views/Structure/StructureRowProviderTests.swift index 894566ed3d..fd59219cda 100644 --- a/TableProTests/Views/Structure/StructureRowProviderTests.swift +++ b/TableProTests/Views/Structure/StructureRowProviderTests.swift @@ -44,6 +44,7 @@ struct StructureRowProviderTests { tab: .columns, databaseType: .mysql, additionalFields: [.name, .type], + serverSupport: .unrestricted, filterText: filterText, sortDescriptor: sortDescriptor ) @@ -148,6 +149,7 @@ struct StructureRowProviderChangeStateTests { tab: tab, databaseType: .mysql, additionalFields: [.primaryKey], + serverSupport: .unrestricted, filterText: filterText ) } diff --git a/TableProTests/Views/Structure/StructureServerSupportTests.swift b/TableProTests/Views/Structure/StructureServerSupportTests.swift new file mode 100644 index 0000000000..b9226b1925 --- /dev/null +++ b/TableProTests/Views/Structure/StructureServerSupportTests.swift @@ -0,0 +1,177 @@ +// +// StructureServerSupportTests.swift +// TableProTests +// + +import Foundation +@testable import TablePro +import TableProPluginKit +import Testing + +private final class StructureSupportStubDriver: PluginDatabaseDriver, @unchecked Sendable { + var supportsSchemas: Bool { false } + var supportsTransactions: Bool { false } + var currentSchema: String? { nil } + var serverVersion: String? { nil } + + var hiddenFields: Set = [] + var hiddenIndexTypes: Set = [] + + var unsupportedStructureColumnFields: Set { hiddenFields } + var unsupportedIndexTypes: Set { hiddenIndexTypes } + + func connect() async throws {} + func disconnect() {} + func ping() async throws {} + func execute(query: String) async throws -> PluginQueryResult { + PluginQueryResult(columns: [], columnTypeNames: [], rows: [], rowsAffected: 0, executionTime: 0) + } + + func fetchTables(schema: String?) async throws -> [PluginTableInfo] { [] } + func fetchColumns(table: String, schema: String?) async throws -> [PluginColumnInfo] { [] } + func fetchIndexes(table: String, schema: String?) async throws -> [PluginIndexInfo] { [] } + func fetchForeignKeys(table: String, schema: String?) async throws -> [PluginForeignKeyInfo] { [] } + func fetchTableDDL(table: String, schema: String?) async throws -> String { "" } + func fetchViewDefinition(view: String, schema: String?) async throws -> String { "" } + func fetchTableMetadata(table: String, schema: String?) async throws -> PluginTableMetadata { + PluginTableMetadata(tableName: table) + } + + func fetchDatabases() async throws -> [String] { [] } + func fetchDatabaseMetadata(_ database: String) async throws -> PluginDatabaseMetadata { + PluginDatabaseMetadata(name: database) + } +} + +private final class DefaultStructureStubDriver: PluginDatabaseDriver, @unchecked Sendable { + var supportsSchemas: Bool { false } + var supportsTransactions: Bool { false } + var currentSchema: String? { nil } + var serverVersion: String? { nil } + + func connect() async throws {} + func disconnect() {} + func ping() async throws {} + func execute(query: String) async throws -> PluginQueryResult { + PluginQueryResult(columns: [], columnTypeNames: [], rows: [], rowsAffected: 0, executionTime: 0) + } + + func fetchTables(schema: String?) async throws -> [PluginTableInfo] { [] } + func fetchColumns(table: String, schema: String?) async throws -> [PluginColumnInfo] { [] } + func fetchIndexes(table: String, schema: String?) async throws -> [PluginIndexInfo] { [] } + func fetchForeignKeys(table: String, schema: String?) async throws -> [PluginForeignKeyInfo] { [] } + func fetchTableDDL(table: String, schema: String?) async throws -> String { "" } + func fetchViewDefinition(view: String, schema: String?) async throws -> String { "" } + func fetchTableMetadata(table: String, schema: String?) async throws -> PluginTableMetadata { + PluginTableMetadata(tableName: table) + } + + func fetchDatabases() async throws -> [String] { [] } + func fetchDatabaseMetadata(_ database: String) async throws -> PluginDatabaseMetadata { + PluginDatabaseMetadata(name: database) + } +} + +@MainActor @Suite("Structure server support") +struct StructureServerSupportTests { + private static let additionalFields: Set = [ + .primaryKey, .generated, .generationExpression + ] + + private static let legacyServer = StructureServerSupport( + unsupportedColumnFields: [.generated, .generationExpression], + unsupportedIndexTypes: ["brin"] + ) + + private func makeManager() -> StructureChangeManager { + let manager = StructureChangeManager() + manager.workingColumns = [EditableColumnDefinition.placeholder()] + return manager + } + + private func provider(tab: StructureTab, support: StructureServerSupport) -> StructureRowProvider { + StructureRowProvider( + changeManager: makeManager(), + tab: tab, + databaseType: .postgresql, + additionalFields: Self.additionalFields, + serverSupport: support + ) + } + + @Test("An unrestricted server offers every field and index type") + func unrestrictedOffersEverything() { + let support = StructureServerSupport.unrestricted + #expect(StructureColumnField.allCases.allSatisfy { support.offers($0) }) + #expect(support.offeredIndexTypes(from: EditableIndexDefinition.IndexType.allCases) + == EditableIndexDefinition.IndexType.allCases) + } + + @Test("Index types are matched case-insensitively") + func indexTypesMatchCaseInsensitively() { + let offered = Self.legacyServer.offeredIndexTypes(from: EditableIndexDefinition.IndexType.allCases) + #expect(!offered.contains(.brin)) + #expect(offered.contains(.gin)) + #expect(offered.count == EditableIndexDefinition.IndexType.allCases.count - 1) + } + + @Test("A server without generated columns never shows the Generated and Expression columns") + func legacyServerHidesGeneratedFields() { + let fields = provider(tab: .columns, support: Self.legacyServer).orderedColumnFields + #expect(!fields.contains(.generated)) + #expect(!fields.contains(.generationExpression)) + #expect(fields.contains(.primaryKey)) + } + + @Test("A server with generated columns keeps them") + func modernServerKeepsGeneratedFields() { + let fields = provider(tab: .columns, support: .unrestricted).orderedColumnFields + #expect(fields.contains(.generated)) + #expect(fields.contains(.generationExpression)) + } + + @Test("The static field order applies the same server support as the provider") + func staticOrderMatchesProvider() { + let fields = StructureRowProvider.orderedFields( + for: .postgresql, + additionalFields: Self.additionalFields, + serverSupport: Self.legacyServer + ) + #expect(fields == provider(tab: .columns, support: Self.legacyServer).orderedColumnFields) + #expect(!fields.contains(.generated)) + } + + @Test("The index type dropdown leaves out what the server lacks") + func indexTypeDropdownFiltersUnsupportedTypes() { + let types = provider(tab: .indexes, support: Self.legacyServer).customDropdownOptions[2]?.compactMap(\.sql) ?? [] + #expect(!types.isEmpty) + #expect(!types.contains("BRIN")) + #expect(types.contains("GIN")) + let unrestricted = provider(tab: .indexes, support: .unrestricted).customDropdownOptions[2]?.compactMap(\.sql) + #expect(unrestricted?.contains("BRIN") == true) + } + + @Test("The adapter bridges what the connected server cannot honour") + func adapterBridgesServerSupport() { + let driver = StructureSupportStubDriver() + driver.hiddenFields = [.generated, .generationExpression] + driver.hiddenIndexTypes = ["BRIN"] + let adapter = PluginDriverAdapter( + connection: DatabaseConnection(name: "Test", type: .postgresql), + pluginDriver: driver + ) + let support = StructureServerSupport(driver: adapter) + #expect(support.unsupportedColumnFields == [.generated, .generationExpression]) + #expect(support.unsupportedIndexTypes == ["BRIN"]) + } + + @Test("A driver built before the hook existed restricts nothing") + func defaultDriverRestrictsNothing() { + let adapter = PluginDriverAdapter( + connection: DatabaseConnection(name: "Test", type: .postgresql), + pluginDriver: DefaultStructureStubDriver() + ) + #expect(StructureServerSupport(driver: adapter) == .unrestricted) + #expect(StructureServerSupport(driver: nil) == .unrestricted) + } +} diff --git a/docs/databases/postgresql.mdx b/docs/databases/postgresql.mdx index 7eddaf1d26..e8e18105c6 100644 --- a/docs/databases/postgresql.mdx +++ b/docs/databases/postgresql.mdx @@ -1,6 +1,6 @@ --- title: PostgreSQL -description: Connect to PostgreSQL with the libpq driver, including PostGIS display, AWS IAM auth, and pg_dump backups +description: Connect to PostgreSQL 9.1 and later with the libpq driver, including PostGIS display, AWS IAM auth, and pg_dump backups --- Unlike MySQL, PostgreSQL will not connect without a **Database**, and it changes database only by reconnecting. Everything else on the form is ordinary. The libpq driver ships inside the app and also serves [Amazon Redshift](/databases/redshift), [CockroachDB](/databases/cockroachdb), and [PGlite](/databases/pglite). @@ -16,7 +16,14 @@ Unlike MySQL, PostgreSQL will not connect without a **Database**, and it changes Fill in the form and click **Save & Connect**. For remote servers use [SSH tunneling](/connections/ssh-tunneling); Google Cloud SQL instances can connect through the [Cloud SQL Auth Proxy](/connections/cloud-sql-proxy). -The sidebar, the structure view, Users & Roles privileges and SQL export work from PostgreSQL 9.1. Generated columns need 12, declarative partitioning and identity columns need 10, and materialized views need 9.3. Some editing still needs a newer server; see [Limitations](#limitations). +Any server from 9.1 on works. A feature the server predates stays out of the sidebar and the structure editor: + +| Feature | Needs | +|---|---| +| Materialized views | 9.3 | +| BRIN indexes, the **Bypass row level security** role attribute | 9.5 | +| Declarative partitioning, identity columns, renaming an enum label | 10 | +| Generated columns | 12 | PostgreSQL connection form @@ -95,7 +102,7 @@ New connections default to **Preferred** (libpq `sslmode=prefer`): TLS first, pl - Columns cannot be reordered. The structure editor adds, renames, retypes, and drops; changing the order of existing columns means recreating the table. - A cross-database tab cannot share session state with the main connection. Statements that depend on a temp table or an open transaction have to run on one database. - Backup and restore need `pg_dump` and `pg_restore` on your Mac. Neither is bundled; install them with Homebrew. `pg_dump` 15 and later refuse PostgreSQL 9.1, so back one up with `pg_dump` 14 or earlier. -- Some edits fail with a syntax error on older servers: editing or creating a trigger before 14, creating a role or changing its attributes before 9.5, and copying objects into a schema that does not exist yet before 9.3. Run the statement from the query editor instead, with `DROP TRIGGER` then `CREATE TRIGGER`, or without `BYPASSRLS` and `IF NOT EXISTS`. +- Before PostgreSQL 12, the [`run_maintenance`](/external-api/mcp-tools) tool's `REINDEX` with no `table` runs without `CONCURRENTLY` and rebuilds the system catalog indexes as well. While an index rebuilds, writes to its table wait, and so do reads that use that index. Run it when the database is quiet. ## Troubleshooting diff --git a/docs/features/table-structure.mdx b/docs/features/table-structure.mdx index 20324feba5..0358efb12f 100644 --- a/docs/features/table-structure.mdx +++ b/docs/features/table-structure.mdx @@ -47,7 +47,7 @@ Changing the default of a column that already exists takes a different route per ### Generated columns -PostgreSQL, CockroachDB, PGlite, MySQL, MariaDB and SQLite add two more fields. **Generated** is a menu of Not generated, STORED and VIRTUAL; **Expression** holds the SQL the value is computed from. Set both on a new row and the column is created as `GENERATED ALWAYS AS (expression)`. +PostgreSQL, CockroachDB, PGlite, MySQL, MariaDB and SQLite add two more fields. **Generated** is a menu of Not generated, STORED and VIRTUAL; **Expression** holds the SQL the value is computed from. Set both on a new row and the column is created as `GENERATED ALWAYS AS (expression)`. PostgreSQL 11 and earlier have no generated columns, so on those servers neither field appears. The keyword is always written out. PostgreSQL 17 and earlier accept STORED only, PostgreSQL 18 made VIRTUAL the default, and MySQL and MariaDB default to VIRTUAL, so leaving it implicit would mean different columns on different servers. @@ -85,7 +85,7 @@ Everything that runs goes to query history rather than the change queue. | Field | Description | |-------|-------------| | **Columns** | Indexed columns. Multi-column indexes list several columns in one row. MySQL prefix lengths are written as `email(20)` | -| **Type** | BTREE, HASH, FULLTEXT, SPATIAL (MySQL), GIN, GIST, BRIN (PostgreSQL) | +| **Type** | BTREE, HASH, FULLTEXT, SPATIAL (MySQL), GIN, GIST, BRIN (PostgreSQL 9.5 and later) | | **Unique** | Whether the index enforces uniqueness | | **Condition** | `WHERE` predicate for partial indexes (PostgreSQL, SQLite, libSQL, Cloudflare D1) | diff --git a/project.yml b/project.yml index e76f79b317..668b9820c7 100644 --- a/project.yml +++ b/project.yml @@ -538,6 +538,7 @@ targets: - Plugins/PostgreSQLDriverPlugin/PostgreSQLTextArray.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLTransactionStatement.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLTypeDefinition.swift + - Plugins/PostgreSQLDriverPlugin/PostgreSQLVersionedStatements.swift - Plugins/PostgreSQLDriverPlugin/RedshiftExternalSchemaQueries.swift - Plugins/PostgreSQLDriverPlugin/RedshiftSchemaQueries.swift - Plugins/KafkaDriverPlugin/KafkaApiKey.swift From 01ee1ba711979314156e89407bb0b51b6f8f9723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 08:34:34 +0700 Subject: [PATCH 33/54] fix(plugin-postgresql): read materialized view columns in the structure tab and autocomplete (#2726) (#2772) --- CHANGELOG.md | 1 + .../PostgreSQLPluginDriver+Columns.swift | 6 +- .../PostgreSQLPluginDriver.swift | 2 +- .../PostgreSQLSchemaQueries.swift | 155 +++++++++++++--- .../Plugins/PostgreSQLColumnQueryTests.swift | 167 +++++++++++++++++- 5 files changed, 302 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0040b4c0d..f0d8ca62c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Empty Columns tab and no autocomplete for PostgreSQL materialized views. (#2726) - Discard restoring a different row than the one edited under a column value filter. - Add Row under a column value filter selecting and opening the wrong row for editing. - Data grid ignoring the theme's background, text, alternate row, NULL, boolean and row number colors. diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift index 2e49910fb8..d84805172f 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift @@ -14,7 +14,8 @@ extension PostgreSQLPluginDriver { let query = PostgreSQLSchemaQueries.columnsQuery( schemaLiteral: safeSchema, tableLiteral: safeTable, - capabilities: versionedCapabilities + capabilities: versionedCapabilities, + includeMaterializedViews: includesMaterializedViews() ) let result = try await execute(query: query) return result.rows.compactMap { row in @@ -28,7 +29,8 @@ extension PostgreSQLPluginDriver { let query = PostgreSQLSchemaQueries.columnsQuery( schemaLiteral: safeSchema, tableLiteral: nil, - capabilities: versionedCapabilities + capabilities: versionedCapabilities, + includeMaterializedViews: includesMaterializedViews() ) let result = try await execute(query: query) var allColumns: [String: [PluginColumnInfo]] = [:] diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift index fb23f60492..31b0cf8037 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift @@ -95,7 +95,7 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { } } - private func includesMaterializedViews() -> Bool { + func includesMaterializedViews() -> Bool { catalogPresence?.hasMaterializedViews ?? versionedCapabilities.hasMaterializedViewsCatalog } diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLSchemaQueries.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLSchemaQueries.swift index 7207b26136..0db4d047c3 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLSchemaQueries.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLSchemaQueries.swift @@ -219,13 +219,6 @@ enum PostgreSQLSchemaQueries { """ } - /// Column introspection for one schema. Passing `tableLiteral` restricts the - /// result to a single table; passing `nil` returns every table's columns and - /// prefixes each row with `table_name`. `schemaLiteral` is the only schema - /// source, so the caller resolves the target schema (qualified reference, - /// then current schema) before escaping and passing it here. The identity, - /// generated, and attribute-join fragments come from the connected server's - /// versioned capabilities. static let enumTypeOidQuery = """ SELECT t.oid::text, t.typarray::text, t.typname FROM pg_catalog.pg_type t @@ -278,12 +271,29 @@ enum PostgreSQLSchemaQueries { """ } + /// Column introspection for one schema. Passing `tableLiteral` restricts the result to a single + /// table; passing `nil` returns every table's columns and prefixes each row with `table_name`. + /// `schemaLiteral` is the only schema source, so the caller resolves the target schema + /// (qualified reference, then current schema) before escaping and passing it here. The identity, + /// generated, and attribute-join fragments come from the connected server's versioned + /// capabilities. + /// + /// `includeMaterializedViews` appends a second arm for `relkind = 'm'`. + /// `information_schema.columns` is defined with `relkind = ANY (ARRAY['r','v','f','p'])`, so a + /// materialized view has no rows there at all and both its Structure tab and its autocomplete + /// came back empty. The arm reproduces `information_schema.columns`' own type, collation, + /// nullability, comment and privilege expressions rather than replacing the base, so the + /// relation kinds that already worked keep byte-identical rows. The caller gates it on probed + /// catalog presence rather than on the server version, because a PostgreSQL-compatible engine + /// can report a recent version and still have no materialized views (#1383). static func columnsQuery( schemaLiteral: String, tableLiteral: String?, - capabilities: PostgreSQLCapabilities + capabilities: PostgreSQLCapabilities, + includeMaterializedViews: Bool ) -> String { let shape = ColumnQueryShape.fragments(tableLiteral: tableLiteral) + let includesTableName = tableLiteral == nil let identityProjection = capabilities.hasIdentityColumns ? "a.attidentity" : "NULL::text" let generatedProjection = capabilities.hasGeneratedColumns ? "a.attgenerated" : "NULL::text" let generationExpressionProjection = capabilities.hasGeneratedColumns @@ -295,20 +305,21 @@ enum PostgreSQLSchemaQueries { ON a.attrelid = rel.oid AND a.attnum = c.ordinal_position """ : "" - return """ + let informationSchemaArm = """ SELECT - \(shape.selectPrefix)c.column_name, - c.data_type, - c.is_nullable, - c.column_default, - c.collation_name, - pg_catalog.col_description(rel.oid, c.ordinal_position), - c.udt_name, + \(includesTableName ? "c.table_name AS table_name,\n " : "")c.column_name AS column_name, + c.data_type AS data_type, + c.is_nullable AS is_nullable, + c.column_default AS column_default, + c.collation_name AS collation_name, + pg_catalog.col_description(rel.oid, c.ordinal_position) AS column_comment, + c.udt_name AS udt_name, CASE WHEN pk.column_name IS NOT NULL THEN 'YES' ELSE 'NO' END AS is_pk, - \(identityProjection), - \(generatedProjection), - c.udt_schema, - \(generationExpressionProjection) + \(identityProjection) AS identity_kind, + \(generatedProjection) AS generated_kind, + c.udt_schema AS udt_schema, + \(generationExpressionProjection) AS generation_expression, + c.ordinal_position AS ordinal_position FROM information_schema.columns c LEFT JOIN pg_catalog.pg_namespace relns ON relns.nspname = c.table_schema @@ -317,7 +328,109 @@ enum PostgreSQLSchemaQueries { AND rel.relname = c.table_name\(attributeJoin) \(ColumnQueryShape.primaryKeyJoin(schemaLiteral: schemaLiteral, fragments: shape)) WHERE c.table_schema = '\(schemaLiteral)'\(shape.mainTableFilter) - ORDER BY \(shape.orderBy) """ + var arms = [informationSchemaArm] + if includeMaterializedViews { + arms.append( + materializedViewColumnsArm( + schemaLiteral: schemaLiteral, + tableLiteral: tableLiteral, + capabilities: capabilities, + includesTableName: includesTableName + ) + ) + } + let orderBy = includesTableName ? "cols.table_name, cols.ordinal_position" : "cols.ordinal_position" + return """ + SELECT + \(columnsOuterProjection(includesTableName: includesTableName)) + FROM ( + \(arms.joined(separator: "\nUNION ALL\n")) + ) cols + ORDER BY \(orderBy) + """ + } + + /// The order `PostgreSQLPluginDriver.mapPgColumnRow` reads the row in. It maps by position, so + /// this list is the contract between the two arms of `columnsQuery` and the mapper. + /// `ordinal_position` stays inside the derived table, named only by the outer `ORDER BY`. + private static func columnsOuterProjection(includesTableName: Bool) -> String { + let columns = (includesTableName ? ["cols.table_name"] : []) + [ + "cols.column_name", + "cols.data_type", + "cols.is_nullable", + "cols.column_default", + "cols.collation_name", + "cols.column_comment", + "cols.udt_name", + "cols.is_pk", + "cols.identity_kind", + "cols.generated_kind", + "cols.udt_schema", + "cols.generation_expression" + ] + return columns.joined(separator: ",\n ") + } + + /// A materialized view's columns, built from `information_schema.columns`' own expressions so a + /// matview column reaches `PostgresColumnTypeResolver` with the same `data_type`, `udt_name` and + /// `udt_schema` a table column does. The `NULL` typmod in `format_type` is deliberate: + /// `information_schema` also spells `numeric(10,2)` as `numeric`, and diverging here would + /// classify one column two different ways depending on which relation it sits in. + /// + /// There is no `pg_attrdef` join and no primary key lookup because PostgreSQL gives a + /// materialized view column neither a default nor a constraint. + private static func materializedViewColumnsArm( + schemaLiteral: String, + tableLiteral: String?, + capabilities: PostgreSQLCapabilities, + includesTableName: Bool + ) -> String { + let tableNameProjection = includesTableName ? "mvc.relname AS table_name,\n " : "" + let tableFilter = tableLiteral.map { "\n AND mvc.relname = '\($0)'" } ?? "" + let identityProjection = capabilities.hasIdentityColumns ? "mva.attidentity" : "NULL::text" + let generatedProjection = capabilities.hasGeneratedColumns ? "mva.attgenerated" : "NULL::text" + return """ + SELECT + \(tableNameProjection)mva.attname AS column_name, + CASE WHEN mvt.typtype = 'd' + THEN CASE WHEN mvbt.typelem <> 0 AND mvbt.typlen = -1 THEN 'ARRAY' + WHEN mvbtn.nspname = 'pg_catalog' THEN pg_catalog.format_type(mvt.typbasetype, NULL) + ELSE 'USER-DEFINED' END + ELSE CASE WHEN mvt.typelem <> 0 AND mvt.typlen = -1 THEN 'ARRAY' + WHEN mvtn.nspname = 'pg_catalog' THEN pg_catalog.format_type(mva.atttypid, NULL) + ELSE 'USER-DEFINED' END + END AS data_type, + CASE WHEN mva.attnotnull OR (mvt.typtype = 'd' AND mvt.typnotnull) THEN 'NO' ELSE 'YES' END AS is_nullable, + NULL::text AS column_default, + CASE WHEN mvcon.nspname <> 'pg_catalog' OR mvco.collname <> 'default' THEN mvco.collname END AS collation_name, + pg_catalog.col_description(mvc.oid, mva.attnum) AS column_comment, + COALESCE(mvbt.typname, mvt.typname) AS udt_name, + 'NO' AS is_pk, + \(identityProjection) AS identity_kind, + \(generatedProjection) AS generated_kind, + COALESCE(mvbtn.nspname, mvtn.nspname) AS udt_schema, + NULL::text AS generation_expression, + mva.attnum AS ordinal_position + FROM pg_catalog.pg_class mvc + JOIN pg_catalog.pg_namespace mvn ON mvn.oid = mvc.relnamespace + JOIN pg_catalog.pg_attribute mva + ON mva.attrelid = mvc.oid + AND mva.attnum > 0 + AND NOT mva.attisdropped + JOIN pg_catalog.pg_type mvt ON mvt.oid = mva.atttypid + JOIN pg_catalog.pg_namespace mvtn ON mvtn.oid = mvt.typnamespace + LEFT JOIN pg_catalog.pg_type mvbt + ON mvt.typtype = 'd' + AND mvbt.oid = mvt.typbasetype + LEFT JOIN pg_catalog.pg_namespace mvbtn ON mvbtn.oid = mvbt.typnamespace + LEFT JOIN pg_catalog.pg_collation mvco ON mvco.oid = mva.attcollation + LEFT JOIN pg_catalog.pg_namespace mvcon ON mvcon.oid = mvco.collnamespace + WHERE mvc.relkind = 'm' + AND mvn.nspname = '\(schemaLiteral)'\(tableFilter) + AND NOT pg_catalog.pg_is_other_temp_schema(mvn.oid) + AND (pg_catalog.pg_has_role(mvc.relowner, 'USAGE') + OR pg_catalog.has_column_privilege(mvc.oid, mva.attnum, 'SELECT, INSERT, UPDATE, REFERENCES')) + """ } } diff --git a/TableProTests/Plugins/PostgreSQLColumnQueryTests.swift b/TableProTests/Plugins/PostgreSQLColumnQueryTests.swift index f21e85ffe3..6903d8d643 100644 --- a/TableProTests/Plugins/PostgreSQLColumnQueryTests.swift +++ b/TableProTests/Plugins/PostgreSQLColumnQueryTests.swift @@ -19,11 +19,21 @@ struct PostgreSQLColumnsQueryTests { private let legacy = PostgreSQLCapabilities(serverVersion: 90_100) private func singleTable(schema: String, table: String) -> String { - PostgreSQLSchemaQueries.columnsQuery(schemaLiteral: schema, tableLiteral: table, capabilities: modern) + PostgreSQLSchemaQueries.columnsQuery( + schemaLiteral: schema, + tableLiteral: table, + capabilities: modern, + includeMaterializedViews: true + ) } private func allTables(schema: String) -> String { - PostgreSQLSchemaQueries.columnsQuery(schemaLiteral: schema, tableLiteral: nil, capabilities: legacy) + PostgreSQLSchemaQueries.columnsQuery( + schemaLiteral: schema, + tableLiteral: nil, + capabilities: legacy, + includeMaterializedViews: false + ) } @Test("single-table query filters on the requested schema and table") @@ -49,17 +59,19 @@ struct PostgreSQLColumnsQueryTests { func singleTableOmitsTableNameColumn() { let query = singleTable(schema: "s2", table: "orders") #expect(!query.contains("c.table_name,")) - #expect(query.contains("ORDER BY c.ordinal_position")) + #expect(query.contains("ORDER BY cols.ordinal_position")) + #expect(!query.contains("ORDER BY c.ordinal_position")) #expect(query.contains("pk ON c.column_name = pk.column_name")) } @Test("all-tables query selects table_name, drops the table filter, and orders by table") func allTablesProjectsTableName() { let query = allTables(schema: "s2") - #expect(query.contains("c.table_name,")) + #expect(query.contains("c.table_name AS table_name,")) #expect(query.contains("WHERE c.table_schema = 's2'")) #expect(!query.contains("c.table_name = '")) - #expect(query.contains("ORDER BY c.table_name, c.ordinal_position")) + #expect(query.contains("ORDER BY cols.table_name, cols.ordinal_position")) + #expect(!query.contains("ORDER BY c.table_name, c.ordinal_position")) #expect(query.contains("pk ON c.table_name = pk.table_name AND c.column_name = pk.column_name")) } @@ -99,6 +111,142 @@ struct PostgreSQLColumnsQueryTests { } } +@Suite("PostgreSQLSchemaQueries.columnsQuery materialized views") +struct PostgreSQLMaterializedViewColumnsQueryTests { + private let modern = PostgreSQLCapabilities(serverVersion: 170_000) + private let legacy = PostgreSQLCapabilities(serverVersion: 90_100) + + private static let armMarkers = [ + "UNION ALL", + "mvc.relkind = 'm'", + "pg_catalog.pg_attribute mva", + "pg_catalog.format_type" + ] + + private static let outerColumns = [ + "cols.column_name", + "cols.data_type", + "cols.is_nullable", + "cols.column_default", + "cols.collation_name", + "cols.column_comment", + "cols.udt_name", + "cols.is_pk", + "cols.identity_kind", + "cols.generated_kind", + "cols.udt_schema", + "cols.generation_expression" + ] + + private func query( + schema: String = "s2", + table: String? = "orders", + capabilities: PostgreSQLCapabilities? = nil, + includeMaterializedViews: Bool = true + ) -> String { + PostgreSQLSchemaQueries.columnsQuery( + schemaLiteral: schema, + tableLiteral: table, + capabilities: capabilities ?? modern, + includeMaterializedViews: includeMaterializedViews + ) + } + + @Test("the materialized view arm appears only when the catalog has materialized views") + func armFollowsTheFlag() { + let included = query() + let excluded = query(includeMaterializedViews: false) + for marker in Self.armMarkers { + #expect(included.contains(marker)) + #expect(!excluded.contains(marker)) + } + } + + @Test("the outer projection is exactly the order the row mapper reads") + func outerProjectionMatchesMapperOrder() { + let singleTable = query() + #expect(singleTable.contains("SELECT\n \(Self.outerColumns.joined(separator: ",\n "))\nFROM (")) + let allTables = query(table: nil) + let withTableName = ["cols.table_name"] + Self.outerColumns + #expect(allTables.contains("SELECT\n \(withTableName.joined(separator: ",\n "))\nFROM (")) + for rendered in [singleTable, allTables] { + #expect(!rendered.contains("cols.ordinal_position,")) + } + } + + @Test("ordering carries through the union on the derived table's ordinal") + func orderingCarriesThroughTheUnion() { + #expect(query().contains("ORDER BY cols.ordinal_position")) + #expect(query(table: nil).contains("ORDER BY cols.table_name, cols.ordinal_position")) + } + + @Test("the arm is scoped to the same schema and table as the information_schema arm", + arguments: ["s2", "analytics", "public"]) + func armIsScopedLikeTheBase(schema: String) { + let singleTable = query(schema: schema) + #expect(singleTable.contains("mvn.nspname = '\(schema)'")) + #expect(singleTable.contains("mvc.relname = 'orders'")) + let allTables = query(schema: schema, table: nil) + #expect(allTables.contains("mvc.relname AS table_name")) + #expect(!allTables.contains("mvc.relname = '")) + } + + @Test("a materialized view column has no primary key and no default") + func armSkipsConstraintsAndDefaults() { + let rendered = query() + #expect(rendered.contains("'NO' AS is_pk")) + #expect(rendered.contains("NULL::text AS column_default")) + #expect(!rendered.contains("pg_attrdef")) + #expect(rendered.components(separatedBy: "information_schema.table_constraints").count - 1 == 1) + } + + @Test("identity and generated mirror the capability switches the base arm uses") + func armMirrorsCapabilitySwitches() { + let modernQuery = query() + #expect(modernQuery.contains("mva.attidentity AS identity_kind")) + #expect(modernQuery.contains("mva.attgenerated AS generated_kind")) + let legacyQuery = query(capabilities: legacy) + #expect(legacyQuery.contains("mvc.relkind = 'm'")) + #expect(!legacyQuery.contains("mva.attidentity")) + #expect(!legacyQuery.contains("mva.attgenerated")) + } + + @Test("type names are spelled the way information_schema spells them, without a typmod") + func armSpellsTypesLikeInformationSchema() { + let rendered = query() + #expect(rendered.contains("pg_catalog.format_type(mva.atttypid, NULL)")) + #expect(rendered.contains("pg_catalog.format_type(mvt.typbasetype, NULL)")) + #expect(!rendered.contains("atttypmod")) + } + + @Test("a domain resolves to its base type, as information_schema does") + func armResolvesDomainsToBaseTypes() { + let rendered = query() + #expect(rendered.contains("mvt.typtype = 'd'")) + #expect(rendered.contains("mvbt.oid = mvt.typbasetype")) + #expect(rendered.contains("COALESCE(mvbt.typname, mvt.typname) AS udt_name")) + #expect(rendered.contains("COALESCE(mvbtn.nspname, mvtn.nspname) AS udt_schema")) + } + + @Test("the default collation is reported as absent rather than as a collation named default") + func armSuppressesTheDefaultCollation() { + let rendered = query() + #expect(rendered.contains( + "CASE WHEN mvcon.nspname <> 'pg_catalog' OR mvco.collname <> 'default' " + + "THEN mvco.collname END AS collation_name" + )) + } + + @Test("the arm carries the comment source and the visibility filters information_schema applies") + func armKeepsCommentsAndPrivileges() { + let rendered = query() + #expect(rendered.contains("pg_catalog.col_description(mvc.oid, mva.attnum) AS column_comment")) + #expect(rendered.contains("pg_catalog.pg_has_role(mvc.relowner")) + #expect(rendered.contains("pg_catalog.has_column_privilege(mvc.oid")) + #expect(rendered.contains("NOT pg_catalog.pg_is_other_temp_schema(mvn.oid)")) + } +} + @Suite("RedshiftSchemaQueries.columnsQuery") struct RedshiftColumnsQueryTests { @Test("single-table query filters on the requested schema and table") @@ -134,4 +282,13 @@ struct RedshiftColumnsQueryTests { #expect(query.contains("AND tc.table_name = kcu.table_name")) } } + + @Test("Redshift keeps a single-arm read and never names relkind") + func redshiftKeepsASingleArmRead() { + for table in ["orders", nil] { + let query = RedshiftSchemaQueries.columnsQuery(schemaLiteral: "s2", tableLiteral: table) + #expect(!query.contains("UNION ALL")) + #expect(!query.contains("relkind")) + } + } } From 3d69ab597e949e13a1c21ab9b4fc45991f595a36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 08:59:05 +0700 Subject: [PATCH 34/54] refactor(settings)!: rebuild the theme engine on a slot registry with a schema gate (#2775) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ngô Quốc Đạt --- CHANGELOG.md | 17 + CLAUDE.md | 3 +- ...SourceEditorConfiguration+Appearance.swift | 7 +- .../Theme/EditorTheme.swift | 6 + TablePro/AppDelegate.swift | 2 +- TablePro/Core/Events/AppEvents.swift | 6 +- ...nSplitViewController+ViewMenuActions.swift | 12 +- .../Core/Storage/AppSettingsManager.swift | 33 +- .../Core/Storage/AppSettingsStorage.swift | 25 + TablePro/Core/Vim/VimCursorManager.swift | 2 +- TablePro/Core/Vim/VimTextBufferAdapter.swift | 2 +- .../Models/Settings/LegacyThemeFonts.swift | 67 +++ .../Models/Settings/TypographySettings.swift | 62 ++ .../Themes/tablepro.default-dark.json | 53 -- .../Themes/tablepro.default-light.json | 53 -- .../Resources/Themes/tablepro.dracula.json | 122 ++-- TablePro/Resources/Themes/tablepro.nord.json | 122 ++-- TablePro/Theme/BuiltInThemes.swift | 127 ++++ TablePro/Theme/HexColor.swift | 68 --- TablePro/Theme/ResolvedThemeColors.swift | 265 --------- TablePro/Theme/ThemeCatalog.swift | 284 +++++++++ TablePro/Theme/ThemeColorValue.swift | 194 +++++++ TablePro/Theme/ThemeColors.swift | 397 ------------- TablePro/Theme/ThemeDefinition.swift | 306 +++++++--- TablePro/Theme/ThemeDocument.swift | 200 +++++++ TablePro/Theme/ThemeEngine.swift | 543 ++++++------------ TablePro/Theme/ThemeFonts.swift | 42 -- TablePro/Theme/ThemeLoadError.swift | 55 ++ TablePro/Theme/ThemePalette.swift | 134 +++++ TablePro/Theme/ThemeRegistryInstaller.swift | 87 ++- TablePro/Theme/ThemeResolver.swift | 68 +++ TablePro/Theme/ThemeSlotValidation.swift | 27 - TablePro/Theme/ThemeStorage.swift | 258 --------- .../Views/Compare/CompareStatusStyle.swift | 34 +- .../Components/HighlightedSQLTextView.swift | 85 +-- .../Editor/Folding/FoldPreviewView.swift | 2 +- .../Editor/History/HistoryDetailPane.swift | 2 +- TablePro/Views/Editor/SQLEditorView.swift | 8 +- TablePro/Views/Import/SQLCodePreview.swift | 3 + TablePro/Views/Results/CellOverlayBase.swift | 16 +- .../Cells/DataGridCellAppearance.swift | 2 +- .../Results/Cells/DataGridCellPalette.swift | 22 +- .../Results/Cells/DataGridCellRenderer.swift | 2 +- .../Views/Results/DataGridBodyChrome.swift | 8 +- .../Views/Results/DataGridCoordinator.swift | 2 + TablePro/Views/Results/DataGridRowView.swift | 18 +- TablePro/Views/Results/DataGridView.swift | 4 +- .../Views/Results/SortableHeaderCell.swift | 4 +- .../Views/Results/SortableHeaderChrome.swift | 6 +- .../RowInspector/JSON/JSONRowColors.swift | 14 +- .../JSON/JSONRowInspectorView.swift | 2 +- .../Appearance/ThemeEditorColorsSection.swift | 340 +++-------- .../Appearance/ThemeEditorFontsSection.swift | 135 ----- .../Settings/Appearance/ThemeEditorView.swift | 96 ++-- .../Settings/Appearance/ThemeListView.swift | 263 +++++---- .../Settings/AppearanceSettingsView.swift | 2 +- .../Settings/DataResultsSettingsView.swift | 6 +- .../Views/Settings/EditorSettingsView.swift | 7 +- .../Settings/Sections/TypographySection.swift | 64 +++ .../Settings/SettingsWindowController.swift | 8 +- .../Views/Settings/ThemePreviewCard.swift | 36 +- TablePro/Views/Structure/DDLTextView.swift | 3 + .../Views/Structure/TriggerEditorView.swift | 3 + .../BundledThemeStatementHighlightTests.swift | 67 --- .../Theme/DataGridThemeColorsTests.swift | 235 -------- .../Theme/ThemeDefinitionTests.swift | 207 ------- TableProTests/Theme/ThemeDocumentTests.swift | 181 ++++++ .../Theme/ThemeSlotCoverageTests.swift | 115 ++++ .../Theme/ThemeSlotValidationTests.swift | 57 +- TableProTests/Theme/ValueFontTests.swift | 27 +- .../Editor/SyntaxHighlightingTests.swift | 6 +- .../Results/DataGridCellAppearanceTests.swift | 4 +- .../DataGridRowNumberRenderingTests.swift | 15 +- .../Results/DataGridRowTintThemeTests.swift | 37 +- docs/customization/appearance.mdx | 73 ++- docs/customization/data-settings.mdx | 12 +- docs/customization/editor-settings.mdx | 16 +- docs/customization/settings.mdx | 5 +- docs/development/plugin-registry.mdx | 4 +- docs/features/overview.mdx | 2 +- docs/features/sql-editor.mdx | 4 +- 81 files changed, 2769 insertions(+), 3144 deletions(-) create mode 100644 TablePro/Models/Settings/LegacyThemeFonts.swift create mode 100644 TablePro/Models/Settings/TypographySettings.swift delete mode 100644 TablePro/Resources/Themes/tablepro.default-dark.json delete mode 100644 TablePro/Resources/Themes/tablepro.default-light.json create mode 100644 TablePro/Theme/BuiltInThemes.swift delete mode 100644 TablePro/Theme/HexColor.swift delete mode 100644 TablePro/Theme/ResolvedThemeColors.swift create mode 100644 TablePro/Theme/ThemeCatalog.swift create mode 100644 TablePro/Theme/ThemeColorValue.swift delete mode 100644 TablePro/Theme/ThemeColors.swift create mode 100644 TablePro/Theme/ThemeDocument.swift delete mode 100644 TablePro/Theme/ThemeFonts.swift create mode 100644 TablePro/Theme/ThemeLoadError.swift create mode 100644 TablePro/Theme/ThemePalette.swift create mode 100644 TablePro/Theme/ThemeResolver.swift delete mode 100644 TablePro/Theme/ThemeSlotValidation.swift delete mode 100644 TablePro/Theme/ThemeStorage.swift delete mode 100644 TablePro/Views/Settings/Appearance/ThemeEditorFontsSection.swift create mode 100644 TablePro/Views/Settings/Sections/TypographySection.swift delete mode 100644 TableProTests/Theme/BundledThemeStatementHighlightTests.swift delete mode 100644 TableProTests/Theme/DataGridThemeColorsTests.swift delete mode 100644 TableProTests/Theme/ThemeDefinitionTests.swift create mode 100644 TableProTests/Theme/ThemeDocumentTests.swift create mode 100644 TableProTests/Theme/ThemeSlotCoverageTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index f0d8ca62c3..c0d5920e73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Warnings in the SQL editor for full-width punctuation, curly quotes and non-ASCII spaces. (#2717) - Highlight rules that color data grid rows or cells by value. (#2723) - **Encoding** option for MySQL and MariaDB connections, with **UTF-8 via Latin 1** for databases written through a Latin 1 client. (#2725) +- Header, grid line, selection and focus colors in the theme editor. +- Themes that name a system color for a slot, so the built-in themes keep the system's own contrast settings. +- Reason shown in Settings > Appearance for a theme file that could not be loaded. - **Refresh Materialized View…** on PostgreSQL, with a concurrent refresh where the view qualifies. (#2726) - **Show DDL** and **Copy DDL** for views and materialized views. (#2726) - **Edit Comment…** for PostgreSQL tables, views, materialized views and foreign tables. (#2726) @@ -40,11 +43,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - First-launch tour replaced by a one-page welcome sheet, shown again from Help > Getting Started. - Beancount connections held at Safe Mode Read-Only. (#2030) - MySQL sessions on the server's default `utf8mb4` collation. +- Theme file format 2. Themes written for earlier versions are not read and need to be recreated. +- Editor Font and Data Grid Font moved to Settings > Editor and Settings > Data & Results, and kept per Mac. +- Editor font size range of 10 to 24 points everywhere, including zoom. - Structure editor options the connected PostgreSQL server does not support left out: generated columns before 12, BRIN before 9.5, and the MySQL-only FULLTEXT and SPATIAL index types. ### Removed - Focus Border color in the theme editor. +- Interface, Sidebar and Toolbar color groups from the theme editor and the theme file. +- Fonts from the theme file. ### Fixed @@ -52,6 +60,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Discard restoring a different row than the one edited under a column value filter. - Add Row under a column value filter selecting and opening the wrong row for editing. - Data grid ignoring the theme's background, text, alternate row, NULL, boolean and row number colors. +- Interface, Sidebar and Toolbar colors having no effect anywhere in the app. +- Line Number color having no effect on the editor gutter. +- Default Light used for the dark theme when the chosen dark theme could not be loaded. +- Editor zoom lost on the next appearance or theme change. +- DDL, trigger and SQL import previews keeping the previous theme's colors. +- Query history preview ignoring the theme and the editor font. +- Theme editor changing the active theme instead of the theme selected for the slot being edited. +- Malformed theme files loading as Default Light under their own name. +- Color with a typo in it rendering as a different color instead of being reported. - Text past the first 64 KB of a UTF-16 SQL import arriving byte-swapped. - SQL import failing on a file whose encoding is not UTF-8 when a character lands on a 64 KB boundary. - Garbled non-Latin text saved from iPhone and iPad to MySQL servers that force a Latin 1 session. (#2725) diff --git a/CLAUDE.md b/CLAUDE.md index cd23f38fec..8e61f7bed2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -153,7 +153,7 @@ When adding a new method to the driver protocol: add to `PluginDatabaseDriver` ( ### Editor Architecture (CodeEditSourceEditor) -- **`ThemeEngine`**: the `@Observable` singleton that owns the active theme, and the single source of truth for editor colors and fonts +- **`ThemeEngine`**: the `@Observable` singleton that owns the active palette and the font caches. The catalog is `ThemeCatalog`, the choice is `ThemeResolver` (pure), and the file format is `ThemeDocument`. Colors come in two tiers: `palette` holds one `NSColor(name:dynamicProvider:)` per slot, which answers for the appearance a view is drawing in, and `resolved` is a static snapshot for the consumers that bake a color (`EditorTheme`, `CALayer`, the grid's per-cell draw path). Fonts are settings, not theme - **Two font domains, and a control never names a third**: `editorFonts` is the Editor Font setting and belongs to a view that also wears the editor's background, text color and syntax palette (the SQL editor, `JSONCodeEditor`, the fold and import previews). Every control that shows or edits a stored *value* takes `ThemeEngine.valueFont` / `valueFontSwiftUI`, which is the Data Grid Font setting, so one value reads the same in the grid cell, its inline editor, the row inspector, a cell popover and a pop-out window. Naming a system text style instead is the defect: it looks right only while the user leaves both settings equal, which is the default, so it ships invisibly (#2393). The inspector sets it once for the whole editor subtree in `InspectorFieldRow`, past the field label and the value menu, so a new field editor inherits it. The switch that decides it is exhaustive over `FieldEditorKind` on purpose: two `default`-armed switches are what let `.typePicker` escape the domain and render a structure row's Name and Type in two different fonts. AppKit will not honour it on a `Picker(.menu)`'s items, which `NSMenu` draws itself; that is the one place the rule stops. - **`TableProEditorTheme`**: adapter to CodeEdit's `EditorTheme` protocol; `ThemeEngine.makeEditorTheme()` builds it - **`CompletionEngine`**: framework-agnostic; **`QueryCompletionAdapter`** bridges to CodeEdit's `CodeSuggestionDelegate` @@ -260,6 +260,7 @@ Four rules follow. A statement whose *answer* is session-scoped is not replayabl | History drawer state | UserDefaults | `HistoryPanelPreferencesStorage` (per connection; visibility, connection scope, source/date/outcome filters; device-local). Live value held in `HistoryPanelState.forConnection`, cleared alongside `SharedSidebarState` when a session ends. | | Trusted external links | UserDefaults | `ExternalConnectionTrustStore` (keyed by database type + host + database + username + URL `name`, never the port; loopback hosts only, enforced on read and write). Consulted by `ExternalConnectionGate` before the external-URL confirmation alert. | | Last backup folder | UserDefaults | `PreferenceKeys.lastBackupDirectory` (one path, app-wide; device-local). Read by the Backup Dump sheet, which falls back to Downloads when the path no longer names a folder. | +| Editor and grid fonts | UserDefaults | `TypographySettings` (family and size for both domains, 10 to 24 pt; device-local, never synced). Sync replaces a settings category wholesale on apply, so a Mac on an older build would reset them, and zoom would push a record per keypress. | | Table load timings | JSON lines | `TableLoadHistoryStore` (`TableLoadHistory.jsonl`, mode `0600`; 7 days, 10,000 records or 5 MB, oldest first; device-local, never uploaded). Written by `TableLoadTracer` through `TableLoadSummarySink`, which is inert under XCTest. Durations and coarse buckets only: no table, schema, host, username, connection id, query text or error message. | ### Logging & Debugging diff --git a/LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/SourceEditorConfiguration/SourceEditorConfiguration+Appearance.swift b/LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/SourceEditorConfiguration/SourceEditorConfiguration+Appearance.swift index 65af0514c5..81e38528a1 100644 --- a/LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/SourceEditorConfiguration/SourceEditorConfiguration+Appearance.swift +++ b/LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/SourceEditorConfiguration/SourceEditorConfiguration+Appearance.swift @@ -163,10 +163,11 @@ extension SourceEditorConfiguration { (controller.textView as? SourceEditorTextView)?.statementHighlightColor = theme.statementHighlight - controller.gutterView.textColor = theme.text.color.withAlphaComponent(0.35) - controller.gutterView.statementRunRibbon.glyphColor = theme.text.color.withAlphaComponent(0.35) + let gutterColor = theme.lineNumber ?? theme.text.color.withAlphaComponent(0.35) + controller.gutterView.textColor = gutterColor + controller.gutterView.statementRunRibbon.glyphColor = gutterColor controller.gutterView.statementRunRibbon.hoveredGlyphColor = theme.text.color - controller.gutterView.foldingRibbon.chevronColor = theme.text.color.withAlphaComponent(0.35) + controller.gutterView.foldingRibbon.chevronColor = gutterColor controller.gutterView.foldingRibbon.collapsedChevronColor = theme.text.color.withAlphaComponent(0.65) controller.gutterView.foldingRibbon.hoveredChevronColor = theme.text.color controller.gutterView.foldingRibbon.foldExtentColor = theme.text.color.withAlphaComponent(0.2) diff --git a/LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/Theme/EditorTheme.swift b/LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/Theme/EditorTheme.swift index c408e822de..89b2838275 100644 --- a/LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/Theme/EditorTheme.swift +++ b/LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/Theme/EditorTheme.swift @@ -35,6 +35,10 @@ public struct EditorTheme: Equatable { public var statementHighlight: NSColor public var selection: NSColor + + /// The gutter's line numbers. `nil` keeps the derived look: the text colour at 35% alpha. + public var lineNumber: NSColor? + public var keywords: Attribute public var commands: Attribute public var types: Attribute @@ -56,6 +60,7 @@ public struct EditorTheme: Equatable { lineHighlight: NSColor, statementHighlight: NSColor = .clear, selection: NSColor, + lineNumber: NSColor? = nil, keywords: Attribute, commands: Attribute, types: Attribute, @@ -76,6 +81,7 @@ public struct EditorTheme: Equatable { self.lineHighlight = lineHighlight self.statementHighlight = statementHighlight self.selection = selection + self.lineNumber = lineNumber self.keywords = keywords self.commands = commands self.types = types diff --git a/TablePro/AppDelegate.swift b/TablePro/AppDelegate.swift index 88ec99047b..d1128c15f8 100644 --- a/TablePro/AppDelegate.swift +++ b/TablePro/AppDelegate.swift @@ -66,7 +66,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { /// Only a screenshot run overrides the mode, so only a screenshot run resolves it twice. if let screenshotMode = ScreenshotEnvironment.appearanceMode { let appearanceSettings = AppSettingsManager.shared.appearance - ThemeEngine.shared.updateAppearanceAndTheme( + ThemeEngine.shared.apply( mode: screenshotMode, lightThemeId: appearanceSettings.preferredLightThemeId, darkThemeId: appearanceSettings.preferredDarkThemeId diff --git a/TablePro/Core/Events/AppEvents.swift b/TablePro/Core/Events/AppEvents.swift index dd2590173a..36abb193f3 100644 --- a/TablePro/Core/Events/AppEvents.swift +++ b/TablePro/Core/Events/AppEvents.swift @@ -13,7 +13,11 @@ final class AppEvents { // MARK: - Theme & Accessibility - let themeChanged = PassthroughSubject() + /// Carries the palette revision and the effective appearance. A consumer that snapshots + /// colours or fonts needs both: a forced Light/Dark switch never changes the theme, and a + /// theme switch never changes the appearance. Subscribing reaches a view that is alive but + /// detached from every window, which a walk of the window tree would miss. + let themeChanged = PassthroughSubject() let accessibilityTextSizeChanged = PassthroughSubject() diff --git a/TablePro/Core/Services/Infrastructure/MainSplitViewController+ViewMenuActions.swift b/TablePro/Core/Services/Infrastructure/MainSplitViewController+ViewMenuActions.swift index 882d26cfbb..f454ac4ce5 100644 --- a/TablePro/Core/Services/Infrastructure/MainSplitViewController+ViewMenuActions.swift +++ b/TablePro/Core/Services/Infrastructure/MainSplitViewController+ViewMenuActions.swift @@ -100,10 +100,18 @@ extension MainSplitViewController { } @objc func increaseEditorTextSize(_ sender: Any?) { - ThemeEngine.shared.adjustEditorFontSize(by: 1) + adjustEditorTextSize(by: 1) } @objc func decreaseEditorTextSize(_ sender: Any?) { - ThemeEngine.shared.adjustEditorFontSize(by: -1) + adjustEditorTextSize(by: -1) + } + + private func adjustEditorTextSize(by delta: Int) { + var typography = AppSettingsManager.shared.typography + let size = TypographySettings.clamp(typography.editorFontSize + delta) + guard size != typography.editorFontSize else { return } + typography.editorFontSize = size + AppSettingsManager.shared.typography = typography } } diff --git a/TablePro/Core/Storage/AppSettingsManager.swift b/TablePro/Core/Storage/AppSettingsManager.swift index 37c77c8234..98f6d6947f 100644 --- a/TablePro/Core/Storage/AppSettingsManager.swift +++ b/TablePro/Core/Storage/AppSettingsManager.swift @@ -26,7 +26,7 @@ final class AppSettingsManager { var appearance: AppearanceSettings { didSet { storage.saveAppearance(appearance) - themeEngine.updateAppearanceAndTheme( + themeEngine.apply( mode: appearance.appearanceMode, lightThemeId: appearance.preferredLightThemeId, darkThemeId: appearance.preferredDarkThemeId @@ -38,19 +38,21 @@ final class AppSettingsManager { var editor: EditorSettings { didSet { storage.saveEditor(editor) - themeEngine.updateEditorSettings( - highlightCurrentLine: editor.highlightCurrentLine, - highlightCurrentStatement: editor.highlightCurrentStatement, - showLineNumbers: editor.showLineNumbers, - tabWidth: editor.clampedTabWidth, - - wordWrap: editor.wordWrap - ) appEvents.editorSettingsChanged.send(()) syncTracker.markDirty(.settings, id: AppSettingsCategory.editor) } } + /// Device-local: it is deliberately absent from `AppSettingsCategory.synced`, so a zoom press + /// never pushes an iCloud record and a Mac on an older build cannot reset it. + var typography: TypographySettings { + didSet { + guard typography != oldValue else { return } + storage.saveTypography(typography) + themeEngine.apply(typography: typography) + } + } + var notifications: NotificationSettings { didSet { guard !isValidating else { return } @@ -242,23 +244,17 @@ final class AppSettingsManager { self.sync = storage.loadSync() self.mcp = storage.loadMCP() self.notifications = storage.loadNotifications() + self.typography = storage.loadTypography() general.language.apply() - themeEngine.updateAppearanceAndTheme( + themeEngine.apply(typography: typography) + themeEngine.apply( mode: appearance.appearanceMode, lightThemeId: appearance.preferredLightThemeId, darkThemeId: appearance.preferredDarkThemeId ) - themeEngine.updateEditorSettings( - highlightCurrentLine: editor.highlightCurrentLine, - highlightCurrentStatement: editor.highlightCurrentStatement, - showLineNumbers: editor.showLineNumbers, - tabWidth: editor.clampedTabWidth, - wordWrap: editor.wordWrap - ) - dateFormattingService.updateFormat(dataGrid.dateFormat) if ai.enabled, ai.providers.contains(where: { $0.type == .copilot }) { @@ -296,6 +292,7 @@ final class AppSettingsManager { ai = .default sync = .default mcp = .default + typography = .default storage.resetToDefaults() } } diff --git a/TablePro/Core/Storage/AppSettingsStorage.swift b/TablePro/Core/Storage/AppSettingsStorage.swift index b3f28ebbce..436f5ba826 100644 --- a/TablePro/Core/Storage/AppSettingsStorage.swift +++ b/TablePro/Core/Storage/AppSettingsStorage.swift @@ -32,6 +32,7 @@ final class AppSettingsStorage: Sendable { static let sync = "com.TablePro.settings.sync" static let mcp = "com.TablePro.settings.mcp" static let notifications = "com.TablePro.settings.notifications" + static let typography = "com.TablePro.settings.typography" static let hasSeenWelcomeSheet = "com.TablePro.settings.hasCompletedOnboarding" static let startupReopenMigration = "com.TablePro.settings.didMigrateStartupToReopenLast" static let jsonFieldHeightMigration = "com.TablePro.settings.didMigrateJsonFieldHeightKey" @@ -85,6 +86,29 @@ final class AppSettingsStorage: Sendable { load(key: Keys.appearance, default: .default) } + /// Fonts moved out of the theme file, and the theme file format they lived in is no longer + /// read. Without this every user who had picked a font or zoomed the editor would silently be + /// returned to System Mono 13 on upgrade, so their sizes are lifted once from whichever theme + /// their slot pointed at, and the theme file itself is left untouched. + func loadTypography() -> TypographySettings { + if let stored = defaults.data(forKey: Keys.typography) { + do { + return try decoder.decode(TypographySettings.self, from: stored) + } catch { + Self.logger.error("Failed to decode typography settings: \(error)") + return .default + } + } + + let carried = LegacyThemeFonts.read(preferring: loadAppearance()) + saveTypography(carried) + return carried + } + + func saveTypography(_ settings: TypographySettings) { + save(settings, key: Keys.typography) + } + func saveAppearance(_ settings: AppearanceSettings) { save(settings, key: Keys.appearance) } @@ -230,6 +254,7 @@ final class AppSettingsStorage: Sendable { saveAI(.default) saveSync(.default) saveMCP(.default) + saveTypography(.default) defaults.removeObject(forKey: PreferenceKeys.selectedSettingsPane.name) defaults.removeObject(forKey: PreferenceKeys.rowInspectorJsonFieldHeight.name) defaults.removeObject(forKey: PreferenceKeys.rowInspectorTextFieldHeight.name) diff --git a/TablePro/Core/Vim/VimCursorManager.swift b/TablePro/Core/Vim/VimCursorManager.swift index 37324754c5..a03c9b0df6 100644 --- a/TablePro/Core/Vim/VimCursorManager.swift +++ b/TablePro/Core/Vim/VimCursorManager.swift @@ -154,7 +154,7 @@ final class VimCursorManager { } else { let layer = CALayer() layer.contentsScale = textView.window?.backingScaleFactor ?? 2.0 - layer.backgroundColor = ThemeEngine.shared.colors.editor.cursor.withAlphaComponent(0.4).cgColor + layer.backgroundColor = ThemeEngine.shared.resolved[.editorCursor].withAlphaComponent(0.4).cgColor layer.frame = frame if !isPaused { diff --git a/TablePro/Core/Vim/VimTextBufferAdapter.swift b/TablePro/Core/Vim/VimTextBufferAdapter.swift index 5747c5e914..acbf3e4934 100644 --- a/TablePro/Core/Vim/VimTextBufferAdapter.swift +++ b/TablePro/Core/Vim/VimTextBufferAdapter.swift @@ -414,7 +414,7 @@ final class VimTextBufferAdapter: VimTextBuffer { } func indentWidth() -> Int { - ThemeEngine.shared.tabWidth + AppSettingsManager.shared.editor.clampedTabWidth } // MARK: - Helpers diff --git a/TablePro/Models/Settings/LegacyThemeFonts.swift b/TablePro/Models/Settings/LegacyThemeFonts.swift new file mode 100644 index 0000000000..4a767deb2f --- /dev/null +++ b/TablePro/Models/Settings/LegacyThemeFonts.swift @@ -0,0 +1,67 @@ +import Foundation +import os + +/// Reads the `fonts` object out of a theme file written before fonts moved into settings. It is +/// the only code that still opens the old format, it runs once, and it writes nothing back: the +/// theme file keeps its own shape and is rejected by the current loader like any other old file. +internal enum LegacyThemeFonts { + private static let logger = Logger(subsystem: "com.TablePro", category: "LegacyThemeFonts") + + private struct Document: Decodable { + struct Fonts: Decodable { + var editorFontFamily: String? + var editorFontSize: Int? + var dataGridFontFamily: String? + var dataGridFontSize: Int? + } + + var fonts: Fonts? + } + + internal static func read(preferring appearance: AppearanceSettings) -> TypographySettings { + let candidates = [appearance.preferredLightThemeId, appearance.preferredDarkThemeId] + + for id in candidates { + guard let fonts = fonts(forThemeId: id) else { continue } + return settings(from: fonts) + } + + return .default + } + + private static func fonts(forThemeId id: String) -> Document.Fonts? { + let directories = [userThemesDirectory, userThemesDirectory.appendingPathComponent("Registry")] + + (Bundle.main.resourceURL.map { [$0] } ?? []) + + for directory in directories { + let url = directory.appendingPathComponent("\(id).json", isDirectory: false) + guard FileManager.default.fileExists(atPath: url.path) else { continue } + + do { + let document = try JSONDecoder().decode(Document.self, from: try Data(contentsOf: url)) + guard let fonts = document.fonts else { continue } + return fonts + } catch { + logger.error("Could not read legacy fonts from \(url.lastPathComponent): \(error)") + } + } + + return nil + } + + private static func settings(from fonts: Document.Fonts) -> TypographySettings { + let fallback = TypographySettings.default + + return TypographySettings( + editorFontFamily: fonts.editorFontFamily ?? fallback.editorFontFamily, + editorFontSize: TypographySettings.clamp(fonts.editorFontSize ?? fallback.editorFontSize), + dataGridFontFamily: fonts.dataGridFontFamily ?? fallback.dataGridFontFamily, + dataGridFontSize: TypographySettings.clamp(fonts.dataGridFontSize ?? fallback.dataGridFontSize) + ) + } + + private static var userThemesDirectory: URL { + AppStorageEnvironment.shared.applicationSupportRoot + .appendingPathComponent("TablePro/Themes", isDirectory: true) + } +} diff --git a/TablePro/Models/Settings/TypographySettings.swift b/TablePro/Models/Settings/TypographySettings.swift new file mode 100644 index 0000000000..dfac2c91ee --- /dev/null +++ b/TablePro/Models/Settings/TypographySettings.swift @@ -0,0 +1,62 @@ +import Foundation + +/// Device-local on purpose. Fonts used to live inside the theme file, so a zoom shortcut rewrote +/// and saved a whole theme. Moving them into a synced settings category would be worse: sync +/// replaces the whole struct on apply, so a Mac still on an older build would push a payload +/// without these keys and reset the fonts on every other Mac, and each zoom press would push a +/// record. The one range here is shared by the pickers, the zoom commands and the font caches; +/// three disagreeing ranges are what let zoom store a size the renderer clamped away. +internal struct TypographySettings: Codable, Equatable, Sendable { + internal var editorFontFamily: String + internal var editorFontSize: Int + internal var dataGridFontFamily: String + internal var dataGridFontSize: Int + + internal static let sizeRange = 10...24 + internal static let systemMonoFamily = "System Mono" + + internal static let `default` = TypographySettings( + editorFontFamily: systemMonoFamily, + editorFontSize: 13, + dataGridFontFamily: systemMonoFamily, + dataGridFontSize: 13 + ) + + internal init( + editorFontFamily: String = systemMonoFamily, + editorFontSize: Int = 13, + dataGridFontFamily: String = systemMonoFamily, + dataGridFontSize: Int = 13 + ) { + self.editorFontFamily = editorFontFamily + self.editorFontSize = editorFontSize + self.dataGridFontFamily = dataGridFontFamily + self.dataGridFontSize = dataGridFontSize + } + + internal init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let fallback = TypographySettings.default + + editorFontFamily = try container.decodeIfPresent(String.self, forKey: .editorFontFamily) + ?? fallback.editorFontFamily + editorFontSize = try container.decodeIfPresent(Int.self, forKey: .editorFontSize) + ?? fallback.editorFontSize + dataGridFontFamily = try container.decodeIfPresent(String.self, forKey: .dataGridFontFamily) + ?? fallback.dataGridFontFamily + dataGridFontSize = try container.decodeIfPresent(Int.self, forKey: .dataGridFontSize) + ?? fallback.dataGridFontSize + } + + internal var clampedEditorFontSize: Int { + Self.clamp(editorFontSize) + } + + internal var clampedDataGridFontSize: Int { + Self.clamp(dataGridFontSize) + } + + internal static func clamp(_ size: Int) -> Int { + min(max(size, sizeRange.lowerBound), sizeRange.upperBound) + } +} diff --git a/TablePro/Resources/Themes/tablepro.default-dark.json b/TablePro/Resources/Themes/tablepro.default-dark.json deleted file mode 100644 index d28e2b4149..0000000000 --- a/TablePro/Resources/Themes/tablepro.default-dark.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "id": "tablepro.default-dark", - "name": "Default Dark", - "version": 1, - "appearance": "dark", - "author": "TablePro", - "editor": { - "background": "#1E1E1E", - "text": "#D4D4D4", - "cursor": "#007AFF", - "currentLineHighlight": "#007AFF14", - "currentStatementHighlight": "#FFFFFF0F", - "selection": "#264F78", - "lineNumber": "#858585", - "invisibles": "#4D4D4D", - "syntax": { - "keyword": "#569CD6", - "string": "#CE9178", - "number": "#B5CEA8", - "comment": "#6A9955", - "null": "#FF8C00", - "operator": "#D4D4D4", - "function": "#DCDCAA", - "type": "#4EC9B0" - } - }, - "dataGrid": { - "modified": "#FFD60A4D", - "inserted": "#32D74B26", - "deleted": "#FF453A26", - "deletedText": "#FF453A80" - }, - "ui": { - "accentColor": null, - "status": { - "success": "#32D74B", - "warning": "#FF9F0A", - "error": "#FF453A", - "info": "#0A84FF" - }, - "badges": { - "background": "#3C3C3C", - "primaryKey": "#0A84FF26", - "autoIncrement": "#BF5AF226" - } - }, - "fonts": { - "editorFontFamily": "System Mono", - "editorFontSize": 13, - "dataGridFontFamily": "System Mono", - "dataGridFontSize": 13 - } -} diff --git a/TablePro/Resources/Themes/tablepro.default-light.json b/TablePro/Resources/Themes/tablepro.default-light.json deleted file mode 100644 index 4de5f91386..0000000000 --- a/TablePro/Resources/Themes/tablepro.default-light.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "id": "tablepro.default-light", - "name": "Default Light", - "version": 1, - "appearance": "light", - "author": "TablePro", - "editor": { - "background": "#FFFFFF", - "text": "#000000", - "cursor": "#007AFF", - "currentLineHighlight": "#007AFF14", - "currentStatementHighlight": "#0A0A0A0F", - "selection": "#B4D8FD", - "lineNumber": "#8E8E93", - "invisibles": "#C7C7CC", - "syntax": { - "keyword": "#0A49A5", - "string": "#C41A16", - "number": "#6C36A9", - "comment": "#007400", - "null": "#C55B00", - "operator": "#000000", - "function": "#326D74", - "type": "#3F6E74" - } - }, - "dataGrid": { - "modified": "#FFD60A4D", - "inserted": "#34C7594D", - "deleted": "#FF3B304D", - "deletedText": "#FF3B3080" - }, - "ui": { - "accentColor": null, - "status": { - "success": "#248A3D", - "warning": "#C55B00", - "error": "#D70015", - "info": "#007AFF" - }, - "badges": { - "background": "#E5E5EA", - "primaryKey": "#007AFF26", - "autoIncrement": "#AF52DE26" - } - }, - "fonts": { - "editorFontFamily": "System Mono", - "editorFontSize": 13, - "dataGridFontFamily": "System Mono", - "dataGridFontSize": 13 - } -} diff --git a/TablePro/Resources/Themes/tablepro.dracula.json b/TablePro/Resources/Themes/tablepro.dracula.json index 083586caf0..70ffe0a603 100644 --- a/TablePro/Resources/Themes/tablepro.dracula.json +++ b/TablePro/Resources/Themes/tablepro.dracula.json @@ -1,80 +1,54 @@ { - "id": "tablepro.dracula", - "name": "Dracula", - "version": 1, - "appearance": "dark", - "author": "TablePro", - "editor": { - "background": "#282A36", - "text": "#F8F8F2", - "cursor": "#F8F8F2", - "currentLineHighlight": "#44475A", - "currentStatementHighlight": "#FFFFFF0F", - "selection": "#44475A", - "lineNumber": "#6272A4", - "invisibles": "#424450", - "syntax": { - "keyword": "#FF79C6", - "string": "#F1FA8C", - "number": "#BD93F9", - "comment": "#6272A4", - "null": "#FFB86C", - "operator": "#FF79C6", - "function": "#50FA7B", - "type": "#8BE9FD" - } - }, + "appearance": "dark", + "author": "TablePro", + "content": { "dataGrid": { - "background": "#282A36", - "text": "#F8F8F2", - "alternateRow": "#21222C", - "nullValue": "#6272A4", - "boolTrue": "#50FA7B", - "boolFalse": "#FF5555", - "rowNumber": "#6272A4", - "modified": "#FFB86C4D", - "inserted": "#50FA7B26", - "deleted": "#FF555526", - "deletedText": "#FF555580" - }, - "ui": { - "windowBackground": "#282A36", - "controlBackground": "#343746", - "cardBackground": "#21222C", - "border": "#44475A", - "primaryText": "#F8F8F2", - "secondaryText": "#BFC0C9", - "tertiaryText": "#6272A4", - "accentColor": "#BD93F9", - "selectionBackground": "#44475A", - "hoverBackground": "#44475A80", - "status": { - "success": "#50FA7B", - "warning": "#FFB86C", - "error": "#FF5555", - "info": "#8BE9FD" - }, - "badges": { - "background": "#44475A", - "primaryKey": "#8BE9FD26", - "autoIncrement": "#BD93F926" - } + "alternateRow": "#21222C", + "background": "#282A36", + "boolFalse": "#FF5555", + "boolTrue": "#50FA7B", + "deleted": "#FF555526", + "deletedText": "#FF555580", + "focusBorder": "#BD93F9", + "gridLine": "#44475A", + "headerBackground": "#21222C", + "headerText": "#F8F8F2", + "inactiveSelection": "#44475A80", + "inserted": "#50FA7B26", + "modified": "#FFB86C4D", + "nullValue": "#6272A4", + "rowNumber": "#6272A4", + "selection": "#44475A", + "selectionText": "#F8F8F2", + "text": "#F8F8F2" }, - "sidebar": { - "background": "#21222C", - "text": "#F8F8F2", - "selectedItem": "#44475A", - "hover": "#343746", - "sectionHeader": "#6272A4" - }, - "toolbar": { - "secondaryText": "#BFC0C9", - "tertiaryText": "#6272A4" + "editor": { + "background": "#282A36", + "currentLine": "#44475A", + "currentStatement": "#FFFFFF0F", + "cursor": "#F8F8F2", + "invisibles": "#424450", + "lineNumber": "#6272A4", + "selection": "#44475A", + "syntax": { + "comment": "#6272A4", + "function": "#50FA7B", + "keyword": "#FF79C6", + "null": "#FFB86C", + "number": "#BD93F9", + "operator": "#FF79C6", + "string": "#F1FA8C", + "type": "#8BE9FD" + }, + "text": "#F8F8F2" }, - "fonts": { - "editorFontFamily": "System Mono", - "editorFontSize": 13, - "dataGridFontFamily": "System Mono", - "dataGridFontSize": 13 + "status": { + "error": "#FF5555", + "success": "#50FA7B", + "warning": "#FFB86C" } + }, + "id": "tablepro.dracula", + "name": "Dracula", + "schema": 2 } diff --git a/TablePro/Resources/Themes/tablepro.nord.json b/TablePro/Resources/Themes/tablepro.nord.json index 7b9c17c916..ef58c5fe3c 100644 --- a/TablePro/Resources/Themes/tablepro.nord.json +++ b/TablePro/Resources/Themes/tablepro.nord.json @@ -1,80 +1,54 @@ { - "id": "tablepro.nord", - "name": "Nord", - "version": 1, - "appearance": "dark", - "author": "TablePro", - "editor": { - "background": "#2E3440", - "text": "#D8DEE9", - "cursor": "#88C0D0", - "currentLineHighlight": "#3B4252", - "currentStatementHighlight": "#FFFFFF0F", - "selection": "#434C5E", - "lineNumber": "#4C566A", - "invisibles": "#3B4252", - "syntax": { - "keyword": "#81A1C1", - "string": "#A3BE8C", - "number": "#B48EAD", - "comment": "#616E88", - "null": "#D08770", - "operator": "#81A1C1", - "function": "#88C0D0", - "type": "#EBCB8B" - } - }, + "appearance": "dark", + "author": "TablePro", + "content": { "dataGrid": { - "background": "#2E3440", - "text": "#D8DEE9", - "alternateRow": "#3B4252", - "nullValue": "#4C566A", - "boolTrue": "#A3BE8C", - "boolFalse": "#BF616A", - "rowNumber": "#4C566A", - "modified": "#EBCB8B4D", - "inserted": "#A3BE8C26", - "deleted": "#BF616A26", - "deletedText": "#BF616A80" - }, - "ui": { - "windowBackground": "#2E3440", - "controlBackground": "#3B4252", - "cardBackground": "#3B4252", - "border": "#434C5E", - "primaryText": "#D8DEE9", - "secondaryText": "#9DA5B4", - "tertiaryText": "#616E88", - "accentColor": "#88C0D0", - "selectionBackground": "#434C5E", - "hoverBackground": "#88C0D00D", - "status": { - "success": "#A3BE8C", - "warning": "#D08770", - "error": "#BF616A", - "info": "#5E81AC" - }, - "badges": { - "background": "#434C5E", - "primaryKey": "#5E81AC26", - "autoIncrement": "#B48EAD26" - } + "alternateRow": "#3B4252", + "background": "#2E3440", + "boolFalse": "#BF616A", + "boolTrue": "#A3BE8C", + "deleted": "#BF616A26", + "deletedText": "#BF616A80", + "focusBorder": "#88C0D0", + "gridLine": "#434C5E", + "headerBackground": "#3B4252", + "headerText": "#D8DEE9", + "inactiveSelection": "#434C5E80", + "inserted": "#A3BE8C26", + "modified": "#EBCB8B4D", + "nullValue": "#4C566A", + "rowNumber": "#4C566A", + "selection": "#434C5E", + "selectionText": "#ECEFF4", + "text": "#D8DEE9" }, - "sidebar": { - "background": "#3B4252", - "text": "#D8DEE9", - "selectedItem": "#434C5E", - "hover": "#434C5E80", - "sectionHeader": "#4C566A" - }, - "toolbar": { - "secondaryText": "#9DA5B4", - "tertiaryText": "#616E88" + "editor": { + "background": "#2E3440", + "currentLine": "#3B4252", + "currentStatement": "#FFFFFF0F", + "cursor": "#88C0D0", + "invisibles": "#3B4252", + "lineNumber": "#4C566A", + "selection": "#434C5E", + "syntax": { + "comment": "#616E88", + "function": "#88C0D0", + "keyword": "#81A1C1", + "null": "#D08770", + "number": "#B48EAD", + "operator": "#81A1C1", + "string": "#A3BE8C", + "type": "#EBCB8B" + }, + "text": "#D8DEE9" }, - "fonts": { - "editorFontFamily": "System Mono", - "editorFontSize": 13, - "dataGridFontFamily": "System Mono", - "dataGridFontSize": 13 + "status": { + "error": "#BF616A", + "success": "#A3BE8C", + "warning": "#D08770" } + }, + "id": "tablepro.nord", + "name": "Nord", + "schema": 2 } diff --git a/TablePro/Theme/BuiltInThemes.swift b/TablePro/Theme/BuiltInThemes.swift new file mode 100644 index 0000000000..61481ad8d6 --- /dev/null +++ b/TablePro/Theme/BuiltInThemes.swift @@ -0,0 +1,127 @@ +import Foundation + +/// Default Light and Default Dark are Swift, not JSON: they are the fallback every other theme is +/// measured against, so they cannot themselves be a file that fails to load. Their surround slots +/// stay on `system:` values, which keeps the unthemed app pixel-identical to before the theme +/// owned these surfaces and keeps the system's Increase Contrast and vibrancy adaptations. +internal enum BuiltInThemes { + internal static let defaultLightId = "tablepro.default-light" + internal static let defaultDarkId = "tablepro.default-dark" + + internal static let light = ThemeDefinition( + id: defaultLightId, + name: String(localized: "Default Light"), + author: "TablePro", + appearance: .light, + editor: EditorThemeColors( + background: .hex("#FFFFFF"), + text: .hex("#000000"), + cursor: .hex("#007AFF"), + selection: .hex("#B4D8FD"), + currentLine: .hex("#007AFF14"), + currentStatement: .hex("#0A0A0A0F"), + lineNumber: .hex("#8E8E93"), + invisibles: .hex("#C7C7CC"), + syntax: SyntaxThemeColors( + keyword: .hex("#0A49A5"), + string: .hex("#C41A16"), + number: .hex("#6C36A9"), + comment: .hex("#007400"), + null: .hex("#C55B00"), + operator: .hex("#000000"), + function: .hex("#326D74"), + type: .hex("#3F6E74") + ) + ), + dataGrid: systemDataGrid( + modified: "#FFD60A4D", + inserted: "#34C7594D", + deleted: "#FF3B304D", + deletedText: "#FF3B3080" + ), + status: StatusThemeColors( + success: .hex("#248A3D"), + warning: .hex("#C55B00"), + error: .hex("#D70015") + ) + ) + + internal static let dark = ThemeDefinition( + id: defaultDarkId, + name: String(localized: "Default Dark"), + author: "TablePro", + appearance: .dark, + editor: EditorThemeColors( + background: .hex("#1E1E1E"), + text: .hex("#D4D4D4"), + cursor: .hex("#007AFF"), + selection: .hex("#264F78"), + currentLine: .hex("#007AFF14"), + currentStatement: .hex("#FFFFFF0F"), + lineNumber: .hex("#858585"), + invisibles: .hex("#4D4D4D"), + syntax: SyntaxThemeColors( + keyword: .hex("#569CD6"), + string: .hex("#CE9178"), + number: .hex("#B5CEA8"), + comment: .hex("#6A9955"), + null: .hex("#FF8C00"), + operator: .hex("#D4D4D4"), + function: .hex("#DCDCAA"), + type: .hex("#4EC9B0") + ) + ), + dataGrid: systemDataGrid( + modified: "#FFD60A4D", + inserted: "#32D74B26", + deleted: "#FF453A26", + deletedText: "#FF453A80" + ), + status: StatusThemeColors( + success: .hex("#32D74B"), + warning: .hex("#FF9F0A"), + error: .hex("#FF453A") + ) + ) + + internal static let all: [ThemeDefinition] = [light, dark] + + internal static func `default`(for appearance: ThemeAppearance) -> ThemeDefinition { + switch appearance { + case .light: return light + case .dark: return dark + } + } + + internal static func defaultId(for appearance: ThemeAppearance) -> String { + `default`(for: appearance).id + } + + private static func systemDataGrid( + modified: String, + inserted: String, + deleted: String, + deletedText: String + ) -> DataGridThemeColors { + DataGridThemeColors( + background: .system(.controlBackground), + text: .system(.label), + alternateRow: .system(.alternatingContentBackgroundOdd), + headerBackground: .system(.windowBackground), + headerText: .system(.label), + gridLine: .system(.grid), + selection: .system(.selectedContentBackground), + selectionText: .system(.alternateSelectedControlText), + inactiveSelection: .system(.unemphasizedSelectedContentBackground), + focusBorder: .system(.keyboardFocusIndicator), + nullValue: .system(.secondaryLabel), + boolTrue: .system(.label), + boolFalse: .system(.label), + rowNumber: .system(.secondaryLabel), + modified: .hex(modified), + inserted: .hex(inserted), + deleted: .hex(deleted), + deletedText: .hex(deletedText) + ) + } +} diff --git a/TablePro/Theme/HexColor.swift b/TablePro/Theme/HexColor.swift deleted file mode 100644 index 5378d3acc9..0000000000 --- a/TablePro/Theme/HexColor.swift +++ /dev/null @@ -1,68 +0,0 @@ -import AppKit -import SwiftUI - -extension String { - var nsColor: NSColor { - let hex = trimmingCharacters(in: .whitespacesAndNewlines) - .trimmingCharacters(in: CharacterSet(charactersIn: "#")) - - let hexLength = (hex as NSString).length - guard hexLength == 6 || hexLength == 8 else { - return .labelColor - } - - var value: UInt64 = 0 - guard Scanner(string: hex).scanHexInt64(&value) else { - return .labelColor - } - - let r, g, b, a: CGFloat - - if hexLength == 8 { - r = CGFloat((value >> 24) & 0xFF) / 255.0 - g = CGFloat((value >> 16) & 0xFF) / 255.0 - b = CGFloat((value >> 8) & 0xFF) / 255.0 - a = CGFloat(value & 0xFF) / 255.0 - } else { - r = CGFloat((value >> 16) & 0xFF) / 255.0 - g = CGFloat((value >> 8) & 0xFF) / 255.0 - b = CGFloat(value & 0xFF) / 255.0 - a = 1.0 - } - - return NSColor(srgbRed: r, green: g, blue: b, alpha: a) - } - - var swiftUIColor: Color { - Color(nsColor: nsColor) - } - - var cgColor: CGColor { - nsColor.cgColor - } -} - -extension NSColor { - var hexString: String { - guard let converted = usingColorSpace(.sRGB) else { - return "#808080" - } - - var r: CGFloat = 0 - var g: CGFloat = 0 - var b: CGFloat = 0 - var a: CGFloat = 0 - converted.getRed(&r, green: &g, blue: &b, alpha: &a) - - let ri = Int(round(r * 255)) - let gi = Int(round(g * 255)) - let bi = Int(round(b * 255)) - - if a < 1.0 { - let ai = Int(round(a * 255)) - return String(format: "#%02X%02X%02X%02X", ri, gi, bi, ai) - } - - return String(format: "#%02X%02X%02X", ri, gi, bi) - } -} diff --git a/TablePro/Theme/ResolvedThemeColors.swift b/TablePro/Theme/ResolvedThemeColors.swift deleted file mode 100644 index 8557126d58..0000000000 --- a/TablePro/Theme/ResolvedThemeColors.swift +++ /dev/null @@ -1,265 +0,0 @@ -import AppKit -import SwiftUI - -struct ResolvedEditorColors { - let background: NSColor - let backgroundSwiftUI: Color - let text: NSColor - let textSwiftUI: Color - let cursor: NSColor - let cursorSwiftUI: Color - let currentLineHighlight: NSColor - let currentLineHighlightSwiftUI: Color - let currentStatementHighlight: NSColor - let selection: NSColor - let selectionSwiftUI: Color - let lineNumber: NSColor - let lineNumberSwiftUI: Color - let invisibles: NSColor - let invisiblesSwiftUI: Color - - let keyword: NSColor - let keywordSwiftUI: Color - let string: NSColor - let stringSwiftUI: Color - let number: NSColor - let numberSwiftUI: Color - let comment: NSColor - let commentSwiftUI: Color - let null: NSColor - let nullSwiftUI: Color - let `operator`: NSColor - let operatorSwiftUI: Color - let function: NSColor - let functionSwiftUI: Color - let type: NSColor - let typeSwiftUI: Color - - init(from colors: EditorThemeColors) { - background = colors.background.nsColor - backgroundSwiftUI = colors.background.swiftUIColor - text = colors.text.nsColor - textSwiftUI = colors.text.swiftUIColor - cursor = colors.cursor.nsColor - cursorSwiftUI = colors.cursor.swiftUIColor - currentLineHighlight = colors.currentLineHighlight.nsColor - currentLineHighlightSwiftUI = colors.currentLineHighlight.swiftUIColor - currentStatementHighlight = colors.currentStatementHighlight.nsColor - selection = colors.selection.nsColor - selectionSwiftUI = colors.selection.swiftUIColor - lineNumber = colors.lineNumber.nsColor - lineNumberSwiftUI = colors.lineNumber.swiftUIColor - invisibles = colors.invisibles.nsColor - invisiblesSwiftUI = colors.invisibles.swiftUIColor - - keyword = colors.syntax.keyword.nsColor - keywordSwiftUI = colors.syntax.keyword.swiftUIColor - string = colors.syntax.string.nsColor - stringSwiftUI = colors.syntax.string.swiftUIColor - number = colors.syntax.number.nsColor - numberSwiftUI = colors.syntax.number.swiftUIColor - comment = colors.syntax.comment.nsColor - commentSwiftUI = colors.syntax.comment.swiftUIColor - null = colors.syntax.null.nsColor - nullSwiftUI = colors.syntax.null.swiftUIColor - `operator` = colors.syntax.operator.nsColor - operatorSwiftUI = colors.syntax.operator.swiftUIColor - function = colors.syntax.function.nsColor - functionSwiftUI = colors.syntax.function.swiftUIColor - type = colors.syntax.type.nsColor - typeSwiftUI = colors.syntax.type.swiftUIColor - } -} - -struct ResolvedDataGridColors { - let background: NSColor - let backgroundSwiftUI: Color - let text: NSColor - let textSwiftUI: Color - let alternateRow: NSColor - let alternateRowSwiftUI: Color - let nullValue: NSColor - let boolTrue: NSColor? - let boolFalse: NSColor? - let rowNumber: NSColor - - let modified: NSColor - let modifiedSwiftUI: Color - let modifiedCG: CGColor - let inserted: NSColor - let insertedSwiftUI: Color - let insertedCG: CGColor - let deleted: NSColor - let deletedSwiftUI: Color - let deletedCG: CGColor - let deletedText: NSColor - let deletedTextSwiftUI: Color - - init(from colors: DataGridThemeColors) { - background = colors.background?.nsColor ?? .controlBackgroundColor - backgroundSwiftUI = colors.background?.swiftUIColor ?? Color(nsColor: .controlBackgroundColor) - text = colors.text?.nsColor ?? .labelColor - textSwiftUI = colors.text?.swiftUIColor ?? Color(nsColor: .labelColor) - alternateRow = colors.alternateRow?.nsColor ?? Self.systemAlternateRow - alternateRowSwiftUI = colors.alternateRow?.swiftUIColor ?? Color(nsColor: Self.systemAlternateRow) - nullValue = colors.nullValue?.nsColor ?? .secondaryLabelColor - boolTrue = colors.boolTrue?.nsColor - boolFalse = colors.boolFalse?.nsColor - rowNumber = colors.rowNumber?.nsColor ?? .secondaryLabelColor - - modified = colors.modified.nsColor - modifiedSwiftUI = colors.modified.swiftUIColor - modifiedCG = colors.modified.cgColor - inserted = colors.inserted.nsColor - insertedSwiftUI = colors.inserted.swiftUIColor - insertedCG = colors.inserted.cgColor - deleted = colors.deleted.nsColor - deletedSwiftUI = colors.deleted.swiftUIColor - deletedCG = colors.deleted.cgColor - deletedText = colors.deletedText.nsColor - deletedTextSwiftUI = colors.deletedText.swiftUIColor - } - - private static var systemAlternateRow: NSColor { - NSColor.alternatingContentBackgroundColors.last ?? .controlBackgroundColor - } -} - -struct ResolvedUIColors { - let windowBackground: NSColor - let windowBackgroundSwiftUI: Color - let controlBackground: NSColor - let controlBackgroundSwiftUI: Color - let cardBackground: NSColor - let cardBackgroundSwiftUI: Color - let border: NSColor - let borderSwiftUI: Color - - let primaryText: NSColor - let primaryTextSwiftUI: Color - let secondaryText: NSColor - let secondaryTextSwiftUI: Color - let tertiaryText: NSColor - let tertiaryTextSwiftUI: Color - - let selectionBackground: NSColor - let selectionBackgroundSwiftUI: Color - let hoverBackground: NSColor - let hoverBackgroundSwiftUI: Color - - let success: NSColor - let successSwiftUI: Color - let warning: NSColor - let warningSwiftUI: Color - let error: NSColor - let errorSwiftUI: Color - let info: NSColor - let infoSwiftUI: Color - - let badgeBackground: NSColor - let badgeBackgroundSwiftUI: Color - let badgePrimaryKey: NSColor - let badgePrimaryKeySwiftUI: Color - let badgeAutoIncrement: NSColor - let badgeAutoIncrementSwiftUI: Color - - init(from colors: UIThemeColors) { - windowBackground = colors.windowBackground?.nsColor ?? .windowBackgroundColor - windowBackgroundSwiftUI = colors.windowBackground?.swiftUIColor ?? Color(nsColor: .windowBackgroundColor) - controlBackground = colors.controlBackground?.nsColor ?? .controlBackgroundColor - controlBackgroundSwiftUI = colors.controlBackground?.swiftUIColor - ?? Color(nsColor: .controlBackgroundColor) - cardBackground = colors.cardBackground?.nsColor ?? .controlBackgroundColor - cardBackgroundSwiftUI = colors.cardBackground?.swiftUIColor ?? Color(nsColor: .controlBackgroundColor) - border = colors.border?.nsColor ?? .separatorColor - borderSwiftUI = colors.border?.swiftUIColor ?? Color(nsColor: .separatorColor) - - primaryText = colors.primaryText?.nsColor ?? .labelColor - primaryTextSwiftUI = colors.primaryText?.swiftUIColor ?? Color(nsColor: .labelColor) - secondaryText = colors.secondaryText?.nsColor ?? .secondaryLabelColor - secondaryTextSwiftUI = colors.secondaryText?.swiftUIColor ?? Color(nsColor: .secondaryLabelColor) - tertiaryText = colors.tertiaryText?.nsColor ?? .tertiaryLabelColor - tertiaryTextSwiftUI = colors.tertiaryText?.swiftUIColor ?? Color(nsColor: .tertiaryLabelColor) - - selectionBackground = colors.selectionBackground?.nsColor ?? .selectedContentBackgroundColor - selectionBackgroundSwiftUI = colors.selectionBackground?.swiftUIColor - ?? Color(nsColor: .selectedContentBackgroundColor) - hoverBackground = colors.hoverBackground?.nsColor ?? .unemphasizedSelectedContentBackgroundColor - hoverBackgroundSwiftUI = colors.hoverBackground?.swiftUIColor - ?? Color(nsColor: .unemphasizedSelectedContentBackgroundColor) - - success = colors.status.success.nsColor - successSwiftUI = colors.status.success.swiftUIColor - warning = colors.status.warning.nsColor - warningSwiftUI = colors.status.warning.swiftUIColor - error = colors.status.error.nsColor - errorSwiftUI = colors.status.error.swiftUIColor - info = colors.status.info.nsColor - infoSwiftUI = colors.status.info.swiftUIColor - - badgeBackground = colors.badges.background.nsColor - badgeBackgroundSwiftUI = colors.badges.background.swiftUIColor - badgePrimaryKey = colors.badges.primaryKey.nsColor - badgePrimaryKeySwiftUI = colors.badges.primaryKey.swiftUIColor - badgeAutoIncrement = colors.badges.autoIncrement.nsColor - badgeAutoIncrementSwiftUI = colors.badges.autoIncrement.swiftUIColor - } -} - -struct ResolvedSidebarColors { - let background: NSColor - let backgroundSwiftUI: Color - let text: NSColor - let textSwiftUI: Color - let selectedItem: NSColor - let selectedItemSwiftUI: Color - let hover: NSColor - let hoverSwiftUI: Color - let sectionHeader: NSColor - let sectionHeaderSwiftUI: Color - - init(from colors: SidebarThemeColors) { - background = colors.background?.nsColor ?? .windowBackgroundColor - backgroundSwiftUI = colors.background?.swiftUIColor ?? Color(nsColor: .windowBackgroundColor) - text = colors.text?.nsColor ?? .labelColor - textSwiftUI = colors.text?.swiftUIColor ?? Color(nsColor: .labelColor) - selectedItem = colors.selectedItem?.nsColor ?? .selectedContentBackgroundColor - selectedItemSwiftUI = colors.selectedItem?.swiftUIColor - ?? Color(nsColor: .selectedContentBackgroundColor) - hover = colors.hover?.nsColor ?? .unemphasizedSelectedContentBackgroundColor - hoverSwiftUI = colors.hover?.swiftUIColor - ?? Color(nsColor: .unemphasizedSelectedContentBackgroundColor) - sectionHeader = colors.sectionHeader?.nsColor ?? .secondaryLabelColor - sectionHeaderSwiftUI = colors.sectionHeader?.swiftUIColor ?? Color(nsColor: .secondaryLabelColor) - } -} - -struct ResolvedToolbarColors { - let secondaryText: NSColor - let secondaryTextSwiftUI: Color - let tertiaryText: NSColor - let tertiaryTextSwiftUI: Color - - init(from colors: ToolbarThemeColors) { - secondaryText = colors.secondaryText?.nsColor ?? .secondaryLabelColor - secondaryTextSwiftUI = colors.secondaryText?.swiftUIColor ?? Color(nsColor: .secondaryLabelColor) - tertiaryText = colors.tertiaryText?.nsColor ?? .tertiaryLabelColor - tertiaryTextSwiftUI = colors.tertiaryText?.swiftUIColor ?? Color(nsColor: .tertiaryLabelColor) - } -} - -struct ResolvedThemeColors { - let editor: ResolvedEditorColors - let dataGrid: ResolvedDataGridColors - let ui: ResolvedUIColors - let sidebar: ResolvedSidebarColors - let toolbar: ResolvedToolbarColors - - init(from theme: ThemeDefinition) { - editor = ResolvedEditorColors(from: theme.editor) - dataGrid = ResolvedDataGridColors(from: theme.dataGrid) - ui = ResolvedUIColors(from: theme.ui) - sidebar = ResolvedSidebarColors(from: theme.sidebar) - toolbar = ResolvedToolbarColors(from: theme.toolbar) - } -} diff --git a/TablePro/Theme/ThemeCatalog.swift b/TablePro/Theme/ThemeCatalog.swift new file mode 100644 index 0000000000..81562859da --- /dev/null +++ b/TablePro/Theme/ThemeCatalog.swift @@ -0,0 +1,284 @@ +import Foundation +import os + +internal struct ThemeCatalogContents: Equatable, Sendable { + internal var themes: [ThemeDefinition] + internal var rejected: [RejectedThemeRecord] + + internal static let empty = ThemeCatalogContents(themes: BuiltInThemes.all, rejected: []) +} + +internal struct RejectedThemeRecord: Equatable, Sendable { + internal let path: String + internal let fileName: String + internal let reason: String +} + +internal enum ThemeOrigin: Sendable { + case bundle + case registry + case user + + internal var allowedPrefix: String? { + switch self { + case .bundle: return ThemeDefinition.builtInPrefix + case .registry: return ThemeDefinition.registryPrefix + case .user: return nil + } + } +} + +/// Owns the list. Loading is off the main actor; every mutation updates the in-memory list +/// synchronously before anything activates, because the old storage refreshed through a detached +/// Task and a save was therefore followed by an activation of the stale copy. +@MainActor +@Observable +internal final class ThemeCatalog { + internal static let shared = ThemeCatalog() + + internal private(set) var themes: [ThemeDefinition] = BuiltInThemes.all + internal private(set) var rejected: [RejectedThemeRecord] = [] + + @ObservationIgnored + nonisolated private static let logger = Logger(subsystem: "com.TablePro", category: "ThemeCatalog") + + @ObservationIgnored + nonisolated private static let bundledOrder = [ + BuiltInThemes.defaultLightId, + BuiltInThemes.defaultDarkId, + "tablepro.dracula", + "tablepro.nord", + ] + + /// Loaded before the first activation, not after it. The old catalog refreshed through a + /// detached Task, so the launch activation ran against built-ins alone and a user theme in a + /// slot resolved to the default until something else re-activated it. + private init() { + reloadSynchronously() + } + + internal func theme(id: String) -> ThemeDefinition? { + themes.first { $0.id == id } + } + + internal func reload() async { + let contents = await Task.detached { ThemeCatalog.loadContents() }.value + themes = contents.themes + rejected = contents.rejected + } + + internal func reloadSynchronously() { + let contents = Self.loadContents() + themes = contents.themes + rejected = contents.rejected + } + + internal func save(_ theme: ThemeDefinition) throws { + guard theme.isEditable else { throw ThemeLoadError.reservedIdentifier(theme.id) } + try Self.write(theme, to: Self.userDirectory) + upsert(theme) + } + + internal func delete(id: String) throws { + guard !id.hasPrefix(ThemeDefinition.builtInPrefix), !id.hasPrefix(ThemeDefinition.registryPrefix) else { + throw ThemeLoadError.reservedIdentifier(id) + } + try Self.remove(id: id, from: Self.userDirectory) + themes.removeAll { $0.id == id } + } + + internal func saveRegistryTheme(_ theme: ThemeDefinition) throws { + try Self.write(theme, to: Self.registryDirectory) + upsert(theme) + } + + internal func deleteRegistryTheme(id: String) throws { + try Self.remove(id: id, from: Self.registryDirectory) + themes.removeAll { $0.id == id } + rejected.removeAll { $0.fileName == "\(id).json" } + } + + internal func importTheme(from url: URL) throws -> ThemeDefinition { + let document = try ThemeDocument(data: try Data(contentsOf: url)) + var theme = document.resolved() + + if !theme.isEditable || containsTheme(id: theme.id) { + theme.id = ThemeIdentifier.generated() + } + + try Self.write(theme, to: Self.userDirectory) + upsert(theme) + return theme + } + + internal func exportTheme(_ theme: ThemeDefinition, to url: URL) throws { + try ThemeEncoder.data(for: theme).write(to: url, options: .atomic) + } + + internal func loadRegistryMeta() -> RegistryThemeMeta { + let url = Self.registryMetaURL + guard FileManager.default.fileExists(atPath: url.path) else { return RegistryThemeMeta() } + do { + let decoder = JSONDecoder() + decoder.dateDecodingStrategy = .iso8601 + return try decoder.decode(RegistryThemeMeta.self, from: try Data(contentsOf: url)) + } catch { + Self.logger.error("Failed to load registry meta: \(error)") + return RegistryThemeMeta() + } + } + + internal func saveRegistryMeta(_ meta: RegistryThemeMeta) throws { + Self.ensureDirectory(Self.registryDirectory) + let encoder = JSONEncoder() + encoder.outputFormatting = [.prettyPrinted, .sortedKeys] + encoder.dateEncodingStrategy = .iso8601 + try encoder.encode(meta).write(to: Self.registryMetaURL, options: .atomic) + } + + private func containsTheme(id: String) -> Bool { + themes.contains { $0.id == id } + } + + private func upsert(_ theme: ThemeDefinition) { + if let index = themes.firstIndex(where: { $0.id == theme.id }) { + themes[index] = theme + return + } + themes.append(theme) + } + + // MARK: - Locations + + nonisolated private static let userDirectory: URL = + AppStorageEnvironment.shared.applicationSupportRoot + .appendingPathComponent("TablePro/Themes", isDirectory: true) + + nonisolated private static let registryDirectory: URL = + userDirectory.appendingPathComponent("Registry", isDirectory: true) + + nonisolated private static let registryMetaURL: URL = + registryDirectory.appendingPathComponent("registry-meta.json") + + // MARK: - Disk + + nonisolated private static func loadContents() -> ThemeCatalogContents { + var themes = BuiltInThemes.all + var rejected: [RejectedThemeRecord] = [] + + ensureDirectory(userDirectory) + ensureDirectory(registryDirectory) + + let sources: [(URL, ThemeOrigin)] = [ + (Bundle.main.resourceURL, .bundle), + (registryDirectory, .registry), + (userDirectory, .user), + ].compactMap { url, source in url.map { ($0, source) } } + + for (directory, source) in sources { + let loaded = load(from: directory, source: source) + rejected.append(contentsOf: loaded.rejected) + + for theme in loaded.themes { + if let index = themes.firstIndex(where: { $0.id == theme.id }) { + themes[index] = theme + continue + } + themes.append(theme) + } + } + + themes.sort { lhs, rhs in + let left = bundledOrder.firstIndex(of: lhs.id) ?? Int.max + let right = bundledOrder.firstIndex(of: rhs.id) ?? Int.max + guard left == right else { return left < right } + return lhs.name.localizedStandardCompare(rhs.name) == .orderedAscending + } + + return ThemeCatalogContents(themes: themes, rejected: rejected) + } + + nonisolated private static func load( + from directory: URL, + source: ThemeOrigin + ) -> (themes: [ThemeDefinition], rejected: [RejectedThemeRecord]) { + let fileManager = FileManager.default + guard fileManager.fileExists(atPath: directory.path) else { return ([], []) } + + let files: [URL] + do { + files = try fileManager.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil) + .filter { $0.pathExtension == "json" && $0.lastPathComponent != "registry-meta.json" } + } catch { + logger.error("Failed to list \(directory.lastPathComponent): \(error)") + return ([], []) + } + + var themes: [ThemeDefinition] = [] + var rejected: [RejectedThemeRecord] = [] + + for file in files { + if source == .bundle, !file.lastPathComponent.hasPrefix(ThemeDefinition.builtInPrefix) { continue } + + do { + let document = try ThemeDocument(data: try Data(contentsOf: file)) + try validate(identifier: document.id, from: source) + themes.append(document.resolved()) + } catch { + guard source != .bundle else { + logger.error("Bundled theme \(file.lastPathComponent) rejected: \(error.localizedDescription)") + continue + } + rejected.append( + RejectedThemeRecord( + path: file.path, + fileName: file.lastPathComponent, + reason: error.localizedDescription + ) + ) + } + } + + return (themes, rejected) + } + + /// A reserved prefix is accepted only from the directory that owns it. A file dropped into the + /// user folder claiming `tablepro.` or `registry.` would otherwise shadow the real theme, be + /// read-only because the prefix says built-in, and be impossible to delete. + nonisolated private static func validate(identifier: String, from source: ThemeOrigin) throws { + guard ThemeIdentifier.isValid(identifier) else { + throw ThemeLoadError.invalidIdentifier(identifier) + } + + let reserved = [ThemeDefinition.builtInPrefix, ThemeDefinition.registryPrefix] + for prefix in reserved where identifier.hasPrefix(prefix) { + guard source.allowedPrefix == prefix else { + throw ThemeLoadError.reservedIdentifier(identifier) + } + } + } + + nonisolated private static func write(_ theme: ThemeDefinition, to directory: URL) throws { + ensureDirectory(directory) + guard ThemeIdentifier.isValid(theme.id) else { throw ThemeLoadError.invalidIdentifier(theme.id) } + let url = directory.appendingPathComponent("\(theme.id).json", isDirectory: false) + try ThemeEncoder.data(for: theme).write(to: url, options: .atomic) + } + + nonisolated private static func remove(id: String, from directory: URL) throws { + guard ThemeIdentifier.isValid(id) else { throw ThemeLoadError.invalidIdentifier(id) } + let url = directory.appendingPathComponent("\(id).json", isDirectory: false) + guard FileManager.default.fileExists(atPath: url.path) else { return } + try FileManager.default.removeItem(at: url) + } + + nonisolated private static func ensureDirectory(_ url: URL) { + let fileManager = FileManager.default + guard !fileManager.fileExists(atPath: url.path) else { return } + do { + try fileManager.createDirectory(at: url, withIntermediateDirectories: true) + } catch { + logger.error("Failed to create \(url.lastPathComponent): \(error)") + } + } +} diff --git a/TablePro/Theme/ThemeColorValue.swift b/TablePro/Theme/ThemeColorValue.swift new file mode 100644 index 0000000000..2a446ea2f6 --- /dev/null +++ b/TablePro/Theme/ThemeColorValue.swift @@ -0,0 +1,194 @@ +import AppKit +import SwiftUI + +internal enum SystemColorName: String, Codable, CaseIterable, Sendable { + case label + case secondaryLabel + case tertiaryLabel + case quaternaryLabel + case text + case textBackground + case selectedText + case selectedTextBackground + case placeholderText + case disabledControlText + case controlBackground + case windowBackground + case underPageBackground + case separator + case grid + case selectedContentBackground + case unemphasizedSelectedContentBackground + case alternateSelectedControlText + case controlAccent + case keyboardFocusIndicator + case alternatingContentBackgroundEven + case alternatingContentBackgroundOdd + case systemRed + case systemGreen + case systemBlue + case systemOrange + case systemYellow + case systemPurple + case systemTeal + case systemGray + + internal var color: NSColor { + switch self { + case .label: return .labelColor + case .secondaryLabel: return .secondaryLabelColor + case .tertiaryLabel: return .tertiaryLabelColor + case .quaternaryLabel: return .quaternaryLabelColor + case .text: return .textColor + case .textBackground: return .textBackgroundColor + case .selectedText: return .selectedTextColor + case .selectedTextBackground: return .selectedTextBackgroundColor + case .placeholderText: return .placeholderTextColor + case .disabledControlText: return .disabledControlTextColor + case .controlBackground: return .controlBackgroundColor + case .windowBackground: return .windowBackgroundColor + case .underPageBackground: return .underPageBackgroundColor + case .separator: return .separatorColor + case .grid: return .gridColor + case .selectedContentBackground: return .selectedContentBackgroundColor + case .unemphasizedSelectedContentBackground: return .unemphasizedSelectedContentBackgroundColor + case .alternateSelectedControlText: return .alternateSelectedControlTextColor + case .controlAccent: return .controlAccentColor + case .keyboardFocusIndicator: return .keyboardFocusIndicatorColor + case .alternatingContentBackgroundEven: return Self.alternatingContentBackground(at: 0) + case .alternatingContentBackgroundOdd: return Self.alternatingContentBackground(at: 1) + case .systemRed: return .systemRed + case .systemGreen: return .systemGreen + case .systemBlue: return .systemBlue + case .systemOrange: return .systemOrange + case .systemYellow: return .systemYellow + case .systemPurple: return .systemPurple + case .systemTeal: return .systemTeal + case .systemGray: return .systemGray + } + } + + private static func alternatingContentBackground(at index: Int) -> NSColor { + let colors = NSColor.alternatingContentBackgroundColors + guard colors.indices.contains(index) else { return .controlBackgroundColor } + return colors[index] + } +} + +/// A theme slot's value. `system` keeps a slot on the AppKit semantic colour its call site used +/// before the theme owned it, so the built-in themes stay pixel-identical to the unthemed app and +/// keep the system's own Increase Contrast and vibrancy adaptations. A custom theme uses `hex`. +internal enum ThemeColorValue: Equatable, Hashable, Sendable { + case hex(String) + case system(SystemColorName) + + internal static let systemPrefix = "system:" + + internal init(validating raw: String) throws { + if raw.hasPrefix(Self.systemPrefix) { + let name = String(raw.dropFirst(Self.systemPrefix.count)) + guard let known = SystemColorName(rawValue: name) else { + throw ThemeLoadError.unknownSystemColor(name) + } + self = .system(known) + return + } + + guard let canonical = HexColor.canonicalize(raw) else { + throw ThemeLoadError.invalidColor(raw) + } + self = .hex(canonical) + } + + internal var rawValue: String { + switch self { + case let .hex(value): return value + case let .system(name): return Self.systemPrefix + name.rawValue + } + } + + internal var nsColor: NSColor { + switch self { + case let .hex(value): return HexColor.color(value) + case let .system(name): return name.color + } + } + + internal var swiftUIColor: Color { + Color(nsColor: nsColor) + } + + internal var isSystem: Bool { + if case .system = self { return true } + return false + } +} + +extension ThemeColorValue: Codable { + internal init(from decoder: Decoder) throws { + let raw = try decoder.singleValueContainer().decode(String.self) + try self.init(validating: raw) + } + + internal func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode(rawValue) + } +} + +/// The parser rejects any string it does not consume whole. The previous one asked only whether +/// `Scanner.scanHexInt64` succeeded, which it does on a valid prefix, so `#FF79CG` silently +/// rendered as `#0FF79C` instead of reporting a typo. +internal enum HexColor { + internal static func canonicalize(_ raw: String) -> String? { + let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) + guard trimmed.hasPrefix("#") else { return nil } + + let digits = trimmed.dropFirst() + guard digits.count == 6 || digits.count == 8 else { return nil } + guard digits.allSatisfy(\.isHexDigit) else { return nil } + + return "#" + digits.uppercased() + } + + internal static func color(_ canonical: String) -> NSColor { + let digits = canonical.dropFirst() + var value: UInt64 = 0 + guard Scanner(string: String(digits)).scanHexInt64(&value) else { return .labelColor } + + if digits.count == 8 { + return NSColor( + srgbRed: CGFloat((value >> 24) & 0xFF) / 255, + green: CGFloat((value >> 16) & 0xFF) / 255, + blue: CGFloat((value >> 8) & 0xFF) / 255, + alpha: CGFloat(value & 0xFF) / 255 + ) + } + + return NSColor( + srgbRed: CGFloat((value >> 16) & 0xFF) / 255, + green: CGFloat((value >> 8) & 0xFF) / 255, + blue: CGFloat(value & 0xFF) / 255, + alpha: 1 + ) + } + + internal static func string(from color: NSColor) -> String { + guard let converted = color.usingColorSpace(.sRGB) else { return "#808080" } + + var red: CGFloat = 0 + var green: CGFloat = 0 + var blue: CGFloat = 0 + var alpha: CGFloat = 0 + converted.getRed(&red, green: &green, blue: &blue, alpha: &alpha) + + let redValue = Int(round(red * 255)) + let greenValue = Int(round(green * 255)) + let blueValue = Int(round(blue * 255)) + + guard alpha < 1 else { + return String(format: "#%02X%02X%02X", redValue, greenValue, blueValue) + } + return String(format: "#%02X%02X%02X%02X", redValue, greenValue, blueValue, Int(round(alpha * 255))) + } +} diff --git a/TablePro/Theme/ThemeColors.swift b/TablePro/Theme/ThemeColors.swift deleted file mode 100644 index 1b4fbd47c1..0000000000 --- a/TablePro/Theme/ThemeColors.swift +++ /dev/null @@ -1,397 +0,0 @@ -// -// ThemeColors.swift -// TablePro -// - -import Foundation -import SwiftUI -// MARK: - Syntax Colors - -internal struct SyntaxColors: Codable, Equatable, Sendable { - var keyword: String - var string: String - var number: String - var comment: String - var null: String - var `operator`: String - var function: String - var type: String - - static let defaultLight = SyntaxColors( - keyword: "#0A49A5", - string: "#C41A16", - number: "#6C36A9", - comment: "#007400", - null: "#C55B00", - operator: "#000000", - function: "#326D74", - type: "#3F6E74" - ) - - init( - keyword: String, - string: String, - number: String, - comment: String, - null: String, - operator: String, - function: String, - type: String - ) { - self.keyword = keyword - self.string = string - self.number = number - self.comment = comment - self.null = null - self.operator = `operator` - self.function = function - self.type = type - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let fallback = SyntaxColors.defaultLight - - keyword = try container.decodeIfPresent(String.self, forKey: .keyword) ?? fallback.keyword - string = try container.decodeIfPresent(String.self, forKey: .string) ?? fallback.string - number = try container.decodeIfPresent(String.self, forKey: .number) ?? fallback.number - comment = try container.decodeIfPresent(String.self, forKey: .comment) ?? fallback.comment - null = try container.decodeIfPresent(String.self, forKey: .null) ?? fallback.null - `operator` = try container.decodeIfPresent(String.self, forKey: .operator) ?? fallback.operator - function = try container.decodeIfPresent(String.self, forKey: .function) ?? fallback.function - type = try container.decodeIfPresent(String.self, forKey: .type) ?? fallback.type - } -} - -// MARK: - Editor Theme Colors - -internal struct EditorThemeColors: Codable, Equatable, Sendable { - var background: String - var text: String - var cursor: String - var currentLineHighlight: String - var selection: String - var lineNumber: String - var invisibles: String - var currentStatementHighlight: String - var syntax: SyntaxColors - - static let defaultLight = EditorThemeColors( - background: "#FFFFFF", - text: "#000000", - cursor: "#007AFF", - currentLineHighlight: "#007AFF14", - selection: "#B4D8FD", - lineNumber: "#8E8E93", - invisibles: "#C7C7CC", - currentStatementHighlight: "#0A0A0A0F", - syntax: .defaultLight - ) - - init( - background: String, - text: String, - cursor: String, - currentLineHighlight: String, - selection: String, - lineNumber: String, - invisibles: String, - currentStatementHighlight: String, - syntax: SyntaxColors - ) { - self.background = background - self.text = text - self.cursor = cursor - self.currentLineHighlight = currentLineHighlight - self.selection = selection - self.lineNumber = lineNumber - self.invisibles = invisibles - self.currentStatementHighlight = currentStatementHighlight - self.syntax = syntax - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let fallback = EditorThemeColors.defaultLight - - background = try container.decodeIfPresent(String.self, forKey: .background) ?? fallback.background - text = try container.decodeIfPresent(String.self, forKey: .text) ?? fallback.text - cursor = try container.decodeIfPresent(String.self, forKey: .cursor) ?? fallback.cursor - currentLineHighlight = try container.decodeIfPresent(String.self, forKey: .currentLineHighlight) - ?? fallback.currentLineHighlight - selection = try container.decodeIfPresent(String.self, forKey: .selection) ?? fallback.selection - lineNumber = try container.decodeIfPresent(String.self, forKey: .lineNumber) ?? fallback.lineNumber - invisibles = try container.decodeIfPresent(String.self, forKey: .invisibles) ?? fallback.invisibles - currentStatementHighlight = try container.decodeIfPresent(String.self, forKey: .currentStatementHighlight) - ?? fallback.currentStatementHighlight - syntax = try container.decodeIfPresent(SyntaxColors.self, forKey: .syntax) ?? fallback.syntax - } -} - -// MARK: - Data Grid Theme Colors - -internal struct DataGridThemeColors: Codable, Equatable, Sendable { - var background: String? - var text: String? - var alternateRow: String? - var nullValue: String? - var boolTrue: String? - var boolFalse: String? - var rowNumber: String? - var modified: String - var inserted: String - var deleted: String - var deletedText: String - - static let defaultLight = DataGridThemeColors( - background: nil, - text: nil, - alternateRow: nil, - nullValue: nil, - boolTrue: nil, - boolFalse: nil, - rowNumber: nil, - modified: "#FFD60A4D", - inserted: "#34C7594D", - deleted: "#FF3B304D", - deletedText: "#FF3B3080" - ) - - init( - background: String?, - text: String?, - alternateRow: String?, - nullValue: String?, - boolTrue: String?, - boolFalse: String?, - rowNumber: String?, - modified: String, - inserted: String, - deleted: String, - deletedText: String - ) { - self.background = background - self.text = text - self.alternateRow = alternateRow - self.nullValue = nullValue - self.boolTrue = boolTrue - self.boolFalse = boolFalse - self.rowNumber = rowNumber - self.modified = modified - self.inserted = inserted - self.deleted = deleted - self.deletedText = deletedText - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let fallback = DataGridThemeColors.defaultLight - - background = try container.decodeIfPresent(String.self, forKey: .background) - text = try container.decodeIfPresent(String.self, forKey: .text) - alternateRow = try container.decodeIfPresent(String.self, forKey: .alternateRow) - nullValue = try container.decodeIfPresent(String.self, forKey: .nullValue) - boolTrue = try container.decodeIfPresent(String.self, forKey: .boolTrue) - boolFalse = try container.decodeIfPresent(String.self, forKey: .boolFalse) - rowNumber = try container.decodeIfPresent(String.self, forKey: .rowNumber) - modified = try container.decodeIfPresent(String.self, forKey: .modified) ?? fallback.modified - inserted = try container.decodeIfPresent(String.self, forKey: .inserted) ?? fallback.inserted - deleted = try container.decodeIfPresent(String.self, forKey: .deleted) ?? fallback.deleted - deletedText = try container.decodeIfPresent(String.self, forKey: .deletedText) ?? fallback.deletedText - } -} - -// MARK: - Status Colors - -internal struct StatusColors: Codable, Equatable, Sendable { - var success: String - var warning: String - var error: String - var info: String - - static let defaultLight = StatusColors( - success: "#248A3D", - warning: "#C55B00", - error: "#D70015", - info: "#007AFF" - ) - - init(success: String, warning: String, error: String, info: String) { - self.success = success - self.warning = warning - self.error = error - self.info = info - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let fallback = StatusColors.defaultLight - - success = try container.decodeIfPresent(String.self, forKey: .success) ?? fallback.success - warning = try container.decodeIfPresent(String.self, forKey: .warning) ?? fallback.warning - error = try container.decodeIfPresent(String.self, forKey: .error) ?? fallback.error - info = try container.decodeIfPresent(String.self, forKey: .info) ?? fallback.info - } -} - -// MARK: - Badge Colors - -internal struct BadgeColors: Codable, Equatable, Sendable { - var background: String - var primaryKey: String - var autoIncrement: String - - static let defaultLight = BadgeColors( - background: "#E5E5EA", - primaryKey: "#007AFF26", - autoIncrement: "#AF52DE26" - ) - - init(background: String, primaryKey: String, autoIncrement: String) { - self.background = background - self.primaryKey = primaryKey - self.autoIncrement = autoIncrement - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let fallback = BadgeColors.defaultLight - - background = try container.decodeIfPresent(String.self, forKey: .background) ?? fallback.background - primaryKey = try container.decodeIfPresent(String.self, forKey: .primaryKey) ?? fallback.primaryKey - autoIncrement = try container.decodeIfPresent(String.self, forKey: .autoIncrement) ?? fallback.autoIncrement - } -} - -// MARK: - UI Theme Colors - -internal struct UIThemeColors: Codable, Equatable, Sendable { - var windowBackground: String? - var controlBackground: String? - var cardBackground: String? - var border: String? - var primaryText: String? - var secondaryText: String? - var tertiaryText: String? - var selectionBackground: String? - var hoverBackground: String? - var status: StatusColors - var badges: BadgeColors - - static let defaultLight = UIThemeColors( - windowBackground: nil, - controlBackground: nil, - cardBackground: nil, - border: nil, - primaryText: nil, - secondaryText: nil, - tertiaryText: nil, - selectionBackground: nil, - hoverBackground: nil, - status: .defaultLight, - badges: .defaultLight - ) - - init( - windowBackground: String?, - controlBackground: String?, - cardBackground: String?, - border: String?, - primaryText: String?, - secondaryText: String?, - tertiaryText: String?, - selectionBackground: String?, - hoverBackground: String?, - status: StatusColors, - badges: BadgeColors - ) { - self.windowBackground = windowBackground - self.controlBackground = controlBackground - self.cardBackground = cardBackground - self.border = border - self.primaryText = primaryText - self.secondaryText = secondaryText - self.tertiaryText = tertiaryText - self.selectionBackground = selectionBackground - self.hoverBackground = hoverBackground - self.status = status - self.badges = badges - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let fallback = UIThemeColors.defaultLight - - windowBackground = try container.decodeIfPresent(String.self, forKey: .windowBackground) - controlBackground = try container.decodeIfPresent(String.self, forKey: .controlBackground) - cardBackground = try container.decodeIfPresent(String.self, forKey: .cardBackground) - border = try container.decodeIfPresent(String.self, forKey: .border) - primaryText = try container.decodeIfPresent(String.self, forKey: .primaryText) - secondaryText = try container.decodeIfPresent(String.self, forKey: .secondaryText) - tertiaryText = try container.decodeIfPresent(String.self, forKey: .tertiaryText) - selectionBackground = try container.decodeIfPresent(String.self, forKey: .selectionBackground) - hoverBackground = try container.decodeIfPresent(String.self, forKey: .hoverBackground) - status = try container.decodeIfPresent(StatusColors.self, forKey: .status) ?? fallback.status - badges = try container.decodeIfPresent(BadgeColors.self, forKey: .badges) ?? fallback.badges - } -} - -// MARK: - Sidebar Theme Colors - -internal struct SidebarThemeColors: Codable, Equatable, Sendable { - var background: String? - var text: String? - var selectedItem: String? - var hover: String? - var sectionHeader: String? - - static let defaultLight = SidebarThemeColors( - background: nil, - text: nil, - selectedItem: nil, - hover: nil, - sectionHeader: nil - ) - - init(background: String?, text: String?, selectedItem: String?, hover: String?, sectionHeader: String?) { - self.background = background - self.text = text - self.selectedItem = selectedItem - self.hover = hover - self.sectionHeader = sectionHeader - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - background = try container.decodeIfPresent(String.self, forKey: .background) - text = try container.decodeIfPresent(String.self, forKey: .text) - selectedItem = try container.decodeIfPresent(String.self, forKey: .selectedItem) - hover = try container.decodeIfPresent(String.self, forKey: .hover) - sectionHeader = try container.decodeIfPresent(String.self, forKey: .sectionHeader) - } -} - -// MARK: - Toolbar Theme Colors - -internal struct ToolbarThemeColors: Codable, Equatable, Sendable { - var secondaryText: String? - var tertiaryText: String? - - static let defaultLight = ToolbarThemeColors( - secondaryText: nil, - tertiaryText: nil - ) - - init(secondaryText: String?, tertiaryText: String?) { - self.secondaryText = secondaryText - self.tertiaryText = tertiaryText - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - secondaryText = try container.decodeIfPresent(String.self, forKey: .secondaryText) - tertiaryText = try container.decodeIfPresent(String.self, forKey: .tertiaryText) - } -} diff --git a/TablePro/Theme/ThemeDefinition.swift b/TablePro/Theme/ThemeDefinition.swift index f0eaddf405..4fccb5f3d5 100644 --- a/TablePro/Theme/ThemeDefinition.swift +++ b/TablePro/Theme/ThemeDefinition.swift @@ -1,80 +1,250 @@ -import SwiftUI +import Foundation -internal struct ThemeDefinition: Codable, Identifiable, Equatable, Sendable { +internal enum ThemeAppearance: String, Codable, CaseIterable, Sendable { + case light + case dark +} + +internal struct SyntaxThemeColors: Equatable, Sendable { + var keyword: ThemeColorValue + var string: ThemeColorValue + var number: ThemeColorValue + var comment: ThemeColorValue + var null: ThemeColorValue + var `operator`: ThemeColorValue + var function: ThemeColorValue + var type: ThemeColorValue +} + +internal struct EditorThemeColors: Equatable, Sendable { + var background: ThemeColorValue + var text: ThemeColorValue + var cursor: ThemeColorValue + var selection: ThemeColorValue + var currentLine: ThemeColorValue + var currentStatement: ThemeColorValue + var lineNumber: ThemeColorValue + var invisibles: ThemeColorValue + var syntax: SyntaxThemeColors +} + +internal struct DataGridThemeColors: Equatable, Sendable { + var background: ThemeColorValue + var text: ThemeColorValue + var alternateRow: ThemeColorValue + var headerBackground: ThemeColorValue + var headerText: ThemeColorValue + var gridLine: ThemeColorValue + var selection: ThemeColorValue + var selectionText: ThemeColorValue + var inactiveSelection: ThemeColorValue + var focusBorder: ThemeColorValue + var nullValue: ThemeColorValue + var boolTrue: ThemeColorValue + var boolFalse: ThemeColorValue + var rowNumber: ThemeColorValue + var modified: ThemeColorValue + var inserted: ThemeColorValue + var deleted: ThemeColorValue + var deletedText: ThemeColorValue +} + +internal struct StatusThemeColors: Equatable, Sendable { + var success: ThemeColorValue + var warning: ThemeColorValue + var error: ThemeColorValue +} + +internal struct ThemeDefinition: Identifiable, Equatable, Sendable { var id: String var name: String - var version: Int - var appearance: ThemeAppearance var author: String + var appearance: ThemeAppearance var editor: EditorThemeColors var dataGrid: DataGridThemeColors - var ui: UIThemeColors - var sidebar: SidebarThemeColors - var toolbar: ToolbarThemeColors - var fonts: ThemeFonts - - var isBuiltIn: Bool { id.hasPrefix("tablepro.") } - var isRegistry: Bool { id.hasPrefix("registry.") } - var isEditable: Bool { !isBuiltIn && !isRegistry } - - static let `default` = ThemeDefinition( - id: "tablepro.default-light", - name: "Default Light", - version: 1, - appearance: .light, - author: "TablePro", - editor: .defaultLight, - dataGrid: .defaultLight, - ui: .defaultLight, - sidebar: .defaultLight, - toolbar: .defaultLight, - fonts: .default - ) - - init( - id: String, - name: String, - version: Int, - appearance: ThemeAppearance, - author: String, - editor: EditorThemeColors, - dataGrid: DataGridThemeColors, - ui: UIThemeColors, - sidebar: SidebarThemeColors, - toolbar: ToolbarThemeColors, - fonts: ThemeFonts - ) { - self.id = id - self.name = name - self.version = version - self.appearance = appearance - self.author = author - self.editor = editor - self.dataGrid = dataGrid - self.ui = ui - self.sidebar = sidebar - self.toolbar = toolbar - self.fonts = fonts + var status: StatusThemeColors + + internal static let builtInPrefix = "tablepro." + internal static let registryPrefix = "registry." + internal static let userPrefix = "user." + + internal var isBuiltIn: Bool { id.hasPrefix(Self.builtInPrefix) } + internal var isRegistry: Bool { id.hasPrefix(Self.registryPrefix) } + internal var isEditable: Bool { !isBuiltIn && !isRegistry } +} + +/// The single registry every slot goes through. A slot exists here because a call site reads it, +/// which is what `ThemeSlotCoverageTests` enforces: the previous schema let whole groups +/// ship with no reader at all, and nothing caught it. The gate, the theme editor and the document +/// decoder all enumerate this list rather than keeping their own copies. +internal enum ThemeSlot: String, CaseIterable, Sendable { + case editorBackground = "content.editor.background" + case editorText = "content.editor.text" + case editorCursor = "content.editor.cursor" + case editorSelection = "content.editor.selection" + case editorCurrentLine = "content.editor.currentLine" + case editorCurrentStatement = "content.editor.currentStatement" + case editorLineNumber = "content.editor.lineNumber" + case editorInvisibles = "content.editor.invisibles" + + case syntaxKeyword = "content.editor.syntax.keyword" + case syntaxString = "content.editor.syntax.string" + case syntaxNumber = "content.editor.syntax.number" + case syntaxComment = "content.editor.syntax.comment" + case syntaxNull = "content.editor.syntax.null" + case syntaxOperator = "content.editor.syntax.operator" + case syntaxFunction = "content.editor.syntax.function" + case syntaxType = "content.editor.syntax.type" + + case gridBackground = "content.dataGrid.background" + case gridText = "content.dataGrid.text" + case gridAlternateRow = "content.dataGrid.alternateRow" + case gridHeaderBackground = "content.dataGrid.headerBackground" + case gridHeaderText = "content.dataGrid.headerText" + case gridLine = "content.dataGrid.gridLine" + case gridSelection = "content.dataGrid.selection" + case gridSelectionText = "content.dataGrid.selectionText" + case gridInactiveSelection = "content.dataGrid.inactiveSelection" + case gridFocusBorder = "content.dataGrid.focusBorder" + case gridNullValue = "content.dataGrid.nullValue" + case gridBoolTrue = "content.dataGrid.boolTrue" + case gridBoolFalse = "content.dataGrid.boolFalse" + case gridRowNumber = "content.dataGrid.rowNumber" + case gridModified = "content.dataGrid.modified" + case gridInserted = "content.dataGrid.inserted" + case gridDeleted = "content.dataGrid.deleted" + case gridDeletedText = "content.dataGrid.deletedText" + + case statusSuccess = "content.status.success" + case statusWarning = "content.status.warning" + case statusError = "content.status.error" + + internal var since: Int { 2 } + + internal var group: ThemeSlotGroup { + switch self { + case .editorBackground, .editorText, .editorCursor, .editorSelection, + .editorCurrentLine, .editorCurrentStatement, .editorLineNumber, .editorInvisibles: + return .editor + case .syntaxKeyword, .syntaxString, .syntaxNumber, .syntaxComment, + .syntaxNull, .syntaxOperator, .syntaxFunction, .syntaxType: + return .syntax + case .gridBackground, .gridText, .gridAlternateRow, .gridHeaderBackground, .gridHeaderText, + .gridLine, .gridSelection, .gridSelectionText, .gridInactiveSelection, .gridFocusBorder, + .gridNullValue, .gridBoolTrue, .gridBoolFalse, .gridRowNumber, + .gridModified, .gridInserted, .gridDeleted, .gridDeletedText: + return .dataGrid + case .statusSuccess, .statusWarning, .statusError: + return .status + } + } + + internal var keyPath: WritableKeyPath { + switch self { + case .editorBackground: return \.editor.background + case .editorText: return \.editor.text + case .editorCursor: return \.editor.cursor + case .editorSelection: return \.editor.selection + case .editorCurrentLine: return \.editor.currentLine + case .editorCurrentStatement: return \.editor.currentStatement + case .editorLineNumber: return \.editor.lineNumber + case .editorInvisibles: return \.editor.invisibles + + case .syntaxKeyword: return \.editor.syntax.keyword + case .syntaxString: return \.editor.syntax.string + case .syntaxNumber: return \.editor.syntax.number + case .syntaxComment: return \.editor.syntax.comment + case .syntaxNull: return \.editor.syntax.null + case .syntaxOperator: return \.editor.syntax.operator + case .syntaxFunction: return \.editor.syntax.function + case .syntaxType: return \.editor.syntax.type + + case .gridBackground: return \.dataGrid.background + case .gridText: return \.dataGrid.text + case .gridAlternateRow: return \.dataGrid.alternateRow + case .gridHeaderBackground: return \.dataGrid.headerBackground + case .gridHeaderText: return \.dataGrid.headerText + case .gridLine: return \.dataGrid.gridLine + case .gridSelection: return \.dataGrid.selection + case .gridSelectionText: return \.dataGrid.selectionText + case .gridInactiveSelection: return \.dataGrid.inactiveSelection + case .gridFocusBorder: return \.dataGrid.focusBorder + case .gridNullValue: return \.dataGrid.nullValue + case .gridBoolTrue: return \.dataGrid.boolTrue + case .gridBoolFalse: return \.dataGrid.boolFalse + case .gridRowNumber: return \.dataGrid.rowNumber + case .gridModified: return \.dataGrid.modified + case .gridInserted: return \.dataGrid.inserted + case .gridDeleted: return \.dataGrid.deleted + case .gridDeletedText: return \.dataGrid.deletedText + + case .statusSuccess: return \.status.success + case .statusWarning: return \.status.warning + case .statusError: return \.status.error + } + } + + internal var label: String { + switch self { + case .editorBackground, .gridBackground: return String(localized: "Background") + case .editorText, .gridText: return String(localized: "Text") + case .editorCursor: return String(localized: "Cursor") + case .editorSelection, .gridSelection: return String(localized: "Selection") + case .editorCurrentLine: return String(localized: "Current Line") + case .editorCurrentStatement: return String(localized: "Current Statement") + case .editorLineNumber: return String(localized: "Line Number") + case .editorInvisibles: return String(localized: "Invisibles") + case .syntaxKeyword: return String(localized: "Keyword") + case .syntaxString: return String(localized: "String") + case .syntaxNumber: return String(localized: "Number") + case .syntaxComment: return String(localized: "Comment") + case .syntaxNull: return String(localized: "NULL") + case .syntaxOperator: return String(localized: "Operator") + case .syntaxFunction: return String(localized: "Function") + case .syntaxType: return String(localized: "Type") + case .gridAlternateRow: return String(localized: "Alternate Row") + case .gridHeaderBackground: return String(localized: "Header Background") + case .gridHeaderText: return String(localized: "Header Text") + case .gridLine: return String(localized: "Grid Line") + case .gridSelectionText: return String(localized: "Selected Text") + case .gridInactiveSelection: return String(localized: "Inactive Selection") + case .gridFocusBorder: return String(localized: "Focus Border") + case .gridNullValue: return String(localized: "NULL Value") + case .gridBoolTrue: return String(localized: "Bool True") + case .gridBoolFalse: return String(localized: "Bool False") + case .gridRowNumber: return String(localized: "Row Number") + case .gridModified: return String(localized: "Modified") + case .gridInserted: return String(localized: "Inserted") + case .gridDeleted: return String(localized: "Deleted") + case .gridDeletedText: return String(localized: "Deleted Text") + case .statusSuccess: return String(localized: "Success") + case .statusWarning: return String(localized: "Warning") + case .statusError: return String(localized: "Error") + } + } +} + +internal enum ThemeSlotGroup: String, CaseIterable, Sendable { + case editor + case syntax + case dataGrid + case status + + internal var label: String { + switch self { + case .editor: return String(localized: "Editor") + case .syntax: return String(localized: "Syntax Colors") + case .dataGrid: return String(localized: "Data Grid") + case .status: return String(localized: "Status") + } } - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let fallback = ThemeDefinition.default - - id = try container.decodeIfPresent(String.self, forKey: .id) ?? fallback.id - name = try container.decodeIfPresent(String.self, forKey: .name) ?? fallback.name - version = try container.decodeIfPresent(Int.self, forKey: .version) ?? fallback.version - appearance = try container.decodeIfPresent(ThemeAppearance.self, forKey: .appearance) ?? fallback.appearance - author = try container.decodeIfPresent(String.self, forKey: .author) ?? fallback.author - editor = try container.decodeIfPresent(EditorThemeColors.self, forKey: .editor) ?? fallback.editor - dataGrid = try container.decodeIfPresent(DataGridThemeColors.self, forKey: .dataGrid) ?? fallback.dataGrid - ui = try container.decodeIfPresent(UIThemeColors.self, forKey: .ui) ?? fallback.ui - sidebar = try container.decodeIfPresent(SidebarThemeColors.self, forKey: .sidebar) ?? fallback.sidebar - toolbar = try container.decodeIfPresent(ToolbarThemeColors.self, forKey: .toolbar) ?? fallback.toolbar - fonts = try container.decodeIfPresent(ThemeFonts.self, forKey: .fonts) ?? fallback.fonts + internal var slots: [ThemeSlot] { + ThemeSlot.allCases.filter { $0.group == self } } } -internal enum ThemeAppearance: String, Codable, Sendable { - case light, dark, auto +internal enum ThemeSchema { + internal static let current = 2 + internal static let oldestSupported = 2 } diff --git a/TablePro/Theme/ThemeDocument.swift b/TablePro/Theme/ThemeDocument.swift new file mode 100644 index 0000000000..4debffd57a --- /dev/null +++ b/TablePro/Theme/ThemeDocument.swift @@ -0,0 +1,200 @@ +import Foundation + +internal indirect enum ThemeJSONNode: Decodable { + case string(String) + case number(Int) + case object([String: ThemeJSONNode]) + + internal init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + + if let value = try? container.decode(String.self) { + self = .string(value) + return + } + if let value = try? container.decode(Int.self) { + self = .number(value) + return + } + self = .object(try container.decode([String: ThemeJSONNode].self)) + } + + internal var stringValue: String? { + if case let .string(value) = self { return value } + return nil + } + + internal var intValue: Int? { + if case let .number(value) = self { return value } + return nil + } + + internal func flattened(prefix: String = "") -> [String: String] { + switch self { + case let .string(value): + return prefix.isEmpty ? [:] : [prefix: value] + case .number: + return [:] + case let .object(children): + var result: [String: String] = [:] + for (key, child) in children { + let path = prefix.isEmpty ? key : "\(prefix).\(key)" + result.merge(child.flattened(prefix: path)) { _, new in new } + } + return result + } + } +} + +/// The theme file format, and the only place a file can be rejected. The previous decoder read +/// every key with `decodeIfPresent` and a Default Light fallback, so an empty object and a VS Code +/// theme both decoded "successfully" and rendered as Default Light under the file's own name. +internal struct ThemeDocument { + internal let schema: Int + internal let id: String + internal let name: String + internal let author: String + internal let appearance: ThemeAppearance + internal let colors: [ThemeSlot: ThemeColorValue] + + private enum MetadataKey: String, CaseIterable { + case schema + case id + case name + case author + case appearance + } + + internal init(data: Data) throws { + let root = try JSONDecoder().decode([String: ThemeJSONNode].self, from: data) + + guard let schema = root[MetadataKey.schema.rawValue]?.intValue else { + throw ThemeLoadError.missingSchema + } + guard schema >= ThemeSchema.oldestSupported else { + throw ThemeLoadError.schemaTooOld(found: schema, supported: ThemeSchema.current) + } + guard schema <= ThemeSchema.current else { + throw ThemeLoadError.schemaTooNew(found: schema, supported: ThemeSchema.current) + } + self.schema = schema + + guard let id = root[MetadataKey.id.rawValue]?.stringValue, !id.isEmpty else { + throw ThemeLoadError.missingField(MetadataKey.id.rawValue) + } + guard ThemeIdentifier.isValid(id) else { + throw ThemeLoadError.invalidIdentifier(id) + } + self.id = id + + guard let name = root[MetadataKey.name.rawValue]?.stringValue, !name.isEmpty else { + throw ThemeLoadError.missingField(MetadataKey.name.rawValue) + } + self.name = name + + guard + let appearanceRaw = root[MetadataKey.appearance.rawValue]?.stringValue, + let appearance = ThemeAppearance(rawValue: appearanceRaw) + else { + throw ThemeLoadError.missingField(MetadataKey.appearance.rawValue) + } + self.appearance = appearance + + author = root[MetadataKey.author.rawValue]?.stringValue ?? "" + + var flat: [String: String] = [:] + for (key, node) in root where MetadataKey(rawValue: key) == nil { + flat.merge(node.flattened(prefix: key)) { _, new in new } + } + + var parsed: [ThemeSlot: ThemeColorValue] = [:] + var unknown: [String] = [] + + for (path, raw) in flat { + guard let slot = ThemeSlot(rawValue: path) else { + unknown.append(path) + continue + } + parsed[slot] = try ThemeColorValue(validating: raw) + } + + guard unknown.isEmpty else { + throw ThemeLoadError.unknownKeys(unknown.sorted()) + } + + let missing = ThemeSlot.allCases + .filter { $0.since <= schema && parsed[$0] == nil } + .map(\.rawValue) + + guard missing.isEmpty else { + throw ThemeLoadError.missingSlots(missing.sorted()) + } + + colors = parsed + } + + /// A slot introduced after this file's schema revision takes the same-appearance built-in's + /// value for that exact slot. Every slot the file's own revision declares is required, so this + /// never papers over an omission the author could have made. + internal func resolved() -> ThemeDefinition { + var definition = BuiltInThemes.default(for: appearance) + definition.id = id + definition.name = name + definition.author = author + definition.appearance = appearance + + for slot in ThemeSlot.allCases { + guard let value = colors[slot] else { continue } + definition[keyPath: slot.keyPath] = value + } + + return definition + } +} + +internal enum ThemeIdentifier { + private static let pattern = #"^[A-Za-z0-9._-]+$"# + + internal static func isValid(_ id: String) -> Bool { + id.range(of: pattern, options: .regularExpression) != nil + && !id.contains("..") + } + + internal static func generated() -> String { + ThemeDefinition.userPrefix + UUID().uuidString.lowercased().prefix(8) + } +} + +internal enum ThemeEncoder { + internal static func data(for theme: ThemeDefinition) throws -> Data { + var root: [String: Any] = [ + "schema": ThemeSchema.current, + "id": theme.id, + "name": theme.name, + "author": theme.author, + "appearance": theme.appearance.rawValue, + ] + + for slot in ThemeSlot.allCases { + insert(theme[keyPath: slot.keyPath].rawValue, at: slot.rawValue.components(separatedBy: "."), into: &root) + } + + return try JSONSerialization.data( + withJSONObject: root, + options: [.prettyPrinted, .sortedKeys, .withoutEscapingSlashes] + ) + } + + private static func insert(_ value: String, at path: [String], into container: inout [String: Any]) { + guard let head = path.first else { return } + + guard path.count > 1 else { + container[head] = value + return + } + + var child = container[head] as? [String: Any] ?? [:] + insert(value, at: Array(path.dropFirst()), into: &child) + container[head] = child + } +} diff --git a/TablePro/Theme/ThemeEngine.swift b/TablePro/Theme/ThemeEngine.swift index 165c5afdc1..89ead1b099 100644 --- a/TablePro/Theme/ThemeEngine.swift +++ b/TablePro/Theme/ThemeEngine.swift @@ -1,11 +1,3 @@ -// -// ThemeEngine.swift -// TablePro -// -// Central @Observable singleton managing the active theme. -// Replaces Theme.swift, SQLEditorTheme, DataGridFontCache, ToolbarDesignTokens. -// - import AppKit import CodeEditSourceEditor import Combine @@ -14,9 +6,6 @@ import Observation import os import SwiftUI -// MARK: - Font Caches - -/// Tags stored on NSTextField.tag to identify which font variant a cell uses. internal enum DataGridFontVariant { static let regular = 0 static let italic = 1 @@ -24,447 +13,263 @@ internal enum DataGridFontVariant { static let rowNumber = 3 } -internal struct EditorFontCache { - let font: NSFont - let lineNumberFont: NSFont - let scaleFactor: CGFloat +internal struct EditorFontCache: Equatable { + internal let font: NSFont + internal let lineNumberFont: NSFont + internal let scaleFactor: CGFloat - init(from fonts: ThemeFonts) { - let scale = Self.computeAccessibilityScale() + internal init(from typography: TypographySettings) { + let scale = Self.accessibilityScale() scaleFactor = scale - let scaledSize = round(CGFloat(min(max(fonts.editorFontSize, 11), 18)) * scale) - font = EditorFontResolver.resolve(familyId: fonts.editorFontFamily, size: scaledSize) - let lineNumSize = max(round((scaledSize - 2)), 9) - lineNumberFont = NSFont.monospacedSystemFont(ofSize: lineNumSize, weight: .regular) + + let size = round(CGFloat(typography.clampedEditorFontSize) * scale) + font = EditorFontResolver.resolve(familyId: typography.editorFontFamily, size: size) + lineNumberFont = NSFont.monospacedSystemFont(ofSize: max(round(size - 2), 9), weight: .regular) } - static func computeAccessibilityScale() -> CGFloat { - let preferredBodyFont = NSFont.preferredFont(forTextStyle: .body) - let scale = preferredBodyFont.pointSize / 13.0 - return min(max(scale, 0.5), 3.0) + internal static func accessibilityScale() -> CGFloat { + let preferred = NSFont.preferredFont(forTextStyle: .body) + return min(max(preferred.pointSize / 13.0, 0.5), 3.0) } } -internal struct DataGridFontCacheResolved { - let regular: NSFont - let italic: NSFont - let medium: NSFont - let rowNumber: NSFont - let monoCharWidth: CGFloat - - init(from fonts: ThemeFonts) { - let scale = EditorFontCache.computeAccessibilityScale() - let scaledSize = round(CGFloat(min(max(fonts.dataGridFontSize, 10), 18)) * scale) - regular = EditorFontResolver.resolve(familyId: fonts.dataGridFontFamily, size: scaledSize) +internal struct DataGridFontCache: Equatable { + internal let regular: NSFont + internal let italic: NSFont + internal let medium: NSFont + internal let rowNumber: NSFont + internal let monoCharWidth: CGFloat + + internal init(from typography: TypographySettings) { + let scale = EditorFontCache.accessibilityScale() + let size = round(CGFloat(typography.clampedDataGridFontSize) * scale) + + regular = EditorFontResolver.resolve(familyId: typography.dataGridFontFamily, size: size) italic = regular.withTraits(.italic) medium = NSFontManager.shared.convert(regular, toHaveTrait: .boldFontMask) - let rowNumSize = max(round(scaledSize - 1), 9) - rowNumber = NSFont.monospacedDigitSystemFont(ofSize: rowNumSize, weight: .regular) - let attrs: [NSAttributedString.Key: Any] = [.font: regular] - monoCharWidth = ("M" as NSString).size(withAttributes: attrs).width + rowNumber = NSFont.monospacedDigitSystemFont(ofSize: max(round(size - 1), 9), weight: .regular) + monoCharWidth = ("M" as NSString).size(withAttributes: [.font: regular]).width } } -// MARK: - ThemeEngine - +/// Owns the active palette and the font caches, and nothing else: the catalog is `ThemeCatalog`, +/// the choice is `ThemeResolver`, and the fonts come from settings. It never writes settings back, +/// so the flow is one way. @Observable @MainActor internal final class ThemeEngine { - static let shared = ThemeEngine() - - // MARK: - Active Theme - - private(set) var activeTheme: ThemeDefinition - - /// Pre-resolved colors (rebuilt on theme change) - private(set) var colors: ResolvedThemeColors - - /// Cached editor fonts - private(set) var editorFonts: EditorFontCache - - /// Cached data grid fonts - private(set) var dataGridFonts: DataGridFontCacheResolved + internal static let shared = ThemeEngine() - // MARK: - Stored Value Font + internal private(set) var pair: ThemePair + internal private(set) var effectiveAppearance: ThemeAppearance + internal private(set) var revision: Int + internal private(set) var palette: ThemePalette + internal private(set) var resolved: ResolvedTheme + internal private(set) var editorFonts: EditorFontCache + internal private(set) var dataGridFonts: DataGridFontCache - /// The font every control that shows or edits a stored value uses, so one value reads the same in - /// the grid cell, its inline editor, the row inspector and a pop-out window. It is the data grid - /// font today; a viewer that also wears the editor's colours and syntax palette takes - /// `editorFonts` instead. - var valueFont: NSFont { dataGridFonts.regular } + internal var activeTheme: ThemeDefinition { pair[effectiveAppearance] } - var valueFontSwiftUI: Font { Font(valueFont) } - - /// The emphasised variant, for the key half of a key/value pair. - var valueFontEmphasizedSwiftUI: Font { Font(dataGridFonts.medium) } - - // MARK: - Available Themes - - private(set) var availableThemes: [ThemeDefinition] - - // MARK: - Editor Behavioral Settings (read from AppSettingsManager) + internal var change: ThemeChange { + ThemeChange(revision: revision, appearance: effectiveAppearance) + } - /// These are not theme properties but are needed by makeEditorTheme() - @ObservationIgnored var highlightCurrentLine: Bool = true - @ObservationIgnored var highlightCurrentStatement: Bool = true - @ObservationIgnored var showLineNumbers: Bool = true - @ObservationIgnored var tabWidth: Int = 4 - @ObservationIgnored var wordWrap: Bool = false + /// Every control that shows or edits a stored value takes this, so one value reads the same in + /// the grid cell, its inline editor, the row inspector, a cell popover and a pop-out window. + internal var valueFont: NSFont { dataGridFonts.regular } + internal var valueFontSwiftUI: Font { Font(valueFont) } + internal var valueFontEmphasizedSwiftUI: Font { Font(dataGridFonts.medium) } - // MARK: - Private + @ObservationIgnored + nonisolated private static let logger = Logger(subsystem: "com.TablePro", category: "ThemeEngine") - @ObservationIgnored nonisolated private static let logger = Logger(subsystem: "com.TablePro", category: "ThemeEngine") + @ObservationIgnored private var mode: AppAppearanceMode = .auto + @ObservationIgnored private var typography: TypographySettings = .default + @ObservationIgnored private var appearanceObservation: NSKeyValueObservation? @ObservationIgnored private var accessibilityObserver: NSObjectProtocol? - @ObservationIgnored private var lastAccessibilityScale: CGFloat = 1.0 - - // MARK: - Init + @ObservationIgnored private var lastAccessibilityScale: CGFloat = 1 private init() { - let theme = ThemeDefinition.default - - self.activeTheme = theme - self.colors = ResolvedThemeColors(from: theme) - self.editorFonts = EditorFontCache(from: theme.fonts) - self.dataGridFonts = DataGridFontCacheResolved(from: theme.fonts) - self.availableThemes = [theme] + pair = .builtIn + effectiveAppearance = .light + revision = 1 + palette = ThemePalette(revision: 1) + resolved = ResolvedTheme(definition: BuiltInThemes.light, appearance: .light) + editorFonts = EditorFontCache(from: .default) + dataGridFonts = DataGridFontCache(from: .default) observeAccessibilityChanges() - - Task { - let themes = await Task.detached { ThemeStorage.loadAllThemes() }.value - self.availableThemes = themes - } } - // MARK: - Theme Lifecycle + // MARK: - Settings entry points - func activateTheme(id: String) { - if let theme = availableThemes.first(where: { $0.id == id }) - ?? ThemeStorage.loadTheme(id: id) { - activateTheme(theme) - return - } - - Self.logger.warning("Theme '\(id)' not found; falling back to default") - activateTheme(.default) - } - - func activateTheme(_ theme: ThemeDefinition) { - activeTheme = theme - colors = ResolvedThemeColors(from: theme) - editorFonts = EditorFontCache(from: theme.fonts) - dataGridFonts = DataGridFontCacheResolved(from: theme.fonts) - - notifyThemeDidChange() - - Self.logger.info("Activated theme: \(theme.name) (\(theme.id))") - } - - // MARK: - Theme CRUD - - func saveUserTheme(_ theme: ThemeDefinition) throws { - try ThemeStorage.saveUserTheme(theme) - - if let index = availableThemes.firstIndex(where: { $0.id == theme.id }) { - availableThemes[index] = theme - } else { - availableThemes.append(theme) - } - reloadAvailableThemes() - - if theme.id == activeTheme.id { - activateTheme(theme) - } - } - - func deleteUserTheme(id: String) throws { - guard !id.hasPrefix("tablepro."), !id.hasPrefix("registry.") else { return } - try ThemeStorage.deleteUserTheme(id: id) - reloadAvailableThemes() - - // If deleted a preferred theme, reset that slot to default - var appearance = AppSettingsManager.shared.appearance - var changed = false - if id == appearance.preferredLightThemeId { - appearance.preferredLightThemeId = "tablepro.default-light" - changed = true - } - if id == appearance.preferredDarkThemeId { - appearance.preferredDarkThemeId = "tablepro.default-dark" - changed = true - } - if changed { - AppSettingsManager.shared.appearance = appearance - } else if id == activeTheme.id { - // Deleted a non-preferred but currently active theme — re-anchor to preferred - let appearance = AppSettingsManager.shared.appearance - updateAppearanceAndTheme( - mode: appearance.appearanceMode, - lightThemeId: appearance.preferredLightThemeId, - darkThemeId: appearance.preferredDarkThemeId - ) - } - } - - func duplicateTheme(_ theme: ThemeDefinition, newName: String) -> ThemeDefinition { - var copy = theme - copy.id = "user.\(UUID().uuidString.lowercased().prefix(8))" - copy.name = newName - copy.author = theme.author - return copy - } + internal func apply(mode: AppAppearanceMode, lightThemeId: String, darkThemeId: String) { + self.mode = mode + applyApplicationAppearance(mode) + updateSystemAppearanceObserver(mode) - func importTheme(from url: URL) throws -> ThemeDefinition { - let theme = try ThemeStorage.importTheme(from: url) - reloadAvailableThemes() - return theme - } + let selection = ThemeResolver.resolve( + mode: mode, + lightThemeId: lightThemeId, + darkThemeId: darkThemeId, + themes: ThemeCatalog.shared.themes, + systemIsDark: Self.systemIsDark() + ) - func exportTheme(_ theme: ThemeDefinition, to url: URL) throws { - try ThemeStorage.exportTheme(theme, to: url) + adopt(selection) } - var registryThemes: [ThemeDefinition] { - availableThemes.filter(\.isRegistry) + internal func apply(typography: TypographySettings) { + guard typography != self.typography else { return } + self.typography = typography + editorFonts = EditorFontCache(from: typography) + dataGridFonts = DataGridFontCache(from: typography) + bumpRevision() + publishChange() } - func uninstallRegistryTheme(registryPluginId: String) throws { - try ThemeRegistryInstaller.shared.uninstall(registryPluginId: registryPluginId) + /// Called when the catalog changes under a selection that is already live, so a saved edit is + /// visible without the settings round trip that used to re-activate a stale cached copy. + internal func reapply(lightThemeId: String, darkThemeId: String) { + apply(mode: mode, lightThemeId: lightThemeId, darkThemeId: darkThemeId) } - func reloadAvailableThemes() { - Task { - let themes = await Task.detached { ThemeStorage.loadAllThemes() }.value - self.availableThemes = themes - } - } + /// The resolver's output applied to the engine. Every entry point above funnels here, and it + /// is the seam a test uses to put a known pair in front of the grid without touching settings. + internal func adopt(_ selection: ThemeSelection) { + let appearanceChanged = selection.effectiveAppearance != effectiveAppearance + let pairChanged = selection.pair != pair - // MARK: - Editor Font Size Zoom + guard appearanceChanged || pairChanged else { return } - func adjustEditorFontSize(by delta: Int) { - var theme = activeTheme - let newSize = max(9, min(24, theme.fonts.editorFontSize + delta)) - guard newSize != theme.fonts.editorFontSize else { return } - theme.fonts.editorFontSize = newSize - activeTheme = theme - editorFonts = EditorFontCache(from: theme.fonts) - notifyThemeDidChange() + pair = selection.pair + effectiveAppearance = selection.effectiveAppearance + ThemeSource.shared.update(selection.pair) - // Persist so the zoom survives re-activation (e.g. system appearance change) - if theme.isEditable { - try? ThemeStorage.saveUserTheme(theme) + if pairChanged { + bumpRevision() } - } - - // MARK: - Font Cache Reload (accessibility) + resolved = ResolvedTheme(definition: activeTheme, appearance: effectiveAppearance) - func reloadFontCaches() { - editorFonts = EditorFontCache(from: activeTheme.fonts) - dataGridFonts = DataGridFontCacheResolved(from: activeTheme.fonts) - notifyThemeDidChange() + publishChange() + Self.logger.info("Theme \(self.activeTheme.id, privacy: .public) revision \(self.revision)") } - // MARK: - Update Editor Behavioral Settings - - func updateEditorSettings( - highlightCurrentLine: Bool, - highlightCurrentStatement: Bool, - showLineNumbers: Bool, - tabWidth: Int, - wordWrap: Bool - ) { - self.highlightCurrentLine = highlightCurrentLine - self.highlightCurrentStatement = highlightCurrentStatement - self.showLineNumbers = showLineNumbers - self.tabWidth = tabWidth - self.wordWrap = wordWrap + private func bumpRevision() { + revision += 1 + palette = ThemePalette(revision: revision) } - // MARK: - CodeEditSourceEditor Theme - - func makeEditorTheme() -> EditorTheme { - let c = colors.editor - - let textAttr = EditorTheme.Attribute(color: srgb(c.text)) - let commentAttr = EditorTheme.Attribute(color: srgb(c.comment)) - let keywordAttr = EditorTheme.Attribute(color: srgb(c.keyword), bold: true) - let stringAttr = EditorTheme.Attribute(color: srgb(c.string)) - let numberAttr = EditorTheme.Attribute(color: srgb(c.number)) - let variableAttr = EditorTheme.Attribute(color: srgb(c.null)) - let typeAttr = EditorTheme.Attribute(color: srgb(c.type)) - let operatorAttr = EditorTheme.Attribute(color: srgb(c.operator)) - let functionAttr = EditorTheme.Attribute(color: srgb(c.function)) - - let lineHighlight: NSColor = highlightCurrentLine ? c.currentLineHighlight : .clear - let statementHighlight: NSColor = highlightCurrentStatement ? resolvedStatementHighlight(c) : .clear - - return EditorTheme( - text: textAttr, - insertionPoint: srgb(c.cursor), - invisibles: EditorTheme.Attribute(color: srgb(c.invisibles)), - background: srgb(c.background), - lineHighlight: srgb(lineHighlight), - statementHighlight: srgb(statementHighlight), - selection: srgb(c.selection), - keywords: keywordAttr, - commands: keywordAttr, - types: typeAttr, - attributes: variableAttr, - variables: variableAttr, - values: variableAttr, - numbers: numberAttr, - strings: stringAttr, - characters: stringAttr, - comments: commentAttr, - operators: operatorAttr, - functions: functionAttr - ) - } - - /// The band's colour, corrected for a theme that never declared one. - /// - /// `EditorThemeColors` falls back to its light defaults for any key a theme omits, and every theme written before - /// this key existed omits it. On a dark custom theme that fallback is a near-black wash on a near-black - /// background: invisible, and indistinguishable from the feature being broken. Deriving the band from the - /// theme's own text colour instead is what the gutter glyph already does. - private func resolvedStatementHighlight(_ colors: ResolvedEditorColors) -> NSColor { - let declared = colors.currentStatementHighlight - let backgroundIsDark = (colors.background.usingColorSpace(.deviceRGB)?.brightnessComponent ?? 1) < 0.5 - let bandIsDark = (declared.usingColorSpace(.deviceRGB)?.brightnessComponent ?? 0) < 0.5 - guard backgroundIsDark, bandIsDark else { return declared } - return colors.text.withAlphaComponent(declared.alphaComponent) + private func publishChange() { + AppEvents.shared.themeChanged.send(change) } - // MARK: - Appearance - - @ObservationIgnored private(set) var appearanceMode: AppAppearanceMode = .auto - private(set) var effectiveAppearance: ThemeAppearance = .light - @ObservationIgnored private var currentLightThemeId: String = "tablepro.default-light" - @ObservationIgnored private var currentDarkThemeId: String = "tablepro.default-dark" - @ObservationIgnored private var systemAppearanceObservation: NSKeyValueObservation? - - /// Central entry point: resolves effective appearance, picks the correct theme, activates it, - /// and derives NSApp.appearance from the theme's own appearance metadata. - func updateAppearanceAndTheme( - mode: AppAppearanceMode, - lightThemeId: String, - darkThemeId: String - ) { - appearanceMode = mode - currentLightThemeId = lightThemeId - currentDarkThemeId = darkThemeId - - applyNSAppAppearance(mode: mode) - - let resolved = resolveEffectiveAppearance(mode) - effectiveAppearance = resolved - - let themeId = resolved == .dark ? darkThemeId : lightThemeId - activateTheme(id: themeId) - - updateSystemAppearanceObserver(mode: mode) - } + // MARK: - Application appearance - /// Resolve which appearance is in effect right now. - private func resolveEffectiveAppearance(_ mode: AppAppearanceMode) -> ThemeAppearance { + private func applyApplicationAppearance(_ mode: AppAppearanceMode) { switch mode { - case .light: return .light - case .dark: return .dark - case .auto: return systemIsDark() ? .dark : .light + case .light: NSApp?.appearance = NSAppearance(named: .aqua) + case .dark: NSApp?.appearance = NSAppearance(named: .darkAqua) + case .auto: NSApp?.appearance = nil } } - private func systemIsDark() -> Bool { - NSApp?.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua + private static func systemIsDark() -> Bool { + NSApp?.effectiveAppearance.bestMatch(from: [.aqua, .darkAqua]) == .darkAqua } - /// Set NSApp.appearance based on the appearance mode (not the theme). - /// Auto mode sets nil so the system controls the chrome. - private func applyNSAppAppearance(mode: AppAppearanceMode) { - switch mode { - case .light: - NSApp?.appearance = NSAppearance(named: .aqua) - case .dark: - NSApp?.appearance = NSAppearance(named: .darkAqua) - case .auto: - NSApp?.appearance = nil - } - } - - // MARK: - System Appearance Observer - - private func updateSystemAppearanceObserver(mode: AppAppearanceMode) { - systemAppearanceObservation = nil - + /// KVO on `NSApplication.effectiveAppearance` is the channel Apple names in the + /// `NSControlTintDidChangeNotification` deprecation text. Only the static tier and the change + /// signal depend on it: the dynamic slot colours answer for the drawing appearance themselves. + private func updateSystemAppearanceObserver(_ mode: AppAppearanceMode) { + appearanceObservation = nil guard mode == .auto else { return } - systemAppearanceObservation = NSApp?.observe(\.effectiveAppearance) { [weak self] _, _ in + appearanceObservation = NSApp?.observe(\.effectiveAppearance) { [weak self] _, _ in Task { @MainActor [weak self] in - guard let self, self.appearanceMode == .auto else { return } - let newAppearance: ThemeAppearance = self.systemIsDark() ? .dark : .light - guard newAppearance != self.effectiveAppearance else { return } - self.effectiveAppearance = newAppearance - let themeId = newAppearance == .dark ? self.currentDarkThemeId : self.currentLightThemeId - self.activateTheme(id: themeId) + self?.systemAppearanceDidChange() } } } - // MARK: - Notifications + private func systemAppearanceDidChange() { + guard mode == .auto else { return } + let appearance: ThemeAppearance = Self.systemIsDark() ? .dark : .light + guard appearance != effectiveAppearance else { return } + + effectiveAppearance = appearance + resolved = ResolvedTheme(definition: activeTheme, appearance: appearance) + publishChange() + } + + // MARK: - CodeEditSourceEditor - private func notifyThemeDidChange() { - AppEvents.shared.themeChanged.send(()) + internal func makeEditorTheme() -> EditorTheme { + let editorSettings = AppSettingsManager.shared.editor + let text = EditorTheme.Attribute(color: resolved[.editorText]) + let comment = EditorTheme.Attribute(color: resolved[.syntaxComment]) + let keyword = EditorTheme.Attribute(color: resolved[.syntaxKeyword], bold: true) + let string = EditorTheme.Attribute(color: resolved[.syntaxString]) + let number = EditorTheme.Attribute(color: resolved[.syntaxNumber]) + let variable = EditorTheme.Attribute(color: resolved[.syntaxNull]) + let type = EditorTheme.Attribute(color: resolved[.syntaxType]) + let operatorAttribute = EditorTheme.Attribute(color: resolved[.syntaxOperator]) + let function = EditorTheme.Attribute(color: resolved[.syntaxFunction]) + + return EditorTheme( + text: text, + insertionPoint: resolved[.editorCursor], + invisibles: EditorTheme.Attribute(color: resolved[.editorInvisibles]), + background: resolved[.editorBackground], + lineHighlight: editorSettings.highlightCurrentLine ? resolved[.editorCurrentLine] : .clear, + statementHighlight: editorSettings.highlightCurrentStatement ? resolved[.editorCurrentStatement] : .clear, + selection: resolved[.editorSelection], + lineNumber: resolved[.editorLineNumber], + keywords: keyword, + commands: keyword, + types: type, + attributes: variable, + variables: variable, + values: variable, + numbers: number, + strings: string, + characters: string, + comments: comment, + operators: operatorAttribute, + functions: function + ) } // MARK: - Accessibility private func observeAccessibilityChanges() { - lastAccessibilityScale = EditorFontCache.computeAccessibilityScale() + lastAccessibilityScale = EditorFontCache.accessibilityScale() accessibilityObserver = NSWorkspace.shared.notificationCenter.addObserver( forName: NSWorkspace.accessibilityDisplayOptionsDidChangeNotification, object: nil, queue: .main ) { [weak self] _ in Task { @MainActor [weak self] in - guard let self else { return } - let newScale = EditorFontCache.computeAccessibilityScale() - guard abs(newScale - lastAccessibilityScale) > 0.01 else { return } - lastAccessibilityScale = newScale - Self.logger.debug("Accessibility text size changed, scale: \(newScale, format: .fixed(precision: 2))") - reloadFontCaches() - AppEvents.shared.accessibilityTextSizeChanged.send(()) + self?.accessibilityDisplayOptionsDidChange() } } } - // MARK: - Helpers + private func accessibilityDisplayOptionsDidChange() { + let scale = EditorFontCache.accessibilityScale() + guard abs(scale - lastAccessibilityScale) > 0.01 else { return } + lastAccessibilityScale = scale - private func srgb(_ color: NSColor) -> NSColor { - if let converted = color.usingColorSpace(.sRGB) { - return converted - } - var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0 - if let deviceRgb = color.usingColorSpace(.deviceRGB) { - deviceRgb.getRed(&r, green: &g, blue: &b, alpha: &a) - } - return NSColor(srgbRed: r, green: g, blue: b, alpha: a) + editorFonts = EditorFontCache(from: typography) + dataGridFonts = DataGridFontCache(from: typography) + bumpRevision() + publishChange() + AppEvents.shared.accessibilityTextSizeChanged.send(()) } } -// MARK: - Database Type Colors (preserved from old Theme.swift) - -extension DatabaseType { +internal extension DatabaseType { @MainActor var themeColor: Color { PluginManager.shared.brandColor(for: self) } } - -// MARK: - View Extensions (preserved from old Theme.swift) - -extension View { - func cardStyle() -> some View { - self - .background(Color(nsColor: .controlBackgroundColor)) - .clipShape(RoundedRectangle(cornerRadius: 6)) - } -} diff --git a/TablePro/Theme/ThemeFonts.swift b/TablePro/Theme/ThemeFonts.swift deleted file mode 100644 index 8fa0901dd9..0000000000 --- a/TablePro/Theme/ThemeFonts.swift +++ /dev/null @@ -1,42 +0,0 @@ -// -// ThemeFonts.swift -// TablePro -// - -import Foundation - -// MARK: - Theme Fonts - -internal struct ThemeFonts: Codable, Equatable, Sendable { - var editorFontFamily: String - var editorFontSize: Int - var dataGridFontFamily: String - var dataGridFontSize: Int - - static let `default` = ThemeFonts( - editorFontFamily: "System Mono", - editorFontSize: 13, - dataGridFontFamily: "System Mono", - dataGridFontSize: 13 - ) - - init(editorFontFamily: String, editorFontSize: Int, dataGridFontFamily: String, dataGridFontSize: Int) { - self.editorFontFamily = editorFontFamily - self.editorFontSize = editorFontSize - self.dataGridFontFamily = dataGridFontFamily - self.dataGridFontSize = dataGridFontSize - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let fallback = ThemeFonts.default - - editorFontFamily = try container.decodeIfPresent(String.self, forKey: .editorFontFamily) - ?? fallback.editorFontFamily - editorFontSize = try container.decodeIfPresent(Int.self, forKey: .editorFontSize) ?? fallback.editorFontSize - dataGridFontFamily = try container.decodeIfPresent(String.self, forKey: .dataGridFontFamily) - ?? fallback.dataGridFontFamily - dataGridFontSize = try container.decodeIfPresent(Int.self, forKey: .dataGridFontSize) - ?? fallback.dataGridFontSize - } -} diff --git a/TablePro/Theme/ThemeLoadError.swift b/TablePro/Theme/ThemeLoadError.swift new file mode 100644 index 0000000000..9c20973d08 --- /dev/null +++ b/TablePro/Theme/ThemeLoadError.swift @@ -0,0 +1,55 @@ +import Foundation + +internal enum ThemeLoadError: LocalizedError, Equatable { + case missingSchema + case schemaTooOld(found: Int, supported: Int) + case schemaTooNew(found: Int, supported: Int) + case missingField(String) + case missingSlots([String]) + case invalidColor(String) + case unknownSystemColor(String) + case unknownKeys([String]) + case reservedIdentifier(String) + case invalidIdentifier(String) + + internal var errorDescription: String? { + switch self { + case .missingSchema: + return String(localized: "The file does not declare a theme format version.") + case let .schemaTooOld(found, supported): + return String( + format: String(localized: "Theme format %1$d is no longer supported. This version of TablePro reads format %2$d."), + found, + supported + ) + case let .schemaTooNew(found, supported): + return String( + format: String(localized: "Theme format %1$d was made for a newer TablePro. This version reads format %2$d."), + found, + supported + ) + case let .missingField(name): + return String(format: String(localized: "The theme is missing the required field \"%@\"."), name) + case let .missingSlots(names): + return String( + format: String(localized: "The theme is missing %1$d required colors, starting with \"%2$@\"."), + names.count, + names.first ?? "" + ) + case let .invalidColor(value): + return String(format: String(localized: "\"%@\" is not a valid color."), value) + case let .unknownSystemColor(name): + return String(format: String(localized: "\"%@\" is not a system color TablePro knows."), name) + case let .unknownKeys(names): + return String( + format: String(localized: "The theme declares %1$d colors TablePro does not use, starting with \"%2$@\"."), + names.count, + names.first ?? "" + ) + case let .reservedIdentifier(identifier): + return String(format: String(localized: "\"%@\" is a reserved theme identifier."), identifier) + case let .invalidIdentifier(identifier): + return String(format: String(localized: "\"%@\" is not a valid theme identifier."), identifier) + } + } +} diff --git a/TablePro/Theme/ThemePalette.swift b/TablePro/Theme/ThemePalette.swift new file mode 100644 index 0000000000..18d1a88c31 --- /dev/null +++ b/TablePro/Theme/ThemePalette.swift @@ -0,0 +1,134 @@ +import AppKit +import os +import SwiftUI + +internal struct ThemePair: Equatable, Sendable { + var light: ThemeDefinition + var dark: ThemeDefinition + + internal subscript(appearance: ThemeAppearance) -> ThemeDefinition { + switch appearance { + case .light: return light + case .dark: return dark + } + } + + internal static let builtIn = ThemePair(light: BuiltInThemes.light, dark: BuiltInThemes.dark) +} + +/// The live pair every dynamic slot colour reads through. A colour object an AppKit view is +/// already holding therefore answers for the theme in effect now, the way `NSColor.labelColor` +/// does, so marking that view for display is enough. Capturing the pair inside the provider +/// instead would freeze each colour at the revision that built it. +internal final class ThemeSource: Sendable { + internal static let shared = ThemeSource() + + private let state = OSAllocatedUnfairLock(initialState: ThemePair.builtIn) + + internal var pair: ThemePair { + state.withLock { $0 } + } + + internal func update(_ pair: ThemePair) { + state.withLock { $0 = pair } + } +} + +/// The dynamic tier. One `NSColor(name:dynamicProvider:)` per slot, so a slot resolves against +/// whatever appearance the view is drawing in, including the vibrant appearances inside a sidebar. +/// The revision only names the colour: SwiftUI caches `Color(nsColor:)` by object identity, so a +/// stable object would never repaint on a theme swap even though the provider answers correctly. +internal struct ThemePalette { + internal let revision: Int + + private let colors: [ThemeSlot: NSColor] + + internal init(revision: Int, source: ThemeSource = .shared) { + self.revision = revision + + var built: [ThemeSlot: NSColor] = [:] + built.reserveCapacity(ThemeSlot.allCases.count) + + for slot in ThemeSlot.allCases { + let name = NSColor.Name("tablepro.\(slot.rawValue).\(revision)") + built[slot] = NSColor(name: name) { appearance in + let definition = source.pair[ThemeAppearance(matching: appearance)] + return definition[keyPath: slot.keyPath].nsColor + } + } + + colors = built + } + + internal subscript(slot: ThemeSlot) -> NSColor { + colors[slot] ?? .labelColor + } + + internal func color(_ slot: ThemeSlot) -> Color { + Color(nsColor: self[slot]) + } +} + +/// The static tier. Snapshot consumers (the CodeEdit `EditorTheme`, `CALayer` colours, the data +/// grid's per-cell draw path) resolve once against the appearance the app has actually settled on. +/// They must not resolve a dynamic colour implicitly: outside a draw pass +/// `NSAppearance.currentDrawing()` still reports the old appearance for at least half a second +/// after `NSApp.appearance` changes, and a dynamic `cgColor` costs 254ns against 11ns for a +/// static one, which the grid pays per cell. +internal struct ResolvedTheme: Equatable { + internal let definition: ThemeDefinition + internal let appearance: ThemeAppearance + + private let colors: [ThemeSlot: NSColor] + + internal init(definition: ThemeDefinition, appearance: ThemeAppearance) { + self.definition = definition + self.appearance = appearance + + let nsAppearance = NSAppearance(named: appearance == .dark ? .darkAqua : .aqua) + var built: [ThemeSlot: NSColor] = [:] + built.reserveCapacity(ThemeSlot.allCases.count) + + let resolve = { + for slot in ThemeSlot.allCases { + let value = definition[keyPath: slot.keyPath] + built[slot] = value.nsColor.usingColorSpace(.sRGB) ?? value.nsColor + } + } + + if let nsAppearance { + nsAppearance.performAsCurrentDrawingAppearance(resolve) + } else { + resolve() + } + + colors = built + } + + internal subscript(slot: ThemeSlot) -> NSColor { + colors[slot] ?? .labelColor + } + + internal func color(_ slot: ThemeSlot) -> Color { + Color(nsColor: self[slot]) + } + + internal func cgColor(_ slot: ThemeSlot) -> CGColor { + self[slot].cgColor + } +} + +internal extension ThemeAppearance { + init(matching appearance: NSAppearance) { + let match = appearance.bestMatch(from: [.aqua, .darkAqua]) + self = match == .darkAqua ? .dark : .light + } +} + +/// Sent on a theme change and on an effective-appearance change, because the snapshot consumers +/// need both: a forced Light/Dark switch never changes the theme pair, and a theme switch never +/// changes the appearance. +internal struct ThemeChange: Equatable, Sendable { + internal let revision: Int + internal let appearance: ThemeAppearance +} diff --git a/TablePro/Theme/ThemeRegistryInstaller.swift b/TablePro/Theme/ThemeRegistryInstaller.swift index 4a7644a43f..fcdca6fdd0 100644 --- a/TablePro/Theme/ThemeRegistryInstaller.swift +++ b/TablePro/Theme/ThemeRegistryInstaller.swift @@ -31,10 +31,12 @@ internal final class ThemeRegistryInstaller { let decodedThemes = try await downloadAndDecode(plugin, progress: progress) + _ = try? removeRegistryFiles(for: plugin.id) + var installedThemes: [InstalledRegistryTheme] = [] for theme in decodedThemes { - try ThemeStorage.saveRegistryTheme(theme) + try ThemeCatalog.shared.saveRegistryTheme(theme) installedThemes.append(InstalledRegistryTheme( id: theme.id, @@ -44,11 +46,12 @@ internal final class ThemeRegistryInstaller { )) } - var meta = ThemeStorage.loadRegistryMeta() + var meta = ThemeCatalog.shared.loadRegistryMeta() meta.installed.append(contentsOf: installedThemes) - try ThemeStorage.saveRegistryMeta(meta) + try ThemeCatalog.shared.saveRegistryMeta(meta) - ThemeEngine.shared.reloadAvailableThemes() + ThemeCatalog.shared.reloadSynchronously() + reactivate() progress(1.0) Self.logger.info("Installed \(installedThemes.count) theme(s) from registry plugin: \(plugin.id)") @@ -57,26 +60,10 @@ internal final class ThemeRegistryInstaller { // MARK: - Uninstall func uninstall(registryPluginId: String) throws { - let removedThemeIds = try removeRegistryFiles(for: registryPluginId) - - ThemeEngine.shared.reloadAvailableThemes() + _ = try removeRegistryFiles(for: registryPluginId) - // Reset preferred theme slots if the uninstalled theme was preferred - var appearance = AppSettingsManager.shared.appearance - var changed = false - for id in removedThemeIds { - if id == appearance.preferredLightThemeId { - appearance.preferredLightThemeId = "tablepro.default-light" - changed = true - } - if id == appearance.preferredDarkThemeId { - appearance.preferredDarkThemeId = "tablepro.default-dark" - changed = true - } - } - if changed { - AppSettingsManager.shared.appearance = appearance - } + ThemeCatalog.shared.reloadSynchronously() + reactivate() Self.logger.info("Uninstalled registry themes for plugin: \(registryPluginId)") } @@ -87,9 +74,6 @@ internal final class ThemeRegistryInstaller { _ plugin: RegistryPlugin, progress: @escaping @MainActor @Sendable (Double) -> Void ) async throws { - let activeId = ThemeEngine.shared.activeTheme.id - - // Download, verify, and decode new themes first (no side effects yet) let stagedThemes = try await downloadAndDecode(plugin, progress: progress) // Remove old files without triggering theme reload or fallback @@ -97,7 +81,7 @@ internal final class ThemeRegistryInstaller { var installedThemes: [InstalledRegistryTheme] = [] for theme in stagedThemes { - try ThemeStorage.saveRegistryTheme(theme) + try ThemeCatalog.shared.saveRegistryTheme(theme) installedThemes.append(InstalledRegistryTheme( id: theme.id, registryPluginId: plugin.id, @@ -106,20 +90,12 @@ internal final class ThemeRegistryInstaller { )) } - var meta = ThemeStorage.loadRegistryMeta() + var meta = ThemeCatalog.shared.loadRegistryMeta() meta.installed.append(contentsOf: installedThemes) - try ThemeStorage.saveRegistryMeta(meta) + try ThemeCatalog.shared.saveRegistryMeta(meta) - // Single reload after swap is complete — no intermediate flicker - ThemeEngine.shared.reloadAvailableThemes() - - // Re-activate the correct theme for the current appearance - let appearance = AppSettingsManager.shared.appearance - ThemeEngine.shared.updateAppearanceAndTheme( - mode: appearance.appearanceMode, - lightThemeId: appearance.preferredLightThemeId, - darkThemeId: appearance.preferredDarkThemeId - ) + ThemeCatalog.shared.reloadSynchronously() + reactivate() Self.logger.info("Updated \(installedThemes.count) theme(s) for registry plugin: \(plugin.id)") } @@ -128,16 +104,16 @@ internal final class ThemeRegistryInstaller { /// Does NOT reload ThemeEngine or trigger fallback — callers manage that. @discardableResult private func removeRegistryFiles(for registryPluginId: String) throws -> Set { - var meta = ThemeStorage.loadRegistryMeta() + var meta = ThemeCatalog.shared.loadRegistryMeta() let themesToRemove = meta.installed.filter { $0.registryPluginId == registryPluginId } let removedIds = Set(themesToRemove.map(\.id)) meta.installed.removeAll { $0.registryPluginId == registryPluginId } - try ThemeStorage.saveRegistryMeta(meta) + try ThemeCatalog.shared.saveRegistryMeta(meta) for entry in themesToRemove { do { - try ThemeStorage.deleteRegistryTheme(id: entry.id) + try ThemeCatalog.shared.deleteRegistryTheme(id: entry.id) } catch { Self.logger.warning("Failed to delete registry theme file \(entry.id): \(error)") } @@ -149,17 +125,20 @@ internal final class ThemeRegistryInstaller { // MARK: - Query func isInstalled(_ registryPluginId: String) -> Bool { - let meta = ThemeStorage.loadRegistryMeta() - return meta.installed.contains { $0.registryPluginId == registryPluginId } + let entries = ThemeCatalog.shared.loadRegistryMeta().installed + .filter { $0.registryPluginId == registryPluginId } + + guard !entries.isEmpty else { return false } + return entries.allSatisfy { ThemeCatalog.shared.theme(id: $0.id) != nil } } func installedVersion(for registryPluginId: String) -> String? { - let meta = ThemeStorage.loadRegistryMeta() + let meta = ThemeCatalog.shared.loadRegistryMeta() return meta.installed.first { $0.registryPluginId == registryPluginId }?.version } func availableUpdates(manifest: RegistryManifest) -> [RegistryPlugin] { - let meta = ThemeStorage.loadRegistryMeta() + let meta = ThemeCatalog.shared.loadRegistryMeta() let installedVersions = Dictionary( meta.installed.map { ($0.registryPluginId, $0.version) }, uniquingKeysWith: { first, _ in first } @@ -250,14 +229,12 @@ internal final class ThemeRegistryInstaller { progress(0.9) - let decoder = JSONDecoder() var decodedThemes: [ThemeDefinition] = [] for jsonURL in jsonFiles { - let data = try Data(contentsOf: jsonURL) - var theme = try decoder.decode(ThemeDefinition.self, from: data) - let originalId = theme.id - theme.id = "registry.\(plugin.id).\(originalId)" + let document = try ThemeDocument(data: try Data(contentsOf: jsonURL)) + var theme = document.resolved() + theme.id = "\(ThemeDefinition.registryPrefix)\(plugin.id).\(theme.id)" decodedThemes.append(theme) } @@ -271,6 +248,14 @@ internal final class ThemeRegistryInstaller { // MARK: - Helpers + private func reactivate() { + let appearance = AppSettingsManager.shared.appearance + ThemeEngine.shared.reapply( + lightThemeId: appearance.preferredLightThemeId, + darkThemeId: appearance.preferredDarkThemeId + ) + } + private func findJsonFiles(in directory: URL) throws -> [URL] { var results: [URL] = [] let fm = FileManager.default diff --git a/TablePro/Theme/ThemeResolver.swift b/TablePro/Theme/ThemeResolver.swift new file mode 100644 index 0000000000..084548c3ad --- /dev/null +++ b/TablePro/Theme/ThemeResolver.swift @@ -0,0 +1,68 @@ +import Foundation + +internal struct ThemeSelection: Equatable, Sendable { + internal let pair: ThemePair + internal let effectiveAppearance: ThemeAppearance + + internal var active: ThemeDefinition { pair[effectiveAppearance] } +} + +/// Pure. It never writes settings: a settings pane that rewrote the saved theme id to make its own +/// filter true silently replaced a theme the user had chosen and then hid it from the list they +/// would have used to put it back. A slot whose theme is missing, rejected, or of the wrong +/// appearance falls back to that slot's own built-in, so a broken dark theme never paints Default +/// Light inside dark chrome. +internal enum ThemeResolver { + internal static func resolve( + mode: AppAppearanceMode, + lightThemeId: String, + darkThemeId: String, + themes: [ThemeDefinition], + systemIsDark: Bool + ) -> ThemeSelection { + let pair = ThemePair( + light: theme(id: lightThemeId, slot: .light, in: themes), + dark: theme(id: darkThemeId, slot: .dark, in: themes) + ) + + return ThemeSelection( + pair: pair, + effectiveAppearance: effectiveAppearance(mode: mode, systemIsDark: systemIsDark) + ) + } + + internal static func effectiveAppearance(mode: AppAppearanceMode, systemIsDark: Bool) -> ThemeAppearance { + switch mode { + case .light: return .light + case .dark: return .dark + case .auto: return systemIsDark ? .dark : .light + } + } + + private static func theme( + id: String, + slot: ThemeAppearance, + in themes: [ThemeDefinition] + ) -> ThemeDefinition { + guard let found = themes.first(where: { $0.id == id }), found.appearance == slot else { + return BuiltInThemes.default(for: slot) + } + return found + } +} + +/// The list a slot offers. A theme only fits the slot whose appearance it declares, and the theme +/// the slot already holds stays listed so the user can always see and re-pick their own choice. +internal enum ThemeSlotValidation { + internal static func fits(_ appearance: ThemeAppearance, slot: ThemeAppearance) -> Bool { + appearance == slot + } + + internal static func eligibleThemes( + _ themes: [ThemeDefinition], + slot: ThemeAppearance, + keeping selectedId: String? + ) -> [ThemeDefinition] { + themes.filter { fits($0.appearance, slot: slot) || $0.id == selectedId } + } +} diff --git a/TablePro/Theme/ThemeSlotValidation.swift b/TablePro/Theme/ThemeSlotValidation.swift deleted file mode 100644 index 61343bd965..0000000000 --- a/TablePro/Theme/ThemeSlotValidation.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// ThemeSlotValidation.swift -// TablePro -// - -import Foundation - -/// `ThemeDefinition.appearance` was declared but never read, so a dark theme could be assigned to -/// the light slot and the app would honour it. The list is filtered to the themes that suit the -/// slot, and the theme the slot already holds is always kept in it. -/// -/// Rewriting the saved id to make the filter true is not an option: a settings pane is a -/// presentation surface, and the rewrite fired on appear, so opening Appearance silently replaced -/// a theme the user had chosen and then hid it from the list they would have used to put it back. -internal enum ThemeSlotValidation { - internal static func fits(_ appearance: ThemeAppearance, slot: ThemeAppearance) -> Bool { - appearance == .auto || appearance == slot - } - - internal static func eligibleThemes( - _ themes: [ThemeDefinition], - slot: ThemeAppearance, - keeping selectedId: String? - ) -> [ThemeDefinition] { - themes.filter { fits($0.appearance, slot: slot) || $0.id == selectedId } - } -} diff --git a/TablePro/Theme/ThemeStorage.swift b/TablePro/Theme/ThemeStorage.swift deleted file mode 100644 index c0cbf9f154..0000000000 --- a/TablePro/Theme/ThemeStorage.swift +++ /dev/null @@ -1,258 +0,0 @@ -// -// ThemeStorage.swift -// TablePro -// -// File I/O for theme JSON files. -// Built-in themes loaded from app bundle, user themes from Application Support. -// - -import Foundation -import os - -internal struct ThemeStorage { - private static let logger = Logger(subsystem: "com.TablePro", category: "ThemeStorage") - - private static let userThemesDirectory: URL = - AppStorageEnvironment.shared.applicationSupportRoot.appendingPathComponent("TablePro/Themes", isDirectory: true) - - private static let bundledThemesDirectory: URL? = { - Bundle.main.resourceURL - }() - - private static let registryThemesDirectory: URL = { - userThemesDirectory.appendingPathComponent("Registry", isDirectory: true) - }() - - private static func themeFileURL(in directory: URL, id: String) throws -> URL { - let allowed = #"^[A-Za-z0-9._-]+$"# - guard id.range(of: allowed, options: .regularExpression) != nil else { - throw CocoaError(.fileWriteInvalidFileName) - } - return directory.appendingPathComponent("\(id).json", isDirectory: false) - } - - // MARK: - Load All Themes - - static func loadAllThemes() -> [ThemeDefinition] { - var themes: [ThemeDefinition] = [] - - // Load built-in themes from app bundle (files copied flat to Resources/) - if let bundleDir = bundledThemesDirectory { - themes.append(contentsOf: loadBuiltInThemes(from: bundleDir)) - } - - if themes.isEmpty { - themes = [ThemeDefinition.default] - } - - ensureRegistryDirectory() - themes.append(contentsOf: loadThemes(from: registryThemesDirectory, isBuiltIn: false)) - - ensureUserDirectory() - themes.append(contentsOf: loadThemes(from: userThemesDirectory, isBuiltIn: false)) - - return themes - } - - // MARK: - Load Single Theme - - static func loadTheme(id: String) -> ThemeDefinition? { - let fm = FileManager.default - - if let userFile = try? themeFileURL(in: userThemesDirectory, id: id), - fm.fileExists(atPath: userFile.path), - let theme = loadTheme(from: userFile) { - return theme - } - - if let registryFile = try? themeFileURL(in: registryThemesDirectory, id: id), - fm.fileExists(atPath: registryFile.path), - let theme = loadTheme(from: registryFile) { - return theme - } - - // User themes are never bundled; skip the bundle search for them. - if !id.hasPrefix("user."), - let bundleDir = bundledThemesDirectory, - let bundleFile = try? themeFileURL(in: bundleDir, id: id), - fm.fileExists(atPath: bundleFile.path), - let theme = loadTheme(from: bundleFile) { - return theme - } - - return id == ThemeDefinition.default.id ? .default : nil - } - - // MARK: - Save User Theme - - static func saveUserTheme(_ theme: ThemeDefinition) throws { - ensureUserDirectory() - let url = try themeFileURL(in: userThemesDirectory, id: theme.id) - let encoder = JSONEncoder() - encoder.outputFormatting = [.prettyPrinted, .sortedKeys] - let data = try encoder.encode(theme) - try data.write(to: url, options: .atomic) - logger.info("Saved user theme: \(theme.id)") - } - - // MARK: - Delete User Theme - - static func deleteUserTheme(id: String) throws { - let url = try themeFileURL(in: userThemesDirectory, id: id) - guard FileManager.default.fileExists(atPath: url.path) else { return } - try FileManager.default.removeItem(at: url) - logger.info("Deleted user theme: \(id)") - } - - // MARK: - Save Registry Theme - - static func saveRegistryTheme(_ theme: ThemeDefinition) throws { - ensureRegistryDirectory() - let url = try themeFileURL(in: registryThemesDirectory, id: theme.id) - let encoder = JSONEncoder() - encoder.outputFormatting = [.prettyPrinted, .sortedKeys] - let data = try encoder.encode(theme) - try data.write(to: url, options: .atomic) - logger.info("Saved registry theme: \(theme.id)") - } - - // MARK: - Delete Registry Theme - - static func deleteRegistryTheme(id: String) throws { - let url = try themeFileURL(in: registryThemesDirectory, id: id) - guard FileManager.default.fileExists(atPath: url.path) else { return } - try FileManager.default.removeItem(at: url) - logger.info("Deleted registry theme: \(id)") - } - - // MARK: - Registry Meta - - private static let registryMetaURL: URL = { - registryThemesDirectory.appendingPathComponent("registry-meta.json") - }() - - static func loadRegistryMeta() -> RegistryThemeMeta { - guard FileManager.default.fileExists(atPath: registryMetaURL.path) else { - return RegistryThemeMeta() - } - do { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .iso8601 - let data = try Data(contentsOf: registryMetaURL) - return try decoder.decode(RegistryThemeMeta.self, from: data) - } catch { - logger.error("Failed to load registry meta: \(error)") - return RegistryThemeMeta() - } - } - - static func saveRegistryMeta(_ meta: RegistryThemeMeta) throws { - ensureRegistryDirectory() - let encoder = JSONEncoder() - encoder.outputFormatting = [.prettyPrinted, .sortedKeys] - encoder.dateEncodingStrategy = .iso8601 - let data = try encoder.encode(meta) - try data.write(to: registryMetaURL, options: .atomic) - } - - // MARK: - Import / Export - - static func importTheme(from sourceURL: URL) throws -> ThemeDefinition { - let data = try Data(contentsOf: sourceURL) - var theme = try JSONDecoder().decode(ThemeDefinition.self, from: data) - - // Avoid clobbering an existing theme on import - if theme.isBuiltIn || theme.isRegistry || loadTheme(id: theme.id) != nil { - theme.id = "user.\(UUID().uuidString.lowercased().prefix(8))" - } - - try saveUserTheme(theme) - return theme - } - - static func exportTheme(_ theme: ThemeDefinition, to destinationURL: URL) throws { - let encoder = JSONEncoder() - encoder.outputFormatting = [.prettyPrinted, .sortedKeys] - let data = try encoder.encode(theme) - try data.write(to: destinationURL, options: .atomic) - logger.info("Exported theme: \(theme.id) to \(destinationURL.lastPathComponent)") - } - - // MARK: - Helpers - - private static func ensureUserDirectory() { - let fm = FileManager.default - if !fm.fileExists(atPath: userThemesDirectory.path) { - do { - try fm.createDirectory(at: userThemesDirectory, withIntermediateDirectories: true) - } catch { - logger.error("Failed to create user themes directory: \(error)") - } - } - } - - private static func ensureRegistryDirectory() { - let fm = FileManager.default - if !fm.fileExists(atPath: registryThemesDirectory.path) { - do { - try fm.createDirectory(at: registryThemesDirectory, withIntermediateDirectories: true) - } catch { - logger.error("Failed to create registry themes directory: \(error)") - } - } - } - - private static let builtInThemeOrder = [ - "tablepro.default-light", - "tablepro.default-dark", - "tablepro.dracula", - "tablepro.nord", - ] - - private static func loadBuiltInThemes(from directory: URL) -> [ThemeDefinition] { - let fm = FileManager.default - guard fm.fileExists(atPath: directory.path) else { return [] } - - do { - let files = try fm.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil) - .filter { $0.pathExtension == "json" && $0.lastPathComponent.hasPrefix("tablepro.") } - - let themes = files.compactMap { loadTheme(from: $0) } - return themes.sorted { lhs, rhs in - let li = builtInThemeOrder.firstIndex(of: lhs.id) ?? Int.max - let ri = builtInThemeOrder.firstIndex(of: rhs.id) ?? Int.max - return li < ri - } - } catch { - logger.error("Failed to list built-in themes: \(error)") - return [] - } - } - - private static func loadThemes(from directory: URL, isBuiltIn: Bool) -> [ThemeDefinition] { - let fm = FileManager.default - guard fm.fileExists(atPath: directory.path) else { return [] } - - do { - let files = try fm.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil) - .filter { $0.pathExtension == "json" && $0.lastPathComponent != "registry-meta.json" } - - return files.compactMap { loadTheme(from: $0) } - } catch { - logger.error("Failed to list themes in \(directory.lastPathComponent): \(error)") - return [] - } - } - - private static func loadTheme(from url: URL) -> ThemeDefinition? { - do { - let data = try Data(contentsOf: url) - return try JSONDecoder().decode(ThemeDefinition.self, from: data) - } catch CocoaError.fileNoSuchFile, CocoaError.fileReadNoSuchFile { - return nil - } catch { - logger.error("Failed to load theme from \(url.lastPathComponent): \(error)") - return nil - } - } -} diff --git a/TablePro/Views/Compare/CompareStatusStyle.swift b/TablePro/Views/Compare/CompareStatusStyle.swift index 754ddcb06b..75d8f13350 100644 --- a/TablePro/Views/Compare/CompareStatusStyle.swift +++ b/TablePro/Views/Compare/CompareStatusStyle.swift @@ -45,16 +45,16 @@ internal enum CompareStatusStyle { @MainActor internal static func tint(for status: TableDiffStatus) -> Color { - let colors = ThemeEngine.shared.colors.ui + let palette = ThemeEngine.shared.palette switch status { case .onlyInSource: - return colors.successSwiftUI + return palette.color(.statusSuccess) case .onlyInTarget: - return colors.errorSwiftUI + return palette.color(.statusError) case .differs: - return colors.warningSwiftUI + return palette.color(.statusWarning) case .identical: - return colors.secondaryTextSwiftUI + return Color(nsColor: .secondaryLabelColor) } } @@ -88,16 +88,16 @@ internal enum CompareStatusStyle { @MainActor internal static func tint(for kind: RowDiffKind) -> Color { - let colors = ThemeEngine.shared.colors.ui + let palette = ThemeEngine.shared.palette switch kind { case .insert: - return colors.successSwiftUI + return palette.color(.statusSuccess) case .update: - return colors.warningSwiftUI + return palette.color(.statusWarning) case .delete: - return colors.errorSwiftUI + return palette.color(.statusError) case .identical: - return colors.secondaryTextSwiftUI + return Color(nsColor: .secondaryLabelColor) } } @@ -105,14 +105,14 @@ internal enum CompareStatusStyle { /// difference here reads the way the same row reads in the grid. @MainActor internal static func rowTint(for kind: RowDiffKind) -> Color { - let colors = ThemeEngine.shared.colors.dataGrid + let palette = ThemeEngine.shared.palette switch kind { case .insert: - return colors.insertedSwiftUI + return palette.color(.gridInserted) case .update: - return colors.modifiedSwiftUI + return palette.color(.gridModified) case .delete: - return colors.deletedSwiftUI + return palette.color(.gridDeleted) case .identical: return .clear } @@ -122,16 +122,16 @@ internal enum CompareStatusStyle { @MainActor internal static var warning: Color { - ThemeEngine.shared.colors.ui.warningSwiftUI + ThemeEngine.shared.palette.color(.statusWarning) } @MainActor internal static var error: Color { - ThemeEngine.shared.colors.ui.errorSwiftUI + ThemeEngine.shared.palette.color(.statusError) } @MainActor internal static var success: Color { - ThemeEngine.shared.colors.ui.successSwiftUI + ThemeEngine.shared.palette.color(.statusSuccess) } } diff --git a/TablePro/Views/Components/HighlightedSQLTextView.swift b/TablePro/Views/Components/HighlightedSQLTextView.swift index db27ed5e38..b7d34e7e21 100644 --- a/TablePro/Views/Components/HighlightedSQLTextView.swift +++ b/TablePro/Views/Components/HighlightedSQLTextView.swift @@ -13,7 +13,6 @@ import TableProPluginKit /// Read-only text view that applies SQL/MQL syntax highlighting via regex struct HighlightedSQLTextView: NSViewRepresentable { let sql: String - var fontSize: CGFloat = 13 var databaseType: DatabaseType = .mysql /// A SwiftUI `.accessibilityIdentifier` lands on the representable's wrapper, not on the text /// view AppKit publishes, so the only way to name this element is to set it on the text view. @@ -30,10 +29,10 @@ struct HighlightedSQLTextView: NSViewRepresentable { textView.setAccessibilityLabel(String(localized: "Query preview")) textView.isEditable = false textView.isSelectable = true - textView.font = NSFont.monospacedSystemFont(ofSize: fontSize, weight: .regular) + textView.font = ThemeEngine.shared.editorFonts.font textView.textContainerInset = NSSize(width: 12, height: 12) - textView.backgroundColor = NSColor.textBackgroundColor - textView.textColor = NSColor.labelColor + textView.backgroundColor = ThemeEngine.shared.palette[.editorBackground] + textView.textColor = ThemeEngine.shared.palette[.editorText] // Disable line wrapping textView.textContainer?.widthTracksTextView = false @@ -49,27 +48,47 @@ struct HighlightedSQLTextView: NSViewRepresentable { func updateNSView(_ scrollView: NSScrollView, context: Context) { guard let textView = scrollView.documentView as? NSTextView else { return } - if let currentFont = textView.font, currentFont.pointSize != fontSize { - textView.font = NSFont.monospacedSystemFont(ofSize: fontSize, weight: .regular) - if !textView.string.isEmpty { - applyHighlighting(to: textView) - } + let editorFont = ThemeEngine.shared.editorFonts.font + let fontChanged = textView.font != editorFont + let textChanged = textView.string != sql + + if fontChanged { + textView.font = editorFont } + textView.backgroundColor = ThemeEngine.shared.palette[.editorBackground] + textView.textColor = ThemeEngine.shared.palette[.editorText] - if textView.string != sql { + if textChanged { textView.string = sql - if !sql.isEmpty { - applyHighlighting(to: textView) - } } + + /// The highlighting bakes a colour per range, so it is applied again whenever the theme or + /// the editor font moves, not only when the query does. + guard !sql.isEmpty, textChanged || fontChanged || context.coordinator.revision != themeRevision else { + return + } + context.coordinator.revision = themeRevision + applyHighlighting(to: textView) + } + + private var themeRevision: Int { + ThemeEngine.shared.revision + } + + func makeCoordinator() -> Coordinator { + Coordinator() + } + + final class Coordinator { + var revision = -1 } // MARK: - Syntax Highlighting // MARK: - Pre-compiled Syntax Patterns - private static let syntaxPatterns: [(regex: NSRegularExpression, color: NSColor)] = { - var patterns: [(NSRegularExpression, NSColor)] = [] + private static let syntaxPatterns: [(regex: NSRegularExpression, slot: ThemeSlot)] = { + var patterns: [(NSRegularExpression, ThemeSlot)] = [] // SQL Keywords (blue) — single alternation regex for all keywords let keywords = [ @@ -86,22 +105,22 @@ struct HighlightedSQLTextView: NSViewRepresentable { ] let keywordPattern = "\\b(" + keywords.joined(separator: "|") + ")\\b" if let regex = try? NSRegularExpression(pattern: keywordPattern, options: .caseInsensitive) { - patterns.append((regex, .systemBlue)) + patterns.append((regex, .syntaxKeyword)) } // Strings (red) if let regex = try? NSRegularExpression(pattern: "'[^']*'", options: .caseInsensitive) { - patterns.append((regex, .systemRed)) + patterns.append((regex, .syntaxString)) } // Backticks (orange) if let regex = try? NSRegularExpression(pattern: "`[^`]*`", options: .caseInsensitive) { - patterns.append((regex, .systemOrange)) + patterns.append((regex, .syntaxNull)) } // Numbers (purple) if let regex = try? NSRegularExpression(pattern: "\\b\\d+\\b", options: .caseInsensitive) { - patterns.append((regex, .systemPurple)) + patterns.append((regex, .syntaxNumber)) } return patterns @@ -109,8 +128,8 @@ struct HighlightedSQLTextView: NSViewRepresentable { // MARK: - Pre-compiled MQL Syntax Patterns - private static let mqlPatterns: [(regex: NSRegularExpression, color: NSColor)] = { - var patterns: [(NSRegularExpression, NSColor)] = [] + private static let mqlPatterns: [(regex: NSRegularExpression, slot: ThemeSlot)] = { + var patterns: [(NSRegularExpression, ThemeSlot)] = [] // MongoDB methods (blue) — single alternation regex for all methods let methods = [ @@ -121,12 +140,12 @@ struct HighlightedSQLTextView: NSViewRepresentable { ] let methodPattern = "\\.(" + methods.joined(separator: "|") + ")\\s*\\(" if let regex = try? NSRegularExpression(pattern: methodPattern, options: []) { - patterns.append((regex, .systemBlue)) + patterns.append((regex, .syntaxKeyword)) } // db. prefix (blue) if let regex = try? NSRegularExpression(pattern: "\\bdb\\.", options: []) { - patterns.append((regex, .systemBlue)) + patterns.append((regex, .syntaxKeyword)) } // MongoDB operators $gt, $lt, $in, etc. (teal) @@ -137,22 +156,22 @@ struct HighlightedSQLTextView: NSViewRepresentable { + "oid|numberInt|numberLong|numberDouble|date|binary|timestamp|numberDecimal)\"", options: [] ) { - patterns.append((regex, .systemTeal)) + patterns.append((regex, .syntaxType)) } // Strings (red) if let regex = try? NSRegularExpression(pattern: "\"[^\"]*\"", options: []) { - patterns.append((regex, .systemRed)) + patterns.append((regex, .syntaxString)) } // Numbers (purple) if let regex = try? NSRegularExpression(pattern: "\\b\\d+\\.?\\d*\\b", options: []) { - patterns.append((regex, .systemPurple)) + patterns.append((regex, .syntaxNumber)) } // Booleans and null (orange) if let regex = try? NSRegularExpression(pattern: "\\b(true|false|null)\\b", options: []) { - patterns.append((regex, .systemOrange)) + patterns.append((regex, .syntaxNull)) } return patterns @@ -167,12 +186,12 @@ struct HighlightedSQLTextView: NSViewRepresentable { textStorage.beginEditing() // Reset to base style - let font = NSFont.monospacedSystemFont(ofSize: fontSize, weight: .regular) + let font = ThemeEngine.shared.editorFonts.font textStorage.addAttribute(.font, value: font, range: fullRange) - textStorage.addAttribute(.foregroundColor, value: NSColor.labelColor, range: fullRange) + textStorage.addAttribute(.foregroundColor, value: ThemeEngine.shared.palette[.editorText], range: fullRange) // Apply pre-compiled patterns - let activePatterns: [(regex: NSRegularExpression, color: NSColor)] + let activePatterns: [(regex: NSRegularExpression, slot: ThemeSlot)] switch PluginManager.shared.editorLanguage(for: databaseType) { case .javascript: activePatterns = Self.mqlPatterns @@ -187,10 +206,12 @@ struct HighlightedSQLTextView: NSViewRepresentable { } else { highlightRange = fullRange } - for (regex, color) in activePatterns { + let palette = ThemeEngine.shared.palette + + for (regex, slot) in activePatterns { let matches = regex.matches(in: text, options: [], range: highlightRange) for match in matches { - textStorage.addAttribute(.foregroundColor, value: color, range: match.range) + textStorage.addAttribute(.foregroundColor, value: palette[slot], range: match.range) } } diff --git a/TablePro/Views/Editor/Folding/FoldPreviewView.swift b/TablePro/Views/Editor/Folding/FoldPreviewView.swift index 3648993cc8..65f856410d 100644 --- a/TablePro/Views/Editor/Folding/FoldPreviewView.swift +++ b/TablePro/Views/Editor/Folding/FoldPreviewView.swift @@ -51,7 +51,7 @@ struct FoldPreviewView: View { .padding(.vertical, 5) } } - .background(ThemeEngine.shared.colors.editor.backgroundSwiftUI) + .background(ThemeEngine.shared.palette.color(.editorBackground)) .clipShape(RoundedRectangle(cornerRadius: Self.cornerRadius, style: .continuous)) .overlay( RoundedRectangle(cornerRadius: Self.cornerRadius, style: .continuous) diff --git a/TablePro/Views/Editor/History/HistoryDetailPane.swift b/TablePro/Views/Editor/History/HistoryDetailPane.swift index 2e6f10a27c..9cc5aa74c8 100644 --- a/TablePro/Views/Editor/History/HistoryDetailPane.swift +++ b/TablePro/Views/Editor/History/HistoryDetailPane.swift @@ -37,7 +37,7 @@ struct HistoryDetailPane: View { databaseType: entry.databaseType, accessibilityIdentifier: "query-history-detail-query" ) - .background(Color(nsColor: ThemeEngine.shared.colors.editor.background)) + .background(ThemeEngine.shared.palette.color(.editorBackground)) .frame(maxWidth: .infinity, maxHeight: .infinity) Divider() diff --git a/TablePro/Views/Editor/SQLEditorView.swift b/TablePro/Views/Editor/SQLEditorView.swift index 028a487225..ec3db9799b 100644 --- a/TablePro/Views/Editor/SQLEditorView.swift +++ b/TablePro/Views/Editor/SQLEditorView.swift @@ -248,17 +248,17 @@ struct SQLEditorView: View { appearance: .init( theme: TableProEditorTheme.make(), font: ThemeEngine.shared.editorFonts.font, - wrapLines: ThemeEngine.shared.wordWrap, - tabWidth: ThemeEngine.shared.tabWidth + wrapLines: AppSettingsManager.shared.editor.wordWrap, + tabWidth: AppSettingsManager.shared.editor.clampedTabWidth ), behavior: .init( - indentOption: .spaces(count: ThemeEngine.shared.tabWidth) + indentOption: .spaces(count: AppSettingsManager.shared.editor.clampedTabWidth) ), layout: .init( contentInsets: NSEdgeInsets(top: 0, left: 0, bottom: 8, right: 0) ), peripherals: EditorPeripherals.editor( - lineNumbers: ThemeEngine.shared.showLineNumbers, + lineNumbers: AppSettingsManager.shared.editor.showLineNumbers, folding: AppSettingsManager.shared.editor.codeFoldingEnabled, statementRunControls: AppSettingsManager.shared.editor.showStatementRunControls, invisibleCharacters: AppSettingsManager.shared.editor.showInvisibleCharacters diff --git a/TablePro/Views/Import/SQLCodePreview.swift b/TablePro/Views/Import/SQLCodePreview.swift index f3472133fe..2789b33323 100644 --- a/TablePro/Views/Import/SQLCodePreview.swift +++ b/TablePro/Views/Import/SQLCodePreview.swift @@ -31,6 +31,9 @@ struct SQLCodePreview: View { .onChange(of: colorScheme) { editorConfiguration = Self.makeConfiguration() } + .onReceive(AppEvents.shared.themeChanged) { _ in + editorConfiguration = Self.makeConfiguration() + } } } diff --git a/TablePro/Views/Results/CellOverlayBase.swift b/TablePro/Views/Results/CellOverlayBase.swift index ff4bd8c92a..2498f26283 100644 --- a/TablePro/Views/Results/CellOverlayBase.swift +++ b/TablePro/Views/Results/CellOverlayBase.swift @@ -4,6 +4,7 @@ // import AppKit +import Combine enum CellOverlayDismissReason { case userAction @@ -233,16 +234,27 @@ class CellOverlayBase: NSObject { final class CellOverlayContainerView: NSView { override var isFlipped: Bool { true } + private var themeCancellable: AnyCancellable? + + override func viewDidMoveToWindow() { + super.viewDidMoveToWindow() + guard window != nil, themeCancellable == nil else { return } + + themeCancellable = AppEvents.shared.themeChanged + .receive(on: RunLoop.main) + .sink { [weak self] _ in self?.applyLayerColors() } + } + override func viewDidChangeEffectiveAppearance() { super.viewDidChangeEffectiveAppearance() applyLayerColors() } /// A `CGColor` is a resolved colour and a layer never resolves it again, so the two layer - /// colours are reapplied whenever the appearance changes under an open overlay. + /// colours are reapplied whenever the appearance or the theme changes under an open overlay. func applyLayerColors() { effectiveAppearance.performAsCurrentDrawingAppearance { - layer?.borderColor = NSColor.keyboardFocusIndicatorColor.cgColor + layer?.borderColor = ThemeEngine.shared.palette[.gridFocusBorder].cgColor layer?.backgroundColor = NSColor.textBackgroundColor.cgColor } } diff --git a/TablePro/Views/Results/Cells/DataGridCellAppearance.swift b/TablePro/Views/Results/Cells/DataGridCellAppearance.swift index 2e8fd93207..f1417c657f 100644 --- a/TablePro/Views/Results/Cells/DataGridCellAppearance.swift +++ b/TablePro/Views/Results/Cells/DataGridCellAppearance.swift @@ -117,6 +117,6 @@ struct DataGridCellAppearance: Equatable { guard kind == .boolean, let rawValue, let isTrue = StoredBoolean.value(of: rawValue) else { return palette.text } - return (isTrue ? palette.booleanTrueText : palette.booleanFalseText) ?? palette.text + return isTrue ? palette.booleanTrueText : palette.booleanFalseText } } diff --git a/TablePro/Views/Results/Cells/DataGridCellPalette.swift b/TablePro/Views/Results/Cells/DataGridCellPalette.swift index 0ddabe24fe..ee04d69fc7 100644 --- a/TablePro/Views/Results/Cells/DataGridCellPalette.swift +++ b/TablePro/Views/Results/Cells/DataGridCellPalette.swift @@ -12,8 +12,8 @@ struct DataGridCellPalette: Equatable { let mediumFont: NSFont let text: NSColor let placeholderText: NSColor - let booleanTrueText: NSColor? - let booleanFalseText: NSColor? + let booleanTrueText: NSColor + let booleanFalseText: NSColor let rowNumberText: NSColor let deletedRowText: NSColor let modifiedColumnTint: NSColor @@ -25,8 +25,8 @@ struct DataGridCellPalette: Equatable { mediumFont: .systemFont(ofSize: NSFont.systemFontSize, weight: .medium), text: .labelColor, placeholderText: .secondaryLabelColor, - booleanTrueText: nil, - booleanFalseText: nil, + booleanTrueText: .labelColor, + booleanFalseText: .labelColor, rowNumberText: .secondaryLabelColor, deletedRowText: .secondaryLabelColor, modifiedColumnTint: .systemYellow, @@ -40,13 +40,13 @@ extension ThemeEngine { regularFont: dataGridFonts.regular, italicFont: dataGridFonts.italic, mediumFont: dataGridFonts.medium, - text: colors.dataGrid.text, - placeholderText: colors.dataGrid.nullValue, - booleanTrueText: colors.dataGrid.boolTrue, - booleanFalseText: colors.dataGrid.boolFalse, - rowNumberText: colors.dataGrid.rowNumber, - deletedRowText: colors.dataGrid.deletedText, - modifiedColumnTint: colors.dataGrid.modified, + text: resolved[.gridText], + placeholderText: resolved[.gridNullValue], + booleanTrueText: resolved[.gridBoolTrue], + booleanFalseText: resolved[.gridBoolFalse], + rowNumberText: resolved[.gridRowNumber], + deletedRowText: resolved[.gridDeletedText], + modifiedColumnTint: resolved[.gridModified], findMatchTint: .findHighlightColor ) } diff --git a/TablePro/Views/Results/Cells/DataGridCellRenderer.swift b/TablePro/Views/Results/Cells/DataGridCellRenderer.swift index fa3a071897..42ce84352a 100644 --- a/TablePro/Views/Results/Cells/DataGridCellRenderer.swift +++ b/TablePro/Views/Results/Cells/DataGridCellRenderer.swift @@ -138,7 +138,7 @@ final class DataGridCellRenderer { private func drawFocusRing(in rect: NSRect) { let path = NSBezierPath(rect: rect.insetBy(dx: 1, dy: 1)) path.lineWidth = 2 - NSColor.keyboardFocusIndicatorColor.setStroke() + ThemeEngine.shared.palette[.gridFocusBorder].setStroke() path.stroke() } } diff --git a/TablePro/Views/Results/DataGridBodyChrome.swift b/TablePro/Views/Results/DataGridBodyChrome.swift index 99685798b2..2700998f82 100644 --- a/TablePro/Views/Results/DataGridBodyChrome.swift +++ b/TablePro/Views/Results/DataGridBodyChrome.swift @@ -67,7 +67,7 @@ enum DataGridBodyChrome { ) { let separators = separatorRects(in: rect, of: view, tableView: tableView, presentsColumn: presentsColumn) guard !separators.isEmpty else { return } - tableView.gridColor.setFill() + ThemeEngine.shared.palette[.gridLine].setFill() separators.forEach { $0.fill() } } @@ -119,7 +119,7 @@ enum DataGridBodyChrome { /// Set on the table rather than read from the theme at each draw, because AppKit reads the /// table's own `backgroundColor` too, for the area an elastic scroll uncovers. static func applyBackground(to tableView: NSTableView) { - let background = ThemeEngine.shared.colors.dataGrid.background + let background = ThemeEngine.shared.palette[.gridBackground] guard tableView.backgroundColor != background else { return } tableView.backgroundColor = background } @@ -132,8 +132,8 @@ enum DataGridBodyChrome { static func stripeColor(forRow row: Int, of tableView: NSTableView) -> NSColor? { guard tableView.usesAlternatingRowBackgroundColors else { return nil } return row.isMultiple(of: 2) - ? ThemeEngine.shared.colors.dataGrid.background - : ThemeEngine.shared.colors.dataGrid.alternateRow + ? ThemeEngine.shared.palette[.gridBackground] + : ThemeEngine.shared.palette[.gridAlternateRow] } /// What a row view lays down before its tint and selection: its stripe, or the table's own diff --git a/TablePro/Views/Results/DataGridCoordinator.swift b/TablePro/Views/Results/DataGridCoordinator.swift index cd8afb63b7..d367280bbb 100644 --- a/TablePro/Views/Results/DataGridCoordinator.swift +++ b/TablePro/Views/Results/DataGridCoordinator.swift @@ -613,6 +613,8 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData .sink { [weak self] _ in if let tableView = self?.tableView { DataGridBodyChrome.applyBackground(to: tableView) + tableView.headerView?.needsDisplay = true + tableView.cornerView?.needsDisplay = true } self?.reloadVisibleRowsAndStates() /// The row-number font is a theme value and it decides the column's width, which diff --git a/TablePro/Views/Results/DataGridRowView.swift b/TablePro/Views/Results/DataGridRowView.swift index 34e0681537..34680e84d9 100644 --- a/TablePro/Views/Results/DataGridRowView.swift +++ b/TablePro/Views/Results/DataGridRowView.swift @@ -250,8 +250,17 @@ class DataGridRowView: NSTableRowView { dirtyRect.fill() } - /// A cell range on a row the table has selected is already covered by `NSTableRowView`'s own - /// selection fill, which runs after this, so only the remaining rows are painted here. + /// `NSTableRowView` fills a selected row with the system's selection colour and offers no way + /// to change it, so the theme's own selection is painted here instead. `super` is not called: + /// its fill would sit on top of this one. + override func drawSelection(in dirtyRect: NSRect) { + guard isSelected else { return } + cellSelectionFill.setFill() + dirtyRect.fill() + } + + /// A cell range on a row the table has selected is already covered by the row's own selection + /// fill, which runs after this, so only the remaining rows are painted here. private func drawCellSelectionFill(in dirtyRect: NSRect) { guard !isSelected, let coordinator, @@ -278,8 +287,9 @@ class DataGridRowView: NSTableRowView { /// emphasized accent is far too dark to sit behind text these rows do not recolour, so that /// one goes on as a tint. private var cellSelectionFill: NSColor { - guard isEmphasized else { return .unemphasizedSelectedContentBackgroundColor } - return NSColor.selectedContentBackgroundColor.withAlphaComponent(Self.emphasizedCellSelectionAlpha) + let palette = ThemeEngine.shared.palette + guard isEmphasized else { return palette[.gridInactiveSelection] } + return palette[.gridSelection].withAlphaComponent(Self.emphasizedCellSelectionAlpha) } private static let emphasizedCellSelectionAlpha: CGFloat = 0.28 diff --git a/TablePro/Views/Results/DataGridView.swift b/TablePro/Views/Results/DataGridView.swift index 19c1780495..5fbdbd772b 100644 --- a/TablePro/Views/Results/DataGridView.swift +++ b/TablePro/Views/Results/DataGridView.swift @@ -48,8 +48,8 @@ extension RowVisualState { /// The wash a row in this state carries, read by the row and by the pinned row gutter over it so /// the two cannot disagree. @MainActor var tint: NSColor? { - if isDeleted { return ThemeEngine.shared.colors.dataGrid.deleted } - if isInserted { return ThemeEngine.shared.colors.dataGrid.inserted } + if isDeleted { return ThemeEngine.shared.palette[.gridDeleted] } + if isInserted { return ThemeEngine.shared.palette[.gridInserted] } return highlight.rowColor?.washColor } diff --git a/TablePro/Views/Results/SortableHeaderCell.swift b/TablePro/Views/Results/SortableHeaderCell.swift index e8f34936e5..02cfdf6366 100644 --- a/TablePro/Views/Results/SortableHeaderCell.swift +++ b/TablePro/Views/Results/SortableHeaderCell.swift @@ -190,7 +190,9 @@ final class SortableHeaderCell: NSTableHeaderCell { } private func foregroundColor(emphasized: Bool) -> NSColor { - emphasized ? .alternateSelectedControlTextColor : .headerTextColor + emphasized + ? ThemeEngine.shared.palette[.gridSelectionText] + : ThemeEngine.shared.palette[.gridHeaderText] } private func commentColor(emphasized: Bool) -> NSColor { diff --git a/TablePro/Views/Results/SortableHeaderChrome.swift b/TablePro/Views/Results/SortableHeaderChrome.swift index 8eb7aba26c..18076f1ebc 100644 --- a/TablePro/Views/Results/SortableHeaderChrome.swift +++ b/TablePro/Views/Results/SortableHeaderChrome.swift @@ -11,12 +11,12 @@ enum SortableHeaderChrome { static let columnDividerHeight: CGFloat = 16 static func fillBackground(_ rect: NSRect) { - NSColor.windowBackgroundColor.setFill() + ThemeEngine.shared.palette[.gridHeaderBackground].setFill() rect.fill() } static func drawBottomSeparator(in bounds: NSRect) { - NSColor.separatorColor.setFill() + ThemeEngine.shared.palette[.gridLine].setFill() NSRect( x: bounds.minX, y: bounds.maxY - separatorThickness, @@ -27,7 +27,7 @@ enum SortableHeaderChrome { static func drawColumnDivider(in cellFrame: NSRect) { let dividerHeight = min(columnDividerHeight, cellFrame.height) - NSColor.separatorColor.setFill() + ThemeEngine.shared.palette[.gridLine].setFill() NSRect( x: cellFrame.maxX - separatorThickness, y: cellFrame.midY - dividerHeight / 2, diff --git a/TablePro/Views/RowInspector/JSON/JSONRowColors.swift b/TablePro/Views/RowInspector/JSON/JSONRowColors.swift index 049a0354bc..8456937411 100644 --- a/TablePro/Views/RowInspector/JSON/JSONRowColors.swift +++ b/TablePro/Views/RowInspector/JSON/JSONRowColors.swift @@ -21,14 +21,14 @@ struct JSONRowColors { @MainActor static func current() -> JSONRowColors { - let colors = ThemeEngine.shared.colors.editor + let palette = ThemeEngine.shared.palette return JSONRowColors( - key: colors.keywordSwiftUI, - string: colors.stringSwiftUI, - number: colors.numberSwiftUI, - literal: colors.nullSwiftUI, - punctuation: colors.textSwiftUI, - placeholder: colors.commentSwiftUI + key: palette.color(.syntaxKeyword), + string: palette.color(.syntaxString), + number: palette.color(.syntaxNumber), + literal: palette.color(.syntaxNull), + punctuation: palette.color(.editorText), + placeholder: palette.color(.syntaxComment) ) } diff --git a/TablePro/Views/RowInspector/JSON/JSONRowInspectorView.swift b/TablePro/Views/RowInspector/JSON/JSONRowInspectorView.swift index 7e157deac3..94ec4eadd6 100644 --- a/TablePro/Views/RowInspector/JSON/JSONRowInspectorView.swift +++ b/TablePro/Views/RowInspector/JSON/JSONRowInspectorView.swift @@ -127,7 +127,7 @@ struct JSONRowInspectorView: View { .padding(.vertical, 6) .frame(maxWidth: .infinity, alignment: .topLeading) } - .background(Color(nsColor: ThemeEngine.shared.colors.editor.background)) + .background(ThemeEngine.shared.palette.color(.editorBackground)) .accessibilityLabel(String(localized: "Row as JSON")) } } diff --git a/TablePro/Views/Settings/Appearance/ThemeEditorColorsSection.swift b/TablePro/Views/Settings/Appearance/ThemeEditorColorsSection.swift index 5e2c70ab6f..c37f98a5ae 100644 --- a/TablePro/Views/Settings/Appearance/ThemeEditorColorsSection.swift +++ b/TablePro/Views/Settings/Appearance/ThemeEditorColorsSection.swift @@ -1,298 +1,116 @@ -// -// ThemeEditorColorsSection.swift -// TablePro -// - import AppKit import os import SwiftUI -// MARK: - HexColorPicker - -struct HexColorPicker: View { - let label: String - @Binding var hex: String - - var body: some View { - let colorBinding = Binding( - get: { hex.swiftUIColor }, - set: { newColor in - if let converted = NSColor(newColor).usingColorSpace(.sRGB) { - hex = converted.hexString - } - } - ) - ColorPicker(label, selection: colorBinding, supportsOpacity: true) - } -} - -// MARK: - ThemeEditorColorsSection - +/// One well per registered slot, driven by `ThemeSlot.allCases`, so a slot the app gains appears +/// here without a second hand-maintained list to keep in step. internal struct ThemeEditorColorsSection: View { - private static let logger = Logger(subsystem: "com.TablePro", category: "ThemeEditorColorsSection") - private var engine: ThemeEngine { ThemeEngine.shared } - private var theme: ThemeDefinition { engine.activeTheme } + internal let theme: ThemeDefinition - var body: some View { - Form { - editorSection - syntaxSection - dataGridSection - interfaceSection - statusSection - badgesSection - sidebarSection - toolbarSection - } - .formStyle(.grouped) - .scrollContentBackground(.hidden) - } - - // MARK: - Editor + @State private var draft: ThemeDefinition? + @State private var saveTask: Task? - private var editorSection: some View { - Section(String(localized: "Editor")) { - LabeledContent(String(localized: "Background")) { - HexColorPicker(label: "", hex: colorBinding(for: \.editor.background)) - } - LabeledContent(String(localized: "Text")) { - HexColorPicker(label: "", hex: colorBinding(for: \.editor.text)) - } - LabeledContent(String(localized: "Cursor")) { - HexColorPicker(label: "", hex: colorBinding(for: \.editor.cursor)) - } - LabeledContent(String(localized: "Current Line")) { - HexColorPicker(label: "", hex: colorBinding(for: \.editor.currentLineHighlight)) - } - LabeledContent(String(localized: "Selection")) { - HexColorPicker(label: "", hex: colorBinding(for: \.editor.selection)) - } - LabeledContent(String(localized: "Line Number")) { - HexColorPicker(label: "", hex: colorBinding(for: \.editor.lineNumber)) - } - LabeledContent(String(localized: "Invisibles")) { - HexColorPicker(label: "", hex: colorBinding(for: \.editor.invisibles)) - } - } - } + private static let logger = Logger(subsystem: "com.TablePro", category: "ThemeEditorColors") + private static let saveDelay = Duration.milliseconds(250) - private var syntaxSection: some View { - Section(String(localized: "Syntax Colors")) { - LabeledContent(String(localized: "Keyword")) { - HexColorPicker(label: "", hex: colorBinding(for: \.editor.syntax.keyword)) - } - LabeledContent(String(localized: "String")) { - HexColorPicker(label: "", hex: colorBinding(for: \.editor.syntax.string)) - } - LabeledContent(String(localized: "Number")) { - HexColorPicker(label: "", hex: colorBinding(for: \.editor.syntax.number)) - } - LabeledContent(String(localized: "Comment")) { - HexColorPicker(label: "", hex: colorBinding(for: \.editor.syntax.comment)) - } - LabeledContent(String(localized: "NULL")) { - HexColorPicker(label: "", hex: colorBinding(for: \.editor.syntax.null)) - } - LabeledContent(String(localized: "Operator")) { - HexColorPicker(label: "", hex: colorBinding(for: \.editor.syntax.operator)) - } - LabeledContent(String(localized: "Function")) { - HexColorPicker(label: "", hex: colorBinding(for: \.editor.syntax.function)) - } - LabeledContent(String(localized: "Type")) { - HexColorPicker(label: "", hex: colorBinding(for: \.editor.syntax.type)) - } - } + private var edited: ThemeDefinition { + guard let draft, draft.id == theme.id else { return theme } + return draft } - // MARK: - Data Grid - - private var dataGridSection: some View { - let system = ResolvedDataGridColors(from: .defaultLight) - let resolved = ResolvedDataGridColors(from: theme.dataGrid) - return Section(String(localized: "Data Grid")) { - optionalColorRow(String(localized: "Background"), keyPath: \.dataGrid.background, - fallback: system.background) - optionalColorRow(String(localized: "Text"), keyPath: \.dataGrid.text, - fallback: system.text) - optionalColorRow(String(localized: "Alternate Row"), keyPath: \.dataGrid.alternateRow, - fallback: system.alternateRow) - optionalColorRow(String(localized: "NULL Value"), keyPath: \.dataGrid.nullValue, - fallback: system.nullValue) - optionalColorRow(String(localized: "Bool True"), keyPath: \.dataGrid.boolTrue, - fallback: resolved.text) - optionalColorRow(String(localized: "Bool False"), keyPath: \.dataGrid.boolFalse, - fallback: resolved.text) - optionalColorRow(String(localized: "Row Number"), keyPath: \.dataGrid.rowNumber, - fallback: system.rowNumber) - LabeledContent(String(localized: "Modified")) { - HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.modified)) - } - LabeledContent(String(localized: "Inserted")) { - HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.inserted)) - } - LabeledContent(String(localized: "Deleted")) { - HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.deleted)) - } - LabeledContent(String(localized: "Deleted Text")) { - HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.deletedText)) + internal var body: some View { + Form { + ForEach(ThemeSlotGroup.allCases, id: \.self) { group in + Section(group.label) { + ForEach(group.slots, id: \.self) { slot in + row(for: slot) + } + } } } + .formStyle(.grouped) + .onDisappear { flush() } } - // MARK: - Interface - - private var interfaceSection: some View { - Section(String(localized: "Interface")) { - optionalColorRow(String(localized: "Window Background"), keyPath: \.ui.windowBackground, - fallback: .windowBackgroundColor) - optionalColorRow(String(localized: "Control Background"), keyPath: \.ui.controlBackground, - fallback: .controlBackgroundColor) - optionalColorRow(String(localized: "Card Background"), keyPath: \.ui.cardBackground, - fallback: .controlBackgroundColor) - optionalColorRow(String(localized: "Border"), keyPath: \.ui.border, - fallback: .separatorColor) - optionalColorRow(String(localized: "Primary Text"), keyPath: \.ui.primaryText, - fallback: .labelColor) - optionalColorRow(String(localized: "Secondary Text"), keyPath: \.ui.secondaryText, - fallback: .secondaryLabelColor) - optionalColorRow(String(localized: "Tertiary Text"), keyPath: \.ui.tertiaryText, - fallback: .tertiaryLabelColor) - optionalColorRow(String(localized: "Selection"), keyPath: \.ui.selectionBackground, - fallback: .selectedContentBackgroundColor) - optionalColorRow(String(localized: "Hover"), keyPath: \.ui.hoverBackground, - fallback: .unemphasizedSelectedContentBackgroundColor) - } - } + private func row(for slot: ThemeSlot) -> some View { + let value = edited[keyPath: slot.keyPath] - private var statusSection: some View { - Section(String(localized: "Status Colors")) { - LabeledContent(String(localized: "Success")) { - HexColorPicker(label: "", hex: colorBinding(for: \.ui.status.success)) - } - LabeledContent(String(localized: "Warning")) { - HexColorPicker(label: "", hex: colorBinding(for: \.ui.status.warning)) - } - LabeledContent(String(localized: "Error")) { - HexColorPicker(label: "", hex: colorBinding(for: \.ui.status.error)) - } - LabeledContent(String(localized: "Info")) { - HexColorPicker(label: "", hex: colorBinding(for: \.ui.status.info)) - } - } - } + return LabeledContent(slot.label) { + HStack(spacing: 8) { + if case let .system(name) = value { + Text(name.rawValue) + .font(.caption) + .foregroundStyle(.secondary) + } - private var badgesSection: some View { - Section(String(localized: "Badges")) { - LabeledContent(String(localized: "Badge Background")) { - HexColorPicker(label: "", hex: colorBinding(for: \.ui.badges.background)) + ColorPicker("", selection: binding(for: slot), supportsOpacity: true) + .labelsHidden() } - LabeledContent(String(localized: "Primary Key")) { - HexColorPicker(label: "", hex: colorBinding(for: \.ui.badges.primaryKey)) - } - LabeledContent(String(localized: "Auto Increment")) { - HexColorPicker(label: "", hex: colorBinding(for: \.ui.badges.autoIncrement)) + .contextMenu { + if case .hex = value, case let .system(name) = BuiltInThemes.default(for: theme.appearance)[keyPath: slot.keyPath] { + Button(String(format: String(localized: "Use System Color (%@)"), name.rawValue)) { + write(.system(name), to: slot) + } + } } } } - // MARK: - Sidebar - - private var sidebarSection: some View { - Section(String(localized: "Sidebar")) { - optionalColorRow(String(localized: "Background"), keyPath: \.sidebar.background, - fallback: .windowBackgroundColor) - optionalColorRow(String(localized: "Text"), keyPath: \.sidebar.text, - fallback: .labelColor) - optionalColorRow(String(localized: "Selected Item"), keyPath: \.sidebar.selectedItem, - fallback: .selectedContentBackgroundColor) - optionalColorRow(String(localized: "Hover"), keyPath: \.sidebar.hover, - fallback: .unemphasizedSelectedContentBackgroundColor) - optionalColorRow(String(localized: "Section Header"), keyPath: \.sidebar.sectionHeader, - fallback: .secondaryLabelColor) - } + private var editedAppearance: NSAppearance? { + NSAppearance(named: theme.appearance == .dark ? .darkAqua : .aqua) } - // MARK: - Toolbar + private func resolved(_ value: ThemeColorValue) -> NSColor { + guard value.isSystem, let editedAppearance else { return value.nsColor } - private var toolbarSection: some View { - Section(String(localized: "Toolbar")) { - optionalColorRow(String(localized: "Secondary Text"), keyPath: \.toolbar.secondaryText, - fallback: .secondaryLabelColor) - optionalColorRow(String(localized: "Tertiary Text"), keyPath: \.toolbar.tertiaryText, - fallback: .tertiaryLabelColor) + var color = value.nsColor + editedAppearance.performAsCurrentDrawingAppearance { + color = value.nsColor.usingColorSpace(.sRGB) ?? value.nsColor } + return color } - // MARK: - Helpers - - private func colorBinding(for keyPath: WritableKeyPath) -> Binding { + private func binding(for slot: ThemeSlot) -> Binding { Binding( - get: { theme[keyPath: keyPath] }, - set: { newValue in - guard theme.isEditable else { return } - var updated = theme - updated[keyPath: keyPath] = newValue - do { - try engine.saveUserTheme(updated) - } catch { - Self.logger.error("Failed to save theme: \(error.localizedDescription, privacy: .public)") - } + get: { Color(nsColor: resolved(edited[keyPath: slot.keyPath])) }, + set: { newColor in + write(.hex(HexColor.string(from: NSColor(newColor))), to: slot) } ) } - private func optionalColorBinding( - for keyPath: WritableKeyPath, - fallback: NSColor - ) -> Binding { - Binding( - get: { - if let hex = theme[keyPath: keyPath] { - return hex - } - return (fallback.usingColorSpace(.sRGB) ?? fallback).hexString - }, - set: { newValue in - guard theme.isEditable else { return } - var updated = theme - updated[keyPath: keyPath] = newValue - do { - try engine.saveUserTheme(updated) - } catch { - Self.logger.error("Failed to save theme: \(error.localizedDescription, privacy: .public)") - } - } - ) + /// The well emits on every drag tick, and each one used to write the file, rescan the themes + /// directory and re-activate. The draft absorbs the ticks and one save follows the settle. + private func write(_ value: ThemeColorValue, to slot: ThemeSlot) { + var updated = edited + updated[keyPath: slot.keyPath] = value + draft = updated + + saveTask?.cancel() + saveTask = Task { @MainActor in + try? await Task.sleep(for: Self.saveDelay) + guard !Task.isCancelled else { return } + save(updated) + } } - @ViewBuilder - private func optionalColorRow( - _ label: String, - keyPath: WritableKeyPath, - fallback: NSColor - ) -> some View { - LabeledContent(label) { - HStack(spacing: 4) { - HexColorPicker(label: "", hex: optionalColorBinding(for: keyPath, fallback: fallback)) - if theme[keyPath: keyPath] != nil { - Button { - guard theme.isEditable else { return } - var updated = theme - updated[keyPath: keyPath] = nil - do { - try engine.saveUserTheme(updated) - } catch { - Self.logger.error("Failed to save theme: \(error.localizedDescription, privacy: .public)") - } - } label: { - Image(systemName: "arrow.counterclockwise") - .font(.caption) - } - .buttonStyle(.borderless) - .help(String(localized: "Reset to System Default")) - } - } + private func flush() { + saveTask?.cancel() + saveTask = nil + guard let draft, draft != theme else { return } + save(draft) + } + + private func save(_ updated: ThemeDefinition) { + do { + try ThemeCatalog.shared.save(updated) + let appearance = AppSettingsManager.shared.appearance + ThemeEngine.shared.reapply( + lightThemeId: appearance.preferredLightThemeId, + darkThemeId: appearance.preferredDarkThemeId + ) + } catch { + Self.logger.error("Could not save theme: \(error.localizedDescription)") } } } diff --git a/TablePro/Views/Settings/Appearance/ThemeEditorFontsSection.swift b/TablePro/Views/Settings/Appearance/ThemeEditorFontsSection.swift deleted file mode 100644 index 89c9b7fc39..0000000000 --- a/TablePro/Views/Settings/Appearance/ThemeEditorFontsSection.swift +++ /dev/null @@ -1,135 +0,0 @@ -import AppKit -import SwiftUI - -struct ThemeEditorFontsSection: View { - var onThemeDuplicated: ((ThemeDefinition) -> Void)? - - private var engine: ThemeEngine { ThemeEngine.shared } - - @State private var editingTheme: ThemeDefinition? - - private var theme: ThemeDefinition { engine.activeTheme } - - private var currentThemeFonts: ThemeFonts { - editingTheme?.fonts ?? theme.fonts - } - - var body: some View { - Form { - editorFontSection - dataGridFontSection - previewSection - } - .formStyle(.grouped) - .scrollContentBackground(.hidden) - .onChange(of: engine.activeTheme.id) { - editingTheme = nil - } - } - - // MARK: - Editor Font - - private var editorFontSection: some View { - Section(String(localized: "Editor Font")) { - fontPicker( - label: String(localized: "Family"), - selection: currentThemeFonts.editorFontFamily, - onChange: { newFamily in - updateFont { $0.editorFontFamily = newFamily } - } - ) - sizePicker( - label: String(localized: "Size"), - value: currentThemeFonts.editorFontSize, - range: 11...18, - onChange: { newSize in - updateFont { $0.editorFontSize = newSize } - } - ) - } - } - - // MARK: - Data Grid Font - - private var dataGridFontSection: some View { - Section(String(localized: "Data Grid Font")) { - fontPicker( - label: String(localized: "Family"), - selection: currentThemeFonts.dataGridFontFamily, - onChange: { newFamily in - updateFont { $0.dataGridFontFamily = newFamily } - } - ) - sizePicker( - label: String(localized: "Size"), - value: currentThemeFonts.dataGridFontSize, - range: 10...18, - onChange: { newSize in - updateFont { $0.dataGridFontSize = newSize } - } - ) - } - } - - // MARK: - Preview - - private var previewSection: some View { - Section(String(localized: "Preview")) { - let fonts = currentThemeFonts - let editorFont = EditorFontResolver.resolve( - familyId: fonts.editorFontFamily, - size: CGFloat(fonts.editorFontSize) - ) - - Text("SELECT * FROM users WHERE id = 42;") - .font(Font(editorFont)) - .foregroundStyle(theme.editor.text.swiftUIColor) - .padding(8) - .frame(maxWidth: .infinity, alignment: .leading) - .background(theme.editor.background.swiftUIColor) - .clipShape(RoundedRectangle(cornerRadius: 4)) - } - } - - // MARK: - Helpers - - private func fontPicker(label: String, selection: String, onChange: @escaping (String) -> Void) -> some View { - Picker(label, selection: Binding( - get: { selection }, - set: { onChange($0) } - )) { - ForEach(EditorFontResolver.availableMonospacedFamilies) { font in - Text(font.displayName).tag(font.id) - } - } - } - - private func sizePicker(label: String, value: Int, range: ClosedRange, - onChange: @escaping (Int) -> Void) -> some View { - Picker(label, selection: Binding( - get: { value }, - set: { onChange($0) } - )) { - ForEach(range, id: \.self) { size in - Text(verbatim: "\(size) pt").tag(size) - } - } - } - - private func updateFont(_ mutate: (inout ThemeFonts) -> Void) { - let base = editingTheme ?? theme - - if base.isBuiltIn { - var copy = engine.duplicateTheme(base, newName: base.name + " (Custom)") - mutate(©.fonts) - try? engine.saveUserTheme(copy) - editingTheme = copy - onThemeDuplicated?(copy) - } else { - var updated = base - mutate(&updated.fonts) - try? engine.saveUserTheme(updated) - editingTheme = updated - } - } -} diff --git a/TablePro/Views/Settings/Appearance/ThemeEditorView.swift b/TablePro/Views/Settings/Appearance/ThemeEditorView.swift index e479f37be5..64e1dbaa58 100644 --- a/TablePro/Views/Settings/Appearance/ThemeEditorView.swift +++ b/TablePro/Views/Settings/Appearance/ThemeEditorView.swift @@ -1,57 +1,35 @@ -// -// ThemeEditorView.swift -// TablePro -// -// Right panel of the appearance HSplitView: theme header, accent color, and tabbed editor sections. -// - +import os import SwiftUI +/// Edits the theme the slot holds, not the theme in effect. Reading `activeTheme` here meant that +/// with the Mac in light mode and the pane set to Editing: Dark, every edit, duplicate and delete +/// landed on the light theme, and the dark slot was then pointed at it. internal struct ThemeEditorView: View { - @Binding var selectedThemeId: String - - private var engine: ThemeEngine { ThemeEngine.shared } - private var theme: ThemeDefinition { engine.activeTheme } - private var isEditable: Bool { theme.isEditable } - - @State private var activeTab: EditorTab = .fonts + @Binding internal var selectedThemeId: String + internal let slotAppearance: ThemeAppearance @State private var errorMessage: String? @State private var showError = false - private enum EditorTab: String, CaseIterable { - case fonts = "Fonts" - case colors = "Colors" + private static let logger = Logger(subsystem: "com.TablePro", category: "ThemeEditorView") - var localizedName: String { - switch self { - case .fonts: return String(localized: "Fonts") - case .colors: return String(localized: "Colors") - } - } + private var catalog: ThemeCatalog { ThemeCatalog.shared } + + private var theme: ThemeDefinition { + catalog.theme(id: selectedThemeId) ?? BuiltInThemes.default(for: slotAppearance) } - var body: some View { + internal var body: some View { VStack(spacing: 0) { - Text(theme.name) - .font(.title3.weight(.semibold)) - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.horizontal, 16) - .padding(.top, 12) - .padding(.bottom, 8) - - Picker("", selection: $activeTab) { - ForEach(EditorTab.allCases, id: \.self) { tab in - Text(tab.localizedName).tag(tab) - } - } - .pickerStyle(.segmented) - .padding(.horizontal, 16) - .padding(.bottom, 8) + header Divider() - tabContent + if theme.isEditable { + ThemeEditorColorsSection(theme: theme) + } else { + duplicatePrompt + } } .alert(String(localized: "Error"), isPresented: $showError) { Button(String(localized: "OK")) {} @@ -62,20 +40,19 @@ internal struct ThemeEditorView: View { } } - @ViewBuilder - private var tabContent: some View { - switch activeTab { - case .fonts: - ThemeEditorFontsSection(onThemeDuplicated: { newTheme in - selectedThemeId = newTheme.id - }) - case .colors: - if isEditable { - ThemeEditorColorsSection() - } else { - duplicatePrompt - } + private var header: some View { + VStack(alignment: .leading, spacing: 2) { + Text(theme.name) + .font(.title3.weight(.semibold)) + + Text(theme.author.isEmpty ? String(localized: "Custom theme") : theme.author) + .font(.caption) + .foregroundStyle(.secondary) } + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.horizontal, 16) + .padding(.top, 12) + .padding(.bottom, 10) } private var duplicatePrompt: some View { @@ -92,11 +69,11 @@ internal struct ThemeEditorView: View { .font(.body) .foregroundStyle(.secondary) - Text(String(localized: "Duplicate it to customize colors.")) + Text("Duplicate it to change its colors.") .font(.subheadline) .foregroundStyle(.tertiary) - Button(String(localized: "Duplicate Theme")) { + Button("Duplicate Theme") { duplicateAndSelect() } .controlSize(.large) @@ -107,12 +84,15 @@ internal struct ThemeEditorView: View { } private func duplicateAndSelect() { - let copy = engine.duplicateTheme(theme, newName: theme.name + " (Copy)") + var copy = theme + copy.id = ThemeIdentifier.generated() + copy.name = String(format: String(localized: "%@ (Copy)"), theme.name) + do { - try engine.saveUserTheme(copy) - engine.activateTheme(copy) + try catalog.save(copy) selectedThemeId = copy.id } catch { + Self.logger.error("Could not duplicate theme: \(error.localizedDescription)") errorMessage = error.localizedDescription showError = true } diff --git a/TablePro/Views/Settings/Appearance/ThemeListView.swift b/TablePro/Views/Settings/Appearance/ThemeListView.swift index 4a943deef7..86ac15be46 100644 --- a/TablePro/Views/Settings/Appearance/ThemeListView.swift +++ b/TablePro/Views/Settings/Appearance/ThemeListView.swift @@ -1,65 +1,60 @@ import AppKit +import os import SwiftUI import UniformTypeIdentifiers +/// Every action here acts on the theme the slot has selected. Acting on the active theme instead +/// let a delete in the dark slot write the light theme's id into it, so at dusk the editor turned +/// white inside dark chrome. internal struct ThemeListView: View { - @Binding var selectedThemeId: String + @Binding internal var selectedThemeId: String internal var slotAppearance: ThemeAppearance = .light - private var engine: ThemeEngine { ThemeEngine.shared } - @State private var showDeleteConfirmation = false @State private var errorMessage: String? @State private var showError = false + private static let logger = Logger(subsystem: "com.TablePro", category: "ThemeListView") + + private var catalog: ThemeCatalog { ThemeCatalog.shared } + private var builtInThemes: [ThemeDefinition] { - ThemeSlotValidation.eligibleThemes( - engine.availableThemes.filter(\.isBuiltIn), - slot: slotAppearance, - keeping: selectedThemeId - ) + eligible(catalog.themes.filter(\.isBuiltIn)) } private var registryThemes: [ThemeDefinition] { - ThemeSlotValidation.eligibleThemes( - engine.registryThemes, - slot: slotAppearance, - keeping: selectedThemeId - ) + eligible(catalog.themes.filter(\.isRegistry)) } private var customThemes: [ThemeDefinition] { - ThemeSlotValidation.eligibleThemes( - engine.availableThemes.filter(\.isEditable), - slot: slotAppearance, - keeping: selectedThemeId - ) + eligible(catalog.themes.filter(\.isEditable)) } private var selectedTheme: ThemeDefinition? { - engine.availableThemes.first { $0.id == selectedThemeId } + catalog.theme(id: selectedThemeId) + } + + private var fallbackThemeId: String { + BuiltInThemes.defaultId(for: slotAppearance) } - private var isDeleteDisabled: Bool { - guard let theme = selectedTheme else { return true } - return !theme.isEditable + private func eligible(_ themes: [ThemeDefinition]) -> [ThemeDefinition] { + ThemeSlotValidation.eligibleThemes(themes, slot: slotAppearance, keeping: selectedThemeId) } - var body: some View { + internal var body: some View { VStack(spacing: 0) { List(selection: $selectedThemeId) { Section("Built-in") { ForEach(builtInThemes) { theme in - ThemeListRowView(theme: theme) - .tag(theme.id) + ThemeListRowView(theme: theme).tag(theme.id) } } if !registryThemes.isEmpty { Section("Registry") { ForEach(registryThemes) { theme in - ThemeListRowView(theme: theme) - .tag(theme.id) + ThemeListRowView(theme: theme).tag(theme.id) } } } @@ -67,8 +62,15 @@ internal struct ThemeListView: View { if !customThemes.isEmpty { Section("Custom") { ForEach(customThemes) { theme in - ThemeListRowView(theme: theme) - .tag(theme.id) + ThemeListRowView(theme: theme).tag(theme.id) + } + } + } + + if !catalog.rejected.isEmpty { + Section("Not Loaded") { + ForEach(catalog.rejected, id: \.path) { record in + rejectedRow(record) } } } @@ -78,72 +80,16 @@ internal struct ThemeListView: View { Divider() - HStack(spacing: 4) { - Menu { - Button(String(localized: "New Theme")) { - duplicateActiveTheme() - } - Divider() - Button(String(localized: "Import…")) { - importTheme() - } - } label: { - Image(systemName: "plus") - .frame(width: 24, height: 24) - } - .menuIndicator(.hidden) - .buttonStyle(.borderless) - .frame(width: 28) - .help(Text("Add Theme")) - .accessibilityLabel(Text("Add Theme")) - - Button { - showDeleteConfirmation = true - } label: { - Image(systemName: "minus") - .frame(width: 24, height: 24) - } - .buttonStyle(.borderless) - .disabled(isDeleteDisabled) - .help(Text("Delete Theme")) - .accessibilityLabel(Text("Delete Theme")) - - Menu { - Button(String(localized: "Duplicate")) { - duplicateActiveTheme() - } - Button(String(localized: "Export…")) { - exportActiveTheme() - } - if selectedTheme?.isRegistry == true { - Divider() - Button(String(localized: "Uninstall"), role: .destructive) { - uninstallRegistryTheme() - } - } - } label: { - Image(systemName: "gearshape") - .frame(width: 24, height: 24) - } - .menuIndicator(.hidden) - .buttonStyle(.borderless) - .frame(width: 28) - .help(Text("Theme Actions")) - .accessibilityLabel(Text("Theme Actions")) - - Spacer() - } - .padding(.horizontal, 8) - .padding(.vertical, 4) + toolbar } .alert(String(localized: "Delete Theme"), isPresented: $showDeleteConfirmation) { - Button(String(localized: "Delete"), role: .destructive) { - deleteSelectedTheme() - } + Button(String(localized: "Delete"), role: .destructive) { deleteSelectedTheme() } Button(String(localized: "Cancel"), role: .cancel) {} } message: { - let name = engine.availableThemes.first(where: { $0.id == selectedThemeId })?.name ?? "" - Text(String(format: String(localized: "Are you sure you want to delete \"%@\"?"), name)) + Text(String( + format: String(localized: "Are you sure you want to delete \"%@\"?"), + selectedTheme?.name ?? "" + )) } .alert(String(localized: "Error"), isPresented: $showError) { Button(String(localized: "OK")) {} @@ -154,53 +100,108 @@ internal struct ThemeListView: View { } } - // MARK: - Actions + /// A file the loader refused is shown with its reason rather than dropped in silence, which is + /// what the previous loader did for a malformed theme. + private func rejectedRow(_ record: RejectedThemeRecord) -> some View { + VStack(alignment: .leading, spacing: 2) { + Text(record.fileName) + .font(.callout) + .lineLimit(1) + + Text(record.reason) + .font(.caption) + .foregroundStyle(.secondary) + .lineLimit(2) + } + .padding(.vertical, 2) + .help(Text(record.reason)) + } - private func duplicateActiveTheme() { - let theme = engine.activeTheme - let copy = engine.duplicateTheme(theme, newName: theme.name + " (Copy)") - do { - try engine.saveUserTheme(copy) - selectedThemeId = copy.id - } catch { - errorMessage = error.localizedDescription - showError = true + private var toolbar: some View { + HStack(spacing: 4) { + Menu { + Button(String(localized: "Duplicate Selected")) { duplicateSelectedTheme() } + Divider() + Button(String(localized: "Import…")) { importTheme() } + } label: { + Image(systemName: "plus").frame(width: 24, height: 24) + } + .menuIndicator(.hidden) + .buttonStyle(.borderless) + .frame(width: 28) + .help(Text("Add Theme")) + .accessibilityLabel(Text("Add Theme")) + + Button { + showDeleteConfirmation = true + } label: { + Image(systemName: "minus").frame(width: 24, height: 24) + } + .buttonStyle(.borderless) + .disabled(selectedTheme?.isEditable != true) + .help(Text("Delete Theme")) + .accessibilityLabel(Text("Delete Theme")) + + Menu { + Button(String(localized: "Duplicate")) { duplicateSelectedTheme() } + Button(String(localized: "Export…")) { exportSelectedTheme() } + if selectedTheme?.isRegistry == true { + Divider() + Button(String(localized: "Uninstall"), role: .destructive) { uninstallRegistryTheme() } + } + } label: { + Image(systemName: "gearshape").frame(width: 24, height: 24) + } + .menuIndicator(.hidden) + .buttonStyle(.borderless) + .frame(width: 28) + .help(Text("Theme Actions")) + .accessibilityLabel(Text("Theme Actions")) + + Spacer() } + .padding(.horizontal, 8) + .padding(.vertical, 4) + } + + // MARK: - Actions + + private func duplicateSelectedTheme() { + guard let theme = selectedTheme else { return } + var copy = theme + copy.id = ThemeIdentifier.generated() + copy.name = String(format: String(localized: "%@ (Copy)"), theme.name) + + perform { try catalog.save(copy) } then: { selectedThemeId = copy.id } } private func deleteSelectedTheme() { - do { - try engine.deleteUserTheme(id: selectedThemeId) - selectedThemeId = engine.activeTheme.id - } catch { - errorMessage = error.localizedDescription - showError = true - } + guard let theme = selectedTheme, theme.isEditable else { return } + perform { try catalog.delete(id: theme.id) } then: { selectedThemeId = fallbackThemeId } } private func uninstallRegistryTheme() { guard let theme = selectedTheme, theme.isRegistry else { return } - let meta = ThemeStorage.loadRegistryMeta() - guard let entry = meta.installed.first(where: { $0.id == theme.id }) else { return } - do { - try engine.uninstallRegistryTheme(registryPluginId: entry.registryPluginId) - selectedThemeId = engine.activeTheme.id - } catch { - errorMessage = error.localizedDescription - showError = true + guard let entry = catalog.loadRegistryMeta().installed.first(where: { $0.id == theme.id }) else { return } + + perform { + try ThemeRegistryInstaller.shared.uninstall(registryPluginId: entry.registryPluginId) + } then: { + selectedThemeId = fallbackThemeId } } - private func exportActiveTheme() { - guard let window = AlertHelper.resolveWindow(nil) else { return } + private func exportSelectedTheme() { + guard let theme = selectedTheme, let window = AlertHelper.resolveWindow(nil) else { return } + let panel = NSSavePanel() panel.allowedContentTypes = [.json] - panel.nameFieldStringValue = engine.activeTheme.name + ".json" + panel.nameFieldStringValue = theme.name + ".json" panel.canCreateDirectories = true panel.beginSheetModal(for: window) { response in guard response == .OK, let url = panel.url else { return } do { - try engine.exportTheme(engine.activeTheme, to: url) + try catalog.exportTheme(theme, to: url) } catch { AlertHelper.showErrorSheet( title: String(localized: "Could not export the theme"), @@ -213,19 +214,29 @@ internal struct ThemeListView: View { private func importTheme() { guard let window = AlertHelper.resolveWindow(nil) else { return } + let panel = NSOpenPanel() panel.allowedContentTypes = [.json] panel.allowsMultipleSelection = false panel.canChooseDirectories = false panel.beginSheetModal(for: window) { response in guard response == .OK, let url = panel.url else { return } - do { - let imported = try self.engine.importTheme(from: url) - self.selectedThemeId = imported.id - } catch { - self.errorMessage = error.localizedDescription - self.showError = true + perform { + let imported = try catalog.importTheme(from: url) + guard imported.appearance == slotAppearance else { return } + selectedThemeId = imported.id } } } + + private func perform(_ work: () throws -> Void, then completion: () -> Void = {}) { + do { + try work() + completion() + } catch { + Self.logger.error("Theme action failed: \(error.localizedDescription)") + errorMessage = error.localizedDescription + showError = true + } + } } diff --git a/TablePro/Views/Settings/AppearanceSettingsView.swift b/TablePro/Views/Settings/AppearanceSettingsView.swift index a273c883e5..b473035976 100644 --- a/TablePro/Views/Settings/AppearanceSettingsView.swift +++ b/TablePro/Views/Settings/AppearanceSettingsView.swift @@ -83,7 +83,7 @@ struct AppearanceSettingsView: View { ThemeListView(selectedThemeId: slotThemeBinding, slotAppearance: slotAppearance) .frame(minWidth: 180, idealWidth: 210, maxWidth: 250) - ThemeEditorView(selectedThemeId: slotThemeBinding) + ThemeEditorView(selectedThemeId: slotThemeBinding, slotAppearance: slotAppearance) .frame(minWidth: 400) } } diff --git a/TablePro/Views/Settings/DataResultsSettingsView.swift b/TablePro/Views/Settings/DataResultsSettingsView.swift index a0a72fea87..af0554b2d0 100644 --- a/TablePro/Views/Settings/DataResultsSettingsView.swift +++ b/TablePro/Views/Settings/DataResultsSettingsView.swift @@ -9,9 +9,12 @@ struct DataResultsSettingsView: View { @Binding var dataGrid: DataGridSettings @Binding var history: HistorySettings @Binding var editor: EditorSettings + @Binding var typography: TypographySettings var body: some View { Form { + TypographySection(domain: .dataGrid, settings: $typography) + DataGridSection(settings: $dataGrid) Section("JSON Viewer") { @@ -34,7 +37,8 @@ struct DataResultsSettingsView: View { DataResultsSettingsView( dataGrid: .constant(.default), history: .constant(.default), - editor: .constant(.default) + editor: .constant(.default), + typography: .constant(.default) ) .frame(width: 450, height: 500) } diff --git a/TablePro/Views/Settings/EditorSettingsView.swift b/TablePro/Views/Settings/EditorSettingsView.swift index f59e3bba5f..7faf144016 100644 --- a/TablePro/Views/Settings/EditorSettingsView.swift +++ b/TablePro/Views/Settings/EditorSettingsView.swift @@ -7,9 +7,12 @@ import SwiftUI struct EditorSettingsView: View { @Binding var settings: EditorSettings + @Binding var typography: TypographySettings var body: some View { Form { + TypographySection(domain: .editor, settings: $typography) + Section("SQL Editor") { Toggle("Show line numbers", isOn: $settings.showLineNumbers) Toggle("Highlight current line", isOn: $settings.highlightCurrentLine) @@ -17,6 +20,8 @@ struct EditorSettingsView: View { Toggle("Word wrap", isOn: $settings.wordWrap) Toggle("Code folding", isOn: $settings.codeFoldingEnabled) Toggle("Run button beside each statement", isOn: $settings.showStatementRunControls) + .disabled(!settings.showLineNumbers) + .help(Text("The run button sits in the gutter, which needs line numbers.")) Toggle("Show invisible characters", isOn: $settings.showInvisibleCharacters) Picker("Tab width:", selection: $settings.tabWidth) { Text("2 spaces").tag(2) @@ -35,6 +40,6 @@ struct EditorSettingsView: View { } #Preview { - EditorSettingsView(settings: .constant(.default)) + EditorSettingsView(settings: .constant(.default), typography: .constant(.default)) .frame(width: 450, height: 500) } diff --git a/TablePro/Views/Settings/Sections/TypographySection.swift b/TablePro/Views/Settings/Sections/TypographySection.swift new file mode 100644 index 0000000000..cb50b3a815 --- /dev/null +++ b/TablePro/Views/Settings/Sections/TypographySection.swift @@ -0,0 +1,64 @@ +import SwiftUI + +/// The two font domains, each on the pane that owns the surfaces it applies to. They used to live +/// inside the theme file, so a zoom shortcut rewrote a whole theme, and a font edit on a built-in +/// forked it into a copy. +internal struct TypographySection: View { + internal enum Domain { + case editor + case dataGrid + + internal var title: String { + switch self { + case .editor: return String(localized: "Editor Font") + case .dataGrid: return String(localized: "Data Grid Font") + } + } + + internal var caption: String { + switch self { + case .editor: + return String(localized: "Applies to the SQL editor, the JSON viewer's Text mode, and the previews.") + case .dataGrid: + return String(localized: "Applies to grid cells, the inspector, cell popovers and the row diff.") + } + } + } + + internal let domain: Domain + @Binding internal var settings: TypographySettings + + internal var body: some View { + Section(domain.title) { + Picker(String(localized: "Family:"), selection: familyBinding) { + ForEach(EditorFontResolver.availableMonospacedFamilies) { family in + Text(family.displayName).tag(family.id) + } + } + + Picker(String(localized: "Size:"), selection: sizeBinding) { + ForEach(TypographySettings.sizeRange, id: \.self) { size in + Text(verbatim: "\(size) pt").tag(size) + } + } + + Text(domain.caption) + .font(.caption) + .foregroundStyle(.secondary) + } + } + + private var familyBinding: Binding { + switch domain { + case .editor: return $settings.editorFontFamily + case .dataGrid: return $settings.dataGridFontFamily + } + } + + private var sizeBinding: Binding { + switch domain { + case .editor: return $settings.editorFontSize + case .dataGrid: return $settings.dataGridFontSize + } + } +} diff --git a/TablePro/Views/Settings/SettingsWindowController.swift b/TablePro/Views/Settings/SettingsWindowController.swift index ae7f2e75e2..0d86a2a587 100644 --- a/TablePro/Views/Settings/SettingsWindowController.swift +++ b/TablePro/Views/Settings/SettingsWindowController.swift @@ -140,12 +140,16 @@ private struct SettingsPaneContent: View { case .appearance: AppearanceSettingsView(settings: $settingsManager.appearance) case .editor: - EditorSettingsView(settings: $settingsManager.editor) + EditorSettingsView( + settings: $settingsManager.editor, + typography: $settingsManager.typography + ) case .data: DataResultsSettingsView( dataGrid: $settingsManager.dataGrid, history: $settingsManager.history, - editor: $settingsManager.editor + editor: $settingsManager.editor, + typography: $settingsManager.typography ) case .keyboard: KeyboardSettingsView(settings: $settingsManager.keyboard) diff --git a/TablePro/Views/Settings/ThemePreviewCard.swift b/TablePro/Views/Settings/ThemePreviewCard.swift index 0efd021cf5..c43c1147d7 100644 --- a/TablePro/Views/Settings/ThemePreviewCard.swift +++ b/TablePro/Views/Settings/ThemePreviewCard.swift @@ -108,36 +108,26 @@ struct ThemePreviewCard: View { /// in, not in whichever one Settings happens to be showing. private var previewColorScheme: ColorScheme { switch theme.appearance { - case .dark: - return .dark - case .light: - return .light - case .auto: - return colorScheme + case .dark: return .dark + case .light: return .light } } private var sidebarStrip: some View { ZStack(alignment: .topLeading) { Rectangle() - .fill(theme.sidebar.background?.swiftUIColor - ?? Color(nsColor: .windowBackgroundColor)) + .fill(theme.dataGrid.headerBackground.swiftUIColor) VStack(alignment: .leading, spacing: size == .compact ? 3 : 4) { let widths: [CGFloat] = size == .compact ? [10, 14, 13, 9] : [14, 18, 17, 12] - ForEach(0..<4, id: \.self) { i in + ForEach(0..<4, id: \.self) { index in RoundedRectangle(cornerRadius: 1) - .fill(i == 1 - ? (theme.sidebar.selectedItem?.swiftUIColor - ?? Color(nsColor: .selectedContentBackgroundColor)).opacity(0.6) - : (theme.sidebar.text?.swiftUIColor - ?? Color(nsColor: .labelColor)).opacity(0.25)) - .frame( - width: widths[i], - height: codeLineHeight - ) + .fill(index == 1 + ? theme.dataGrid.selection.swiftUIColor.opacity(0.6) + : theme.dataGrid.rowNumber.swiftUIColor.opacity(0.6)) + .frame(width: widths[index], height: codeLineHeight) } } .padding(.top, size == .compact ? 5 : 8) @@ -174,7 +164,7 @@ struct ThemePreviewCard: View { } } - private func codeLine(widths: [CGFloat], colors: [String]) -> some View { + private func codeLine(widths: [CGFloat], colors: [ThemeColorValue]) -> some View { HStack(spacing: size == .compact ? 2 : 3) { ForEach(Array(zip(widths, colors).enumerated()), id: \.offset) { _, pair in RoundedRectangle(cornerRadius: 1) @@ -185,22 +175,22 @@ struct ThemePreviewCard: View { } private var dataGridArea: some View { - let colors = ResolvedDataGridColors(from: theme.dataGrid) + let colors = theme.dataGrid return VStack(spacing: 0) { ForEach(0.. [String: Any] { - let url = Self.themesDirectory.appendingPathComponent("\(id).json") - let data = try Data(contentsOf: url) - let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] - let editor = json?["editor"] as? [String: Any] - return try #require(editor) - } - - @Test("Every bundled theme declares currentStatementHighlight", arguments: themeIds) - func themeDeclaresStatementHighlight(id: String) throws { - let colors = try editorColors(for: id) - let value = colors["currentStatementHighlight"] as? String - #expect(value?.isEmpty == false, "\(id) omits currentStatementHighlight") - } - - /// A band the same colour as the caret line or the selection tells the reader nothing. Dracula and Nord already - /// set those two equal to each other, so the collision is live rather than hypothetical. - @Test("The statement highlight differs from the line highlight and the selection", arguments: themeIds) - func statementHighlightIsDistinct(id: String) throws { - let colors = try editorColors(for: id) - let statement = colors["currentStatementHighlight"] as? String - - #expect(statement != colors["currentLineHighlight"] as? String, "\(id): band matches the caret line") - #expect(statement != colors["selection"] as? String, "\(id): band matches the selection") - #expect(statement != colors["background"] as? String, "\(id): band matches the background") - } - - /// The band is painted under the caret line highlight, so it has to layer with it rather than cover it. - @Test("The statement highlight carries alpha", arguments: themeIds) - func statementHighlightCarriesAlpha(id: String) throws { - let colors = try editorColors(for: id) - let value = try #require(colors["currentStatementHighlight"] as? String) - - #expect(value.count == 9, "\(id): expected #RRGGBBAA, got \(value)") - } -} diff --git a/TableProTests/Theme/DataGridThemeColorsTests.swift b/TableProTests/Theme/DataGridThemeColorsTests.swift deleted file mode 100644 index d3a745e32b..0000000000 --- a/TableProTests/Theme/DataGridThemeColorsTests.swift +++ /dev/null @@ -1,235 +0,0 @@ -// -// DataGridThemeColorsTests.swift -// TableProTests -// - -import AppKit -import Foundation -@testable import TablePro -import Testing - -/// Activates themes on the shared `ThemeEngine`. Every body that does is synchronous and -/// `@MainActor`, so nothing else on the main actor can run between activating a test theme and -/// restoring the original one. -@Suite("Data grid theme colors", .serialized) -@MainActor -struct DataGridThemeColorsTests { - private static let systemDefaultedKeys = [ - "background", "text", "alternateRow", "nullValue", "boolTrue", "boolFalse", "rowNumber", - ] - - private static var repositoryRoot: URL { - URL(fileURLWithPath: #filePath) - .deletingLastPathComponent() - .deletingLastPathComponent() - .deletingLastPathComponent() - } - - private func sRGB(_ color: NSColor?) -> NSColor? { - color?.usingColorSpace(.sRGB) - } - - private func matches(_ lhs: NSColor?, _ hex: String) -> Bool { - guard let lhs = sRGB(lhs), let rhs = sRGB(hex.nsColor) else { return false } - return abs(lhs.redComponent - rhs.redComponent) < 0.01 - && abs(lhs.greenComponent - rhs.greenComponent) < 0.01 - && abs(lhs.blueComponent - rhs.blueComponent) < 0.01 - && abs(lhs.alphaComponent - rhs.alphaComponent) < 0.01 - } - - private func withTheme(_ configure: (inout DataGridThemeColors) -> Void, _ body: () throws -> Void) rethrows { - let engine = ThemeEngine.shared - let original = engine.activeTheme - defer { engine.activateTheme(original) } - var theme = ThemeDefinition.default - theme.id = "test.grid-colors" - configure(&theme.dataGrid) - engine.activateTheme(theme) - try body() - } - - // MARK: - Decoding - - @Test("An undeclared grid color decodes as absent, a state tint as the default") - func emptyGroupDecodes() throws { - let decoded = try JSONDecoder().decode(DataGridThemeColors.self, from: Data("{}".utf8)) - - #expect(decoded == DataGridThemeColors.defaultLight) - #expect(decoded.background == nil) - #expect(decoded.boolTrue == nil) - #expect(decoded.modified == DataGridThemeColors.defaultLight.modified) - } - - @Test("A theme written with focusBorder still decodes, and the key is dropped on save") - func focusBorderIsIgnored() throws { - let json = """ - { "background": "#282A36", "text": "#F8F8F2", "focusBorder": "#BD93F9", "deleted": "#FF555526" } - """ - let decoded = try JSONDecoder().decode(DataGridThemeColors.self, from: Data(json.utf8)) - let encoded = try #require(String(data: JSONEncoder().encode(decoded), encoding: .utf8)) - - #expect(decoded.background == "#282A36") - #expect(decoded.text == "#F8F8F2") - #expect(decoded.deleted == "#FF555526") - #expect(!encoded.contains("focusBorder")) - } - - @Test("An undeclared grid color is left out of the saved file") - func undeclaredColorsAreNotWritten() throws { - let encoded = try #require(String(data: JSONEncoder().encode(DataGridThemeColors.defaultLight), encoding: .utf8)) - - for key in Self.systemDefaultedKeys { - #expect(!encoded.contains("\"\(key)\""), "\(key) was written") - } - } - - // MARK: - Resolution - - @Test("An undeclared grid color resolves to the color the grid draws without a theme") - func undeclaredColorsResolveToSystem() { - let resolved = ResolvedDataGridColors(from: .defaultLight) - - #expect(resolved.background == .controlBackgroundColor) - #expect(resolved.text == .labelColor) - #expect(resolved.alternateRow == NSColor.alternatingContentBackgroundColors.last) - #expect(resolved.nullValue == .secondaryLabelColor) - #expect(resolved.rowNumber == .secondaryLabelColor) - #expect(resolved.boolTrue == nil) - #expect(resolved.boolFalse == nil) - } - - @Test("A declared grid color resolves to its own value") - func declaredColorsResolve() { - var colors = DataGridThemeColors.defaultLight - colors.background = "#102030" - colors.text = "#405060" - colors.alternateRow = "#708090" - colors.nullValue = "#A0B0C0" - colors.boolTrue = "#00FF00" - colors.boolFalse = "#FF0000" - colors.rowNumber = "#123456" - let resolved = ResolvedDataGridColors(from: colors) - - #expect(matches(resolved.background, "#102030")) - #expect(matches(resolved.text, "#405060")) - #expect(matches(resolved.alternateRow, "#708090")) - #expect(matches(resolved.nullValue, "#A0B0C0")) - #expect(matches(resolved.boolTrue, "#00FF00")) - #expect(matches(resolved.boolFalse, "#FF0000")) - #expect(matches(resolved.rowNumber, "#123456")) - } - - // MARK: - The grid reads them - - @Test("The table and its stripes take the theme's background and alternate row") - func stripesFollowTheTheme() { - withTheme({ - $0.background = "#102030" - $0.alternateRow = "#708090" - }) { - let tableView = NSTableView() - tableView.usesAlternatingRowBackgroundColors = true - DataGridBodyChrome.applyBackground(to: tableView) - - #expect(matches(tableView.backgroundColor, "#102030")) - #expect(matches(DataGridBodyChrome.stripeColor(forRow: 0, of: tableView), "#102030")) - #expect(matches(DataGridBodyChrome.stripeColor(forRow: 1, of: tableView), "#708090")) - #expect(matches(DataGridBodyChrome.rowBackgroundColor(forRow: 3, of: tableView), "#708090")) - - tableView.usesAlternatingRowBackgroundColors = false - #expect(DataGridBodyChrome.stripeColor(forRow: 1, of: tableView) == nil) - #expect(matches(DataGridBodyChrome.rowBackgroundColor(forRow: 1, of: tableView), "#102030")) - } - } - - @Test("Without grid colors the stripes are the pair NSTableView hands its rows") - func stripesFallBackToSystem() { - withTheme({ _ in }) { - let tableView = NSTableView() - tableView.usesAlternatingRowBackgroundColors = true - DataGridBodyChrome.applyBackground(to: tableView) - let system = NSColor.alternatingContentBackgroundColors - - #expect(tableView.backgroundColor == .controlBackgroundColor) - #expect(DataGridBodyChrome.stripeColor(forRow: 0, of: tableView) == system.first) - #expect(DataGridBodyChrome.stripeColor(forRow: 1, of: tableView) == system.last) - } - } - - @Test("Row numbers take the theme's color, and a deleted row's the deleted text") - func rowNumberColor() { - withTheme({ - $0.rowNumber = "#123456" - $0.deletedText = "#FF000080" - }) { - let registry = DataGridCellRegistry() - let deleted = RowVisualState(isDeleted: true, isInserted: false, modifiedColumns: []) - - #expect(matches(registry.rowNumberColor(for: .empty), "#123456")) - #expect(matches(registry.rowNumberColor(for: deleted), "#FF000080")) - } - } - - @Test("The cell palette carries the theme's text, NULL and boolean colors") - func paletteFollowsTheTheme() { - withTheme({ - $0.text = "#405060" - $0.nullValue = "#A0B0C0" - $0.boolTrue = "#00FF00" - }) { - let palette = ThemeEngine.shared.dataGridCellPalette - - #expect(matches(palette.text, "#405060")) - #expect(matches(palette.placeholderText, "#A0B0C0")) - #expect(matches(palette.booleanTrueText, "#00FF00")) - #expect(palette.booleanFalseText == nil) - } - } - - /// Eight of these keys were declared, editable and shipped in every theme while the grid drew - /// system colors instead, so a theme could set them and see nothing change. - @Test("Every data grid theme color is read by the grid") - func everyKeyHasAGridReader() throws { - let keys = Mirror(reflecting: DataGridThemeColors.defaultLight).children.compactMap(\.label) - let resultsDirectory = Self.repositoryRoot.appendingPathComponent("TablePro/Views/Results", isDirectory: true) - let enumerator = try #require(FileManager.default.enumerator(at: resultsDirectory, includingPropertiesForKeys: nil)) - var source = "" - for case let url as URL in enumerator where url.pathExtension == "swift" { - source += try String(contentsOf: url, encoding: .utf8) - } - - #expect(!keys.isEmpty) - for key in keys { - #expect(source.contains("dataGrid.\(key)"), "No grid code reads the \(key) theme color") - } - } - - // MARK: - Bundled themes - - private func dataGridGroup(ofTheme id: String) throws -> [String: Any] { - let url = Self.repositoryRoot.appendingPathComponent("TablePro/Resources/Themes/\(id).json") - let json = try JSONSerialization.jsonObject(with: Data(contentsOf: url)) as? [String: Any] - return try #require(json?["dataGrid"] as? [String: Any]) - } - - @Test("The default themes leave the grid on system colors", arguments: [ - "tablepro.default-light", "tablepro.default-dark", - ]) - func defaultThemesDeclareNoGridColors(id: String) throws { - let group = try dataGridGroup(ofTheme: id) - - for key in Self.systemDefaultedKeys + ["focusBorder"] { - #expect(group[key] == nil, "\(id) declares \(key)") - } - } - - @Test("The designed themes declare every grid color", arguments: ["tablepro.dracula", "tablepro.nord"]) - func designedThemesDeclareGridColors(id: String) throws { - let group = try dataGridGroup(ofTheme: id) - - for key in Self.systemDefaultedKeys { - #expect((group[key] as? String)?.isEmpty == false, "\(id) omits \(key)") - } - #expect(group["focusBorder"] == nil) - } -} diff --git a/TableProTests/Theme/ThemeDefinitionTests.swift b/TableProTests/Theme/ThemeDefinitionTests.swift deleted file mode 100644 index d6c60cea2f..0000000000 --- a/TableProTests/Theme/ThemeDefinitionTests.swift +++ /dev/null @@ -1,207 +0,0 @@ -// -// ThemeDefinitionTests.swift -// TableProTests -// -// Tests for ThemeDefinition and EditorThemeColors, focusing on the -// currentStatementHighlight field and Codable backward compatibility. -// - -import AppKit -import Foundation -import TableProPluginKit -import Testing -@testable import TablePro - -@Suite("Theme Definition") -struct ThemeDefinitionTests { - // MARK: - Default light theme - - /// The band is painted under the caret line highlight, so it carries alpha rather than being opaque. An opaque - /// value covers the caret line instead of layering with it. - @Test("Default light editor colors include currentStatementHighlight") - func defaultLightHasCurrentStatementHighlight() { - let colors = EditorThemeColors.defaultLight - #expect(colors.currentStatementHighlight == "#0A0A0A0F") - } - - @Test("Default light editor colors have expected background") - func defaultLightBackground() { - let colors = EditorThemeColors.defaultLight - #expect(colors.background == "#FFFFFF") - } - - // MARK: - Codable round-trip - - @Test("EditorThemeColors survives encode-decode round-trip") - func editorThemeColorsRoundTrip() throws { - let original = EditorThemeColors.defaultLight - let encoder = JSONEncoder() - let data = try encoder.encode(original) - let decoder = JSONDecoder() - let decoded = try decoder.decode(EditorThemeColors.self, from: data) - - #expect(decoded.currentStatementHighlight == original.currentStatementHighlight) - #expect(decoded.background == original.background) - #expect(decoded.text == original.text) - #expect(decoded.cursor == original.cursor) - #expect(decoded.currentLineHighlight == original.currentLineHighlight) - #expect(decoded.selection == original.selection) - #expect(decoded.lineNumber == original.lineNumber) - #expect(decoded.invisibles == original.invisibles) - #expect(decoded == original) - } - - @Test("Full ThemeDefinition survives encode-decode round-trip") - func themeDefinitionRoundTrip() throws { - let original = ThemeDefinition.default - let encoder = JSONEncoder() - let data = try encoder.encode(original) - let decoder = JSONDecoder() - let decoded = try decoder.decode(ThemeDefinition.self, from: data) - - #expect(decoded.editor.currentStatementHighlight == original.editor.currentStatementHighlight) - #expect(decoded == original) - } - - // MARK: - Backward compatibility - - @Test("Decoding JSON missing currentStatementHighlight falls back to default") - func backwardCompatibilityMissingField() throws { - // JSON with all editor fields EXCEPT currentStatementHighlight - let json = """ - { - "background": "#1E1E1E", - "text": "#D4D4D4", - "cursor": "#AEAFAD", - "currentLineHighlight": "#2A2D2E", - "selection": "#264F78", - "lineNumber": "#858585", - "invisibles": "#3B3B3B", - "syntax": { - "keyword": "#569CD6", - "string": "#CE9178", - "number": "#B5CEA8", - "comment": "#6A9955", - "null": "#569CD6", - "operator": "#D4D4D4", - "function": "#DCDCAA", - "type": "#4EC9B0" - } - } - """ - let data = Data(json.utf8) - let decoded = try JSONDecoder().decode(EditorThemeColors.self, from: data) - - // Should fall back to defaultLight's value - #expect(decoded.currentStatementHighlight == EditorThemeColors.defaultLight.currentStatementHighlight) - // Other fields should use the provided values - #expect(decoded.background == "#1E1E1E") - #expect(decoded.text == "#D4D4D4") - } - - @Test("Decoding empty JSON falls back to all defaults") - func emptyJsonFallsBackToDefaults() throws { - let json = "{}" - let data = Data(json.utf8) - let decoded = try JSONDecoder().decode(EditorThemeColors.self, from: data) - - #expect(decoded == EditorThemeColors.defaultLight) - } - - @Test("Decoding JSON with currentStatementHighlight preserves custom value") - func customCurrentStatementHighlight() throws { - let json = """ - { - "background": "#FFFFFF", - "text": "#000000", - "cursor": "#000000", - "currentLineHighlight": "#ECF5FF", - "selection": "#B4D8FD", - "lineNumber": "#747478", - "invisibles": "#D6D6D6", - "currentStatementHighlight": "#AABBCC", - "syntax": { - "keyword": "#9B2393", - "string": "#C41A16", - "number": "#1C00CF", - "comment": "#5D6C79", - "null": "#9B2393", - "operator": "#000000", - "function": "#326D74", - "type": "#3F6E74" - } - } - """ - let data = Data(json.utf8) - let decoded = try JSONDecoder().decode(EditorThemeColors.self, from: data) - - #expect(decoded.currentStatementHighlight == "#AABBCC") - } - - // MARK: - Editor font resolver - - @Test("Font resolver always exposes System Mono") - func resolverExposesSystemMono() { - let families = EditorFontResolver.availableMonospacedFamilies - #expect(families.contains { $0.id == EditorFontResolver.systemMonoId }) - } - - @Test("System Mono is first in picker list") - func systemMonoFirst() { - let families = EditorFontResolver.availableMonospacedFamilies - #expect(families.first?.id == EditorFontResolver.systemMonoId) - } - - @Test("Editor font cache falls back for unknown font family") - func editorCacheFallsBackForUnknownFamily() { - let fonts = ThemeFonts( - editorFontFamily: "NoSuchFamily-XYZ", - editorFontSize: 13, - dataGridFontFamily: "System Mono", - dataGridFontSize: 13 - ) - let cache = EditorFontCache(from: fonts) - #expect(cache.font.pointSize > 0) - } - - @Test("Data grid cache falls back for unknown font family") - func dataGridCacheFallsBackForUnknownFamily() { - let fonts = ThemeFonts( - editorFontFamily: "System Mono", - editorFontSize: 13, - dataGridFontFamily: "NoSuchFamily-XYZ", - dataGridFontSize: 13 - ) - let cache = DataGridFontCacheResolved(from: fonts) - #expect(cache.regular.pointSize > 0) - #expect(cache.monoCharWidth > 0) - } - - @Test("Resolver list has unique IDs") - func resolverListHasUniqueIds() { - let ids = EditorFontResolver.availableMonospacedFamilies.map(\.id) - #expect(Set(ids).count == ids.count) - } - - @Test("Unknown family reports unavailable") - func unknownFamilyUnavailable() { - #expect(EditorFontResolver.isAvailable(familyId: "NoSuchFamily-XYZ") == false) - } - - @Test("ThemeFonts decode keeps legacy family strings") - func themeFontsDecodeKeepsLegacyStrings() throws { - let json = #"{"editorFontFamily":"Menlo","editorFontSize":13,"dataGridFontFamily":"Monaco","dataGridFontSize":13}"# - let decoded = try JSONDecoder().decode(ThemeFonts.self, from: Data(json.utf8)) - #expect(decoded.editorFontFamily == "Menlo") - #expect(decoded.dataGridFontFamily == "Monaco") - } - - @Test("All resolver font families are monospaced") - func allResolverFamiliesAreMonospaced() { - let families = EditorFontResolver.availableMonospacedFamilies - for family in families where family.id != EditorFontResolver.systemMonoId { - let font = EditorFontResolver.resolve(familyId: family.id, size: 12) - #expect(font.fontDescriptor.symbolicTraits.contains(.monoSpace)) - } - } -} diff --git a/TableProTests/Theme/ThemeDocumentTests.swift b/TableProTests/Theme/ThemeDocumentTests.swift new file mode 100644 index 0000000000..8346849fd8 --- /dev/null +++ b/TableProTests/Theme/ThemeDocumentTests.swift @@ -0,0 +1,181 @@ +// +// ThemeDocumentTests.swift +// TableProTests +// +// The previous decoder read every key with `decodeIfPresent` and a Default Light fallback, so an +// empty object and a VS Code theme both decoded "successfully" and rendered as Default Light under +// the file's own name. These pin the gate that replaced it. +// + +import Foundation +@testable import TablePro +import Testing + +@Suite("Theme document gate") +struct ThemeDocumentTests { + private static func json(_ object: [String: Any]) -> Data { + // swiftlint:disable:next force_try + try! JSONSerialization.data(withJSONObject: object) + } + + private static func completeTheme(appearance: ThemeAppearance = .dark) -> [String: Any] { + var root: [String: Any] = [ + "schema": ThemeSchema.current, + "id": "user.test", + "name": "Test", + "author": "Tests", + "appearance": appearance.rawValue, + ] + + for slot in ThemeSlot.allCases { + var cursor = root + insert(slot.rawValue.components(separatedBy: "."), value: "#112233", into: &cursor) + root = cursor + } + + return root + } + + private static func insert(_ path: [String], value: String, into container: inout [String: Any]) { + guard let head = path.first else { return } + guard path.count > 1 else { + container[head] = value + return + } + var child = container[head] as? [String: Any] ?? [:] + insert(Array(path.dropFirst()), value: value, into: &child) + container[head] = child + } + + @Test("A complete document decodes") + func completeDocumentDecodes() throws { + let document = try ThemeDocument(data: Self.json(Self.completeTheme())) + #expect(document.id == "user.test") + #expect(document.appearance == .dark) + #expect(document.colors.count == ThemeSlot.allCases.count) + } + + @Test("An empty object is rejected") + func emptyObjectIsRejected() { + #expect(throws: ThemeLoadError.missingSchema) { + try ThemeDocument(data: Self.json([:])) + } + } + + @Test("A file in the old format is rejected") + func oldSchemaIsRejected() { + let old: [String: Any] = [ + "version": 1, + "id": "user.old", + "name": "Old", + "appearance": "dark", + "editor": ["background": "#000000"], + ] + + #expect(throws: ThemeLoadError.missingSchema) { + try ThemeDocument(data: Self.json(old)) + } + } + + @Test("A schema from a newer TablePro is rejected") + func newerSchemaIsRejected() { + var root = Self.completeTheme() + root["schema"] = ThemeSchema.current + 1 + + #expect(throws: ThemeLoadError.schemaTooNew(found: ThemeSchema.current + 1, supported: ThemeSchema.current)) { + try ThemeDocument(data: Self.json(root)) + } + } + + @Test("A missing slot is reported, not filled in silently") + func missingSlotIsRejected() throws { + var root = Self.completeTheme() + var content = try #require(root["content"] as? [String: Any]) + var editor = try #require(content["editor"] as? [String: Any]) + editor.removeValue(forKey: "cursor") + content["editor"] = editor + root["content"] = content + + #expect(throws: ThemeLoadError.missingSlots([ThemeSlot.editorCursor.rawValue])) { + try ThemeDocument(data: Self.json(root)) + } + } + + @Test("A key TablePro does not use is reported") + func unknownKeyIsRejected() throws { + var root = Self.completeTheme() + var content = try #require(root["content"] as? [String: Any]) + content["sidebar"] = ["background": "#000000"] + root["content"] = content + + #expect(throws: ThemeLoadError.unknownKeys(["content.sidebar.background"])) { + try ThemeDocument(data: Self.json(root)) + } + } + + /// A valid prefix used to satisfy the parser, so `#FF79CG` rendered as `#0FF79C` with nothing + /// logged and nothing shown. + @Test("A color with a typo in it is rejected") + func malformedColorIsRejected() throws { + var root = Self.completeTheme() + var content = try #require(root["content"] as? [String: Any]) + var editor = try #require(content["editor"] as? [String: Any]) + editor["background"] = "#FF79CG" + content["editor"] = editor + root["content"] = content + + #expect(throws: ThemeLoadError.invalidColor("#FF79CG")) { + try ThemeDocument(data: Self.json(root)) + } + } + + @Test("An unknown system color name is rejected") + func unknownSystemColorIsRejected() throws { + var root = Self.completeTheme() + var content = try #require(root["content"] as? [String: Any]) + var editor = try #require(content["editor"] as? [String: Any]) + editor["background"] = "system:notARealColor" + content["editor"] = editor + root["content"] = content + + #expect(throws: ThemeLoadError.unknownSystemColor("notARealColor")) { + try ThemeDocument(data: Self.json(root)) + } + } + + @Test("A system color reference round-trips") + func systemColorRoundTrips() throws { + var root = Self.completeTheme() + var content = try #require(root["content"] as? [String: Any]) + var editor = try #require(content["editor"] as? [String: Any]) + editor["background"] = "system:textBackground" + content["editor"] = editor + root["content"] = content + + let theme = try ThemeDocument(data: Self.json(root)).resolved() + #expect(theme.editor.background == .system(.textBackground)) + + let reread = try ThemeDocument(data: ThemeEncoder.data(for: theme)).resolved() + #expect(reread.editor.background == .system(.textBackground)) + } + + @Test("Every slot round-trips through the encoder") + func everySlotRoundTrips() throws { + let theme = try ThemeDocument(data: Self.json(Self.completeTheme())).resolved() + let reread = try ThemeDocument(data: ThemeEncoder.data(for: theme)).resolved() + + for slot in ThemeSlot.allCases { + #expect(reread[keyPath: slot.keyPath] == theme[keyPath: slot.keyPath], "\(slot.rawValue)") + } + } + + @Test("Hex parsing consumes the whole string") + func hexParsingIsStrict() { + #expect(HexColor.canonicalize("#ff79c6") == "#FF79C6") + #expect(HexColor.canonicalize("#FF79C680") == "#FF79C680") + #expect(HexColor.canonicalize("#FF79CG") == nil) + #expect(HexColor.canonicalize("FF79C6") == nil) + #expect(HexColor.canonicalize("#FFF") == nil) + #expect(HexColor.canonicalize("") == nil) + } +} diff --git a/TableProTests/Theme/ThemeSlotCoverageTests.swift b/TableProTests/Theme/ThemeSlotCoverageTests.swift new file mode 100644 index 0000000000..bcbf96e21a --- /dev/null +++ b/TableProTests/Theme/ThemeSlotCoverageTests.swift @@ -0,0 +1,115 @@ +// +// ThemeSlotCoverageTests.swift +// TableProTests +// +// Whole colour groups shipped declared, editable and read by nothing: `sidebar` and `toolbar` had +// no reader at all, `ui` had one, and `ui.accentColor` was declared by every bundled theme and had +// no property to decode into. A slot exists here only because a call site reads it. +// + +import Foundation +@testable import TablePro +import Testing + +@Suite("Theme slot coverage") +struct ThemeSlotCoverageTests { + private static let repositoryRoot: URL = { + var url = URL(fileURLWithPath: #filePath) + for _ in 0 ..< 3 { + url.deleteLastPathComponent() + } + return url + }() + + /// The files that declare the slots. Everything else counts as a reader, including + /// `ThemeEngine.makeEditorTheme`, which is where the editor and syntax slots are read. + private static let definitionFiles: Set = [ + "ThemeDefinition.swift", "BuiltInThemes.swift", "ThemeColorValue.swift", + "ThemeDocument.swift", "ThemePalette.swift", "ThemeCatalog.swift", "ThemeResolver.swift", + ] + + private static let appSource: String = { + let directory = repositoryRoot.appendingPathComponent("TablePro", isDirectory: true) + guard let enumerator = FileManager.default.enumerator(at: directory, includingPropertiesForKeys: nil) else { + return "" + } + + var source = "" + for case let url as URL in enumerator where url.pathExtension == "swift" { + guard !Self.definitionFiles.contains(url.lastPathComponent) else { continue } + source += (try? String(contentsOf: url, encoding: .utf8)) ?? "" + } + return source + }() + + @Test("Every slot is read by app code") + func everySlotHasAReader() { + #expect(!Self.appSource.isEmpty) + + for slot in ThemeSlot.allCases { + #expect(Self.appSource.contains(".\(String(describing: slot))"), "Nothing reads \(slot.rawValue)") + } + } + + @Test("Slot paths are unique and namespaced") + func slotPathsAreWellFormed() { + let paths = ThemeSlot.allCases.map(\.rawValue) + #expect(Set(paths).count == paths.count) + + for path in paths { + #expect(path.hasPrefix("content."), "\(path)") + #expect(path.components(separatedBy: ".").count >= 3, "\(path)") + } + } + + @Test("Every slot belongs to exactly one group") + func groupsPartitionTheSlots() { + let grouped = ThemeSlotGroup.allCases.flatMap(\.slots) + #expect(Set(grouped) == Set(ThemeSlot.allCases)) + #expect(grouped.count == ThemeSlot.allCases.count) + } + + // MARK: - Bundled themes + + @Test("Every bundled theme passes the gate", arguments: ["tablepro.dracula", "tablepro.nord"]) + func bundledThemesPassTheGate(id: String) throws { + let url = Self.repositoryRoot.appendingPathComponent("TablePro/Resources/Themes/\(id).json") + let document = try ThemeDocument(data: try Data(contentsOf: url)) + + #expect(document.id == id) + #expect(document.colors.count == ThemeSlot.allCases.count) + } + + /// The bundled themes are the only ones shipped, so a hand-typed colour that never renders is + /// caught here rather than by a user. + @Test("Bundled themes declare a real colour for every slot", arguments: ["tablepro.dracula", "tablepro.nord"]) + func bundledThemesDeclareHexColors(id: String) throws { + let url = Self.repositoryRoot.appendingPathComponent("TablePro/Resources/Themes/\(id).json") + let theme = try ThemeDocument(data: try Data(contentsOf: url)).resolved() + + for slot in ThemeSlot.allCases { + let value = theme[keyPath: slot.keyPath] + #expect(!value.isSystem, "\(id) leaves \(slot.rawValue) on a system colour") + } + } + + /// Default Light and Default Dark keep the surrounds on system colours so the unthemed app is + /// unchanged and keeps the system's Increase Contrast handling. + @Test("The default themes keep the grid surrounds on system colours") + func defaultThemesUseSystemSurrounds() { + for theme in BuiltInThemes.all { + #expect(theme.dataGrid.background.isSystem) + #expect(theme.dataGrid.text.isSystem) + #expect(theme.dataGrid.alternateRow.isSystem) + #expect(theme.dataGrid.selection.isSystem) + #expect(theme.editor.background.isSystem == false) + } + } + + @Test("The default themes declare the appearance of their slot") + func defaultThemesDeclareTheirAppearance() { + #expect(BuiltInThemes.light.appearance == .light) + #expect(BuiltInThemes.dark.appearance == .dark) + #expect(BuiltInThemes.default(for: .dark).id == BuiltInThemes.defaultDarkId) + } +} diff --git a/TableProTests/Theme/ThemeSlotValidationTests.swift b/TableProTests/Theme/ThemeSlotValidationTests.swift index fa5b0167c7..633071e4eb 100644 --- a/TableProTests/Theme/ThemeSlotValidationTests.swift +++ b/TableProTests/Theme/ThemeSlotValidationTests.swift @@ -20,27 +20,20 @@ struct ThemeSlotValidationTests { #expect(ThemeSlotValidation.fits(.light, slot: .dark) == false) } - @Test("An auto theme fits both slots") - func autoFitsBoth() { - #expect(ThemeSlotValidation.fits(.auto, slot: .light)) - #expect(ThemeSlotValidation.fits(.auto, slot: .dark)) - } - private func theme(_ id: String, _ appearance: ThemeAppearance) -> ThemeDefinition { - var copy = ThemeDefinition.default + var copy = BuiltInThemes.default(for: appearance) copy.id = id - copy.appearance = appearance return copy } private var sample: [ThemeDefinition] { - [theme("light", .light), theme("dark", .dark), theme("auto", .auto)] + [theme("light", .light), theme("dark", .dark)] } @Test("Only fitting themes stay in the list") func listIsFiltered() { let eligible = ThemeSlotValidation.eligibleThemes(sample, slot: .light, keeping: nil) - #expect(eligible.map(\.id) == ["light", "auto"]) + #expect(eligible.map(\.id) == ["light"]) } /// The row the user is standing on can never be filtered away, because the alternative was to @@ -48,18 +41,56 @@ struct ThemeSlotValidationTests { @Test("A contradicting theme stays listed while it is the one selected") func selectedContradictingThemeIsKept() { let eligible = ThemeSlotValidation.eligibleThemes(sample, slot: .light, keeping: "dark") - #expect(eligible.map(\.id) == ["light", "dark", "auto"]) + #expect(eligible.map(\.id) == ["light", "dark"]) } @Test("Keeping a selection does not duplicate a theme that already fits") func keptSelectionIsNotDuplicated() { let eligible = ThemeSlotValidation.eligibleThemes(sample, slot: .light, keeping: "light") - #expect(eligible.map(\.id) == ["light", "auto"]) + #expect(eligible.map(\.id) == ["light"]) } @Test("An unknown selected id adds nothing to the list") func unknownSelectionAddsNothing() { let eligible = ThemeSlotValidation.eligibleThemes(sample, slot: .dark, keeping: "does.not.exist") - #expect(eligible.map(\.id) == ["dark", "auto"]) + #expect(eligible.map(\.id) == ["dark"]) + } + + /// A slot whose theme is missing, rejected, or of the wrong appearance falls back to that + /// slot's own built-in. Falling back to Default Light whichever slot asked painted a white + /// editor inside dark chrome. + @Test("A dark slot that cannot resolve falls back to Default Dark") + func darkSlotFallsBackToDefaultDark() { + let selection = ThemeResolver.resolve( + mode: .dark, + lightThemeId: BuiltInThemes.defaultLightId, + darkThemeId: "user.deleted", + themes: BuiltInThemes.all, + systemIsDark: true + ) + + #expect(selection.pair.dark.id == BuiltInThemes.defaultDarkId) + #expect(selection.active.appearance == .dark) + } + + @Test("A light theme sitting in the dark slot falls back to Default Dark") + func misfitThemeInDarkSlotFallsBack() { + let selection = ThemeResolver.resolve( + mode: .dark, + lightThemeId: BuiltInThemes.defaultLightId, + darkThemeId: BuiltInThemes.defaultLightId, + themes: BuiltInThemes.all, + systemIsDark: true + ) + + #expect(selection.pair.dark.id == BuiltInThemes.defaultDarkId) + } + + @Test("Auto follows the system appearance") + func autoFollowsSystem() { + #expect(ThemeResolver.effectiveAppearance(mode: .auto, systemIsDark: true) == .dark) + #expect(ThemeResolver.effectiveAppearance(mode: .auto, systemIsDark: false) == .light) + #expect(ThemeResolver.effectiveAppearance(mode: .light, systemIsDark: true) == .light) + #expect(ThemeResolver.effectiveAppearance(mode: .dark, systemIsDark: false) == .dark) } } diff --git a/TableProTests/Theme/ValueFontTests.swift b/TableProTests/Theme/ValueFontTests.swift index 0e80b9b7df..ba040ee5f5 100644 --- a/TableProTests/Theme/ValueFontTests.swift +++ b/TableProTests/Theme/ValueFontTests.swift @@ -15,10 +15,10 @@ import Foundation @testable import TablePro import Testing -/// The first two tests activate a theme on the shared `ThemeEngine`. What keeps that from reaching a +/// The first two tests change the fonts on the shared `ThemeEngine`. What keeps that from reaching a /// suite running in parallel is that both bodies are synchronous and `@MainActor`, so nothing else on -/// the main actor can interleave between activating the test theme and restoring the original one, the -/// same way `DataGridRowTintThemeTests` holds. Adding an `await` inside `withTheme` would break it. +/// the main actor can interleave between applying the test fonts and restoring the original ones, the +/// same way `DataGridRowTintThemeTests` holds. Adding an `await` inside `withTypography` breaks it. @Suite("Stored value font", .serialized) @MainActor struct ValueFontTests { @@ -30,30 +30,27 @@ struct ValueFontTests { return url }() - private static func theme(editorSize: Int, gridSize: Int) -> ThemeDefinition { - var theme = ThemeDefinition.default - theme.id = "user.value-font-tests" - theme.fonts = ThemeFonts( + private static func typography(editorSize: Int, gridSize: Int) -> TypographySettings { + TypographySettings( editorFontFamily: "Menlo", editorFontSize: editorSize, dataGridFontFamily: "Courier", dataGridFontSize: gridSize ) - return theme } - private func withTheme(_ theme: ThemeDefinition, _ body: () -> Void) { - let previous = ThemeEngine.shared.activeTheme - ThemeEngine.shared.activateTheme(theme) + private func withTypography(_ typography: TypographySettings, _ body: () -> Void) { + let previous = AppSettingsManager.shared.typography + ThemeEngine.shared.apply(typography: typography) body() - ThemeEngine.shared.activateTheme(previous) + ThemeEngine.shared.apply(typography: previous) } // MARK: - Which setting the value font comes from @Test("The value font is the data grid font, not the editor font") func valueFontFollowsTheDataGridFont() { - withTheme(Self.theme(editorSize: 18, gridSize: 11)) { + withTypography(Self.typography(editorSize: 18, gridSize: 11)) { let engine = ThemeEngine.shared #expect(engine.valueFont == engine.dataGridFonts.regular) #expect(engine.valueFont != engine.editorFonts.font) @@ -67,8 +64,8 @@ struct ValueFontTests { func valueFontIgnoresTheEditorSize() { var afterSmall: NSFont? var afterLarge: NSFont? - withTheme(Self.theme(editorSize: 11, gridSize: 13)) { afterSmall = ThemeEngine.shared.valueFont } - withTheme(Self.theme(editorSize: 18, gridSize: 13)) { afterLarge = ThemeEngine.shared.valueFont } + withTypography(Self.typography(editorSize: 11, gridSize: 13)) { afterSmall = ThemeEngine.shared.valueFont } + withTypography(Self.typography(editorSize: 18, gridSize: 13)) { afterLarge = ThemeEngine.shared.valueFont } #expect(afterSmall == afterLarge) } diff --git a/TableProTests/Views/Editor/SyntaxHighlightingTests.swift b/TableProTests/Views/Editor/SyntaxHighlightingTests.swift index 784b5575fe..c91f5a3c30 100644 --- a/TableProTests/Views/Editor/SyntaxHighlightingTests.swift +++ b/TableProTests/Views/Editor/SyntaxHighlightingTests.swift @@ -177,11 +177,11 @@ struct SyntaxHighlightingTests { @MainActor @Test("The theme's operator and function colours reach the editor") func themeCarriesOperatorAndFunctionColors() { - let colors = ThemeEngine.shared.colors.editor + let resolved = ThemeEngine.shared.resolved let theme = ThemeEngine.shared.makeEditorTheme() - #expect(Self.sameColor(theme.operators.color, colors.operator)) - #expect(Self.sameColor(theme.functions.color, colors.function)) + #expect(Self.sameColor(theme.operators.color, resolved[.syntaxOperator])) + #expect(Self.sameColor(theme.functions.color, resolved[.syntaxFunction])) } // MARK: - Helpers diff --git a/TableProTests/Views/Results/DataGridCellAppearanceTests.swift b/TableProTests/Views/Results/DataGridCellAppearanceTests.swift index 7bfc51a180..aa622c28fe 100644 --- a/TableProTests/Views/Results/DataGridCellAppearanceTests.swift +++ b/TableProTests/Views/Results/DataGridCellAppearanceTests.swift @@ -21,8 +21,8 @@ struct DataGridCellAppearanceTests { mediumFont: .systemFont(ofSize: 13, weight: .medium), text: .labelColor, placeholderText: .secondaryLabelColor, - booleanTrueText: nil, - booleanFalseText: nil, + booleanTrueText: .labelColor, + booleanFalseText: .labelColor, rowNumberText: .secondaryLabelColor, deletedRowText: .systemRed, modifiedColumnTint: .systemYellow, diff --git a/TableProTests/Views/Results/DataGridRowNumberRenderingTests.swift b/TableProTests/Views/Results/DataGridRowNumberRenderingTests.swift index 4c2f02654f..94ed94fb4b 100644 --- a/TableProTests/Views/Results/DataGridRowNumberRenderingTests.swift +++ b/TableProTests/Views/Results/DataGridRowNumberRenderingTests.swift @@ -456,13 +456,16 @@ struct DataGridRowNumberRenderingTests { @Test("Rows paint the theme's stripes, and the strip still matches them") func rowsPaintTheThemesStripes() throws { let engine = ThemeEngine.shared - let original = engine.activeTheme - defer { engine.activateTheme(original) } - var theme = ThemeDefinition.default + let restore = ThemeSelection(pair: engine.pair, effectiveAppearance: engine.effectiveAppearance) + defer { engine.adopt(restore) } + var theme = BuiltInThemes.light theme.id = "test.grid-stripes" - theme.dataGrid.background = "#282A36" - theme.dataGrid.alternateRow = "#44475A" - engine.activateTheme(theme) + theme.dataGrid.background = .hex("#282A36") + theme.dataGrid.alternateRow = .hex("#44475A") + engine.adopt(ThemeSelection( + pair: ThemePair(light: theme, dark: BuiltInThemes.dark), + effectiveAppearance: .light + )) let grid = makeGrid(appearance: .aqua) let rows = grid.rowsUnderTheStrip diff --git a/TableProTests/Views/Results/DataGridRowTintThemeTests.swift b/TableProTests/Views/Results/DataGridRowTintThemeTests.swift index 9997f2c42d..26e5ca3adc 100644 --- a/TableProTests/Views/Results/DataGridRowTintThemeTests.swift +++ b/TableProTests/Views/Results/DataGridRowTintThemeTests.swift @@ -68,24 +68,30 @@ struct DataGridRowTintThemeTests { return try #require(color.usingColorSpace(.sRGB)) } - private func theme(_ base: ThemeDefinition, id: String, deletedHex: String) -> ThemeDefinition { + private func selection(_ base: ThemeDefinition, id: String, deletedHex: String) -> ThemeSelection { var copy = base copy.id = id - copy.dataGrid.deleted = deletedHex - return copy + copy.dataGrid.deleted = .hex(deletedHex) + + let pair = copy.appearance == .dark + ? ThemePair(light: BuiltInThemes.light, dark: copy) + : ThemePair(light: copy, dark: BuiltInThemes.dark) + + return ThemeSelection(pair: pair, effectiveAppearance: copy.appearance) } @Test("A deleted row takes the new theme's tint even though its state did not change") func deletedRowTintFollowsThemeChange() throws { let engine = ThemeEngine.shared let original = engine.activeTheme - defer { engine.activateTheme(original) } + let restore = ThemeSelection(pair: engine.pair, effectiveAppearance: engine.effectiveAppearance) + defer { engine.adopt(restore) } - engine.activateTheme(theme(original, id: "test.tint.red", deletedHex: "#FF0000")) + engine.adopt(selection(original, id: "test.tint.red", deletedHex: "#FF0000")) let harness = makeRowView(state: Self.deleted) let firstTint = try renderedTint(of: harness.rowView) - engine.activateTheme(theme(original, id: "test.tint.blue", deletedHex: "#0000FF")) + engine.adopt(selection(original, id: "test.tint.blue", deletedHex: "#0000FF")) harness.rowView.invalidateVisualState() let secondTint = try renderedTint(of: harness.rowView) @@ -97,8 +103,9 @@ struct DataGridRowTintThemeTests { func rowPaintsTheLiveState() throws { let engine = ThemeEngine.shared let original = engine.activeTheme - defer { engine.activateTheme(original) } - engine.activateTheme(theme(original, id: "test.tint.red", deletedHex: "#FF0000")) + let restore = ThemeSelection(pair: engine.pair, effectiveAppearance: engine.effectiveAppearance) + defer { engine.adopt(restore) } + engine.adopt(selection(original, id: "test.tint.red", deletedHex: "#FF0000")) let harness = makeRowView(state: .empty) let before = try renderedTint(of: harness.rowView) @@ -114,8 +121,9 @@ struct DataGridRowTintThemeTests { func pendingDeleteOutranksHighlightWash() throws { let engine = ThemeEngine.shared let original = engine.activeTheme - defer { engine.activateTheme(original) } - engine.activateTheme(theme(original, id: "test.tint.red", deletedHex: "#FF0000")) + let restore = ThemeSelection(pair: engine.pair, effectiveAppearance: engine.effectiveAppearance) + defer { engine.adopt(restore) } + engine.adopt(selection(original, id: "test.tint.red", deletedHex: "#FF0000")) let highlight = RowHighlight( rowRule: HighlightRule(columnName: "status", value: "paid", color: .blue), @@ -125,7 +133,7 @@ struct DataGridRowTintThemeTests { let tint = try renderedTint(of: harness.rowView) #expect(tint.redComponent > tint.blueComponent) - #expect(Self.deleted.highlighted(highlight).tint == engine.colors.dataGrid.deleted) + #expect(Self.deleted.highlighted(highlight).tint == engine.palette[.gridDeleted]) #expect(RowVisualState.empty.highlighted(highlight).tint == HighlightColor.blue.washColor) } @@ -133,13 +141,14 @@ struct DataGridRowTintThemeTests { func plainRowStaysUntinted() throws { let engine = ThemeEngine.shared let original = engine.activeTheme - defer { engine.activateTheme(original) } + let restore = ThemeSelection(pair: engine.pair, effectiveAppearance: engine.effectiveAppearance) + defer { engine.adopt(restore) } - engine.activateTheme(theme(original, id: "test.tint.red", deletedHex: "#FF0000")) + engine.adopt(selection(original, id: "test.tint.red", deletedHex: "#FF0000")) let harness = makeRowView(state: .empty) let firstTint = try renderedTint(of: harness.rowView) - engine.activateTheme(theme(original, id: "test.tint.blue", deletedHex: "#0000FF")) + engine.adopt(selection(original, id: "test.tint.blue", deletedHex: "#0000FF")) harness.rowView.invalidateVisualState() let secondTint = try renderedTint(of: harness.rowView) diff --git a/docs/customization/appearance.mdx b/docs/customization/appearance.mdx index ec506c18bb..97ae4631e6 100644 --- a/docs/customization/appearance.mdx +++ b/docs/customization/appearance.mdx @@ -1,6 +1,6 @@ --- title: Appearance -description: Themes, per-theme fonts, color customization, and connection colors +description: Themes, color customization, theme files, and connection colors --- Light and Dark each hold their own theme. The **Editing** control at the top of the tab says which of the two the theme list writes to, so setting your dark theme never means leaving Light mode; **Appearance** beside it picks the one in use, or **Auto** to follow the system. @@ -12,28 +12,23 @@ Light and Dark each hold their own theme. The **Editing** control at the top of ## Themes -Four ship with the app: Default Light, Default Dark, and two more dark ones, Dracula and Nord. One theme carries the editor and syntax colors, the data grid colors, the interface colors, and both fonts. +Four ship with the app: Default Light, Default Dark, and two more dark ones, Dracula and Nord. A theme carries the editor and syntax colors, the data grid colors, and the status colors. -The list groups them into Built-in, Registry, and Custom, and shows the ones that suit the slot you are editing plus whatever that slot already holds. Click a row to assign it; it applies at once if that slot is the one in use. +A theme declares whether it is light or dark, and only appears in the matching slot, plus whatever that slot already holds. Click a row to assign it; it applies at once if that slot is the one in use. -The editor on the right always edits the **active** theme, not the row you highlighted. Switch **Editing** to the slot in use before you change a font or a color, or the change lands on the other theme. +The editor on the right edits the theme selected in the slot named by **Editing**, so a change always lands on the theme you can see highlighted. | Control | What it does | |--------|--------| -| **+** menu | **New Theme** copies the active theme; **Import…** reads a theme JSON file | +| **+** menu | **Duplicate Selected** copies the selected theme; **Import…** reads a theme JSON file | | **-** button | Deletes the selected theme. Custom themes only | -| **Gear** menu | **Duplicate** and **Export…** act on the active theme; **Uninstall** removes the selected registry theme | +| **Gear** menu | **Duplicate** and **Export…** act on the selected theme; **Uninstall** removes the selected registry theme | -A built-in or registry theme is read-only, so the first change forks it. Changing a font makes "Name (Custom)" and edits that; **Duplicate**, **New Theme**, and the **Duplicate Theme** button on the Colors tab make "Name (Copy)" for you to edit. +A built-in or registry theme is read-only and shows a **Duplicate Theme** button, which makes "Name (Copy)" for you to edit. -## Fonts +Fonts are not part of a theme. Editor Font lives in [Editor settings](/customization/editor-settings) and Data Grid Font in [Data settings](/customization/data-settings), and both stay on the Mac you set them on. -The pickers list the monospaced families installed on your Mac; the preview renders a sample query in the theme's own editor colors. - -| Setting | Options | Default | Applies to | -|---------|---------|---------|------------| -| Editor Font | Family + size, 11 to 18 pt | System Mono, 13 pt | SQL editor and the JSON viewer's Text mode | -| Data Grid Font | Family + size, 10 to 18 pt | System Mono, 13 pt | Grid cells, the inspector, the cell popovers and the Compare row diff | +A theme file the app cannot read is listed under **Not Loaded** with the reason, rather than dropped without a word. ## Colors @@ -41,52 +36,48 @@ Custom themes get color wells here. A built-in or registry theme shows a lock an | Group | Controls | |-------|----------| -| Editor | Background, text, cursor, current line, selection, line number, invisibles | +| Editor | Background, text, cursor, selection, current line, current statement, line number, invisibles | | Syntax Colors | Keyword, string, number, comment, NULL, operator, function, type | -| Data Grid | Background, text, alternate row, NULL value, bool true/false, row number, modified/inserted/deleted rows, deleted text | -| Interface | Window, control, and card backgrounds, border, primary/secondary/tertiary text, selection, hover | -| Status Colors | Success, warning, error, info | -| Badges | Badge background, primary key, auto increment | -| Sidebar | Background, text, selected item, hover, section header | -| Toolbar | Secondary and tertiary text | +| Data Grid | Background, text, alternate row, header background, header text, grid line, selection, selected text, inactive selection, focus border, NULL value, bool true/false, row number, modified/inserted/deleted rows, deleted text | +| Status | Success, warning, error | -Interface, Sidebar, and Toolbar colors sit on macOS system colors until you override one, which is why an untouched theme follows your system accent color. So do the grid's background, text, alternate row, NULL value, and row number. Bool true and false show in the grid's text color until you set them. An overridden well grows a reset button that puts the system color back. +A slot holds either a hex color or the name of a macOS system color. Default Light and Default Dark keep the data grid surrounds on system colors, which is why an untouched theme follows your system accent and its Increase Contrast setting. Right-click a well that a built-in leaves on a system color to put that system color back. ## Theme files -A theme is one JSON file. **Export…** in the gear menu writes every color the active theme sets, which is the shortest way to start a new one; **Import…** in the **+** menu reads one back into `~/Library/Application Support/TablePro/Themes/`. Community themes install from the [registry](/features/plugins) under **Settings > Plugins > Browse**, Themes category. +A theme is one JSON file. **Export…** in the gear menu writes every color the selected theme sets, which is the shortest way to start a new one; **Import…** in the **+** menu reads one back into `~/Library/Application Support/TablePro/Themes/`. Community themes install from the [registry](/features/plugins) under **Settings > Plugins > Browse**, Themes category. | Key | Holds | |-----|-------| +| `schema` | Format version. `2` is the version this release reads | | `id`, `name`, `author` | Identity. An `id` that collides with a built-in, a registry theme, or one you already have is replaced on import | -| `version` | Format version, `1` | -| `appearance` | `light`, `dark`, or `auto`. Decides which slot lists the theme; `auto` lists in both | -| `editor` | Editor colors, with syntax colors nested under `syntax` | -| `dataGrid` | Grid colors | -| `ui` | Interface colors, with `status` and `badges` nested | -| `sidebar`, `toolbar` | Sidebar and toolbar colors | -| `fonts` | `editorFontFamily`, `editorFontSize`, `dataGridFontFamily`, `dataGridFontSize` | +| `appearance` | `light` or `dark`. Decides which slot lists the theme | +| `content.editor` | Editor colors, with syntax colors nested under `syntax` | +| `content.dataGrid` | Grid colors | +| `content.status` | Success, warning and error colors | ```json { + "schema": 2, "id": "user.midnight", "name": "Midnight", - "version": 1, - "appearance": "dark", "author": "You", - "editor": { - "background": "#2E3440", - "text": "#D8DEE9", - "currentStatementHighlight": "#FFFFFF0F", - "syntax": { "keyword": "#81A1C1", "string": "#A3BE8C" } - }, - "fonts": { "editorFontFamily": "System Mono", "editorFontSize": 13 } + "appearance": "dark", + "content": { + "editor": { + "background": "#2E3440", + "text": "#D8DEE9", + "syntax": { "keyword": "#81A1C1", "string": "#A3BE8C" } + }, + "dataGrid": { "background": "system:textBackground" }, + "status": { "error": "#BF616A" } + } } ``` -Colors are sRGB hex, `#RRGGBB` or `#RRGGBBAA` for a translucent overlay such as a selection band. A value that is neither renders as the system label color, which is how a typo shows up. +A color is sRGB hex, `#RRGGBB` or `#RRGGBBAA` for a translucent overlay such as a selection band, or `system:` followed by a macOS system color name such as `system:textBackground`. -Every key is optional. A group you leave out falls back to Default Light. A color left out of `ui`, `sidebar`, or `toolbar` is the macOS system color rather than a fixed value, and so is a `dataGrid` `background`, `text`, `alternateRow`, `nullValue`, or `rowNumber`. A missing `boolTrue` or `boolFalse` uses the grid's text color. +Every color a theme declares must be one TablePro reads, and every color TablePro reads must be present. A file that misses one, names one TablePro does not use, carries a color the app cannot parse, or declares a `schema` this release does not read is refused and listed under **Not Loaded** with the reason. Themes written for an earlier version of TablePro are not read and need to be written again. ## Connection colors diff --git a/docs/customization/data-settings.mdx b/docs/customization/data-settings.mdx index e4636fda75..593a1d4c88 100644 --- a/docs/customization/data-settings.mdx +++ b/docs/customization/data-settings.mdx @@ -1,17 +1,25 @@ --- title: Data Settings -description: Data grid, pagination, query result cap, JSON viewer, and query history +description: Data grid font, pagination, query result cap, JSON viewer, and query history --- Browsing a table pages 1,000 rows at a time, and a query that returns more than 10,000 rows stops there. Both numbers, and the rest of what the grid does before you touch anything, are on **Settings > Data**. -The tab is app-wide, so these values apply to every connection you open; filters, column widths, and the sort you clicked are remembered per table instead. Grid fonts are per-theme, on the theme's Fonts tab under [Appearance](/customization/appearance). +The tab is app-wide, so these values apply to every connection you open; filters, column widths, and the sort you clicked are remembered per table instead. The font here is set per Mac, not per theme, and is not synced. Data settings tab Data settings tab +## Font + +| Setting | Default | Applies to | +|---------|---------|------------| +| Data Grid Font | System Mono, 13 pt | Grid cells, the inspector, the cell popovers and the Compare row diff | + +The picker lists the monospaced families installed on your Mac, at 10 to 24 pt. + ## Data Grid | Setting | Default | Notes | diff --git a/docs/customization/editor-settings.mdx b/docs/customization/editor-settings.mdx index c4367eae85..5b2ea15c38 100644 --- a/docs/customization/editor-settings.mdx +++ b/docs/customization/editor-settings.mdx @@ -1,27 +1,35 @@ --- title: Editor Settings -description: SQL editor, Vim mode, line numbers, indentation, and query parameter settings +description: SQL editor font, Vim mode, line numbers, indentation, and query parameter settings --- **Settings > Editor** covers typing and how SQL is displayed. Grid, pagination, result cap and JSON viewer settings are on the [Data](/customization/data-settings) tab instead. -Editor fonts are per-theme. Edit them on the theme's Fonts tab under [Appearance](/customization/appearance). +The font here is set per Mac, not per theme, and is not synced. Editor settings Editor settings +## Font + +| Setting | Default | Applies to | +|---------|---------|------------| +| Editor Font | System Mono, 13 pt | SQL editor, the JSON viewer's Text mode, and the DDL, trigger and import previews | + +The picker lists the monospaced families installed on your Mac, at 10 to 24 pt. `Cmd+=` and `Cmd+-` change the size over the same range. + ## SQL editor | Setting | Default | Notes | |---------|---------|-------| -| Show line numbers | On | | +| Show line numbers | On | Turning this off also hides the per-statement run button | | Highlight current line | On | | | Highlight current statement | On | A faint band behind the statement the cursor is in. See [Statement markers](/features/sql-editor#statement-markers) | | Word wrap | Off | Off means long lines scroll horizontally | | Code folding | On | Shows the fold ribbon in the gutter. See [Code Folding](/features/code-folding) | -| Run button beside each statement | On | Gutter run buttons, revealed when the pointer is over the gutter | +| Run button beside each statement | On | Gutter run buttons, revealed when the pointer is over the gutter. Needs line numbers on | | Tab width | 4 spaces | 2, 4, or 8 | | Auto-uppercase keywords | Off | Uppercases SQL keywords on word boundaries. Strings, comments, and quoted identifiers are untouched | | Query parameters (`:name` syntax) | On | Detects `:name` placeholders and shows the parameter panel. See [Query Parameters](/features/query-parameters) | diff --git a/docs/customization/settings.mdx b/docs/customization/settings.mdx index b1e0b7271c..cdad509d32 100644 --- a/docs/customization/settings.mdx +++ b/docs/customization/settings.mdx @@ -12,7 +12,7 @@ The settings window is app-wide: a value on any of these eleven tabs holds for e Language, startup, tabs, sidebar, query timeout, updates, reset. - Appearance mode, themes, per-theme fonts and colors. + Appearance mode, themes and theme colors. SQL editor, Vim mode, line numbers, query parameters. Data grid, pagination, result cap, JSON viewer, and query history. Custom shortcuts. @@ -47,8 +47,7 @@ What a fresh install ships with, so one glance down this column says what you ch | Appearance | Appearance | Auto | | Appearance | Light theme | Default Light | | Appearance | Dark theme | Default Dark | -| Appearance | Editor font | System Mono, 13 pt | -| Appearance | Data grid font | System Mono, 13 pt | +| Editor | Editor font | System Mono, 13 pt | | Editor | Show line numbers | On | | Editor | Highlight current line | On | | Editor | Highlight current statement | On | diff --git a/docs/development/plugin-registry.mdx b/docs/development/plugin-registry.mdx index da9ef7a492..e848422167 100644 --- a/docs/development/plugin-registry.mdx +++ b/docs/development/plugin-registry.mdx @@ -140,9 +140,9 @@ The app fetches the manifest from `raw.githubusercontent.com/TableProApp/plugins Themes use the same manifest with `category: "theme"`. Four things differ from a driver: - Pure JSON data. No executable code, no code signing, no `.tableplugin` bundle -- The ZIP holds `.json` files, each a valid `ThemeDefinition`. Packs with several themes work +- The ZIP holds `.json` files, each a theme file in format `schema: 2`. Packs with several themes work - They install to `~/Library/Application Support/TablePro/Themes/Registry/` -- No `pluginKitVersion` is needed, and the flat v1 fields still decode +- No `pluginKitVersion` is needed. Set `minAppVersion` to the release that reads the format the theme is written in, because that is the only check an older TablePro runs before installing it ```json { diff --git a/docs/features/overview.mdx b/docs/features/overview.mdx index 185199f83e..415084957c 100644 --- a/docs/features/overview.mdx +++ b/docs/features/overview.mdx @@ -212,7 +212,7 @@ First time here: [Quick Start](/quickstart) gets you from install to a query wit Every tab, its controls, and their defaults. - Themes, fonts, colors, connection colors. + Themes, theme colors, connection colors. Editor toggles, Vim mode, indentation. diff --git a/docs/features/sql-editor.mdx b/docs/features/sql-editor.mdx index 7163fe9d78..8f1889fa6a 100644 --- a/docs/features/sql-editor.mdx +++ b/docs/features/sql-editor.mdx @@ -191,6 +191,6 @@ For the execution plan rather than an opinion, press `Cmd+Option+E` and see [Exp ## Editor settings -**Settings > Editor** holds line numbers, current-line and current-statement highlighting, word wrap, [code folding](/features/code-folding), the per-statement run button, [invisible characters](#invisible-characters), tab width, auto-uppercase keywords, [query parameters](/features/query-parameters), and [vim mode](/features/vim-mode). Editor font family and size are per theme, in **Settings > Appearance**. +**Settings > Editor** holds line numbers, current-line and current-statement highlighting, word wrap, [code folding](/features/code-folding), the per-statement run button, [invisible characters](#invisible-characters), tab width, auto-uppercase keywords, [query parameters](/features/query-parameters), and [vim mode](/features/vim-mode). Editor font family and size are on that same tab. -Editor windows remember their size, position and font zoom between launches. See [Query Tabs](/features/tabs#switching-tabs). +The font size set by `Cmd+=` and `Cmd+-` is the Editor Font setting, so it is kept between launches. See [Query Tabs](/features/tabs#switching-tabs). From 3b339f030a4f9e4740190878418ba2fd74feac64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 08:59:19 +0700 Subject: [PATCH 35/54] fix(plugin-clickhouse): keep binary values through export, object copy and compare (#2773) --- CHANGELOG.md | 2 + .../ClickHouseHTTPChunks.swift | 116 ++++++++++ .../ClickHousePlugin.swift | 213 +++++------------- .../ClickHouseTabSeparatedRowDecoder.swift | 79 +++++++ ...lickHouseTabSeparatedRowDecoderTests.swift | 183 +++++++++++++++ docs/databases/clickhouse.mdx | 2 +- project.yml | 1 + 7 files changed, 444 insertions(+), 152 deletions(-) create mode 100644 Plugins/ClickHouseDriverPlugin/ClickHouseHTTPChunks.swift create mode 100644 Plugins/TableProPluginKit/ClickHouseTabSeparatedRowDecoder.swift create mode 100644 TableProTests/Plugins/ClickHouseTabSeparatedRowDecoderTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index c0d5920e73..0e80091898 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -212,6 +212,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Garbled ClickHouse text whenever another value in the same result held binary data. - Carriage returns, quotes, NUL bytes and Enum type names shown with backslash escapes on ClickHouse. - Edits and deletes matching no row on ClickHouse tables with a binary value in the row. +- Binary ClickHouse values written as replacement characters by an export, an object copy and a compare. (#2725) +- ClickHouse export with a **Row limit** failing with a syntax error. (#2725) - Non-ASCII SQL Server filter values turned into `?` and matching the wrong rows on non-Unicode collations. - Empty structure, missing indexes and failed renames for non-ASCII SQL Server object names on non-Unicode collations. - Changing a defaulted SQL Server column failing when a name contains a quote or non-ASCII text. diff --git a/Plugins/ClickHouseDriverPlugin/ClickHouseHTTPChunks.swift b/Plugins/ClickHouseDriverPlugin/ClickHouseHTTPChunks.swift new file mode 100644 index 0000000000..db1d779973 --- /dev/null +++ b/Plugins/ClickHouseDriverPlugin/ClickHouseHTTPChunks.swift @@ -0,0 +1,116 @@ +import Foundation +import TableProPluginKit + +/// The response body of a streaming read, as the bytes the socket produced. +/// +/// `URLSession.AsyncBytes.lines` hands back a UTF-8 decoded `String`, which replaces every byte a +/// `String` column holds that is not valid UTF-8 before anything can look at it, and iterating the +/// same sequence a byte at a time costs an async suspension per byte: measured on a million-row +/// read, 7.6s for `lines` and 44s for the bytes under it. A per-task delegate hands over the `Data` +/// untouched and about 85 KB at a time, and the same read then costs 0.18s. It is a *task* delegate +/// rather than a session one so the driver keeps its own session, and with it the +/// `ClickHouseTLSDelegate` that answers the server trust challenge. +/// +/// One chunk is in flight at a time: the transfer is suspended as each chunk is handed over and +/// resumed once the reader has finished with it, so a slow writer downstream stops the download +/// rather than letting the rest of the result pile up in memory. That resume is why the body is +/// read through `forEachChunk` and not by iterating a sequence: a caller cannot forget it. +internal final class ClickHouseHTTPChunks: NSObject, URLSessionDataDelegate, @unchecked Sendable { + /// An error body is text the user reads, not a result, so it is held whole up to this and the + /// rest dropped. ClickHouse exception text runs to a few kilobytes at most. + private static let errorBodyByteCap = 65_536 + + private let stream: AsyncThrowingStream + private let continuation: AsyncThrowingStream.Continuation + private let lock = NSLock() + private var task: URLSessionDataTask? + private var isTransferSuspended = false + private var failureStatusCode: Int? + private var failureBody = Data() + + internal init(session: URLSession, request: URLRequest) { + (stream, continuation) = AsyncThrowingStream.makeStream() + super.init() + + let dataTask = session.dataTask(with: request) + dataTask.delegate = self + lock.withLock { task = dataTask } + continuation.onTermination = { _ in dataTask.cancel() } + dataTask.resume() + } + + /// The transfer is torn down on every way out, a thrown error and a cancellation included. A + /// reader that walks away leaves the task suspended mid-body with nothing left to resume it, so + /// without this the connection stays open until the driver disconnects. + internal func forEachChunk(_ body: (Data) async throws -> Void) async throws { + defer { endTransfer() } + for try await chunk in stream { + try await body(chunk) + resumeTransfer() + } + } + + internal func urlSession( + _ session: URLSession, + dataTask: URLSessionDataTask, + didReceive response: URLResponse, + completionHandler: @escaping (URLSession.ResponseDisposition) -> Void + ) { + if let statusCode = (response as? HTTPURLResponse)?.statusCode, statusCode >= 400 { + lock.withLock { failureStatusCode = statusCode } + } + completionHandler(.allow) + } + + internal func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) { + let isFailure = lock.withLock { () -> Bool in + guard failureStatusCode != nil else { return false } + let room = Self.errorBodyByteCap - failureBody.count + if room > 0 { failureBody.append(data.prefix(room)) } + return true + } + guard !isFailure else { return } + + continuation.yield(data) + let shouldSuspend = lock.withLock { () -> Bool in + guard !isTransferSuspended else { return false } + isTransferSuspended = true + return true + } + guard shouldSuspend else { return } + dataTask.suspend() + } + + internal func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { + let failure = lock.withLock { () -> Error? in + guard failureStatusCode != nil else { return error } + let body = String(decoding: failureBody, as: UTF8.self) // swiftlint:disable:this optional_data_string_conversion + return ClickHouseError(message: body.trimmingCharacters(in: .whitespacesAndNewlines)) + } + guard let failure else { + continuation.finish() + return + } + continuation.finish(throwing: failure) + } + + private func resumeTransfer() { + let suspended = lock.withLock { () -> URLSessionDataTask? in + guard isTransferSuspended else { return nil } + isTransferSuspended = false + return task + } + suspended?.resume() + } + + private func endTransfer() { + let outstanding = lock.withLock { () -> URLSessionDataTask? in + let current = task + task = nil + isTransferSuspended = false + return current + } + outstanding?.cancel() + continuation.finish() + } +} diff --git a/Plugins/ClickHouseDriverPlugin/ClickHousePlugin.swift b/Plugins/ClickHouseDriverPlugin/ClickHousePlugin.swift index 7b50dd3864..5a7b02ec87 100644 --- a/Plugins/ClickHouseDriverPlugin/ClickHousePlugin.swift +++ b/Plugins/ClickHouseDriverPlugin/ClickHousePlugin.swift @@ -495,8 +495,9 @@ final class ClickHousePluginDriver: PluginDatabaseDriver, @unchecked Sendable { // MARK: - Streaming - /// A bounded read is one HTTP request. The unbounded `streamRows` path still pays a separate - /// `LIMIT 0` probe to learn its columns, so it is deliberately not reused here. + /// A bounded read is one HTTP request, and so is the unbounded `streamRows` path: the format + /// both ask for names its columns, so neither pays a `LIMIT 0` probe to learn them. That probe + /// appended to the statement, which a query already carrying a `LIMIT` rejects outright. func executeBoundedQuery(query: String, rowCap: Int) async throws -> PluginQueryResult? { let started = Date() let stream = PluginRowStream.make { continuation, abort in @@ -526,87 +527,70 @@ final class ClickHousePluginDriver: PluginDatabaseDriver, @unchecked Sendable { return (session, _currentDatabase) } - var trimmedQuery = query.trimmingCharacters(in: .whitespacesAndNewlines) - while trimmedQuery.hasSuffix(";") { - trimmedQuery = String(trimmedQuery.dropLast()).trimmingCharacters(in: .whitespacesAndNewlines) - } - - let request = try buildStreamRequest(query: trimmedQuery, database: database, rowCap: rowCap) - let (bytes, response) = try await session.bytes(for: request) - - if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode >= 400 { - var body = "" - for try await line in bytes.lines { - body += line - } - throw ClickHouseError(message: body.trimmingCharacters(in: .whitespacesAndNewlines)) - } + let request = try buildStreamRequest( + query: Self.withoutTrailingSemicolons(query), + database: database, + rowCap: rowCap + ) + try await streamTabSeparatedRows( + request: request, + session: session, + batchSize: min(5_000, rowCap + 1), + continuation: continuation + ) + } - /// JSONCompactEachRowWithNamesAndTypes puts the names on line one and the types on line - /// two, both as positional arrays, so the columns arrive without a second round trip and - /// survive a zero-row result. - var columns: [String] = [] - var columnTypeNames: [String] = [] + /// `TabSeparatedWithNamesAndTypes` carries the names on line one and the types on line two, so + /// the columns arrive with the rows and survive a result holding none. It is the format the + /// non-streaming read asks for too, which is what keeps an exported value and the same value in + /// the grid the same text, and unlike a JSON string it can carry a byte no encoding covers. + private func streamTabSeparatedRows( + request: URLRequest, + session: URLSession, + batchSize: Int, + continuation: AsyncThrowingStream.Continuation + ) async throws { + var decoder = ClickHouseTabSeparatedRowDecoder() var headerSent = false - let batchSize = min(5_000, rowCap + 1) var batch: [PluginRow] = [] batch.reserveCapacity(batchSize) - for try await line in bytes.lines { - try Task.checkCancellation() - - let trimmedLine = line.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmedLine.isEmpty { continue } - guard let lineData = trimmedLine.data(using: .utf8) else { continue } - - if columns.isEmpty { - columns = (try? JSONSerialization.jsonObject(with: lineData) as? [String]) ?? [] - continue - } - if columnTypeNames.isEmpty { - columnTypeNames = (try? JSONSerialization.jsonObject(with: lineData) as? [String]) ?? [] - continuation.yield(.header(PluginStreamHeader( - columns: columns, - columnTypeNames: columnTypeNames, - estimatedRowCount: nil - ))) - headerSent = true - continue - } - - guard let values = try? JSONSerialization.jsonObject(with: lineData) as? [Any] else { continue } - var row: [PluginCellValue] = [] - row.reserveCapacity(columns.count) - for index in columns.indices { - let value: Any? = index < values.count ? values[index] : nil - row.append(Self.boundedCellValue(value)) - } - batch.append(row) - if batch.count >= batchSize { - continuation.yield(.rows(batch)) - batch.removeAll(keepingCapacity: true) - } - } - - if !headerSent { + func sendHeader(_ header: ClickHouseTabSeparatedRowDecoder.Header) { + guard !headerSent else { return } + headerSent = true continuation.yield(.header(PluginStreamHeader( - columns: columns, - columnTypeNames: columnTypeNames, + columns: header.columns, + columnTypeNames: header.columnTypeNames, estimatedRowCount: nil ))) } + + try await ClickHouseHTTPChunks(session: session, request: request).forEachChunk { chunk in + try Task.checkCancellation() + let rows = decoder.consume(chunk) + if let header = decoder.header { + sendHeader(header) + } + batch.append(contentsOf: rows) + guard batch.count >= batchSize else { return } + continuation.yield(.rows(batch)) + batch.removeAll(keepingCapacity: true) + } + + batch.append(contentsOf: decoder.finish()) + sendHeader(decoder.header ?? ClickHouseTabSeparatedRowDecoder.Header(columns: [], columnTypeNames: [])) if !batch.isEmpty { continuation.yield(.rows(batch)) } continuation.finish() } - private static func boundedCellValue(_ value: Any?) -> PluginCellValue { - guard let value, !(value is NSNull) else { return .null } - if let str = value as? String { return .text(str) } - if let num = value as? NSNumber { return .text(NumberText.text(for: num)) } - if let jsonStr = NumberText.json(from: value, sortedKeys: false) { return .text(jsonStr) } - return .text(String(describing: value)) + private static func withoutTrailingSemicolons(_ query: String) -> String { + var trimmed = query.trimmingCharacters(in: .whitespacesAndNewlines) + while trimmed.hasSuffix(";") { + trimmed = String(trimmed.dropLast()).trimmingCharacters(in: .whitespacesAndNewlines) + } + return trimmed } func streamRows(query: String) -> AsyncThrowingStream { @@ -633,87 +617,13 @@ final class ClickHousePluginDriver: PluginDatabaseDriver, @unchecked Sendable { return (session, _currentDatabase) } - var trimmedQuery = query.trimmingCharacters(in: .whitespacesAndNewlines) - while trimmedQuery.hasSuffix(";") { - trimmedQuery = String(trimmedQuery.dropLast()).trimmingCharacters(in: .whitespacesAndNewlines) - } - - let headerResult = try await executeRaw("\(trimmedQuery) LIMIT 0") - continuation.yield(.header(PluginStreamHeader( - columns: headerResult.columns, - columnTypeNames: headerResult.columnTypeNames, - estimatedRowCount: nil - ))) - - let columnOrder = headerResult.columns - - guard !columnOrder.isEmpty else { - continuation.finish() - return - } - - let streamRequest = try buildStreamRequest( - query: trimmedQuery, database: database + let request = try buildStreamRequest(query: Self.withoutTrailingSemicolons(query), database: database) + try await streamTabSeparatedRows( + request: request, + session: session, + batchSize: 5_000, + continuation: continuation ) - - let (bytes, response) = try await session.bytes(for: streamRequest) - - if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode >= 400 { - var body = "" - for try await line in bytes.lines { - body += line - } - throw ClickHouseError(message: body.trimmingCharacters(in: .whitespacesAndNewlines)) - } - - let batchSize = 5_000 - var batch: [PluginRow] = [] - batch.reserveCapacity(batchSize) - - for try await line in bytes.lines { - try Task.checkCancellation() - - let trimmedLine = line.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmedLine.isEmpty { continue } - - guard let lineData = trimmedLine.data(using: .utf8), - let json = try? JSONSerialization.jsonObject(with: lineData) as? [String: Any] else { - continue - } - - var row: [PluginCellValue] = [] - for colName in columnOrder { - if let value = json[colName] { - if value is NSNull { - row.append(.null) - } else if let str = value as? String { - row.append(.text(str)) - } else if let num = value as? NSNumber { - row.append(.text(NumberText.text(for: num))) - } else { - if let jsonStr = NumberText.json(from: value, sortedKeys: false) { - row.append(.text(jsonStr)) - } else { - row.append(.text(String(describing: value))) - } - } - } else { - row.append(.null) - } - } - - batch.append(row) - if batch.count >= batchSize { - continuation.yield(.rows(batch)) - batch.removeAll(keepingCapacity: true) - } - } - - if !batch.isEmpty { - continuation.yield(.rows(batch)) - } - - continuation.finish() } private func buildStreamRequest(query: String, database: String, rowCap: Int? = nil) throws -> URLRequest { @@ -729,15 +639,16 @@ final class ClickHousePluginDriver: PluginDatabaseDriver, @unchecked Sendable { if !database.isEmpty { queryItems.append(URLQueryItem(name: "database", value: database)) } + queryItems.append(URLQueryItem( + name: "default_format", + value: ClickHouseResponseClassifier.requestedFormat + )) if let rowCap { /// The bound rides as an HTTP setting so the SQL in the body stays exactly what the /// user wrote. One row past the cap, so a full page can be told from a truncated one. - queryItems.append(URLQueryItem(name: "default_format", value: "JSONCompactEachRowWithNamesAndTypes")) queryItems.append(URLQueryItem(name: "max_result_rows", value: String(rowCap + 1))) queryItems.append(URLQueryItem(name: "result_overflow_mode", value: "break")) queryItems.append(URLQueryItem(name: "cancel_http_readonly_queries_on_client_close", value: "1")) - } else { - queryItems.append(URLQueryItem(name: "default_format", value: "JSONEachRow")) } components.queryItems = queryItems diff --git a/Plugins/TableProPluginKit/ClickHouseTabSeparatedRowDecoder.swift b/Plugins/TableProPluginKit/ClickHouseTabSeparatedRowDecoder.swift new file mode 100644 index 0000000000..66af57f23a --- /dev/null +++ b/Plugins/TableProPluginKit/ClickHouseTabSeparatedRowDecoder.swift @@ -0,0 +1,79 @@ +import Foundation + +/// The streaming half of `ClickHouseResponseClassifier`, for the reads that hand rows back as they +/// arrive and so can never hold the whole response. A chunk boundary falls wherever the network +/// put it, so the bytes it cut in half are kept until the line they belong to is whole: a field is +/// offered to a text decode only once nothing more can be appended to it. +/// +/// A value that is not valid UTF-8 stays `.bytes`, decided per value rather than per column the +/// way `classify` decides it. Demoting a column means rewriting the rows already handed over, and +/// a stream has no way back to them. +public struct ClickHouseTabSeparatedRowDecoder: Sendable { + public struct Header: Equatable, Sendable { + public let columns: [String] + public let columnTypeNames: [String] + + public init(columns: [String], columnTypeNames: [String]) { + self.columns = columns + self.columnTypeNames = columnTypeNames + } + } + + public private(set) var header: Header? + + private var pendingBytes: [UInt8] = [] + private var columnNames: [String]? + + public init() {} + + public mutating func consume(_ data: Data) -> [[PluginCellValue]] { + guard !data.isEmpty else { return [] } + + var buffer = pendingBytes + pendingBytes = [] + buffer.append(contentsOf: data) + + var rows: [[PluginCellValue]] = [] + var lineStart = 0 + for index in buffer.indices where buffer[index] == ClickHouseTabSeparatedBytes.lineSeparator { + if let row = ingest(buffer[lineStart.. [[PluginCellValue]] { + let buffer = pendingBytes + pendingBytes = [] + guard !buffer.isEmpty, let row = ingest(buffer[...]) else { return [] } + return [row] + } + + private mutating func ingest(_ line: ArraySlice) -> [PluginCellValue]? { + guard let columnNames else { + self.columnNames = ClickHouseTabSeparatedBytes.fields(line).map(ClickHouseTabSeparatedBytes.headerText) + return nil + } + guard header != nil else { + header = Header( + columns: columnNames, + columnTypeNames: ClickHouseTabSeparatedBytes.fields(line).map(ClickHouseTabSeparatedBytes.headerText) + ) + return nil + } + guard !line.isEmpty else { return nil } + return ClickHouseTabSeparatedBytes.fields(line).map(Self.cellValue) + } + + private static func cellValue(_ field: ArraySlice) -> PluginCellValue { + guard !ClickHouseTabSeparatedBytes.isNullMarker(field) else { return .null } + let value = ClickHouseTabSeparatedBytes.unescape(field) + guard let text = String(bytes: value, encoding: .utf8) else { return .bytes(Data(value)) } + return .text(text) + } +} diff --git a/TableProTests/Plugins/ClickHouseTabSeparatedRowDecoderTests.swift b/TableProTests/Plugins/ClickHouseTabSeparatedRowDecoderTests.swift new file mode 100644 index 0000000000..e911b7024f --- /dev/null +++ b/TableProTests/Plugins/ClickHouseTabSeparatedRowDecoderTests.swift @@ -0,0 +1,183 @@ +// +// ClickHouseTabSeparatedRowDecoderTests.swift +// TableProTests +// + +import Foundation +import TableProPluginKit +import Testing + +@Suite("ClickHouse Tab Separated Row Decoder") +struct ClickHouseTabSeparatedRowDecoderTests { + private struct Decoded { + let header: ClickHouseTabSeparatedRowDecoder.Header? + let rows: [[PluginCellValue]] + } + + private static let header = Data("id\tlabel\tpayload\nUInt32\tString\tString\n".utf8) + + private func decodeAll(_ chunks: [Data]) -> Decoded { + var decoder = ClickHouseTabSeparatedRowDecoder() + var rows: [[PluginCellValue]] = [] + for chunk in chunks { + rows.append(contentsOf: decoder.consume(chunk)) + } + rows.append(contentsOf: decoder.finish()) + return Decoded(header: decoder.header, rows: rows) + } + + private func decodeAll(_ body: Data) -> Decoded { + decodeAll([body]) + } + + private func bytewise(_ body: Data) -> [[PluginCellValue]] { + decodeAll(body.map { Data([$0]) }).rows + } + + // MARK: - Header + + @Test("The first two lines are the column names and the column types") + func readsNamesAndTypes() { + let outcome = decodeAll(Self.header) + #expect(outcome.header?.columns == ["id", "label", "payload"]) + #expect(outcome.header?.columnTypeNames == ["UInt32", "String", "String"]) + #expect(outcome.rows.isEmpty) + } + + @Test("A body holding nothing reports no header") + func emptyBodyHasNoHeader() { + let outcome = decodeAll(Data()) + #expect(outcome.header == nil) + #expect(outcome.rows.isEmpty) + } + + @Test("A name that is not valid UTF-8 keeps the column rather than dropping it") + func headerReplacesUndecodableBytes() { + var body = Data("id\t".utf8) + body.append(contentsOf: [0xDE, 0xAD]) + body.append(contentsOf: Data("\nUInt32\tString\n".utf8)) + let outcome = decodeAll(body) + #expect(outcome.header?.columns.count == 2) + #expect(outcome.header?.columns.first == "id") + } + + // MARK: - Values + + @Test("A field that decodes as UTF-8 is text") + func decodesTextValues() { + var body = Self.header + body.append(contentsOf: Data("1\tünïcødé\thello\n".utf8)) + let outcome = decodeAll(body) + #expect(outcome.rows == [[.text("1"), .text("ünïcødé"), .text("hello")]]) + } + + @Test("A field that is not valid UTF-8 keeps its exact bytes") + func keepsUndecodableBytes() { + var body = Self.header + body.append(contentsOf: Data("1\tplain\t".utf8)) + body.append(contentsOf: [0xDE, 0xAD, 0xBE, 0xEF]) + body.append(contentsOf: Data("\n".utf8)) + let outcome = decodeAll(body) + #expect(outcome.rows.count == 1) + #expect(outcome.rows[0][2] == .bytes(Data([0xDE, 0xAD, 0xBE, 0xEF]))) + } + + @Test("A binary value in one row leaves a text value in the same column as text") + func decidesPerValueRatherThanPerColumn() { + var body = Self.header + body.append(contentsOf: Data("1\ta\t".utf8)) + body.append(contentsOf: [0xDE, 0xAD, 0xBE, 0xEF]) + body.append(contentsOf: Data("\n2\tb\thello world\n".utf8)) + let outcome = decodeAll(body) + #expect(outcome.rows.count == 2) + #expect(outcome.rows[0][2] == .bytes(Data([0xDE, 0xAD, 0xBE, 0xEF]))) + #expect(outcome.rows[1][2] == .text("hello world")) + } + + @Test("A lone backslash-N field is null") + func readsNullMarker() { + var body = Self.header + body.append(contentsOf: Data("1\t\\N\tvalue\n".utf8)) + let outcome = decodeAll(body) + #expect(outcome.rows == [[.text("1"), .null, .text("value")]]) + } + + @Test("An escaped backslash before N is the literal text, not null") + func escapedBackslashIsNotNull() { + var body = Self.header + body.append(contentsOf: Data("1\t\\\\N\tvalue\n".utf8)) + let outcome = decodeAll(body) + #expect(outcome.rows == [[.text("1"), .text("\\N"), .text("value")]]) + } + + @Test("Every escape ClickHouse writes comes back as its byte") + func unescapesEveryEscape() { + var body = Self.header + body.append(contentsOf: Data("1\ta\\tb\\nc\\rd\\0e\\be\\fg\\'h\\\\i\tvalue\n".utf8)) + let outcome = decodeAll(body) + let expected = "a\tb\nc\rd\u{0}e\u{8}e\u{C}g'h\\i" + #expect(outcome.rows.count == 1) + #expect(outcome.rows[0][1] == .text(expected)) + } + + @Test("Array, Map and Tuple arrive as the text ClickHouse writes for them") + func keepsCompoundValuesAsWritten() { + var body = Data("tags\tattrs\tpair\nArray(String)\tMap(String, String)\tTuple(UInt8, String)\n".utf8) + body.append(contentsOf: Data("['a','b']\t{'k':'v'}\t(7,'x')\n".utf8)) + let outcome = decodeAll(body) + #expect(outcome.rows == [[.text("['a','b']"), .text("{'k':'v'}"), .text("(7,'x')")]]) + } + + // MARK: - Chunk boundaries + + @Test("A row split across two chunks decodes once it is whole") + func joinsRowsAcrossChunks() { + var first = Self.header + first.append(contentsOf: Data("1\tlab".utf8)) + let second = Data("el\tvalue\n".utf8) + let outcome = decodeAll([first, second]) + #expect(outcome.rows == [[.text("1"), .text("label"), .text("value")]]) + } + + @Test("A chunk that cuts a multi-byte character in half does not corrupt it") + func joinsMultiByteCharactersAcrossChunks() { + var body = Self.header + body.append(contentsOf: Data("1\tünïcødé\tvalue\n".utf8)) + #expect(bytewise(body) == [[.text("1"), .text("ünïcødé"), .text("value")]]) + } + + @Test("Feeding one byte at a time gives the same rows as one chunk") + func chunkingDoesNotChangeTheResult() { + var body = Self.header + body.append(contentsOf: Data("1\ta\t".utf8)) + body.append(contentsOf: [0xDE, 0xAD, 0xBE, 0xEF]) + body.append(contentsOf: Data("\n2\tb\thello\n3\t\\N\t\\t\n".utf8)) + #expect(bytewise(body) == decodeAll(body).rows) + } + + // MARK: - Body edges + + @Test("A body that ends without its closing newline still yields its last row") + func yieldsUnterminatedFinalRow() { + var body = Self.header + body.append(contentsOf: Data("1\tlabel\tvalue".utf8)) + let outcome = decodeAll(body) + #expect(outcome.rows == [[.text("1"), .text("label"), .text("value")]]) + } + + @Test("A blank line between rows is not a row") + func skipsBlankLines() { + var body = Self.header + body.append(contentsOf: Data("1\ta\tb\n\n2\tc\td\n".utf8)) + let outcome = decodeAll(body) + #expect(outcome.rows.count == 2) + } + + @Test("A field holding nothing is empty text, never null") + func emptyFieldIsEmptyText() { + var body = Self.header + body.append(contentsOf: Data("1\t\tvalue\n".utf8)) + let outcome = decodeAll(body) + #expect(outcome.rows == [[.text("1"), .text(""), .text("value")]]) + } +} diff --git a/docs/databases/clickhouse.mdx b/docs/databases/clickhouse.mdx index 389e4b1706..3d8bb546b3 100644 --- a/docs/databases/clickhouse.mdx +++ b/docs/databases/clickhouse.mdx @@ -86,7 +86,7 @@ The CA file may be PEM or DER. If **Verify CA** cannot read it, the connection f - No auto-increment, and the primary key and sorting key are fixed at creation. Structure editing covers adding, modifying, and dropping columns and data-skipping indexes; recreate the table for anything else. - A `SET` does not carry to the next statement. Every statement is its own HTTP request with no session id, and the setting is gone by the next one. Put it in a `SETTINGS` clause on the query itself. - A query with its own `FORMAT` clause, such as `SELECT 1 FORMAT JSON`, shows the server's raw output in one column instead of a parsed table. Drop the clause to get a grid. -- A column with even one value that is not valid UTF-8 shows every row as hex, and its cells do not open for inline editing. `String` and `FixedString` hold raw bytes, so a hash or a stray byte is enough. Select `toValidUTF8(column)` to read it as text, with the bad bytes replaced. +- A column with even one value that is not valid UTF-8 shows every row as hex in the grid, and its cells do not open for inline editing. `String` and `FixedString` hold raw bytes, so a hash or a stray byte is enough. An export, an object copy and a data compare judge each value on its own, so a row holding text stays text there. Select `toValidUTF8(column)` to read it as text, with the bad bytes replaced. ## Troubleshooting diff --git a/project.yml b/project.yml index 668b9820c7..eeeb04ce26 100644 --- a/project.yml +++ b/project.yml @@ -403,6 +403,7 @@ targets: - Plugins/ClickHouseDriverPlugin/ClickHouseCapabilities.swift - Plugins/ClickHouseDriverPlugin/ClickHouseCredentials.swift - Plugins/ClickHouseDriverPlugin/ClickHouseGeneratedColumnClassification.swift + - Plugins/ClickHouseDriverPlugin/ClickHouseHTTPChunks.swift - Plugins/ClickHouseDriverPlugin/ClickHouseParameterBinding.swift - Plugins/ClickHouseDriverPlugin/ClickHousePlugin.swift - Plugins/ClickHouseDriverPlugin/ClickHousePluginDriver+Http.swift From 66e56b3097f964621166df511bb117bf42ca7b04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 09:21:27 +0700 Subject: [PATCH 36/54] fix(plugin-postgresql): write table and column comments into SQL exports (#2726) (#2774) --- CHANGELOG.md | 1 + Plugins/BeancountDriverPlugin/Info.plist | 2 +- Plugins/BigQueryDriverPlugin/Info.plist | 2 +- Plugins/CSVExportPlugin/Info.plist | 2 +- Plugins/CSVImportPlugin/Info.plist | 2 +- Plugins/CassandraDriverPlugin/Info.plist | 2 +- Plugins/ClickHouseDriverPlugin/Info.plist | 2 +- Plugins/CloudflareD1DriverPlugin/Info.plist | 2 +- .../CloudflareR2SQLDriverPlugin/Info.plist | 2 +- Plugins/DamengDriverPlugin/Info.plist | 2 +- Plugins/DuckDBDriverPlugin/Info.plist | 2 +- Plugins/DynamoDBDriverPlugin/Info.plist | 2 +- Plugins/ElasticsearchDriverPlugin/Info.plist | 2 +- Plugins/EtcdDriverPlugin/Info.plist | 2 +- Plugins/HTMLExportPlugin/Info.plist | 2 +- Plugins/JSONExportPlugin/Info.plist | 2 +- Plugins/JSONImportPlugin/Info.plist | 2 +- Plugins/KafkaDriverPlugin/Info.plist | 2 +- Plugins/LibSQLDriverPlugin/Info.plist | 2 +- Plugins/MQLExportPlugin/Info.plist | 2 +- Plugins/MSSQLDriverPlugin/Info.plist | 2 +- Plugins/MarkdownExportPlugin/Info.plist | 2 +- Plugins/MongoDBDriverPlugin/Info.plist | 2 +- Plugins/MySQLDriverPlugin/Info.plist | 2 +- Plugins/OracleDriverPlugin/Info.plist | 2 +- Plugins/ParquetExportPlugin/Info.plist | 2 +- Plugins/PostgreSQLDriverPlugin/Info.plist | 2 +- .../PostgreSQLCommentStatements.swift | 79 ++++++ .../PostgreSQLPluginDriver+Comments.swift | 25 ++ .../PostgreSQLRelationSQL.swift | 17 ++ Plugins/RedisDriverPlugin/Info.plist | 2 +- Plugins/SQLExportPlugin/Info.plist | 2 +- Plugins/SQLExportPlugin/SQLExportPlugin.swift | 56 +++++ Plugins/SQLImportPlugin/Info.plist | 2 +- Plugins/SQLiteDriverPlugin/Info.plist | 2 +- Plugins/SnowflakeDriverPlugin/Info.plist | 2 +- Plugins/SpannerDriverPlugin/Info.plist | 2 +- Plugins/SurrealDBDriverPlugin/Info.plist | 2 +- .../PluginDatabaseDriver.swift | 18 ++ .../PluginExportDataSource.swift | 7 + Plugins/TeradataDriverPlugin/Info.plist | 2 +- Plugins/TrinoDriverPlugin/Info.plist | 2 +- Plugins/TypesenseDriverPlugin/Info.plist | 2 +- Plugins/XLSXExportPlugin/Info.plist | 2 +- Plugins/XLSXImportPlugin/Info.plist | 2 +- Plugins/XMLExportPlugin/Info.plist | 2 +- TablePro/Core/Database/DatabaseDriver.swift | 6 + TablePro/Core/Database/TableDDLComposer.swift | 47 +++- .../Plugins/ExportDataSourceAdapter.swift | 5 + .../Core/Plugins/PluginDriverAdapter.swift | 4 + TablePro/Core/Plugins/PluginManager.swift | 12 +- .../Core/Database/TableDDLComposerTests.swift | 79 ++++++ .../Plugins/PluginKitABIResilienceTests.swift | 2 + .../PostgreSQLCommentStatementsTests.swift | 164 +++++++++++++ .../Plugins/SQLExportCommentPhaseTests.swift | 229 ++++++++++++++++++ docs/databases/postgresql.mdx | 2 + docs/development/plugin-development.mdx | 2 +- docs/development/plugin-registry.mdx | 4 +- docs/features/import-export.mdx | 2 + docs/features/table-structure.mdx | 2 +- project.yml | 1 + 61 files changed, 784 insertions(+), 58 deletions(-) create mode 100644 Plugins/PostgreSQLDriverPlugin/PostgreSQLCommentStatements.swift create mode 100644 Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Comments.swift create mode 100644 TableProTests/Core/Database/TableDDLComposerTests.swift create mode 100644 TableProTests/Plugins/PostgreSQLCommentStatementsTests.swift create mode 100644 TableProTests/Plugins/SQLExportCommentPhaseTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e80091898..e4227ba39a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -98,6 +98,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Default PostgreSQL schema taken from the schema list rather than the search path. - Safe Mode minimum from a configuration profile missing from the toolbar, the Database menu and the connection form. (#2030) - PostgreSQL connection hanging after running `COPY FROM STDIN` or `COPY TO STDOUT` in the query editor and on iOS. +- Table, view and column comments missing from a PostgreSQL SQL export. (#2726) - Stop not ending queries on MySQL and MariaDB servers without TLS. - Wrong results after MySQL retakes a dropped connection, on a session that had set a variable, a session setting or a database. - Session state set by the `/*! ... */` statements a MySQL dump writes counting as a comment. diff --git a/Plugins/BeancountDriverPlugin/Info.plist b/Plugins/BeancountDriverPlugin/Info.plist index f2092a8740..b5df38bac7 100644 --- a/Plugins/BeancountDriverPlugin/Info.plist +++ b/Plugins/BeancountDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesDatabaseTypeIds Beancount diff --git a/Plugins/BigQueryDriverPlugin/Info.plist b/Plugins/BigQueryDriverPlugin/Info.plist index 832b49a1ce..146cf11acb 100644 --- a/Plugins/BigQueryDriverPlugin/Info.plist +++ b/Plugins/BigQueryDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 27 + 28 diff --git a/Plugins/CSVExportPlugin/Info.plist b/Plugins/CSVExportPlugin/Info.plist index f3fd1d096d..2d117f1940 100644 --- a/Plugins/CSVExportPlugin/Info.plist +++ b/Plugins/CSVExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesExportFormatIds csv diff --git a/Plugins/CSVImportPlugin/Info.plist b/Plugins/CSVImportPlugin/Info.plist index 3193aefa9f..842846c821 100644 --- a/Plugins/CSVImportPlugin/Info.plist +++ b/Plugins/CSVImportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesImportFormatIds csv diff --git a/Plugins/CassandraDriverPlugin/Info.plist b/Plugins/CassandraDriverPlugin/Info.plist index 2401c48616..76638da801 100644 --- a/Plugins/CassandraDriverPlugin/Info.plist +++ b/Plugins/CassandraDriverPlugin/Info.plist @@ -21,6 +21,6 @@ NSPrincipalClass $(PRODUCT_MODULE_NAME).CassandraPlugin TableProPluginKitVersion - 27 + 28 diff --git a/Plugins/ClickHouseDriverPlugin/Info.plist b/Plugins/ClickHouseDriverPlugin/Info.plist index 8ce272816c..7801e3f0f1 100644 --- a/Plugins/ClickHouseDriverPlugin/Info.plist +++ b/Plugins/ClickHouseDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesDatabaseTypeIds ClickHouse diff --git a/Plugins/CloudflareD1DriverPlugin/Info.plist b/Plugins/CloudflareD1DriverPlugin/Info.plist index 832b49a1ce..146cf11acb 100644 --- a/Plugins/CloudflareD1DriverPlugin/Info.plist +++ b/Plugins/CloudflareD1DriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 27 + 28 diff --git a/Plugins/CloudflareR2SQLDriverPlugin/Info.plist b/Plugins/CloudflareR2SQLDriverPlugin/Info.plist index b46ca19179..3db72c176e 100644 --- a/Plugins/CloudflareR2SQLDriverPlugin/Info.plist +++ b/Plugins/CloudflareR2SQLDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesDatabaseTypeIds Cloudflare R2 SQL diff --git a/Plugins/DamengDriverPlugin/Info.plist b/Plugins/DamengDriverPlugin/Info.plist index 492ba91715..2e197ca2fd 100644 --- a/Plugins/DamengDriverPlugin/Info.plist +++ b/Plugins/DamengDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesDatabaseTypeIds Dameng diff --git a/Plugins/DuckDBDriverPlugin/Info.plist b/Plugins/DuckDBDriverPlugin/Info.plist index fd30d5aac1..ab35b0b9e7 100644 --- a/Plugins/DuckDBDriverPlugin/Info.plist +++ b/Plugins/DuckDBDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 27 + 28 diff --git a/Plugins/DynamoDBDriverPlugin/Info.plist b/Plugins/DynamoDBDriverPlugin/Info.plist index 832b49a1ce..146cf11acb 100644 --- a/Plugins/DynamoDBDriverPlugin/Info.plist +++ b/Plugins/DynamoDBDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 27 + 28 diff --git a/Plugins/ElasticsearchDriverPlugin/Info.plist b/Plugins/ElasticsearchDriverPlugin/Info.plist index 31731eb0ce..0c66dd9a1f 100644 --- a/Plugins/ElasticsearchDriverPlugin/Info.plist +++ b/Plugins/ElasticsearchDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.53.0 TableProPluginKitVersion - 27 + 28 diff --git a/Plugins/EtcdDriverPlugin/Info.plist b/Plugins/EtcdDriverPlugin/Info.plist index 832b49a1ce..146cf11acb 100644 --- a/Plugins/EtcdDriverPlugin/Info.plist +++ b/Plugins/EtcdDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 27 + 28 diff --git a/Plugins/HTMLExportPlugin/Info.plist b/Plugins/HTMLExportPlugin/Info.plist index 66625c5083..19bf6bc094 100644 --- a/Plugins/HTMLExportPlugin/Info.plist +++ b/Plugins/HTMLExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesExportFormatIds html diff --git a/Plugins/JSONExportPlugin/Info.plist b/Plugins/JSONExportPlugin/Info.plist index 614d123511..eb95d411c9 100644 --- a/Plugins/JSONExportPlugin/Info.plist +++ b/Plugins/JSONExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesExportFormatIds json diff --git a/Plugins/JSONImportPlugin/Info.plist b/Plugins/JSONImportPlugin/Info.plist index 5077345493..8abf91183c 100644 --- a/Plugins/JSONImportPlugin/Info.plist +++ b/Plugins/JSONImportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesImportFormatIds json diff --git a/Plugins/KafkaDriverPlugin/Info.plist b/Plugins/KafkaDriverPlugin/Info.plist index 79f552256f..2af849aadd 100644 --- a/Plugins/KafkaDriverPlugin/Info.plist +++ b/Plugins/KafkaDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesDatabaseTypeIds Kafka diff --git a/Plugins/LibSQLDriverPlugin/Info.plist b/Plugins/LibSQLDriverPlugin/Info.plist index 832b49a1ce..146cf11acb 100644 --- a/Plugins/LibSQLDriverPlugin/Info.plist +++ b/Plugins/LibSQLDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 27 + 28 diff --git a/Plugins/MQLExportPlugin/Info.plist b/Plugins/MQLExportPlugin/Info.plist index c5d88098f7..25bbaf509b 100644 --- a/Plugins/MQLExportPlugin/Info.plist +++ b/Plugins/MQLExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesExportFormatIds mql diff --git a/Plugins/MSSQLDriverPlugin/Info.plist b/Plugins/MSSQLDriverPlugin/Info.plist index fd30d5aac1..ab35b0b9e7 100644 --- a/Plugins/MSSQLDriverPlugin/Info.plist +++ b/Plugins/MSSQLDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 27 + 28 diff --git a/Plugins/MarkdownExportPlugin/Info.plist b/Plugins/MarkdownExportPlugin/Info.plist index 11dd85dc4b..f3419755a8 100644 --- a/Plugins/MarkdownExportPlugin/Info.plist +++ b/Plugins/MarkdownExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesExportFormatIds md diff --git a/Plugins/MongoDBDriverPlugin/Info.plist b/Plugins/MongoDBDriverPlugin/Info.plist index fd30d5aac1..ab35b0b9e7 100644 --- a/Plugins/MongoDBDriverPlugin/Info.plist +++ b/Plugins/MongoDBDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 27 + 28 diff --git a/Plugins/MySQLDriverPlugin/Info.plist b/Plugins/MySQLDriverPlugin/Info.plist index 1ed41cbaf3..df293ea509 100644 --- a/Plugins/MySQLDriverPlugin/Info.plist +++ b/Plugins/MySQLDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesDatabaseTypeIds MySQL diff --git a/Plugins/OracleDriverPlugin/Info.plist b/Plugins/OracleDriverPlugin/Info.plist index fd30d5aac1..ab35b0b9e7 100644 --- a/Plugins/OracleDriverPlugin/Info.plist +++ b/Plugins/OracleDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 27 + 28 diff --git a/Plugins/ParquetExportPlugin/Info.plist b/Plugins/ParquetExportPlugin/Info.plist index 1ae4446c1a..d102922e6b 100644 --- a/Plugins/ParquetExportPlugin/Info.plist +++ b/Plugins/ParquetExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesExportFormatIds parquet diff --git a/Plugins/PostgreSQLDriverPlugin/Info.plist b/Plugins/PostgreSQLDriverPlugin/Info.plist index fd4040f800..dd32fb8a25 100644 --- a/Plugins/PostgreSQLDriverPlugin/Info.plist +++ b/Plugins/PostgreSQLDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesDatabaseTypeIds PostgreSQL diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLCommentStatements.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLCommentStatements.swift new file mode 100644 index 0000000000..ad26d20e43 --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLCommentStatements.swift @@ -0,0 +1,79 @@ +// +// PostgreSQLCommentStatements.swift +// PostgreSQLDriverPlugin +// +// The COMMENT statements that reattach one relation's comment and its column comments. Pure, so it +// is testable without a server. +// + +import Foundation + +public enum PostgreSQLCommentStatements { + /// The relation's own comment first, then one row per commented column in `attnum` order, which + /// is the order `pg_dump` writes them in. + /// + /// `relkind` rides on every row, the column rows included, because it is what decides the + /// keyword `COMMENT ON` takes and a relation with no comment of its own still has columns to + /// write. A row with no description is filtered out here rather than rendered as `IS NULL`, which + /// would erase a comment instead of restoring one. + public static func catalogQuery(name: String, schema: String) -> String { + let nameLiteral = PostgreSQLObjectQueries.quoteLiteral(name) + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(schema) + return """ + SELECT relkind, attname, description + FROM ( + SELECT + c.relkind::text AS relkind, + NULL::text AS attname, + pg_catalog.obj_description(c.oid, 'pg_class') AS description, + 0 AS ordinal, + 0 AS attnum + FROM pg_catalog.pg_class c + JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace + WHERE n.nspname = \(schemaLiteral) + AND c.relname = \(nameLiteral) + AND c.relkind IN ('r', 'p', 'f', 'v', 'm') + AND pg_catalog.obj_description(c.oid, 'pg_class') IS NOT NULL + UNION ALL + SELECT + c.relkind::text AS relkind, + a.attname AS attname, + pg_catalog.col_description(c.oid, a.attnum) AS description, + 1 AS ordinal, + a.attnum AS attnum + FROM pg_catalog.pg_class c + JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace + JOIN pg_catalog.pg_attribute a ON a.attrelid = c.oid + WHERE n.nspname = \(schemaLiteral) + AND c.relname = \(nameLiteral) + AND c.relkind IN ('r', 'p', 'f', 'v', 'm') + AND a.attnum > 0 + AND NOT a.attisdropped + AND pg_catalog.col_description(c.oid, a.attnum) IS NOT NULL + ) AS relation_comments + ORDER BY ordinal, attnum + """ + } + + /// Renders what `catalogQuery` answered. Rows are projected as `relkind`, `attname`, + /// `description`, and a nil `attname` marks the relation's own comment. + public static func statements(name: String, schema: String, rows: [[String?]]) -> [String] { + let target = PostgreSQLObjectQueries.qualifiedName(schema: schema, name: name) + return rows.compactMap { statement(target: target, row: $0) } + } + + private static func statement(target: String, row: [String?]) -> String? { + guard row.count >= 3, + let relkind = row[0], + let keyword = PostgreSQLRelationSQL.commentKeyword(forRelkind: relkind), + let description = row[2], + !description.isEmpty + else { return nil } + let literal = PostgreSQLObjectQueries.quoteLiteral(description) + guard let column = row[1], !column.isEmpty else { + return "COMMENT ON \(keyword) \(target) IS \(literal)" + } + let columnRef = "\(target).\(PostgreSQLObjectQueries.quoteIdentifier(column))" + return "COMMENT ON COLUMN \(columnRef) IS \(literal)" + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Comments.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Comments.swift new file mode 100644 index 0000000000..60608d2cb5 --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Comments.swift @@ -0,0 +1,25 @@ +// +// PostgreSQLPluginDriver+Comments.swift +// PostgreSQLDriverPlugin +// + +import Foundation +import TableProPluginKit + +extension PostgreSQLPluginDriver { + /// A plain read rather than the `search_path`-emptied one `fetchViewDefinition` takes: nothing + /// here is deparsed by the server, so the session's path cannot change the answer. + /// + /// Cockroach, Redshift and PGlite inherit this, which is correct: all three keep + /// `obj_description` and `col_description`. + func fetchCommentDDL(table: String, schema: String?) async throws -> [String] { + let resolvedSchema = schema ?? core.currentSchema + let query = PostgreSQLCommentStatements.catalogQuery(name: table, schema: resolvedSchema) + let result = try await execute(query: query) + return PostgreSQLCommentStatements.statements( + name: table, + schema: resolvedSchema, + rows: result.rows.map { $0.map(\.asText) } + ) + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLRelationSQL.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLRelationSQL.swift index ee84077a7c..1e220eadcd 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLRelationSQL.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLRelationSQL.swift @@ -28,6 +28,23 @@ public enum PostgreSQLRelationSQL { } } + /// The same keyword read from `pg_class.relkind`, which is what a catalog read has to hand. A + /// partitioned table takes `TABLE`, the keyword `COMMENT ON PARTITIONED TABLE` does not exist. + public static func commentKeyword(forRelkind relkind: String) -> String? { + switch relkind { + case "r", "p": + return "TABLE" + case "f": + return "FOREIGN TABLE" + case "v": + return "VIEW" + case "m": + return "MATERIALIZED VIEW" + default: + return nil + } + } + /// `COMMENT` takes a literal and nothing else, so the value is quoted here rather than bound. The /// quoting reads the same whatever `standard_conforming_strings` is set to. public static func commentStatement( diff --git a/Plugins/RedisDriverPlugin/Info.plist b/Plugins/RedisDriverPlugin/Info.plist index f02bf31c1c..92ff8ddca9 100644 --- a/Plugins/RedisDriverPlugin/Info.plist +++ b/Plugins/RedisDriverPlugin/Info.plist @@ -21,7 +21,7 @@ NSPrincipalClass $(PRODUCT_MODULE_NAME).RedisPlugin TableProPluginKitVersion - 27 + 28 TableProProvidesDatabaseTypeIds Redis diff --git a/Plugins/SQLExportPlugin/Info.plist b/Plugins/SQLExportPlugin/Info.plist index abd1a7dfdb..966eed5590 100644 --- a/Plugins/SQLExportPlugin/Info.plist +++ b/Plugins/SQLExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesExportFormatIds sql diff --git a/Plugins/SQLExportPlugin/SQLExportPlugin.swift b/Plugins/SQLExportPlugin/SQLExportPlugin.swift index 0d89712688..5219d8fb4d 100644 --- a/Plugins/SQLExportPlugin/SQLExportPlugin.swift +++ b/Plugins/SQLExportPlugin/SQLExportPlugin.swift @@ -54,6 +54,10 @@ final class SQLExportPlugin: ExportFormatPlugin, SettablePlugin, @unchecked Send /// a table whose `CREATE TABLE` came back fine and only lost its indexes is a different thing /// to tell the user about. var indexFailures: [String] = [] + + /// Kept apart for the same reason `indexFailures` is: an object whose definition came back fine + /// and only lost its comments is a different thing to tell the user about. + var commentFailures: [String] = [] var metadataWarnings: [String] = [] /// The tables a foreign key cycle left the ordering unable to place. They keep the order the @@ -114,6 +118,7 @@ final class SQLExportPlugin: ExportFormatPlugin, SettablePlugin, @unchecked Send ) async throws -> ExportFormatResult { ddlFailures = [] indexFailures = [] + commentFailures = [] metadataWarnings = [] exportSpansContainers = false tablesUnorderedByCycle = [] @@ -244,6 +249,11 @@ final class SQLExportPlugin: ExportFormatPlugin, SettablePlugin, @unchecked Send format: String(localized: "Could not fetch indexes for: %@"), indexFailures.joined(separator: ", "))) } + if !commentFailures.isEmpty { + warnings.append(String( + format: String(localized: "Could not fetch comments for: %@"), + commentFailures.joined(separator: ", "))) + } warnings.append(contentsOf: metadataWarnings) return ExportFormatResult(warnings: warnings) } @@ -489,7 +499,51 @@ final class SQLExportPlugin: ExportFormatPlugin, SettablePlugin, @unchecked Send let ddlWarning = "Warning: failed to fetch DDL for table \(sanitizedName): \(error)" Self.logger.warning("Failed to fetch DDL for table \(sanitizedName): \(error)") try writer.write("-- \(PluginExportUtilities.sanitizeForSQLComment(ddlWarning))\n\n") + continue + } + try await writeComments(for: table, dataSource: dataSource, to: writer) + } + } + + /// The kinds whose `CREATE` this dump writes as the object the driver's `COMMENT` keyword names. + /// A routine, trigger, sequence or type is skipped rather than asked, so a dump of one costs no + /// round trip. + /// + /// A foreign table is left out for a harder reason: the dump writes `CREATE TABLE` for it, so + /// PostgreSQL's own `COMMENT ON FOREIGN TABLE` fails the restore with `"f_orders" is not a + /// foreign table`. Measured on PostgreSQL 17.11. Add it back once a foreign table's `CREATE` is + /// its own. + private static let commentedKinds: Set = [ + .table, .view, .materializedView + ] + + /// Writes an object's comments directly after its own `CREATE`, which is where `pg_dump` puts + /// them, so a comment travels with the object it belongs to rather than with a later phase. + /// + /// Only ever called on the success branch: a `COMMENT` on an object whose `CREATE` was not + /// written fails the restore. An unreadable comment list is recorded and commented into the file + /// rather than failing the export, exactly as the index phase does. + private func writeComments( + for object: PluginExportTable, + dataSource: any PluginExportDataSource, + to writer: SQLExportFileWriter + ) async throws { + guard Self.commentedKinds.contains(object.kind) else { return } + let sanitizedName = PluginExportUtilities.sanitizeForSQLComment(object.name) + do { + let statements = try await dataSource.fetchCommentDDL( + table: object.name, databaseName: object.databaseName) + guard !statements.isEmpty else { return } + for statement in statements { + let terminated = statement.hasSuffix(";") ? statement : "\(statement);" + try writer.write("\(terminated)\n") } + try writer.write("\n") + } catch { + commentFailures.append(sanitizedName) + Self.logger.warning("Failed to fetch comments for \(sanitizedName): \(error)") + let warning = "Warning: failed to fetch comments for \(sanitizedName): \(error)" + try writer.write("-- \(PluginExportUtilities.sanitizeForSQLComment(warning))\n\n") } } @@ -532,7 +586,9 @@ final class SQLExportPlugin: ExportFormatPlugin, SettablePlugin, @unchecked Send Self.logger.warning("Failed to fetch DDL for \(sanitizedName): \(error)") let warning = "Warning: failed to fetch definition for \(label.lowercased()) \(sanitizedName): \(error)" try writer.write("-- \(PluginExportUtilities.sanitizeForSQLComment(warning))\n\n") + continue } + try await writeComments(for: object, dataSource: dataSource, to: writer) } } diff --git a/Plugins/SQLImportPlugin/Info.plist b/Plugins/SQLImportPlugin/Info.plist index 6d943056e4..75df0c8bc1 100644 --- a/Plugins/SQLImportPlugin/Info.plist +++ b/Plugins/SQLImportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesImportFormatIds sql diff --git a/Plugins/SQLiteDriverPlugin/Info.plist b/Plugins/SQLiteDriverPlugin/Info.plist index abf2a2ff1b..2563adc79a 100644 --- a/Plugins/SQLiteDriverPlugin/Info.plist +++ b/Plugins/SQLiteDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesDatabaseTypeIds SQLite diff --git a/Plugins/SnowflakeDriverPlugin/Info.plist b/Plugins/SnowflakeDriverPlugin/Info.plist index 285dd606a8..21c3a16871 100644 --- a/Plugins/SnowflakeDriverPlugin/Info.plist +++ b/Plugins/SnowflakeDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.48.0 TableProPluginKitVersion - 27 + 28 diff --git a/Plugins/SpannerDriverPlugin/Info.plist b/Plugins/SpannerDriverPlugin/Info.plist index cd7bdb6246..dac8735b47 100644 --- a/Plugins/SpannerDriverPlugin/Info.plist +++ b/Plugins/SpannerDriverPlugin/Info.plist @@ -5,7 +5,7 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 27 + 28 TableProProvidesDatabaseTypeIds Spanner diff --git a/Plugins/SurrealDBDriverPlugin/Info.plist b/Plugins/SurrealDBDriverPlugin/Info.plist index 29d097761f..9c080f515b 100644 --- a/Plugins/SurrealDBDriverPlugin/Info.plist +++ b/Plugins/SurrealDBDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesDatabaseTypeIds SurrealDB diff --git a/Plugins/TableProPluginKit/PluginDatabaseDriver.swift b/Plugins/TableProPluginKit/PluginDatabaseDriver.swift index a75fc3dde5..e7df24678f 100644 --- a/Plugins/TableProPluginKit/PluginDatabaseDriver.swift +++ b/Plugins/TableProPluginKit/PluginDatabaseDriver.swift @@ -112,6 +112,19 @@ public protocol PluginDatabaseDriver: AnyObject, Sendable { /// here must not also declare the same indexes in `fetchTableDDL`, or the dump creates each /// one twice. func fetchIndexDDL(table: String, schema: String?) async throws -> [String] + + /// The `COMMENT` statements that reattach this relation's own comment and its column comments, + /// ready to run. A dump writes them directly after the object's `CREATE`, which is where every + /// engine's own tool puts them. + /// + /// This is statement text rather than the comment strings, because only the driver knows the + /// keyword its engine demands: PostgreSQL checks `COMMENT ON TABLE` against the relation's + /// `relkind` and refuses it on a view with "is not a table". + /// + /// Returning nothing is the right answer for an engine whose `CREATE TABLE` carries its comments + /// inline. A driver that answers here must not also declare the same comments in + /// `fetchTableDDL`, or the dump sets each one twice. + func fetchCommentDDL(table: String, schema: String?) async throws -> [String] func fetchForeignKeys(table: String, schema: String?) async throws -> [PluginForeignKeyInfo] func fetchTriggers(table: String, schema: String?) async throws -> [PluginTriggerInfo] func fetchCheckConstraints(table: String, schema: String?) async throws -> [PluginCheckConstraintInfo] @@ -637,6 +650,11 @@ public extension PluginDatabaseDriver { /// statements from `fetchTableDDL` in the same change. func fetchIndexDDL(table: String, schema: String?) async throws -> [String] { [] } + /// Defaults to nothing, which is correct for an engine whose `CREATE TABLE` already carries its + /// comments and for one that stores none. A driver that overrides this must drop the same + /// statements from `fetchTableDDL` in the same change. + func fetchCommentDDL(table: String, schema: String?) async throws -> [String] { [] } + /// Answers whether `fetchAllIndexes` is a single query rather than the N+1 default below. var providesBulkIndexFetch: Bool { false } diff --git a/Plugins/TableProPluginKit/PluginExportDataSource.swift b/Plugins/TableProPluginKit/PluginExportDataSource.swift index ad82492825..3eb3afdf0c 100644 --- a/Plugins/TableProPluginKit/PluginExportDataSource.swift +++ b/Plugins/TableProPluginKit/PluginExportDataSource.swift @@ -20,6 +20,11 @@ public protocol PluginExportDataSource: AnyObject, Sendable { /// statements this table needs that `fetchTableDDL` does not already declare. func fetchIndexDDL(table: String, databaseName: String) async throws -> [String] + /// Mirrors `PluginDatabaseDriver.fetchCommentDDL` for the export side: the `COMMENT` statements + /// that reattach this relation's comment and its column comments, which `fetchTableDDL` does not + /// declare. + func fetchCommentDDL(table: String, databaseName: String) async throws -> [String] + /// The CREATE statement for any exportable object, routines, triggers, views and user types /// included. One method rather than one per kind, because the caller already knows the kind and /// every driver answers the same question: what would recreate this. @@ -61,6 +66,8 @@ public extension PluginExportDataSource { func fetchIndexDDL(table: String, databaseName: String) async throws -> [String] { [] } + func fetchCommentDDL(table: String, databaseName: String) async throws -> [String] { [] } + func fetchObjectDDL(_ object: PluginExportTable) async throws -> String { try await fetchTableDDL(table: object.name, databaseName: object.databaseName) } diff --git a/Plugins/TeradataDriverPlugin/Info.plist b/Plugins/TeradataDriverPlugin/Info.plist index fd30d5aac1..ab35b0b9e7 100644 --- a/Plugins/TeradataDriverPlugin/Info.plist +++ b/Plugins/TeradataDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 27 + 28 diff --git a/Plugins/TrinoDriverPlugin/Info.plist b/Plugins/TrinoDriverPlugin/Info.plist index fd30d5aac1..ab35b0b9e7 100644 --- a/Plugins/TrinoDriverPlugin/Info.plist +++ b/Plugins/TrinoDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 27 + 28 diff --git a/Plugins/TypesenseDriverPlugin/Info.plist b/Plugins/TypesenseDriverPlugin/Info.plist index 6be544d69e..1f4925cbd9 100644 --- a/Plugins/TypesenseDriverPlugin/Info.plist +++ b/Plugins/TypesenseDriverPlugin/Info.plist @@ -5,7 +5,7 @@ TableProMinAppVersion 0.73.0 TableProPluginKitVersion - 27 + 28 TableProProvidesDatabaseTypeIds Typesense diff --git a/Plugins/XLSXExportPlugin/Info.plist b/Plugins/XLSXExportPlugin/Info.plist index af15eb0527..8c8d82e6c7 100644 --- a/Plugins/XLSXExportPlugin/Info.plist +++ b/Plugins/XLSXExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesExportFormatIds xlsx diff --git a/Plugins/XLSXImportPlugin/Info.plist b/Plugins/XLSXImportPlugin/Info.plist index 7ecc3428a5..b393420625 100644 --- a/Plugins/XLSXImportPlugin/Info.plist +++ b/Plugins/XLSXImportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesImportFormatIds xlsx diff --git a/Plugins/XMLExportPlugin/Info.plist b/Plugins/XMLExportPlugin/Info.plist index 62d5b9037f..d32c9164b3 100644 --- a/Plugins/XMLExportPlugin/Info.plist +++ b/Plugins/XMLExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 27 + 28 TableProProvidesExportFormatIds xml diff --git a/TablePro/Core/Database/DatabaseDriver.swift b/TablePro/Core/Database/DatabaseDriver.swift index d0a1fab0cc..b2f9e4c7d8 100644 --- a/TablePro/Core/Database/DatabaseDriver.swift +++ b/TablePro/Core/Database/DatabaseDriver.swift @@ -164,6 +164,10 @@ protocol DatabaseDriver: AnyObject, Sendable { /// Empty on an engine whose CREATE TABLE carries them inline. Default returns empty. func fetchIndexDDL(table: String) async throws -> [String] + /// The COMMENT statements that reattach this relation's comment and its column comments. Empty + /// on an engine whose CREATE TABLE carries them inline. Default returns empty. + func fetchCommentDDL(table: String) async throws -> [String] + /// Fetch dependent type definitions (e.g., PostgreSQL enum types) for a table. /// Returns array of (typeName, labels) pairs. Default returns empty. func fetchDependentTypes(forTable table: String) async throws -> [(name: String, labels: [String])] @@ -347,6 +351,8 @@ extension DatabaseDriver { func fetchIndexDDL(table: String) async throws -> [String] { [] } + func fetchCommentDDL(table: String) async throws -> [String] { [] } + func resolveQueryCompletionProfile( databaseTypeId: String, base: QueryCompletionProfile diff --git a/TablePro/Core/Database/TableDDLComposer.swift b/TablePro/Core/Database/TableDDLComposer.swift index ede092bda1..74aab77285 100644 --- a/TablePro/Core/Database/TableDDLComposer.swift +++ b/TablePro/Core/Database/TableDDLComposer.swift @@ -7,24 +7,39 @@ import Foundation /// Joins a table's `CREATE TABLE` to the statements that stand outside it. /// -/// A driver answers `fetchTableDDL` with the table alone and `fetchIndexDDL` with the indexes that -/// statement does not declare, because a dump replays them in different phases: the table before -/// its rows, the indexes after. Anything showing one table's whole definition at once, Copy DDL and -/// the MCP schema tools among them, puts the two back together here rather than each spelling out -/// its own separator. +/// A driver answers `fetchTableDDL` with the table alone, `fetchCommentDDL` with its comments and +/// `fetchIndexDDL` with the indexes that statement does not declare, because a dump replays them in +/// different phases: the table and its comments before its rows, the indexes after. Anything showing +/// one table's whole definition at once, Copy DDL and the MCP schema tools among them, puts the +/// pieces back together here rather than each spelling out its own separator. internal enum TableDDLComposer { - internal static func compose(tableDDL: String, indexDDL: [String], preamble: String = "") -> String { - let statements = indexDDL - .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } - .filter { !$0.isEmpty } - .map { $0.hasSuffix(";") ? $0 : "\($0);" } + /// The comments keep the dump's own placement, between the table and its indexes, so the text + /// Show DDL and Copy DDL hand over is the text a restore runs. + internal static func compose( + tableDDL: String, + indexDDL: [String], + commentDDL: [String] = [], + preamble: String = "" + ) -> String { + let comments = terminated(commentDDL) + let indexes = terminated(indexDDL) var composed = preamble.isEmpty ? tableDDL : "\(preamble)\n\(tableDDL)" - guard !statements.isEmpty else { return composed } + guard !comments.isEmpty || !indexes.isEmpty else { return composed } if !composed.hasSuffix(";") { composed += ";" } - return composed + "\n\n" + statements.joined(separator: "\n") + for block in [comments, indexes] where !block.isEmpty { + composed += "\n\n" + block.joined(separator: "\n") + } + return composed + } + + private static func terminated(_ statements: [String]) -> [String] { + statements + .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } + .filter { !$0.isEmpty } + .map { $0.hasSuffix(";") ? $0 : "\($0);" } } /// One object's whole definition, read on a driver already pinned to its scope. The Structure @@ -39,7 +54,13 @@ internal enum TableDDLComposer { let preamble = includesDependencies ? try await dependencyPreamble(for: table, using: driver) : "" let baseDDL = try await driver.fetchTableDDL(table: table) let indexDDL = (try? await driver.fetchIndexDDL(table: table)) ?? [] - return compose(tableDDL: baseDDL, indexDDL: indexDDL, preamble: preamble) + let commentDDL = (try? await driver.fetchCommentDDL(table: table)) ?? [] + return compose( + tableDDL: baseDDL, + indexDDL: indexDDL, + commentDDL: commentDDL, + preamble: preamble + ) } private static func dependencyPreamble(for table: String, using driver: DatabaseDriver) async throws -> String { diff --git a/TablePro/Core/Plugins/ExportDataSourceAdapter.swift b/TablePro/Core/Plugins/ExportDataSourceAdapter.swift index b470c13d3d..f27e7d21c0 100644 --- a/TablePro/Core/Plugins/ExportDataSourceAdapter.swift +++ b/TablePro/Core/Plugins/ExportDataSourceAdapter.swift @@ -213,6 +213,11 @@ final class ExportDataSourceAdapter: PluginExportDataSource, @unchecked Sendable return try await pluginDriver.fetchIndexDDL(table: table, schema: exportSchema(for: databaseName)) } + func fetchCommentDDL(table: String, databaseName: String) async throws -> [String] { + guard let pluginDriver else { return [] } + return try await pluginDriver.fetchCommentDDL(table: table, schema: exportSchema(for: databaseName)) + } + // MARK: - Object DDL /// A driver addresses a routine, trigger or type through the info object it handed out, which diff --git a/TablePro/Core/Plugins/PluginDriverAdapter.swift b/TablePro/Core/Plugins/PluginDriverAdapter.swift index cfd613970a..de3757028a 100644 --- a/TablePro/Core/Plugins/PluginDriverAdapter.swift +++ b/TablePro/Core/Plugins/PluginDriverAdapter.swift @@ -432,6 +432,10 @@ final class PluginDriverAdapter: DatabaseDriver, SchemaSwitchable, DatabaseRepor try await pluginDriver.fetchIndexDDL(table: table, schema: pluginDriver.currentSchema) } + func fetchCommentDDL(table: String) async throws -> [String] { + try await pluginDriver.fetchCommentDDL(table: table, schema: pluginDriver.currentSchema) + } + func fetchDependentTypes(forTable table: String) async throws -> [(name: String, labels: [String])] { try await pluginDriver.fetchDependentTypes(table: table, schema: pluginDriver.currentSchema) } diff --git a/TablePro/Core/Plugins/PluginManager.swift b/TablePro/Core/Plugins/PluginManager.swift index e7624f75be..825f0210b4 100644 --- a/TablePro/Core/Plugins/PluginManager.swift +++ b/TablePro/Core/Plugins/PluginManager.swift @@ -14,7 +14,15 @@ import TableProPluginKit @MainActor @Observable final class PluginManager { static let shared = PluginManager(userDefaults: AppStorageEnvironment.shared.defaults) - /// Raised to 26 for `objectCommentStatement`, `refreshMaterializedViewStatement` and + /// Raised to 28 for `fetchCommentDDL` on `PluginDatabaseDriver` and `PluginExportDataSource`, + /// which is what lets a dump reattach a relation's own comment and its column comments instead + /// of leaving whether they appear at all to each driver's `fetchTableDDL`. + /// + /// Raised to 27 before that for `hasLostConnection`, `unsupportedStructureColumnFields`, + /// `unsupportedIndexTypes` and `schemaOperationRefusal` on `PluginDatabaseDriver`, plus the + /// `PluginSchemaOperation` the last one answers about. + /// + /// Raised to 26 before that for `objectCommentStatement`, `refreshMaterializedViewStatement` and /// `concurrentRefreshAvailability` on `PluginDatabaseDriver`, plus the /// `PluginConcurrentRefreshAvailability` the last one answers with. /// @@ -41,7 +49,7 @@ final class PluginManager { /// rebuilt CassandraDriver for the v20 requirements it implements none of. Left at 20, such a /// plugin passes `validateBundleVersions` in a shipped v20 app and then fails /// `Bundle.loadAndReturnError`; at 21 that app refuses it and says to update. - nonisolated static let currentPluginKitVersion = 27 + nonisolated static let currentPluginKitVersion = 28 /// Still 19, so every plugin already published for the previous release keeps loading. nonisolated static let minimumCompatiblePluginKitVersion = 19 diff --git a/TableProTests/Core/Database/TableDDLComposerTests.swift b/TableProTests/Core/Database/TableDDLComposerTests.swift new file mode 100644 index 0000000000..3f54e745f5 --- /dev/null +++ b/TableProTests/Core/Database/TableDDLComposerTests.swift @@ -0,0 +1,79 @@ +// +// TableDDLComposerTests.swift +// TableProTests +// + +import Foundation +@testable import TablePro +import Testing + +@Suite("Table DDL composition") +struct TableDDLComposerTests { + private let tableDDL = "CREATE TABLE \"app\".\"orders\" (\n id integer\n)" + private let comment = "COMMENT ON TABLE \"app\".\"orders\" IS 'Orders table'" + private let index = "CREATE INDEX idx_orders_day ON \"app\".\"orders\" (day)" + + private func offset(of needle: String, in text: String) throws -> Int { + let range = try #require(text.range(of: needle), "\(needle) missing from the composition") + return text.distance(from: text.startIndex, to: range.lowerBound) + } + + @Test("Comments sit after the table statement and before the indexes, as a dump writes them") + func commentsSitBetweenTheTableAndItsIndexes() throws { + let composed = TableDDLComposer.compose( + tableDDL: tableDDL, indexDDL: [index], commentDDL: [comment]) + + #expect(try offset(of: "CREATE TABLE", in: composed) < offset(of: "COMMENT ON TABLE", in: composed)) + #expect(try offset(of: "COMMENT ON TABLE", in: composed) < offset(of: "CREATE INDEX", in: composed)) + } + + @Test("Every statement is terminated once, even one the driver already terminated") + func statementsAreTerminatedOnce() { + let composed = TableDDLComposer.compose( + tableDDL: tableDDL, + indexDDL: ["\(index);"], + commentDDL: [comment]) + + #expect(composed.contains("IS 'Orders table';")) + #expect(!composed.contains("IS 'Orders table';;")) + #expect(composed.contains("(day);")) + #expect(!composed.contains("(day);;")) + } + + @Test("The preamble stays first") + func preambleStaysFirst() throws { + let composed = TableDDLComposer.compose( + tableDDL: tableDDL, + indexDDL: [], + commentDDL: [comment], + preamble: "CREATE SEQUENCE orders_id_seq;") + + #expect(try offset(of: "CREATE SEQUENCE", in: composed) < offset(of: "CREATE TABLE", in: composed)) + #expect(try offset(of: "CREATE TABLE", in: composed) < offset(of: "COMMENT ON TABLE", in: composed)) + } + + @Test("An empty comment list composes exactly as it did before comments existed") + func emptyCommentListChangesNothing() { + let withComments = TableDDLComposer.compose( + tableDDL: tableDDL, indexDDL: [index], commentDDL: []) + let withoutComments = TableDDLComposer.compose(tableDDL: tableDDL, indexDDL: [index]) + + #expect(withComments == withoutComments) + } + + @Test("Comments alone still terminate the table statement and stand in their own block") + func commentsAloneComposeWithoutIndexes() { + let composed = TableDDLComposer.compose( + tableDDL: tableDDL, indexDDL: [], commentDDL: [comment]) + + #expect(composed == "\(tableDDL);\n\n\(comment);") + } + + @Test("A blank comment statement is dropped rather than written as an empty line") + func blankStatementsAreDropped() { + let composed = TableDDLComposer.compose( + tableDDL: tableDDL, indexDDL: [], commentDDL: ["", " \n"]) + + #expect(composed == tableDDL) + } +} diff --git a/TableProTests/Core/Plugins/PluginKitABIResilienceTests.swift b/TableProTests/Core/Plugins/PluginKitABIResilienceTests.swift index 1e8588b170..91f999b5c5 100644 --- a/TableProTests/Core/Plugins/PluginKitABIResilienceTests.swift +++ b/TableProTests/Core/Plugins/PluginKitABIResilienceTests.swift @@ -47,6 +47,8 @@ struct PluginKitABIResilienceTests { #expect(try await driver.fetchSchemas().isEmpty) #expect(try await driver.fetchExternalSchemaNames().isEmpty) #expect(try await driver.fetchApproximateRowCount(table: "users", schema: nil) == nil) + #expect(try await driver.fetchIndexDDL(table: "users", schema: nil).isEmpty) + #expect(try await driver.fetchCommentDDL(table: "users", schema: nil).isEmpty) let base = QueryCompletionProfile( resolvedDialect: nil, statementCompletions: [CompletionEntry(label: "SELECT", insertText: "SELECT")], diff --git a/TableProTests/Plugins/PostgreSQLCommentStatementsTests.swift b/TableProTests/Plugins/PostgreSQLCommentStatementsTests.swift new file mode 100644 index 0000000000..f53ae8bf15 --- /dev/null +++ b/TableProTests/Plugins/PostgreSQLCommentStatementsTests.swift @@ -0,0 +1,164 @@ +// +// PostgreSQLCommentStatementsTests.swift +// TableProTests +// + +import Foundation +import Testing + +@Suite("PostgreSQL comment statements") +struct PostgreSQLCommentStatementsTests { + private func row(relkind: String, column: String?, description: String?) -> [String?] { + [relkind, column, description] + } + + @Test("The relation's own comment is rendered first, then its columns in row order") + func relationCommentPrecedesColumns() { + let statements = PostgreSQLCommentStatements.statements( + name: "orders", + schema: "app", + rows: [ + row(relkind: "r", column: nil, description: "Orders table"), + row(relkind: "r", column: "id", description: "Primary key"), + row(relkind: "r", column: "label", description: "Label") + ]) + + #expect(statements == [ + "COMMENT ON TABLE \"app\".\"orders\" IS 'Orders table'", + "COMMENT ON COLUMN \"app\".\"orders\".\"id\" IS 'Primary key'", + "COMMENT ON COLUMN \"app\".\"orders\".\"label\" IS 'Label'" + ]) + } + + @Test("relkind picks the keyword, because the server refuses a mismatched one") + func relkindPicksTheKeyword() { + #expect(PostgreSQLRelationSQL.commentKeyword(forRelkind: "r") == "TABLE") + #expect(PostgreSQLRelationSQL.commentKeyword(forRelkind: "p") == "TABLE") + #expect(PostgreSQLRelationSQL.commentKeyword(forRelkind: "f") == "FOREIGN TABLE") + #expect(PostgreSQLRelationSQL.commentKeyword(forRelkind: "v") == "VIEW") + #expect(PostgreSQLRelationSQL.commentKeyword(forRelkind: "m") == "MATERIALIZED VIEW") + #expect(PostgreSQLRelationSQL.commentKeyword(forRelkind: "i") == nil) + } + + @Test("A view, a materialized view and a foreign table each get their own keyword") + func eachRelationKindRendersItsKeyword() { + let view = PostgreSQLCommentStatements.statements( + name: "v_orders", schema: "app", + rows: [row(relkind: "v", column: nil, description: "View comment")]) + let matview = PostgreSQLCommentStatements.statements( + name: "m_orders", schema: "app", + rows: [row(relkind: "m", column: nil, description: "Matview comment")]) + let foreign = PostgreSQLCommentStatements.statements( + name: "f_orders", schema: "app", + rows: [row(relkind: "f", column: nil, description: "Foreign comment")]) + + #expect(view == ["COMMENT ON VIEW \"app\".\"v_orders\" IS 'View comment'"]) + #expect(matview == ["COMMENT ON MATERIALIZED VIEW \"app\".\"m_orders\" IS 'Matview comment'"]) + #expect(foreign == ["COMMENT ON FOREIGN TABLE \"app\".\"f_orders\" IS 'Foreign comment'"]) + } + + @Test("A relkind with no COMMENT keyword yields no statement") + func unknownRelkindYieldsNothing() { + let statements = PostgreSQLCommentStatements.statements( + name: "orders_pkey", schema: "app", + rows: [row(relkind: "i", column: nil, description: "Index comment")]) + + #expect(statements.isEmpty) + } + + @Test("A value holding a backslash and a quote renders the server's own quote_literal output") + func backslashAndQuoteRenderAsEscapeString() { + let statements = PostgreSQLCommentStatements.statements( + name: "orders", schema: "app", + rows: [row( + relkind: "r", + column: "path", + description: #"Windows path C:\temp and a quote ' here"#)]) + + #expect(statements == [ + #"COMMENT ON COLUMN "app"."orders"."path" IS E'Windows path C:\\temp and a quote '' here'"# + ]) + } + + @Test("A comment with a single quote and no backslash stays a plain literal") + func singleQuoteDoublesInPlainLiteral() { + let statements = PostgreSQLCommentStatements.statements( + name: "orders", schema: "app", + rows: [row(relkind: "r", column: "label", description: "It's a label")]) + + #expect(statements == ["COMMENT ON COLUMN \"app\".\"orders\".\"label\" IS 'It''s a label'"]) + } + + @Test("A multi-line comment stays inside one literal") + func multiLineCommentStaysOneLiteral() { + let statements = PostgreSQLCommentStatements.statements( + name: "orders", schema: "app", + rows: [row(relkind: "r", column: "notes", description: "First line\nSecond line")]) + + #expect(statements == [ + "COMMENT ON COLUMN \"app\".\"orders\".\"notes\" IS 'First line\nSecond line'" + ]) + } + + @Test("A double quote in an identifier is doubled") + func doubleQuoteInIdentifierIsDoubled() { + let statements = PostgreSQLCommentStatements.statements( + name: "od\"d", schema: "sc\"h", + rows: [row(relkind: "r", column: "co\"l", description: "Comment")]) + + #expect(statements == ["COMMENT ON COLUMN \"sc\"\"h\".\"od\"\"d\".\"co\"\"l\" IS 'Comment'"]) + } + + @Test("A nil or empty description yields no statement, never IS NULL") + func emptyDescriptionYieldsNothing() { + let statements = PostgreSQLCommentStatements.statements( + name: "orders", schema: "app", + rows: [ + row(relkind: "r", column: nil, description: nil), + row(relkind: "r", column: "id", description: "") + ]) + + #expect(statements.isEmpty) + } + + @Test("A short row is skipped rather than read past its end") + func shortRowIsSkipped() { + let statements = PostgreSQLCommentStatements.statements( + name: "orders", schema: "app", rows: [["r", nil]]) + + #expect(statements.isEmpty) + } + + @Test("catalogQuery quotes both literals so a name holding a quote cannot end them") + func catalogQueryQuotesItsLiterals() { + let query = PostgreSQLCommentStatements.catalogQuery(name: "O'Brien", schema: "sa'les") + + #expect(query.contains("c.relname = 'O''Brien'")) + #expect(query.contains("n.nspname = 'sa''les'")) + #expect(!query.contains("'O'Brien'")) + } + + @Test("catalogQuery reads only the relation kinds a COMMENT statement can name") + func catalogQueryFiltersRelationKinds() { + let query = PostgreSQLCommentStatements.catalogQuery(name: "orders", schema: "app") + + #expect(query.contains("c.relkind IN ('r', 'p', 'f', 'v', 'm')")) + } + + @Test("catalogQuery excludes dropped and system columns and orders the relation before them") + func catalogQueryExcludesDroppedColumns() { + let query = PostgreSQLCommentStatements.catalogQuery(name: "orders", schema: "app") + + #expect(query.contains("NOT a.attisdropped")) + #expect(query.contains("a.attnum > 0")) + #expect(query.contains("ORDER BY ordinal, attnum")) + } + + @Test("catalogQuery reads both description functions and drops a relation with neither") + func catalogQueryReadsBothDescriptionFunctions() { + let query = PostgreSQLCommentStatements.catalogQuery(name: "orders", schema: "app") + + #expect(query.contains("pg_catalog.obj_description(c.oid, 'pg_class') IS NOT NULL")) + #expect(query.contains("pg_catalog.col_description(c.oid, a.attnum) IS NOT NULL")) + } +} diff --git a/TableProTests/Plugins/SQLExportCommentPhaseTests.swift b/TableProTests/Plugins/SQLExportCommentPhaseTests.swift new file mode 100644 index 0000000000..5e13f098aa --- /dev/null +++ b/TableProTests/Plugins/SQLExportCommentPhaseTests.swift @@ -0,0 +1,229 @@ +// +// SQLExportCommentPhaseTests.swift +// TableProTests +// + +import Foundation +import TableProPluginKit +import Testing + +@Suite("SQL export comments") +struct SQLExportCommentPhaseTests { + private final class StubExportDataSource: PluginExportDataSource, @unchecked Sendable { + let databaseTypeId: String + let commentDDL: [String: [String]] + let failingTables: Set + + init( + databaseTypeId: String = "PostgreSQL", + commentDDL: [String: [String]] = [:], + failingTables: Set = [] + ) { + self.databaseTypeId = databaseTypeId + self.commentDDL = commentDDL + self.failingTables = failingTables + } + + func streamRows(table: String, databaseName: String) -> AsyncThrowingStream { + AsyncThrowingStream { continuation in + continuation.yield(.header(PluginStreamHeader(columns: ["id"], columnTypeNames: ["INTEGER"]))) + continuation.yield(.rows([[.text("1")]])) + continuation.finish() + } + } + + func fetchTableDDL(table: String, databaseName: String) async throws -> String { + "CREATE TABLE \(table) (id INTEGER)" + } + + func fetchObjectDDL(_ object: PluginExportTable) async throws -> String { + switch object.kind { + case .view: return "CREATE OR REPLACE VIEW \(object.name) AS SELECT 1" + case .materializedView: return "CREATE MATERIALIZED VIEW \(object.name) AS SELECT 1" + case .routine: return "CREATE FUNCTION \(object.name)() RETURNS integer AS $$ SELECT 1 $$ LANGUAGE sql" + default: return try await fetchTableDDL(table: object.name, databaseName: object.databaseName) + } + } + + func fetchCommentDDL(table: String, databaseName: String) async throws -> [String] { + if failingTables.contains(table) { + throw StubError.unreadable + } + return commentDDL[table] ?? [] + } + + func execute(query: String) async throws -> PluginQueryResult { + PluginQueryResult(columns: [], columnTypeNames: [], rows: [], rowsAffected: 0, executionTime: 0) + } + + func quoteIdentifier(_ identifier: String) -> String { + "\"\(identifier.replacingOccurrences(of: "\"", with: "\"\""))\"" + } + + func escapeStringLiteral(_ value: String) -> String { + value.replacingOccurrences(of: "'", with: "''") + } + + func fetchApproximateRowCount(table: String, databaseName: String) async throws -> Int? { nil } + } + + private enum StubError: Error { + case unreadable + } + + private func table( + _ name: String, + kind: PluginExportObjectKind = .table, + optionValues: [Bool] = [true, true, true] + ) -> PluginExportTable { + PluginExportTable( + name: name, + databaseName: "", + tableType: kind.rawValue, + optionValues: optionValues, + schema: nil, + kind: kind) + } + + private func runExport( + tables: [PluginExportTable], + dataSource: StubExportDataSource + ) async throws -> (dump: String, result: ExportFormatResult) { + let output = try await SQLExportHarness.shared.dump(tables: tables, dataSource: dataSource) + return (output.text, output.result) + } + + private func offset(of needle: String, in dump: String) throws -> Int { + let range = try #require(dump.range(of: needle), "\(needle) missing from the dump") + return dump.distance(from: dump.startIndex, to: range.lowerBound) + } + + @Test("A driver that reports comment DDL gets it into the dump, terminated") + func commentsReachTheDump() async throws { + let source = StubExportDataSource(commentDDL: ["orders": [ + "COMMENT ON TABLE orders IS 'Orders table'", + "COMMENT ON COLUMN orders.id IS 'Primary key'" + ]]) + + let (dump, result) = try await runExport(tables: [table("orders")], dataSource: source) + + #expect(dump.contains("COMMENT ON TABLE orders IS 'Orders table';")) + #expect(dump.contains("COMMENT ON COLUMN orders.id IS 'Primary key';")) + #expect(result.warnings.isEmpty) + } + + @Test("A comment rides with its own object: after the CREATE, before the rows and the indexes") + func commentsFollowTheCreate() async throws { + let source = StubExportDataSource( + commentDDL: ["orders": ["COMMENT ON TABLE orders IS 'Orders table'"]]) + + let (dump, _) = try await runExport(tables: [table("orders")], dataSource: source) + + #expect(try offset(of: "CREATE TABLE orders", in: dump) < offset(of: "COMMENT ON TABLE", in: dump)) + #expect(try offset(of: "COMMENT ON TABLE", in: dump) < offset(of: "INSERT INTO", in: dump)) + } + + @Test("A view's comments sit in its own block, right after its CREATE") + func viewCommentsFollowTheViewCreate() async throws { + let source = StubExportDataSource(commentDDL: ["v_orders": [ + "COMMENT ON VIEW v_orders IS 'View comment'", + "COMMENT ON COLUMN v_orders.id IS 'View column comment'" + ]]) + + let (dump, _) = try await runExport( + tables: [table("v_orders", kind: .view)], dataSource: source) + + #expect(try offset(of: "CREATE OR REPLACE VIEW", in: dump) < offset(of: "COMMENT ON VIEW", in: dump)) + #expect(dump.contains("COMMENT ON COLUMN v_orders.id IS 'View column comment';")) + } + + @Test("A materialized view's comment falls after its CREATE and before the next object header") + func matviewCommentFollowsItsCreate() async throws { + let source = StubExportDataSource( + commentDDL: ["m_orders": ["COMMENT ON MATERIALIZED VIEW m_orders IS 'Matview comment'"]]) + + let (dump, _) = try await runExport( + tables: [ + table("m_orders", kind: .materializedView), + table("r_sum", kind: .routine) + ], + dataSource: source) + + #expect(try offset(of: "CREATE MATERIALIZED VIEW", in: dump) + < offset(of: "COMMENT ON MATERIALIZED VIEW", in: dump)) + #expect(try offset(of: "COMMENT ON MATERIALIZED VIEW", in: dump) + < offset(of: "-- Routine: r_sum", in: dump)) + } + + @Test("A statement the driver already terminated is not terminated twice") + func terminatedStatementsStaySingleTerminated() async throws { + let source = StubExportDataSource( + commentDDL: ["orders": ["COMMENT ON TABLE orders IS 'Orders table';"]]) + + let (dump, _) = try await runExport(tables: [table("orders")], dataSource: source) + + #expect(dump.contains("IS 'Orders table';")) + #expect(!dump.contains("IS 'Orders table';;")) + } + + @Test("A source answering nothing writes no COMMENT ON anywhere") + func noCommentsWritesNothing() async throws { + let source = StubExportDataSource(databaseTypeId: "MySQL") + + let (dump, result) = try await runExport(tables: [table("orders")], dataSource: source) + + #expect(!dump.contains("COMMENT ON")) + #expect(result.warnings.isEmpty) + } + + @Test("A table with Structure unticked contributes no comment statements") + func structureGatesTheCommentPhase() async throws { + let source = StubExportDataSource( + commentDDL: ["orders": ["COMMENT ON TABLE orders IS 'Orders table'"]]) + + let (dump, _) = try await runExport( + tables: [table("orders", optionValues: [false, true, true])], dataSource: source) + + #expect(!dump.contains("COMMENT ON")) + } + + @Test("An unreadable comment list is named in the warnings and does not fail the export") + func unreadableCommentsAreReported() async throws { + let source = StubExportDataSource( + commentDDL: ["customers": ["COMMENT ON TABLE customers IS 'Customers'"]], + failingTables: ["orders"]) + + let (dump, result) = try await runExport( + tables: [table("orders"), table("customers")], dataSource: source) + + #expect(result.warnings.contains { $0.contains("Could not fetch comments for") && $0.contains("orders") }) + #expect(dump.contains("-- Warning: failed to fetch comments for orders")) + #expect(dump.contains("COMMENT ON TABLE customers IS 'Customers';")) + #expect(dump.contains("CREATE TABLE customers (id INTEGER);")) + #expect(dump.contains("INSERT INTO")) + } + + @Test("A routine is never asked for comments, so its definition is all that is written") + func routinesAreNotAskedForComments() async throws { + let source = StubExportDataSource( + commentDDL: ["r_sum": ["COMMENT ON FUNCTION r_sum() IS 'never asked'"]]) + + let (dump, _) = try await runExport( + tables: [table("r_sum", kind: .routine)], dataSource: source) + + #expect(!dump.contains("COMMENT ON FUNCTION")) + } + + @Test("A foreign table is never asked, because the dump writes CREATE TABLE for it") + func foreignTablesAreNotAskedForComments() async throws { + let source = StubExportDataSource( + commentDDL: ["f_orders": ["COMMENT ON FOREIGN TABLE f_orders IS 'Foreign comment'"]]) + + let (dump, result) = try await runExport( + tables: [table("f_orders", kind: .foreignTable)], dataSource: source) + + #expect(dump.contains("CREATE TABLE f_orders")) + #expect(!dump.contains("COMMENT ON FOREIGN TABLE")) + #expect(result.warnings.isEmpty) + } +} diff --git a/docs/databases/postgresql.mdx b/docs/databases/postgresql.mdx index e8e18105c6..a12790c402 100644 --- a/docs/databases/postgresql.mdx +++ b/docs/databases/postgresql.mdx @@ -81,6 +81,8 @@ A view's definition is rebuilt to run anywhere. Every table it reads is schema-q **Edit Comment…** writes `COMMENT ON`, picking `TABLE`, `VIEW`, `MATERIALIZED VIEW` or `FOREIGN TABLE` to match the object. Column comments are written from the Columns tab as `COMMENT ON COLUMN`. Clearing the field writes `IS NULL`, which removes the comment. Only the object's owner may comment on it. +An SQL export writes those statements back for tables, views and materialized views, so a dump and a restore keep their comments. See [Import & Export](/features/import-export). + ## Cross-database tabs PostgreSQL has no in-place `USE`, so a tab bound to a database other than the connection's active one runs on a second connection opened for that database. It shares no temp tables, session variables, or open transaction with the query editor on the main connection: keep a multi-statement transaction or a `CREATE TEMP TABLE` on tabs bound to one database. Binding itself is on [Tabs](/features/tabs#where-a-tab-points). diff --git a/docs/development/plugin-development.mdx b/docs/development/plugin-development.mdx index 2f4e2101c4..d471008fde 100644 --- a/docs/development/plugin-development.mdx +++ b/docs/development/plugin-development.mdx @@ -13,7 +13,7 @@ A plugin is a macOS loadable bundle target with `WRAPPER_EXTENSION = tableplugin | Key | Type | Required | Purpose | |-----|------|----------|---------| -| `TableProPluginKitVersion` | integer | Yes | The PluginKit ABI the plugin was built against. Current value: 27 | +| `TableProPluginKitVersion` | integer | Yes | The PluginKit ABI the plugin was built against. Current value: 28 | | `TableProProvidesDatabaseTypeIds` | array of strings | Recommended | Database type IDs the plugin serves, which is what makes lazy loading possible | | `CFBundleShortVersionString` | string | Yes | Plugin version, read by registry update checks | | `TableProMinAppVersion` | string | No | The loader rejects the plugin on an older app | diff --git a/docs/development/plugin-registry.mdx b/docs/development/plugin-registry.mdx index e848422167..d8c922514e 100644 --- a/docs/development/plugin-registry.mdx +++ b/docs/development/plugin-registry.mdx @@ -68,13 +68,13 @@ Themes carry no native code, so they match on architecture alone. "binaries": [ { "architecture": "arm64", - "pluginKitVersion": 27, + "pluginKitVersion": 28, "downloadURL": "https://github.com/TableProApp/TablePro/releases/download/plugin-oracle-v1.0.26/OracleDriver-arm64.zip", "sha256": "" }, { "architecture": "x86_64", - "pluginKitVersion": 27, + "pluginKitVersion": 28, "downloadURL": "https://github.com/TableProApp/TablePro/releases/download/plugin-oracle-v1.0.26/OracleDriver-x86_64.zip", "sha256": "" } diff --git a/docs/features/import-export.mdx b/docs/features/import-export.mdx index eaa2c74533..399a430beb 100644 --- a/docs/features/import-export.mdx +++ b/docs/features/import-export.mdx @@ -121,6 +121,8 @@ As SQL, a results export writes `INSERT` statements only. A result set is the ou Structure carries the table's indexes. They are written after the rows, next to the deferred foreign keys, which is where `pg_dump` and `sqlite3 .dump` put them: a bulk load into an indexed table pays to maintain an index the restore is about to build anyway. On MySQL, MariaDB, ClickHouse, Trino and CockroachDB the server writes them inside `CREATE TABLE`, so they arrive with the table instead. A materialized view's indexes follow the view. + On PostgreSQL, Structure carries comments as well. Each table, view and materialized view gets its own `COMMENT ON` and one `COMMENT ON COLUMN` per commented column, directly after its `CREATE`. A foreign table is the exception: its comments are dropped, because the dump writes `CREATE TABLE` for it and PostgreSQL then refuses `COMMENT ON FOREIGN TABLE`. Where the server's own `CREATE TABLE` already carries the comment, MySQL and MariaDB among them, it arrives with the table instead. + All three are on by default, so an SQL export carries `DROP TABLE IF EXISTS` unless you untick **Drop**. Run that file against the wrong database and it drops the tables first. diff --git a/docs/features/table-structure.mdx b/docs/features/table-structure.mdx index 0358efb12f..ecd11c004b 100644 --- a/docs/features/table-structure.mdx +++ b/docs/features/table-structure.mdx @@ -169,7 +169,7 @@ Triggers are available for MySQL, MariaDB, PostgreSQL, SQLite, SQL Server, Oracl ## DDL tab -Read-only `CREATE TABLE` with syntax highlighting and font size controls. **Copy**, **Export** as a `.sql` file, and **Open in Editor** send it onward. On PostgreSQL the `CREATE SEQUENCE` and `CREATE TYPE … AS ENUM` statements the table depends on are prepended, so the script runs on an empty database. +Read-only `CREATE TABLE` with syntax highlighting and font size controls. **Copy**, **Export** as a `.sql` file, and **Open in Editor** send it onward. On PostgreSQL the `CREATE SEQUENCE` and `CREATE TYPE … AS ENUM` statements the table depends on are prepended, so the script runs on an empty database, and the table's `COMMENT ON` statements follow it. Open the tab on a view and it carries that view's own `CREATE VIEW` or `CREATE MATERIALIZED VIEW` instead, the same statement **Show DDL** opens. A materialized view's indexes follow it. diff --git a/project.yml b/project.yml index eeeb04ce26..9a8aa71f1a 100644 --- a/project.yml +++ b/project.yml @@ -526,6 +526,7 @@ targets: - Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogPresence.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogTypeNames.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLCheckConstraintDefinition.swift + - Plugins/PostgreSQLDriverPlugin/PostgreSQLCommentStatements.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLForeignKeyQueries.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLIndexQueries.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift From 006fffba3202efbbb528e3eb21d185f241dd26c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 09:21:59 +0700 Subject: [PATCH 37/54] fix(plugin-cockroach): read DDL and indexes from the object's own schema (#2726) (#2776) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ngô Quốc Đạt --- CHANGELOG.md | 1 + .../CockroachPluginDriver.swift | 13 ++-- .../CockroachRelationSQL.swift | 31 ++++++++ .../Plugins/CockroachRelationSQLTests.swift | 74 +++++++++++++++++++ project.yml | 1 + 5 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 Plugins/PostgreSQLDriverPlugin/CockroachRelationSQL.swift create mode 100644 TableProTests/Plugins/CockroachRelationSQLTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index e4227ba39a..350198c0e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -218,6 +218,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Non-ASCII SQL Server filter values turned into `?` and matching the wrong rows on non-Unicode collations. - Empty structure, missing indexes and failed renames for non-ASCII SQL Server object names on non-Unicode collations. - Changing a defaulted SQL Server column failing when a name contains a quote or non-ASCII text. +- CockroachDB DDL, view definition and index reads ignoring the schema of an object outside the current schema. (#2726) - Silent replay of a PostgreSQL statement on a new connection after a drop, a lost `COMMIT` reported as saved included. - Query timeout and startup commands missing after the PostgreSQL driver reconnected on its own. - Server Dashboard sessions, metrics and slow queries failing on PostgreSQL 9.6 and earlier. diff --git a/Plugins/PostgreSQLDriverPlugin/CockroachPluginDriver.swift b/Plugins/PostgreSQLDriverPlugin/CockroachPluginDriver.swift index ff7bb84970..75b23ed111 100644 --- a/Plugins/PostgreSQLDriverPlugin/CockroachPluginDriver.swift +++ b/Plugins/PostgreSQLDriverPlugin/CockroachPluginDriver.swift @@ -95,8 +95,7 @@ final class CockroachPluginDriver: LibPQBackedDriver, @unchecked Sendable { } func fetchIndexes(table: String, schema: String?) async throws -> [PluginIndexInfo] { - let quotedTable = quoteIdentifier(table) - let query = "SHOW INDEXES FROM \(quoteIdentifier(core.currentSchema)).\(quotedTable)" + let query = CockroachRelationSQL.showIndexes(table: table, schema: schema ?? core.currentSchema) let result = try await execute(query: query) guard let columnIndex = result.columns.firstIndex(of: "column_name"), @@ -156,8 +155,9 @@ final class CockroachPluginDriver: LibPQBackedDriver, @unchecked Sendable { } func fetchTableDDL(table: String, schema: String?) async throws -> String { - let quotedTable = quoteIdentifier(table) - let result = try await execute(query: "SHOW CREATE TABLE \(quoteIdentifier(core.currentSchema)).\(quotedTable)") + let result = try await execute( + query: CockroachRelationSQL.showCreateTable(table: table, schema: schema ?? core.currentSchema) + ) guard let ddl = Self.createStatement(from: result) else { throw LibPQPluginError(message: "Failed to fetch DDL for table '\(table)'", sqlState: nil, detail: nil) } @@ -165,8 +165,9 @@ final class CockroachPluginDriver: LibPQBackedDriver, @unchecked Sendable { } func fetchViewDefinition(view: String, schema: String?) async throws -> String { - let quotedView = quoteIdentifier(view) - let result = try await execute(query: "SHOW CREATE VIEW \(quoteIdentifier(core.currentSchema)).\(quotedView)") + let result = try await execute( + query: CockroachRelationSQL.showCreateView(view: view, schema: schema ?? core.currentSchema) + ) guard let ddl = Self.createStatement(from: result) else { throw LibPQPluginError(message: "Failed to fetch definition for view '\(view)'", sqlState: nil, detail: nil) } diff --git a/Plugins/PostgreSQLDriverPlugin/CockroachRelationSQL.swift b/Plugins/PostgreSQLDriverPlugin/CockroachRelationSQL.swift new file mode 100644 index 0000000000..ab41816ff1 --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/CockroachRelationSQL.swift @@ -0,0 +1,31 @@ +// +// CockroachRelationSQL.swift +// PostgreSQLDriverPlugin +// +// CockroachDB's SHOW statements for one relation. Pure, so it is testable without a server. +// + +import Foundation +import TableProPluginKit + +/// Every statement names the schema of the object asked for, never the session's own schema. +/// CockroachDB resolves a two-part `schema.object` name against the connection's current database, +/// so two parts are all these reads need and the session schema is never consulted. Reading +/// `currentSchema` instead sent an export or a compare of an object outside the connection's schema +/// at a same-named object in that schema, or at no object at all. +/// +/// `schema` is non-optional on purpose: the `?? currentSchema` fallback stays at the call site, +/// where the driver knows its own session, so no caller can reach these builders without one. +public enum CockroachRelationSQL { + public static func showCreateTable(table: String, schema: String) -> String { + "SHOW CREATE TABLE \(PostgreSQLObjectQueries.qualifiedName(schema: schema, name: table))" + } + + public static func showCreateView(view: String, schema: String) -> String { + "SHOW CREATE VIEW \(PostgreSQLObjectQueries.qualifiedName(schema: schema, name: view))" + } + + public static func showIndexes(table: String, schema: String) -> String { + "SHOW INDEXES FROM \(PostgreSQLObjectQueries.qualifiedName(schema: schema, name: table))" + } +} diff --git a/TableProTests/Plugins/CockroachRelationSQLTests.swift b/TableProTests/Plugins/CockroachRelationSQLTests.swift new file mode 100644 index 0000000000..0b8a6ff9be --- /dev/null +++ b/TableProTests/Plugins/CockroachRelationSQLTests.swift @@ -0,0 +1,74 @@ +// +// CockroachRelationSQLTests.swift +// TableProTests +// +// Tests for the CockroachDB SHOW statement builders (compiled via the plugin source list). +// Regression cover for metadata reads that took a schema argument and queried the session's +// current schema instead, so an export or compare of an object outside the connection's own +// schema read a same-named object in that schema or failed to find one at all. +// + +import Foundation +import Testing + +@Suite("CockroachRelationSQL") +struct CockroachRelationSQLTests { + @Test("SHOW CREATE TABLE names the requested schema") + func showCreateTableNamesRequestedSchema() { + let statement = CockroachRelationSQL.showCreateTable(table: "orders", schema: "analytics") + #expect(statement == "SHOW CREATE TABLE \"analytics\".\"orders\"") + } + + @Test("SHOW CREATE VIEW names the requested schema") + func showCreateViewNamesRequestedSchema() { + let statement = CockroachRelationSQL.showCreateView(view: "daily_rides", schema: "analytics") + #expect(statement == "SHOW CREATE VIEW \"analytics\".\"daily_rides\"") + } + + @Test("SHOW INDEXES names the requested schema") + func showIndexesNamesRequestedSchema() { + let statement = CockroachRelationSQL.showIndexes(table: "orders", schema: "analytics") + #expect(statement == "SHOW INDEXES FROM \"analytics\".\"orders\"") + } + + @Test("no builder substitutes the public schema", arguments: ["public", "analytics", "s2", "Mixed Case"]) + func everyBuilderCarriesTheSchemaThrough(schema: String) { + let statements = [ + CockroachRelationSQL.showCreateTable(table: "orders", schema: schema), + CockroachRelationSQL.showCreateView(view: "orders", schema: schema), + CockroachRelationSQL.showIndexes(table: "orders", schema: schema), + ] + for statement in statements { + #expect(statement.contains("\"\(schema)\".\"orders\"")) + if schema != "public" { + #expect(!statement.contains("\"public\".")) + } + } + } + + @Test("an embedded double quote is doubled in both parts") + func embeddedQuoteIsDoubled() { + let statement = CockroachRelationSQL.showCreateTable(table: "we\"ird", schema: "my\"schema") + #expect(statement == "SHOW CREATE TABLE \"my\"\"schema\".\"we\"\"ird\"") + } + + @Test("the target is the shared qualified name") + func targetIsSharedQualifiedName() { + let target = PostgreSQLObjectQueries.qualifiedName(schema: "s", name: "t") + #expect(CockroachRelationSQL.showCreateTable(table: "t", schema: "s").hasSuffix(target)) + #expect(CockroachRelationSQL.showCreateView(view: "t", schema: "s").hasSuffix(target)) + #expect(CockroachRelationSQL.showIndexes(table: "t", schema: "s").hasSuffix(target)) + } + + @Test("the name carries no database component") + func nameCarriesNoDatabaseComponent() { + let statements = [ + CockroachRelationSQL.showCreateTable(table: "orders", schema: "analytics"), + CockroachRelationSQL.showCreateView(view: "orders", schema: "analytics"), + CockroachRelationSQL.showIndexes(table: "orders", schema: "analytics"), + ] + for statement in statements { + #expect(statement.components(separatedBy: ".").count == 2) + } + } +} diff --git a/project.yml b/project.yml index 9a8aa71f1a..d745d85f94 100644 --- a/project.yml +++ b/project.yml @@ -509,6 +509,7 @@ targets: - Plugins/CloudflareD1DriverPlugin/CloudflareD1DefaultValue.swift - Plugins/CloudflareD1DriverPlugin/D1HttpClient.swift - Plugins/MSSQLDriverPlugin/MSSQLCheckConstraintDefinition.swift + - Plugins/PostgreSQLDriverPlugin/CockroachRelationSQL.swift - Plugins/PostgreSQLDriverPlugin/ColumnQueryShape.swift - Plugins/PostgreSQLDriverPlugin/LibPQByteaDecoder.swift - Plugins/PostgreSQLDriverPlugin/LibPQCellDecoding.swift From 242b76e028a20c1ab3990b5e81ef250e98ecae4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 09:22:19 +0700 Subject: [PATCH 38/54] fix(plugin-postgresql): quote every catalog literal so a backslash cannot escape it (#2726) (#2777) --- CHANGELOG.md | 2 +- .../CockroachPluginDriver.swift | 31 +-- .../ColumnQueryShape.swift | 23 +- .../LibPQDriverCore.swift | 11 +- .../PostgreSQLCatalogForeignKeys.swift | 6 +- .../PostgreSQLObjectQueries.swift | 33 ++- .../PostgreSQLPluginDriver+BulkMetadata.swift | 4 +- ...PostgreSQLPluginDriver+ColumnReorder.swift | 46 ++-- .../PostgreSQLPluginDriver+Columns.swift | 11 +- .../PostgreSQLPluginDriver+Principals.swift | 36 +-- ...ostgreSQLPluginDriver+TriggerEditing.swift | 6 +- .../PostgreSQLPluginDriver.swift | 55 +++-- .../PostgreSQLPrincipalQueries.swift | 41 ++-- .../PostgreSQLSchemaQueries.swift | 35 +-- .../RedshiftExternalSchemaQueries.swift | 32 +-- .../RedshiftPluginDriver.swift | 107 ++++----- .../RedshiftSchemaQueries.swift | 18 +- .../PostgreSQLCatalogForeignKeysTests.swift | 16 +- .../Plugins/PostgreSQLColumnQueryTests.swift | 22 +- .../PostgreSQLLegacyCatalogQueryTests.swift | 16 +- .../PostgreSQLLiteralQuotingTests.swift | 215 ++++++++++++++++++ .../PostgreSQLPartitionFilterTests.swift | 6 +- .../Plugins/PostgreSQLTypeQueryTests.swift | 2 + .../RedshiftExternalObjectsTests.swift | 50 ++-- scripts/check-postgres-literal-quoting.sh | 110 +++++++++ 25 files changed, 633 insertions(+), 301 deletions(-) create mode 100644 TableProTests/Plugins/PostgreSQLLiteralQuotingTests.swift create mode 100755 scripts/check-postgres-literal-quoting.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 350198c0e8..d0fd462355 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -236,7 +236,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - BigQuery Google sign-in accepting an authorization response without PKCE or a state check. - PostgreSQL sessions inheriting `standard_conforming_strings = off`, which let a backslash break out of any quoted literal. -- PostgreSQL comment and password literals escaped by quote doubling alone, which a backslash can break out of. (#2726) +- PostgreSQL catalog, comment and password literals escaped by quote doubling alone, which a backslash can break out of. (#2726) ## [0.73.0] - 2026-09-09 diff --git a/Plugins/PostgreSQLDriverPlugin/CockroachPluginDriver.swift b/Plugins/PostgreSQLDriverPlugin/CockroachPluginDriver.swift index 75b23ed111..6921f9c739 100644 --- a/Plugins/PostgreSQLDriverPlugin/CockroachPluginDriver.swift +++ b/Plugins/PostgreSQLDriverPlugin/CockroachPluginDriver.swift @@ -57,11 +57,11 @@ final class CockroachPluginDriver: LibPQBackedDriver, @unchecked Sendable { // MARK: - Schema func fetchTables(schema: String?) async throws -> [PluginTableInfo] { - let schemaLiteral = escapeLiteral(schema ?? core.currentSchema) + let resolvedSchema = schema ?? core.currentSchema let query = """ SELECT table_name, table_type FROM information_schema.tables - WHERE table_schema = '\(schemaLiteral)' + WHERE table_schema = \(PostgreSQLObjectQueries.quoteLiteral(resolvedSchema)) ORDER BY table_name """ let result = try await execute(query: query) @@ -74,16 +74,18 @@ final class CockroachPluginDriver: LibPQBackedDriver, @unchecked Sendable { } func fetchColumns(table: String, schema: String?) async throws -> [PluginColumnInfo] { - let safeTable = escapeLiteral(table) - let schemaLiteral = escapeLiteral(schema ?? core.currentSchema) - let query = Self.columnsQuery(schemaLiteral: schemaLiteral, tableFilter: "AND c.table_name = '\(safeTable)'") + let resolvedSchema = schema ?? core.currentSchema + let query = Self.columnsQuery( + schema: resolvedSchema, + tableFilter: "AND c.table_name = \(PostgreSQLObjectQueries.quoteLiteral(table))" + ) let result = try await execute(query: query) return result.rows.compactMap { Self.mapColumnRow($0, includesTableName: false) } } func fetchAllColumns(schema: String?) async throws -> [String: [PluginColumnInfo]] { - let schemaLiteral = escapeLiteral(schema ?? core.currentSchema) - let query = Self.columnsQuery(schemaLiteral: schemaLiteral, tableFilter: "", includesTableName: true) + let resolvedSchema = schema ?? core.currentSchema + let query = Self.columnsQuery(schema: resolvedSchema, tableFilter: "", includesTableName: true) let result = try await execute(query: query) var allColumns: [String: [PluginColumnInfo]] = [:] for row in result.rows { @@ -144,8 +146,8 @@ final class CockroachPluginDriver: LibPQBackedDriver, @unchecked Sendable { func fetchForeignKeys(table: String, schema: String?) async throws -> [PluginForeignKeyInfo] { let query = PostgreSQLCatalogForeignKeys.query( - schemaLiteral: PostgreSQLObjectQueries.quoteLiteral(schema ?? core.currentSchema), - tableLiteral: PostgreSQLObjectQueries.quoteLiteral(table), + schema: schema ?? core.currentSchema, + table: table, excludesPartitionClones: PostgreSQLCatalogForeignKeys.excludesPartitionClones( serverVersionNumber: core.serverVersionNumber ) @@ -191,11 +193,11 @@ final class CockroachPluginDriver: LibPQBackedDriver, @unchecked Sendable { } func fetchDatabaseMetadata(_ database: String) async throws -> PluginDatabaseMetadata { - let escapedDb = escapeLiteral(database) + let databaseLiteral = PostgreSQLObjectQueries.quoteLiteral(database) let query = """ SELECT COUNT(*) FROM information_schema.tables - WHERE table_catalog = '\(escapedDb)' + WHERE table_catalog = \(databaseLiteral) AND table_schema NOT IN ('pg_catalog', 'information_schema', 'crdb_internal', 'pg_extension') """ let tableCount = (try? await execute(query: query)) @@ -227,10 +229,11 @@ final class CockroachPluginDriver: LibPQBackedDriver, @unchecked Sendable { // MARK: - Query Helpers private static func columnsQuery( - schemaLiteral: String, + schema: String, tableFilter: String, includesTableName: Bool = false ) -> String { + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(schema) let selectPrefix = includesTableName ? "c.table_name,\n" : "" let orderBy = includesTableName ? "c.table_name, c.ordinal_position" : "c.ordinal_position" return """ @@ -257,9 +260,9 @@ final class CockroachPluginDriver: LibPQBackedDriver, @unchecked Sendable { ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema WHERE tc.constraint_type = 'PRIMARY KEY' - AND tc.table_schema = '\(schemaLiteral)' + AND tc.table_schema = \(schemaLiteral) ) pk ON c.table_name = pk.table_name AND c.column_name = pk.column_name - WHERE c.table_schema = '\(schemaLiteral)' \(tableFilter) + WHERE c.table_schema = \(schemaLiteral) \(tableFilter) ORDER BY \(orderBy) """ } diff --git a/Plugins/PostgreSQLDriverPlugin/ColumnQueryShape.swift b/Plugins/PostgreSQLDriverPlugin/ColumnQueryShape.swift index e7156ebdb9..123ad1202a 100644 --- a/Plugins/PostgreSQLDriverPlugin/ColumnQueryShape.swift +++ b/Plugins/PostgreSQLDriverPlugin/ColumnQueryShape.swift @@ -20,24 +20,29 @@ enum ColumnQueryShape { let orderBy: String } - /// Fragments for a column query scoped to one schema. Passing `tableLiteral` - /// restricts the query to a single table; passing `nil` returns every table's - /// columns, prefixes each row with `table_name`, and orders by table. - static func fragments(tableLiteral: String?) -> Fragments { - let includesTableName = tableLiteral == nil + /// Fragments for a column query scoped to one schema. Passing `table` restricts + /// the query to a single table; passing `nil` returns every table's columns, + /// prefixes each row with `table_name`, and orders by table. + /// + /// The name arrives raw and is quoted here through + /// `PostgreSQLObjectQueries.quoteLiteral`, which is the only spelling that reads + /// the same whatever `standard_conforming_strings` is set to. + static func fragments(table: String?) -> Fragments { + let includesTableName = table == nil + let tableLiteral = table.map { PostgreSQLObjectQueries.quoteLiteral($0) } return Fragments( selectPrefix: includesTableName ? "c.table_name,\n" : "", pkSelect: includesTableName ? "kcu.table_name, kcu.column_name" : "kcu.column_name", - pkTableFilter: tableLiteral.map { "\n AND tc.table_name = '\($0)'" } ?? "", + pkTableFilter: tableLiteral.map { "\n AND tc.table_name = \($0)" } ?? "", pkJoin: includesTableName ? "c.table_name = pk.table_name AND c.column_name = pk.column_name" : "c.column_name = pk.column_name", - mainTableFilter: tableLiteral.map { " AND c.table_name = '\($0)'" } ?? "", + mainTableFilter: tableLiteral.map { " AND c.table_name = \($0)" } ?? "", orderBy: includesTableName ? "c.table_name, c.ordinal_position" : "c.ordinal_position" ) } - static func primaryKeyJoin(schemaLiteral: String, fragments: Fragments) -> String { + static func primaryKeyJoin(schema: String, fragments: Fragments) -> String { """ LEFT JOIN ( SELECT DISTINCT \(fragments.pkSelect) @@ -47,7 +52,7 @@ enum ColumnQueryShape { AND tc.table_schema = kcu.table_schema AND tc.table_name = kcu.table_name WHERE tc.constraint_type = 'PRIMARY KEY' - AND tc.table_schema = '\(schemaLiteral)'\(fragments.pkTableFilter) + AND tc.table_schema = \(PostgreSQLObjectQueries.quoteLiteral(schema))\(fragments.pkTableFilter) ) pk ON \(fragments.pkJoin) """ } diff --git a/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift b/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift index f7c7a527d1..7927b87d53 100644 --- a/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift +++ b/Plugins/PostgreSQLDriverPlugin/LibPQDriverCore.swift @@ -203,7 +203,7 @@ final class LibPQDriverCore: @unchecked Sendable { func applyQueryTimeout(_ seconds: Int) async throws { let ms = seconds * 1_000 - _ = try await execute(query: "SET statement_timeout = '\(ms)'") + _ = try await execute(query: "SET statement_timeout = \(ms)") } private func connection() throws -> LibPQPluginConnection { @@ -310,11 +310,12 @@ extension LibPQBackedDriver { var hasLostConnection: Bool { core.hasLostConnection } var parameterStyle: ParameterStyle { .dollar } + /// The PluginKit requirement, whose contract is inner text: the app and the export plugins wrap + /// the result in their own quotes. Nothing in this plugin may build catalog SQL with it, because + /// its correctness rests on `standard_conforming_strings` still being what the last connection + /// message reported. `PostgreSQLObjectQueries.quoteLiteral` needs no such agreement, so every + /// statement this plugin builds goes through that instead. func escapeStringLiteral(_ value: String) -> String { LibPQStringConformance.escape(value, standardConformingStrings: core.standardConformingStrings) } - - func escapeLiteral(_ str: String) -> String { - escapeStringLiteral(str) - } } diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogForeignKeys.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogForeignKeys.swift index 6e00ee739f..bda37195eb 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogForeignKeys.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogForeignKeys.swift @@ -37,7 +37,9 @@ nonisolated enum PostgreSQLCatalogForeignKeys { } } - static func query(schemaLiteral: String, tableLiteral: String, excludesPartitionClones: Bool) -> String { + static func query(schema: String, table: String, excludesPartitionClones: Bool) -> String { + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(schema) + let tableLiteral = PostgreSQLObjectQueries.quoteLiteral(table) let cloneFilter = excludesPartitionClones ? """ AND NOT EXISTS ( @@ -49,7 +51,7 @@ nonisolated enum PostgreSQLCatalogForeignKeys { let branches = Side.allCases.map { side in """ SELECT c.oid, c.conname, ref_ns.nspname, ref_cl.relname, c.confdeltype, c.confupdtype, - c.conkey, c.confkey, '\(side.rawValue)', a.attnum, a.attname + c.conkey, c.confkey, \(PostgreSQLObjectQueries.quoteLiteral(side.rawValue)), a.attnum, a.attname FROM pg_catalog.pg_constraint c JOIN pg_catalog.pg_class cl ON cl.oid = c.conrelid JOIN pg_catalog.pg_namespace ns ON ns.oid = cl.relnamespace diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift index 2ef04833a5..28b7c64a1b 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift @@ -10,20 +10,29 @@ import Foundation import TableProPluginKit public enum PostgreSQLObjectQueries { - public static func escapeLiteral(_ value: String) -> String { - value.replacingOccurrences(of: "'", with: "''") + /// The single owner of literal quoting for every statement this plugin builds, which is why it + /// returns the quotes too: the `E` prefix sits outside them, so a helper that returns inner text + /// for a call site to wrap can never be setting-independent. Measured on PostgreSQL 17.11 with + /// `standard_conforming_strings = off`: a schema named `a\b` listed as `'a\b'` returns no rows, + /// and one named `x\' OR true--` listed that way closes the literal after `x'` and runs + /// `OR true` as SQL, which turned a one-row listing into every relation in the database. + /// + /// Doubling the quote is enough while the value holds no backslash, and the output is then + /// byte-identical to plain quote doubling. With one, the value is written as an `E''` string, + /// where a backslash is always an escape whatever the setting says, and is doubled here. This is + /// what the server's own `quote_literal` emits for the same values. + /// + /// A NUL is dropped rather than escaped. libpq takes a NUL-terminated C string, so a NUL would + /// truncate the statement, and PostgreSQL rejects `\000` in a literal outright ("invalid byte + /// sequence for encoding UTF8"). This matches the PluginKit default's own NUL strip. + public static func quoteLiteral(_ value: String) -> String { + let stripped = value.replacingOccurrences(of: "\0", with: "") + guard stripped.contains("\\") else { return "'\(escapeQuotes(stripped))'" } + return "E'\(escapeQuotes(stripped.replacingOccurrences(of: "\\", with: "\\\\")))'" } - /// A literal that reads the same whatever `standard_conforming_strings` is set to. Doubling the - /// quote is enough while the value has no backslash; with one, a server running the legacy - /// setting would let `\'` swallow a doubled quote and close the literal early, so such a value - /// is written as an `E''` string, where a backslash is always an escape and is doubled here. - public static func quoteLiteral(_ value: String) -> String { - guard value.contains("\\") else { return "'\(escapeLiteral(value))'" } - let escaped = value - .replacingOccurrences(of: "\\", with: "\\\\") - .replacingOccurrences(of: "'", with: "''") - return "E'\(escaped)'" + private static func escapeQuotes(_ value: String) -> String { + value.replacingOccurrences(of: "'", with: "''") } public static func quoteIdentifier(_ name: String) -> String { diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+BulkMetadata.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+BulkMetadata.swift index bc49f251a6..4c309fd9d7 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+BulkMetadata.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+BulkMetadata.swift @@ -35,7 +35,7 @@ extension PostgreSQLPluginDriver { var providesBulkTableMetadataFetch: Bool { true } func fetchAllTableMetadata(schema: String?) async throws -> [String: PluginTableMetadata] { - let schemaLiteral = escapeLiteral(schema ?? core.currentSchema) + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(schema ?? core.currentSchema) let query = """ SELECT c.relname AS table_name, @@ -46,7 +46,7 @@ extension PostgreSQLPluginDriver { obj_description(c.oid, 'pg_class') AS comment FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace - WHERE n.nspname = '\(schemaLiteral)' AND c.relkind IN ('r', 'p', 'm', 'f') + WHERE n.nspname = \(schemaLiteral) AND c.relkind IN ('r', 'p', 'm', 'f') ORDER BY c.relname """ let result = try await execute(query: query) diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+ColumnReorder.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+ColumnReorder.swift index 791a577acd..f3ded63fd9 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+ColumnReorder.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+ColumnReorder.swift @@ -118,28 +118,28 @@ extension PostgreSQLPluginDriver { /// A new identity column starts its sequence at one, so it is wound forward to the rows the /// copy just wrote. Without this the next insert collides with an existing key. /// - /// Both arguments are escaped. A schema or table name may legally contain an apostrophe, - /// and it lands inside a single-quoted literal here. + /// `qualified` is already a quoted identifier pair, and `pg_get_serial_sequence` takes the + /// whole pair as one literal, so it is composed first and quoted once. A schema, table or + /// column name may legally contain an apostrophe or a backslash, and both land inside a + /// literal here. func identityResets(qualified: String, quote: (String) -> String) -> [String] { - identityColumns.map { column in - """ + let relationLiteral = PostgreSQLObjectQueries.quoteLiteral(qualified) + return identityColumns.map { column in + let columnLiteral = PostgreSQLObjectQueries.quoteLiteral(column) + return """ SELECT setval( - pg_get_serial_sequence('\(literal(qualified))', '\(literal(column))'), + pg_get_serial_sequence(\(relationLiteral), \(columnLiteral)), GREATEST(COALESCE((SELECT MAX(\(quote(column))) FROM \(qualified)), 0), 1), true ) """ } } - - private func literal(_ value: String) -> String { - value.replacingOccurrences(of: "'", with: "''") - } } private func fetchRebuildParts(table: String, schema: String) async throws -> RebuildParts { - let safeTable = escapeLiteral(table) - let safeSchema = escapeLiteral(schema) + let tableLiteral = PostgreSQLObjectQueries.quoteLiteral(table) + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(schema) let caps = versionedCapabilities var parts = RebuildParts() @@ -182,7 +182,7 @@ extension PostgreSQLPluginDriver { JOIN pg_class c ON c.oid = a.attrelid JOIN pg_namespace n ON n.oid = c.relnamespace LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = a.attnum - WHERE c.relname = '\(safeTable)' AND n.nspname = '\(safeSchema)' + WHERE c.relname = \(tableLiteral) AND n.nspname = \(schemaLiteral) AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum """).rows @@ -203,7 +203,7 @@ extension PostgreSQLPluginDriver { FROM pg_constraint con JOIN pg_class c ON c.oid = con.conrelid JOIN pg_namespace n ON n.oid = c.relnamespace - WHERE c.relname = '\(safeTable)' AND n.nspname = '\(safeSchema)' + WHERE c.relname = \(tableLiteral) AND n.nspname = \(schemaLiteral) AND con.contype IN ('p', 'u', 'c', 'x') ORDER BY CASE con.contype WHEN 'p' THEN 0 WHEN 'u' THEN 1 ELSE 2 END, con.conname """) @@ -213,7 +213,7 @@ extension PostgreSQLPluginDriver { FROM pg_constraint con JOIN pg_class c ON c.oid = con.conrelid JOIN pg_namespace n ON n.oid = c.relnamespace - WHERE c.relname = '\(safeTable)' AND n.nspname = '\(safeSchema)' AND con.contype = 'f' + WHERE c.relname = \(tableLiteral) AND n.nspname = \(schemaLiteral) AND con.contype = 'f' ORDER BY con.conname """) @@ -226,7 +226,7 @@ extension PostgreSQLPluginDriver { JOIN pg_namespace n ON n.oid = c.relnamespace JOIN pg_class c2 ON c2.oid = con.conrelid JOIN pg_namespace n2 ON n2.oid = c2.relnamespace - WHERE c.relname = '\(safeTable)' AND n.nspname = '\(safeSchema)' AND con.contype = 'f' + WHERE c.relname = \(tableLiteral) AND n.nspname = \(schemaLiteral) AND con.contype = 'f' AND con.conrelid <> con.confrelid ORDER BY con.conname """ @@ -245,12 +245,12 @@ extension PostgreSQLPluginDriver { /// fail on a duplicate name. parts.indexes = try await textRows(""" SELECT indexdef FROM pg_indexes - WHERE tablename = '\(safeTable)' AND schemaname = '\(safeSchema)' + WHERE tablename = \(tableLiteral) AND schemaname = \(schemaLiteral) AND indexname NOT IN ( SELECT con.conname FROM pg_constraint con JOIN pg_class c ON c.oid = con.conrelid JOIN pg_namespace n ON n.oid = c.relnamespace - WHERE c.relname = '\(safeTable)' AND n.nspname = '\(safeSchema)' + WHERE c.relname = \(tableLiteral) AND n.nspname = \(schemaLiteral) ) ORDER BY indexname """) @@ -260,7 +260,7 @@ extension PostgreSQLPluginDriver { FROM pg_trigger t JOIN pg_class c ON c.oid = t.tgrelid JOIN pg_namespace n ON n.oid = c.relnamespace - WHERE c.relname = '\(safeTable)' AND n.nspname = '\(safeSchema)' AND NOT t.tgisinternal + WHERE c.relname = \(tableLiteral) AND n.nspname = \(schemaLiteral) AND NOT t.tgisinternal ORDER BY t.tgname """) @@ -279,7 +279,7 @@ extension PostgreSQLPluginDriver { FROM pg_trigger t JOIN pg_class c ON c.oid = t.tgrelid JOIN pg_namespace n ON n.oid = c.relnamespace - WHERE c.relname = '\(safeTable)' AND n.nspname = '\(safeSchema)' AND NOT t.tgisinternal + WHERE c.relname = \(tableLiteral) AND n.nspname = \(schemaLiteral) AND NOT t.tgisinternal AND t.tgenabled <> 'O' ORDER BY t.tgname """) @@ -296,7 +296,7 @@ extension PostgreSQLPluginDriver { FROM pg_attribute a JOIN pg_class c ON c.oid = a.attrelid JOIN pg_namespace n ON n.oid = c.relnamespace - WHERE c.relname = '\(safeTable)' AND n.nspname = '\(safeSchema)' + WHERE c.relname = \(tableLiteral) AND n.nspname = \(schemaLiteral) AND a.attnum > 0 AND NOT a.attisdropped AND \(caps.hasIdentityColumns ? "a.attidentity = ''" : "true") AND pg_get_serial_sequence( @@ -310,7 +310,7 @@ extension PostgreSQLPluginDriver { || ' IS ' || quote_literal(obj_description(c.oid, 'pg_class')) FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace - WHERE c.relname = '\(safeTable)' AND n.nspname = '\(safeSchema)' + WHERE c.relname = \(tableLiteral) AND n.nspname = \(schemaLiteral) AND obj_description(c.oid, 'pg_class') IS NOT NULL UNION ALL SELECT 'COMMENT ON COLUMN ' || quote_ident(n.nspname) || '.' || quote_ident(c.relname) @@ -319,7 +319,7 @@ extension PostgreSQLPluginDriver { FROM pg_attribute a JOIN pg_class c ON c.oid = a.attrelid JOIN pg_namespace n ON n.oid = c.relnamespace - WHERE c.relname = '\(safeTable)' AND n.nspname = '\(safeSchema)' + WHERE c.relname = \(tableLiteral) AND n.nspname = \(schemaLiteral) AND a.attnum > 0 AND NOT a.attisdropped AND col_description(c.oid, a.attnum) IS NOT NULL """) @@ -332,7 +332,7 @@ extension PostgreSQLPluginDriver { JOIN pg_namespace dn ON dn.oid = dc.relnamespace JOIN pg_class c ON c.oid = d.refobjid JOIN pg_namespace n ON n.oid = c.relnamespace - WHERE c.relname = '\(safeTable)' AND n.nspname = '\(safeSchema)' + WHERE c.relname = \(tableLiteral) AND n.nspname = \(schemaLiteral) AND dc.relkind IN ('v', 'm') AND dc.oid <> c.oid ORDER BY 1 diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift index d84805172f..ba85aae076 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift @@ -8,12 +8,10 @@ import TableProPluginKit extension PostgreSQLPluginDriver { func fetchColumns(table: String, schema: String?) async throws -> [PluginColumnInfo] { - let safeSchema = escapeStringLiteral(schema ?? core.currentSchema) - let safeTable = escapeStringLiteral(table) let catalog = try await fetchTypeCatalog() let query = PostgreSQLSchemaQueries.columnsQuery( - schemaLiteral: safeSchema, - tableLiteral: safeTable, + schema: schema ?? core.currentSchema, + table: table, capabilities: versionedCapabilities, includeMaterializedViews: includesMaterializedViews() ) @@ -24,11 +22,10 @@ extension PostgreSQLPluginDriver { } func fetchAllColumns(schema: String?) async throws -> [String: [PluginColumnInfo]] { - let safeSchema = escapeStringLiteral(schema ?? core.currentSchema) let catalog = try await fetchTypeCatalog() let query = PostgreSQLSchemaQueries.columnsQuery( - schemaLiteral: safeSchema, - tableLiteral: nil, + schema: schema ?? core.currentSchema, + table: nil, capabilities: versionedCapabilities, includeMaterializedViews: includesMaterializedViews() ) diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Principals.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Principals.swift index a22d646375..fec2c9458d 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Principals.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Principals.swift @@ -28,7 +28,7 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { ) async throws -> [PluginPrivilegeScope] { let database = try await currentDatabaseName() let sql = PostgreSQLPrincipalQueries.searchObjects( - patternLiteral: escapeStringLiteral(query), + pattern: query, limit: limit ) let result = try await execute(query: sql) @@ -78,13 +78,13 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { } func fetchGrants(for principal: PluginPrincipalRef) async throws -> [PluginGrantInfo] { - let roleLiteral = escapeStringLiteral(principal.name) + let role = principal.name let database = try await currentDatabaseName() - let databaseGrants = try await fetchDatabaseGrants(roleLiteral: roleLiteral) - let schemaGrants = try await fetchSchemaGrants(roleLiteral: roleLiteral, database: database) - let tableGrants = try await fetchTableGrants(roleLiteral: roleLiteral, database: database) - let columnGrants = try await fetchColumnGrants(roleLiteral: roleLiteral, database: database) + let databaseGrants = try await fetchDatabaseGrants(role: role) + let schemaGrants = try await fetchSchemaGrants(role: role, database: database) + let tableGrants = try await fetchTableGrants(role: role, database: database) + let columnGrants = try await fetchColumnGrants(role: role, database: database) return databaseGrants + schemaGrants + tableGrants + columnGrants } @@ -118,7 +118,7 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { } private func tables(in database: String, schema: String) async throws -> [PluginPrivilegeScope] { - let query = PostgreSQLPrincipalQueries.tables(schemaLiteral: escapeStringLiteral(schema)) + let query = PostgreSQLPrincipalQueries.tables(schema: schema) let result = try await execute(query: query) return result.rows.compactMap { row in guard let table = row[safe: 0]?.asText else { return nil } @@ -132,8 +132,8 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { table: String ) async throws -> [PluginPrivilegeScope] { let query = PostgreSQLPrincipalQueries.columns( - schemaLiteral: escapeStringLiteral(schema), - tableLiteral: escapeStringLiteral(table) + schema: schema, + table: table ) let result = try await execute(query: query) return result.rows.compactMap { row in @@ -142,8 +142,8 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { } } - private func fetchColumnGrants(roleLiteral: String, database: String) async throws -> [PluginGrantInfo] { - let query = PostgreSQLPrincipalQueries.columnGrants(roleLiteral: roleLiteral) + private func fetchColumnGrants(role: String, database: String) async throws -> [PluginGrantInfo] { + let query = PostgreSQLPrincipalQueries.columnGrants(role: role) let result = try await execute(query: query) return result.rows.compactMap { row -> PluginGrantInfo? in guard let schema = row[safe: 0]?.asText, @@ -166,7 +166,7 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { func principalOwnsObjects(_ principal: PluginPrincipalRef) async throws -> Bool { let query = PostgreSQLPrincipalQueries.ownsObjects( - roleLiteral: escapeStringLiteral(principal.name) + role: principal.name ) let result = try await execute(query: query) return PostgreSQLCatalogBoolean.isTrue(result.rows.first?[safe: 0]?.asText) @@ -188,8 +188,8 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { return result.rows.first?[safe: 0]?.asText ?? "" } - private func fetchDatabaseGrants(roleLiteral: String) async throws -> [PluginGrantInfo] { - let query = PostgreSQLPrincipalQueries.databaseGrants(roleLiteral: roleLiteral) + private func fetchDatabaseGrants(role: String) async throws -> [PluginGrantInfo] { + let query = PostgreSQLPrincipalQueries.databaseGrants(role: role) let result = try await execute(query: query) return result.rows.compactMap { row -> PluginGrantInfo? in guard let database = row[safe: 0]?.asText, @@ -202,8 +202,8 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { } } - private func fetchSchemaGrants(roleLiteral: String, database: String) async throws -> [PluginGrantInfo] { - let query = PostgreSQLPrincipalQueries.schemaGrants(roleLiteral: roleLiteral) + private func fetchSchemaGrants(role: String, database: String) async throws -> [PluginGrantInfo] { + let query = PostgreSQLPrincipalQueries.schemaGrants(role: role) let result = try await execute(query: query) return result.rows.compactMap { row -> PluginGrantInfo? in guard let schema = row[safe: 0]?.asText, @@ -216,8 +216,8 @@ extension PostgreSQLPluginDriver: PluginPrincipalManagement { } } - private func fetchTableGrants(roleLiteral: String, database: String) async throws -> [PluginGrantInfo] { - let query = PostgreSQLPrincipalQueries.tableGrants(roleLiteral: roleLiteral) + private func fetchTableGrants(role: String, database: String) async throws -> [PluginGrantInfo] { + let query = PostgreSQLPrincipalQueries.tableGrants(role: role) let result = try await execute(query: query) return result.rows.compactMap { row -> PluginGrantInfo? in guard let schema = row[safe: 0]?.asText, diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+TriggerEditing.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+TriggerEditing.swift index f969299e77..6e8be86845 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+TriggerEditing.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+TriggerEditing.swift @@ -31,9 +31,9 @@ internal extension PostgreSQLPluginDriver { FROM pg_catalog.pg_trigger t JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace - WHERE t.tgname = '\(escapeLiteral(name))' - AND c.relname = '\(escapeLiteral(table))' - AND n.nspname = '\(escapeLiteral(resolvedSchema))' + WHERE t.tgname = \(PostgreSQLObjectQueries.quoteLiteral(name)) + AND c.relname = \(PostgreSQLObjectQueries.quoteLiteral(table)) + AND n.nspname = \(PostgreSQLObjectQueries.quoteLiteral(resolvedSchema)) AND NOT t.tgisinternal LIMIT 1 """ diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift index 31b0cf8037..eeac512846 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift @@ -220,11 +220,10 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { func fetchPartitions(table: String, schema: String?) async throws -> [PluginTableInfo] { guard versionedCapabilities.hasDeclarativePartitioning else { return [] } - let schemaLiteral = escapeLiteral(schema ?? core.currentSchema) let result = try await execute( query: PostgreSQLSchemaQueries.fetchPartitions( - schemaLiteral: schemaLiteral, - tableLiteral: escapeLiteral(table) + schema: schema ?? core.currentSchema, + table: table ) ) return result.rows.compactMap { row -> PluginTableInfo? in @@ -304,7 +303,7 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { let query = """ SELECT reltuples::bigint FROM pg_class - WHERE relname = '\(escapeLiteral(table))' + WHERE relname = \(PostgreSQLObjectQueries.quoteLiteral(table)) AND relnamespace = ( SELECT oid FROM pg_namespace WHERE nspname = current_schema() ) @@ -315,9 +314,9 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { } func fetchTableDDL(table: String, schema: String?) async throws -> String { - let safeTable = escapeLiteral(table) + let tableLiteral = PostgreSQLObjectQueries.quoteLiteral(table) let resolvedSchema = schema ?? core.currentSchema - let schemaLiteral = escapeLiteral(resolvedSchema) + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(resolvedSchema) let quotedTable = quoteIdentifier(table) let caps = versionedCapabilities @@ -364,8 +363,8 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { JOIN pg_class c ON c.oid = a.attrelid JOIN pg_namespace n ON n.oid = c.relnamespace LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = a.attnum - WHERE c.relname = '\(safeTable)' - AND n.nspname = '\(schemaLiteral)' + WHERE c.relname = \(tableLiteral) + AND n.nspname = \(schemaLiteral) AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum @@ -377,8 +376,8 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { FROM pg_constraint con JOIN pg_class c ON c.oid = con.conrelid JOIN pg_namespace n ON n.oid = c.relnamespace - WHERE c.relname = '\(safeTable)' - AND n.nspname = '\(schemaLiteral)' + WHERE c.relname = \(tableLiteral) + AND n.nspname = \(schemaLiteral) AND con.contype IN ('p', 'u', 'c') ORDER BY CASE con.contype WHEN 'p' THEN 0 WHEN 'u' THEN 1 WHEN 'c' THEN 2 END @@ -428,8 +427,8 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { JOIN pg_class c ON c.oid = ix.indrelid JOIN pg_class i ON i.oid = ix.indexrelid JOIN pg_namespace n ON n.oid = c.relnamespace - WHERE c.relname = '\(escapeLiteral(table))' - AND n.nspname = '\(escapeLiteral(schema ?? core.currentSchema))' + WHERE c.relname = \(PostgreSQLObjectQueries.quoteLiteral(table)) + AND n.nspname = \(PostgreSQLObjectQueries.quoteLiteral(schema ?? core.currentSchema)) AND NOT EXISTS ( SELECT 1 FROM pg_constraint con WHERE con.conindid = ix.indexrelid ) @@ -440,7 +439,7 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { } func fetchTableMetadata(table: String, schema: String?) async throws -> PluginTableMetadata { - let schemaLiteral = escapeLiteral(schema ?? core.currentSchema) + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(schema ?? core.currentSchema) let query = """ SELECT pg_total_relation_size(c.oid) AS total_size, @@ -450,8 +449,8 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { obj_description(c.oid, 'pg_class') AS comment FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace - WHERE c.relname = '\(escapeLiteral(table))' - AND n.nspname = '\(schemaLiteral)' + WHERE c.relname = \(PostgreSQLObjectQueries.quoteLiteral(table)) + AND n.nspname = \(schemaLiteral) """ let result = try await execute(query: query) guard let row = result.rows.first else { @@ -486,12 +485,12 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { } func fetchDatabaseMetadata(_ database: String) async throws -> PluginDatabaseMetadata { - let escapedDbLiteral = escapeLiteral(database) + let databaseLiteral = PostgreSQLObjectQueries.quoteLiteral(database) let query = """ SELECT (SELECT COUNT(*) FROM information_schema.tables t - WHERE t.table_catalog = '\(escapedDbLiteral)' + WHERE t.table_catalog = \(databaseLiteral) AND t.table_schema NOT LIKE 'pg!_%' ESCAPE '!' AND t.table_schema <> 'information_schema' AND NOT EXISTS ( @@ -503,7 +502,7 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { WHERE cn.nspname = t.table_schema AND child.relname = t.table_name AND parent.relkind IN ('p', 'I'))), - pg_database_size('\(escapedDbLiteral)') + pg_database_size(\(databaseLiteral)) """ let result = try await execute(query: query) let row = result.rows.first @@ -543,8 +542,8 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { private static let relkindsCreatedByTableDDL = "('r', 'p', 'f')" func fetchDependentTypes(table: String, schema: String?) async throws -> [(name: String, labels: [String])] { - let safeTable = escapeLiteral(table) - let schemaLiteral = escapeLiteral(schema ?? core.currentSchema) + let tableLiteral = PostgreSQLObjectQueries.quoteLiteral(table) + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(schema ?? core.currentSchema) let query = """ SELECT DISTINCT t.typname, array_agg(e.enumlabel ORDER BY e.enumsortorder)::text @@ -553,8 +552,8 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { JOIN pg_namespace n ON n.oid = c.relnamespace JOIN pg_type t ON t.oid = a.atttypid JOIN pg_enum e ON e.enumtypid = t.oid - WHERE c.relname = '\(safeTable)' - AND n.nspname = '\(schemaLiteral)' + WHERE c.relname = \(tableLiteral) + AND n.nspname = \(schemaLiteral) AND c.relkind IN \(Self.relkindsCreatedByTableDDL) AND a.attnum > 0 AND NOT a.attisdropped @@ -665,7 +664,7 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { ) } - var sql = "CREATE DATABASE \(quotedName) ENCODING '\(encoding)'" + var sql = "CREATE DATABASE \(quotedName) ENCODING \(PostgreSQLObjectQueries.quoteLiteral(encoding))" let supportsProvider = versionedCapabilities.hasDatabaseICULocale let provider = supportsProvider ? (request.values["provider"] ?? "libc") : "libc" @@ -689,8 +688,8 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { detail: nil ) } - let escapedCollation = escapeLiteral(collation) - sql += " LC_COLLATE '\(escapedCollation)' LC_CTYPE '\(escapedCollation)'" + let collationLiteral = PostgreSQLObjectQueries.quoteLiteral(collation) + sql += " LC_COLLATE \(collationLiteral) LC_CTYPE \(collationLiteral)" guard let templateDefaults = await templateDefaultsTask else { throw LibPQPluginError( @@ -726,11 +725,11 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { detail: nil ) } - let escapedIcu = escapeLiteral(icuLocale) + let icuLiteral = PostgreSQLObjectQueries.quoteLiteral(icuLocale) if versionedCapabilities.hasModernICUSyntax { - sql += " LOCALE_PROVIDER 'icu' LOCALE '\(escapedIcu)' TEMPLATE template0" + sql += " LOCALE_PROVIDER 'icu' LOCALE \(icuLiteral) TEMPLATE template0" } else { - sql += " LOCALE_PROVIDER 'icu' ICU_LOCALE '\(escapedIcu)' LC_COLLATE 'C' LC_CTYPE 'C' TEMPLATE template0" + sql += " LOCALE_PROVIDER 'icu' ICU_LOCALE \(icuLiteral) LC_COLLATE 'C' LC_CTYPE 'C' TEMPLATE template0" } default: diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPrincipalQueries.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPrincipalQueries.swift index c6fb94fd0a..cd4023fe2d 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPrincipalQueries.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPrincipalQueries.swift @@ -76,14 +76,21 @@ enum PostgreSQLPrincipalQueries { PluginPrivilegeDescriptor(name: "REFERENCES", label: "References", category: structure) ] - static func searchObjects(patternLiteral: String, limit: Int) -> String { + /// The wildcards are wrapped around the pattern before it is quoted, because an `E` prefix + /// cannot be spliced into the middle of a literal: `ILIKE '%' || E'…' || '%'` would be the only + /// alternative, and one literal is simpler to read. + /// + /// LIKE metacharacters in the typed pattern are deliberately left alone and remain a separate + /// defect: a typed `%` still matches anything, and a typed backslash still acts as LIKE's own + /// escape. Quoting fixes which statement runs, not what the pattern means. + static func searchObjects(pattern: String, limit: Int) -> String { """ SELECT n.nspname, c.relname FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('r', 'v', 'm', 'p', 'f') AND n.nspname NOT IN ('pg_catalog', 'information_schema') - AND c.relname ILIKE '%\(patternLiteral)%' + AND c.relname ILIKE \(PostgreSQLObjectQueries.quoteLiteral("%\(pattern)%")) ORDER BY n.nspname, c.relname LIMIT \(max(1, limit)) """ @@ -97,32 +104,32 @@ enum PostgreSQLPrincipalQueries { ORDER BY n.nspname """ - static func tables(schemaLiteral: String) -> String { + static func tables(schema: String) -> String { """ SELECT c.relname FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace - WHERE n.nspname = '\(schemaLiteral)' + WHERE n.nspname = \(PostgreSQLObjectQueries.quoteLiteral(schema)) AND c.relkind IN ('r', 'v', 'm', 'p', 'f') ORDER BY c.relname """ } - static func columns(schemaLiteral: String, tableLiteral: String) -> String { + static func columns(schema: String, table: String) -> String { """ SELECT a.attname FROM pg_attribute a JOIN pg_class c ON c.oid = a.attrelid JOIN pg_namespace n ON n.oid = c.relnamespace - WHERE n.nspname = '\(schemaLiteral)' - AND c.relname = '\(tableLiteral)' + WHERE n.nspname = \(PostgreSQLObjectQueries.quoteLiteral(schema)) + AND c.relname = \(PostgreSQLObjectQueries.quoteLiteral(table)) AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum """ } - static func columnGrants(roleLiteral: String) -> String { + static func columnGrants(role: String) -> String { """ SELECT s.nspname, s.relname, s.attname, (s.acl).privilege_type, (s.acl).is_grantable FROM ( @@ -136,7 +143,7 @@ enum PostgreSQLPrincipalQueries { AND n.nspname NOT IN ('pg_catalog', 'information_schema') ) s JOIN pg_roles r ON r.oid = (s.acl).grantee - WHERE r.rolname = '\(roleLiteral)' + WHERE r.rolname = \(PostgreSQLObjectQueries.quoteLiteral(role)) ORDER BY s.nspname, s.relname, s.attname, (s.acl).privilege_type """ } @@ -168,7 +175,7 @@ enum PostgreSQLPrincipalQueries { ORDER BY member.rolname, grantedRole.rolname """ - static func databaseGrants(roleLiteral: String) -> String { + static func databaseGrants(role: String) -> String { """ SELECT s.datname, (s.acl).privilege_type, (s.acl).is_grantable FROM ( @@ -178,12 +185,12 @@ enum PostgreSQLPrincipalQueries { AND NOT d.datistemplate ) s JOIN pg_roles r ON r.oid = (s.acl).grantee - WHERE r.rolname = '\(roleLiteral)' + WHERE r.rolname = \(PostgreSQLObjectQueries.quoteLiteral(role)) ORDER BY s.datname, (s.acl).privilege_type """ } - static func schemaGrants(roleLiteral: String) -> String { + static func schemaGrants(role: String) -> String { """ SELECT s.nspname, (s.acl).privilege_type, (s.acl).is_grantable FROM ( @@ -193,12 +200,12 @@ enum PostgreSQLPrincipalQueries { AND n.nspname NOT IN ('pg_catalog', 'information_schema') ) s JOIN pg_roles r ON r.oid = (s.acl).grantee - WHERE r.rolname = '\(roleLiteral)' + WHERE r.rolname = \(PostgreSQLObjectQueries.quoteLiteral(role)) ORDER BY s.nspname, (s.acl).privilege_type """ } - static func tableGrants(roleLiteral: String) -> String { + static func tableGrants(role: String) -> String { """ SELECT s.nspname, s.relname, (s.acl).privilege_type, (s.acl).is_grantable FROM ( @@ -210,18 +217,18 @@ enum PostgreSQLPrincipalQueries { AND n.nspname NOT IN ('pg_catalog', 'information_schema') ) s JOIN pg_roles r ON r.oid = (s.acl).grantee - WHERE r.rolname = '\(roleLiteral)' + WHERE r.rolname = \(PostgreSQLObjectQueries.quoteLiteral(role)) ORDER BY s.nspname, s.relname, (s.acl).privilege_type """ } - static func ownsObjects(roleLiteral: String) -> String { + static func ownsObjects(role: String) -> String { """ SELECT EXISTS ( SELECT 1 FROM pg_shdepend s JOIN pg_roles r ON r.oid = s.refobjid - WHERE r.rolname = '\(roleLiteral)' + WHERE r.rolname = \(PostgreSQLObjectQueries.quoteLiteral(role)) AND s.deptype IN ('o', 'a') ) """ diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLSchemaQueries.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLSchemaQueries.swift index 0db4d047c3..7e41070945 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLSchemaQueries.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLSchemaQueries.swift @@ -176,15 +176,15 @@ enum PostgreSQLSchemaQueries { /// `relpartbound` exists only from PostgreSQL 10, so unlike `fetchTables` /// this query cannot be issued against an older server. The caller gates it /// on `PostgreSQLCapabilities.hasDeclarativePartitioning`. - static func fetchPartitions(schemaLiteral: String, tableLiteral: String) -> String { + static func fetchPartitions(schema: String, table: String) -> String { """ SELECT cc.relname, cc.relkind FROM pg_catalog.pg_inherits i JOIN pg_catalog.pg_class parent ON parent.oid = i.inhparent JOIN pg_catalog.pg_namespace pn ON pn.oid = parent.relnamespace JOIN pg_catalog.pg_class cc ON cc.oid = i.inhrelid - WHERE pn.nspname = '\(schemaLiteral)' - AND parent.relname = '\(tableLiteral)' + WHERE pn.nspname = \(PostgreSQLObjectQueries.quoteLiteral(schema)) + AND parent.relname = \(PostgreSQLObjectQueries.quoteLiteral(table)) AND parent.relkind = 'p' ORDER BY pg_catalog.pg_get_expr(cc.relpartbound, cc.oid) = 'DEFAULT', cc.relname """ @@ -271,10 +271,10 @@ enum PostgreSQLSchemaQueries { """ } - /// Column introspection for one schema. Passing `tableLiteral` restricts the result to a single - /// table; passing `nil` returns every table's columns and prefixes each row with `table_name`. - /// `schemaLiteral` is the only schema source, so the caller resolves the target schema - /// (qualified reference, then current schema) before escaping and passing it here. The identity, + /// Column introspection for one schema. Passing `table` restricts the result to a single table; + /// passing `nil` returns every table's columns and prefixes each row with `table_name`. + /// `schema` is the only schema source, so the caller resolves the target schema (qualified + /// reference, then current schema) and passes it raw; quoting happens here. The identity, /// generated, and attribute-join fragments come from the connected server's versioned /// capabilities. /// @@ -287,13 +287,14 @@ enum PostgreSQLSchemaQueries { /// catalog presence rather than on the server version, because a PostgreSQL-compatible engine /// can report a recent version and still have no materialized views (#1383). static func columnsQuery( - schemaLiteral: String, - tableLiteral: String?, + schema: String, + table: String?, capabilities: PostgreSQLCapabilities, includeMaterializedViews: Bool ) -> String { - let shape = ColumnQueryShape.fragments(tableLiteral: tableLiteral) - let includesTableName = tableLiteral == nil + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(schema) + let shape = ColumnQueryShape.fragments(table: table) + let includesTableName = table == nil let identityProjection = capabilities.hasIdentityColumns ? "a.attidentity" : "NULL::text" let generatedProjection = capabilities.hasGeneratedColumns ? "a.attgenerated" : "NULL::text" let generationExpressionProjection = capabilities.hasGeneratedColumns @@ -326,15 +327,15 @@ enum PostgreSQLSchemaQueries { LEFT JOIN pg_catalog.pg_class rel ON rel.relnamespace = relns.oid AND rel.relname = c.table_name\(attributeJoin) - \(ColumnQueryShape.primaryKeyJoin(schemaLiteral: schemaLiteral, fragments: shape)) - WHERE c.table_schema = '\(schemaLiteral)'\(shape.mainTableFilter) + \(ColumnQueryShape.primaryKeyJoin(schema: schema, fragments: shape)) + WHERE c.table_schema = \(schemaLiteral)\(shape.mainTableFilter) """ var arms = [informationSchemaArm] if includeMaterializedViews { arms.append( materializedViewColumnsArm( schemaLiteral: schemaLiteral, - tableLiteral: tableLiteral, + table: table, capabilities: capabilities, includesTableName: includesTableName ) @@ -382,12 +383,12 @@ enum PostgreSQLSchemaQueries { /// materialized view column neither a default nor a constraint. private static func materializedViewColumnsArm( schemaLiteral: String, - tableLiteral: String?, + table: String?, capabilities: PostgreSQLCapabilities, includesTableName: Bool ) -> String { let tableNameProjection = includesTableName ? "mvc.relname AS table_name,\n " : "" - let tableFilter = tableLiteral.map { "\n AND mvc.relname = '\($0)'" } ?? "" + let tableFilter = table.map { "\n AND mvc.relname = \(PostgreSQLObjectQueries.quoteLiteral($0))" } ?? "" let identityProjection = capabilities.hasIdentityColumns ? "mva.attidentity" : "NULL::text" let generatedProjection = capabilities.hasGeneratedColumns ? "mva.attgenerated" : "NULL::text" return """ @@ -427,7 +428,7 @@ enum PostgreSQLSchemaQueries { LEFT JOIN pg_catalog.pg_collation mvco ON mvco.oid = mva.attcollation LEFT JOIN pg_catalog.pg_namespace mvcon ON mvcon.oid = mvco.collnamespace WHERE mvc.relkind = 'm' - AND mvn.nspname = '\(schemaLiteral)'\(tableFilter) + AND mvn.nspname = \(schemaLiteral)\(tableFilter) AND NOT pg_catalog.pg_is_other_temp_schema(mvn.oid) AND (pg_catalog.pg_has_role(mvc.relowner, 'USAGE') OR pg_catalog.has_column_privilege(mvc.oid, mva.attnum, 'SELECT, INSERT, UPDATE, REFERENCES')) diff --git a/Plugins/PostgreSQLDriverPlugin/RedshiftExternalSchemaQueries.swift b/Plugins/PostgreSQLDriverPlugin/RedshiftExternalSchemaQueries.swift index a26217dccb..63d4a1e3d0 100644 --- a/Plugins/PostgreSQLDriverPlugin/RedshiftExternalSchemaQueries.swift +++ b/Plugins/PostgreSQLDriverPlugin/RedshiftExternalSchemaQueries.swift @@ -21,30 +21,30 @@ enum RedshiftExternalSchemaQueries { /// Tables registered in one external schema. Both views carry rows for /// every database on the cluster, so the connected database is part of the - /// filter; two databases can each hold a schema of the same name. Literals - /// are escaped by the caller, matching the convention in + /// filter; two databases can each hold a schema of the same name. Names + /// arrive raw and are quoted here, matching the convention in /// RedshiftSchemaQueries. - static func listExternalTables(schemaLiteral: String, databaseLiteral: String) -> String { + static func listExternalTables(schema: String, database: String) -> String { """ SELECT tablename, tabletype FROM svv_external_tables - WHERE schemaname = '\(schemaLiteral)' - AND redshift_database_name = '\(databaseLiteral)' + WHERE schemaname = \(PostgreSQLObjectQueries.quoteLiteral(schema)) + AND redshift_database_name = \(PostgreSQLObjectQueries.quoteLiteral(database)) ORDER BY tablename """ } - /// Column introspection for one external schema. Passing `tableLiteral` - /// restricts the result to a single table; passing `nil` returns every - /// table's columns and prefixes each row with `tablename`. + /// Column introspection for one external schema. Passing `table` restricts + /// the result to a single table; passing `nil` returns every table's columns + /// and prefixes each row with `tablename`. static func listExternalColumns( - schemaLiteral: String, - tableLiteral: String?, - databaseLiteral: String + schema: String, + table: String?, + database: String ) -> String { - let selectPrefix = tableLiteral == nil ? "tablename,\n " : "" - let tableFilter = tableLiteral.map { " AND tablename = '\($0)'" } ?? "" - let orderBy = tableLiteral == nil ? "tablename, columnnum" : "columnnum" + let selectPrefix = table == nil ? "tablename,\n " : "" + let tableFilter = table.map { " AND tablename = \(PostgreSQLObjectQueries.quoteLiteral($0))" } ?? "" + let orderBy = table == nil ? "tablename, columnnum" : "columnnum" return """ SELECT \(selectPrefix)columnname, @@ -52,8 +52,8 @@ enum RedshiftExternalSchemaQueries { is_nullable, part_key FROM svv_external_columns - WHERE schemaname = '\(schemaLiteral)'\(tableFilter) - AND redshift_database_name = '\(databaseLiteral)' + WHERE schemaname = \(PostgreSQLObjectQueries.quoteLiteral(schema))\(tableFilter) + AND redshift_database_name = \(PostgreSQLObjectQueries.quoteLiteral(database)) ORDER BY \(orderBy) """ } diff --git a/Plugins/PostgreSQLDriverPlugin/RedshiftPluginDriver.swift b/Plugins/PostgreSQLDriverPlugin/RedshiftPluginDriver.swift index a49821e5bc..30ef394303 100644 --- a/Plugins/PostgreSQLDriverPlugin/RedshiftPluginDriver.swift +++ b/Plugins/PostgreSQLDriverPlugin/RedshiftPluginDriver.swift @@ -75,11 +75,11 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { func fetchTables(schema: String?) async throws -> [PluginTableInfo] { let resolvedSchema = schema ?? core.currentSchema - let schemaLiteral = escapeLiteral(resolvedSchema) + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(resolvedSchema) let query = """ SELECT table_name, table_type FROM information_schema.tables - WHERE table_schema = '\(schemaLiteral)' + WHERE table_schema = \(schemaLiteral) ORDER BY table_name """ let result = try await execute(query: query) @@ -92,7 +92,7 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { guard isExternalSchema(resolvedSchema) else { return localTables } - let externalTables = await fetchExternalTables(schemaLiteral: schemaLiteral, schema: resolvedSchema) + let externalTables = await fetchExternalTables(schema: resolvedSchema) guard !externalTables.isEmpty else { return localTables } let localNames = Set(localTables.map(\.name)) @@ -100,12 +100,12 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { return merged.sorted { $0.name.localizedStandardCompare($1.name) == .orderedAscending } } - private func fetchExternalTables(schemaLiteral: String, schema: String) async -> [PluginTableInfo] { + private func fetchExternalTables(schema: String) async -> [PluginTableInfo] { do { let result = try await execute( query: RedshiftExternalSchemaQueries.listExternalTables( - schemaLiteral: schemaLiteral, - databaseLiteral: escapeLiteral(connectedDatabase) + schema: schema, + database: connectedDatabase ) ) return result.rows.compactMap { row -> PluginTableInfo? in @@ -128,27 +128,19 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { func fetchColumns(table: String, schema: String?) async throws -> [PluginColumnInfo] { let resolvedSchema = schema ?? core.currentSchema if isExternalSchema(resolvedSchema) { - let external = await fetchExternalColumns( - schemaLiteral: escapeLiteral(resolvedSchema), - tableLiteral: escapeLiteral(table), - schema: resolvedSchema - ) + let external = await fetchExternalColumns(schema: resolvedSchema, table: table) if !external.isEmpty { return external } } return try await fetchLocalColumns(table: table, schema: resolvedSchema) } - private func fetchExternalColumns( - schemaLiteral: String, - tableLiteral: String, - schema: String - ) async -> [PluginColumnInfo] { + private func fetchExternalColumns(schema: String, table: String) async -> [PluginColumnInfo] { do { let result = try await execute( query: RedshiftExternalSchemaQueries.listExternalColumns( - schemaLiteral: schemaLiteral, - tableLiteral: tableLiteral, - databaseLiteral: escapeLiteral(connectedDatabase) + schema: schema, + table: table, + database: connectedDatabase ) ) return result.rows.compactMap { row -> PluginColumnInfo? in @@ -186,11 +178,7 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { } private func fetchLocalColumns(table: String, schema: String) async throws -> [PluginColumnInfo] { - let schemaLiteral = escapeLiteral(schema) - let query = RedshiftSchemaQueries.columnsQuery( - schemaLiteral: schemaLiteral, - tableLiteral: escapeLiteral(table) - ) + let query = RedshiftSchemaQueries.columnsQuery(schema: schema, table: table) let result = try await execute(query: query) return result.rows.compactMap { row -> PluginColumnInfo? in guard row.count >= 4, @@ -236,25 +224,19 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { func fetchAllColumns(schema: String?) async throws -> [String: [PluginColumnInfo]] { let resolvedSchema = schema ?? core.currentSchema if isExternalSchema(resolvedSchema) { - let external = await fetchExternalAllColumns( - schemaLiteral: escapeLiteral(resolvedSchema), - schema: resolvedSchema - ) + let external = await fetchExternalAllColumns(schema: resolvedSchema) if !external.isEmpty { return external } } return try await fetchLocalAllColumns(schema: resolvedSchema) } - private func fetchExternalAllColumns( - schemaLiteral: String, - schema: String - ) async -> [String: [PluginColumnInfo]] { + private func fetchExternalAllColumns(schema: String) async -> [String: [PluginColumnInfo]] { do { let result = try await execute( query: RedshiftExternalSchemaQueries.listExternalColumns( - schemaLiteral: schemaLiteral, - tableLiteral: nil, - databaseLiteral: escapeLiteral(connectedDatabase) + schema: schema, + table: nil, + database: connectedDatabase ) ) var allColumns: [String: [PluginColumnInfo]] = [:] @@ -277,8 +259,7 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { } private func fetchLocalAllColumns(schema: String) async throws -> [String: [PluginColumnInfo]] { - let schemaLiteral = escapeLiteral(schema) - let query = RedshiftSchemaQueries.columnsQuery(schemaLiteral: schemaLiteral, tableLiteral: nil) + let query = RedshiftSchemaQueries.columnsQuery(schema: schema, table: nil) let result = try await execute(query: query) var allColumns: [String: [PluginColumnInfo]] = [:] for row in result.rows { @@ -326,8 +307,8 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { } func fetchIndexes(table: String, schema: String?) async throws -> [PluginIndexInfo] { - let safeTable = escapeLiteral(table) - let schemaLiteral = escapeLiteral(schema ?? core.currentSchema) + let tableLiteral = PostgreSQLObjectQueries.quoteLiteral(table) + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(schema ?? core.currentSchema) let query = """ SELECT "column", @@ -335,8 +316,8 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { distkey, sortkey FROM pg_table_def - WHERE schemaname = '\(schemaLiteral)' - AND tablename = '\(safeTable)' + WHERE schemaname = \(schemaLiteral) + AND tablename = \(tableLiteral) AND (distkey = true OR sortkey != 0) ORDER BY sortkey """ @@ -366,8 +347,8 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { func fetchForeignKeys(table: String, schema: String?) async throws -> [PluginForeignKeyInfo] { let query = PostgreSQLCatalogForeignKeys.query( - schemaLiteral: PostgreSQLObjectQueries.quoteLiteral(schema ?? core.currentSchema), - tableLiteral: PostgreSQLObjectQueries.quoteLiteral(table), + schema: schema ?? core.currentSchema, + table: table, excludesPartitionClones: PostgreSQLCatalogForeignKeys.excludesPartitionClones( serverVersionNumber: core.serverVersionNumber ) @@ -379,13 +360,13 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { func fetchApproximateRowCount(table: String, schema: String?) async throws -> Int? { let resolvedSchema = schema ?? core.currentSchema guard !isExternalSchema(resolvedSchema) else { return nil } - let safeTable = escapeLiteral(table) - let schemaLiteral = escapeLiteral(resolvedSchema) + let tableLiteral = PostgreSQLObjectQueries.quoteLiteral(table) + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(resolvedSchema) let query = """ SELECT tbl_rows FROM svv_table_info - WHERE "table" = '\(safeTable)' - AND schema = '\(schemaLiteral)' + WHERE "table" = \(tableLiteral) + AND schema = \(schemaLiteral) """ let result = try await execute(query: query) guard let firstRow = result.rows.first, let value = firstRow[0].asText, let count = Int(value) else { return nil } @@ -393,9 +374,9 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { } func fetchTableDDL(table: String, schema: String?) async throws -> String { - let safeTable = escapeLiteral(table) + let tableLiteral = PostgreSQLObjectQueries.quoteLiteral(table) let resolvedSchema = schema ?? core.currentSchema - let schemaLiteral = escapeLiteral(resolvedSchema) + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(resolvedSchema) let quotedTable = quoteIdentifier(table) let quotedSchema = quoteIdentifier(resolvedSchema) @@ -417,8 +398,8 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { JOIN pg_class c ON c.oid = a.attrelid JOIN pg_namespace n ON n.oid = c.relnamespace LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = a.attnum - WHERE c.relname = '\(safeTable)' - AND n.nspname = '\(schemaLiteral)' + WHERE c.relname = \(tableLiteral) + AND n.nspname = \(schemaLiteral) AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum @@ -483,13 +464,13 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { } func fetchViewDefinition(view: String, schema: String?) async throws -> String { - let safeView = escapeLiteral(view) - let schemaLiteral = escapeLiteral(schema ?? core.currentSchema) + let viewLiteral = PostgreSQLObjectQueries.quoteLiteral(view) + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(schema ?? core.currentSchema) let query = """ SELECT 'CREATE OR REPLACE VIEW ' || quote_ident(schemaname) || '.' || quote_ident(viewname) || ' AS ' || E'\\n' || definition AS ddl FROM pg_views - WHERE viewname = '\(safeView)' - AND schemaname = '\(schemaLiteral)' + WHERE viewname = \(viewLiteral) + AND schemaname = \(schemaLiteral) """ let result = try await execute(query: query) guard let firstRow = result.rows.first, let ddl = firstRow[0].asText else { @@ -503,8 +484,8 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { guard !isExternalSchema(resolvedSchema) else { return PluginTableMetadata(tableName: table, engine: "Redshift External") } - let safeTable = escapeLiteral(table) - let schemaLiteral = escapeLiteral(resolvedSchema) + let tableLiteral = PostgreSQLObjectQueries.quoteLiteral(table) + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(resolvedSchema) let query = """ SELECT tbl_rows, @@ -513,8 +494,8 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { unsorted, stats_off FROM svv_table_info - WHERE "table" = '\(safeTable)' - AND schema = '\(schemaLiteral)' + WHERE "table" = \(tableLiteral) + AND schema = \(schemaLiteral) """ let result = try await execute(query: query) guard let row = result.rows.first else { @@ -552,12 +533,12 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { } func fetchDatabaseMetadata(_ database: String) async throws -> PluginDatabaseMetadata { - let escapedDbLiteral = escapeLiteral(database) + let databaseLiteral = PostgreSQLObjectQueries.quoteLiteral(database) let countQuery = """ SELECT COUNT(DISTINCT "table") AS table_count FROM svv_table_info WHERE schema NOT IN ('pg_internal', 'pg_catalog', 'information_schema') - AND database = '\(escapedDbLiteral)' + AND database = \(databaseLiteral) """ let sizeQuery = """ SELECT SUM(size) FROM svv_table_info WHERE database = current_database() @@ -651,7 +632,7 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { // MARK: - All Tables Metadata func allTablesMetadataSQL(schema: String?) -> String? { - let s = schema ?? currentSchema ?? "public" + let schemaLiteral = PostgreSQLObjectQueries.quoteLiteral(schema ?? currentSchema ?? "public") return """ SELECT schema, @@ -663,7 +644,7 @@ final class RedshiftPluginDriver: LibPQBackedDriver, @unchecked Sendable { unsorted, stats_off FROM svv_table_info - WHERE schema = '\(s)' + WHERE schema = \(schemaLiteral) ORDER BY "table" """ } diff --git a/Plugins/PostgreSQLDriverPlugin/RedshiftSchemaQueries.swift b/Plugins/PostgreSQLDriverPlugin/RedshiftSchemaQueries.swift index 98b9b6190c..f081a31dc1 100644 --- a/Plugins/PostgreSQLDriverPlugin/RedshiftSchemaQueries.swift +++ b/Plugins/PostgreSQLDriverPlugin/RedshiftSchemaQueries.swift @@ -10,13 +10,13 @@ import Foundation enum RedshiftSchemaQueries { - /// Column introspection for one schema. Passing `tableLiteral` restricts the - /// result to a single table; passing `nil` returns every table's columns and - /// prefixes each row with `table_name`. `schemaLiteral` is the only schema - /// source, so the caller resolves the target schema (qualified reference, - /// then current schema) before escaping and passing it here. - static func columnsQuery(schemaLiteral: String, tableLiteral: String?) -> String { - let shape = ColumnQueryShape.fragments(tableLiteral: tableLiteral) + /// Column introspection for one schema. Passing `table` restricts the result + /// to a single table; passing `nil` returns every table's columns and prefixes + /// each row with `table_name`. `schema` is the only schema source, so the + /// caller resolves the target schema (qualified reference, then current + /// schema) and passes it raw; quoting happens here. + static func columnsQuery(schema: String, table: String?) -> String { + let shape = ColumnQueryShape.fragments(table: table) return """ SELECT \(shape.selectPrefix)c.column_name, @@ -34,8 +34,8 @@ enum RedshiftSchemaQueries { LEFT JOIN pg_catalog.pg_description pgd ON pgd.objoid = cls.oid AND pgd.objsubid = c.ordinal_position - \(ColumnQueryShape.primaryKeyJoin(schemaLiteral: schemaLiteral, fragments: shape)) - WHERE c.table_schema = '\(schemaLiteral)'\(shape.mainTableFilter) + \(ColumnQueryShape.primaryKeyJoin(schema: schema, fragments: shape)) + WHERE c.table_schema = \(PostgreSQLObjectQueries.quoteLiteral(schema))\(shape.mainTableFilter) ORDER BY \(shape.orderBy) """ } diff --git a/TableProTests/Plugins/PostgreSQLCatalogForeignKeysTests.swift b/TableProTests/Plugins/PostgreSQLCatalogForeignKeysTests.swift index 982e99ba8c..dcff6d5ea9 100644 --- a/TableProTests/Plugins/PostgreSQLCatalogForeignKeysTests.swift +++ b/TableProTests/Plugins/PostgreSQLCatalogForeignKeysTests.swift @@ -136,8 +136,8 @@ struct PostgreSQLCatalogForeignKeysTests { @Test("The query filters on the table's own schema and name and reads both key arrays") func queryFiltersOnSchemaAndTable() { let query = PostgreSQLCatalogForeignKeys.query( - schemaLiteral: "'sales'", - tableLiteral: "'orders'", + schema: "sales", + table: "orders", excludesPartitionClones: true ) #expect(query.contains("ns.nspname = 'sales'")) @@ -150,8 +150,8 @@ struct PostgreSQLCatalogForeignKeysTests { @Test("Both branches project every decoded column") func branchesProjectEveryColumn() { let query = PostgreSQLCatalogForeignKeys.query( - schemaLiteral: "'public'", - tableLiteral: "'t'", + schema: "public", + table: "t", excludesPartitionClones: false ) let branches = query.components(separatedBy: "UNION ALL") @@ -170,13 +170,13 @@ struct PostgreSQLCatalogForeignKeysTests { @Test("A server without conparentid is never sent the clone filter") func cloneFilterOmittedWhenUnsupported() { let filtered = PostgreSQLCatalogForeignKeys.query( - schemaLiteral: "'public'", - tableLiteral: "'t'", + schema: "public", + table: "t", excludesPartitionClones: true ) let plain = PostgreSQLCatalogForeignKeys.query( - schemaLiteral: "'public'", - tableLiteral: "'t'", + schema: "public", + table: "t", excludesPartitionClones: false ) #expect(filtered.contains("parent.oid = c.conparentid")) diff --git a/TableProTests/Plugins/PostgreSQLColumnQueryTests.swift b/TableProTests/Plugins/PostgreSQLColumnQueryTests.swift index 6903d8d643..e22521a508 100644 --- a/TableProTests/Plugins/PostgreSQLColumnQueryTests.swift +++ b/TableProTests/Plugins/PostgreSQLColumnQueryTests.swift @@ -20,8 +20,8 @@ struct PostgreSQLColumnsQueryTests { private func singleTable(schema: String, table: String) -> String { PostgreSQLSchemaQueries.columnsQuery( - schemaLiteral: schema, - tableLiteral: table, + schema: schema, + table: table, capabilities: modern, includeMaterializedViews: true ) @@ -29,8 +29,8 @@ struct PostgreSQLColumnsQueryTests { private func allTables(schema: String) -> String { PostgreSQLSchemaQueries.columnsQuery( - schemaLiteral: schema, - tableLiteral: nil, + schema: schema, + table: nil, capabilities: legacy, includeMaterializedViews: false ) @@ -145,8 +145,8 @@ struct PostgreSQLMaterializedViewColumnsQueryTests { includeMaterializedViews: Bool = true ) -> String { PostgreSQLSchemaQueries.columnsQuery( - schemaLiteral: schema, - tableLiteral: table, + schema: schema, + table: table, capabilities: capabilities ?? modern, includeMaterializedViews: includeMaterializedViews ) @@ -251,7 +251,7 @@ struct PostgreSQLMaterializedViewColumnsQueryTests { struct RedshiftColumnsQueryTests { @Test("single-table query filters on the requested schema and table") func singleTableFiltersOnRequestedSchema() { - let query = RedshiftSchemaQueries.columnsQuery(schemaLiteral: "s2", tableLiteral: "orders") + let query = RedshiftSchemaQueries.columnsQuery(schema: "s2", table: "orders") #expect(query.contains("WHERE c.table_schema = 's2' AND c.table_name = 'orders'")) #expect(query.contains("AND tc.table_schema = 's2'")) #expect(query.contains("AND tc.table_name = 'orders'")) @@ -261,13 +261,13 @@ struct RedshiftColumnsQueryTests { @Test("a non-active schema is not ignored", arguments: ["s2", "analytics", "public"]) func nonActiveSchemaThreadsThrough(schema: String) { - let query = RedshiftSchemaQueries.columnsQuery(schemaLiteral: schema, tableLiteral: "orders") + let query = RedshiftSchemaQueries.columnsQuery(schema: schema, table: "orders") #expect(query.contains("c.table_schema = '\(schema)'")) } @Test("all-tables query selects table_name, drops the table filter, and orders by table") func allTablesProjectsTableName() { - let query = RedshiftSchemaQueries.columnsQuery(schemaLiteral: "s2", tableLiteral: nil) + let query = RedshiftSchemaQueries.columnsQuery(schema: "s2", table: nil) #expect(query.contains("c.table_name,")) #expect(query.contains("WHERE c.table_schema = 's2'")) #expect(!query.contains("c.table_name = '")) @@ -278,7 +278,7 @@ struct RedshiftColumnsQueryTests { @Test("primary key columns are matched to the constraint's own table") func primaryKeyJoinIsTableScoped() { for table in ["orders", nil] { - let query = RedshiftSchemaQueries.columnsQuery(schemaLiteral: "s2", tableLiteral: table) + let query = RedshiftSchemaQueries.columnsQuery(schema: "s2", table: table) #expect(query.contains("AND tc.table_name = kcu.table_name")) } } @@ -286,7 +286,7 @@ struct RedshiftColumnsQueryTests { @Test("Redshift keeps a single-arm read and never names relkind") func redshiftKeepsASingleArmRead() { for table in ["orders", nil] { - let query = RedshiftSchemaQueries.columnsQuery(schemaLiteral: "s2", tableLiteral: table) + let query = RedshiftSchemaQueries.columnsQuery(schema: "s2", table: table) #expect(!query.contains("UNION ALL")) #expect(!query.contains("relkind")) } diff --git a/TableProTests/Plugins/PostgreSQLLegacyCatalogQueryTests.swift b/TableProTests/Plugins/PostgreSQLLegacyCatalogQueryTests.swift index 339254e523..a363995fe7 100644 --- a/TableProTests/Plugins/PostgreSQLLegacyCatalogQueryTests.swift +++ b/TableProTests/Plugins/PostgreSQLLegacyCatalogQueryTests.swift @@ -33,10 +33,10 @@ struct PostgreSQLLegacyCatalogQueryTests { PostgreSQLSchemaQueries.checkConstraintsQuery(schema: "public", table: "t"), PostgreSQLSchemaQueries.collationList(capabilities: legacy), PostgreSQLSchemaQueries.allTablesMetadata(schema: "public"), - PostgreSQLPrincipalQueries.databaseGrants(roleLiteral: "r"), - PostgreSQLPrincipalQueries.schemaGrants(roleLiteral: "r"), - PostgreSQLPrincipalQueries.tableGrants(roleLiteral: "r"), - PostgreSQLPrincipalQueries.columnGrants(roleLiteral: "r"), + PostgreSQLPrincipalQueries.databaseGrants(role: "r"), + PostgreSQLPrincipalQueries.schemaGrants(role: "r"), + PostgreSQLPrincipalQueries.tableGrants(role: "r"), + PostgreSQLPrincipalQueries.columnGrants(role: "r"), PostgreSQLSequenceQueries.sequenceList(schema: "public", dependentOnTable: "orders", source: .sequenceParameters), PostgreSQLSchemaQueries.fetchTables(schema: "public", includeMaterializedViews: true, includeForeignTables: true), PostgreSQLViewDefinition.catalogQuery(name: "v", schema: "public") @@ -382,10 +382,10 @@ struct PostgreSQLGrantQueryTests { @Test("aclexplode runs in a subquery's select list, which PostgreSQL 9.1 accepts") func grantsAvoidLateral() { let queries = [ - PostgreSQLPrincipalQueries.databaseGrants(roleLiteral: "reader"), - PostgreSQLPrincipalQueries.schemaGrants(roleLiteral: "reader"), - PostgreSQLPrincipalQueries.tableGrants(roleLiteral: "reader"), - PostgreSQLPrincipalQueries.columnGrants(roleLiteral: "reader") + PostgreSQLPrincipalQueries.databaseGrants(role: "reader"), + PostgreSQLPrincipalQueries.schemaGrants(role: "reader"), + PostgreSQLPrincipalQueries.tableGrants(role: "reader"), + PostgreSQLPrincipalQueries.columnGrants(role: "reader") ] for sql in queries { #expect(!sql.contains("LATERAL")) diff --git a/TableProTests/Plugins/PostgreSQLLiteralQuotingTests.swift b/TableProTests/Plugins/PostgreSQLLiteralQuotingTests.swift new file mode 100644 index 0000000000..d9af0f9c66 --- /dev/null +++ b/TableProTests/Plugins/PostgreSQLLiteralQuotingTests.swift @@ -0,0 +1,215 @@ +// +// PostgreSQLLiteralQuotingTests.swift +// TableProTests +// + +import Foundation +import Testing + +/// Every catalog statement the PostgreSQL-family plugin builds names objects by literal, and a +/// catalog name may legally hold a backslash. With `standard_conforming_strings = off` a backslash +/// inside a plain literal is an escape, so `'a\b'` does not mean `a\b` and `'x\'' OR true--'` ends +/// after `x'` and leaves `OR true` as SQL. Measured on PostgreSQL 17.11: the first returned no rows +/// for a schema holding one table, the second turned a one-row listing into 417 rows, every relation +/// in the database. +/// +/// `PostgreSQLObjectQueries.quoteLiteral` is the single answer, and these cases pin both halves of +/// it: an `E''` string whenever the value holds a backslash, and output byte-identical to plain +/// quote doubling whenever it does not. +@Suite("PostgreSQL literal quoting") +struct PostgreSQLLiteralQuotingTests { + private static let caps = PostgreSQLCapabilities.assumingModernWhenUnknown(170_000) + + /// Every pure builder in the plugin that names an object by literal, called with one schema and + /// one table so a single assertion covers the lot. Redshift and CockroachDB are included: no + /// server for either was available, and a name with no backslash is byte-identical on both, + /// which is what makes that safe. + private static func statements(schema: String, table: String) -> [String] { + [ + PostgreSQLSchemaQueries.fetchTables( + schema: schema, includeMaterializedViews: true, includeForeignTables: true + ), + PostgreSQLSchemaQueries.fetchPartitions(schema: schema, table: table), + PostgreSQLSchemaQueries.columnsQuery( + schema: schema, table: table, capabilities: caps, includeMaterializedViews: true + ), + PostgreSQLSchemaQueries.checkConstraintsQuery(schema: schema, table: table), + PostgreSQLSchemaQueries.allTablesMetadata(schema: schema), + PostgreSQLObjectQueries.routineList(schema: schema, capabilities: caps), + PostgreSQLObjectQueries.triggerList(schema: schema, table: table), + PostgreSQLObjectQueries.routineDefinitionByName(name: table, schema: schema, arguments: nil), + PostgreSQLObjectQueries.userDefinedTypeList(schema: schema, identity: nil, capabilities: caps), + PostgreSQLIndexQueries.indexList(schema: schema, table: table), + PostgreSQLForeignKeyQueries.foreignKeyList(schema: schema, table: table, capabilities: caps), + PostgreSQLSequenceQueries.sequenceList( + schema: schema, dependentOnTable: table, source: .sequencesView + ), + PostgreSQLCatalogForeignKeys.query(schema: schema, table: table, excludesPartitionClones: true), + PostgreSQLPrincipalQueries.tables(schema: schema), + PostgreSQLPrincipalQueries.columns(schema: schema, table: table), + PostgreSQLPrincipalQueries.databaseGrants(role: schema), + PostgreSQLPrincipalQueries.schemaGrants(role: schema), + PostgreSQLPrincipalQueries.tableGrants(role: schema), + PostgreSQLPrincipalQueries.columnGrants(role: schema), + PostgreSQLPrincipalQueries.ownsObjects(role: schema), + PostgreSQLRelationSQL.concurrentRefreshQuery(name: table, schema: schema), + PostgreSQLViewDefinition.catalogQuery(name: table, schema: schema), + RedshiftSchemaQueries.columnsQuery(schema: schema, table: table), + RedshiftExternalSchemaQueries.listExternalTables(schema: schema, database: table), + RedshiftExternalSchemaQueries.listExternalColumns( + schema: schema, table: table, database: table + ), + ColumnQueryShape.primaryKeyJoin( + schema: schema, fragments: ColumnQueryShape.fragments(table: table) + ) + ] + } + + @Test("A backslash in a catalog name is emitted as an E'' literal") + func backslashNamesBecomeEscapeStrings() { + for statement in Self.statements(schema: #"a\b"#, table: #"c\d"#) { + #expect(statement.contains(#"E'a\\b'"#), "No E-string for the schema in: \(statement)") + #expect(!statement.contains(#"'a\b'"#), "A plain literal survived in: \(statement)") + #expect(!statement.contains(#"'c\d'"#), "A plain literal survived in: \(statement)") + } + } + + @Test("A plain name keeps its plain literal") + func plainNamesStayPlain() { + for statement in Self.statements(schema: "s2", table: "orders") { + #expect(statement.contains("'s2'"), "The schema lost its plain literal in: \(statement)") + } + } + + @Test("An apostrophe in a catalog name is doubled and nothing else") + func apostropheNamesAreDoubled() { + for statement in Self.statements(schema: "o'brien", table: "d'ev") { + #expect(statement.contains("'o''brien'"), "The schema lost its doubled quote in: \(statement)") + #expect(!statement.contains("E'o''brien'"), "An apostrophe took an E-string in: \(statement)") + } + } + + /// The blast-radius guard, stated as the property rather than per call site: for any value + /// holding no backslash, `quoteLiteral` emits exactly what plain quote doubling emitted before + /// this change, so the only statements that move are the ones that were wrong. + @Test("A value without a backslash quotes byte-identically to plain quote doubling") + func quotingIsUnchangedWithoutABackslash() { + let values = ["", "public", "s2", "orders", "o'brien", "''", "%wild_card%", "Ünïcødé", "a\tb"] + for value in values { + let doubled = value.replacingOccurrences(of: "'", with: "''") + #expect(PostgreSQLObjectQueries.quoteLiteral(value) == "'\(doubled)'") + } + } + + /// The injection the probe demonstrated. Quote doubling alone wrote + /// `schemaname = 'x\'' OR true--'`, whose literal ends after `x'` under the legacy setting, so + /// `OR true` ran as SQL and the listing returned every relation in the database. + @Test("A quote after a backslash cannot close the literal") + func quoteAfterBackslashCannotEscape() { + let statement = PostgreSQLSchemaQueries.allTablesMetadata(schema: #"x\' OR true--"#) + #expect(statement.contains(#"E'x\\'' OR true--'"#)) + #expect(!statement.contains(#"'x\'' OR true--'"#)) + #expect(statement.components(separatedBy: "OR true").count == 2) + } + + /// The wildcards go on before the quoting, because an `E` prefix cannot be spliced into the + /// middle of a literal. + @Test("A search pattern is wrapped in its wildcards and then quoted once") + func searchPatternIsQuotedAsAWhole() { + #expect(PostgreSQLPrincipalQueries.searchObjects(pattern: "ord", limit: 10).contains("ILIKE '%ord%'")) + #expect( + PostgreSQLPrincipalQueries.searchObjects(pattern: #"a\b"#, limit: 10) + .contains(#"ILIKE E'%a\\b%'"#) + ) + } + + @Test("A NUL is dropped on both arms rather than reaching libpq") + func nulIsStripped() { + #expect(PostgreSQLObjectQueries.quoteLiteral("a\0b") == "'ab'") + #expect(PostgreSQLObjectQueries.quoteLiteral("a\0\\b") == #"E'a\\b'"#) + #expect(!PostgreSQLSchemaQueries.allTablesMetadata(schema: "a\0b").contains("\0")) + } +} + +/// Nothing at runtime can see a statement that wraps its own quotes around an already-complete +/// literal: `''E'a\\b''` is valid SQL that matches nothing, and a plain `'\(name)'` only misbehaves +/// on a server running the legacy setting. So the guard is a source scan, the same shape +/// `IndexDDLOwnershipTests` and `SyncMapperFieldAccessTests` use. +@Suite("PostgreSQL literal quoting source scan") +struct PostgreSQLLiteralQuotingSourceScanTests { + /// `PostgreSQLObjectQueries` owns the quoting and is the one file allowed to write the quotes + /// itself. `LibPQConnectionString` builds a libpq conninfo string, whose quoting rules are + /// libpq's rather than SQL's. + private static let quotingOwners: Set = [ + "PostgreSQLObjectQueries.swift", + "LibPQConnectionString.swift" + ] + + /// `LibPQDriverCore` carries the `escapeStringLiteral` PluginKit requirement, whose contract is + /// inner text for the app and the export plugins to wrap in their own quotes, and + /// `LibPQStringConformance` implements it. Both read the session's reported + /// `standard_conforming_strings`, so neither may be reached from a statement builder. + private static let escapeHelperOwners: Set = [ + "LibPQDriverCore.swift", + "LibPQStringConformance.swift" + ] + + private static let pluginDirectory: URL? = { + var directory = URL(fileURLWithPath: #filePath) + for _ in 0..<3 { directory.deleteLastPathComponent() } + let plugin = directory + .appendingPathComponent("Plugins") + .appendingPathComponent("PostgreSQLDriverPlugin") + return FileManager.default.fileExists(atPath: plugin.path) ? plugin : nil + }() + + private static func sources() throws -> [(name: String, text: String)] { + guard let pluginDirectory else { return [] } + let files = try FileManager.default.contentsOfDirectory( + at: pluginDirectory, includingPropertiesForKeys: nil) + return try files + .filter { $0.pathExtension == "swift" } + .map { ($0.lastPathComponent, try String(contentsOf: $0, encoding: .utf8)) } + } + + @Test("The scan reaches the plugin sources at all") + func sourcesAreReachable() throws { + let sources = try Self.sources() + #expect(!sources.isEmpty, "No PostgreSQL plugin sources found; the guards below would pass vacuously") + #expect(sources.contains { $0.name == "PostgreSQLObjectQueries.swift" }) + #expect(Self.escapeHelperOwners.isSubset(of: Set(sources.map(\.name)))) + } + + /// A line carrying `message:` is a Swift diagnostic quoting a name for the reader, not SQL. + @Test("No file builds a SQL literal by hand") + func noHandWrittenLiterals() throws { + var offenders: [String] = [] + for source in try Self.sources() where !Self.quotingOwners.contains(source.name) { + for (offset, line) in source.text.components(separatedBy: "\n").enumerated() + where line.contains(#"'\("#) && !line.contains("message:") { + offenders.append("\(source.name):\(offset + 1)") + } + } + + #expect( + offenders.isEmpty, + "These lines quote a literal themselves instead of calling quoteLiteral: \(offenders)" + ) + } + + @Test("No file builds catalog SQL through a session-dependent escape helper") + func noSessionDependentEscapeHelpers() throws { + let helpers = ["escapeLiteral(", "escapeStringLiteral(", "LibPQStringConformance.escape("] + var offenders: [String] = [] + for source in try Self.sources() where !Self.escapeHelperOwners.contains(source.name) { + for helper in helpers where source.text.contains(helper) { + offenders.append("\(source.name): \(helper)") + } + } + + #expect( + offenders.isEmpty, + "These files reach for an escape helper instead of quoteLiteral: \(offenders)" + ) + } +} diff --git a/TableProTests/Plugins/PostgreSQLPartitionFilterTests.swift b/TableProTests/Plugins/PostgreSQLPartitionFilterTests.swift index b4ed54fc60..903e6f0c14 100644 --- a/TableProTests/Plugins/PostgreSQLPartitionFilterTests.swift +++ b/TableProTests/Plugins/PostgreSQLPartitionFilterTests.swift @@ -69,7 +69,7 @@ struct PostgreSQLPartitionFilterTests { @Test("Partition listing is scoped to one parent in one schema") func fetchPartitionsScopesToParent() { - let query = PostgreSQLSchemaQueries.fetchPartitions(schemaLiteral: "public", tableLiteral: "orders") + let query = PostgreSQLSchemaQueries.fetchPartitions(schema: "public", table: "orders") #expect(query.contains("pn.nspname = 'public'")) #expect(query.contains("parent.relname = 'orders'")) #expect(query.contains("parent.relkind = 'p'")) @@ -77,13 +77,13 @@ struct PostgreSQLPartitionFilterTests { @Test("Partition listing sorts the DEFAULT partition last") func fetchPartitionsSortsDefaultLast() { - let query = PostgreSQLSchemaQueries.fetchPartitions(schemaLiteral: "public", tableLiteral: "orders") + let query = PostgreSQLSchemaQueries.fetchPartitions(schema: "public", table: "orders") #expect(query.contains("ORDER BY pg_catalog.pg_get_expr(cc.relpartbound, cc.oid) = 'DEFAULT', cc.relname")) } @Test("Partition listing projects relkind so subpartitioned children stay expandable") func fetchPartitionsProjectsRelkind() { - let query = PostgreSQLSchemaQueries.fetchPartitions(schemaLiteral: "public", tableLiteral: "orders") + let query = PostgreSQLSchemaQueries.fetchPartitions(schema: "public", table: "orders") #expect(query.contains("SELECT cc.relname, cc.relkind")) } } diff --git a/TableProTests/Plugins/PostgreSQLTypeQueryTests.swift b/TableProTests/Plugins/PostgreSQLTypeQueryTests.swift index 4132156878..3fa93767a4 100644 --- a/TableProTests/Plugins/PostgreSQLTypeQueryTests.swift +++ b/TableProTests/Plugins/PostgreSQLTypeQueryTests.swift @@ -116,6 +116,8 @@ struct PostgreSQLTypeQueryTests { #expect(PostgreSQLObjectQueries.quoteLiteral("it's") == "'it''s'") #expect(PostgreSQLObjectQueries.quoteLiteral("back\\slash") == "E'back\\\\slash'") #expect(PostgreSQLObjectQueries.quoteLiteral("\\'; DROP TYPE x; --") == "E'\\\\''; DROP TYPE x; --'") + #expect(PostgreSQLObjectQueries.quoteLiteral("a\0b") == "'ab'") + #expect(PostgreSQLObjectQueries.quoteLiteral("a\0\\b") == "E'a\\\\b'") let sql = PostgreSQLObjectQueries.userDefinedTypeList( schema: "a\\'b", identity: nil, capabilities: .assumingModernWhenUnknown(170_000) diff --git a/TableProTests/Plugins/RedshiftExternalObjectsTests.swift b/TableProTests/Plugins/RedshiftExternalObjectsTests.swift index 9af554c325..fe38f49028 100644 --- a/TableProTests/Plugins/RedshiftExternalObjectsTests.swift +++ b/TableProTests/Plugins/RedshiftExternalObjectsTests.swift @@ -16,16 +16,16 @@ struct RedshiftExternalSchemaQueriesTests { private var allQueries: [String] { [ RedshiftExternalSchemaQueries.listExternalSchemaNames, - RedshiftExternalSchemaQueries.listExternalTables(schemaLiteral: "etl", databaseLiteral: "dev"), + RedshiftExternalSchemaQueries.listExternalTables(schema: "etl", database: "dev"), RedshiftExternalSchemaQueries.listExternalColumns( - schemaLiteral: "etl", - tableLiteral: "customers", - databaseLiteral: "dev" + schema: "etl", + table: "customers", + database: "dev" ), RedshiftExternalSchemaQueries.listExternalColumns( - schemaLiteral: "etl", - tableLiteral: nil, - databaseLiteral: "dev" + schema: "etl", + table: nil, + database: "dev" ), ] } @@ -52,7 +52,7 @@ struct RedshiftExternalSchemaQueriesTests { @Test("table listing filters on the requested schema and orders by name") func tableListingFiltersOnSchema() { - let query = RedshiftExternalSchemaQueries.listExternalTables(schemaLiteral: "etl", databaseLiteral: "dev") + let query = RedshiftExternalSchemaQueries.listExternalTables(schema: "etl", database: "dev") #expect(query.contains("FROM svv_external_tables")) #expect(query.contains("WHERE schemaname = 'etl'")) #expect(query.contains("ORDER BY tablename")) @@ -61,20 +61,20 @@ struct RedshiftExternalSchemaQueriesTests { @Test("every external catalog read is scoped to the connected database") func externalReadsAreScopedToDatabase() { - let tables = RedshiftExternalSchemaQueries.listExternalTables(schemaLiteral: "etl", databaseLiteral: "dev") + let tables = RedshiftExternalSchemaQueries.listExternalTables(schema: "etl", database: "dev") #expect(tables.contains("redshift_database_name = 'dev'")) let single = RedshiftExternalSchemaQueries.listExternalColumns( - schemaLiteral: "etl", - tableLiteral: "customers", - databaseLiteral: "dev" + schema: "etl", + table: "customers", + database: "dev" ) #expect(single.contains("redshift_database_name = 'dev'")) let all = RedshiftExternalSchemaQueries.listExternalColumns( - schemaLiteral: "etl", - tableLiteral: nil, - databaseLiteral: "dev" + schema: "etl", + table: nil, + database: "dev" ) #expect(all.contains("redshift_database_name = 'dev'")) } @@ -82,9 +82,9 @@ struct RedshiftExternalSchemaQueriesTests { @Test("single-table column query filters on the table and orders by column number") func singleTableColumnQuery() { let query = RedshiftExternalSchemaQueries.listExternalColumns( - schemaLiteral: "etl", - tableLiteral: "customers", - databaseLiteral: "dev" + schema: "etl", + table: "customers", + database: "dev" ) #expect(query.contains("FROM svv_external_columns")) #expect(query.contains("WHERE schemaname = 'etl'")) @@ -97,20 +97,20 @@ struct RedshiftExternalSchemaQueriesTests { @Test("all-tables column query prefixes tablename and omits the table filter") func allTablesColumnQuery() { let query = RedshiftExternalSchemaQueries.listExternalColumns( - schemaLiteral: "etl", - tableLiteral: nil, - databaseLiteral: "dev" + schema: "etl", + table: nil, + database: "dev" ) #expect(query.contains("tablename,")) #expect(!query.contains("AND tablename =")) #expect(query.contains("ORDER BY tablename, columnnum")) } - @Test("escaped schema literals reach the generated SQL intact") - func escapedLiteralsAreInterpolated() { + @Test("A raw name with an apostrophe reaches the generated SQL doubled") + func rawNamesAreQuoted() { let query = RedshiftExternalSchemaQueries.listExternalTables( - schemaLiteral: "o''brien", - databaseLiteral: "d''ev" + schema: "o'brien", + database: "d'ev" ) #expect(query.contains("WHERE schemaname = 'o''brien'")) #expect(query.contains("redshift_database_name = 'd''ev'")) diff --git a/scripts/check-postgres-literal-quoting.sh b/scripts/check-postgres-literal-quoting.sh new file mode 100755 index 0000000000..8eb442c027 --- /dev/null +++ b/scripts/check-postgres-literal-quoting.sh @@ -0,0 +1,110 @@ +#!/usr/bin/env bash +# +# Check PostgreSQLObjectQueries.quoteLiteral against a real PostgreSQL server. +# +# A catalog name may legally hold a backslash, and with standard_conforming_strings = off a +# backslash inside a plain literal is an escape. So a name listed as '...' can decode to something +# else, or end the literal early and leave the rest as SQL. Neither shows up in a unit test, because +# both depend on a server setting, and neither raises: the first returns no rows and the second +# returns too many. +# +# This builds a schema for every name shape that matters, runs the literal the plugin now emits +# against a session with the setting off, and compares the row count with the one the plugin +# emitted before the fix. +# +# Usage: +# scripts/check-postgres-literal-quoting.sh [host] [port] [user] +# +# Needs psql and a reachable PostgreSQL the user may create a database on. Exits non-zero when a +# quoted literal does not find exactly the one table its schema holds. + +set -uo pipefail + +HOST="${1:-127.0.0.1}" +PORT="${2:-5432}" +USER_NAME="${3:-postgres}" +SOURCE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift" +DATABASE="tablepro_literal_quoting_check" + +command -v psql > /dev/null || { + echo "psql not found" >&2 + exit 3 +} +[ -f "$SOURCE" ] || { + echo "not found: $SOURCE" >&2 + exit 3 +} + +psql_do() { + psql -X -q -h "$HOST" -p "$PORT" -U "$USER_NAME" -d "$1" -v ON_ERROR_STOP=1 "${@:2}" +} + +if ! psql_do postgres -Atc "SELECT 1" > /dev/null 2>&1; then + echo "no PostgreSQL at $HOST:$PORT as $USER_NAME" >&2 + exit 3 +fi + +grep -qF "E'" "$SOURCE" || { + echo "FAIL: $SOURCE no longer emits an E-string; update this script with the quoting rule" >&2 + exit 1 +} + +VERSION="$(psql_do postgres -Atc "SHOW server_version")" +echo "Checking literal quoting against PostgreSQL $VERSION at $HOST:$PORT" + +psql_do postgres -c "DROP DATABASE IF EXISTS $DATABASE" > /dev/null +psql_do postgres -c "CREATE DATABASE $DATABASE" > /dev/null +trap 'psql -X -q -h "$HOST" -p "$PORT" -U "$USER_NAME" -d postgres -c "DROP DATABASE IF EXISTS $DATABASE" > /dev/null 2>&1' EXIT + +# Each schema holds exactly one table, so a correct literal always answers 1. +# name | plain literal (the old spelling) | E-string (the spelling the plugin now emits) +CASES=( + "plain|'plain'|'plain'" + "o'q|'o''q'|'o''q'" + "a\\b|'a\\b'|E'a\\\\b'" + "x\\' OR true--|'x\\'' OR true--'|E'x\\\\'' OR true--'" + "tail\\|'tail\\'|E'tail\\\\'" +) + +for entry in "${CASES[@]}"; do + name="${entry%%|*}" + psql_do "$DATABASE" -c "CREATE SCHEMA \"${name//\"/\"\"}\"" > /dev/null + psql_do "$DATABASE" -c "CREATE TABLE \"${name//\"/\"\"}\".t1 (id int)" > /dev/null +done + +# Counting relations across the whole database is what makes an early-closed literal visible: a +# predicate the server parsed as OR true answers with every table rather than raising. +count_for() { + PGOPTIONS="-c standard_conforming_strings=off" psql -X -q -A -t \ + -h "$HOST" -p "$PORT" -U "$USER_NAME" -d "$DATABASE" -c " + SELECT count(*) + FROM pg_catalog.pg_class c + JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace + WHERE n.nspname = $1 AND c.relkind IN ('r', 'p', 'm', 'f')" 2> /dev/null +} + +failures=0 +for entry in "${CASES[@]}"; do + rest="${entry#*|}" + name="${entry%%|*}" + plain="${rest%%|*}" + quoted="${rest#*|}" + + before="$(count_for "$plain")" + after="$(count_for "$quoted")" + [ -n "$before" ] || before="error" + + if [ "$after" = "1" ]; then + printf 'ok %-18s before=%-6s after=%s\n' "$name" "$before" "$after" + else + printf 'FAIL %-18s before=%-6s after=%s (expected 1)\n' "$name" "$before" "$after" + failures=$((failures + 1)) + fi +done + +if [ "$failures" -gt 0 ]; then + echo "$failures literal(s) did not find exactly their own schema; see PostgreSQLObjectQueries.quoteLiteral" >&2 + exit 1 +fi + +echo "Every quoted literal found exactly its own schema on PostgreSQL $VERSION with standard_conforming_strings off." From f626098d4b5268b13525ed7ef08eb90906994ee7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Nam=20Long?= Date: Sat, 12 Sep 2026 09:23:57 +0700 Subject: [PATCH 39/54] feat(plugin-weaviate): add Weaviate REST driver (#2742) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(plugin-weaviate): add Weaviate REST driver Co-authored-by: Nguyễn Nam Long * fix(plugin-weaviate): compile JSON display of objects and arrays Co-authored-by: Nguyễn Nam Long * fix(plugin-weaviate): hide built-in credentials and compile Swift 6 fixtures Co-authored-by: Nguyễn Nam Long * fix(plugin-weaviate): reject SQL as REST console and type expect comments Co-authored-by: Nguyễn Nam Long * fix(plugin-weaviate): gate the API key on the auth method and report unsupported filters * fix(plugin-weaviate): write a text cell as text and ping an endpoint that checks the key --------- Co-authored-by: Nguyễn Nam Long Co-authored-by: Ngo Quoc Dat --- .github/plugin-registry.json | 14 + CHANGELOG.md | 1 + Packages/TableProCore/Package.swift | 11 + .../TableProCoreTypes/DatabaseType.swift | 4 +- .../TableProWeaviateCore/WeaviateAuth.swift | 93 +++ .../TableProWeaviateCore/WeaviateError.swift | 57 ++ .../WeaviateFilterBuilder.swift | 309 ++++++++++ .../WeaviateGraphQL.swift | 140 +++++ .../TableProWeaviateCore/WeaviateJSON.swift | 73 +++ .../WeaviateObjectCodec.swift | 141 +++++ .../WeaviatePathEncoding.swift | 28 + .../TableProWeaviateCore/WeaviateQuery.swift | 360 +++++++++++ .../TableProWeaviateCore/WeaviateSchema.swift | 119 ++++ .../Wire/WeaviateClient.swift | 140 +++++ .../Wire/WeaviateTransport.swift | 174 ++++++ .../DatabaseTypeTests.swift | 10 +- .../WeaviateAuthAndQueryTests.swift | 195 ++++++ .../WeaviateClientTests.swift | 279 +++++++++ .../WeaviateFilterAndPathTests.swift | 565 ++++++++++++++++++ .../WeaviateTestSupport.swift | 120 ++++ Plugins/WeaviateDriverPlugin/Info.plist | 14 + .../WeaviateDriverPlugin/WeaviatePlugin.swift | 146 +++++ .../WeaviatePluginDriver+Execution.swift | 202 +++++++ .../WeaviatePluginDriver+Metadata.swift | 215 +++++++ .../WeaviatePluginDriver.swift | 122 ++++ .../weaviate-icon.imageset/Contents.json | 16 + .../weaviate-icon.imageset/weaviate.svg | 1 + ...ginMetadataRegistry+RegistryDefaults.swift | 1 + ...ginMetadataRegistry+WeaviateDefaults.swift | 156 +++++ .../Core/Plugins/PluginMetadataRegistry.swift | 3 +- .../Core/Utilities/SQL/QueryClassifier.swift | 67 +++ TablePro/Models/Connection/DatabaseType.swift | 1 + .../weaviate-icon.imageset/Contents.json | 16 + .../weaviate-icon.imageset/weaviate.svg | 1 + .../weaviate-icon.imageset/Contents.json | 16 + .../weaviate-icon.imageset/weaviate.svg | 1 + .../Helpers/DatabaseTypeStyle.swift | 1 + ...PluginMetadataRegistryTypeCountTests.swift | 10 +- .../SQL/QueryClassifierHardeningTests.swift | 46 ++ .../WeaviateConnectionFieldsTests.swift | 141 +++++ docs/connections/connection-form.mdx | 1 + docs/connections/ssh-tunneling.mdx | 2 +- docs/connections/ssl.mdx | 2 +- docs/databases/index.mdx | 5 +- docs/databases/weaviate.mdx | 132 ++++ docs/docs.json | 3 +- docs/index.mdx | 2 +- docs/snippets/driver-counts.mdx | 4 +- project.yml | 12 +- 49 files changed, 4155 insertions(+), 17 deletions(-) create mode 100644 Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateAuth.swift create mode 100644 Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateError.swift create mode 100644 Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateFilterBuilder.swift create mode 100644 Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateGraphQL.swift create mode 100644 Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateJSON.swift create mode 100644 Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateObjectCodec.swift create mode 100644 Packages/TableProCore/Sources/TableProWeaviateCore/WeaviatePathEncoding.swift create mode 100644 Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateQuery.swift create mode 100644 Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateSchema.swift create mode 100644 Packages/TableProCore/Sources/TableProWeaviateCore/Wire/WeaviateClient.swift create mode 100644 Packages/TableProCore/Sources/TableProWeaviateCore/Wire/WeaviateTransport.swift create mode 100644 Packages/TableProCore/Tests/TableProWeaviateCoreTests/WeaviateAuthAndQueryTests.swift create mode 100644 Packages/TableProCore/Tests/TableProWeaviateCoreTests/WeaviateClientTests.swift create mode 100644 Packages/TableProCore/Tests/TableProWeaviateCoreTests/WeaviateFilterAndPathTests.swift create mode 100644 Packages/TableProCore/Tests/TableProWeaviateCoreTests/WeaviateTestSupport.swift create mode 100644 Plugins/WeaviateDriverPlugin/Info.plist create mode 100644 Plugins/WeaviateDriverPlugin/WeaviatePlugin.swift create mode 100644 Plugins/WeaviateDriverPlugin/WeaviatePluginDriver+Execution.swift create mode 100644 Plugins/WeaviateDriverPlugin/WeaviatePluginDriver+Metadata.swift create mode 100644 Plugins/WeaviateDriverPlugin/WeaviatePluginDriver.swift create mode 100644 TablePro/Assets.xcassets/weaviate-icon.imageset/Contents.json create mode 100644 TablePro/Assets.xcassets/weaviate-icon.imageset/weaviate.svg create mode 100644 TablePro/Core/Plugins/PluginMetadataRegistry+WeaviateDefaults.swift create mode 100644 TableProMobile/TableProMobile/Assets.xcassets/weaviate-icon.imageset/Contents.json create mode 100644 TableProMobile/TableProMobile/Assets.xcassets/weaviate-icon.imageset/weaviate.svg create mode 100644 TableProMobile/TableProWidget/Assets.xcassets/weaviate-icon.imageset/Contents.json create mode 100644 TableProMobile/TableProWidget/Assets.xcassets/weaviate-icon.imageset/weaviate.svg create mode 100644 TableProTests/Plugins/WeaviateConnectionFieldsTests.swift create mode 100644 docs/databases/weaviate.mdx diff --git a/.github/plugin-registry.json b/.github/plugin-registry.json index 2ee21b30d2..89cd97b446 100644 --- a/.github/plugin-registry.json +++ b/.github/plugin-registry.json @@ -415,6 +415,20 @@ "category": "database-driver", "homepage": "https://docs.tablepro.app/databases/typesense" }, + "weaviate": { + "target": "WeaviateDriverPlugin", + "bundleName": "WeaviateDriverPlugin", + "bundleId": "com.TablePro.WeaviateDriverPlugin", + "bundled": false, + "displayName": "Weaviate Driver", + "summary": "Weaviate driver over the REST API with a GraphQL console", + "databaseTypeIds": [ + "Weaviate" + ], + "icon": "weaviate-icon", + "category": "database-driver", + "homepage": "https://docs.tablepro.app/databases/weaviate" + }, "xlsx": { "target": "XLSXExport", "bundleName": "XLSXExport", diff --git a/CHANGELOG.md b/CHANGELOG.md index d0fd462355..3f3ee13933 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Strikethrough on a row queued for deletion, and an underline on a new row or an edited value. - Google Cloud Spanner as a registry plugin over the REST API. (#1226, #2480) +- Weaviate as a registry REST plugin, collections as tables. (#1724) - TiDB and Databend connection types on the MySQL driver. (#1066, #2514) - Empty state in the inspector and the assistant for a connection that is not up. - **Check connections** in Settings > General, including Only when I use the connection. (#2700) diff --git a/Packages/TableProCore/Package.swift b/Packages/TableProCore/Package.swift index 12982aeb23..c853d1efb3 100644 --- a/Packages/TableProCore/Package.swift +++ b/Packages/TableProCore/Package.swift @@ -23,6 +23,7 @@ let package = Package( .library(name: "TableProTrinoCore", targets: ["TableProTrinoCore"]), .library(name: "TableProGoogleCloud", targets: ["TableProGoogleCloud"]), .library(name: "TableProSpannerCore", targets: ["TableProSpannerCore"]), + .library(name: "TableProWeaviateCore", targets: ["TableProWeaviateCore"]), .library(name: "TableProNumberFormatting", targets: ["TableProNumberFormatting"]), .library(name: "TableProR2SQLCore", targets: ["TableProR2SQLCore"]) ], @@ -102,6 +103,11 @@ let package = Package( dependencies: ["TableProGoogleCloud"], path: "Sources/TableProSpannerCore" ), + .target( + name: "TableProWeaviateCore", + dependencies: [], + path: "Sources/TableProWeaviateCore" + ), .target( name: "TableProR2SQLCore", dependencies: [], @@ -162,6 +168,11 @@ let package = Package( dependencies: ["TableProSpannerCore", "TableProGoogleCloud"], path: "Tests/TableProSpannerCoreTests" ), + .testTarget( + name: "TableProWeaviateCoreTests", + dependencies: ["TableProWeaviateCore"], + path: "Tests/TableProWeaviateCoreTests" + ), .testTarget( name: "TableProR2SQLCoreTests", dependencies: ["TableProR2SQLCore"], diff --git a/Packages/TableProCore/Sources/TableProCoreTypes/DatabaseType.swift b/Packages/TableProCore/Sources/TableProCoreTypes/DatabaseType.swift index 211eda5ad6..75a4803a4b 100644 --- a/Packages/TableProCore/Sources/TableProCoreTypes/DatabaseType.swift +++ b/Packages/TableProCore/Sources/TableProCoreTypes/DatabaseType.swift @@ -40,12 +40,13 @@ public struct DatabaseType: Hashable, Codable, Sendable, RawRepresentable { public static let trino = DatabaseType(rawValue: "Trino") public static let kafka = DatabaseType(rawValue: "Kafka") public static let cloudflareR2SQL = DatabaseType(rawValue: "Cloudflare R2 SQL") + public static let weaviate = DatabaseType(rawValue: "Weaviate") public static let allKnownTypes: [DatabaseType] = [ .mysql, .mariadb, .tidb, .databend, .postgresql, .sqlite, .redis, .mongodb, .clickhouse, .mssql, .oracle, .dameng, .duckdb, .cassandra, .redshift, .etcd, .cloudflareD1, .dynamodb, .bigquery, .spanner, .snowflake, .libsql, .beancount, - .surrealdb, .teradata, .trino, .kafka, .cloudflareR2SQL + .surrealdb, .teradata, .trino, .kafka, .cloudflareR2SQL, .weaviate ] /// Icon name for this database type — asset catalog name (e.g. "mysql-icon") or SF Symbol fallback @@ -79,6 +80,7 @@ public struct DatabaseType: Hashable, Codable, Sendable, RawRepresentable { case .trino: return "trino-icon" case .kafka: return "kafka-icon" case .cloudflareR2SQL: return "cloudflare-r2-sql-icon" + case .weaviate: return "weaviate-icon" default: return "externaldrive" } } diff --git a/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateAuth.swift b/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateAuth.swift new file mode 100644 index 0000000000..bf2a74a611 --- /dev/null +++ b/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateAuth.swift @@ -0,0 +1,93 @@ +import Foundation + +public enum WeaviateFieldID { + public static let authMethod = "wvAuthMethod" + public static let apiKey = "wvApiKey" + public static let skipTLSVerify = "wvSkipTLSVerify" +} + +public enum WeaviateAuthMethod: String, Sendable, Equatable { + case none + case apiKey +} + +public struct WeaviateAuth: Sendable, Equatable { + public let method: WeaviateAuthMethod + public let apiKey: String + + public init(method: WeaviateAuthMethod, apiKey: String = "") { + self.method = method + self.apiKey = apiKey.trimmingCharacters(in: .whitespacesAndNewlines) + } + + public static func parse(fields: [String: String]) -> WeaviateAuth { + let raw = fields[WeaviateFieldID.authMethod] ?? WeaviateAuthMethod.none.rawValue + let method = WeaviateAuthMethod(rawValue: raw) ?? .none + return WeaviateAuth(method: method, apiKey: fields[WeaviateFieldID.apiKey] ?? "") + } + + /// A key left in the form after the user switches back to None must not be sent: the form + /// keeps the field's text, and only the method says whether the connection is authenticated. + public var authorizationHeader: String? { + guard method == .apiKey, !apiKey.isEmpty else { return nil } + return "Bearer \(apiKey)" + } +} + +public struct WeaviateConnectionSettings: Sendable, Equatable { + public static let defaultPort = 8_080 + + public let host: String + public let port: Int + public let usesTLS: Bool + public let auth: WeaviateAuth + public let skipTLSVerify: Bool + + public init( + host: String, + port: Int, + usesTLS: Bool, + auth: WeaviateAuth, + skipTLSVerify: Bool + ) { + self.host = host.trimmingCharacters(in: .whitespacesAndNewlines) + self.port = port + self.usesTLS = usesTLS + self.auth = auth + self.skipTLSVerify = skipTLSVerify + } + + public static func parse( + host: String, + port: Int, + usesTLS: Bool, + fields: [String: String] + ) throws -> WeaviateConnectionSettings { + let resolvedHost = host.trimmingCharacters(in: .whitespacesAndNewlines) + let resolvedPort = port > 0 ? port : defaultPort + let skipTLS = fields[WeaviateFieldID.skipTLSVerify] == "true" + let settings = WeaviateConnectionSettings( + host: resolvedHost.isEmpty ? "localhost" : resolvedHost, + port: resolvedPort, + usesTLS: usesTLS, + auth: WeaviateAuth.parse(fields: fields), + skipTLSVerify: skipTLS + ) + _ = try settings.baseURL() + if settings.auth.method == .apiKey, settings.auth.apiKey.isEmpty { + throw WeaviateError.configuration(String(localized: "Enter a Weaviate API key.")) + } + return settings + } + + public func baseURL() throws -> URL { + var components = URLComponents() + components.scheme = usesTLS ? "https" : "http" + components.host = host + components.port = port + guard let url = components.url else { + throw WeaviateError.configuration(String(localized: "The host is not valid in a URL.")) + } + return url + } +} diff --git a/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateError.swift b/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateError.swift new file mode 100644 index 0000000000..854bfa4951 --- /dev/null +++ b/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateError.swift @@ -0,0 +1,57 @@ +import Foundation + +public enum WeaviateError: Error, LocalizedError, Equatable, Sendable { + case configuration(String) + case notConnected + case transport(String) + case authentication(String) + case api(status: Int, message: String) + case malformedResponse(String) + case cancelled + + public var errorDescription: String? { + switch self { + case .configuration(let detail), .transport(let detail), .malformedResponse(let detail): + return detail + case .notConnected: + return String(localized: "Not connected to Weaviate.") + case .authentication(let detail): + return detail + case .api(_, let message): + return message + case .cancelled: + return String(localized: "The request was cancelled.") + } + } + + public static func from(status: Int, body: Data) -> WeaviateError { + let message = apiMessage(from: body) + ?? String(format: String(localized: "Weaviate returned HTTP %d."), status) + if status == 401 || status == 403 { + return .authentication(message) + } + return .api(status: status, message: message) + } + + public static func apiMessage(from body: Data) -> String? { + guard let json = try? JSONSerialization.jsonObject(with: body) else { + let text = String(data: body, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines) + return (text?.isEmpty ?? true) ? nil : text + } + if let object = json as? [String: Any] { + if let errors = object["error"] as? [[String: Any]] { + let messages = errors.compactMap { $0["message"] as? String }.filter { !$0.isEmpty } + if !messages.isEmpty { + return messages.joined(separator: "\n") + } + } + if let error = object["error"] as? String, !error.isEmpty { + return error + } + if let message = object["message"] as? String, !message.isEmpty { + return message + } + } + return nil + } +} diff --git a/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateFilterBuilder.swift b/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateFilterBuilder.swift new file mode 100644 index 0000000000..d9235f1578 --- /dev/null +++ b/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateFilterBuilder.swift @@ -0,0 +1,309 @@ +import Foundation + +public enum WeaviateFilterError: Error, LocalizedError, Equatable { + case unsupportedOperator(String) + case missingUpperBound(column: String) + case notANumber(column: String, value: String) + case notABoolean(column: String, value: String) + case notADate(column: String, value: String) + case emptyList(column: String) + case comparisonNeedsNumberOrDate(column: String, op: String) + case textMatchNeedsText(column: String, op: String) + case vectorNotFilterable(column: String) + + public var errorDescription: String? { + switch self { + case .unsupportedOperator(let op): + return String(format: String(localized: "Weaviate cannot filter with %@."), op) + case .missingUpperBound(let column): + return String(format: String(localized: "BETWEEN on %@ needs an upper bound."), column) + case .notANumber(let column, let value): + return String( + format: String(localized: "%@ is a numeric property, and %@ is not a number."), + column, value + ) + case .notABoolean(let column, let value): + return String( + format: String(localized: "%@ is a boolean property, so it matches only true or false, not %@."), + column, value + ) + case .notADate(let column, let value): + return String( + format: String(localized: "%@ is a date property, and %@ is not an RFC 3339 timestamp such as 2024-01-31T00:00:00Z."), + column, value + ) + case .emptyList(let column): + return String(format: String(localized: "IN on %@ needs at least one value."), column) + case .comparisonNeedsNumberOrDate(let column, let op): + return String( + format: String(localized: "Weaviate compares only numbers and dates with %@, and %@ is neither."), + op, column + ) + case .textMatchNeedsText(let column, let op): + return String( + format: String(localized: "Weaviate matches text with %@, and %@ is not a text property."), + op, column + ) + case .vectorNotFilterable(let column): + return String(format: String(localized: "Weaviate cannot filter on %@."), column) + } + } +} + +/// Weaviate has no array value field: an `int[]` property filters with `valueInt`, so the kind is +/// always the element's. +public enum WeaviateValueKind: String, Sendable, Equatable { + case text + case uuid + case int + case number + case boolean + case date + + public var graphQLField: String { + switch self { + case .text, .uuid: return "valueText" + case .int: return "valueInt" + case .number: return "valueNumber" + case .boolean: return "valueBoolean" + case .date: return "valueDate" + } + } + + public var isOrdered: Bool { + self == .int || self == .number || self == .date + } + + /// `Like` compiles to a regex over the inverted index, which Weaviate only builds for text. + public var acceptsPatternMatch: Bool { + self == .text + } + + public static func forDataType(_ dataType: String) -> WeaviateValueKind { + var name = dataType.trimmingCharacters(in: .whitespaces).lowercased() + while name.hasSuffix("[]") { + name = String(name.dropLast(2)) + } + switch name { + case "int": return .int + case "number": return .number + case "boolean", "bool": return .boolean + case "date": return .date + case "uuid": return .uuid + default: return .text + } + } +} + +public enum WeaviateFilterBuilder { + public static func graphQLWhere( + filters: [WeaviateFilterSpec], + logicMode: String, + types: [String: String] + ) throws -> String? { + guard !filters.isEmpty else { return nil } + let operands = try filters.map { try operand(for: $0, types: types) } + guard operands.count > 1 else { return operands[0] } + let op = logicMode.uppercased() == "OR" ? "Or" : "And" + return "{ operator: \(op) operands: [\(operands.joined(separator: " "))] }" + } + + public static func operand(for filter: WeaviateFilterSpec, types: [String: String]) throws -> String { + let column = filter.column + guard column != WeaviateSchema.vectorColumn else { + throw WeaviateFilterError.vectorNotFilterable(column: column) + } + let path = column == WeaviateSchema.uuidColumn ? WeaviateSchema.uuidGraphQLPath : column + let kind = column == WeaviateSchema.uuidColumn + ? WeaviateValueKind.text + : WeaviateValueKind.forDataType(types[column] ?? "text") + let op = filter.op.uppercased() + + switch op { + case "=": + return try comparison("Equal", path: path, column: column, value: filter.value, kind: kind) + case "!=", "<>": + return try comparison("NotEqual", path: path, column: column, value: filter.value, kind: kind) + case ">", ">=", "<", "<=": + guard kind.isOrdered else { + throw WeaviateFilterError.comparisonNeedsNumberOrDate(column: column, op: op) + } + return try comparison(orderedOperator(op), path: path, column: column, value: filter.value, kind: kind) + case "CONTAINS": + return try like(pattern: "*\(filter.value)*", path: path, column: column, kind: kind, op: op) + case "NOT CONTAINS": + return negated(try like(pattern: "*\(filter.value)*", path: path, column: column, kind: kind, op: op)) + case "STARTS WITH": + return try like(pattern: "\(filter.value)*", path: path, column: column, kind: kind, op: op) + case "ENDS WITH": + return try like(pattern: "*\(filter.value)", path: path, column: column, kind: kind, op: op) + case "IN": + return try containsList("ContainsAny", filter.value, path: path, column: column, kind: kind) + case "NOT IN": + return try containsList("ContainsNone", filter.value, path: path, column: column, kind: kind) + case "BETWEEN": + return try between(filter, path: path, column: column, kind: kind) + case "IS NULL": + return "{ path: [\"\(escape(path))\"] operator: IsNull valueBoolean: true }" + case "IS NOT NULL": + return "{ path: [\"\(escape(path))\"] operator: IsNull valueBoolean: false }" + case "IS EMPTY": + return try emptiness("Equal", path: path, column: column, kind: kind, op: op) + case "IS NOT EMPTY": + return try emptiness("GreaterThan", path: path, column: column, kind: kind, op: op) + default: + throw WeaviateFilterError.unsupportedOperator(op) + } + } + + private static func orderedOperator(_ op: String) -> String { + switch op { + case ">": return "GreaterThan" + case ">=": return "GreaterThanEqual" + case "<": return "LessThan" + default: return "LessThanEqual" + } + } + + private static func comparison( + _ operatorName: String, + path: String, + column: String, + value: String, + kind: WeaviateValueKind + ) throws -> String { + let literal = try literal(value, column: column, kind: kind) + return "{ path: [\"\(escape(path))\"] operator: \(operatorName) \(kind.graphQLField): \(literal) }" + } + + /// Weaviate compiles a `Like` value into a regex over the inverted index. An int, number or + /// date property crashes that compile, and a uuid property is refused outright. + private static func like( + pattern: String, + path: String, + column: String, + kind: WeaviateValueKind, + op: String + ) throws -> String { + guard kind.acceptsPatternMatch else { + throw WeaviateFilterError.textMatchNeedsText(column: column, op: op) + } + return "{ path: [\"\(escape(path))\"] operator: Like valueText: \"\(escape(pattern))\" }" + } + + private static func containsList( + _ operatorName: String, + _ value: String, + path: String, + column: String, + kind: WeaviateValueKind + ) throws -> String { + let parts = value + .split(separator: ",") + .map { $0.trimmingCharacters(in: .whitespaces) } + .filter { !$0.isEmpty } + guard !parts.isEmpty else { + throw WeaviateFilterError.emptyList(column: column) + } + let literals = try parts.map { try literal($0, column: column, kind: kind) } + return "{ path: [\"\(escape(path))\"] operator: \(operatorName) \(kind.graphQLField): [\(literals.joined(separator: ", "))] }" + } + + /// Weaviate has no "is empty": it counts with `len(prop)`, which needs `indexPropertyLength` on + /// the collection and answers with what to turn on when it is off. There is no `len(id)`, and a + /// uuid property has no length either. + private static func emptiness( + _ operatorName: String, + path: String, + column: String, + kind: WeaviateValueKind, + op: String + ) throws -> String { + guard kind == .text, column != WeaviateSchema.uuidColumn else { + throw WeaviateFilterError.textMatchNeedsText(column: column, op: op) + } + return "{ path: [\"len(\(escape(path)))\"] operator: \(operatorName) valueInt: 0 }" + } + + private static func between( + _ filter: WeaviateFilterSpec, + path: String, + column: String, + kind: WeaviateValueKind + ) throws -> String { + guard kind.isOrdered else { + throw WeaviateFilterError.comparisonNeedsNumberOrDate(column: column, op: "BETWEEN") + } + guard let upperBound = filter.secondValue, !upperBound.trimmingCharacters(in: .whitespaces).isEmpty else { + throw WeaviateFilterError.missingUpperBound(column: column) + } + let lower = try comparison( + "GreaterThanEqual", path: path, column: column, value: filter.value, kind: kind + ) + let upper = try comparison( + "LessThanEqual", path: path, column: column, value: upperBound, kind: kind + ) + return "{ operator: And operands: [\(lower) \(upper)] }" + } + + private static func negated(_ operand: String) -> String { + "{ operator: Not operands: [\(operand)] }" + } + + private static func literal(_ value: String, column: String, kind: WeaviateValueKind) throws -> String { + let trimmed = value.trimmingCharacters(in: .whitespaces) + switch kind { + case .text, .uuid: + return "\"\(escape(value))\"" + case .int: + guard let number = Int(trimmed) else { + throw WeaviateFilterError.notANumber(column: column, value: value) + } + return String(number) + case .number: + guard let number = Double(trimmed) else { + throw WeaviateFilterError.notANumber(column: column, value: value) + } + return String(number) + case .boolean: + switch trimmed.lowercased() { + case "true", "1": return "true" + case "false", "0": return "false" + default: throw WeaviateFilterError.notABoolean(column: column, value: value) + } + case .date: + guard WeaviateDateLiteral.isRFC3339(trimmed) else { + throw WeaviateFilterError.notADate(column: column, value: value) + } + return "\"\(escape(trimmed))\"" + } + } + + static func escape(_ value: String) -> String { + var result = "" + result.reserveCapacity(value.count) + for character in value { + switch character { + case "\\": result += "\\\\" + case "\"": result += "\\\"" + case "\n": result += "\\n" + case "\r": result += "\\r" + case "\t": result += "\\t" + default: result.append(character) + } + } + return result + } +} + +/// Weaviate parses a `valueDate` with Go's RFC 3339 layout and answers +/// `trying parse time as RFC3339 string` for anything else, including a bare `2024-01-31`. +public enum WeaviateDateLiteral { + public static func isRFC3339(_ value: String) -> Bool { + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime] + if formatter.date(from: value) != nil { return true } + formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + return formatter.date(from: value) != nil + } +} diff --git a/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateGraphQL.swift b/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateGraphQL.swift new file mode 100644 index 0000000000..0705167481 --- /dev/null +++ b/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateGraphQL.swift @@ -0,0 +1,140 @@ +import Foundation + +public enum WeaviateGraphQL { + public static func getQuery( + collection: String, + properties: [String], + limit: Int, + offset: Int, + sorts: [WeaviateSortSpec], + filters: [WeaviateFilterSpec], + logicMode: String, + schema: [String: WeaviateProperty], + includeVector: Bool = true + ) throws -> String { + let types = schema.mapValues(\.dataType) + let fields = properties + .filter { $0 != WeaviateSchema.uuidColumn && $0 != WeaviateSchema.vectorColumn } + .compactMap { selection(for: $0, schema: schema) } + .joined(separator: " ") + var args: [String] = ["limit: \(max(limit, 0))", "offset: \(max(offset, 0))"] + if let whereClause = try WeaviateFilterBuilder.graphQLWhere( + filters: filters, logicMode: logicMode, types: types + ) { + args.append("where: \(whereClause)") + } + let sortArgs = sorts.compactMap { sort -> String? in + guard let path = sortPath(for: sort) else { return nil } + let order = sort.ascending ? "asc" : "desc" + return "{ path: [\"\(WeaviateFilterBuilder.escape(path))\"] order: \(order) }" + } + if !sortArgs.isEmpty { + args.append("sort: [\(sortArgs.joined(separator: " "))]") + } + let argumentList = args.joined(separator: ", ") + let additional = includeVector ? "id vector" : "id" + return """ + { Get { \(collection)(\(argumentList)) { \(fields) _additional { \(additional) } } } } + """ + } + + /// A structured property needs its own sub-selection, and an `object` with no declared nested + /// properties has nothing to select, so it is left out rather than failing the query. + private static func selection(for name: String, schema: [String: WeaviateProperty]) -> String? { + guard let property = schema[name] else { return name } + switch WeaviatePropertyShape.of(property) { + case .scalar: + return name + case .geoCoordinates: + return "\(name) { latitude longitude }" + case .phoneNumber: + return "\(name) { input internationalFormatted nationalFormatted countryCode national valid defaultCountry }" + case .object: + let nested = property.nestedProperties + .compactMap { selection(for: $0.name, schema: [$0.name: $0]) } + .joined(separator: " ") + return nested.isEmpty ? nil : "\(name) { \(nested) }" + case .crossReference(let targets): + let fragments = targets.map { "... on \($0) { _additional { id } }" }.joined(separator: " ") + return "\(name) { \(fragments) }" + } + } + + /// `vector` is a grid column rather than a property, so Weaviate has nothing to sort on. Every + /// real property is passed through: a type it cannot sort, such as uuid, is reported by the + /// server, which beats painting a sort chevron over rows in insertion order. + private static func sortPath(for sort: WeaviateSortSpec) -> String? { + if sort.column == WeaviateSchema.uuidColumn { + return WeaviateSchema.uuidGraphQLPath + } + return sort.column == WeaviateSchema.vectorColumn ? nil : sort.column + } + + public static func looksLikeGraphQL(_ text: String) -> Bool { + let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines) + if trimmed.hasPrefix("{") { return true } + let lowered = trimmed.lowercased() + return lowered.hasPrefix("query") || lowered.hasPrefix("mutation") || lowered.hasPrefix("subscription") + || lowered.hasPrefix("fragment") + } + + public static func requestBody(query: String) throws -> Data { + let trimmed = query.trimmingCharacters(in: .whitespacesAndNewlines) + if let data = trimmed.data(using: .utf8), + let object = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + object["query"] != nil { + return try WeaviateJSON.data(object) + } + return try WeaviateJSON.data(["query": trimmed]) + } +} + +public struct WeaviateConsoleRequest: Sendable, Equatable { + public let method: String + public let path: String + public let body: String? + + public init(method: String, path: String, body: String?) { + self.method = method + self.path = path + self.body = body + } +} + +public enum WeaviateConsoleParser { + public static func parse(_ input: String) -> WeaviateConsoleRequest? { + let trimmed = input.trimmingCharacters(in: .whitespacesAndNewlines) + guard let newline = trimmed.firstIndex(where: \.isNewline) else { + return parseHeader(trimmed, body: nil) + } + let header = String(trimmed[.. WeaviateConsoleRequest? { + let parts = header.split(maxSplits: 2, omittingEmptySubsequences: true, whereSeparator: \.isWhitespace) + guard parts.count >= 2 else { return nil } + let method = String(parts[0]).uppercased() + guard ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"].contains(method) else { + return nil + } + let rawPath = String(parts[1]) + guard rawPath.hasPrefix("/") else { return nil } + var path = rawPath + if path != "/", path != "/v1", !path.hasPrefix("/v1/"), !path.hasPrefix("/v1?") { + path = "/v1" + path + } + let inlineBody = parts.count > 2 + ? String(parts[2]).trimmingCharacters(in: .whitespacesAndNewlines) + : "" + return WeaviateConsoleRequest( + method: method, + path: path, + body: body ?? (inlineBody.isEmpty ? nil : inlineBody) + ) + } +} diff --git a/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateJSON.swift b/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateJSON.swift new file mode 100644 index 0000000000..6ae697efdb --- /dev/null +++ b/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateJSON.swift @@ -0,0 +1,73 @@ +import Foundation + +public enum WeaviateJSON { + public static func dictionary(_ value: Any?) -> [String: Any]? { + value as? [String: Any] + } + + public static func data(_ object: Any, pretty: Bool = false) throws -> Data { + guard JSONSerialization.isValidJSONObject(object) else { + throw WeaviateError.malformedResponse(String(localized: "Request body is not valid JSON.")) + } + var options: JSONSerialization.WritingOptions = [.sortedKeys] + if pretty { + options.insert(.prettyPrinted) + } + return try JSONSerialization.data(withJSONObject: object, options: options) + } + + public static func text(_ object: Any, pretty: Bool = false) throws -> String { + let encoded = try data(object, pretty: pretty) + return String(data: encoded, encoding: .utf8) ?? "{}" + } + + public static func displayText(_ value: Any?) -> String? { + switch value { + case nil, is NSNull: + return nil + case let text as String: + return text + case let number as NSNumber: + if CFGetTypeID(number) == CFBooleanGetTypeID() { + return number.boolValue ? "true" : "false" + } + return number.stringValue + case let object as [String: Any]: + return (try? text(object)) ?? nil + case let object as [Any]: + return (try? text(object)) ?? nil + default: + return String(describing: value as Any) + } + } + + /// Only a property the grid renders as JSON is parsed back as JSON. Running the parser over + /// every type sends a `text` cell holding `{"a":1}` as an object, which Weaviate rejects while + /// the grid reports the save. + public static func parsedValue(_ text: String, typeName: String) -> Any { + let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines) + let declared = typeName.trimmingCharacters(in: .whitespaces) + let isArray = declared.hasSuffix("[]") + if !isArray { + switch WeaviateValueKind.forDataType(declared) { + case .boolean: + if trimmed.lowercased() == "true" { return true } + if trimmed.lowercased() == "false" { return false } + return text + case .int: + return Int(trimmed) ?? text + case .number: + return Double(trimmed) ?? text + case .text, .uuid, .date: + break + } + } + let shape = WeaviatePropertyShape.of(WeaviateProperty(name: "", dataType: declared)) + guard isArray || shape != .scalar else { return text } + guard let data = trimmed.data(using: .utf8), + let parsed = try? JSONSerialization.jsonObject(with: data), + parsed is [Any] || parsed is [String: Any] + else { return text } + return parsed + } +} diff --git a/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateObjectCodec.swift b/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateObjectCodec.swift new file mode 100644 index 0000000000..d202dfba72 --- /dev/null +++ b/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateObjectCodec.swift @@ -0,0 +1,141 @@ +import Foundation + +public struct WeaviateObject: Sendable, Equatable { + public let uuid: String + public let className: String + public let properties: [String: String?] + public let vector: [Double]? + + public init(uuid: String, className: String, properties: [String: String?], vector: [Double]?) { + self.uuid = uuid + self.className = className + self.properties = properties + self.vector = vector + } + + public static func parse(_ json: [String: Any]) -> WeaviateObject? { + let uuid = (json["id"] as? String) ?? "" + let className = (json["class"] as? String) ?? "" + let raw = json["properties"] as? [String: Any] ?? [:] + var properties: [String: String?] = [:] + for (key, value) in raw { + properties[key] = WeaviateJSON.displayText(value) + } + let vector = vector(from: json["vector"]) + if uuid.isEmpty, properties.isEmpty, vector == nil { + return nil + } + return WeaviateObject(uuid: uuid, className: className, properties: properties, vector: vector) + } + + public static func parseList(_ json: Any) -> [WeaviateObject] { + let objects: [[String: Any]] + if let object = json as? [String: Any] { + objects = object["objects"] as? [[String: Any]] ?? [] + } else if let array = json as? [[String: Any]] { + objects = array + } else { + return [] + } + return objects.compactMap(parse) + } + + public var vectorText: String? { + guard let vector, !vector.isEmpty else { + return vector == nil ? nil : "[]" + } + return "[" + vector.map(Self.numberText).joined(separator: ",") + "]" + } + + private static func numberText(_ value: Double) -> String { + if value.rounded() == value, let whole = Int(exactly: value) { + return String(whole) + } + return String(value) + } + + static func vector(from value: Any?) -> [Double]? { + if let numbers = value as? [Double] { + return numbers + } + if let numbers = value as? [NSNumber] { + return numbers.map(\.doubleValue) + } + return nil + } +} + +public enum WeaviateObjectCodec { + static let additionalKey = "_additional" + + public static func row(for object: WeaviateObject, columns: [String]) -> [String?] { + return columns.map { column in + switch column { + case WeaviateSchema.uuidColumn: + return object.uuid.isEmpty ? nil : object.uuid + case WeaviateSchema.vectorColumn: + return object.vectorText + default: + if let value = object.properties[column] { + return value + } + return nil + } + } + } + + public static func objects(fromGraphQL json: Any) -> [WeaviateObject] { + guard let root = json as? [String: Any] else { return [] } + if let errors = root["errors"] as? [[String: Any]], !errors.isEmpty { + return [] + } + guard let data = root["data"] as? [String: Any] else { return [] } + if let get = data["Get"] as? [String: Any] { + return objects(fromGet: get) + } + return [] + } + + public static func graphQLErrors(from json: Any) -> [String] { + guard let root = json as? [String: Any], + let errors = root["errors"] as? [[String: Any]] + else { return [] } + return errors.compactMap { $0["message"] as? String }.filter { !$0.isEmpty } + } + + private static func objects(fromGet get: [String: Any]) -> [WeaviateObject] { + var result: [WeaviateObject] = [] + for (className, value) in get { + guard let rows = value as? [[String: Any]] else { continue } + for row in rows { + result.append(object(fromGetRow: row, className: className)) + } + } + return result + } + + /// `_additional` is where a vector search puts `distance`, `score` and `certainty`, which are + /// the whole point of the query the user wrote. Only `id` and `vector` have a column of their + /// own; the rest become properties so they reach the grid. + private static func object(fromGetRow row: [String: Any], className: String) -> WeaviateObject { + var properties: [String: String?] = [:] + var additional: [String: Any] = [:] + var uuid = "" + var vector: [Double]? + for (key, value) in row { + if key == additionalKey, let fields = value as? [String: Any] { + additional = fields + continue + } + properties[key] = WeaviateJSON.displayText(value) + } + uuid = (additional["id"] as? String) ?? uuid + vector = WeaviateObject.vector(from: additional["vector"]) + for (key, value) in additional where key != "id" && key != WeaviateSchema.vectorColumn { + let name = properties[key] == nil ? key : "\(additionalKey).\(key)" + properties[name] = WeaviateJSON.displayText(value) + } + return WeaviateObject(uuid: uuid, className: className, properties: properties, vector: vector) + } +} + diff --git a/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviatePathEncoding.swift b/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviatePathEncoding.swift new file mode 100644 index 0000000000..0d6ffcd3c4 --- /dev/null +++ b/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviatePathEncoding.swift @@ -0,0 +1,28 @@ +import Foundation + +public enum WeaviatePathEncoding { + private static let allowed: CharacterSet = { + var set = CharacterSet.alphanumerics + set.insert(charactersIn: "-_") + return set + }() + + public static func segment(_ value: String) -> String { + value.addingPercentEncoding(withAllowedCharacters: allowed) ?? value + } + + /// A console line carries its own query string (`GET /v1/objects?class=Article`), so the path + /// is parsed rather than assigned whole: `URLComponents.path` percent-encodes `?` into `%3F` + /// and sends the request to a path that does not exist. + public static func resolve(_ path: String, query: [String: String] = [:], against base: URL) -> URL? { + guard path.hasPrefix("/"), !path.contains("://") else { return nil } + guard var components = URLComponents(url: base, resolvingAgainstBaseURL: false), + let requested = URLComponents(string: path) + else { return nil } + components.percentEncodedPath = requested.percentEncodedPath + var items = requested.queryItems ?? [] + items += query.keys.sorted().map { URLQueryItem(name: $0, value: query[$0]) } + components.queryItems = items.isEmpty ? nil : items + return components.url + } +} diff --git a/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateQuery.swift b/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateQuery.swift new file mode 100644 index 0000000000..773b8cf34d --- /dev/null +++ b/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateQuery.swift @@ -0,0 +1,360 @@ +import Foundation + +public struct WeaviateFilterSpec: Codable, Sendable, Equatable { + public let column: String + public let op: String + public let value: String + + /// The upper bound of `BETWEEN`, carried apart from `value` so a value holding a comma cannot + /// be mistaken for the separator between the two bounds. + public let secondValue: String? + + public init(column: String, op: String, value: String, secondValue: String? = nil) { + self.column = column + self.op = op + self.value = value + self.secondValue = secondValue + } +} + +public struct WeaviateSortSpec: Codable, Sendable, Equatable { + public let column: String + public let ascending: Bool + + public init(column: String, ascending: Bool) { + self.column = column + self.ascending = ascending + } +} + +public struct WeaviateParsedSearch: Sendable, Equatable { + public let collection: String + public let offset: Int + public let limit: Int + public let sorts: [WeaviateSortSpec] + public let filters: [WeaviateFilterSpec] + public let logicMode: String + public let propertyNames: [String] + + public init( + collection: String, + offset: Int, + limit: Int, + sorts: [WeaviateSortSpec], + filters: [WeaviateFilterSpec], + logicMode: String, + propertyNames: [String] + ) { + self.collection = collection + self.offset = offset + self.limit = limit + self.sorts = sorts + self.filters = filters + self.logicMode = logicMode + self.propertyNames = propertyNames + } + + /// `GET /v1/objects` sorts, but only on a property: the grid's `vector` column is not one, and + /// Weaviate answers `no such prop with name 'vector'`. Everything else goes through GraphQL, + /// whose `sort` argument takes the object id as well. + public var sortableSorts: [WeaviateSortSpec] { + sorts.filter { $0.column != WeaviateSchema.vectorColumn } + } + + public var usesGraphQL: Bool { + !filters.isEmpty || !sortableSorts.isEmpty + } +} + +public enum WeaviateBrowseQuery { + public static let searchTag = "WEAVIATE_SEARCH:" + + public static func encode( + collection: String, + offset: Int, + limit: Int, + sorts: [WeaviateSortSpec], + filters: [WeaviateFilterSpec], + logicMode: String, + propertyNames: [String] + ) -> String { + let payload: [String: Any] = [ + "collection": collection, + "offset": offset, + "limit": limit, + "logicMode": logicMode, + "sorts": sorts.map { ["column": $0.column, "ascending": $0.ascending] }, + "filters": filters.map { filter -> [String: Any] in + var encoded: [String: Any] = ["column": filter.column, "op": filter.op, "value": filter.value] + if let secondValue = filter.secondValue { + encoded["secondValue"] = secondValue + } + return encoded + }, + "properties": propertyNames + ] + let body = (try? WeaviateJSON.data(payload)) ?? Data() + return searchTag + body.base64EncodedString() + } + + public static func parse(_ query: String) -> WeaviateParsedSearch? { + guard query.hasPrefix(searchTag) else { return nil } + let encoded = String(query.dropFirst(searchTag.count)) + guard let data = Data(base64Encoded: encoded), + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + let collection = json["collection"] as? String + else { return nil } + let sortsJSON = json["sorts"] as? [[String: Any]] ?? [] + let filtersJSON = json["filters"] as? [[String: Any]] ?? [] + let properties = json["properties"] as? [String] ?? [] + return WeaviateParsedSearch( + collection: collection, + offset: json["offset"] as? Int ?? 0, + limit: json["limit"] as? Int ?? 25, + sorts: sortsJSON.compactMap { item in + guard let column = item["column"] as? String else { return nil } + return WeaviateSortSpec(column: column, ascending: item["ascending"] as? Bool ?? true) + }, + filters: filtersJSON.compactMap { item in + guard let column = item["column"] as? String, let op = item["op"] as? String else { + return nil + } + return WeaviateFilterSpec( + column: column, + op: op, + value: item["value"] as? String ?? "", + secondValue: item["secondValue"] as? String + ) + }, + logicMode: json["logicMode"] as? String ?? "AND", + propertyNames: properties + ) + } + + public static func isTagged(_ query: String) -> Bool { + query.hasPrefix(searchTag) + } +} + +public struct WeaviateWriteRequest: Sendable, Equatable { + public let method: String + public let path: String + public let query: [String: String] + public let body: String? + + public init(method: String, path: String, query: [String: String] = [:], body: String?) { + self.method = method + self.path = path + self.query = query + self.body = body + } +} + +public enum WeaviateWriteCodec { + public static let writeTag = "WEAVIATE_WRITE:" + + public static func encode(_ request: WeaviateWriteRequest) -> String { + let payload: [String: Any] = [ + "method": request.method, + "path": request.path, + "query": request.query, + "body": request.body ?? "" + ] + let data = (try? WeaviateJSON.data(payload)) ?? Data() + return writeTag + data.base64EncodedString() + } + + public static func decode(_ statement: String) -> WeaviateWriteRequest? { + guard statement.hasPrefix(writeTag) else { return nil } + let encoded = String(statement.dropFirst(writeTag.count)) + guard let data = Data(base64Encoded: encoded), + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + let method = json["method"] as? String, + let path = json["path"] as? String + else { return nil } + let query = json["query"] as? [String: String] ?? [:] + let body = json["body"] as? String + return WeaviateWriteRequest( + method: method, + path: path, + query: query, + body: (body?.isEmpty ?? true) ? nil : body + ) + } + + public static func isTagged(_ statement: String) -> Bool { + statement.hasPrefix(writeTag) + } +} + +public struct WeaviateCellChange: Sendable, Equatable { + public let column: String + public let newText: String? + + public init(column: String, newText: String?) { + self.column = column + self.newText = newText + } +} + +public struct WeaviateTrackedChange: Sendable, Equatable { + public enum Kind: String, Sendable, Equatable { + case insert + case update + case delete + } + + public let kind: Kind + public let uuid: String? + public let values: [String: String?] + public let cellChanges: [WeaviateCellChange] + + public init( + kind: Kind, + uuid: String?, + values: [String: String?], + cellChanges: [WeaviateCellChange] + ) { + self.kind = kind + self.uuid = uuid + self.values = values + self.cellChanges = cellChanges + } +} + +public enum WeaviateSkipReason: String, Sendable, Equatable { + case missingUUID + case noEditableColumns + case payloadNotEncodable +} + +public struct WeaviateSkippedChange: Sendable, Equatable { + public let kind: WeaviateTrackedChange.Kind + public let reason: WeaviateSkipReason + + public init(kind: WeaviateTrackedChange.Kind, reason: WeaviateSkipReason) { + self.kind = kind + self.reason = reason + } +} + +/// A skipped change writes nothing while the grid reports the save succeeded, so the driver has to +/// be able to say what it dropped. Same reason the MongoDB generator logs its own skips. +public struct WeaviateWriteBatch: Sendable, Equatable { + public let requests: [WeaviateWriteRequest] + public let skipped: [WeaviateSkippedChange] + + public init(requests: [WeaviateWriteRequest], skipped: [WeaviateSkippedChange]) { + self.requests = requests + self.skipped = skipped + } +} + +public enum WeaviateStatementGenerator { + public static func generate( + collection: String, + columns: [String], + typeNames: [String], + changes: [WeaviateTrackedChange] + ) -> WeaviateWriteBatch { + let types = Dictionary(zip(columns, typeNames), uniquingKeysWith: { first, _ in first }) + var requests: [WeaviateWriteRequest] = [] + var skipped: [WeaviateSkippedChange] = [] + for change in changes { + let request: WeaviateWriteRequest? + switch change.kind { + case .insert: + request = insert(collection: collection, types: types, change: change) + case .update: + request = update(collection: collection, types: types, change: change) + case .delete: + request = delete(collection: collection, change: change) + } + if let request { + requests.append(request) + } else { + skipped.append(WeaviateSkippedChange(kind: change.kind, reason: reason(for: change))) + } + } + return WeaviateWriteBatch(requests: requests, skipped: skipped) + } + + private static func reason(for change: WeaviateTrackedChange) -> WeaviateSkipReason { + if change.kind != .insert, change.uuid?.isEmpty ?? true { + return .missingUUID + } + if change.kind == .update, editablePatch(from: change).isEmpty { + return .noEditableColumns + } + return .payloadNotEncodable + } + + private static func editablePatch(from change: WeaviateTrackedChange) -> [String: String?] { + var patch: [String: String?] = [:] + for cell in change.cellChanges where !WeaviateSchema.immutableColumns.contains(cell.column) { + patch[cell.column] = cell.newText + } + return patch + } + + private static func insert( + collection: String, + types: [String: String], + change: WeaviateTrackedChange + ) -> WeaviateWriteRequest? { + var payload: [String: Any] = [ + "class": collection, + "properties": properties(from: change.values, types: types) + ] + if let uuid = change.uuid, !uuid.isEmpty { + payload["id"] = uuid + } + guard let body = try? WeaviateJSON.text(payload) else { return nil } + return WeaviateWriteRequest(method: "POST", path: "/v1/objects", body: body) + } + + private static func update( + collection: String, + types: [String: String], + change: WeaviateTrackedChange + ) -> WeaviateWriteRequest? { + guard let uuid = change.uuid, !uuid.isEmpty else { return nil } + let patch = editablePatch(from: change) + guard !patch.isEmpty else { return nil } + let payload: [String: Any] = [ + "class": collection, + "properties": properties(from: patch, types: types) + ] + guard let body = try? WeaviateJSON.text(payload) else { return nil } + return WeaviateWriteRequest( + method: "PATCH", + path: "/v1/objects/\(WeaviatePathEncoding.segment(uuid))", + query: ["class": collection], + body: body + ) + } + + private static func delete(collection: String, change: WeaviateTrackedChange) -> WeaviateWriteRequest? { + guard let uuid = change.uuid, !uuid.isEmpty else { return nil } + return WeaviateWriteRequest( + method: "DELETE", + path: "/v1/objects/\(WeaviatePathEncoding.segment(uuid))", + query: ["class": collection], + body: nil + ) + } + + private static func properties(from values: [String: String?], types: [String: String]) -> [String: Any] { + var result: [String: Any] = [:] + for (column, text) in values { + if WeaviateSchema.immutableColumns.contains(column) { continue } + if column.hasPrefix("\(WeaviateObjectCodec.additionalKey).") { continue } + if let text { + result[column] = WeaviateJSON.parsedValue(text, typeName: types[column] ?? "text") + } else { + result[column] = NSNull() + } + } + return result + } +} diff --git a/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateSchema.swift b/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateSchema.swift new file mode 100644 index 0000000000..b1478e6ec8 --- /dev/null +++ b/Packages/TableProCore/Sources/TableProWeaviateCore/WeaviateSchema.swift @@ -0,0 +1,119 @@ +import Foundation + +public struct WeaviateProperty: Sendable, Equatable { + public let name: String + public let dataTypes: [String] + public let nestedProperties: [WeaviateProperty] + + public var dataType: String { dataTypes.first ?? "text" } + + public init(name: String, dataType: String) { + self.init(name: name, dataTypes: [dataType], nestedProperties: []) + } + + public init(name: String, dataTypes: [String], nestedProperties: [WeaviateProperty]) { + self.name = name + self.dataTypes = dataTypes.isEmpty ? ["text"] : dataTypes + self.nestedProperties = nestedProperties + } + + public static func parse(_ json: [String: Any]) -> WeaviateProperty? { + guard let name = json["name"] as? String, !name.isEmpty else { return nil } + let nested = json["nestedProperties"] as? [[String: Any]] ?? [] + return WeaviateProperty( + name: name, + dataTypes: json["dataType"] as? [String] ?? [], + nestedProperties: nested.compactMap(WeaviateProperty.parse) + ) + } +} + +/// A GraphQL field with a structured type is refused without a sub-selection: asking for a +/// `geoCoordinates` property by name answers `Field "place" ... must have a sub selection` and the +/// whole query fails, taking the filtered browse with it. +public enum WeaviatePropertyShape: Sendable, Equatable { + case scalar + case geoCoordinates + case phoneNumber + case object + case crossReference([String]) + + private static let scalarTypes: Set = [ + "text", "string", "int", "number", "boolean", "bool", "date", "uuid", "blob" + ] + + public static func of(_ property: WeaviateProperty) -> WeaviatePropertyShape { + let names = property.dataTypes.map { element($0) } + guard let first = names.first else { return .scalar } + if scalarTypes.contains(first.lowercased()) { return .scalar } + switch first { + case "geoCoordinates": return .geoCoordinates + case "phoneNumber": return .phoneNumber + case "object": return .object + default: + return first.first?.isUppercase == true ? .crossReference(names) : .scalar + } + } + + private static func element(_ dataType: String) -> String { + var name = dataType.trimmingCharacters(in: .whitespaces) + while name.hasSuffix("[]") { + name = String(name.dropLast(2)) + } + return name + } +} + +public struct WeaviateCollection: Sendable, Equatable { + public let name: String + public let properties: [WeaviateProperty] + public let vectorizer: String? + + public init(name: String, properties: [WeaviateProperty], vectorizer: String? = nil) { + self.name = name + self.properties = properties + self.vectorizer = vectorizer + } + + public static func parse(_ json: [String: Any]) -> WeaviateCollection? { + guard let name = json["class"] as? String, !name.isEmpty else { return nil } + let rawProperties = json["properties"] as? [[String: Any]] ?? [] + let properties = rawProperties.compactMap(WeaviateProperty.parse) + return WeaviateCollection( + name: name, + properties: properties, + vectorizer: json["vectorizer"] as? String + ) + } +} + +public enum WeaviateSchema { + public static let uuidColumn = "uuid" + public static let vectorColumn = "vector" + public static let immutableColumns: [String] = [uuidColumn, vectorColumn] + + /// Weaviate names the object id `id` inside a `where` or `sort` argument, and normalizes it to + /// `_id` in its own errors. The grid calls the same column `uuid`. + public static let uuidGraphQLPath = "id" + + public static func collections(from json: Any) -> [WeaviateCollection] { + let classes: [[String: Any]] + if let object = json as? [String: Any] { + classes = object["classes"] as? [[String: Any]] ?? [] + } else if let array = json as? [[String: Any]] { + classes = array + } else { + return [] + } + return classes.compactMap(WeaviateCollection.parse) + } + + public static func columns(for collection: WeaviateCollection) -> [(name: String, type: String, isPrimaryKey: Bool)] { + var result: [(name: String, type: String, isPrimaryKey: Bool)] = [ + (uuidColumn, "uuid", true) + ] + result += collection.properties.map { ($0.name, $0.dataType, false) } + result.append((vectorColumn, "vector", false)) + return result + } +} diff --git a/Packages/TableProCore/Sources/TableProWeaviateCore/Wire/WeaviateClient.swift b/Packages/TableProCore/Sources/TableProWeaviateCore/Wire/WeaviateClient.swift new file mode 100644 index 0000000000..cb56e8146b --- /dev/null +++ b/Packages/TableProCore/Sources/TableProWeaviateCore/Wire/WeaviateClient.swift @@ -0,0 +1,140 @@ +import Foundation + +public final class WeaviateClient: @unchecked Sendable { + public let settings: WeaviateConnectionSettings + private let transport: WeaviateTransport + private let timeout: @Sendable () -> TimeInterval + private let lock = NSLock() + private var _version: String? + + public init( + settings: WeaviateConnectionSettings, + transport: WeaviateTransport, + timeout: @escaping @Sendable () -> TimeInterval + ) { + self.settings = settings + self.transport = transport + self.timeout = timeout + } + + public var serverVersion: String? { + lock.withLock { _version } + } + + public func cancelAll() { + transport.cancelAll() + } + + public func connect() async throws { + let ready = try await send(method: "GET", path: "/v1/.well-known/ready") + try throwIfFailed(ready) + let meta = try await send(method: "GET", path: "/v1/meta") + try throwIfFailed(meta) + if let json = WeaviateJSON.dictionary(meta.json), let version = json["version"] as? String { + lock.withLock { _version = version } + } + } + + /// `/v1/.well-known/ready` is the readiness probe and answers 200 with no key at all, so a + /// revoked key would leave the health monitor reporting a session every query then fails on. + public func ping() async throws { + let response = try await send(method: "GET", path: "/v1/meta") + try throwIfFailed(response) + } + + public func schema() async throws -> [WeaviateCollection] { + let response = try await send(method: "GET", path: "/v1/schema") + try throwIfFailed(response) + guard let json = response.json else { + throw WeaviateError.malformedResponse(String(localized: "Schema response was empty.")) + } + return WeaviateSchema.collections(from: json) + } + + public func objects( + collection: String, + limit: Int, + offset: Int, + includeVector: Bool = true + ) async throws -> [WeaviateObject] { + var query = [ + "class": collection, + "limit": String(max(limit, 0)), + "offset": String(max(offset, 0)) + ] + if includeVector { + query["include"] = "vector" + } + let response = try await send(method: "GET", path: "/v1/objects", query: query) + try throwIfFailed(response) + guard let json = response.json else { return [] } + return WeaviateObject.parseList(json) + } + + public func graphql(_ query: String) async throws -> WeaviateHTTPResponse { + let body = try WeaviateGraphQL.requestBody(query: query) + let response = try await send(method: "POST", path: "/v1/graphql", body: body) + try throwIfFailed(response) + if let json = response.json { + let errors = WeaviateObjectCodec.graphQLErrors(from: json) + if !errors.isEmpty { + throw WeaviateError.api(status: response.statusCode, message: errors.joined(separator: "\n")) + } + } + return response + } + + public func execute(write request: WeaviateWriteRequest) async throws -> WeaviateHTTPResponse { + let body = request.body.flatMap { $0.data(using: .utf8) } + let response = try await send( + method: request.method, + path: request.path, + query: request.query, + body: body + ) + try throwIfFailed(response) + return response + } + + public func execute(console request: WeaviateConsoleRequest) async throws -> WeaviateHTTPResponse { + let body = request.body.flatMap { $0.data(using: .utf8) } + let response = try await send(method: request.method, path: request.path, body: body) + try throwIfFailed(response) + return response + } + + public func send( + method: String, + path: String, + query: [String: String] = [:], + body: Data? = nil + ) async throws -> WeaviateHTTPResponse { + let base = try settings.baseURL() + guard let url = WeaviatePathEncoding.resolve(path, query: query, against: base) else { + throw WeaviateError.configuration(String(format: String(localized: "Invalid path: %@"), path)) + } + var headers = [ + "Accept": "application/json" + ] + if body != nil { + headers["Content-Type"] = "application/json" + } + if let authorization = settings.auth.authorizationHeader { + headers["Authorization"] = authorization + } + let request = WeaviateHTTPRequest( + method: method, + url: url, + headers: headers, + body: body, + timeoutInterval: timeout() + ) + return try await transport.send(request) + } + + public func throwIfFailed(_ response: WeaviateHTTPResponse) throws { + guard (200..<300).contains(response.statusCode) else { + throw WeaviateError.from(status: response.statusCode, body: response.body) + } + } +} diff --git a/Packages/TableProCore/Sources/TableProWeaviateCore/Wire/WeaviateTransport.swift b/Packages/TableProCore/Sources/TableProWeaviateCore/Wire/WeaviateTransport.swift new file mode 100644 index 0000000000..f7695710e2 --- /dev/null +++ b/Packages/TableProCore/Sources/TableProWeaviateCore/Wire/WeaviateTransport.swift @@ -0,0 +1,174 @@ +import Foundation + +public struct WeaviateHTTPRequest: Sendable, Equatable { + public let method: String + public let url: URL + public let headers: [String: String] + public let body: Data? + public let timeoutInterval: TimeInterval + + public init( + method: String, + url: URL, + headers: [String: String], + body: Data?, + timeoutInterval: TimeInterval + ) { + self.method = method + self.url = url + self.headers = headers + self.body = body + self.timeoutInterval = timeoutInterval + } +} + +public struct WeaviateHTTPResponse: Sendable, Equatable { + public let statusCode: Int + public let body: Data + private let parsed: ParsedResponseJSON + + public init(statusCode: Int, body: Data) { + self.statusCode = statusCode + self.body = body + self.parsed = ParsedResponseJSON(body) + } + + /// A filtered browse reads this two or three times, and a page of 1536-dimension vectors is + /// several megabytes, so the body is parsed once and the result held. + public var json: Any? { + parsed.value + } + + public var text: String { + String(data: body, encoding: .utf8) ?? "" + } + + public static func == (lhs: WeaviateHTTPResponse, rhs: WeaviateHTTPResponse) -> Bool { + lhs.statusCode == rhs.statusCode && lhs.body == rhs.body + } +} + +private final class ParsedResponseJSON: @unchecked Sendable { + private let body: Data + private let lock = NSLock() + private var value_: Any? + private var hasParsed = false + + init(_ body: Data) { + self.body = body + } + + var value: Any? { + lock.withLock { + if !hasParsed { + value_ = try? JSONSerialization.jsonObject(with: body, options: [.fragmentsAllowed]) + hasParsed = true + } + return value_ + } + } +} + +public protocol WeaviateTransport: Sendable { + func send(_ request: WeaviateHTTPRequest) async throws -> WeaviateHTTPResponse + func cancelAll() +} + +public final class URLSessionWeaviateTransport: WeaviateTransport, @unchecked Sendable { + private let session: URLSession + private let lock = NSLock() + private var inFlight: [ObjectIdentifier: URLSessionTask] = [:] + + public init( + configuration: URLSessionConfiguration = .ephemeral, + resourceTimeout: TimeInterval, + skipTLSVerify: Bool = false + ) { + configuration.timeoutIntervalForResource = resourceTimeout + if skipTLSVerify { + let delegate = InsecureTLSDelegate() + session = URLSession(configuration: configuration, delegate: delegate, delegateQueue: nil) + } else { + session = URLSession(configuration: configuration) + } + } + + deinit { + session.invalidateAndCancel() + } + + public func cancelAll() { + let tasks = lock.withLock { Array(inFlight.values) } + tasks.forEach { $0.cancel() } + } + + public func send(_ request: WeaviateHTTPRequest) async throws -> WeaviateHTTPResponse { + var urlRequest = URLRequest(url: request.url) + urlRequest.httpMethod = request.method + urlRequest.httpBody = request.body + urlRequest.timeoutInterval = request.timeoutInterval + for (name, value) in request.headers { + urlRequest.setValue(value, forHTTPHeaderField: name) + } + + let tracker = TaskTracker(transport: self) + defer { tracker.finish() } + do { + let (data, response) = try await session.data(for: urlRequest, delegate: tracker) + guard let httpResponse = response as? HTTPURLResponse else { + throw WeaviateError.transport(String(localized: "Weaviate answered with something other than HTTP.")) + } + return WeaviateHTTPResponse(statusCode: httpResponse.statusCode, body: data) + } catch let error as URLError where error.code == .cancelled { + throw WeaviateError.cancelled + } catch let error as WeaviateError { + throw error + } catch let error as URLError { + throw WeaviateError.transport(error.localizedDescription) + } + } + + fileprivate func register(_ task: URLSessionTask) { + lock.withLock { inFlight[ObjectIdentifier(task)] = task } + } + + fileprivate func unregister(_ task: URLSessionTask) { + lock.withLock { inFlight[ObjectIdentifier(task)] = nil } + } +} + +private final class InsecureTLSDelegate: NSObject, URLSessionDelegate { + func urlSession( + _ session: URLSession, + didReceive challenge: URLAuthenticationChallenge, + completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void + ) { + guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust, + let trust = challenge.protectionSpace.serverTrust + else { + completionHandler(.performDefaultHandling, nil) + return + } + completionHandler(.useCredential, URLCredential(trust: trust)) + } +} + +private final class TaskTracker: NSObject, URLSessionTaskDelegate, @unchecked Sendable { + private weak var transport: URLSessionWeaviateTransport? + private let lock = NSLock() + private var task: URLSessionTask? + + init(transport: URLSessionWeaviateTransport) { + self.transport = transport + } + + func urlSession(_ session: URLSession, didCreateTask task: URLSessionTask) { + lock.withLock { self.task = task } + transport?.register(task) + } + + func finish() { + guard let task = lock.withLock({ task }) else { return } + transport?.unregister(task) + } +} diff --git a/Packages/TableProCore/Tests/TableProModelsTests/DatabaseTypeTests.swift b/Packages/TableProCore/Tests/TableProModelsTests/DatabaseTypeTests.swift index f0d7b2e80f..afa059d747 100644 --- a/Packages/TableProCore/Tests/TableProModelsTests/DatabaseTypeTests.swift +++ b/Packages/TableProCore/Tests/TableProModelsTests/DatabaseTypeTests.swift @@ -59,7 +59,7 @@ struct DatabaseTypeTests { @Test("allKnownTypes contains all expected types") func allKnownTypesComplete() { - #expect(DatabaseType.allKnownTypes.count == 28) + #expect(DatabaseType.allKnownTypes.count == 29) #expect(DatabaseType.allKnownTypes.contains(.mysql)) #expect(DatabaseType.allKnownTypes.contains(.tidb)) #expect(DatabaseType.allKnownTypes.contains(.databend)) @@ -74,6 +74,7 @@ struct DatabaseTypeTests { #expect(DatabaseType.allKnownTypes.contains(.dameng)) #expect(DatabaseType.allKnownTypes.contains(.kafka)) #expect(DatabaseType.allKnownTypes.contains(.cloudflareR2SQL)) + #expect(DatabaseType.allKnownTypes.contains(.weaviate)) } /// The list has no duplicates, which a count alone would not catch: adding a type twice @@ -91,6 +92,13 @@ struct DatabaseTypeTests { #expect(DatabaseType.cloudflareR2SQL.pluginTypeId == "Cloudflare R2 SQL") } + @Test("Weaviate resolves its icon and plugin type id") + func weaviateIdentity() { + #expect(DatabaseType.weaviate.rawValue == "Weaviate") + #expect(DatabaseType.weaviate.iconName == "weaviate-icon") + #expect(DatabaseType.weaviate.pluginTypeId == "Weaviate") + } + @Test("Hashable conformance") func hashableConformance() { var set: Set = [.mysql, .postgresql, .mysql] diff --git a/Packages/TableProCore/Tests/TableProWeaviateCoreTests/WeaviateAuthAndQueryTests.swift b/Packages/TableProCore/Tests/TableProWeaviateCoreTests/WeaviateAuthAndQueryTests.swift new file mode 100644 index 0000000000..e11c48cd81 --- /dev/null +++ b/Packages/TableProCore/Tests/TableProWeaviateCoreTests/WeaviateAuthAndQueryTests.swift @@ -0,0 +1,195 @@ +import Foundation +import Testing +@testable import TableProWeaviateCore + +@Suite("Weaviate auth and settings") +struct WeaviateAuthTests { + @Test("Field ids stay Weaviate-prefixed") + func fieldIdsArePrefixed() { + #expect(WeaviateFieldID.authMethod == "wvAuthMethod") + #expect(WeaviateFieldID.apiKey == "wvApiKey") + #expect(WeaviateFieldID.skipTLSVerify == "wvSkipTLSVerify") + #expect(WeaviateFieldID.authMethod != "esAuthMethod") + #expect(WeaviateFieldID.apiKey != "esApiKey") + } + + @Test("API key mode without a key is refused") + func apiKeyRequiresValue() { + #expect(throws: WeaviateError.configuration("Enter a Weaviate API key.")) { + _ = try WeaviateConnectionSettings.parse( + host: "localhost", + port: 8_080, + usesTLS: false, + fields: [WeaviateFieldID.authMethod: "apiKey"] + ) + } + } + + @Test("A pasted key is not sent when Auth Method is None") + func noneModeIgnoresAPastedKey() throws { + let settings = try WeaviateConnectionSettings.parse( + host: "localhost", + port: 8_080, + usesTLS: false, + fields: [ + WeaviateFieldID.authMethod: "none", + WeaviateFieldID.apiKey: "wv-secret" + ] + ) + #expect(settings.auth.authorizationHeader == nil) + } + + @Test("None mode does not require a key") + func noneModeConnects() throws { + let settings = try WeaviateConnectionSettings.parse( + host: "localhost", + port: 0, + usesTLS: false, + fields: [WeaviateFieldID.authMethod: "none"] + ) + #expect(settings.port == 8_080) + #expect(settings.auth.authorizationHeader == nil) + #expect(try settings.baseURL().absoluteString == "http://localhost:8080") + } + + @Test("TLS uses https") + func tlsUsesHTTPS() throws { + let settings = try WeaviateConnectionSettings.parse( + host: "example.weaviate.cloud", + port: 443, + usesTLS: true, + fields: [ + WeaviateFieldID.authMethod: "apiKey", + WeaviateFieldID.apiKey: "key" + ] + ) + #expect(try settings.baseURL().absoluteString == "https://example.weaviate.cloud:443") + #expect(settings.auth.authorizationHeader == "Bearer key") + } +} + +@Suite("Weaviate query tags") +struct WeaviateQueryTests { + @Test("Browse tags round-trip") + func browseRoundTrip() throws { + let encoded = WeaviateBrowseQuery.encode( + collection: "Article", + offset: 10, + limit: 25, + sorts: [WeaviateSortSpec(column: "title", ascending: true)], + filters: [WeaviateFilterSpec(column: "title", op: "=", value: "Hello")], + logicMode: "AND", + propertyNames: ["uuid", "title"] + ) + #expect(WeaviateBrowseQuery.isTagged(encoded)) + let parsed = try #require(WeaviateBrowseQuery.parse(encoded)) + #expect(parsed.collection == "Article") + #expect(parsed.offset == 10) + #expect(parsed.limit == 25) + #expect(parsed.usesGraphQL) + #expect(parsed.filters.first?.value == "Hello") + } + + @Test("An unfiltered browse stays on REST objects") + func unfilteredUsesREST() throws { + let encoded = WeaviateBrowseQuery.encode( + collection: "Article", + offset: 0, + limit: 25, + sorts: [], + filters: [], + logicMode: "AND", + propertyNames: ["uuid", "title"] + ) + let parsed = try #require(WeaviateBrowseQuery.parse(encoded)) + #expect(!parsed.usesGraphQL) + } + + @Test("Write tags round-trip") + func writeRoundTrip() throws { + let original = WeaviateWriteRequest( + method: "PATCH", + path: "/v1/objects/abc", + query: ["class": "Article"], + body: "{\"title\":\"x\"}" + ) + let encoded = WeaviateWriteCodec.encode(original) + #expect(WeaviateWriteCodec.isTagged(encoded)) + #expect(WeaviateWriteCodec.decode(encoded) == original) + } +} + +@Suite("Weaviate GraphQL and console") +struct WeaviateGraphQLTests { + @Test("A Get query asks for _additional id and vector") + func getQueryIncludesAdditional() throws { + let query = try WeaviateGraphQL.getQuery( + collection: "Article", + properties: ["uuid", "title", "vector"], + limit: 10, + offset: 0, + sorts: [], + filters: [WeaviateFilterSpec(column: "title", op: "=", value: "Hello")], + logicMode: "AND", + schema: ["title": WeaviateProperty(name: "title", dataType: "text")] + ) + #expect(query.contains("Get")) + #expect(query.contains("Article")) + #expect(query.contains("title")) + #expect(query.contains("_additional { id vector }")) + #expect(query.contains("operator: Equal")) + #expect(query.contains("valueText: \"Hello\"")) + #expect(!query.contains(" uuid ")) + } + + @Test("GraphQL detection") + func detection() { + #expect(WeaviateGraphQL.looksLikeGraphQL("{ Get { Article { title } } }")) + #expect(WeaviateGraphQL.looksLikeGraphQL("query { Get { Article { title } } }")) + #expect(!WeaviateGraphQL.looksLikeGraphQL("GET /v1/schema")) + } + + @Test("Console parser reads a method and path") + func consoleParser() throws { + let request = try #require(WeaviateConsoleParser.parse("GET /v1/schema")) + #expect(request.method == "GET") + #expect(request.path == "/v1/schema") + #expect(request.body == nil) + + let withBody = try #require(WeaviateConsoleParser.parse("POST /v1/graphql\n{ \"query\": \"{ Get { Article { title } } }\" }")) + #expect(withBody.method == "POST") + #expect(withBody.body?.contains("Get") == true) + } + + @Test("A SQL delete is not a console request") + func sqlIsNotConsole() { + #expect(WeaviateConsoleParser.parse("DELETE FROM Article") == nil) + #expect(WeaviateConsoleParser.parse("UPDATE Article SET title = 'x'") == nil) + #expect(WeaviateConsoleParser.parse("GET schema") == nil) + } +} + +@Suite("Weaviate columns") +struct WeaviateSchemaTests { + @Test("uuid leads and vector trails, and both are the primary key surface") + func columnOrder() { + let collection = WeaviateCollection( + name: "Article", + properties: [WeaviateProperty(name: "title", dataType: "text")] + ) + let columns = WeaviateSchema.columns(for: collection) + #expect(columns.map(\.name) == ["uuid", "title", "vector"]) + #expect(columns.first?.isPrimaryKey == true) + #expect(WeaviateSchema.immutableColumns == ["uuid", "vector"]) + } + + @Test("Object and array properties display as JSON") + func displayTextEncodesCollections() { + #expect(WeaviateJSON.displayText(["title": "Hello"]) == "{\"title\":\"Hello\"}") + let vector = WeaviateJSON.displayText([0.1, 0.2]) + #expect(vector?.hasPrefix("[") == true) + #expect(vector?.hasSuffix("]") == true) + #expect(WeaviateJSON.displayText(true) == "true") + #expect(WeaviateJSON.displayText(NSNull()) == nil) + } +} diff --git a/Packages/TableProCore/Tests/TableProWeaviateCoreTests/WeaviateClientTests.swift b/Packages/TableProCore/Tests/TableProWeaviateCoreTests/WeaviateClientTests.swift new file mode 100644 index 0000000000..2ea2b8300b --- /dev/null +++ b/Packages/TableProCore/Tests/TableProWeaviateCoreTests/WeaviateClientTests.swift @@ -0,0 +1,279 @@ +import Foundation +import Testing +@testable import TableProWeaviateCore + +@Suite("Weaviate client") +struct WeaviateClientTests { + @Test("Connect reads ready and meta, and stores the version") + func connectStoresVersion() async throws { + let transport = FakeWeaviateTransport() + transport.respond(method: "GET", path: "/v1/.well-known/ready", status: 200, body: ".") + transport.respond(method: "GET", path: "/v1/meta", status: 200, json: WeaviateFixtures.meta) + let client = testClient(transport: transport) + + try await client.connect() + + #expect(client.serverVersion == "1.27.0") + #expect(transport.requests.map { $0.url.path } == ["/v1/.well-known/ready", "/v1/meta"]) + } + + @Test("An API key is sent as a Bearer header") + func apiKeyIsBearer() async throws { + let transport = FakeWeaviateTransport() + transport.respond(method: "GET", path: "/v1/meta", status: 200, json: WeaviateFixtures.meta) + let client = testClient( + transport: transport, + auth: WeaviateAuth(method: .apiKey, apiKey: "wv-secret") + ) + + try await client.ping() + + #expect(transport.requests.first?.headers["Authorization"] == "Bearer wv-secret") + } + + @Test("A ping asks an endpoint that checks the key") + func pingIsAuthenticated() async throws { + let transport = FakeWeaviateTransport() + transport.respond(method: "GET", path: "/v1/meta", status: 200, json: WeaviateFixtures.meta) + let client = testClient(transport: transport) + + try await client.ping() + + #expect(transport.requests.map { $0.url.path } == ["/v1/meta"]) + } + + @Test("Anonymous auth sends no Authorization header") + func anonymousHasNoAuthorization() async throws { + let transport = FakeWeaviateTransport() + transport.respond(method: "GET", path: "/v1/meta", status: 200, json: WeaviateFixtures.meta) + let client = testClient(transport: transport) + + try await client.ping() + + #expect(transport.requests.first?.headers["Authorization"] == nil) + } + + @Test("Schema lists collections and properties") + func schemaListsCollections() async throws { + let transport = FakeWeaviateTransport() + transport.respond(method: "GET", path: "/v1/schema", status: 200, json: WeaviateFixtures.schema) + let client = testClient(transport: transport) + + let collections = try await client.schema() + + #expect(collections.map(\.name) == ["Article"]) + #expect(collections.first?.properties.map(\.name) == ["title", "wordCount"]) + #expect(collections.first?.properties.map(\.dataType) == ["text", "int"]) + } + + @Test("Objects include uuid, properties and the vector as display text") + func objectsIncludeUUIDAndVector() async throws { + let transport = FakeWeaviateTransport() + transport.respond(method: "GET", path: "/v1/objects", status: 200, json: WeaviateFixtures.objects) + let client = testClient(transport: transport) + + let objects = try await client.objects(collection: "Article", limit: 25, offset: 0) + let object = try #require(objects.first) + let columns = ["uuid", "title", "wordCount", "vector"] + let row = WeaviateObjectCodec.row(for: object, columns: columns) + + #expect(object.uuid == WeaviateFixtures.articleUUID) + #expect(row[0] == WeaviateFixtures.articleUUID) + #expect(row[1] == "Hello") + #expect(row[2] == "12") + #expect(row[3]?.contains("0.1") == true) + #expect(row[3]?.hasPrefix("[") == true) + #expect(transport.requests.first?.url.query?.contains("class=Article") == true) + #expect(transport.requests.first?.url.query?.contains("include=vector") == true) + } + + @Test("HTTP 401 becomes an authentication error") + func unauthorizedIsAuthentication() async throws { + let transport = FakeWeaviateTransport() + transport.respond( + method: "GET", + path: "/v1/meta", + status: 401, + json: ["error": [["message": "invalid api key"]]] + ) + let client = testClient(transport: transport) + + await #expect(throws: WeaviateError.authentication("invalid api key")) { + try await client.ping() + } + } + + @Test("A server error body is surfaced") + func serverErrorMessage() async throws { + let transport = FakeWeaviateTransport() + transport.respond( + method: "GET", + path: "/v1/schema", + status: 500, + json: ["error": [["message": "store unavailable"]]] + ) + let client = testClient(transport: transport) + + await #expect(throws: WeaviateError.api(status: 500, message: "store unavailable")) { + _ = try await client.schema() + } + } + + @Test("GraphQL Get rows flatten uuid from _additional") + func graphqlGetFlattensUUID() async throws { + let transport = FakeWeaviateTransport() + transport.respond(method: "POST", path: "/v1/graphql", status: 200, json: WeaviateFixtures.graphqlGet) + let client = testClient(transport: transport) + + let response = try await client.graphql("{ Get { Article { title } } }") + let objects = WeaviateObjectCodec.objects(fromGraphQL: response.json as Any) + let object = try #require(objects.first) + + #expect(object.uuid == WeaviateFixtures.articleUUID) + #expect(object.properties["title"] == "Hello") + #expect(object.vectorText?.contains("0.1") == true) + } + + @Test("GraphQL errors in a 200 response still fail") + func graphqlErrorsFail() async throws { + let transport = FakeWeaviateTransport() + transport.respond( + method: "POST", + path: "/v1/graphql", + status: 200, + json: ["errors": [["message": "Cannot query field"]]] + ) + let client = testClient(transport: transport) + + await #expect(throws: WeaviateError.api(status: 200, message: "Cannot query field")) { + _ = try await client.graphql("{ Get { Missing { title } } }") + } + } +} + +@Suite("Weaviate uuid edits") +struct WeaviateUUIDEditTests { + @Test("An update is a PATCH keyed by uuid and does not write uuid or vector") + func updateIsPatchByUUID() async throws { + let batch = WeaviateStatementGenerator.generate( + collection: "Article", + columns: ["uuid", "title", "vector"], + typeNames: ["uuid", "text", "vector"], + changes: [ + WeaviateTrackedChange( + kind: .update, + uuid: WeaviateFixtures.articleUUID, + values: [:], + cellChanges: [ + WeaviateCellChange(column: "title", newText: "Edited"), + WeaviateCellChange(column: "vector", newText: "[9,9]"), + WeaviateCellChange(column: "uuid", newText: "nope") + ] + ) + ] + ) + let request = try #require(batch.requests.first) + #expect(request.method == "PATCH") + #expect(request.path == "/v1/objects/\(WeaviateFixtures.articleUUID)") + #expect(request.query["class"] == "Article") + let body = try #require(request.body) + #expect(body.contains("\"title\":\"Edited\"")) + #expect(!body.contains("vector")) + #expect(!body.contains("nope")) + + let transport = FakeWeaviateTransport() + transport.respond( + method: "PATCH", + path: "/v1/objects/\(WeaviateFixtures.articleUUID)", + status: 200, + json: ["id": WeaviateFixtures.articleUUID] + ) + let client = testClient(transport: transport) + let response = try await client.execute(write: request) + #expect(response.statusCode == 200) + #expect(transport.requests.first?.httpMethodMatchesPatch == true) + } + + @Test("A delete is DELETE /v1/objects/{uuid}") + func deleteUsesUUID() async throws { + let batch = WeaviateStatementGenerator.generate( + collection: "Article", + columns: ["uuid", "title"], + typeNames: ["uuid", "text"], + changes: [ + WeaviateTrackedChange( + kind: .delete, + uuid: WeaviateFixtures.articleUUID, + values: [:], + cellChanges: [] + ) + ] + ) + let request = try #require(batch.requests.first) + #expect(request.method == "DELETE") + #expect(request.path.hasSuffix(WeaviateFixtures.articleUUID)) + + let transport = FakeWeaviateTransport() + transport.respond( + method: "DELETE", + path: "/v1/objects/\(WeaviateFixtures.articleUUID)", + status: 204, + body: "" + ) + let client = testClient(transport: transport) + let response = try await client.execute(write: request) + #expect(response.statusCode == 204) + } + + @Test("An update without a uuid is skipped") + func updateWithoutUUIDIsSkipped() { + let batch = WeaviateStatementGenerator.generate( + collection: "Article", + columns: ["uuid", "title"], + typeNames: ["uuid", "text"], + changes: [ + WeaviateTrackedChange( + kind: .update, + uuid: nil, + values: [:], + cellChanges: [WeaviateCellChange(column: "title", newText: "Edited")] + ) + ] + ) + #expect(batch.requests.isEmpty) + #expect(batch.skipped == [WeaviateSkippedChange(kind: .update, reason: .missingUUID)]) + } + + @Test("Insert posts the collection and properties, and an explicit uuid") + func insertPostsObject() throws { + let batch = WeaviateStatementGenerator.generate( + collection: "Article", + columns: ["uuid", "title", "wordCount"], + typeNames: ["uuid", "text", "int"], + changes: [ + WeaviateTrackedChange( + kind: .insert, + uuid: WeaviateFixtures.articleUUID, + values: [ + "uuid": WeaviateFixtures.articleUUID, + "title": "Hello", + "wordCount": "12" + ], + cellChanges: [] + ) + ] + ) + let request = try #require(batch.requests.first) + #expect(request.method == "POST") + #expect(request.path == "/v1/objects") + let body = try #require(request.body) + #expect(body.contains("\"class\":\"Article\"")) + #expect(body.contains("\"id\":\"\(WeaviateFixtures.articleUUID)\"")) + #expect(body.contains("\"title\":\"Hello\"")) + #expect(body.contains("\"wordCount\":12")) + } +} + +private extension WeaviateHTTPRequest { + var httpMethodMatchesPatch: Bool { method == "PATCH" } +} diff --git a/Packages/TableProCore/Tests/TableProWeaviateCoreTests/WeaviateFilterAndPathTests.swift b/Packages/TableProCore/Tests/TableProWeaviateCoreTests/WeaviateFilterAndPathTests.swift new file mode 100644 index 0000000000..4b3336785c --- /dev/null +++ b/Packages/TableProCore/Tests/TableProWeaviateCoreTests/WeaviateFilterAndPathTests.swift @@ -0,0 +1,565 @@ +import Foundation +import Testing +@testable import TableProWeaviateCore + +private let articleTypes = [ + "title": "text", + "wordCount": "int", + "ratio": "number", + "live": "boolean", + "published": "date", + "tags": "text[]", + "scores": "int[]" +] + +private let articleSchema = articleTypes.mapValues { WeaviateProperty(name: "", dataType: $0) } + +private func operand(_ column: String, _ op: String, _ value: String, second: String? = nil) throws -> String { + try WeaviateFilterBuilder.operand( + for: WeaviateFilterSpec(column: column, op: op, value: value, secondValue: second), + types: articleTypes + ) +} + +@Suite("Weaviate filter value types") +struct WeaviateFilterValueTypeTests { + @Test("Each data type picks the value field Weaviate demands") + func valueFieldFollowsDataType() throws { + #expect(try operand("title", "=", "Hello").contains("valueText: \"Hello\"")) + #expect(try operand("wordCount", "=", "12").contains("valueInt: 12")) + #expect(try operand("ratio", ">", "1.5").contains("valueNumber: 1.5")) + #expect(try operand("live", "=", "true").contains("valueBoolean: true")) + #expect(try operand("published", ">", "2024-01-31T00:00:00Z") + .contains("valueDate: \"2024-01-31T00:00:00Z\"")) + } + + @Test("An array property filters on its element type") + func arrayUsesElementField() throws { + #expect(try operand("tags", "=", "alpha").contains("valueText: \"alpha\"")) + #expect(try operand("scores", "=", "3").contains("valueInt: 3")) + } + + @Test("The uuid column filters as text on the id path") + func uuidFiltersAsText() throws { + let clause = try operand(WeaviateSchema.uuidColumn, "=", "c8f5c3e0-1b2a-4d3e-9f10-111213141516") + #expect(clause.contains("path: [\"id\"]")) + #expect(clause.contains("valueText:")) + } + + @Test("A value that is not a number is refused instead of becoming zero") + func badNumberThrows() { + #expect(throws: WeaviateFilterError.notANumber(column: "wordCount", value: "abc")) { + _ = try operand("wordCount", "=", "abc") + } + #expect(throws: WeaviateFilterError.notANumber(column: "ratio", value: "abc")) { + _ = try operand("ratio", "=", "abc") + } + } + + @Test("A value that is not a boolean is refused instead of becoming false") + func badBooleanThrows() { + #expect(throws: WeaviateFilterError.notABoolean(column: "live", value: "yes")) { + _ = try operand("live", "=", "yes") + } + } + + @Test("A date needs a full RFC 3339 timestamp") + func badDateThrows() { + #expect(throws: WeaviateFilterError.notADate(column: "published", value: "2024-01-31")) { + _ = try operand("published", ">", "2024-01-31") + } + #expect(WeaviateDateLiteral.isRFC3339("2024-01-31T00:00:00+07:00")) + #expect(WeaviateDateLiteral.isRFC3339("2024-01-31T00:00:00.123Z")) + } +} + +@Suite("Weaviate filter operators") +struct WeaviateFilterOperatorTests { + @Test("Substring operators become Like patterns") + func likePatterns() throws { + #expect(try operand("title", "CONTAINS", "ell").contains("operator: Like valueText: \"*ell*\"")) + #expect(try operand("title", "STARTS WITH", "He").contains("valueText: \"He*\"")) + #expect(try operand("title", "ENDS WITH", "lo").contains("valueText: \"*lo\"")) + #expect(try operand("title", "NOT CONTAINS", "ell").hasPrefix("{ operator: Not operands: [")) + } + + @Test("IN and NOT IN become ContainsAny") + func listOperators() throws { + let inClause = try operand("wordCount", "IN", "10, 30") + #expect(inClause.contains("operator: ContainsAny valueInt: [10, 30]")) + let notIn = try operand("title", "NOT IN", "a,b") + #expect(notIn.contains("operator: ContainsNone valueText: [\"a\", \"b\"]")) + } + + @Test("IN with no values is refused") + func emptyListThrows() { + #expect(throws: WeaviateFilterError.emptyList(column: "title")) { + _ = try operand("title", "IN", " , ") + } + } + + @Test("BETWEEN becomes a bounded And and needs its upper bound") + func betweenBounds() throws { + let clause = try operand("wordCount", "BETWEEN", "5", second: "10") + #expect(clause.hasPrefix("{ operator: And operands: [")) + #expect(clause.contains("operator: GreaterThanEqual valueInt: 5")) + #expect(clause.contains("operator: LessThanEqual valueInt: 10")) + + #expect(throws: WeaviateFilterError.missingUpperBound(column: "wordCount")) { + _ = try operand("wordCount", "BETWEEN", "5") + } + } + + @Test("IS NULL maps to IsNull in both directions") + func nullOperators() throws { + #expect(try operand("title", "IS NULL", "").contains("operator: IsNull valueBoolean: true")) + #expect(try operand("title", "IS NOT NULL", "").contains("operator: IsNull valueBoolean: false")) + } + + @Test("An operator Weaviate cannot express is reported, not dropped") + func unsupportedOperatorsThrow() { + #expect(throws: WeaviateFilterError.unsupportedOperator("REGEX")) { + _ = try operand("title", "REGEX", "^a") + } + } + + @Test("Emptiness counts with len(), which is what Weaviate offers") + func emptinessUsesLength() throws { + #expect(try operand("title", "IS EMPTY", "") + .contains("path: [\"len(title)\"] operator: Equal valueInt: 0")) + #expect(try operand("title", "IS NOT EMPTY", "") + .contains("path: [\"len(title)\"] operator: GreaterThan valueInt: 0")) + #expect(throws: WeaviateFilterError.textMatchNeedsText(column: "wordCount", op: "IS EMPTY")) { + _ = try operand("wordCount", "IS EMPTY", "") + } + } + + @Test("Comparing text, and matching a number as text, are both refused") + func mismatchedOperatorsThrow() { + #expect(throws: WeaviateFilterError.comparisonNeedsNumberOrDate(column: "title", op: ">")) { + _ = try operand("title", ">", "Row 1") + } + #expect(throws: WeaviateFilterError.textMatchNeedsText(column: "wordCount", op: "CONTAINS")) { + _ = try operand("wordCount", "CONTAINS", "1") + } + } + + @Test("The vector column cannot be filtered") + func vectorFilterThrows() { + #expect(throws: WeaviateFilterError.vectorNotFilterable(column: "vector")) { + _ = try operand(WeaviateSchema.vectorColumn, "=", "[1,2]") + } + } + + @Test("A quote in a value cannot break out of the GraphQL string") + func valuesAreEscaped() throws { + let clause = try operand("title", "=", "a\"b\\c") + #expect(clause.contains("valueText: \"a\\\"b\\\\c\"")) + } + + @Test("Several filters join under one logic operator") + func logicMode() throws { + let built = try WeaviateFilterBuilder.graphQLWhere( + filters: [ + WeaviateFilterSpec(column: "title", op: "=", value: "a"), + WeaviateFilterSpec(column: "wordCount", op: ">", value: "3") + ], + logicMode: "OR", + types: articleTypes + ) + let clause = try #require(built) + #expect(clause.hasPrefix("{ operator: Or operands: [")) + } +} + +@Suite("Weaviate sorting") +struct WeaviateSortTests { + @Test("A uuid sort reaches GraphQL, which can sort by the object id") + func uuidSortUsesGraphQL() throws { + let encoded = WeaviateBrowseQuery.encode( + collection: "Article", + offset: 0, + limit: 25, + sorts: [WeaviateSortSpec(column: WeaviateSchema.uuidColumn, ascending: false)], + filters: [], + logicMode: "AND", + propertyNames: ["uuid", "title"] + ) + let parsed = try #require(WeaviateBrowseQuery.parse(encoded)) + #expect(parsed.usesGraphQL) + + let query = try WeaviateGraphQL.getQuery( + collection: "Article", + properties: parsed.propertyNames, + limit: parsed.limit, + offset: parsed.offset, + sorts: parsed.sortableSorts, + filters: [], + logicMode: "AND", + schema: articleSchema + ) + #expect(query.contains("sort: [{ path: [\"id\"] order: desc }]")) + } + + @Test("A vector sort is dropped, because Weaviate has no such property") + func vectorSortIsDropped() throws { + let encoded = WeaviateBrowseQuery.encode( + collection: "Article", + offset: 0, + limit: 25, + sorts: [WeaviateSortSpec(column: WeaviateSchema.vectorColumn, ascending: true)], + filters: [], + logicMode: "AND", + propertyNames: ["uuid", "vector"] + ) + let parsed = try #require(WeaviateBrowseQuery.parse(encoded)) + #expect(parsed.sortableSorts.isEmpty) + #expect(!parsed.usesGraphQL) + } + + @Test("BETWEEN survives the browse tag round-trip") + func secondValueRoundTrips() throws { + let encoded = WeaviateBrowseQuery.encode( + collection: "Article", + offset: 0, + limit: 25, + sorts: [], + filters: [WeaviateFilterSpec(column: "wordCount", op: "BETWEEN", value: "5", secondValue: "10")], + logicMode: "AND", + propertyNames: ["uuid"] + ) + let parsed = try #require(WeaviateBrowseQuery.parse(encoded)) + #expect(parsed.filters.first?.secondValue == "10") + } +} + +@Suite("Weaviate request paths") +struct WeaviatePathTests { + private let base = URL(string: "http://localhost:8080")! + + @Test("A console path keeps its query string instead of encoding the question mark") + func consoleQueryStringSurvives() throws { + let url = try #require( + WeaviatePathEncoding.resolve("/v1/objects?class=Article&limit=10", against: base) + ) + #expect(url.path == "/v1/objects") + #expect(!url.absoluteString.contains("%3F")) + #expect(url.query == "class=Article&limit=10") + } + + @Test("A path and passed query items merge") + func mergedQueryItems() throws { + let url = try #require( + WeaviatePathEncoding.resolve("/v1/objects?class=Article", query: ["limit": "5"], against: base) + ) + let items = try #require(URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems) + #expect(items.contains(URLQueryItem(name: "class", value: "Article"))) + #expect(items.contains(URLQueryItem(name: "limit", value: "5"))) + } + + @Test("An already-encoded segment is not encoded twice") + func encodedSegmentSurvives() throws { + let uuid = "c8f5c3e0-1b2a-4d3e-9f10-111213141516" + let url = try #require( + WeaviatePathEncoding.resolve("/v1/objects/\(WeaviatePathEncoding.segment(uuid))", against: base) + ) + #expect(url.path == "/v1/objects/\(uuid)") + } + + @Test("An absolute or relative path is refused") + func hostiledPathsRefused() { + #expect(WeaviatePathEncoding.resolve("http://evil.example/v1", against: base) == nil) + #expect(WeaviatePathEncoding.resolve("v1/schema", against: base) == nil) + } +} + +@Suite("Weaviate response decoding") +struct WeaviateResponseDecodingTests { + @Test("A vector component at the edge of Int does not trap") + func hugeVectorComponent() { + let object = WeaviateObject( + uuid: "u1", + className: "Article", + properties: [:], + vector: [9_223_372_036_854_775_808.0, 1.5] + ) + let text = object.vectorText + #expect(text?.hasPrefix("[9.223372036854776e+18") == true) + #expect(text?.hasSuffix("1.5]") == true) + } + + @Test("A Get row keeps the _additional fields a vector search returns") + func additionalFieldsBecomeColumns() { + let objects = WeaviateObjectCodec.objects(fromGraphQL: [ + "data": [ + "Get": [ + "Article": [ + [ + "title": "Hello", + "_additional": ["id": "u1", "distance": 0.42, "score": "0.9"] + ] + ] + ] + ] + ]) + let object = objects.first + #expect(object?.uuid == "u1") + #expect(object?.properties["title"] == "Hello") + #expect(object?.properties["distance"] == "0.42") + #expect(object?.properties["score"] == "0.9") + } + + @Test("A property keeps its name when _additional carries the same one") + func propertyWinsOverAdditional() { + let objects = WeaviateObjectCodec.objects(fromGraphQL: [ + "data": ["Get": ["Article": [["distance": "mine", "_additional": ["id": "u1", "distance": 0.42]]]]] + ]) + #expect(objects.first?.properties["distance"] == "mine") + #expect(objects.first?.properties["_additional.distance"] == "0.42") + } + + @Test("A response body is parsed once and still compares by its bytes") + func responseEquality() { + let body = Data(#"{"a":1}"#.utf8) + let first = WeaviateHTTPResponse(statusCode: 200, body: body) + let second = WeaviateHTTPResponse(statusCode: 200, body: body) + #expect(first == second) + #expect(WeaviateJSON.dictionary(first.json)?["a"] as? Int == 1) + #expect(WeaviateJSON.dictionary(first.json)?["a"] as? Int == 1) + #expect(first != WeaviateHTTPResponse(statusCode: 500, body: body)) + } +} + +@Suite("Weaviate write generation") +struct WeaviateWriteGenerationTests { + @Test("A duplicate column name does not trap the generator") + func duplicateColumnNames() throws { + let batch = WeaviateStatementGenerator.generate( + collection: "Article", + columns: ["uuid", "title", "title"], + typeNames: ["uuid", "text", "int"], + changes: [ + WeaviateTrackedChange( + kind: .update, + uuid: "c8f5c3e0-1b2a-4d3e-9f10-111213141516", + values: [:], + cellChanges: [WeaviateCellChange(column: "title", newText: "Edited")] + ) + ] + ) + let body = try #require(batch.requests.first?.body) + #expect(body.contains("\"title\":\"Edited\"")) + } + + @Test("A delete with no uuid is reported rather than dropped in silence") + func deleteWithoutUUIDIsReported() { + let batch = WeaviateStatementGenerator.generate( + collection: "Article", + columns: ["uuid", "title"], + typeNames: ["uuid", "text"], + changes: [WeaviateTrackedChange(kind: .delete, uuid: nil, values: [:], cellChanges: [])] + ) + #expect(batch.requests.isEmpty) + #expect(batch.skipped == [WeaviateSkippedChange(kind: .delete, reason: .missingUUID)]) + } + + @Test("An update touching only read-only columns is reported") + func updateWithNoEditableColumns() { + let batch = WeaviateStatementGenerator.generate( + collection: "Article", + columns: ["uuid", "vector"], + typeNames: ["uuid", "vector"], + changes: [ + WeaviateTrackedChange( + kind: .update, + uuid: "c8f5c3e0-1b2a-4d3e-9f10-111213141516", + values: [:], + cellChanges: [WeaviateCellChange(column: "vector", newText: "[1,2]")] + ) + ] + ) + #expect(batch.requests.isEmpty) + #expect(batch.skipped == [WeaviateSkippedChange(kind: .update, reason: .noEditableColumns)]) + } +} + + +@Suite("Weaviate selection sets") +struct WeaviateSelectionSetTests { + private func query(_ properties: [WeaviateProperty]) throws -> String { + try WeaviateGraphQL.getQuery( + collection: "Article", + properties: properties.map(\.name), + limit: 5, + offset: 0, + sorts: [], + filters: [], + logicMode: "AND", + schema: Dictionary(properties.map { ($0.name, $0) }, uniquingKeysWith: { first, _ in first }) + ) + } + + @Test("A structured property asks for its own fields instead of failing the query") + func structuredPropertiesGetSubSelections() throws { + let built = try query([ + WeaviateProperty(name: "title", dataType: "text"), + WeaviateProperty(name: "place", dataType: "geoCoordinates"), + WeaviateProperty(name: "phone", dataType: "phoneNumber") + ]) + #expect(built.contains("place { latitude longitude }")) + #expect(built.contains("phone { input internationalFormatted")) + #expect(built.contains(" title ")) + } + + @Test("An object property selects its declared nested properties") + func objectSelectsNested() throws { + let built = try query([ + WeaviateProperty( + name: "meta", + dataTypes: ["object"], + nestedProperties: [ + WeaviateProperty(name: "k", dataType: "text"), + WeaviateProperty(name: "inner", dataTypes: ["object"], nestedProperties: [ + WeaviateProperty(name: "deep", dataType: "int") + ]) + ] + ) + ]) + #expect(built.contains("meta { k inner { deep } }")) + } + + @Test("An object with no declared nested properties is left out") + func emptyObjectIsOmitted() throws { + let built = try query([ + WeaviateProperty(name: "title", dataType: "text"), + WeaviateProperty(name: "meta", dataTypes: ["object"], nestedProperties: []) + ]) + #expect(!built.contains("meta")) + #expect(built.contains("title")) + } + + @Test("A cross-reference asks for the referenced ids") + func crossReferenceUsesFragments() throws { + let built = try query([ + WeaviateProperty(name: "category", dataTypes: ["Category", "Topic"], nestedProperties: []) + ]) + #expect(built.contains("category { ... on Category { _additional { id } } ... on Topic { _additional { id } } }")) + } + + @Test("A nested property list survives schema parsing") + func schemaParsesNestedProperties() throws { + let collections = WeaviateSchema.collections(from: [ + "classes": [[ + "class": "Article", + "properties": [ + ["name": "meta", "dataType": ["object"], "nestedProperties": [["name": "k", "dataType": ["text"]]]], + ["name": "category", "dataType": ["Category"]] + ] + ]] + ]) + let properties = try #require(collections.first?.properties) + #expect(properties.first?.nestedProperties.map(\.name) == ["k"]) + #expect(WeaviatePropertyShape.of(properties[1]) == .crossReference(["Category"])) + } +} + +@Suite("Weaviate value round-trip") +struct WeaviateParsedValueTests { + @Test("Text keeps its own punctuation instead of being parsed as JSON") + func textStaysText() { + #expect(WeaviateJSON.parsedValue("{\"a\":1}", typeName: "text") as? String == "{\"a\":1}") + #expect(WeaviateJSON.parsedValue("[1,2]", typeName: "text") as? String == "[1,2]") + #expect(WeaviateJSON.parsedValue("{\"a\":1}", typeName: "string") as? String == "{\"a\":1}") + #expect(WeaviateJSON.parsedValue("2024-01-31T00:00:00Z", typeName: "date") as? String == "2024-01-31T00:00:00Z") + } + + @Test("A type the grid renders as JSON parses back") + func structuredParsesBack() { + #expect(WeaviateJSON.parsedValue("[\"a\",\"b\"]", typeName: "text[]") as? [String] == ["a", "b"]) + #expect(WeaviateJSON.parsedValue("[1,2]", typeName: "int[]") as? [Int] == [1, 2]) + let object = WeaviateJSON.parsedValue("{\"k\":\"v\"}", typeName: "object") as? [String: Any] + #expect(object?["k"] as? String == "v") + let geo = WeaviateJSON.parsedValue("{\"latitude\":1}", typeName: "geoCoordinates") as? [String: Any] + #expect(geo?["latitude"] as? Int == 1) + } + + @Test("A scalar parses to its own type, and an unparsable one stays text") + func scalarsParse() { + #expect(WeaviateJSON.parsedValue("12", typeName: "int") as? Int == 12) + #expect(WeaviateJSON.parsedValue("1.5", typeName: "number") as? Double == 1.5) + #expect(WeaviateJSON.parsedValue("true", typeName: "boolean") as? Bool == true) + #expect(WeaviateJSON.parsedValue("abc", typeName: "int") as? String == "abc") + #expect(WeaviateJSON.parsedValue("yes", typeName: "boolean") as? String == "yes") + } + + @Test("A property named with a leading underscore is written, and a synthetic column is not") + func underscoreNamedPropertyIsWritten() throws { + let batch = WeaviateStatementGenerator.generate( + collection: "Event", + columns: ["uuid", "_source", "distance"], + typeNames: ["uuid", "text", "number"], + changes: [ + WeaviateTrackedChange( + kind: .update, + uuid: "c8f5c3e0-1b2a-4d3e-9f10-111213141516", + values: [:], + cellChanges: [ + WeaviateCellChange(column: "_source", newText: "manual"), + WeaviateCellChange(column: "_additional.distance", newText: "0.4") + ] + ) + ] + ) + let body = try #require(batch.requests.first?.body) + #expect(body.contains("\"_source\":\"manual\"")) + #expect(!body.contains("_additional")) + } +} + +@Suite("Weaviate console requests") +struct WeaviateConsoleRequestTests { + @Test("A body typed on the request line is kept") + func inlineBodySurvives() throws { + let request = try #require( + WeaviateConsoleParser.parse("POST /v1/objects {\"class\": \"Article\"}") + ) + #expect(request.method == "POST") + #expect(request.path == "/v1/objects") + #expect(request.body == "{\"class\": \"Article\"}") + } + + @Test("A body on the lines below still wins") + func multilineBodyWins() throws { + let request = try #require(WeaviateConsoleParser.parse("POST /v1/graphql\n{ \"query\": \"x\" }")) + #expect(request.body == "{ \"query\": \"x\" }") + } + + @Test("Any path is resolved under /v1") + func everyPathIsPrefixed() throws { + #expect(try #require(WeaviateConsoleParser.parse("GET /nodes")).path == "/v1/nodes") + #expect(try #require(WeaviateConsoleParser.parse("POST /batch/objects")).path == "/v1/batch/objects") + #expect(try #require(WeaviateConsoleParser.parse("GET /v1/schema")).path == "/v1/schema") + #expect(try #require(WeaviateConsoleParser.parse("GET /")).path == "/") + } + + @Test("SQL is still not a console request") + func sqlIsRefused() { + #expect(WeaviateConsoleParser.parse("DELETE FROM Article") == nil) + #expect(WeaviateConsoleParser.parse("UPDATE Article SET title = 'x'") == nil) + } + + @Test("A browse that is not showing the vector does not ask for it") + func vectorIsOptional() throws { + let withVector = try WeaviateGraphQL.getQuery( + collection: "Article", properties: ["uuid", "title"], limit: 5, offset: 0, + sorts: [], filters: [], logicMode: "AND", schema: [:], includeVector: true + ) + let withoutVector = try WeaviateGraphQL.getQuery( + collection: "Article", properties: ["uuid", "title"], limit: 5, offset: 0, + sorts: [], filters: [], logicMode: "AND", schema: [:], includeVector: false + ) + #expect(withVector.contains("_additional { id vector }")) + #expect(withoutVector.contains("_additional { id }")) + #expect(!withoutVector.contains("vector")) + } +} diff --git a/Packages/TableProCore/Tests/TableProWeaviateCoreTests/WeaviateTestSupport.swift b/Packages/TableProCore/Tests/TableProWeaviateCoreTests/WeaviateTestSupport.swift new file mode 100644 index 0000000000..cd6a8ba115 --- /dev/null +++ b/Packages/TableProCore/Tests/TableProWeaviateCoreTests/WeaviateTestSupport.swift @@ -0,0 +1,120 @@ +import Foundation +@testable import TableProWeaviateCore + +final class FakeWeaviateTransport: WeaviateTransport, @unchecked Sendable { + struct Route: Equatable { + let method: String + let path: String + } + + var responses: [String: WeaviateHTTPResponse] = [:] + var requests: [WeaviateHTTPRequest] = [] + var error: WeaviateError? + + func send(_ request: WeaviateHTTPRequest) async throws -> WeaviateHTTPResponse { + if let error { + throw error + } + requests.append(request) + let key = Self.key(method: request.method, url: request.url) + if let response = responses[key] ?? responses[request.url.path] { + return response + } + throw WeaviateError.malformedResponse("No fake response for \(key)") + } + + func cancelAll() {} + + func respond(method: String, path: String, status: Int, json: Any) { + let data = (try? JSONSerialization.data(withJSONObject: json)) ?? Data() + responses[Self.key(method: method, path: path)] = WeaviateHTTPResponse(statusCode: status, body: data) + } + + func respond(method: String, path: String, status: Int, body: String) { + responses[Self.key(method: method, path: path)] = WeaviateHTTPResponse( + statusCode: status, + body: Data(body.utf8) + ) + } + + static func key(method: String, path: String) -> String { + "\(method.uppercased()) \(path)" + } + + static func key(method: String, url: URL) -> String { + key(method: method, path: url.path) + } +} + +func testSettings(auth: WeaviateAuth = WeaviateAuth(method: .none)) -> WeaviateConnectionSettings { + WeaviateConnectionSettings( + host: "localhost", + port: 8_080, + usesTLS: false, + auth: auth, + skipTLSVerify: false + ) +} + +func testClient( + transport: FakeWeaviateTransport, + auth: WeaviateAuth = WeaviateAuth(method: .none) +) -> WeaviateClient { + WeaviateClient(settings: testSettings(auth: auth), transport: transport, timeout: { 30 }) +} + +enum WeaviateFixtures { + static let articleUUID = "c8f5c3e0-1b2a-4d3e-9f10-111213141516" + + static var schema: [String: Any] { + [ + "classes": [ + [ + "class": "Article", + "vectorizer": "none", + "properties": [ + ["name": "title", "dataType": ["text"]], + ["name": "wordCount", "dataType": ["int"]] + ] + ] + ] + ] + } + + static var objects: [String: Any] { + [ + "objects": [ + [ + "id": articleUUID, + "class": "Article", + "properties": ["title": "Hello", "wordCount": 12], + "vector": [0.1, 0.2, 0.3] + ] + ], + "totalResults": 1 + ] + } + + static var graphqlGet: [String: Any] { + [ + "data": [ + "Get": [ + "Article": [ + [ + "title": "Hello", + "wordCount": 12, + "_additional": [ + "id": articleUUID, + "vector": [0.1, 0.2] + ] + ] + ] + ] + ] + ] + } + + static var meta: [String: Any] { + ["version": "1.27.0"] + } +} diff --git a/Plugins/WeaviateDriverPlugin/Info.plist b/Plugins/WeaviateDriverPlugin/Info.plist new file mode 100644 index 0000000000..48893d9d17 --- /dev/null +++ b/Plugins/WeaviateDriverPlugin/Info.plist @@ -0,0 +1,14 @@ + + + + + TableProMinAppVersion + 0.73.0 + TableProPluginKitVersion + 25 + TableProProvidesDatabaseTypeIds + + Weaviate + + + diff --git a/Plugins/WeaviateDriverPlugin/WeaviatePlugin.swift b/Plugins/WeaviateDriverPlugin/WeaviatePlugin.swift new file mode 100644 index 0000000000..d533f77b68 --- /dev/null +++ b/Plugins/WeaviateDriverPlugin/WeaviatePlugin.swift @@ -0,0 +1,146 @@ +import Foundation +import TableProPluginKit +import TableProWeaviateCore + +final class WeaviatePlugin: NSObject, TableProPlugin, DriverPlugin { + static let pluginName = "Weaviate Driver" + static let pluginVersion = "1.0.0" + static let pluginDescription = "Weaviate support over the REST API with a GraphQL console" + static let capabilities: [PluginCapability] = [.databaseDriver] + + static let databaseTypeId = "Weaviate" + static let databaseDisplayName = "Weaviate" + static let iconName = "weaviate-icon" + static let defaultPort = WeaviateConnectionSettings.defaultPort + static let isDownloadable = true + + static let navigationModel: NavigationModel = .standard + static let pathFieldRole: PathFieldRole = .database + static let requiresAuthentication = false + static let brandColorHex = "#01B0D3" + static let queryLanguageName = "GraphQL" + static let editorLanguage: EditorLanguage = .javascript + static let supportsForeignKeys = false + static let supportsSchemaEditing = false + static let supportsDatabaseSwitching = false + static let supportsImport = false + static let supportsExport = true + static let supportsSSH = false + static let supportsSSL = true + static let supportsReadOnlyMode = true + static let supportsForeignKeyDisable = false + static let supportsAddColumn = false + static let supportsModifyColumn = false + static let supportsDropColumn = false + static let supportsAddIndex = false + static let supportsDropIndex = false + static let supportsModifyPrimaryKey = false + static let databaseGroupingStrategy: GroupingStrategy = .flat + static let defaultGroupName = "default" + static let tableEntityName = "Collections" + static let containerEntityName = "Cluster" + static let immutableColumns: [String] = WeaviateSchema.immutableColumns + static let defaultPrimaryKeyColumn: String? = WeaviateSchema.uuidColumn + static let structureColumnFields: [StructureColumnField] = [.name, .type, .nullable] + static let sqlDialect: SQLDialectDescriptor? = nil + + static let columnTypesByCategory: [String: [String]] = weaviateColumnTypes + + static let additionalConnectionFields: [ConnectionField] = weaviateConnectionFields() + + static var statementCompletions: [CompletionEntry] { weaviateCompletions } + + func createDriver(config: DriverConnectionConfig) -> any PluginDatabaseDriver { + WeaviatePluginDriver(config: config) + } +} + +func weaviateConnectionFields() -> [ConnectionField] { + [ + ConnectionField( + id: WeaviateFieldID.authMethod, + label: String(localized: "Auth Method"), + defaultValue: WeaviateAuthMethod.none.rawValue, + fieldType: .dropdown(options: [ + .init(value: WeaviateAuthMethod.none.rawValue, label: "None"), + .init(value: WeaviateAuthMethod.apiKey.rawValue, label: "API Key") + ]), + section: .authentication + ), + ConnectionField( + id: WeaviateFieldID.apiKey, + label: String(localized: "API Key"), + placeholder: "Weaviate API key", + fieldType: .secure, + section: .authentication, + hidesPassword: true + ).withHidesUsername(true), + ConnectionField( + id: WeaviateFieldID.skipTLSVerify, + label: String(localized: "Skip TLS Verification"), + defaultValue: "false", + fieldType: .toggle, + section: .advanced + ) + ] +} + +let weaviateCompletions: [CompletionEntry] = [ + CompletionEntry( + label: "Get", + insertText: """ + { + Get { + Article(limit: 10) { + title + _additional { id distance } + } + } + } + """ + ), + CompletionEntry( + label: "Near text", + insertText: """ + { + Get { + Article( + nearText: { concepts: ["search term"] } + limit: 10 + ) { + title + _additional { id distance } + } + } + } + """ + ), + CompletionEntry( + label: "Hybrid", + insertText: """ + { + Get { + Article( + hybrid: { query: "search term", alpha: 0.5 } + limit: 10 + ) { + title + _additional { id score } + } + } + } + """ + ), + CompletionEntry(label: "GET /v1/schema", insertText: "GET /v1/schema"), + CompletionEntry(label: "GET /v1/meta", insertText: "GET /v1/meta"), + CompletionEntry(label: "GET /v1/objects", insertText: "GET /v1/objects?class=Article&limit=10") +] + +let weaviateColumnTypes: [String: [String]] = [ + "Text": ["text", "text[]", "string", "string[]", "uuid", "uuid[]"], + "Numeric": ["int", "int[]", "number", "number[]"], + "Boolean": ["boolean", "boolean[]"], + "Date": ["date", "date[]"], + "Structured": ["object", "object[]", "geoCoordinates", "phoneNumber"], + "Vector": ["vector"] +] diff --git a/Plugins/WeaviateDriverPlugin/WeaviatePluginDriver+Execution.swift b/Plugins/WeaviateDriverPlugin/WeaviatePluginDriver+Execution.swift new file mode 100644 index 0000000000..55632941d2 --- /dev/null +++ b/Plugins/WeaviateDriverPlugin/WeaviatePluginDriver+Execution.swift @@ -0,0 +1,202 @@ +import Foundation +import TableProPluginKit +import TableProWeaviateCore + +extension WeaviatePluginDriver { + func execute(query: String) async throws -> PluginQueryResult { + let started = Date() + let client = try requireClient() + let trimmed = query.trimmingCharacters(in: .whitespacesAndNewlines) + + if trimmed.lowercased() == "select 1" { + try await client.ping() + return PluginQueryResult( + columns: ["ok"], + columnTypeNames: ["int"], + rows: [[.text("1")]], + rowsAffected: 0, + executionTime: Date().timeIntervalSince(started) + ) + } + + if WeaviateBrowseQuery.isTagged(trimmed) { + return try await executeSearch(trimmed, client: client, started: started) + } + if WeaviateWriteCodec.isTagged(trimmed) { + return try await executeWrite(trimmed, client: client, started: started) + } + if let console = WeaviateConsoleParser.parse(trimmed) { + return try await executeConsole(console, client: client, started: started) + } + if WeaviateGraphQL.looksLikeGraphQL(trimmed) { + return try await executeGraphQL(trimmed, client: client, started: started) + } + + throw WeaviateError.malformedResponse( + String(localized: "Enter a GraphQL query, or a request like GET /v1/schema.") + ) + } + + private func executeSearch( + _ query: String, + client: WeaviateClient, + started: Date + ) async throws -> PluginQueryResult { + guard let parsed = WeaviateBrowseQuery.parse(query) else { + throw WeaviateError.malformedResponse(String(localized: "Invalid browse request.")) + } + let collection = try await cachedCollection(parsed.collection) + let wantsVector = parsed.propertyNames.isEmpty + || parsed.propertyNames.contains(WeaviateSchema.vectorColumn) + let objects: [WeaviateObject] + if parsed.usesGraphQL { + let graphql = try WeaviateGraphQL.getQuery( + collection: parsed.collection, + properties: parsed.propertyNames, + limit: parsed.limit, + offset: parsed.offset, + sorts: parsed.sortableSorts, + filters: parsed.filters, + logicMode: parsed.logicMode, + schema: propertySchema(of: collection), + includeVector: wantsVector + ) + let response = try await client.graphql(graphql) + objects = WeaviateObjectCodec.objects(fromGraphQL: response.json as Any) + } else { + objects = try await client.objects( + collection: parsed.collection, + limit: parsed.limit, + offset: parsed.offset, + includeVector: wantsVector + ) + } + return render(objects: objects, collection: collection, columns: parsed.propertyNames, started: started) + } + + private func executeWrite( + _ statement: String, + client: WeaviateClient, + started: Date + ) async throws -> PluginQueryResult { + guard let request = WeaviateWriteCodec.decode(statement) else { + throw WeaviateError.malformedResponse(String(localized: "Invalid write request.")) + } + let response = try await client.execute(write: request) + let outcome: String + if let json = WeaviateJSON.dictionary(response.json), let id = json["id"] as? String { + outcome = id + } else if response.statusCode == 204 { + outcome = "deleted" + } else { + outcome = "ok" + } + return PluginQueryResult( + columns: ["result"], + columnTypeNames: ["text"], + rows: [[.text(outcome)]], + rowsAffected: 1, + executionTime: Date().timeIntervalSince(started) + ) + } + + private func executeConsole( + _ request: WeaviateConsoleRequest, + client: WeaviateClient, + started: Date + ) async throws -> PluginQueryResult { + if request.method == "POST", request.path.hasPrefix("/v1/graphql"), let body = request.body { + return try await executeGraphQL(body, client: client, started: started) + } + let response = try await client.execute(console: request) + if request.path.hasPrefix("/v1/objects"), let json = response.json { + let objects = WeaviateObject.parseList(json) + if !objects.isEmpty { + return await renderReturnedColumns(objects, started: started) + } + } + return renderJSON(response, started: started) + } + + private func executeGraphQL( + _ query: String, + client: WeaviateClient, + started: Date + ) async throws -> PluginQueryResult { + let response = try await client.graphql(query) + let objects = WeaviateObjectCodec.objects(fromGraphQL: response.json as Any) + if !objects.isEmpty { + return await renderReturnedColumns(objects, started: started) + } + return renderJSON(response, started: started) + } + + /// A console query selects its own fields, so the result shows what came back rather than every + /// column the collection has. That is also what carries `_additional { distance }` into the grid. + private func renderReturnedColumns(_ objects: [WeaviateObject], started: Date) async -> PluginQueryResult { + let collectionName = objects.first?.className ?? "" + let collection = (try? await cachedCollection(collectionName)) + ?? WeaviateCollection(name: collectionName, properties: []) + return render( + objects: objects, + collection: collection, + columns: returnedColumns(of: objects, collection: collection), + started: started + ) + } + + private func returnedColumns(of objects: [WeaviateObject], collection: WeaviateCollection) -> [String] { + let declared = collection.properties.map(\.name) + let returned = Set(objects.flatMap { $0.properties.keys }) + var columns: [String] = [] + if objects.contains(where: { !$0.uuid.isEmpty }) { + columns.append(WeaviateSchema.uuidColumn) + } + columns += declared.filter { returned.contains($0) } + columns += returned.subtracting(declared).sorted() + if objects.contains(where: { $0.vector != nil }) { + columns.append(WeaviateSchema.vectorColumn) + } + return columns.isEmpty ? [WeaviateSchema.uuidColumn] : columns + } + + private func render( + objects: [WeaviateObject], + collection: WeaviateCollection, + columns: [String], + started: Date + ) -> PluginQueryResult { + let resolved = columns.isEmpty + ? WeaviateSchema.columns(for: collection).map(\.name) + : columns + let rows = objects.map { object in + WeaviateObjectCodec.row(for: object, columns: resolved).map { value in + value.map(PluginCellValue.text) ?? .null + } + } + return PluginQueryResult( + columns: resolved, + columnTypeNames: resolved.map { typeName(for: $0, collection: collection) }, + rows: rows, + rowsAffected: 0, + executionTime: Date().timeIntervalSince(started) + ) + } + + private func renderJSON(_ response: WeaviateHTTPResponse, started: Date) -> PluginQueryResult { + let pretty: String + if let json = response.json, JSONSerialization.isValidJSONObject(json), + let text = try? WeaviateJSON.text(json, pretty: true) { + pretty = text + } else { + pretty = response.text + } + return PluginQueryResult( + columns: ["response"], + columnTypeNames: ["json"], + rows: [[.text(pretty)]], + rowsAffected: 0, + executionTime: Date().timeIntervalSince(started) + ) + } +} diff --git a/Plugins/WeaviateDriverPlugin/WeaviatePluginDriver+Metadata.swift b/Plugins/WeaviateDriverPlugin/WeaviatePluginDriver+Metadata.swift new file mode 100644 index 0000000000..eb3f150c54 --- /dev/null +++ b/Plugins/WeaviateDriverPlugin/WeaviatePluginDriver+Metadata.swift @@ -0,0 +1,215 @@ +import Foundation +import TableProPluginKit +import TableProWeaviateCore + +extension WeaviatePluginDriver { + func fetchDatabases() async throws -> [String] { + [WeaviatePlugin.defaultGroupName] + } + + func fetchDatabaseMetadata(_ database: String) async throws -> PluginDatabaseMetadata { + PluginDatabaseMetadata(name: database) + } + + func fetchTables(schema: String?) async throws -> [PluginTableInfo] { + let collections = try await requireClient().schema() + remember(collections) + return collections.map { PluginTableInfo(name: $0.name, type: "TABLE") } + } + + func fetchColumns(table: String, schema: String?) async throws -> [PluginColumnInfo] { + let collection = try await cachedCollection(table) + return WeaviateSchema.columns(for: collection).map { column in + PluginColumnInfo( + name: column.name, + dataType: column.type, + isNullable: !column.isPrimaryKey, + isPrimaryKey: column.isPrimaryKey + ) + } + } + + func fetchIndexes(table: String, schema: String?) async throws -> [PluginIndexInfo] { + [ + PluginIndexInfo( + name: WeaviateSchema.uuidColumn, + columns: [WeaviateSchema.uuidColumn], + isUnique: true, + isPrimary: true, + type: "PRIMARY KEY" + ) + ] + } + + func fetchForeignKeys(table: String, schema: String?) async throws -> [PluginForeignKeyInfo] { + [] + } + + func fetchTableDDL(table: String, schema: String?) async throws -> String { + let collections = try await requireClient().schema() + guard let collection = collections.first(where: { $0.name == table }) else { + return "{}" + } + var payload: [String: Any] = [ + "class": collection.name, + "properties": collection.properties.map { ["name": $0.name, "dataType": [$0.dataType]] } + ] + if let vectorizer = collection.vectorizer { + payload["vectorizer"] = vectorizer + } + return (try? WeaviateJSON.text(payload, pretty: true)) ?? "{}" + } + + func fetchViewDefinition(view: String, schema: String?) async throws -> String { + throw WeaviateError.configuration(String(localized: "Weaviate does not support views.")) + } + + func fetchTableMetadata(table: String, schema: String?) async throws -> PluginTableMetadata { + PluginTableMetadata(tableName: table, engine: "Weaviate") + } + + func buildBrowseQuery( + table: String, + sortColumns: [(columnIndex: Int, ascending: Bool)], + columns: [String], + limit: Int, + offset: Int + ) -> String? { + buildFilteredQuery( + table: table, + schema: nil, + queryFilters: [], + logicMode: "AND", + sortColumns: sortColumns, + columns: columns, + limit: limit, + offset: offset, + columnKinds: [:] + ) + } + + func buildFilteredQuery( + table: String, + schema: String?, + queryFilters filters: [PluginQueryFilter], + logicMode: String, + sortColumns: [(columnIndex: Int, ascending: Bool)], + columns: [String], + limit: Int, + offset: Int, + columnKinds: [String: PluginColumnKind] + ) -> String? { + let sorts = sortColumns.compactMap { sort -> WeaviateSortSpec? in + guard sort.columnIndex >= 0, sort.columnIndex < columns.count else { return nil } + let column = columns[sort.columnIndex] + guard column != WeaviateSchema.vectorColumn else { return nil } + return WeaviateSortSpec(column: column, ascending: sort.ascending) + } + let specs = filters.map { filter in + WeaviateFilterSpec( + column: filter.column, + op: filter.op, + value: filter.value, + secondValue: filter.secondValue + ) + } + return WeaviateBrowseQuery.encode( + collection: table, + offset: offset, + limit: limit, + sorts: sorts, + filters: specs, + logicMode: logicMode, + propertyNames: columns + ) + } + + func generateStatements( + table: String, + columns: [String], + primaryKeyColumns: [String], + changes: [PluginRowChange], + insertedRowData: [Int: [PluginCellValue]], + deletedRowIndices: Set, + insertedRowIndices: Set + ) -> [(statement: String, parameters: [PluginCellValue])]? { + let collection = rememberedCollection(table) + let typeNames = columns.map { column in + typeName(for: column, collection: collection ?? WeaviateCollection(name: table, properties: [])) + } + let tracked = changes.compactMap { change -> WeaviateTrackedChange? in + mappedChange( + change, + columns: columns, + insertedRowData: insertedRowData, + deletedRowIndices: deletedRowIndices, + insertedRowIndices: insertedRowIndices + ) + } + let batch = WeaviateStatementGenerator.generate( + collection: table, + columns: columns, + typeNames: typeNames, + changes: tracked + ) + for skipped in batch.skipped { + WeaviatePluginDriver.logger.warning( + "Skipped a \(skipped.kind.rawValue, privacy: .public) on \(table, privacy: .private): \(skipped.reason.rawValue, privacy: .public)" + ) + } + return batch.requests.map { (WeaviateWriteCodec.encode($0), []) } + } + + private func mappedChange( + _ change: PluginRowChange, + columns: [String], + insertedRowData: [Int: [PluginCellValue]], + deletedRowIndices: Set, + insertedRowIndices: Set + ) -> WeaviateTrackedChange? { + switch change.type { + case .insert: + guard insertedRowIndices.contains(change.rowIndex) else { return nil } + var values: [String: String?] = [:] + if let row = insertedRowData[change.rowIndex] { + for (index, column) in columns.enumerated() where index < row.count { + guard let text = row[index].asText else { continue } + values[column] = text + } + } else { + for cell in change.cellChanges { + guard let text = cell.newValue.asText else { continue } + values[cell.columnName] = text + } + } + return WeaviateTrackedChange( + kind: .insert, + uuid: values[WeaviateSchema.uuidColumn] ?? nil, + values: values, + cellChanges: [] + ) + case .update: + let uuid = uuid(from: change, columns: columns) + let cells = change.cellChanges.map { + WeaviateCellChange(column: $0.columnName, newText: $0.newValue.asText) + } + return WeaviateTrackedChange(kind: .update, uuid: uuid, values: [:], cellChanges: cells) + case .delete: + guard deletedRowIndices.contains(change.rowIndex) else { return nil } + return WeaviateTrackedChange( + kind: .delete, + uuid: uuid(from: change, columns: columns), + values: [:], + cellChanges: [] + ) + } + } + + private func uuid(from change: PluginRowChange, columns: [String]) -> String? { + guard let original = change.originalRow, + let index = columns.firstIndex(of: WeaviateSchema.uuidColumn), + index < original.count + else { return nil } + return original[index].asText + } +} diff --git a/Plugins/WeaviateDriverPlugin/WeaviatePluginDriver.swift b/Plugins/WeaviateDriverPlugin/WeaviatePluginDriver.swift new file mode 100644 index 0000000000..7f869e31f1 --- /dev/null +++ b/Plugins/WeaviateDriverPlugin/WeaviatePluginDriver.swift @@ -0,0 +1,122 @@ +import Foundation +import os +import TableProPluginKit +import TableProWeaviateCore + +internal final class WeaviatePluginDriver: PluginDatabaseDriver, @unchecked Sendable { + static let logger = Logger(subsystem: "com.TablePro", category: "WeaviatePluginDriver") + + private let config: DriverConnectionConfig + private let lock = NSLock() + private var client: WeaviateClient? + private var cachedCollections: [String: WeaviateCollection] = [:] + let queryTimeout = HttpQueryTimeoutBox() + + init(config: DriverConnectionConfig) { + self.config = config + } + + var serverVersion: String? { lock.withLock { client?.serverVersion } } + + var supportsTransactions: Bool { false } + + var capabilities: PluginCapabilities { [.cancelQuery] } + + var parameterStyle: ParameterStyle { .questionMark } + + func beginTransaction() async throws {} + func commitTransaction() async throws {} + func rollbackTransaction() async throws {} + + func connect() async throws { + let settings = try WeaviateConnectionSettings.parse( + host: config.host, + port: config.port, + usesTLS: config.ssl.isEnabled, + fields: config.additionalFields + ) + let skipTLS = settings.skipTLSVerify + || (config.ssl.isEnabled && !config.ssl.verifiesCertificate) + let timeout = queryTimeout + let transport = URLSessionWeaviateTransport( + resourceTimeout: HttpQueryTimeout.sessionResourceTimeout, + skipTLSVerify: skipTLS + ) + let client = WeaviateClient( + settings: settings, + transport: transport, + timeout: { timeout.requestTimeoutInterval } + ) + try await client.connect() + lock.withLock { + self.client = client + cachedCollections.removeAll() + } + } + + func disconnect() { + lock.withLock { + client?.cancelAll() + client = nil + cachedCollections.removeAll() + } + } + + func ping() async throws { + try await requireClient().ping() + } + + func cancelQuery() throws { + lock.withLock { client?.cancelAll() } + } + + func applyQueryTimeout(_ seconds: Int) async throws { + queryTimeout.set(serverTimeoutSeconds: seconds) + } + + func requireClient() throws -> WeaviateClient { + guard let client = lock.withLock({ client }) else { + throw WeaviateError.notConnected + } + return client + } + + func remember(_ collections: [WeaviateCollection]) { + lock.withLock { + for collection in collections { + cachedCollections[collection.name] = collection + } + } + } + + func rememberedCollection(_ name: String) -> WeaviateCollection? { + lock.withLock { cachedCollections[name] } + } + + func cachedCollection(_ name: String) async throws -> WeaviateCollection { + if let cached = rememberedCollection(name) { + return cached + } + let collections = try await requireClient().schema() + remember(collections) + return rememberedCollection(name) ?? WeaviateCollection(name: name, properties: []) + } + + func propertySchema(of collection: WeaviateCollection) -> [String: WeaviateProperty] { + Dictionary( + collection.properties.map { ($0.name, $0) }, + uniquingKeysWith: { first, _ in first } + ) + } + + func typeName(for column: String, collection: WeaviateCollection) -> String { + switch column { + case WeaviateSchema.uuidColumn: + return "uuid" + case WeaviateSchema.vectorColumn: + return "vector" + default: + return collection.properties.first { $0.name == column }?.dataType ?? "text" + } + } +} diff --git a/TablePro/Assets.xcassets/weaviate-icon.imageset/Contents.json b/TablePro/Assets.xcassets/weaviate-icon.imageset/Contents.json new file mode 100644 index 0000000000..fcfa2ae760 --- /dev/null +++ b/TablePro/Assets.xcassets/weaviate-icon.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images": [ + { + "filename": "weaviate.svg", + "idiom": "universal" + } + ], + "info": { + "author": "xcode", + "version": 1 + }, + "properties": { + "preserves-vector-representation": true, + "template-rendering-intent": "template" + } +} diff --git a/TablePro/Assets.xcassets/weaviate-icon.imageset/weaviate.svg b/TablePro/Assets.xcassets/weaviate-icon.imageset/weaviate.svg new file mode 100644 index 0000000000..fafccd810f --- /dev/null +++ b/TablePro/Assets.xcassets/weaviate-icon.imageset/weaviate.svg @@ -0,0 +1 @@ +Weaviate diff --git a/TablePro/Core/Plugins/PluginMetadataRegistry+RegistryDefaults.swift b/TablePro/Core/Plugins/PluginMetadataRegistry+RegistryDefaults.swift index d8f4b855e9..f5b3ce0476 100644 --- a/TablePro/Core/Plugins/PluginMetadataRegistry+RegistryDefaults.swift +++ b/TablePro/Core/Plugins/PluginMetadataRegistry+RegistryDefaults.swift @@ -1141,6 +1141,7 @@ extension PluginMetadataRegistry { + duckdbPluginDefaults(dialect: duckdbDialect, columnTypes: duckdbColumnTypes) + cloudPluginDefaults() + elasticsearchPluginDefaults() + surrealDBPluginDefaults() + kafkaPluginDefaults() + typesensePluginDefaults() + r2SQLPluginDefaults() + + weaviatePluginDefaults() } // swiftlint:enable function_body_length } diff --git a/TablePro/Core/Plugins/PluginMetadataRegistry+WeaviateDefaults.swift b/TablePro/Core/Plugins/PluginMetadataRegistry+WeaviateDefaults.swift new file mode 100644 index 0000000000..4ca4b1c04c --- /dev/null +++ b/TablePro/Core/Plugins/PluginMetadataRegistry+WeaviateDefaults.swift @@ -0,0 +1,156 @@ +import Foundation +import TableProPluginKit + +extension PluginMetadataRegistry { + func weaviatePluginDefaults() -> [(typeId: String, snapshot: PluginMetadataSnapshot)] { + [ + ("Weaviate", PluginMetadataSnapshot( + displayName: "Weaviate", iconName: "weaviate-icon", defaultPort: 8_080, + requiresAuthentication: false, supportsForeignKeys: false, supportsSchemaEditing: false, + isDownloadable: true, primaryUrlScheme: "", parameterStyle: .questionMark, + navigationModel: .standard, explainVariants: [], pathFieldRole: .database, + supportsHealthMonitor: true, urlSchemes: [], postConnectActions: [], + brandColorHex: "#01B0D3", + queryLanguageName: "GraphQL", editorLanguage: .javascript, + connectionMode: .network, supportsDatabaseSwitching: false, + capabilities: PluginMetadataSnapshot.CapabilityFlags( + supportsSchemaSwitching: false, + supportsImport: false, + supportsExport: true, + supportsSSH: false, + supportsSSL: true, + supportsCascadeDrop: false, + supportsForeignKeyDisable: false, + supportsReadOnlyMode: true, + supportsQueryProgress: false, + requiresReconnectForDatabaseSwitch: false, + supportsDropDatabase: false, + supportsAddColumn: false, + supportsModifyColumn: false, + supportsDropColumn: false, + supportsAddIndex: false, + supportsDropIndex: false, + supportsModifyPrimaryKey: false, + supportsOpportunisticTLS: false, + supportsCloudflareTunnel: false, + supportsPrincipalConnectionLimit: false + ), + schema: PluginMetadataSnapshot.SchemaInfo( + defaultSchemaName: "", + defaultGroupName: "default", + tableEntityName: "Collections", + containerEntityName: "Cluster", + defaultPrimaryKeyColumn: "uuid", + immutableColumns: ["uuid", "vector"], + systemDatabaseNames: [], + systemSchemaNames: [], + fileExtensions: [], + databaseGroupingStrategy: .flat, + structureColumnFields: [.name, .type, .nullable] + ), + editor: PluginMetadataSnapshot.EditorConfig( + sqlDialect: nil, + statementCompletions: weaviateCompletions, + columnTypesByCategory: weaviateColumnTypes + ), + connection: PluginMetadataSnapshot.ConnectionConfig( + additionalConnectionFields: weaviateConnectionFields(), + category: .document, + tagline: String(localized: "Open-source vector database"), + hidesBuiltInPassword: true, + hidesBuiltInDatabase: true + ) + )) + ] + } +} + +private let weaviateCompletions: [CompletionEntry] = [ + CompletionEntry( + label: "Get", + insertText: """ + { + Get { + Article(limit: 10) { + title + _additional { id distance } + } + } + } + """ + ), + CompletionEntry( + label: "Near text", + insertText: """ + { + Get { + Article( + nearText: { concepts: ["search term"] } + limit: 10 + ) { + title + _additional { id distance } + } + } + } + """ + ), + CompletionEntry( + label: "Hybrid", + insertText: """ + { + Get { + Article( + hybrid: { query: "search term", alpha: 0.5 } + limit: 10 + ) { + title + _additional { id score } + } + } + } + """ + ), + CompletionEntry(label: "GET /v1/schema", insertText: "GET /v1/schema"), + CompletionEntry(label: "GET /v1/meta", insertText: "GET /v1/meta"), + CompletionEntry(label: "GET /v1/objects", insertText: "GET /v1/objects?class=Article&limit=10") +] + +private let weaviateColumnTypes: [String: [String]] = [ + "Text": ["text", "text[]", "string", "string[]", "uuid", "uuid[]"], + "Numeric": ["int", "int[]", "number", "number[]"], + "Boolean": ["boolean", "boolean[]"], + "Date": ["date", "date[]"], + "Structured": ["object", "object[]", "geoCoordinates", "phoneNumber"], + "Vector": ["vector"] +] + +func weaviateConnectionFields() -> [ConnectionField] { + [ + ConnectionField( + id: "wvAuthMethod", + label: String(localized: "Auth Method"), + defaultValue: "none", + fieldType: .dropdown(options: [ + .init(value: "none", label: "None"), + .init(value: "apiKey", label: "API Key") + ]), + section: .authentication + ), + ConnectionField( + id: "wvApiKey", + label: String(localized: "API Key"), + placeholder: "Weaviate API key", + fieldType: .secure, + section: .authentication, + hidesPassword: true + ).withHidesUsername(true), + ConnectionField( + id: "wvSkipTLSVerify", + label: String(localized: "Skip TLS Verification"), + defaultValue: "false", + fieldType: .toggle, + section: .advanced + ) + ] +} diff --git a/TablePro/Core/Plugins/PluginMetadataRegistry.swift b/TablePro/Core/Plugins/PluginMetadataRegistry.swift index d6c246abaa..d11638b29c 100644 --- a/TablePro/Core/Plugins/PluginMetadataRegistry.swift +++ b/TablePro/Core/Plugins/PluginMetadataRegistry.swift @@ -686,7 +686,7 @@ final class PluginMetadataRegistry: @unchecked Sendable { return .analytical case "Spanner": return .relational - case "MongoDB", "Elasticsearch", "SurrealDB", "Typesense": + case "MongoDB", "Elasticsearch", "SurrealDB", "Typesense", "Weaviate": return .document case "Redis": return .keyValue @@ -728,6 +728,7 @@ final class PluginMetadataRegistry: @unchecked Sendable { case "SurrealDB": return String(localized: "Multi-model database with SurrealQL") case "Kafka": return String(localized: "Event streaming platform") case "Typesense": return String(localized: "Typo-tolerant open-source search engine") + case "Weaviate": return String(localized: "Open-source vector database") default: return "" } } diff --git a/TablePro/Core/Utilities/SQL/QueryClassifier.swift b/TablePro/Core/Utilities/SQL/QueryClassifier.swift index 0b06ebbc99..76d634cd3b 100644 --- a/TablePro/Core/Utilities/SQL/QueryClassifier.swift +++ b/TablePro/Core/Utilities/SQL/QueryClassifier.swift @@ -581,6 +581,8 @@ private extension QueryClassifier { return elasticsearchClassification(trimmed) case .typesense: return typesenseClassification(trimmed) + case .weaviate: + return weaviateClassification(trimmed) default: return nil } @@ -749,4 +751,69 @@ private extension QueryClassifier { } return QueryClassification(tier: .write, reachesFilesystemOrExecutesCode: touchesUnsafeSurface) } + + /// A bare operation, a `{"query": ...}` envelope and a console body are the same request, and + /// the driver forwards the envelope verbatim, so the read-only gate has to read all three. + static func weaviateDeclaresMutation(_ body: String) -> Bool { + let trimmed = body.trimmingCharacters(in: .whitespacesAndNewlines) + if trimmed.lowercased().hasPrefix("mutation") { + return true + } + guard let data = trimmed.data(using: .utf8), + let object = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + let query = object["query"] as? String + else { return false } + return query.trimmingCharacters(in: .whitespacesAndNewlines).lowercased().hasPrefix("mutation") + } + + /// The driver takes a body from the rest of the request line as well as from the lines below + /// it, so the gate has to read the same two places. + static func weaviateConsoleBody(_ trimmed: String) -> String { + let lines = trimmed.split(separator: "\n", maxSplits: 1, omittingEmptySubsequences: false) + let header = lines.first.map(String.init) ?? "" + let following = lines.count > 1 ? String(lines[1]) : "" + let parts = header.split(maxSplits: 2, omittingEmptySubsequences: true, whereSeparator: \.isWhitespace) + let inline = parts.count > 2 ? String(parts[2]) : "" + return inline.isEmpty ? following : inline + } + + static func weaviateClassification(_ trimmed: String) -> QueryClassification { + if trimmed.hasPrefix("WEAVIATE_SEARCH:") { + return .safe + } + if trimmed.hasPrefix("WEAVIATE_WRITE:") { + let encoded = String(trimmed.dropFirst("WEAVIATE_WRITE:".count)) + if let data = Data(base64Encoded: encoded), + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + (json["method"] as? String)?.uppercased() == "DELETE" { + return QueryClassification(tier: .destructive, reachesFilesystemOrExecutesCode: false) + } + return QueryClassification(tier: .write, reachesFilesystemOrExecutesCode: false) + } + let lowered = trimmed.lowercased() + if lowered.hasPrefix("mutation") { + return QueryClassification(tier: .write, reachesFilesystemOrExecutesCode: false) + } + if trimmed.hasPrefix("{") || lowered.hasPrefix("query") || lowered.hasPrefix("fragment") { + return weaviateDeclaresMutation(trimmed) + ? QueryClassification(tier: .write, reachesFilesystemOrExecutesCode: false) + : .safe + } + let (verb, path) = typesenseRequestLine(trimmed) + if verb == "GET" || verb == "HEAD" { + return .safe + } + if verb == "POST", path == "/V1/GRAPHQL" { + return weaviateDeclaresMutation(weaviateConsoleBody(trimmed)) + ? QueryClassification(tier: .write, reachesFilesystemOrExecutesCode: false) + : .safe + } + if verb == "DELETE" { + return QueryClassification(tier: .destructive, reachesFilesystemOrExecutesCode: false) + } + if verb.isEmpty { + return .safe + } + return QueryClassification(tier: .write, reachesFilesystemOrExecutesCode: false) + } } diff --git a/TablePro/Models/Connection/DatabaseType.swift b/TablePro/Models/Connection/DatabaseType.swift index db70ba1768..713c7e0331 100644 --- a/TablePro/Models/Connection/DatabaseType.swift +++ b/TablePro/Models/Connection/DatabaseType.swift @@ -49,6 +49,7 @@ extension DatabaseType { static let typesense = DatabaseType(rawValue: "Typesense") static let teradata = DatabaseType(rawValue: "Teradata") static let trino = DatabaseType(rawValue: "Trino") + static let weaviate = DatabaseType(rawValue: "Weaviate") } extension DatabaseType: Codable { diff --git a/TableProMobile/TableProMobile/Assets.xcassets/weaviate-icon.imageset/Contents.json b/TableProMobile/TableProMobile/Assets.xcassets/weaviate-icon.imageset/Contents.json new file mode 100644 index 0000000000..fcfa2ae760 --- /dev/null +++ b/TableProMobile/TableProMobile/Assets.xcassets/weaviate-icon.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images": [ + { + "filename": "weaviate.svg", + "idiom": "universal" + } + ], + "info": { + "author": "xcode", + "version": 1 + }, + "properties": { + "preserves-vector-representation": true, + "template-rendering-intent": "template" + } +} diff --git a/TableProMobile/TableProMobile/Assets.xcassets/weaviate-icon.imageset/weaviate.svg b/TableProMobile/TableProMobile/Assets.xcassets/weaviate-icon.imageset/weaviate.svg new file mode 100644 index 0000000000..fafccd810f --- /dev/null +++ b/TableProMobile/TableProMobile/Assets.xcassets/weaviate-icon.imageset/weaviate.svg @@ -0,0 +1 @@ +Weaviate diff --git a/TableProMobile/TableProWidget/Assets.xcassets/weaviate-icon.imageset/Contents.json b/TableProMobile/TableProWidget/Assets.xcassets/weaviate-icon.imageset/Contents.json new file mode 100644 index 0000000000..fcfa2ae760 --- /dev/null +++ b/TableProMobile/TableProWidget/Assets.xcassets/weaviate-icon.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images": [ + { + "filename": "weaviate.svg", + "idiom": "universal" + } + ], + "info": { + "author": "xcode", + "version": 1 + }, + "properties": { + "preserves-vector-representation": true, + "template-rendering-intent": "template" + } +} diff --git a/TableProMobile/TableProWidget/Assets.xcassets/weaviate-icon.imageset/weaviate.svg b/TableProMobile/TableProWidget/Assets.xcassets/weaviate-icon.imageset/weaviate.svg new file mode 100644 index 0000000000..fafccd810f --- /dev/null +++ b/TableProMobile/TableProWidget/Assets.xcassets/weaviate-icon.imageset/weaviate.svg @@ -0,0 +1 @@ +Weaviate diff --git a/TableProMobile/TableProWidget/Helpers/DatabaseTypeStyle.swift b/TableProMobile/TableProWidget/Helpers/DatabaseTypeStyle.swift index c5e91110f7..3c35e2db30 100644 --- a/TableProMobile/TableProWidget/Helpers/DatabaseTypeStyle.swift +++ b/TableProMobile/TableProWidget/Helpers/DatabaseTypeStyle.swift @@ -22,6 +22,7 @@ enum DatabaseTypeStyle { case "DynamoDB": return "dynamodb-icon" case "BigQuery": return "bigquery-icon" case "Spanner": return "spanner-icon" + case "Weaviate": return "weaviate-icon" default: return "externaldrive" } } diff --git a/TableProTests/Core/Plugins/PluginMetadataRegistryTypeCountTests.swift b/TableProTests/Core/Plugins/PluginMetadataRegistryTypeCountTests.swift index ef6d5a6e67..c5300773f3 100644 --- a/TableProTests/Core/Plugins/PluginMetadataRegistryTypeCountTests.swift +++ b/TableProTests/Core/Plugins/PluginMetadataRegistryTypeCountTests.swift @@ -11,7 +11,7 @@ import Testing /// this registry, `docs/snippets/driver-counts.mdx`, and the marketing site. Nothing at runtime /// reconciles them, and by August 2026 they read 28, 27 and 25 at once. /// -/// The answer is 34, and the reason it once read 28 is worth keeping. Turso is served by +/// The answer is 35, and the reason it once read 28 is worth keeping. Turso is served by /// the libSQL plugin and was the only alias in `reverseTypeIndex` with no curated entry of its /// own, so it was the only type the picker could not offer before its plugin was installed. /// ScyllaDB is the shape every other alias already had: an alias of Cassandra with a curated @@ -24,7 +24,7 @@ import Testing /// `docs/scripts/check-docs-against-source.py` reads the registry and holds the docs half. /// /// The count is taken from the built-in defaults rather than from `allRegisteredTypeIds()`. -/// Both answer 34 under XCTest, where no plugin bundle ever loads, but the registry is a +/// Both answer 35 under XCTest, where no plugin bundle ever loads, but the registry is a /// process-global singleton and suites that register a synthetic type run alongside this one. @MainActor @Suite("PluginMetadataRegistry engine count") @@ -34,7 +34,7 @@ struct PluginMetadataRegistryTypeCountTests { "CockroachDB", "Dameng", "Databend", "DuckDB", "DynamoDB", "Elasticsearch", "etcd", "Kafka", "libSQL", "MariaDB", "MongoDB", "MySQL", "Oracle", "PGlite", "PostgreSQL", "Redis", "Redshift", "ScyllaDB", "Snowflake", "Spanner", "SQL Server", "SQLite", "SurrealDB", "Teradata", "TiDB", "Trino", - "Turso", "Typesense" + "Turso", "Typesense", "Weaviate" ] private static func builtInTypeIds() -> Set { @@ -43,10 +43,10 @@ struct PluginMetadataRegistryTypeCountTests { return Set(curated + registry) } - @Test("The app ships 34 database types before any plugin loads") + @Test("The app ships 35 database types before any plugin loads") func builtInDefaultsCoverTwentyNineTypes() { let ids = Self.builtInTypeIds() - #expect(ids.count == 34) + #expect(ids.count == 35) #expect(ids == Self.expectedTypeIds) } diff --git a/TableProTests/Core/Utilities/SQL/QueryClassifierHardeningTests.swift b/TableProTests/Core/Utilities/SQL/QueryClassifierHardeningTests.swift index 6b5ad141ab..704293ee76 100644 --- a/TableProTests/Core/Utilities/SQL/QueryClassifierHardeningTests.swift +++ b/TableProTests/Core/Utilities/SQL/QueryClassifierHardeningTests.swift @@ -545,6 +545,52 @@ struct QueryClassifierNonSqlTests { ) } + @Test("Weaviate GraphQL reads are safe and uuid deletes are destructive") + func weaviateTiers() { + #expect(!QueryClassifier.isWriteQuery("{ Get { Article { title } } }", databaseType: .weaviate)) + #expect(!QueryClassifier.isWriteQuery("query { Get { Article { title } } }", databaseType: .weaviate)) + #expect(!QueryClassifier.isWriteQuery("GET /v1/schema", databaseType: .weaviate)) + #expect(!QueryClassifier.isWriteQuery("POST /v1/graphql {}", databaseType: .weaviate)) + #expect(QueryClassifier.isWriteQuery("mutation { delete { Article } }", databaseType: .weaviate)) + #expect(QueryClassifier.isWriteQuery("POST /v1/objects {}", databaseType: .weaviate)) + #expect(QueryClassifier.classifyTier("DELETE /v1/objects/abc", databaseType: .weaviate) == .destructive) + let search = "WEAVIATE_SEARCH:e30=" + #expect(!QueryClassifier.isWriteQuery(search, databaseType: .weaviate)) + } + + @Test("A console body declaring a mutation is classified the same as a bare one") + func weaviateConsoleBodyIsRead() { + #expect(QueryClassifier.isWriteQuery( + "POST /v1/graphql\nmutation { delete { Article } }", + databaseType: .weaviate + )) + #expect(QueryClassifier.isWriteQuery( + "POST /v1/graphql\n{\"query\": \"mutation { delete { Article } }\"}", + databaseType: .weaviate + )) + #expect(!QueryClassifier.isWriteQuery( + "POST /v1/graphql\n{\"query\": \"{ Get { Article { title } } }\"}", + databaseType: .weaviate + )) + #expect(!QueryClassifier.isWriteQuery( + "POST /v1/graphql?pretty\n{ Get { Article { title } } }", + databaseType: .weaviate + )) + } + + @Test("A mutation inside a query envelope is a write however it is typed") + func weaviateEnvelopeIsRead() { + #expect(QueryClassifier.isWriteQuery( + "{\"query\": \"mutation { delete { Article } }\"}", + databaseType: .weaviate + )) + #expect(!QueryClassifier.isWriteQuery( + "{\"query\": \"{ Get { Article { title } } }\"}", + databaseType: .weaviate + )) + #expect(!QueryClassifier.isWriteQuery("{ Get { Article { title } } }", databaseType: .weaviate)) + } + @Test("Elasticsearch stored scripts are flagged as code execution on both verbs") func elasticsearchScriptsAreFlagged() { #expect( diff --git a/TableProTests/Plugins/WeaviateConnectionFieldsTests.swift b/TableProTests/Plugins/WeaviateConnectionFieldsTests.swift new file mode 100644 index 0000000000..3046f3bd04 --- /dev/null +++ b/TableProTests/Plugins/WeaviateConnectionFieldsTests.swift @@ -0,0 +1,141 @@ +import Foundation +@testable import TablePro +import TableProPluginKit +import TableProWeaviateCore +import Testing + +@Suite("Weaviate registry snapshot") +struct WeaviateRegistrySnapshotTests { + private func snapshot() throws -> PluginMetadataSnapshot { + let defaults = PluginMetadataRegistry.shared.registryPluginDefaults() + return try #require(defaults.first { $0.typeId == "Weaviate" }).snapshot + } + + @Test("Weaviate is a collection engine on port 8080 with no SQL dialect") + func connectionShape() throws { + let snapshot = try snapshot() + #expect(snapshot.defaultPort == 8_080) + #expect(snapshot.editor.sqlDialect == nil) + #expect(snapshot.queryLanguageName == "GraphQL") + #expect(snapshot.schema.tableEntityName == "Collections") + #expect(snapshot.schema.defaultPrimaryKeyColumn == "uuid") + #expect(snapshot.schema.immutableColumns == ["uuid", "vector"]) + #expect(!snapshot.supportsForeignKeys) + #expect(!snapshot.capabilities.supportsSSH) + #expect(snapshot.capabilities.supportsSSL) + #expect(snapshot.connection.category == .document) + #expect(snapshot.iconName == "weaviate-icon") + } + + @Test("Auth field ids are Weaviate-prefixed and do not collide with Elasticsearch") + func authFieldIdsArePrefixed() throws { + let ids = try snapshot().connection.additionalConnectionFields.map(\.id) + #expect(ids == [ + WeaviateFieldID.authMethod, + WeaviateFieldID.apiKey, + WeaviateFieldID.skipTLSVerify + ]) + #expect(!ids.contains("esAuthMethod")) + #expect(!ids.contains("esApiKey")) + let elasticsearch = try #require( + PluginMetadataRegistry.shared.registryPluginDefaults().first { $0.typeId == "Elasticsearch" } + ) + let esIds = elasticsearch.snapshot.connection.additionalConnectionFields.map(\.id) + #expect(Set(ids).isDisjoint(with: Set(esIds))) + } +} + +@Suite("Weaviate connection fields") +struct WeaviateConnectionFieldsTests { + private func fields() throws -> [ConnectionField] { + let defaults = PluginMetadataRegistry.shared.registryPluginDefaults() + let entry = try #require(defaults.first { $0.typeId == "Weaviate" }) + return entry.snapshot.connection.additionalConnectionFields + } + + @Test("Auth method defaults to none") + func authMethodDefaultsToNone() throws { + let fields = try fields() + let method = try #require(fields.first { $0.id == WeaviateFieldID.authMethod }) + #expect(method.defaultValue == "none") + guard case .dropdown(let options) = method.fieldType else { + Issue.record("Expected a dropdown field type") + return + } + #expect(options.map(\.value) == ["none", "apiKey"]) + } + + @Test("The API key replaces both built-in credential rows") + func apiKeyReplacesUsernameAndPassword() throws { + let fields = try fields() + let apiKey = try #require(fields.first { $0.id == WeaviateFieldID.apiKey }) + #expect(apiKey.isSecure) + #expect(!apiKey.isRequired) + #expect(apiKey.hidesPassword) + #expect(fields.hidesPassword(forValues: [:])) + #expect(fields.hidesUsername(forValues: [:])) + #expect(fields.hidesPassword(forValues: [WeaviateFieldID.authMethod: "none"])) + #expect(fields.hidesPassword(forValues: [WeaviateFieldID.authMethod: "apiKey"])) + #expect(fields.hidesUsername(forValues: [WeaviateFieldID.authMethod: "none"])) + #expect(fields.hidesUsername(forValues: [WeaviateFieldID.authMethod: "apiKey"])) + } + + @Test("The snapshot hides the built-in password for every auth method") + @MainActor + func snapshotHidesBuiltInPassword() throws { + let defaults = PluginMetadataRegistry.shared.registryPluginDefaults() + let snapshot = try #require(defaults.first { $0.typeId == "Weaviate" }).snapshot + #expect(snapshot.connection.hidesBuiltInPassword) + for method in ["none", "apiKey"] { + var connection = DatabaseConnection(name: "Weaviate", type: .weaviate) + connection.additionalFields = [WeaviateFieldID.authMethod: method] + #expect(PluginManager.shared.hidesPassword(for: connection), "\(method)") + } + } +} + +@Suite("Weaviate field parity") +struct WeaviateFieldParityTests { + private static let repoRoot = URL(fileURLWithPath: #filePath) + .deletingLastPathComponent() + .deletingLastPathComponent() + .deletingLastPathComponent() + + private func source(_ path: String) throws -> String { + try String(contentsOf: Self.repoRoot.appendingPathComponent(path), encoding: .utf8) + } + + /// The plugin's own field list replaces the registry snapshot the moment the plugin is + /// installed, and no test can link both copies, so the two sources are compared as text. + @Test("The plugin's field list matches the registry copy") + func pluginCopyMatchesRegistryCopy() throws { + let plugin = try source("Plugins/WeaviateDriverPlugin/WeaviatePlugin.swift") + let registry = try source("TablePro/Core/Plugins/PluginMetadataRegistry+WeaviateDefaults.swift") + for field in [WeaviateFieldID.authMethod, WeaviateFieldID.apiKey, WeaviateFieldID.skipTLSVerify] { + #expect(registry.contains("id: \"\(field)\""), Comment(rawValue: field)) + } + #expect(plugin.contains("id: WeaviateFieldID.authMethod")) + #expect(plugin.contains("id: WeaviateFieldID.apiKey")) + #expect(plugin.contains("id: WeaviateFieldID.skipTLSVerify")) + for copy in [plugin, registry] { + #expect(copy.contains("hidesPassword: true")) + #expect(copy.contains("withHidesUsername(true)")) + #expect(copy.contains("apiKey")) + } + } +} + +@Suite("Weaviate plugin manifest") +struct WeaviatePluginManifestTests { + @Test("Info.plist declares PluginKit 25 and the Weaviate type id") + func plistDeclaresType() throws { + let url = URL(fileURLWithPath: #filePath) + .deletingLastPathComponent() + .deletingLastPathComponent() + .deletingLastPathComponent() + .appendingPathComponent("Plugins/WeaviateDriverPlugin/Info.plist") + let plist = try #require(NSDictionary(contentsOf: url) as? [String: Any]) + #expect(plist["TableProPluginKitVersion"] as? Int == 25) + #expect(plist["TableProProvidesDatabaseTypeIds"] as? [String] == ["Weaviate"]) + } +} diff --git a/docs/connections/connection-form.mdx b/docs/connections/connection-form.mdx index adf4952cea..04b99c7ecb 100644 --- a/docs/connections/connection-form.mdx +++ b/docs/connections/connection-form.mdx @@ -128,6 +128,7 @@ Metadata connections, the extra ones TablePro opens to read a database's object | [SurrealDB](/databases/surrealdb) | 8000 | Yes | Yes | Yes | No | Yes | Yes | | [Elasticsearch](/databases/elasticsearch) | 9200 | No | Yes | No | No | No | No | | [Typesense](/databases/typesense) | 8108 | No | Yes | No | No | No | No | +| [Weaviate](/databases/weaviate) | 8080 | No | Yes | No | No | No | No | | [Snowflake](/databases/snowflake) | 443 | No | No | No | No | No | No | | [SQLite](/databases/sqlite) | File | No | No | No | No | No | No | | [DuckDB](/databases/duckdb) | File | No | No | No | No | No | No | diff --git a/docs/connections/ssh-tunneling.mdx b/docs/connections/ssh-tunneling.mdx index 84626b658d..fbdbc365d1 100644 --- a/docs/connections/ssh-tunneling.mdx +++ b/docs/connections/ssh-tunneling.mdx @@ -37,7 +37,7 @@ To share one SSH config across connections, save it with **Save Current as Profi Network section with SSH Tunnel selected and a saved profile in the Profile picker -**SSH Tunnel** is not offered on SQLite, PGlite, libSQL, Beancount, BigQuery, Spanner, Cloudflare D1, Cloudflare R2 SQL, DynamoDB, Elasticsearch, Typesense, or Snowflake: each is reached over a local file, a loopback socket, or a vendor HTTP API. +**SSH Tunnel** is not offered on SQLite, PGlite, libSQL, Beancount, BigQuery, Spanner, Cloudflare D1, Cloudflare R2 SQL, DynamoDB, Elasticsearch, Typesense, Weaviate, or Snowflake: each is reached over a local file, a loopback socket, or a vendor HTTP API. ## Authentication methods diff --git a/docs/connections/ssl.mdx b/docs/connections/ssl.mdx index 470bb8c21c..81b6c35e8e 100644 --- a/docs/connections/ssl.mdx +++ b/docs/connections/ssl.mdx @@ -43,7 +43,7 @@ A new connection starts on the mode that matches the driver's own default, and t | MySQL, MariaDB | Preferred | Tries TLS, then retries plain on an SSL handshake error. Auth and network errors are not retried | | SQL Server | Preferred | FreeTDS `encryption=request`, falls back to plain | | Teradata | Disabled | Opens a TLS transport, retries on a plain socket if it fails to come up | -| MongoDB, Redis, Cassandra, ClickHouse, Elasticsearch, Typesense, SurrealDB | Disabled | Nothing. No fallback exists, so Preferred forces TLS exactly like Required | +| MongoDB, Redis, Cassandra, ClickHouse, Elasticsearch, Typesense, SurrealDB, Weaviate | Disabled | Nothing. No fallback exists, so Preferred forces TLS exactly like Required | | etcd | Disabled | Nothing. The driver never reads these fields. Set **TLS Mode** on the Options section instead, and see [etcd](/databases/etcd) | | Trino | Disabled | Sends every request over HTTPS with no fallback, again like Required | | Oracle | Disabled | Connects in plain TCP, so it behaves like Disabled. A red warning appears under the picker; use Required to enforce TCPS | diff --git a/docs/databases/index.mdx b/docs/databases/index.mdx index c0d2e822b9..a5cb337dc9 100644 --- a/docs/databases/index.mdx +++ b/docs/databases/index.mdx @@ -1,11 +1,11 @@ --- title: Supported Databases -description: All 34 engines TablePro connects to, their default ports, and which ones need a plugin +description: All 35 engines TablePro connects to, their default ports, and which ones need a plugin --- import DriverCounts from "/snippets/driver-counts.mdx"; -Thirty-four engines, and every one of them is free to use. What differs between them is where the +Thirty-five engines, and every one of them is free to use. What differs between them is where the driver comes from, not what the license covers. @@ -48,6 +48,7 @@ driver comes from, not what the license covers. | [Trino](/databases/trino) | 8080 | Plugin | | [Typesense](/databases/typesense) | 8108 | Plugin | | [Turso](/databases/libsql) | API-based | Plugin | +| [Weaviate](/databases/weaviate) | 8080 | Plugin | Rows sharing a page share a driver. MariaDB reads as MySQL, ScyllaDB as Cassandra, Turso as libSQL, and Redshift, CockroachDB and PGlite all speak the PostgreSQL wire protocol. TiDB and Databend diff --git a/docs/databases/weaviate.mdx b/docs/databases/weaviate.mdx new file mode 100644 index 0000000000..d1dfc1a8c5 --- /dev/null +++ b/docs/databases/weaviate.mdx @@ -0,0 +1,132 @@ +--- +title: Weaviate +description: Connect to Weaviate, browse collections, edit objects by uuid, and run GraphQL +--- + +import RegistryPlugin from "/snippets/registry-plugin.mdx"; + +Collections are tables, objects are rows, and `uuid` is the primary key. The editor speaks GraphQL, not SQL. Vector and hybrid search go through `/v1/graphql`. Browse and row edits use `/v1/objects`. + + + +## Quick setup + +Click **New Connection…**, select **Weaviate**, enter host and port, pick an **Auth Method**, then click **Save & Connect**. + +There is no Database field. One connection reaches one Weaviate instance, and its collections are the objects. + +## Connection settings + +| Field | Description | +|-------|-------------| +| **Host** | Node hostname. `localhost` for Docker, a Weaviate Cloud hostname for hosted clusters | +| **Port** | `8080` by default. Weaviate Cloud answers on `443` | +| **Auth Method** | None, or API Key | +| **API Key** | Sent as an `Authorization: Bearer` header, and only when **Auth Method** is API Key | +| **Skip TLS Verification** | Advanced section. Trusts any certificate, even under **Verify CA** or **Verify Identity** | + +## Authentication + +| Auth Method | What is sent | +|-------------|--------------| +| **None** | Nothing. For a local node with anonymous access | +| **API Key** | An `Authorization: Bearer` header. Paste the Weaviate Cloud key, or the key the local node was started with | + +Weaviate Cloud requires an API key and HTTPS. Set **SSL Mode** to **Required** (or **Verify Identity** if you have the CA) and **Auth Method** to API Key. + +## Browsing collections + +The sidebar lists collections from `GET /v1/schema`. + +Every grid has `uuid` first and `vector` last. `uuid` is the primary key. Both columns are read-only. Property columns come from the collection schema. Arrays and objects render as JSON in the cell. + +A vector is shown as a JSON number array. It is not a SQL BLOB and the inline editor does not write it back. + +Unfiltered pages load through `GET /v1/objects`. A column filter or a sort becomes a GraphQL `Get` with `where` and `sort`. + +## Filtering + +Filter values are typed from the collection schema: an `int` property filters as a number, a `date` property needs a full RFC 3339 timestamp such as `2024-01-31T00:00:00Z`, and an array property filters on one element. + +| Operator | What Weaviate runs | +|----------|--------------------| +| **=**, **!=** | `Equal`, `NotEqual` | +| **>**, **>=**, **<**, **<=** | Numbers and dates only | +| **CONTAINS**, **NOT CONTAINS**, **STARTS WITH**, **ENDS WITH** | `Like` with `*` wildcards, text properties only | +| **IN**, **NOT IN** | `ContainsAny`, `ContainsNone` over a comma-separated list | +| **BETWEEN** | Two bounds, both inclusive | +| **IS NULL**, **IS NOT NULL** | `IsNull`, which needs `indexNullState` on the collection | +| **IS EMPTY**, **IS NOT EMPTY** | `len()`, which needs `indexPropertyLength` on the collection | + +**REGEX** has no Weaviate equivalent, and a filter Weaviate cannot run reports why instead of returning the whole collection. + +Grid edits are REST calls keyed by `uuid`. + +| Change | Request | +|--------|---------| +| New row | `POST /v1/objects`, with an `id` if you typed one | +| Edited cells | `PATCH /v1/objects/{uuid}?class=Collection` | +| Deleted row | `DELETE /v1/objects/{uuid}?class=Collection` | + +An update or delete with no `uuid` is skipped and logged. + +## GraphQL editor + +Type a GraphQL operation and run it. Weaviate's GraphQL API reads only: `{ Get { … } }` and `query { … }` work, and there is no mutation type. Writes go through REST. + +```graphql +{ + Get { + Article( + nearText: { concepts: ["search term"] } + limit: 10 + ) { + title + _additional { id distance } + } + } +} +``` + +`Get` responses render as a grid of the fields the query selected, with `_additional.id` mapped to `uuid`. The rest of `_additional`, such as `distance` and `score`, each become a column. Anything else, including `Aggregate`, is shown as formatted JSON. + +A REST line also runs, the way the other search drivers do: + +```http +GET /v1/schema +``` + +A path without `/v1` gets it, so `GET /nodes` reaches `/v1/nodes`. A body goes on the same line as the path or on the lines under it. + +## SSL/TLS + +New connections start on **Disabled**, plain HTTP. Every other mode goes over HTTPS. **Preferred** and **Required (skip verify)** accept a self-signed certificate. See [SSL/TLS](/connections/ssl). + +## Limitations + +- Oracle-style SQL is not available. Use GraphQL, or the REST console for `/v1/schema` and `/v1/objects`. +- gRPC is not used. +- Cross-references are properties, not foreign keys. There are no routines, triggers, or schema edits from Structure. +- Multi-tenancy is not exposed. Name a tenant in GraphQL if the collection requires one. +- Paging stops at row 10,000. Weaviate refuses an offset and limit that add up past `QUERY_MAXIMUM_RESULTS`, which defaults to 10,000. +- No [SSH tunnel](/connections/ssh-tunneling). +- The plugin is registry-only. It is not on iPhone or iPad. + +## Troubleshooting + +### Authentication failed: … + +The API key was rejected, or the node expects a key and **Auth Method** is None. Weaviate Cloud needs both HTTPS and an API key. + +### The connection drops after the API key changes + +A revoked or rotated key fails the next health check, because the check reads `/v1/meta` rather than the unauthenticated readiness endpoint. Paste the new key and connect again. + +### Connection failed: … + +A TLS or network failure. For a self-signed certificate set **SSL Mode** to **Required (skip verify)**, or turn on **Skip TLS Verification**. + +## Related + +- [Import & Export](/features/import-export) +- [Filtering](/features/filtering) diff --git a/docs/docs.json b/docs/docs.json index 43abd690e3..43c7fc135d 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -175,7 +175,8 @@ "databases/teradata", "databases/tidb", "databases/trino", - "databases/typesense" + "databases/typesense", + "databases/weaviate" ] }, { diff --git a/docs/index.mdx b/docs/index.mdx index 4f67682ea0..062214abf9 100644 --- a/docs/index.mdx +++ b/docs/index.mdx @@ -1,6 +1,6 @@ --- title: Introduction -description: Native macOS database client for MySQL, PostgreSQL, SQLite, MongoDB, Redis, and 29 more +description: Native macOS database client for MySQL, PostgreSQL, SQLite, MongoDB, Redis, and 30 more --- import DriverCounts from "/snippets/driver-counts.mdx"; diff --git a/docs/snippets/driver-counts.mdx b/docs/snippets/driver-counts.mdx index 36442e09d9..b7e36c271a 100644 --- a/docs/snippets/driver-counts.mdx +++ b/docs/snippets/driver-counts.mdx @@ -1,3 +1,3 @@ -Five drivers ship inside the app and cover eleven databases. Twenty-one registry plugins cover the -other twenty-three and install on the first connection that needs one. See +Five drivers ship inside the app and cover eleven databases. Twenty-two registry plugins cover the +other twenty-four and install on the first connection that needs one. See [Plugins & Themes](/features/plugins). diff --git a/project.yml b/project.yml index d745d85f94..c8943891f0 100644 --- a/project.yml +++ b/project.yml @@ -639,7 +639,7 @@ targets: dependencies: - target: TablePro - package: TableProCore - products: [TableProMSSQLCore, TableProNumberFormatting] + products: [TableProMSSQLCore, TableProNumberFormatting, TableProWeaviateCore] # The Kafka integration suite drives the real driver, so the test target links what # the plugin target links: zstd for decompression and NIO for the transport. - package: zstd @@ -1262,6 +1262,15 @@ targets: - package: TableProCore product: TableProNumberFormatting + WeaviateDriverPlugin: + templates: [DriverPlugin] + templateAttributes: + folder: WeaviateDriverPlugin + principalClass: WeaviatePlugin + dependencies: + - package: TableProCore + product: TableProWeaviateCore + # Compile-checks every plugin, including the registry-only ones the app does not # embed. CI builds this scheme so a registry plugin cannot rot between releases. aggregateTargets: @@ -1306,6 +1315,7 @@ aggregateTargets: - TeradataDriver - TrinoDriverPlugin - TypesenseDriverPlugin + - WeaviateDriverPlugin - XLSXExport scheme: {} From 5c175dd81c62ace1bf5990b5b824bb5249e50e68 Mon Sep 17 00:00:00 2001 From: Ngo Quoc Dat Date: Sat, 12 Sep 2026 09:28:29 +0700 Subject: [PATCH 40/54] fix(plugin-mysql): apply the query timeout to OceanBase statements that are not read-only --- .../MySQLPluginDriver+Flavor.swift | 26 ++++++++++++--- .../MySQLDriverPlugin/MySQLServerFlavor.swift | 32 +++++++++---------- .../DockerComposeExtractor.swift | 20 ++++++++---- .../ProjectYamlExtractorTests.swift | 21 ++++++++++++ .../Plugins/MySQLServerFlavorTests.swift | 2 +- 5 files changed, 72 insertions(+), 29 deletions(-) diff --git a/Plugins/MySQLDriverPlugin/MySQLPluginDriver+Flavor.swift b/Plugins/MySQLDriverPlugin/MySQLPluginDriver+Flavor.swift index aca207660c..a4179cd257 100644 --- a/Plugins/MySQLDriverPlugin/MySQLPluginDriver+Flavor.swift +++ b/Plugins/MySQLDriverPlugin/MySQLPluginDriver+Flavor.swift @@ -59,11 +59,7 @@ extension MySQLPluginDriver { } if variant == MySQLServerFlavor.oceanbaseVariant { - guard let comment = await firstValue(of: MySQLFlavorResolution.oceanbaseProbe, on: connection), - MySQLServerFlavor.namesOceanBase(comment) else { - throw MySQLFlavorMismatchError(kind: .notOceanBase) - } - return .oceanbase(version: MySQLServerFlavor.oceanbaseVersion(fromVersionComment: comment)) + return try await oceanbaseFlavor(on: connection) } guard MySQLFlavorResolution.needsTiDBVersionProbe(banner: banner, variant: variant) else { @@ -76,6 +72,26 @@ extension MySQLPluginDriver { return .tidb(version: version) } + /// The handshake banner is a plain MySQL version on OceanBase, so `@@version_comment` is the only + /// thing that names the engine and the connection cannot be confirmed without it. A server that + /// answers with another engine's comment is refused; a probe that does not answer at all is not + /// evidence of anything, and failing there would turn one unlucky reconnect into a connection the + /// user cannot reopen. + private func oceanbaseFlavor(on connection: MariaDBPluginConnection) async throws -> MySQLServerFlavor { + let comment: String + do { + comment = try await connection.executeQuery(MySQLFlavorResolution.oceanbaseProbe) + .rows.first?.first?.asText ?? "" + } catch { + Self.logger.debug("OceanBase probe failed: \(error.localizedDescription, privacy: .public)") + return .oceanbase(version: nil) + } + guard MySQLServerFlavor.namesOceanBase(comment) else { + throw MySQLFlavorMismatchError(kind: .notOceanBase) + } + return .oceanbase(version: MySQLServerFlavor.oceanbaseVersion(fromVersionComment: comment)) + } + func killTarget(for flavor: MySQLServerFlavor, on connection: MariaDBPluginConnection) async -> MySQLKillTarget { guard flavor.isTiDB || flavor.isDatabend else { return .threadId } let identifier = await firstValue(of: MySQLFlavorResolution.connectionIdentifierProbe, on: connection) diff --git a/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift b/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift index 98c5b13f61..cb8435c2fa 100644 --- a/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift +++ b/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift @@ -87,21 +87,11 @@ nonisolated internal enum MySQLServerFlavor: Equatable, Sendable { var isDatabend: Bool { self == .databend } - var isOceanBase: Bool { - guard case .oceanbase = self else { return false } - return true - } - var tidbVersion: MySQLEngineVersion? { guard case .tidb(let version) = self else { return nil } return version } - var oceanbaseVersion: MySQLEngineVersion? { - guard case .oceanbase(let version) = self else { return nil } - return version - } - var systemDatabaseNames: [String] { switch self { case .mysql, .mariadb: @@ -136,21 +126,29 @@ nonisolated internal enum MySQLServerFlavor: Equatable, Sendable { } /// OceanBase enforces `ob_query_timeout` of its own, 10 seconds by default, and - /// `max_execution_time` only outranks it while it is above zero. Zero is the setting's "no - /// limit", which an export relies on, so it has to lift OceanBase's own limit as well. The - /// server clamps the value it accepts there and warns; this is what it clamps to. + /// `max_execution_time` governs read-only statements alone: measured on 4.4.2.1, an `UPDATE` + /// under a 30 second `max_execution_time` still failed at 10 seconds with error 4012. So the + /// setting has to move OceanBase's own limit, in microseconds, whatever its value. Zero is the + /// setting's "no limit", which an export relies on, and the server clamps what it accepts + /// there; this is what it clamps to. static let oceanbaseUnlimitedQueryTimeoutMicroseconds = 3_216_672_000_000_000 + static func oceanbaseQueryTimeoutStatement(seconds: Int) -> String { + let microseconds = seconds > 0 + ? seconds * 1_000_000 + : oceanbaseUnlimitedQueryTimeoutMicroseconds + return "SET SESSION max_execution_time = \(max(seconds, 0) * 1_000), ob_query_timeout = \(microseconds)" + } + func queryTimeoutStatement(seconds: Int) -> String { switch self { case .mariadb: return "SET SESSION max_statement_time = \(seconds)" case .databend: return "SET max_execute_time_in_seconds = \(seconds)" - case .oceanbase where seconds <= 0: - return "SET SESSION max_execution_time = 0, ob_query_timeout = " - + "\(Self.oceanbaseUnlimitedQueryTimeoutMicroseconds)" - case .mysql, .tidb, .oceanbase: + case .oceanbase: + return Self.oceanbaseQueryTimeoutStatement(seconds: seconds) + case .mysql, .tidb: return "SET SESSION max_execution_time = \(seconds * 1_000)" } } diff --git a/TablePro/Core/Services/ProjectImport/DockerComposeExtractor.swift b/TablePro/Core/Services/ProjectImport/DockerComposeExtractor.swift index 6e7ab04f7b..925489ae79 100644 --- a/TablePro/Core/Services/ProjectImport/DockerComposeExtractor.swift +++ b/TablePro/Core/Services/ProjectImport/DockerComposeExtractor.swift @@ -4,6 +4,7 @@ // import Foundation +import TableProPluginKit enum DockerComposeExtractor { struct ServiceDatabase { @@ -116,6 +117,18 @@ enum DockerComposeExtractor { return nil } + /// OBProxy routes by a cluster the observer's own port does not need, and `root@sys` reaches it + /// only when the proxy was given a default cluster, so the name goes into the username whenever + /// the compose file states it. + private static func applyOceanBaseCredentials(_ fields: inout ScannedConnectionFields, variables: [String: String]) { + let tenantPassword = variables["OB_TENANT_PASSWORD"]?.nilIfEmpty + let tenant = variables["OB_TENANT_NAME"]?.nilIfEmpty ?? (tenantPassword != nil ? "test" : "sys") + let cluster = variables["OB_CLUSTER_NAME"]?.nilIfEmpty + fields.username = "root@\(tenant)" + (cluster.map { "#\($0)" } ?? "") + fields.password = tenant == "sys" ? variables["OB_SYS_PASSWORD"] ?? "" : tenantPassword ?? "" + fields.database = variables["OB_DATABASE"] ?? "" + } + static func repositoryComponents(of image: String) -> [String] { let withoutDigest = image.split(separator: "@", maxSplits: 1).first.map(String.init) ?? image var components = withoutDigest.split(separator: "/").map(String.init) @@ -193,12 +206,7 @@ enum DockerComposeExtractor { fields.password = variables["QUERY_DEFAULT_PASSWORD"] ?? "" fields.database = "default" case .oceanbase: - let tenant = variables["OB_TENANT_NAME"] ?? (variables["OB_TENANT_PASSWORD"] != nil ? "test" : "sys") - fields.username = "root@\(tenant)" - fields.password = tenant == "sys" - ? variables["OB_SYS_PASSWORD"] ?? "" - : variables["OB_TENANT_PASSWORD"] ?? "" - fields.database = variables["OB_DATABASE"] ?? "" + applyOceanBaseCredentials(&fields, variables: variables) case .mariadb, .mysql: let prefix = variables["MARIADB_PASSWORD"] != nil || variables["MARIADB_DATABASE"] != nil ? "MARIADB" diff --git a/TableProTests/Core/Services/ProjectImport/ProjectYamlExtractorTests.swift b/TableProTests/Core/Services/ProjectImport/ProjectYamlExtractorTests.swift index 774ba1e4a5..317749d3a2 100644 --- a/TableProTests/Core/Services/ProjectImport/ProjectYamlExtractorTests.swift +++ b/TableProTests/Core/Services/ProjectImport/ProjectYamlExtractorTests.swift @@ -305,6 +305,27 @@ struct DockerComposeExtractorTests { #expect(proxy?.parsedURL.port == 2_883) } + @Test("An OBProxy cluster name joins the username, and an empty tenant name keeps the default") + func testOceanBaseClusterAndEmptyTenant() { + let candidates = extract(""" + services: + proxy: + image: oceanbase/obproxy-ce:latest + environment: + OB_CLUSTER_NAME: obcluster + ports: + - "2883:2883" + ob: + image: oceanbase/oceanbase-ce:latest + environment: + OB_TENANT_NAME: "" + ports: + - "2881:2881" + """) + #expect(candidates.first { $0.sourceKey == "services.proxy" }?.parsedURL.username == "root@sys#obcluster") + #expect(candidates.first { $0.sourceKey == "services.ob" }?.parsedURL.username == "root@sys") + } + @Test("OceanBase images that do not serve SQL are not imported") func testOceanBaseNonDatabaseImages() { let candidates = extract(""" diff --git a/TableProTests/Plugins/MySQLServerFlavorTests.swift b/TableProTests/Plugins/MySQLServerFlavorTests.swift index c2c27cd4c1..3035869caa 100644 --- a/TableProTests/Plugins/MySQLServerFlavorTests.swift +++ b/TableProTests/Plugins/MySQLServerFlavorTests.swift @@ -138,7 +138,7 @@ struct MySQLServerFlavorTests { (.mysql, 0, "SET SESSION max_execution_time = 0"), (.mysql, 30, "SET SESSION max_execution_time = 30000"), (.tidb(version: nil), 30, "SET SESSION max_execution_time = 30000"), - (.oceanbase(version: nil), 30, "SET SESSION max_execution_time = 30000"), + (.oceanbase(version: nil), 30, "SET SESSION max_execution_time = 30000, ob_query_timeout = 30000000"), (.oceanbase(version: nil), 0, "SET SESSION max_execution_time = 0, ob_query_timeout = 3216672000000000"), (.databend, 30, "SET max_execute_time_in_seconds = 30") ]) From 72b735a8f815815554e3925bea3a8d760461109d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 09:44:08 +0700 Subject: [PATCH 41/54] test(datagrid): give the pending-change palette the boolean colors its type now requires (#2779) * test(datagrid): give the pending-change palette the boolean colors its type now requires * docs(claude-md): count 41 plugin bundles and list Weaviate among the registry-only ones --- CLAUDE.md | 4 ++-- .../Views/Results/DataGridPendingChangeMarkTests.swift | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 8e61f7bed2..a86f64d6b4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -23,7 +23,7 @@ TablePro is a native macOS database client (SwiftUI + AppKit), a fast, lightweig - **Source**: `TablePro/` holds `Core/` (business logic, services), `Views/` (UI), `Models/` (data structures), `ViewModels/`, `Extensions/` and `Theme/` - **Plugins**: `Plugins/` holds the `.tableplugin` bundles plus the `TableProPluginKit` shared framework. - **Bundled in app** (the 18 targets in the app's `copy: { destination: plugins }` phase in `project.yml`): MySQL, PostgreSQL, SQLite, ClickHouse, Redis, CSV export, JSON export, SQL export, XLSX export, Markdown export, HTML export, XML export, MQL export, SQL import, JSON import, CSV import, XLSX import, CSV inspector. These ship inside the app bundle and their updates normally ride with the next app release. Six of them (`sqlite`, `clickhouse`, `redis`, `xlsx`, `mql`, `sqlimport`) also have registry arms in `build-plugin.yml`, so a bundled plugin can be published when users on an already-shipped app need the fix sooner. `scripts/build-plugin.sh:10` explains the flag that makes that work. - - **Registry-only** (the other 22): MongoDB, Oracle, DuckDB, MSSQL, Cassandra, Etcd, CloudflareD1, CloudflareR2SQL, DynamoDB, BigQuery, Spanner, LibSQL, Snowflake, Elasticsearch, Typesense, Beancount, SurrealDB, Teradata, Trino, Dameng, Kafka, Parquet export. Parquet is registry-only because it links its own copy of DuckDB, which does the encoding, and that is too large to ship in the app for one format. Distributed via [TableProApp/plugins](https://github.com/TableProApp/plugins) `plugins.json`, installed into the user plugins directory. + - **Registry-only** (the other 23): MongoDB, Oracle, DuckDB, MSSQL, Cassandra, Etcd, CloudflareD1, CloudflareR2SQL, DynamoDB, BigQuery, Spanner, LibSQL, Snowflake, Elasticsearch, Typesense, Beancount, SurrealDB, Teradata, Trino, Dameng, Kafka, Weaviate, Parquet export. Parquet is registry-only because it links its own copy of DuckDB, which does the encoding, and that is too large to ship in the app for one format. Distributed via [TableProApp/plugins](https://github.com/TableProApp/plugins) `plugins.json`, installed into the user plugins directory. - **C bridges**: Each plugin contains its own C bridge module (e.g., `Plugins/MySQLDriverPlugin/CMariaDB/`, `Plugins/PostgreSQLDriverPlugin/CLibPQ/`) - **Static libs**: `Libs/` holds pre-built `.a` files and `Libs/ios/` holds the iOS xcframeworks. Both are downloaded by `scripts/download-libs.sh` and are not in git. - **SPM deps**: declared in `project.yml`. Vendored local packages under `LocalPackages/` (CodeEditSourceEditor, CodeEditTextView, CodeEditLanguages) and `Packages/` (TableProCore, TableProOracle); remote packages are Sparkle, swift-certificates and Yams. Revisions are pinned by the tracked `Package.resolved` inside each generated `.xcodeproj`. @@ -103,7 +103,7 @@ git add Libs/ios/checksums.sha256 && git commit -m "build: update iOS xcframewor Run `scripts/generate-project.sh` after editing any of those, and after adding, moving, or deleting a source file: XcodeGen globs sources at generation time, so a new file is not in the project until you regenerate. Changing signing in the Xcode UI is pointless, because the next generate discards it; set `TABLEPRO_DEVELOPMENT_TEAM` and `TABLEPRO_APP_BUNDLE_IDENTIFIER` in `Configs/Secrets.xcconfig` instead. -The 40 plugin bundles share one `DriverPlugin` target template; a plugin declares only its folder, principal class, and any C-library link flags. Every target gets a shared scheme named after it, which is what `scripts/build-plugin.sh [arm64|x86_64|both] [version]` builds. The `AllPlugins` aggregate target compile-checks all 40, including the registry-only ones the app does not embed, and PR CI runs it: the `Compile every plugin` step in the `app-tests` job of `.github/workflows/macos-tests.yml` builds that scheme whenever the change touches `Plugins/` or any other watched path. What PR CI still does not cover is plugin packaging, signing and notarization, which only `build-plugin.yml` does and only on a release tag. +The 41 plugin bundles share one `DriverPlugin` target template; a plugin declares only its folder, principal class, and any C-library link flags. Every target gets a shared scheme named after it, which is what `scripts/build-plugin.sh [arm64|x86_64|both] [version]` builds. The `AllPlugins` aggregate target compile-checks all 41, including the registry-only ones the app does not embed, and PR CI runs it: the `Compile every plugin` step in the `app-tests` job of `.github/workflows/macos-tests.yml` builds that scheme whenever the change touches `Plugins/` or any other watched path. What PR CI still does not cover is plugin packaging, signing and notarization, which only `build-plugin.yml` does and only on a release tag. ### Plugin System diff --git a/TableProTests/Views/Results/DataGridPendingChangeMarkTests.swift b/TableProTests/Views/Results/DataGridPendingChangeMarkTests.swift index 9e3961df6e..d867d39fa9 100644 --- a/TableProTests/Views/Results/DataGridPendingChangeMarkTests.swift +++ b/TableProTests/Views/Results/DataGridPendingChangeMarkTests.swift @@ -22,8 +22,8 @@ struct DataGridPendingChangeMarkTests { mediumFont: .monospacedSystemFont(ofSize: 13, weight: .medium), text: .labelColor, placeholderText: .secondaryLabelColor, - booleanTrueText: nil, - booleanFalseText: nil, + booleanTrueText: .labelColor, + booleanFalseText: .labelColor, rowNumberText: .secondaryLabelColor, deletedRowText: .systemRed, modifiedColumnTint: .systemYellow, From 3837a73575b9e29273e847a315417f9e07d0a87c Mon Sep 17 00:00:00 2001 From: Ngo Quoc Dat Date: Sat, 12 Sep 2026 09:53:56 +0700 Subject: [PATCH 42/54] test(plugins): count OceanBase in the built-in database types --- .../Core/Plugins/PluginMetadataRegistryTypeCountTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TableProTests/Core/Plugins/PluginMetadataRegistryTypeCountTests.swift b/TableProTests/Core/Plugins/PluginMetadataRegistryTypeCountTests.swift index 3b42aeab02..22290af1e4 100644 --- a/TableProTests/Core/Plugins/PluginMetadataRegistryTypeCountTests.swift +++ b/TableProTests/Core/Plugins/PluginMetadataRegistryTypeCountTests.swift @@ -43,10 +43,10 @@ struct PluginMetadataRegistryTypeCountTests { return Set(curated + registry) } - @Test("The app ships 35 database types before any plugin loads") + @Test("The app ships 36 database types before any plugin loads") func builtInDefaultsCoverTwentyNineTypes() { let ids = Self.builtInTypeIds() - #expect(ids.count == 35) + #expect(ids.count == 36) #expect(ids == Self.expectedTypeIds) } From 3a837d649c280e5c29c6521202644cf7d6c7502b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 10:04:41 +0700 Subject: [PATCH 43/54] fix(sidebar): offer maintenance only where it applies and preview the statement that runs (#2726) (#2780) Claude-Session: https://claude.ai/code/session_013prPDi2xCGd2JqrfEnTELn --- CHANGELOG.md | 3 + Plugins/BeancountDriverPlugin/Info.plist | 2 +- Plugins/BigQueryDriverPlugin/Info.plist | 2 +- Plugins/CSVExportPlugin/Info.plist | 2 +- Plugins/CSVImportPlugin/Info.plist | 2 +- Plugins/CassandraDriverPlugin/Info.plist | 2 +- Plugins/ClickHouseDriverPlugin/Info.plist | 2 +- Plugins/CloudflareD1DriverPlugin/Info.plist | 2 +- .../CloudflareR2SQLDriverPlugin/Info.plist | 2 +- Plugins/DamengDriverPlugin/Info.plist | 2 +- Plugins/DuckDBDriverPlugin/Info.plist | 2 +- Plugins/DynamoDBDriverPlugin/Info.plist | 2 +- Plugins/ElasticsearchDriverPlugin/Info.plist | 2 +- Plugins/EtcdDriverPlugin/Info.plist | 2 +- Plugins/HTMLExportPlugin/Info.plist | 2 +- Plugins/JSONExportPlugin/Info.plist | 2 +- Plugins/JSONImportPlugin/Info.plist | 2 +- Plugins/KafkaDriverPlugin/Info.plist | 2 +- Plugins/LibSQLDriverPlugin/Info.plist | 2 +- Plugins/MQLExportPlugin/Info.plist | 2 +- Plugins/MSSQLDriverPlugin/Info.plist | 2 +- Plugins/MarkdownExportPlugin/Info.plist | 2 +- Plugins/MongoDBDriverPlugin/Info.plist | 2 +- Plugins/MySQLDriverPlugin/Info.plist | 2 +- .../MySQLDriverPlugin/MySQLMaintenance.swift | 95 ++++++ .../MySQLDriverPlugin/MySQLPluginDriver.swift | 22 +- .../MySQLDriverPlugin/MySQLServerFlavor.swift | 6 +- Plugins/OracleDriverPlugin/Info.plist | 2 +- Plugins/ParquetExportPlugin/Info.plist | 2 +- Plugins/PostgreSQLDriverPlugin/Info.plist | 2 +- .../PostgreSQLMaintenance.swift | 123 +++++++ .../PostgreSQLPluginDriver.swift | 36 +- Plugins/RedisDriverPlugin/Info.plist | 2 +- Plugins/SQLExportPlugin/Info.plist | 2 +- Plugins/SQLImportPlugin/Info.plist | 2 +- Plugins/SQLiteDriverPlugin/Info.plist | 2 +- .../SQLiteMaintenance.swift | 50 +++ Plugins/SQLiteDriverPlugin/SQLitePlugin.swift | 17 +- Plugins/SnowflakeDriverPlugin/Info.plist | 2 +- Plugins/SpannerDriverPlugin/Info.plist | 2 +- Plugins/SurrealDBDriverPlugin/Info.plist | 2 +- .../PluginDatabaseDriver.swift | 16 + .../PluginMaintenanceOperation.swift | 159 +++++++++ Plugins/TeradataDriverPlugin/Info.plist | 2 +- Plugins/TrinoDriverPlugin/Info.plist | 2 +- Plugins/TypesenseDriverPlugin/Info.plist | 2 +- Plugins/WeaviateDriverPlugin/Info.plist | 2 +- Plugins/XLSXExportPlugin/Info.plist | 2 +- Plugins/XLSXImportPlugin/Info.plist | 2 +- Plugins/XMLExportPlugin/Info.plist | 2 +- TablePro/Core/Database/DatabaseDriver.swift | 33 +- .../Core/MCP/MCPConnectionBridge+Server.swift | 111 +++++- .../MCP/Protocol/Tools/MaintenanceTools.swift | 51 ++- .../Core/Menu/MaintenanceMenuDelegate.swift | 5 +- .../Core/Plugins/PluginDriverAdapter.swift | 20 +- TablePro/Core/Plugins/PluginManager.swift | 10 +- ...itViewController+DatabaseMenuActions.swift | 4 +- .../Database/TableOperationEligibility.swift | 32 ++ ...ainContentCoordinator+SidebarActions.swift | 53 ++- ...ontentCommandActions+DatabaseObjects.swift | 14 +- .../Views/Main/MainContentCoordinator.swift | 9 +- TablePro/Views/Main/MainContentView.swift | 12 +- ...abaseTreeOutlineCoordinator+Commands.swift | 2 +- .../DatabaseTreeOutlineCoordinator+Menu.swift | 2 +- TablePro/Views/Sidebar/MaintenanceSheet.swift | 151 +++++---- .../Menu/DatabaseTreeMenuContext.swift | 3 +- .../Sidebar/Menu/DatabaseTreeMenuSpec.swift | 13 +- .../Sidebar/Menu/SidebarMenuCommand.swift | 4 +- .../Views/Sidebar/SidebarContextMenu.swift | 7 +- .../Plugins/PluginKitABIResilienceTests.swift | 12 + .../MaintenanceEligibilityTests.swift | 96 ++++++ .../MaintenanceOperationDescriptorTests.swift | 316 ++++++++++++++++++ .../Plugins/MySQLServerFlavorTests.swift | 4 +- .../Main/MaintenanceSheetIdentityTests.swift | 52 ++- .../Views/SidebarContextMenuLogicTests.swift | 16 +- docs/development/plugin-development.mdx | 2 +- docs/development/plugin-registry.mdx | 4 +- docs/features/table-operations.mdx | 6 +- project.yml | 3 + 79 files changed, 1421 insertions(+), 233 deletions(-) create mode 100644 Plugins/MySQLDriverPlugin/MySQLMaintenance.swift create mode 100644 Plugins/PostgreSQLDriverPlugin/PostgreSQLMaintenance.swift create mode 100644 Plugins/SQLiteDriverPlugin/SQLiteMaintenance.swift create mode 100644 Plugins/TableProPluginKit/PluginMaintenanceOperation.swift create mode 100644 TableProTests/Models/Database/MaintenanceEligibilityTests.swift create mode 100644 TableProTests/Plugins/MaintenanceOperationDescriptorTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f3ee13933..d364d21888 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -230,6 +230,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Cross-engine copy and JSON import creating `jsonb` columns on PostgreSQL 9.3 and earlier. - SQL Server edits and deletes matching no row when the row is identified by a binary column. - SQL Server parameters sent to the wrong placeholders when a column name holds a question mark. +- Maintenance offered on views and sequences, where the server skips or refuses it. (#2726) +- Maintenance running against a same-named object in another schema. (#2726) +- Maintenance SQL preview showing a statement the app never runs. (#2726) - `[` in a SQL Server filter value read as a wildcard. - Non-ASCII text turned into `?` by Copy as INSERT, Copy as IN, Preview Referenced Row, compare scripts and column defaults on SQL Server. diff --git a/Plugins/BeancountDriverPlugin/Info.plist b/Plugins/BeancountDriverPlugin/Info.plist index b5df38bac7..ae8234631a 100644 --- a/Plugins/BeancountDriverPlugin/Info.plist +++ b/Plugins/BeancountDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesDatabaseTypeIds Beancount diff --git a/Plugins/BigQueryDriverPlugin/Info.plist b/Plugins/BigQueryDriverPlugin/Info.plist index 146cf11acb..1ff5e9424b 100644 --- a/Plugins/BigQueryDriverPlugin/Info.plist +++ b/Plugins/BigQueryDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 28 + 29 diff --git a/Plugins/CSVExportPlugin/Info.plist b/Plugins/CSVExportPlugin/Info.plist index 2d117f1940..0a65f60446 100644 --- a/Plugins/CSVExportPlugin/Info.plist +++ b/Plugins/CSVExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesExportFormatIds csv diff --git a/Plugins/CSVImportPlugin/Info.plist b/Plugins/CSVImportPlugin/Info.plist index 842846c821..18dba8028a 100644 --- a/Plugins/CSVImportPlugin/Info.plist +++ b/Plugins/CSVImportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesImportFormatIds csv diff --git a/Plugins/CassandraDriverPlugin/Info.plist b/Plugins/CassandraDriverPlugin/Info.plist index 76638da801..c0ce92deb8 100644 --- a/Plugins/CassandraDriverPlugin/Info.plist +++ b/Plugins/CassandraDriverPlugin/Info.plist @@ -21,6 +21,6 @@ NSPrincipalClass $(PRODUCT_MODULE_NAME).CassandraPlugin TableProPluginKitVersion - 28 + 29 diff --git a/Plugins/ClickHouseDriverPlugin/Info.plist b/Plugins/ClickHouseDriverPlugin/Info.plist index 7801e3f0f1..45c92896f9 100644 --- a/Plugins/ClickHouseDriverPlugin/Info.plist +++ b/Plugins/ClickHouseDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesDatabaseTypeIds ClickHouse diff --git a/Plugins/CloudflareD1DriverPlugin/Info.plist b/Plugins/CloudflareD1DriverPlugin/Info.plist index 146cf11acb..1ff5e9424b 100644 --- a/Plugins/CloudflareD1DriverPlugin/Info.plist +++ b/Plugins/CloudflareD1DriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 28 + 29 diff --git a/Plugins/CloudflareR2SQLDriverPlugin/Info.plist b/Plugins/CloudflareR2SQLDriverPlugin/Info.plist index 3db72c176e..8c38b7dea5 100644 --- a/Plugins/CloudflareR2SQLDriverPlugin/Info.plist +++ b/Plugins/CloudflareR2SQLDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesDatabaseTypeIds Cloudflare R2 SQL diff --git a/Plugins/DamengDriverPlugin/Info.plist b/Plugins/DamengDriverPlugin/Info.plist index 2e197ca2fd..da99fbc7aa 100644 --- a/Plugins/DamengDriverPlugin/Info.plist +++ b/Plugins/DamengDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesDatabaseTypeIds Dameng diff --git a/Plugins/DuckDBDriverPlugin/Info.plist b/Plugins/DuckDBDriverPlugin/Info.plist index ab35b0b9e7..da17a5a58e 100644 --- a/Plugins/DuckDBDriverPlugin/Info.plist +++ b/Plugins/DuckDBDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 28 + 29 diff --git a/Plugins/DynamoDBDriverPlugin/Info.plist b/Plugins/DynamoDBDriverPlugin/Info.plist index 146cf11acb..1ff5e9424b 100644 --- a/Plugins/DynamoDBDriverPlugin/Info.plist +++ b/Plugins/DynamoDBDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 28 + 29 diff --git a/Plugins/ElasticsearchDriverPlugin/Info.plist b/Plugins/ElasticsearchDriverPlugin/Info.plist index 0c66dd9a1f..b5fdecd437 100644 --- a/Plugins/ElasticsearchDriverPlugin/Info.plist +++ b/Plugins/ElasticsearchDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.53.0 TableProPluginKitVersion - 28 + 29 diff --git a/Plugins/EtcdDriverPlugin/Info.plist b/Plugins/EtcdDriverPlugin/Info.plist index 146cf11acb..1ff5e9424b 100644 --- a/Plugins/EtcdDriverPlugin/Info.plist +++ b/Plugins/EtcdDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 28 + 29 diff --git a/Plugins/HTMLExportPlugin/Info.plist b/Plugins/HTMLExportPlugin/Info.plist index 19bf6bc094..c621f63e4c 100644 --- a/Plugins/HTMLExportPlugin/Info.plist +++ b/Plugins/HTMLExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesExportFormatIds html diff --git a/Plugins/JSONExportPlugin/Info.plist b/Plugins/JSONExportPlugin/Info.plist index eb95d411c9..8215860cbb 100644 --- a/Plugins/JSONExportPlugin/Info.plist +++ b/Plugins/JSONExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesExportFormatIds json diff --git a/Plugins/JSONImportPlugin/Info.plist b/Plugins/JSONImportPlugin/Info.plist index 8abf91183c..83099a26e5 100644 --- a/Plugins/JSONImportPlugin/Info.plist +++ b/Plugins/JSONImportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesImportFormatIds json diff --git a/Plugins/KafkaDriverPlugin/Info.plist b/Plugins/KafkaDriverPlugin/Info.plist index 2af849aadd..e77aa7ce69 100644 --- a/Plugins/KafkaDriverPlugin/Info.plist +++ b/Plugins/KafkaDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesDatabaseTypeIds Kafka diff --git a/Plugins/LibSQLDriverPlugin/Info.plist b/Plugins/LibSQLDriverPlugin/Info.plist index 146cf11acb..1ff5e9424b 100644 --- a/Plugins/LibSQLDriverPlugin/Info.plist +++ b/Plugins/LibSQLDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 28 + 29 diff --git a/Plugins/MQLExportPlugin/Info.plist b/Plugins/MQLExportPlugin/Info.plist index 25bbaf509b..73f154e0a9 100644 --- a/Plugins/MQLExportPlugin/Info.plist +++ b/Plugins/MQLExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesExportFormatIds mql diff --git a/Plugins/MSSQLDriverPlugin/Info.plist b/Plugins/MSSQLDriverPlugin/Info.plist index ab35b0b9e7..da17a5a58e 100644 --- a/Plugins/MSSQLDriverPlugin/Info.plist +++ b/Plugins/MSSQLDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 28 + 29 diff --git a/Plugins/MarkdownExportPlugin/Info.plist b/Plugins/MarkdownExportPlugin/Info.plist index f3419755a8..10135b9189 100644 --- a/Plugins/MarkdownExportPlugin/Info.plist +++ b/Plugins/MarkdownExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesExportFormatIds md diff --git a/Plugins/MongoDBDriverPlugin/Info.plist b/Plugins/MongoDBDriverPlugin/Info.plist index ab35b0b9e7..da17a5a58e 100644 --- a/Plugins/MongoDBDriverPlugin/Info.plist +++ b/Plugins/MongoDBDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 28 + 29 diff --git a/Plugins/MySQLDriverPlugin/Info.plist b/Plugins/MySQLDriverPlugin/Info.plist index df293ea509..220bbf0a89 100644 --- a/Plugins/MySQLDriverPlugin/Info.plist +++ b/Plugins/MySQLDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesDatabaseTypeIds MySQL diff --git a/Plugins/MySQLDriverPlugin/MySQLMaintenance.swift b/Plugins/MySQLDriverPlugin/MySQLMaintenance.swift new file mode 100644 index 0000000000..117acf7b95 --- /dev/null +++ b/Plugins/MySQLDriverPlugin/MySQLMaintenance.swift @@ -0,0 +1,95 @@ +// +// MySQLMaintenance.swift +// MySQLDriverPlugin +// + +import Foundation +import TableProPluginKit + +/// MySQL's maintenance operations and the statements they produce. +/// +/// Pure, so the confirmation sheet's preview and the statement that runs are one function rather +/// than two implementations that drifted: the sheet printed `CHECK TABLE orders MEDIUM` with the +/// name unquoted where `CHECK TABLE \`orders\` MEDIUM` ran. +/// +/// The kind sets come from the MySQL reference rather than from a probe, because no MySQL server was +/// available: `OPTIMIZE TABLE`, `ANALYZE TABLE` and `REPAIR TABLE` are documented on base tables and +/// partitioned tables, while `CHECK TABLE` is documented to check views as well, for references in +/// the view body to tables that no longer exist. +nonisolated internal enum MySQLMaintenance { + internal static let optimize = "OPTIMIZE TABLE" + internal static let analyze = "ANALYZE TABLE" + internal static let check = "CHECK TABLE" + internal static let repair = "REPAIR TABLE" + + internal static let modeKey = "mode" + internal static let checkModes = ["QUICK", "FAST", "MEDIUM", "EXTENDED", "CHANGED"] + internal static let defaultCheckMode = "MEDIUM" + + internal static let analyzeOperation = PluginMaintenanceOperation( + name: analyze, + appliesTo: [.table, .partitionedTable], + scope: .object + ) + + internal static let operations: [PluginMaintenanceOperation] = [ + PluginMaintenanceOperation( + name: optimize, + appliesTo: [.table, .partitionedTable], + scope: .object + ), + analyzeOperation, + PluginMaintenanceOperation( + name: check, + appliesTo: [.table, .partitionedTable, .view], + scope: .object, + options: [ + PluginMaintenanceOption( + key: modeKey, + label: String(localized: "Check mode:"), + defaultValue: defaultCheckMode, + choices: checkModes + ) + ] + ), + PluginMaintenanceOperation( + name: repair, + appliesTo: [.table, .partitionedTable], + scope: .object + ) + ] + + /// Every MySQL maintenance statement names one table, so a nil one produces nothing rather than a + /// database-wide form the engine does not have. + /// + /// The mode is matched against the declared choices instead of being interpolated as it arrives. + /// It reaches here from an MCP client as well as from the sheet's picker, and it lands in the + /// statement text unquoted. + internal static func statements( + operation: String, + table: String?, + schema: String?, + options: [String: String], + flavor: MySQLServerFlavor + ) -> [String]? { + guard let table, flavor.maintenanceOperations.contains(where: { $0.name == operation }) else { return nil } + let target = qualified(table: table, schema: schema, flavor: flavor) + switch operation { + case optimize, analyze, repair: + return ["\(operation) \(target)"] + case check: + let mode = checkModes.first { $0 == options[modeKey] } ?? defaultCheckMode + return ["\(check) \(target) \(mode)"] + default: + return nil + } + } + + private static func qualified(table: String, schema: String?, flavor: MySQLServerFlavor) -> String { + func quote(_ name: String) -> String { + flavor.isDatabend ? DatabendCatalog.quoteIdentifier(name) : mysqlQuoteIdentifier(name) + } + guard let schema, !schema.isEmpty else { return quote(table) } + return "\(quote(schema)).\(quote(table))" + } +} diff --git a/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift b/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift index 0f8e42873b..6ca4c71ae8 100644 --- a/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift +++ b/Plugins/MySQLDriverPlugin/MySQLPluginDriver.swift @@ -1078,21 +1078,21 @@ final class MySQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { // MARK: - Maintenance func supportedMaintenanceOperations() -> [String]? { + flavor.maintenanceOperations.map(\.name) + } + + func maintenanceOperations() -> [PluginMaintenanceOperation]? { flavor.maintenanceOperations } func maintenanceStatements(operation: String, table: String?, schema: String?, options: [String: String]) -> [String]? { - guard let table, flavor.maintenanceOperations.contains(operation) else { return nil } - let quoted = quoteIdentifier(table) - switch operation { - case "OPTIMIZE TABLE": return ["OPTIMIZE TABLE \(quoted)"] - case "ANALYZE TABLE": return ["ANALYZE TABLE \(quoted)"] - case "CHECK TABLE": - let mode = options["mode"] ?? "MEDIUM" - return ["CHECK TABLE \(quoted) \(mode)"] - case "REPAIR TABLE": return ["REPAIR TABLE \(quoted)"] - default: return nil - } + MySQLMaintenance.statements( + operation: operation, + table: table, + schema: schema, + options: options, + flavor: flavor + ) } // MARK: - Create Table DDL diff --git a/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift b/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift index 9cb8554964..de86b086ed 100644 --- a/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift +++ b/Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift @@ -88,12 +88,12 @@ nonisolated internal enum MySQLServerFlavor: Equatable, Sendable { } } - var maintenanceOperations: [String] { + var maintenanceOperations: [PluginMaintenanceOperation] { switch self { case .mysql, .mariadb: - return ["OPTIMIZE TABLE", "ANALYZE TABLE", "CHECK TABLE", "REPAIR TABLE"] + return MySQLMaintenance.operations case .tidb, .databend: - return ["ANALYZE TABLE"] + return [MySQLMaintenance.analyzeOperation] } } diff --git a/Plugins/OracleDriverPlugin/Info.plist b/Plugins/OracleDriverPlugin/Info.plist index ab35b0b9e7..da17a5a58e 100644 --- a/Plugins/OracleDriverPlugin/Info.plist +++ b/Plugins/OracleDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 28 + 29 diff --git a/Plugins/ParquetExportPlugin/Info.plist b/Plugins/ParquetExportPlugin/Info.plist index d102922e6b..9b0f410aba 100644 --- a/Plugins/ParquetExportPlugin/Info.plist +++ b/Plugins/ParquetExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesExportFormatIds parquet diff --git a/Plugins/PostgreSQLDriverPlugin/Info.plist b/Plugins/PostgreSQLDriverPlugin/Info.plist index dd32fb8a25..840343d78f 100644 --- a/Plugins/PostgreSQLDriverPlugin/Info.plist +++ b/Plugins/PostgreSQLDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesDatabaseTypeIds PostgreSQL diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLMaintenance.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLMaintenance.swift new file mode 100644 index 0000000000..0253f0adfc --- /dev/null +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLMaintenance.swift @@ -0,0 +1,123 @@ +// +// PostgreSQLMaintenance.swift +// PostgreSQLDriverPlugin +// + +import Foundation +import TableProPluginKit + +/// PostgreSQL's maintenance operations and the statements they produce. +/// +/// Pure, so the confirmation sheet's preview and the statement that runs are one function rather +/// than two implementations that drifted: the sheet used to print `REINDEX orders`, which is not +/// valid SQL, where `REINDEX TABLE "orders"` ran. +/// +/// Every kind set below is what PostgreSQL 17.11 answered to the statement on that kind. The two +/// that are not obvious: `CLUSTER` is accepted on a partitioned table and can never succeed there, +/// because `ALTER TABLE … CLUSTER ON` refuses with "cannot mark index clustered in partitioned +/// table"; and `ANALYZE` on a foreign table succeeds with no warning and writes `pg_statistic` rows, +/// because the wrapper samples it, while `VACUUM` on the same table warns and skips. +internal enum PostgreSQLMaintenance { + internal static let vacuum = "VACUUM" + internal static let analyze = "ANALYZE" + internal static let reindex = "REINDEX" + internal static let cluster = "CLUSTER" + + internal static let verboseKey = "verbose" + internal static let fullKey = "full" + internal static let analyzeKey = "analyze" + + internal static let operations: [PluginMaintenanceOperation] = [ + PluginMaintenanceOperation( + name: vacuum, + appliesTo: [.table, .partitionedTable, .materializedView], + scope: .objectOrDatabase, + options: [ + PluginMaintenanceOption( + key: fullKey, + label: String(localized: "FULL (rewrites the whole object, blocks access)"), + defaultValue: "false" + ), + PluginMaintenanceOption( + key: analyzeKey, + label: String(localized: "ANALYZE (update statistics afterwards)"), + defaultValue: "false" + ), + PluginMaintenanceOption( + key: verboseKey, + label: String(localized: "VERBOSE (report progress)"), + defaultValue: "false" + ) + ] + ), + PluginMaintenanceOperation( + name: analyze, + appliesTo: [.table, .partitionedTable, .materializedView, .foreignTable], + scope: .objectOrDatabase + ), + PluginMaintenanceOperation( + name: reindex, + appliesTo: [.table, .partitionedTable, .materializedView], + scope: .objectOrDatabase, + options: [ + PluginMaintenanceOption( + key: verboseKey, + label: String(localized: "VERBOSE (report progress)"), + defaultValue: "false" + ) + ] + ), + PluginMaintenanceOperation( + name: cluster, + appliesTo: [.table, .materializedView], + scope: .object + ) + ] + + /// A nil `schema` leaves the name unqualified, which is what a caller with no schema to offer + /// means. Everything in the app does have one, and has to pass it: `search_path` resolves a bare + /// name against `pg_temp` first, so a temp table of the same name is what got maintained. + internal static func statements( + operation: String, + table: String?, + schema: String?, + options: [String: String], + connectedDatabase: String?, + capabilities: PostgreSQLCapabilities + ) -> [String]? { + let target = table.map { qualified(table: $0, schema: schema) } + switch operation { + case vacuum: + var flags: [String] = [] + if isOn(options[fullKey]) { flags.append("FULL") } + if isOn(options[analyzeKey]) { flags.append("ANALYZE") } + if isOn(options[verboseKey]) { flags.append("VERBOSE") } + let clause = flags.isEmpty ? "" : " (\(flags.joined(separator: ", ")))" + return [target.map { "VACUUM\(clause) \($0)" } ?? "VACUUM\(clause)"] + case analyze: + return [target.map { "ANALYZE \($0)" } ?? "ANALYZE"] + case reindex: + guard let target else { + return PostgreSQLVersionedStatements.reindexDatabase( + currentDatabase: connectedDatabase, + capabilities: capabilities + ).map { [$0] } + } + let clause = isOn(options[verboseKey]) ? " (VERBOSE)" : "" + return ["REINDEX\(clause) TABLE \(target)"] + case cluster: + return target.map { ["CLUSTER \($0)"] } + default: + return nil + } + } + + private static func qualified(table: String, schema: String?) -> String { + guard let schema, !schema.isEmpty else { return PostgreSQLObjectQueries.quoteIdentifier(table) } + return PostgreSQLObjectQueries.qualifiedName(schema: schema, name: table) + } + + private static func isOn(_ value: String?) -> Bool { + value == "true" + } +} diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift index eeac512846..4a1ba2a73d 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift @@ -132,32 +132,22 @@ class PostgreSQLPluginDriver: LibPQBackedDriver, @unchecked Sendable { // MARK: - Maintenance func supportedMaintenanceOperations() -> [String]? { - ["VACUUM", "ANALYZE", "REINDEX", "CLUSTER"] + PostgreSQLMaintenance.operations.map(\.name) + } + + func maintenanceOperations() -> [PluginMaintenanceOperation]? { + PostgreSQLMaintenance.operations } func maintenanceStatements(operation: String, table: String?, schema: String?, options: [String: String]) -> [String]? { - let target = table.map { quoteIdentifier($0) } - switch operation { - case "VACUUM": - var opts: [String] = [] - if options["full"] == "true" { opts.append("FULL") } - if options["analyze"] == "true" { opts.append("ANALYZE") } - if options["verbose"] == "true" { opts.append("VERBOSE") } - let optClause = opts.isEmpty ? "" : "(\(opts.joined(separator: ", "))) " - return [target.map { "VACUUM \(optClause)\($0)" } ?? "VACUUM"] - case "ANALYZE": - return [target.map { "ANALYZE \($0)" } ?? "ANALYZE"] - case "REINDEX": - if let target { return ["REINDEX TABLE \(target)"] } - return PostgreSQLVersionedStatements.reindexDatabase( - currentDatabase: connectedDatabase, - capabilities: versionedCapabilities - ).map { [$0] } - case "CLUSTER": - return target.map { ["CLUSTER \($0)"] } - default: - return nil - } + PostgreSQLMaintenance.statements( + operation: operation, + table: table, + schema: schema, + options: options, + connectedDatabase: connectedDatabase, + capabilities: versionedCapabilities + ) } // MARK: - View Templates diff --git a/Plugins/RedisDriverPlugin/Info.plist b/Plugins/RedisDriverPlugin/Info.plist index 92ff8ddca9..095004d2c5 100644 --- a/Plugins/RedisDriverPlugin/Info.plist +++ b/Plugins/RedisDriverPlugin/Info.plist @@ -21,7 +21,7 @@ NSPrincipalClass $(PRODUCT_MODULE_NAME).RedisPlugin TableProPluginKitVersion - 28 + 29 TableProProvidesDatabaseTypeIds Redis diff --git a/Plugins/SQLExportPlugin/Info.plist b/Plugins/SQLExportPlugin/Info.plist index 966eed5590..62eb5de5da 100644 --- a/Plugins/SQLExportPlugin/Info.plist +++ b/Plugins/SQLExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesExportFormatIds sql diff --git a/Plugins/SQLImportPlugin/Info.plist b/Plugins/SQLImportPlugin/Info.plist index 75df0c8bc1..851ff49322 100644 --- a/Plugins/SQLImportPlugin/Info.plist +++ b/Plugins/SQLImportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesImportFormatIds sql diff --git a/Plugins/SQLiteDriverPlugin/Info.plist b/Plugins/SQLiteDriverPlugin/Info.plist index 2563adc79a..cbba27e09b 100644 --- a/Plugins/SQLiteDriverPlugin/Info.plist +++ b/Plugins/SQLiteDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesDatabaseTypeIds SQLite diff --git a/Plugins/SQLiteDriverPlugin/SQLiteMaintenance.swift b/Plugins/SQLiteDriverPlugin/SQLiteMaintenance.swift new file mode 100644 index 0000000000..ec4c34964a --- /dev/null +++ b/Plugins/SQLiteDriverPlugin/SQLiteMaintenance.swift @@ -0,0 +1,50 @@ +// +// SQLiteMaintenance.swift +// SQLiteDriverPlugin +// + +import Foundation +import TableProPluginKit + +/// SQLite's maintenance operations and the statements they produce. +/// +/// Pure, so the confirmation sheet's preview and the statement that runs are one function rather than +/// two implementations that drifted: the sheet printed `VACUUM orders` where `VACUUM` ran, and +/// `Integrity Check orders` where `PRAGMA integrity_check` ran. +/// +/// Probed against SQLite 3.54.0. `VACUUM` and `PRAGMA integrity_check` act on the whole database and +/// name no object, which is why they are `.database`: the table the sheet printed beside them was +/// never in the statement. `ANALYZE` and `REINDEX` accept an object, and on a view both succeed and +/// do nothing, `ANALYZE "vw"` writing no `sqlite_stat1` row at all, so a view is not in their kind +/// sets. There is no kind error to go on here: a name SQLite does not recognise as a table is a +/// silent no-op reported as success. +nonisolated internal enum SQLiteMaintenance { + internal static let vacuum = "VACUUM" + internal static let analyze = "ANALYZE" + internal static let reindex = "REINDEX" + /// Not localized: it is the operation's identity, switched on here and sent to MCP clients as the + /// name they pass back. + internal static let integrityCheck = "Integrity Check" + + internal static let operations: [PluginMaintenanceOperation] = [ + PluginMaintenanceOperation(name: vacuum, appliesTo: [], scope: .database), + PluginMaintenanceOperation(name: analyze, appliesTo: [.table], scope: .objectOrDatabase), + PluginMaintenanceOperation(name: reindex, appliesTo: [.table], scope: .objectOrDatabase), + PluginMaintenanceOperation(name: integrityCheck, appliesTo: [], scope: .database) + ] + + internal static func statements(operation: String, table: String?) -> [String]? { + switch operation { + case vacuum: + return [vacuum] + case analyze: + return [table.map { "ANALYZE \(sqliteQuoteIdentifier($0))" } ?? "ANALYZE"] + case reindex: + return [table.map { "REINDEX \(sqliteQuoteIdentifier($0))" } ?? "REINDEX"] + case integrityCheck: + return ["PRAGMA integrity_check"] + default: + return nil + } + } +} diff --git a/Plugins/SQLiteDriverPlugin/SQLitePlugin.swift b/Plugins/SQLiteDriverPlugin/SQLitePlugin.swift index 7ba6a91c89..fc5ae1ff65 100644 --- a/Plugins/SQLiteDriverPlugin/SQLitePlugin.swift +++ b/Plugins/SQLiteDriverPlugin/SQLitePlugin.swift @@ -571,8 +571,7 @@ final class SQLitePluginDriver: PluginDatabaseDriver, @unchecked Sendable { } func quoteIdentifier(_ name: String) -> String { - let escaped = name.replacingOccurrences(of: "`", with: "``") - return "`\(escaped)`" + sqliteQuoteIdentifier(name) } init(config: DriverConnectionConfig) { @@ -656,17 +655,15 @@ final class SQLitePluginDriver: PluginDatabaseDriver, @unchecked Sendable { // MARK: - Maintenance func supportedMaintenanceOperations() -> [String]? { - ["VACUUM", "ANALYZE", "REINDEX", "Integrity Check"] + SQLiteMaintenance.operations.map(\.name) + } + + func maintenanceOperations() -> [PluginMaintenanceOperation]? { + SQLiteMaintenance.operations } func maintenanceStatements(operation: String, table: String?, schema: String?, options: [String: String]) -> [String]? { - switch operation { - case "VACUUM": return ["VACUUM"] - case "ANALYZE": return table.map { ["ANALYZE \(quoteIdentifier($0))"] } ?? ["ANALYZE"] - case "REINDEX": return table.map { ["REINDEX \(quoteIdentifier($0))"] } ?? ["REINDEX"] - case "Integrity Check": return ["PRAGMA integrity_check"] - default: return nil - } + SQLiteMaintenance.statements(operation: operation, table: table) } // MARK: - View Templates diff --git a/Plugins/SnowflakeDriverPlugin/Info.plist b/Plugins/SnowflakeDriverPlugin/Info.plist index 21c3a16871..97dcecf8c0 100644 --- a/Plugins/SnowflakeDriverPlugin/Info.plist +++ b/Plugins/SnowflakeDriverPlugin/Info.plist @@ -5,6 +5,6 @@ TableProMinAppVersion 0.48.0 TableProPluginKitVersion - 28 + 29 diff --git a/Plugins/SpannerDriverPlugin/Info.plist b/Plugins/SpannerDriverPlugin/Info.plist index dac8735b47..3f8b6ffdc3 100644 --- a/Plugins/SpannerDriverPlugin/Info.plist +++ b/Plugins/SpannerDriverPlugin/Info.plist @@ -5,7 +5,7 @@ TableProMinAppVersion 0.42.0 TableProPluginKitVersion - 28 + 29 TableProProvidesDatabaseTypeIds Spanner diff --git a/Plugins/SurrealDBDriverPlugin/Info.plist b/Plugins/SurrealDBDriverPlugin/Info.plist index 9c080f515b..58bac760c2 100644 --- a/Plugins/SurrealDBDriverPlugin/Info.plist +++ b/Plugins/SurrealDBDriverPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesDatabaseTypeIds SurrealDB diff --git a/Plugins/TableProPluginKit/PluginDatabaseDriver.swift b/Plugins/TableProPluginKit/PluginDatabaseDriver.swift index e7df24678f..d518214ff2 100644 --- a/Plugins/TableProPluginKit/PluginDatabaseDriver.swift +++ b/Plugins/TableProPluginKit/PluginDatabaseDriver.swift @@ -376,6 +376,15 @@ public protocol PluginDatabaseDriver: AnyObject, Sendable { func supportedMaintenanceOperations() -> [String]? func maintenanceStatements(operation: String, table: String?, schema: String?, options: [String: String]) -> [String]? + /// The maintenance operations this driver offers, each carrying the object kinds it may name, the + /// scope its statement has and the options it reads. Return nil where the engine has no + /// maintenance at all. + /// + /// `supportedMaintenanceOperations()` answers bare names, which cannot say any of that, so the + /// app offered every operation on every object and hand-wrote its own preview of the SQL. A + /// driver that answers this one is the single source of both. + func maintenanceOperations() -> [PluginMaintenanceOperation]? + // EXPLAIN query building (optional) func buildExplainQuery(_ sql: String) -> String? @@ -839,6 +848,13 @@ public extension PluginDatabaseDriver { func supportedMaintenanceOperations() -> [String]? { nil } func maintenanceStatements(operation: String, table: String?, schema: String?, options: [String: String]) -> [String]? { nil } + /// Lifts a driver that answers only the older name list into descriptors, so an already-built + /// plugin keeps exactly the behaviour it had. `PluginMaintenanceOperation.lifting` says what that + /// is, and is where the rule is asserted. + func maintenanceOperations() -> [PluginMaintenanceOperation]? { + supportedMaintenanceOperations().map(PluginMaintenanceOperation.lifting) + } + func buildExplainQuery(_ sql: String) -> String? { nil } func injectRowLimit(_ sql: String, limit: Int) -> String? { nil } diff --git a/Plugins/TableProPluginKit/PluginMaintenanceOperation.swift b/Plugins/TableProPluginKit/PluginMaintenanceOperation.swift new file mode 100644 index 0000000000..e2c1239584 --- /dev/null +++ b/Plugins/TableProPluginKit/PluginMaintenanceOperation.swift @@ -0,0 +1,159 @@ +// +// PluginMaintenanceOperation.swift +// TableProPluginKit +// + +import Foundation + +/// The kind of object a maintenance operation may name, spelled as `PluginTableInfo.type` is. +/// +/// A struct rather than an enum, for the reason `DatabaseType` is one: a driver may report a kind +/// this framework never heard of, and `PluginDriverAdapter` already logs and falls back for exactly +/// that. An unknown spelling has to compare unequal to every known kind rather than fail to exist. +/// +/// The raw value is uppercased on the way in so a driver that answers `"view"` and one that answers +/// `"VIEW"` land on the same kind. +public struct PluginObjectKind: RawRepresentable, Hashable, Sendable, Codable { + public let rawValue: String + + public init(rawValue: String) { + self.rawValue = rawValue.uppercased() + } + + public init(_ name: String) { + self.init(rawValue: name) + } + + public static let table = PluginObjectKind(rawValue: "TABLE") + public static let partitionedTable = PluginObjectKind(rawValue: "PARTITIONED TABLE") + public static let view = PluginObjectKind(rawValue: "VIEW") + public static let materializedView = PluginObjectKind(rawValue: "MATERIALIZED VIEW") + public static let foreignTable = PluginObjectKind(rawValue: "FOREIGN TABLE") + public static let systemTable = PluginObjectKind(rawValue: "SYSTEM TABLE") + public static let externalTable = PluginObjectKind(rawValue: "EXTERNAL TABLE") + + /// Every kind the object browser lists as a table row. + /// + /// What a driver that answers only the older `supportedMaintenanceOperations()` inherits, so its + /// menu keeps exactly the shape it had before kinds existed. + public static let allTableLike: Set = [ + .table, + .partitionedTable, + .view, + .materializedView, + .foreignTable, + .systemTable, + .externalTable + ] +} + +/// What an operation's statement may name. +/// +/// SQLite's `VACUUM` and `PRAGMA integrity_check` take no object at all, so an operation list of +/// bare names cannot say that the table the sheet printed beside them was never in the statement. +public enum PluginMaintenanceScope: String, Sendable, Codable { + case object + case database + case objectOrDatabase + + /// Whether a statement for this operation may name one object. + public var admitsObject: Bool { + switch self { + case .object, .objectOrDatabase: return true + case .database: return false + } + } + + /// Whether a statement for this operation may name no object and act on the whole database. + public var admitsDatabase: Bool { + switch self { + case .database, .objectOrDatabase: return true + case .object: return false + } + } +} + +/// One option an operation accepts, as the driver that builds the statement declares it. +/// +/// Declared rather than assumed because the confirmation sheet used to decide this itself, gated on +/// two engine names: an engine that grew the same flags would not have been offered them, and the +/// keys the sheet produced had to agree by hand with the keys the driver read. +public struct PluginMaintenanceOption: Hashable, Sendable, Codable { + /// The key this option's value travels under in the `options` dictionary. + public let key: String + public let label: String + public let defaultValue: String + /// The fixed set of values, or nil for a boolean the caller sends as `"true"` or `"false"`. + public let choices: [String]? + + public init(key: String, label: String, defaultValue: String, choices: [String]? = nil) { + self.key = key + self.label = label + self.defaultValue = defaultValue + self.choices = choices + } + + public var isToggle: Bool { choices == nil } +} + +/// One maintenance operation, with everything the caller needs to decide whether to offer it. +/// +/// The older `supportedMaintenanceOperations()` answers a list of bare names, which cannot say which +/// objects an operation works on. PostgreSQL answers `VACUUM` on a view with a WARNING and the +/// success command tag `VACUUM`, so the app reported success over work the server skipped, while +/// `REINDEX` on the same view failed outright. +public struct PluginMaintenanceOperation: Hashable, Sendable, Codable { + public let name: String + public let appliesTo: Set + public let scope: PluginMaintenanceScope + public let options: [PluginMaintenanceOption] + + public init( + name: String, + appliesTo: Set, + scope: PluginMaintenanceScope, + options: [PluginMaintenanceOption] = [] + ) { + self.name = name + self.appliesTo = appliesTo + self.scope = scope + self.options = options + } + + /// Whether a statement for this operation may name an object of `kind`. + public func applies(to kind: PluginObjectKind) -> Bool { + scope.admitsObject && appliesTo.contains(kind) + } + + /// The object a statement for this operation should name, given the object it was reached from. + /// + /// Nil for an operation that acts on the whole database, so the object is dropped rather than + /// printed beside a statement that never mentions it: the sheet showed `VACUUM orders` on SQLite + /// where `VACUUM` ran. + public func target(_ objectName: String?) -> String? { + scope.admitsObject ? objectName : nil + } + + /// Every option's default, which is what a caller sends when the user changes nothing. + public var defaultOptionValues: [String: String] { + var values: [String: String] = [:] + for option in options { + values[option.key] = option.defaultValue + } + return values + } + + /// Lifts a driver's older list of bare names into descriptors. + /// + /// What `PluginDatabaseDriver.maintenanceOperations()` defaults to, so a plugin built before kinds + /// existed keeps exactly the behaviour it had: every table-like kind, either scope, no options. + public static func lifting(_ names: [String]) -> [PluginMaintenanceOperation] { + names.map { + PluginMaintenanceOperation( + name: $0, + appliesTo: PluginObjectKind.allTableLike, + scope: .objectOrDatabase + ) + } + } +} diff --git a/Plugins/TeradataDriverPlugin/Info.plist b/Plugins/TeradataDriverPlugin/Info.plist index ab35b0b9e7..da17a5a58e 100644 --- a/Plugins/TeradataDriverPlugin/Info.plist +++ b/Plugins/TeradataDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 28 + 29 diff --git a/Plugins/TrinoDriverPlugin/Info.plist b/Plugins/TrinoDriverPlugin/Info.plist index ab35b0b9e7..da17a5a58e 100644 --- a/Plugins/TrinoDriverPlugin/Info.plist +++ b/Plugins/TrinoDriverPlugin/Info.plist @@ -3,6 +3,6 @@ TableProPluginKitVersion - 28 + 29 diff --git a/Plugins/TypesenseDriverPlugin/Info.plist b/Plugins/TypesenseDriverPlugin/Info.plist index 1f4925cbd9..976e8f9ca5 100644 --- a/Plugins/TypesenseDriverPlugin/Info.plist +++ b/Plugins/TypesenseDriverPlugin/Info.plist @@ -5,7 +5,7 @@ TableProMinAppVersion 0.73.0 TableProPluginKitVersion - 28 + 29 TableProProvidesDatabaseTypeIds Typesense diff --git a/Plugins/WeaviateDriverPlugin/Info.plist b/Plugins/WeaviateDriverPlugin/Info.plist index 48893d9d17..b30794dd75 100644 --- a/Plugins/WeaviateDriverPlugin/Info.plist +++ b/Plugins/WeaviateDriverPlugin/Info.plist @@ -5,7 +5,7 @@ TableProMinAppVersion 0.73.0 TableProPluginKitVersion - 25 + 29 TableProProvidesDatabaseTypeIds Weaviate diff --git a/Plugins/XLSXExportPlugin/Info.plist b/Plugins/XLSXExportPlugin/Info.plist index 8c8d82e6c7..6a27e6a72d 100644 --- a/Plugins/XLSXExportPlugin/Info.plist +++ b/Plugins/XLSXExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesExportFormatIds xlsx diff --git a/Plugins/XLSXImportPlugin/Info.plist b/Plugins/XLSXImportPlugin/Info.plist index b393420625..8d2d3def8f 100644 --- a/Plugins/XLSXImportPlugin/Info.plist +++ b/Plugins/XLSXImportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesImportFormatIds xlsx diff --git a/Plugins/XMLExportPlugin/Info.plist b/Plugins/XMLExportPlugin/Info.plist index d32c9164b3..a1a7ea95b1 100644 --- a/Plugins/XMLExportPlugin/Info.plist +++ b/Plugins/XMLExportPlugin/Info.plist @@ -3,7 +3,7 @@ TableProPluginKitVersion - 28 + 29 TableProProvidesExportFormatIds xml diff --git a/TablePro/Core/Database/DatabaseDriver.swift b/TablePro/Core/Database/DatabaseDriver.swift index b2f9e4c7d8..c17ffac981 100644 --- a/TablePro/Core/Database/DatabaseDriver.swift +++ b/TablePro/Core/Database/DatabaseDriver.swift @@ -245,12 +245,26 @@ protocol DatabaseDriver: AnyObject, Sendable { // MARK: - Maintenance - /// Returns the list of supported maintenance operations (e.g. "VACUUM", "ANALYZE"). - /// Returns nil if maintenance is not supported. - func supportedMaintenanceOperations() -> [String]? + /// The maintenance operations this connection offers, each with the object kinds it may name, its + /// scope and its options. Returns nil if maintenance is not supported. + /// + /// Descriptors rather than names, because the menu has to decide whether an operation applies to + /// the object the user clicked: PostgreSQL skips a `VACUUM` on a view with a WARNING and the + /// success command tag `VACUUM`, and refuses a `REINDEX` on one outright. + func maintenanceOperations() -> [PluginMaintenanceOperation]? - /// Generates SQL statements for a maintenance operation. - func maintenanceStatements(operation: String, table: String?, options: [String: String]) -> [String]? + /// Generates SQL statements for a maintenance operation. The single source of the statement, so + /// the confirmation sheet previews this rather than writing its own copy of the SQL. + /// + /// A nil `schema` means the caller genuinely has none to offer. Everything in the app does, and + /// passes it: PostgreSQL resolves a bare name against `pg_temp` first, so a temp table of the + /// same name is what got maintained. + func maintenanceStatements( + operation: String, + table: String?, + schema: String?, + options: [String: String] + ) -> [String]? // MARK: - Object Comments and Materialized Views @@ -576,8 +590,13 @@ extension DatabaseDriver { try await fetchFilteredRowCount(table: table, filters: filters, logicMode: logicMode) } - func supportedMaintenanceOperations() -> [String]? { nil } - func maintenanceStatements(operation: String, table: String?, options: [String: String]) -> [String]? { nil } + func maintenanceOperations() -> [PluginMaintenanceOperation]? { nil } + func maintenanceStatements( + operation: String, + table: String?, + schema: String?, + options: [String: String] + ) -> [String]? { nil } func objectCommentStatement(name: String, objectType: String, schema: String?, comment: String?) -> String? { nil diff --git a/TablePro/Core/MCP/MCPConnectionBridge+Server.swift b/TablePro/Core/MCP/MCPConnectionBridge+Server.swift index 93516df545..84c86bc8fb 100644 --- a/TablePro/Core/MCP/MCPConnectionBridge+Server.swift +++ b/TablePro/Core/MCP/MCPConnectionBridge+Server.swift @@ -213,27 +213,86 @@ extension MCPConnectionBridge { return sql } + /// Each operation carries the object kinds it applies to, its scope and its options, because a + /// client that only knows the name cannot tell that `VACUUM` on a view is skipped by the server or + /// that `VACUUM` reads a `full` option at all. func maintenanceOperations(connectionId: UUID) async throws -> JsonValue { try await ensureConnected(connectionId) let operations = await MainActor.run { - DatabaseManager.shared.driver(for: connectionId)?.supportedMaintenanceOperations() + DatabaseManager.shared.driver(for: connectionId)?.maintenanceOperations() } + let sorted = (operations ?? []).sorted { $0.name < $1.name } return .object([ - "operations": .array((operations ?? []).sorted().map { .string($0) }), + "operations": .array(sorted.map(Self.encode(maintenance:))), "is_supported": .bool(operations != nil) ]) } + static func encode(maintenance operation: PluginMaintenanceOperation) -> JsonValue { + .object([ + "name": .string(operation.name), + "applies_to": .array(operation.appliesTo.map(\.rawValue).sorted().map { .string($0) }), + "scope": .string(operation.scope.rawValue), + "options": .array(operation.options.map(Self.encode(maintenanceOption:))) + ]) + } + + /// `choices` is left out rather than sent as null for a true/false flag, so the payload stays valid + /// against the declared output schema. + static func encode(maintenanceOption option: PluginMaintenanceOption) -> JsonValue { + var payload: [String: JsonValue] = [ + "key": .string(option.key), + "label": .string(option.label), + "default": .string(option.defaultValue) + ] + if let choices = option.choices { + payload["choices"] = .array(choices.map { .string($0) }) + } + return .object(payload) + } + + /// Refuses an operation the object's kind rules out, rather than handing back a statement the + /// server will skip with a warning and a success tag. The kind comes from the same table listing + /// `list_tables` reads. func maintenanceStatements( - connectionId: UUID, + scope: DatabaseScope, operation: String, table: String?, options: [String: String] ) async throws -> [String] { - try await ensureConnected(connectionId) + try await ensureConnected(scope.connectionId) + let descriptor = try await resolveMaintenanceOperation( + connectionId: scope.connectionId, + operation: operation + ) + if let table { + guard descriptor.scope.admitsObject else { + throw DatabaseAccessError.invalidArgument( + String( + format: String(localized: "%@ acts on the whole database. Omit 'table'."), + descriptor.name + ) + ) + } + try await requireMaintenanceKind(descriptor: descriptor, scope: scope, table: table) + } else { + guard descriptor.scope.admitsDatabase else { + throw DatabaseAccessError.invalidArgument( + String( + format: String(localized: "%@ needs a table. Pass 'table'."), + descriptor.name + ) + ) + } + } + let statements = await MainActor.run { - DatabaseManager.shared.driver(for: connectionId)? - .maintenanceStatements(operation: operation, table: table, options: options) + DatabaseManager.shared.driver(for: scope.connectionId)?.maintenanceStatements( + operation: operation, + table: table, + schema: scope.schema, + options: options + ) } guard let statements, !statements.isEmpty else { throw DatabaseAccessError.invalidArgument( @@ -243,6 +302,46 @@ extension MCPConnectionBridge { return statements } + private func resolveMaintenanceOperation( + connectionId: UUID, + operation: String + ) async throws -> PluginMaintenanceOperation { + let operations = await MainActor.run { + DatabaseManager.shared.driver(for: connectionId)?.maintenanceOperations() + } + guard let match = operations?.first(where: { $0.name == operation }) else { + throw DatabaseAccessError.invalidArgument( + String(localized: "That maintenance operation is not available on this connection.") + ) + } + return match + } + + private func requireMaintenanceKind( + descriptor: PluginMaintenanceOperation, + scope: DatabaseScope, + table: String + ) async throws { + let tables = try await DatabaseManager.shared.withMetadataDriver(scope: scope) { driver in + try await driver.fetchTables(schema: scope.schema) + } + guard let found = tables.first(where: { $0.name == table }) else { + throw DatabaseAccessError.invalidArgument( + String(format: String(localized: "No object named %@ in this schema."), table) + ) + } + let kind = TableOperationEligibility.pluginKind(found.type) + guard descriptor.applies(to: kind) else { + throw DatabaseAccessError.invalidArgument( + String( + format: String(localized: "%1$@ does not apply to a %2$@."), + descriptor.name, + found.type.rawValue + ) + ) + } + } + func sessionContexts(connectionId: UUID) async throws -> JsonValue { try await ensureConnected(connectionId) let scope = await MainActor.run { DatabaseManager.shared.browseScope(for: connectionId) } diff --git a/TablePro/Core/MCP/Protocol/Tools/MaintenanceTools.swift b/TablePro/Core/MCP/Protocol/Tools/MaintenanceTools.swift index 9cac418f14..89fd730b2d 100644 --- a/TablePro/Core/MCP/Protocol/Tools/MaintenanceTools.swift +++ b/TablePro/Core/MCP/Protocol/Tools/MaintenanceTools.swift @@ -23,8 +23,41 @@ public struct ListMaintenanceOperationsTool: MCPToolImplementation { public static let outputSchema: JsonValue? = MCPToolSchema.object( properties: [ "operations": MCPToolSchema.array( - String(localized: "Operation names, sorted"), - of: MCPToolSchema.stringItem + String(localized: "Operations, sorted by name"), + of: MCPToolSchema.object( + properties: [ + "name": MCPToolSchema.string(String(localized: "Operation name to pass to run_maintenance")), + "applies_to": MCPToolSchema.array( + String( + localized: """ + Object kinds this operation may name, as list_tables reports them. \ + Empty when it acts on the whole database only. + """ + ), + of: MCPToolSchema.stringItem + ), + "scope": MCPToolSchema.string( + String(localized: "Whether the statement names an object, the database, or either"), + enumValues: ["object", "database", "objectOrDatabase"] + ), + "options": MCPToolSchema.array( + String(localized: "Options this operation reads, by key"), + of: MCPToolSchema.object( + properties: [ + "key": MCPToolSchema.string(String(localized: "Key to send in 'options'")), + "label": MCPToolSchema.string(String(localized: "What the option does")), + "default": MCPToolSchema.string(String(localized: "Value used when omitted")), + "choices": MCPToolSchema.array( + String(localized: "Accepted values, or null for a true/false flag"), + of: MCPToolSchema.stringItem + ) + ], + required: ["key", "label", "default"] + ) + ) + ], + required: ["name", "applies_to", "scope", "options"] + ) ), "is_supported": MCPToolSchema.boolean(String(localized: "Whether this engine has maintenance at all")) ], @@ -121,10 +154,17 @@ public struct RunMaintenanceTool: MCPToolImplementation { } let meta = try await ToolConnectionMetadata.resolve(connectionId: connectionId) + /// Resolved before the statements, because the schema it carries is what qualifies the target + /// and its kind is what says whether the operation applies at all. + let scope = try await MCPScopeArguments.resolve( + arguments, + connectionId: connectionId, + services: services + ) let statements: [String] do { statements = try await services.connectionBridge.maintenanceStatements( - connectionId: connectionId, + scope: scope, operation: operation, table: table, options: options @@ -135,11 +175,6 @@ public struct RunMaintenanceTool: MCPToolImplementation { let settings = await services.settingsProvider() let timeoutSeconds = try MCPLimitResolver.resolveTimeoutSeconds(arguments, settings: settings) - let scope = try await MCPScopeArguments.resolve( - arguments, - connectionId: connectionId, - services: services - ) var results: [JsonValue] = [] for statement in statements { diff --git a/TablePro/Core/Menu/MaintenanceMenuDelegate.swift b/TablePro/Core/Menu/MaintenanceMenuDelegate.swift index 8ac13ef0aa..fa432b38eb 100644 --- a/TablePro/Core/Menu/MaintenanceMenuDelegate.swift +++ b/TablePro/Core/Menu/MaintenanceMenuDelegate.swift @@ -4,8 +4,9 @@ // import AppKit +import TableProPluginKit -/// Which maintenance operations exist depends on the driver and on what is selected, +/// Which maintenance operations exist depends on the driver and on the kind of the selected object, /// so the submenu is filled when it opens rather than at build time. `menuNeedsUpdate` /// is AppKit's hook for exactly that, and the responder chain resolves the window the /// same way it will resolve the item the user picks. @@ -24,7 +25,7 @@ final class MaintenanceMenuDelegate: NSObject, NSMenuDelegate { return } for operation in operations { - let item = NSMenuItem(title: operation, action: Self.action, keyEquivalent: "") + let item = NSMenuItem(title: operation.name, action: Self.action, keyEquivalent: "") item.target = nil item.representedObject = operation menu.addItem(item) diff --git a/TablePro/Core/Plugins/PluginDriverAdapter.swift b/TablePro/Core/Plugins/PluginDriverAdapter.swift index de3757028a..743b968ddc 100644 --- a/TablePro/Core/Plugins/PluginDriverAdapter.swift +++ b/TablePro/Core/Plugins/PluginDriverAdapter.swift @@ -770,12 +770,24 @@ final class PluginDriverAdapter: DatabaseDriver, SchemaSwitchable, DatabaseRepor // MARK: - Maintenance Operations - func supportedMaintenanceOperations() -> [String]? { - pluginDriver.supportedMaintenanceOperations() + func maintenanceOperations() -> [PluginMaintenanceOperation]? { + pluginDriver.maintenanceOperations() } - func maintenanceStatements(operation: String, table: String?, options: [String: String]) -> [String]? { - pluginDriver.maintenanceStatements(operation: operation, table: table, schema: pluginDriver.currentSchema, options: options) + /// The session's own schema stands in only when the caller has none, so a command that does carry + /// the object's schema qualifies with that one rather than with wherever the session points. + func maintenanceStatements( + operation: String, + table: String?, + schema: String?, + options: [String: String] + ) -> [String]? { + pluginDriver.maintenanceStatements( + operation: operation, + table: table, + schema: schema ?? pluginDriver.currentSchema, + options: options + ) } // MARK: - Object Comments and Materialized Views diff --git a/TablePro/Core/Plugins/PluginManager.swift b/TablePro/Core/Plugins/PluginManager.swift index 825f0210b4..6c37c2efe6 100644 --- a/TablePro/Core/Plugins/PluginManager.swift +++ b/TablePro/Core/Plugins/PluginManager.swift @@ -14,7 +14,13 @@ import TableProPluginKit @MainActor @Observable final class PluginManager { static let shared = PluginManager(userDefaults: AppStorageEnvironment.shared.defaults) - /// Raised to 28 for `fetchCommentDDL` on `PluginDatabaseDriver` and `PluginExportDataSource`, + /// Raised to 29 for `maintenanceOperations` on `PluginDatabaseDriver`, plus the + /// `PluginMaintenanceOperation`, `PluginMaintenanceOption`, `PluginMaintenanceScope` and + /// `PluginObjectKind` it answers with. Together they say which object kinds a maintenance + /// operation may name, whether its statement names an object at all, and which options it reads, + /// none of which the older list of bare names could. + /// + /// Raised to 28 before that for `fetchCommentDDL` on `PluginDatabaseDriver` and `PluginExportDataSource`, /// which is what lets a dump reattach a relation's own comment and its column comments instead /// of leaving whether they appear at all to each driver's `fetchTableDDL`. /// @@ -49,7 +55,7 @@ final class PluginManager { /// rebuilt CassandraDriver for the v20 requirements it implements none of. Left at 20, such a /// plugin passes `validateBundleVersions` in a shipped v20 app and then fails /// `Bundle.loadAndReturnError`; at 21 that app refuses it and says to update. - nonisolated static let currentPluginKitVersion = 28 + nonisolated static let currentPluginKitVersion = 29 /// Still 19, so every plugin already published for the previous release keeps loading. nonisolated static let minimumCompatiblePluginKitVersion = 19 diff --git a/TablePro/Core/Services/Infrastructure/MainSplitViewController+DatabaseMenuActions.swift b/TablePro/Core/Services/Infrastructure/MainSplitViewController+DatabaseMenuActions.swift index 17b461d795..36ef59e49b 100644 --- a/TablePro/Core/Services/Infrastructure/MainSplitViewController+DatabaseMenuActions.swift +++ b/TablePro/Core/Services/Infrastructure/MainSplitViewController+DatabaseMenuActions.swift @@ -5,6 +5,7 @@ import AppKit import SwiftUI +import TableProPluginKit extension MainSplitViewController { @objc func switchConnection(_ sender: Any?) { @@ -105,7 +106,8 @@ extension MainSplitViewController { } @objc func runMaintenanceOperation(_ sender: Any?) { - guard let operation = (sender as? NSMenuItem)?.representedObject as? String else { return } + guard let operation = (sender as? NSMenuItem)?.representedObject as? PluginMaintenanceOperation + else { return } commandActions?.runMaintenanceOperation(operation) } diff --git a/TablePro/Models/Database/TableOperationEligibility.swift b/TablePro/Models/Database/TableOperationEligibility.swift index ecd54f1305..e4385403c3 100644 --- a/TablePro/Models/Database/TableOperationEligibility.swift +++ b/TablePro/Models/Database/TableOperationEligibility.swift @@ -36,4 +36,36 @@ enum TableOperationEligibility { guard !targets.isEmpty else { return false } return targets.allSatisfy { canTruncate($0.table.type) } } + + /// The driver's vocabulary for the same kind. Spelled out rather than taken from `rawValue` so + /// adding a case to `TableInfo.TableType` stops compiling here instead of silently producing a + /// kind no driver declares, which would read as "no maintenance applies". + static func pluginKind(_ type: TableInfo.TableType?) -> PluginObjectKind { + switch type { + case .table, .none: return .table + case .partitionedTable: return .partitionedTable + case .view: return .view + case .materializedView: return .materializedView + case .foreignTable: return .foreignTable + case .systemTable: return .systemTable + case .externalTable: return .externalTable + } + } + + /// The maintenance the driver offers on an object of this kind. + /// + /// The one answer for the sidebar's contextual menu, the menu bar's Table Maintenance submenu and + /// the MCP tool. Offering every operation on every row is how `VACUUM` came to be offered on a + /// view, where PostgreSQL skips it with a WARNING and still reports success, and `REINDEX` on one, + /// where it fails outright. + /// + /// An operation whose statement names no object is kept whatever the row is: the row is only + /// where it is reached from, which is how SQLite's `VACUUM` is reachable at all. + static func maintenanceOperations( + _ all: [PluginMaintenanceOperation], + for type: TableInfo.TableType? + ) -> [PluginMaintenanceOperation] { + let kind = pluginKind(type) + return all.filter { $0.scope.admitsObject ? $0.applies(to: kind) : true } + } } diff --git a/TablePro/Views/Main/Extensions/MainContentCoordinator+SidebarActions.swift b/TablePro/Views/Main/Extensions/MainContentCoordinator+SidebarActions.swift index ec94a0109e..113a4a4df8 100644 --- a/TablePro/Views/Main/Extensions/MainContentCoordinator+SidebarActions.swift +++ b/TablePro/Views/Main/Extensions/MainContentCoordinator+SidebarActions.swift @@ -247,13 +247,13 @@ extension MainContentCoordinator { // MARK: - Maintenance - func supportedMaintenanceOperations() -> [String] { + func maintenanceOperations() -> [PluginMaintenanceOperation] { guard let driver = DatabaseManager.shared.driver(for: connectionId) else { return [] } - return driver.supportedMaintenanceOperations() ?? [] + return driver.maintenanceOperations() ?? [] } func showMaintenanceSheet( - operation: String, + operation: PluginMaintenanceOperation, tableName: String, database: String? = nil, schema: String? = nil @@ -263,6 +263,26 @@ extension MainContentCoordinator { ) } + /// The statements the confirmation sheet shows, built by the driver that will run them. + /// + /// Synchronous and pure, so the sheet can call it from `body` on every toggle. It used to write + /// its own SQL instead, which disagreed with what ran: `REINDEX orders`, not valid SQL, where + /// `REINDEX TABLE "orders"` runs. + func maintenancePreview( + operation: PluginMaintenanceOperation, + tableName: String?, + schema: String?, + options: [String: String] + ) -> [String] { + guard let driver = DatabaseManager.shared.driver(for: connectionId) else { return [] } + return driver.maintenanceStatements( + operation: operation.name, + table: operation.target(tableName), + schema: schema, + options: options + ) ?? [] + } + /// Runs against the database the object it names lives in, on a scoped lease. /// /// A maintenance statement names its table and nothing else, so where it lands is decided @@ -273,16 +293,16 @@ extension MainContentCoordinator { /// Every other statement the user owns takes a scoped lease; this one now does too, which also /// puts it behind the same gate rather than interleaving with a tab's work on one handle. func executeMaintenance( - operation: String, + operation: PluginMaintenanceOperation, tableName: String, options: [String: String], database: String? = nil, schema: String? = nil ) { - guard let driver = DatabaseManager.shared.driver(for: connectionId) else { return } - guard let statements = driver.maintenanceStatements( - operation: operation, table: tableName, options: options - ) else { return } + let statements = maintenancePreview( + operation: operation, tableName: tableName, schema: schema, options: options + ) + guard !statements.isEmpty else { return } /// The object the user picked names its own database, and only a command that names none /// falls back to where the browser is pointing. `resolvedScope` is what decides that, so a /// schema is never carried across a database boundary. @@ -290,6 +310,9 @@ extension MainContentCoordinator { database: database, schema: schema, for: connectionId ) ?? browseScope else { return } + /// What the statement acts on, which is the database itself for an operation that names no + /// object. Reporting the table there claimed work the statement never asked for. + let subject = operation.target(tableName) ?? scope.database Task { [weak self] in guard let self else { return } let decision = await ExecutionGateProvider.shared.authorize( @@ -300,13 +323,13 @@ extension MainContentCoordinator { kind: .maintenance, caller: .userInterface, capabilities: .interactiveUser, - operationDescription: operation + operationDescription: operation.name ) ) guard case .authorized = decision else { if let reason = decision.deniedReason { await AlertHelper.showErrorSheet( - title: String(format: String(localized: "%@ failed"), operation), + title: String(format: String(localized: "%@ failed"), operation.name), message: reason, window: self.contentWindow ) @@ -329,14 +352,18 @@ extension MainContentCoordinator { } } await AlertHelper.showInfoSheet( - title: String(format: String(localized: "%@ completed"), operation), + title: String(format: String(localized: "%@ completed"), operation.name), message: lastResult?.statusMessage - ?? String(format: String(localized: "%@ on %@ completed successfully."), operation, tableName), + ?? String( + format: String(localized: "%@ on %@ completed successfully."), + operation.name, + subject + ), window: self.contentWindow ) } catch { await AlertHelper.showErrorSheet( - title: String(format: String(localized: "%@ failed"), operation), + title: String(format: String(localized: "%@ failed"), operation.name), message: error.localizedDescription, window: self.contentWindow ) diff --git a/TablePro/Views/Main/MainContentCommandActions+DatabaseObjects.swift b/TablePro/Views/Main/MainContentCommandActions+DatabaseObjects.swift index b55f1724b2..83b8f6978c 100644 --- a/TablePro/Views/Main/MainContentCommandActions+DatabaseObjects.swift +++ b/TablePro/Views/Main/MainContentCommandActions+DatabaseObjects.swift @@ -4,6 +4,7 @@ // import Foundation +import TableProPluginKit /// Commands that act on the object selected in the sidebar. The sidebar's own /// context menu reaches the same coordinator methods, so the menu bar is a second @@ -80,15 +81,20 @@ extension MainContentCommandActions { return .of(DatabaseManager.shared.driver(for: connectionId)) } - var maintenanceOperations: [String] { - guard selectedObject != nil else { return [] } - return coordinator?.supportedMaintenanceOperations() ?? [] + /// Narrowed to the selected object's kind, the same rule the sidebar's submenu follows. Asking + /// only whether something was selected is how the menu bar offered `REINDEX` on a view. + var maintenanceOperations: [PluginMaintenanceOperation] { + guard let object = selectedObject else { return [] } + return TableOperationEligibility.maintenanceOperations( + coordinator?.maintenanceOperations() ?? [], + for: object.type + ) } /// The menu acts on the object browser's selection, and `TableInfo` carries a schema but no /// database, so this names only the schema and the command falls back to the database being /// browsed. The sidebar's own contextual menu carries the clicked row's database and does not. - func runMaintenanceOperation(_ operation: String) { + func runMaintenanceOperation(_ operation: PluginMaintenanceOperation) { guard let object = selectedObject else { return } coordinator?.showMaintenanceSheet( operation: operation, tableName: object.name, schema: object.schema diff --git a/TablePro/Views/Main/MainContentCoordinator.swift b/TablePro/Views/Main/MainContentCoordinator.swift index 9b7c5b5c50..348b5eacd1 100644 --- a/TablePro/Views/Main/MainContentCoordinator.swift +++ b/TablePro/Views/Main/MainContentCoordinator.swift @@ -68,7 +68,12 @@ enum ActiveSheet: Identifiable { /// its table and nothing else, so acting on wherever the object browser happens to point /// maintains the same-named table in another database whenever the two have drifted apart. /// This is the rule the sidebar's other destructive commands already keep by carrying their ref. - case maintenance(operation: String, tableName: String, database: String?, schema: String?) + case maintenance( + operation: PluginMaintenanceOperation, + tableName: String, + database: String?, + schema: String? + ) case createDatabase /// The object's own database and schema travel in the target, for the reason `.maintenance` /// carries them: the comment is written to the object the user right-clicked, not to a @@ -94,7 +99,7 @@ enum ActiveSheet: Identifiable { case .restoreDatabase(let fileURL): "restoreDatabase-\(fileURL.path)" case .serverSideExport(let table): "serverSideExport-\(table ?? "")" case .maintenance(let operation, let tableName, let database, let schema): - "maintenance-\(operation)-\(database ?? "")-\(schema ?? "")-\(tableName)" + "maintenance-\(operation.name)-\(database ?? "")-\(schema ?? "")-\(tableName)" case .createDatabase: "createDatabase" case .editObjectComment(let target): "editObjectComment-\(target.scope.database)-\(target.scope.schema ?? "")-\(target.name)" diff --git a/TablePro/Views/Main/MainContentView.swift b/TablePro/Views/Main/MainContentView.swift index e9108bdbd3..cf20d267d0 100644 --- a/TablePro/Views/Main/MainContentView.swift +++ b/TablePro/Views/Main/MainContentView.swift @@ -214,8 +214,16 @@ struct MainContentView: View { MaintenanceSheet( operation: operation, tableName: tableName, - databaseType: connection.type, - onExecute: { operation, tableName, options in + databaseName: database ?? coordinator.browseDatabaseName, + preview: { options in + coordinator.maintenancePreview( + operation: operation, + tableName: tableName, + schema: schema, + options: options + ) + }, + onExecute: { options in coordinator.executeMaintenance( operation: operation, tableName: tableName, diff --git a/TablePro/Views/Sidebar/DatabaseTreeOutlineCoordinator+Commands.swift b/TablePro/Views/Sidebar/DatabaseTreeOutlineCoordinator+Commands.swift index 0fb8c3fc92..6d8a7e6dd1 100644 --- a/TablePro/Views/Sidebar/DatabaseTreeOutlineCoordinator+Commands.swift +++ b/TablePro/Views/Sidebar/DatabaseTreeOutlineCoordinator+Commands.swift @@ -76,7 +76,7 @@ extension DatabaseTreeOutlineCoordinator { operation: operation, tableName: tableName, database: ref.database, - schema: ref.schema + schema: ref.qualifyingSchema ) } case .truncateTables(let targets, let ref): diff --git a/TablePro/Views/Sidebar/DatabaseTreeOutlineCoordinator+Menu.swift b/TablePro/Views/Sidebar/DatabaseTreeOutlineCoordinator+Menu.swift index 96abd9e56a..7364a5f2de 100644 --- a/TablePro/Views/Sidebar/DatabaseTreeOutlineCoordinator+Menu.swift +++ b/TablePro/Views/Sidebar/DatabaseTreeOutlineCoordinator+Menu.swift @@ -45,7 +45,7 @@ extension DatabaseTreeOutlineCoordinator: NSMenuDelegate { isReadOnly: mainCoordinator?.safeModeLevel.blocksAllWrites ?? false, supportsImport: PluginManager.shared.supportsImport(for: databaseType), importFormats: PluginManager.shared.importFormatOptions(for: databaseType), - maintenanceOperations: mainCoordinator?.supportedMaintenanceOperations() ?? [], + maintenanceOperations: mainCoordinator?.maintenanceOperations() ?? [], dropEligibility: ContainerDropEligibility.Context( activeDatabase: activeDatabase, activeSchema: activeSchema, diff --git a/TablePro/Views/Sidebar/MaintenanceSheet.swift b/TablePro/Views/Sidebar/MaintenanceSheet.swift index 95e3dd2516..1fb40c5e60 100644 --- a/TablePro/Views/Sidebar/MaintenanceSheet.swift +++ b/TablePro/Views/Sidebar/MaintenanceSheet.swift @@ -2,44 +2,58 @@ // MaintenanceSheet.swift // TablePro // -// Confirmation sheet for database maintenance operations -// (VACUUM, ANALYZE, OPTIMIZE, REINDEX, etc.) -// import SwiftUI +import TableProPluginKit +/// Confirms a maintenance operation and shows the statements that will run. +/// +/// The preview is the driver's own SQL, handed in as a closure, and the Execute button sends the same +/// option values back through the same builder. It used to write its own copy of the statement and +/// disagree with it: `REINDEX orders`, which is not valid SQL, where `REINDEX TABLE "orders"` ran. +/// The option controls come from the operation for the same reason, rather than from a switch gated +/// on two engine names. struct MaintenanceSheet: View { @Environment(\.dismiss) private var dismiss - let operation: String - let tableName: String - let databaseType: DatabaseType - let onExecute: (String, String, [String: String]) -> Void + let operation: PluginMaintenanceOperation + let tableName: String? + let databaseName: String? + /// Statements for the given option values. Synchronous and pure, so calling it for every toggle + /// while `body` runs costs an array of strings. + let preview: ([String: String]) -> [String] + let onExecute: ([String: String]) -> Void + + @State private var values: [String: String] - @State private var fullVacuum = false - @State private var analyzeAfterVacuum = false - @State private var verbose = false - @State private var checkMode = "MEDIUM" + init( + operation: PluginMaintenanceOperation, + tableName: String?, + databaseName: String?, + preview: @escaping ([String: String]) -> [String], + onExecute: @escaping ([String: String]) -> Void + ) { + self.operation = operation + self.tableName = tableName + self.databaseName = databaseName + self.preview = preview + self.onExecute = onExecute + _values = State(initialValue: operation.defaultOptionValues) + } var body: some View { VStack(alignment: .leading, spacing: 16) { - HStack { - Image(systemName: "wrench.and.screwdriver") - .font(.title2) - .foregroundStyle(.secondary) - VStack(alignment: .leading, spacing: 2) { - Text(operation) - .font(.headline) - Text(tableName) - .font(.subheadline) - .foregroundStyle(.secondary) - } - Spacer() - } + header Divider() - operationOptions + if !operation.options.isEmpty { + VStack(alignment: .leading, spacing: 8) { + ForEach(operation.options, id: \.key) { option in + optionControl(option) + } + } + } VStack(alignment: .leading, spacing: 4) { Text(String(localized: "SQL Preview")) @@ -47,6 +61,7 @@ struct MaintenanceSheet: View { .foregroundStyle(.secondary) Text(sqlPreview) .font(.system(.body, design: .monospaced)) + .textSelection(.enabled) .padding(8) .frame(maxWidth: .infinity, alignment: .leading) .background(Color(nsColor: .textBackgroundColor)) @@ -60,66 +75,72 @@ struct MaintenanceSheet: View { Button(String(localized: "Cancel")) { dismiss() } .keyboardShortcut(.cancelAction) Button(String(localized: "Execute")) { - onExecute(operation, tableName, buildOptions()) + onExecute(values) dismiss() } .keyboardShortcut(.defaultAction) .buttonStyle(.borderedProminent) + .disabled(sqlPreview.isEmpty) } } .padding(20) .frame(width: 420) } - // MARK: - Options + private var header: some View { + HStack { + Image(systemName: "wrench.and.screwdriver") + .font(.title2) + .foregroundStyle(.secondary) + VStack(alignment: .leading, spacing: 2) { + Text(operation.name) + .font(.headline) + if let subject { + Text(subject) + .font(.subheadline) + .foregroundStyle(.secondary) + } + } + Spacer() + } + } + + /// What the statement acts on. An operation that names no object reads as the database it runs + /// against, rather than as the table the row it was reached from happened to be. + private var subject: String? { + operation.target(tableName)?.nilIfEmpty ?? databaseName?.nilIfEmpty + } @ViewBuilder - private var operationOptions: some View { - switch operation { - case "VACUUM" where databaseType == .postgresql || databaseType == .redshift: - Toggle(String(localized: "FULL (rewrites entire table, blocks access)"), isOn: $fullVacuum) - Toggle(String(localized: "ANALYZE (update statistics after vacuum)"), isOn: $analyzeAfterVacuum) - Toggle(String(localized: "VERBOSE (print progress)"), isOn: $verbose) - case "CHECK TABLE": - Picker(String(localized: "Check mode:"), selection: $checkMode) { - Text("QUICK").tag("QUICK") - Text("FAST").tag("FAST") - Text("MEDIUM").tag("MEDIUM") - Text("EXTENDED").tag("EXTENDED") - Text("CHANGED").tag("CHANGED") + private func optionControl(_ option: PluginMaintenanceOption) -> some View { + if let choices = option.choices { + Picker(option.label, selection: binding(for: option)) { + ForEach(choices, id: \.self) { choice in + Text(choice).tag(choice) + } } .pickerStyle(.menu) .frame(width: 200) - default: - EmptyView() + } else { + Toggle(option.label, isOn: toggleBinding(for: option)) } } - // MARK: - SQL Preview + private func binding(for option: PluginMaintenanceOption) -> Binding { + Binding( + get: { values[option.key] ?? option.defaultValue }, + set: { values[option.key] = $0 } + ) + } - private var sqlPreview: String { - let options = buildOptions() - switch operation { - case "VACUUM" where databaseType == .postgresql || databaseType == .redshift: - var opts: [String] = [] - if options["full"] == "true" { opts.append("FULL") } - if options["analyze"] == "true" { opts.append("ANALYZE") } - if options["verbose"] == "true" { opts.append("VERBOSE") } - let optClause = opts.isEmpty ? "" : "(\(opts.joined(separator: ", "))) " - return "VACUUM \(optClause)\(tableName)" - case "CHECK TABLE": - return "CHECK TABLE \(tableName) \(checkMode)" - default: - return "\(operation) \(tableName)" - } + private func toggleBinding(for option: PluginMaintenanceOption) -> Binding { + Binding( + get: { (values[option.key] ?? option.defaultValue) == "true" }, + set: { values[option.key] = $0 ? "true" : "false" } + ) } - private func buildOptions() -> [String: String] { - var options: [String: String] = [:] - if fullVacuum { options["full"] = "true" } - if analyzeAfterVacuum { options["analyze"] = "true" } - if verbose { options["verbose"] = "true" } - if operation == "CHECK TABLE" { options["mode"] = checkMode } - return options + private var sqlPreview: String { + preview(values).joined(separator: ";\n") } } diff --git a/TablePro/Views/Sidebar/Menu/DatabaseTreeMenuContext.swift b/TablePro/Views/Sidebar/Menu/DatabaseTreeMenuContext.swift index aac5b9476a..eed6bab57e 100644 --- a/TablePro/Views/Sidebar/Menu/DatabaseTreeMenuContext.swift +++ b/TablePro/Views/Sidebar/Menu/DatabaseTreeMenuContext.swift @@ -23,7 +23,8 @@ internal struct DatabaseTreeMenuContext { internal let isReadOnly: Bool internal let supportsImport: Bool internal let importFormats: [ImportFormatOption] - internal let maintenanceOperations: [String] + /// Everything the driver offers. The spec narrows it to the clicked row's own kind. + internal let maintenanceOperations: [PluginMaintenanceOperation] internal let dropEligibility: ContainerDropEligibility.Context internal let renameEligibility: ObjectRenameEligibility.Context internal let containerEntityName: String diff --git a/TablePro/Views/Sidebar/Menu/DatabaseTreeMenuSpec.swift b/TablePro/Views/Sidebar/Menu/DatabaseTreeMenuSpec.swift index d7d935655d..3265e8e301 100644 --- a/TablePro/Views/Sidebar/Menu/DatabaseTreeMenuSpec.swift +++ b/TablePro/Views/Sidebar/Menu/DatabaseTreeMenuSpec.swift @@ -159,15 +159,22 @@ internal enum DatabaseTreeMenuSpec { ) { items.append(.command(String(localized: "Refresh Materialized View…"), .refreshMaterializedView(ref))) } + let applicable = TableOperationEligibility.maintenanceOperations( + context.maintenanceOperations, + for: ref.table.type + ) if SidebarContextMenuLogic.maintenanceGroupEnabled( isReadOnly: context.isReadOnly, hasSelection: true, - supportedOperations: context.maintenanceOperations + applicableOperations: applicable ) { items.append(.submenu( title: String(localized: "Maintenance"), - items: context.maintenanceOperations.map { operation in - .command(operation, .maintenance(operation: operation, tableName: ref.table.name, ref: ref)) + items: applicable.map { operation in + .command( + operation.name, + .maintenance(operation: operation, tableName: ref.table.name, ref: ref) + ) } )) } diff --git a/TablePro/Views/Sidebar/Menu/SidebarMenuCommand.swift b/TablePro/Views/Sidebar/Menu/SidebarMenuCommand.swift index 349e0b2acc..6821cf80b8 100644 --- a/TablePro/Views/Sidebar/Menu/SidebarMenuCommand.swift +++ b/TablePro/Views/Sidebar/Menu/SidebarMenuCommand.swift @@ -36,7 +36,9 @@ internal enum SidebarMenuCommand: Equatable { case exportTables(names: Set, ref: DatabaseTreeTableRef) case transferTables(names: Set, ref: DatabaseTreeTableRef) case importTables(formatId: String, ref: DatabaseTreeTableRef) - case maintenance(operation: String, tableName: String, ref: DatabaseTreeTableRef) + /// Carries the whole descriptor rather than the operation's name, because the sheet it opens needs + /// the scope and the options to build the statement it shows and the one it runs. + case maintenance(operation: PluginMaintenanceOperation, tableName: String, ref: DatabaseTreeTableRef) /// Queued rather than run, so these carry every target in full: a queue keyed by name is /// resolved against whatever the tab in front points at by the time Save runs. case truncateTables(targets: [DatabaseTreeTableRef], ref: DatabaseTreeTableRef) diff --git a/TablePro/Views/Sidebar/SidebarContextMenu.swift b/TablePro/Views/Sidebar/SidebarContextMenu.swift index 7b403237ec..49913bc207 100644 --- a/TablePro/Views/Sidebar/SidebarContextMenu.swift +++ b/TablePro/Views/Sidebar/SidebarContextMenu.swift @@ -38,12 +38,15 @@ enum SidebarContextMenuLogic { } } + /// Asked with the operations that apply to the clicked object, not with everything the driver + /// offers: on a view PostgreSQL has four operations and none of them works, so the submenu is + /// omitted rather than filled with commands that skip or fail. static func maintenanceGroupEnabled( isReadOnly: Bool, hasSelection: Bool, - supportedOperations: [String] + applicableOperations: [PluginMaintenanceOperation] ) -> Bool { guard !isReadOnly, hasSelection else { return false } - return !supportedOperations.isEmpty + return !applicableOperations.isEmpty } } diff --git a/TableProTests/Core/Plugins/PluginKitABIResilienceTests.swift b/TableProTests/Core/Plugins/PluginKitABIResilienceTests.swift index 91f999b5c5..87ec41f017 100644 --- a/TableProTests/Core/Plugins/PluginKitABIResilienceTests.swift +++ b/TableProTests/Core/Plugins/PluginKitABIResilienceTests.swift @@ -31,6 +31,7 @@ struct PluginKitABIResilienceTests { #expect(driver.foreignKeyDisableStatements() == nil) #expect(driver.foreignKeyEnableStatements() == nil) #expect(driver.supportedMaintenanceOperations() == nil) + #expect(driver.maintenanceOperations() == nil) #expect(driver.buildExplainQuery("SELECT 1") == nil) #expect(driver.injectRowLimit("SELECT 1", limit: 100) == nil) #expect(driver.defaultExportQuery(table: "users") == nil) @@ -41,6 +42,17 @@ struct PluginKitABIResilienceTests { #expect(driver.schemaOperationRefusal(.renameCheckConstraint(from: "a", to: "b")) == nil) } + @Test("A driver that answers only the older name list has it lifted into table-like descriptors") + func legacyMaintenanceNamesAreLifted() { + let lifted = PluginMaintenanceOperation.lifting(["VACUUM", "ANALYZE"]) + + #expect(lifted.map(\.name) == ["VACUUM", "ANALYZE"]) + #expect(lifted.allSatisfy { $0.appliesTo == PluginObjectKind.allTableLike }) + #expect(lifted.allSatisfy { $0.scope == .objectOrDatabase }) + #expect(lifted.allSatisfy { $0.options.isEmpty }) + #expect(lifted.allSatisfy { $0.applies(to: .view) }) + } + @Test("A driver that omits defaulted requirements falls back to the documented asynchronous defaults") func asynchronousDefaults() async throws { let driver = makeMinimalDriver() diff --git a/TableProTests/Models/Database/MaintenanceEligibilityTests.swift b/TableProTests/Models/Database/MaintenanceEligibilityTests.swift new file mode 100644 index 0000000000..bc220a2502 --- /dev/null +++ b/TableProTests/Models/Database/MaintenanceEligibilityTests.swift @@ -0,0 +1,96 @@ +// +// MaintenanceEligibilityTests.swift +// TableProTests +// +// The sidebar, the menu bar and the MCP tool all filter maintenance through one function. Before it +// existed each surface offered every operation the driver named on every row, so PostgreSQL VACUUM +// reached a view, where the server skips it with a WARNING and still answers the command tag VACUUM. +// + +import Foundation +@testable import TablePro +import TableProPluginKit +import Testing + +@Suite("Maintenance eligibility") +struct MaintenanceEligibilityTests { + private func operation( + _ name: String, + kinds: Set, + scope: PluginMaintenanceScope = .object + ) -> PluginMaintenanceOperation { + PluginMaintenanceOperation(name: name, appliesTo: kinds, scope: scope, options: []) + } + + private var postgresLike: [PluginMaintenanceOperation] { + [ + operation("VACUUM", kinds: [.table, .partitionedTable, .materializedView], scope: .objectOrDatabase), + operation("ANALYZE", kinds: [.table, .partitionedTable, .materializedView, .foreignTable], scope: .objectOrDatabase), + operation("REINDEX", kinds: [.table, .partitionedTable, .materializedView], scope: .objectOrDatabase), + operation("CLUSTER", kinds: [.table, .materializedView]) + ] + } + + @Test("A view keeps only the operations its kind is named in") + func viewKeepsNothingItCannotRun() { + let offered = TableOperationEligibility.maintenanceOperations(postgresLike, for: .view).map(\.name) + + #expect(offered.isEmpty) + } + + @Test("A materialized view keeps every operation but the ones its kind is absent from") + func materializedViewKeepsMost() { + let offered = TableOperationEligibility.maintenanceOperations(postgresLike, for: .materializedView).map(\.name) + + #expect(offered == ["VACUUM", "ANALYZE", "REINDEX", "CLUSTER"]) + } + + /// Measured on PostgreSQL 17.11: `ALTER TABLE ... CLUSTER ON` is refused on a partitioned table, + /// so CLUSTER can never succeed there however the server answers the CLUSTER statement itself. + @Test("A partitioned table keeps everything except CLUSTER") + func partitionedTableDropsCluster() { + let offered = TableOperationEligibility.maintenanceOperations(postgresLike, for: .partitionedTable).map(\.name) + + #expect(offered == ["VACUUM", "ANALYZE", "REINDEX"]) + #expect(!offered.contains("CLUSTER")) + } + + /// Measured on PostgreSQL 17.11: ANALYZE on a foreign table samples through the FDW and succeeds + /// with no warning, while VACUUM skips it. + @Test("A foreign table keeps ANALYZE alone") + func foreignTableKeepsAnalyze() { + let offered = TableOperationEligibility.maintenanceOperations(postgresLike, for: .foreignTable).map(\.name) + + #expect(offered == ["ANALYZE"]) + } + + /// A database-wide operation names no object, so the row it was reached from cannot disqualify it. + /// SQLite's VACUUM is reachable at all only because of this. + @Test("A database-wide operation survives every kind, including one it names nowhere") + func databaseWideOperationIsAlwaysKept() { + let wide = [operation("VACUUM", kinds: [], scope: .database)] + + for type in [TableInfo.TableType.table, .view, .materializedView, .foreignTable, .systemTable, .externalTable] { + #expect(TableOperationEligibility.maintenanceOperations(wide, for: type).map(\.name) == ["VACUUM"]) + } + } + + @Test("A row with no known type is treated as a table") + func unknownTypeFallsBackToTable() { + let offered = TableOperationEligibility.maintenanceOperations(postgresLike, for: nil).map(\.name) + + #expect(offered == ["VACUUM", "ANALYZE", "REINDEX", "CLUSTER"]) + } + + @Test("Every table-like kind maps to the driver's own spelling") + func kindsMapToDriverVocabulary() { + #expect(TableOperationEligibility.pluginKind(.table) == .table) + #expect(TableOperationEligibility.pluginKind(.partitionedTable) == .partitionedTable) + #expect(TableOperationEligibility.pluginKind(.view) == .view) + #expect(TableOperationEligibility.pluginKind(.materializedView) == .materializedView) + #expect(TableOperationEligibility.pluginKind(.foreignTable) == .foreignTable) + #expect(TableOperationEligibility.pluginKind(.systemTable) == .systemTable) + #expect(TableOperationEligibility.pluginKind(.externalTable) == .externalTable) + #expect(TableOperationEligibility.pluginKind(nil) == .table) + } +} diff --git a/TableProTests/Plugins/MaintenanceOperationDescriptorTests.swift b/TableProTests/Plugins/MaintenanceOperationDescriptorTests.swift new file mode 100644 index 0000000000..671a1267b4 --- /dev/null +++ b/TableProTests/Plugins/MaintenanceOperationDescriptorTests.swift @@ -0,0 +1,316 @@ +// +// MaintenanceOperationDescriptorTests.swift +// TableProTests +// +// Maintenance used to be a list of bare operation names, so the app offered every one of them on +// every object: PostgreSQL skips a VACUUM on a view with a WARNING and still reports the success +// command tag VACUUM, and refuses a REINDEX on one outright. The kind sets below are what +// PostgreSQL 17.11 and SQLite 3.54.0 actually answered. +// + +import Foundation +@testable import TablePro +import TableProPluginKit +import Testing + +@Suite("Maintenance operation descriptors") +struct MaintenanceOperationDescriptorTests { + private func postgres(_ name: String) throws -> PluginMaintenanceOperation { + try #require(PostgreSQLMaintenance.operations.first { $0.name == name }) + } + + private func sqlite(_ name: String) throws -> PluginMaintenanceOperation { + try #require(SQLiteMaintenance.operations.first { $0.name == name }) + } + + private func mysql(_ name: String) throws -> PluginMaintenanceOperation { + try #require(MySQLMaintenance.operations.first { $0.name == name }) + } + + private func postgresStatements( + _ operation: String, + table: String?, + schema: String?, + options: [String: String] = [:] + ) -> [String]? { + PostgreSQLMaintenance.statements( + operation: operation, + table: table, + schema: schema, + options: options, + connectedDatabase: "app", + capabilities: PostgreSQLCapabilities(serverVersion: 170_011) + ) + } + + // MARK: - PostgreSQL kinds + + @Test("CLUSTER is offered on a table and a materialized view and on nothing else") + func clusterKinds() throws { + let cluster = try postgres("CLUSTER") + + #expect(cluster.applies(to: .table)) + #expect(cluster.applies(to: .materializedView)) + #expect(!cluster.applies(to: .partitionedTable)) + #expect(!cluster.applies(to: .view)) + #expect(!cluster.applies(to: .foreignTable)) + } + + @Test("ANALYZE reaches a foreign table and VACUUM does not") + func foreignTableTakesAnalyzeOnly() throws { + #expect(try postgres("ANALYZE").applies(to: .foreignTable)) + #expect(try !postgres("VACUUM").applies(to: .foreignTable)) + } + + @Test("Nothing PostgreSQL offers applies to a view") + func noPostgresOperationAppliesToAView() { + #expect(PostgreSQLMaintenance.operations.allSatisfy { !$0.applies(to: .view) }) + } + + @Test("REINDEX covers a partitioned table, which CLUSTER cannot") + func partitionedTableKinds() throws { + #expect(try postgres("REINDEX").applies(to: .partitionedTable)) + #expect(try postgres("VACUUM").applies(to: .partitionedTable)) + #expect(try postgres("ANALYZE").applies(to: .partitionedTable)) + } + + // MARK: - PostgreSQL statements + + @Test("A PostgreSQL target is qualified with the schema it was handed") + func qualifiesTheSchema() { + #expect(postgresStatements("REINDEX", table: "orders", schema: "app") == ["REINDEX TABLE \"app\".\"orders\""]) + #expect(postgresStatements("ANALYZE", table: "orders", schema: "app") == ["ANALYZE \"app\".\"orders\""]) + #expect(postgresStatements("VACUUM", table: "orders", schema: "app") == ["VACUUM \"app\".\"orders\""]) + #expect(postgresStatements("CLUSTER", table: "orders", schema: "app") == ["CLUSTER \"app\".\"orders\""]) + } + + @Test("A schema that is nil or empty leaves the name unqualified") + func unqualifiedWithoutASchema() { + #expect(postgresStatements("REINDEX", table: "orders", schema: nil) == ["REINDEX TABLE \"orders\""]) + #expect(postgresStatements("REINDEX", table: "orders", schema: "") == ["REINDEX TABLE \"orders\""]) + } + + @Test("A quote in a schema or table name is doubled rather than closing the identifier") + func quotesAreEscaped() { + #expect( + postgresStatements("ANALYZE", table: "or\"ders", schema: "a\"pp") + == ["ANALYZE \"a\"\"pp\".\"or\"\"ders\""] + ) + } + + @Test("VACUUM renders the flags the descriptor declares") + func vacuumFlags() { + #expect( + postgresStatements( + "VACUUM", + table: "orders", + schema: "app", + options: ["full": "true", "analyze": "true", "verbose": "true"] + ) == ["VACUUM (FULL, ANALYZE, VERBOSE) \"app\".\"orders\""] + ) + #expect( + postgresStatements("VACUUM", table: "orders", schema: "app", options: ["analyze": "true"]) + == ["VACUUM (ANALYZE) \"app\".\"orders\""] + ) + #expect( + postgresStatements("VACUUM", table: "orders", schema: "app", options: ["full": "false"]) + == ["VACUUM \"app\".\"orders\""] + ) + } + + @Test("REINDEX renders its own VERBOSE flag before the TABLE keyword") + func reindexVerbose() { + #expect( + postgresStatements("REINDEX", table: "orders", schema: "app", options: ["verbose": "true"]) + == ["REINDEX (VERBOSE) TABLE \"app\".\"orders\""] + ) + } + + @Test("A PostgreSQL operation with no table falls back to the database-wide form") + func databaseWideForms() { + #expect(postgresStatements("VACUUM", table: nil, schema: "app") == ["VACUUM"]) + #expect( + postgresStatements("VACUUM", table: nil, schema: "app", options: ["analyze": "true"]) + == ["VACUUM (ANALYZE)"] + ) + #expect(postgresStatements("ANALYZE", table: nil, schema: "app") == ["ANALYZE"]) + /// From PostgreSQL 16 the database name is optional and the statement reindexes the one it is + /// connected to, which is what `PostgreSQLVersionedStatements.reindexDatabase` emits and what + /// 17.11 accepted when this was measured. The named form is the 12 to 15 arm, pinned by + /// `PostgreSQLVersionedStatementsTests`. + #expect(postgresStatements("REINDEX", table: nil, schema: "app") == ["REINDEX DATABASE CONCURRENTLY"]) + #expect(postgresStatements("CLUSTER", table: nil, schema: "app") == nil) + } + + @Test("An operation PostgreSQL does not have produces nothing") + func unknownPostgresOperation() { + #expect(postgresStatements("OPTIMIZE TABLE", table: "orders", schema: "app") == nil) + } + + // MARK: - SQLite + + @Test("SQLite VACUUM and Integrity Check name no object and ignore one") + func sqliteDatabaseScoped() throws { + let vacuum = try sqlite("VACUUM") + let integrity = try sqlite("Integrity Check") + + #expect(vacuum.scope == .database) + #expect(integrity.scope == .database) + #expect(vacuum.appliesTo.isEmpty) + #expect(integrity.appliesTo.isEmpty) + #expect(vacuum.target("orders") == nil) + #expect(integrity.target("orders") == nil) + #expect(SQLiteMaintenance.statements(operation: "VACUUM", table: "orders") == ["VACUUM"]) + #expect(SQLiteMaintenance.statements(operation: "Integrity Check", table: "orders") == ["PRAGMA integrity_check"]) + } + + @Test("SQLite ANALYZE and REINDEX are offered on a table and not on a view") + func sqliteObjectScoped() throws { + for name in ["ANALYZE", "REINDEX"] { + let operation = try sqlite(name) + #expect(operation.applies(to: .table)) + #expect(!operation.applies(to: .view)) + #expect(operation.scope == .objectOrDatabase) + } + #expect(SQLiteMaintenance.statements(operation: "ANALYZE", table: "orders") == ["ANALYZE `orders`"]) + #expect(SQLiteMaintenance.statements(operation: "REINDEX", table: nil) == ["REINDEX"]) + } + + @Test("A backtick in a SQLite object name is doubled") + func sqliteQuoting() { + #expect(SQLiteMaintenance.statements(operation: "ANALYZE", table: "or`ders") == ["ANALYZE `or``ders`"]) + } + + // MARK: - MySQL + + @Test("CHECK TABLE is the only MySQL operation offered on a view") + func mysqlViewKinds() throws { + #expect(try mysql("CHECK TABLE").applies(to: .view)) + #expect(try !mysql("OPTIMIZE TABLE").applies(to: .view)) + #expect(try !mysql("ANALYZE TABLE").applies(to: .view)) + #expect(try !mysql("REPAIR TABLE").applies(to: .view)) + } + + @Test("CHECK TABLE declares its mode, defaulting to MEDIUM") + func mysqlCheckMode() throws { + let check = try mysql("CHECK TABLE") + let mode = try #require(check.options.first) + + #expect(check.options.count == 1) + #expect(mode.key == "mode") + #expect(mode.defaultValue == "MEDIUM") + #expect(mode.choices == ["QUICK", "FAST", "MEDIUM", "EXTENDED", "CHANGED"]) + #expect(!mode.isToggle) + } + + @Test("A MySQL target is backtick-quoted and qualified only when a schema is handed over") + func mysqlStatements() { + #expect( + MySQLMaintenance.statements( + operation: "OPTIMIZE TABLE", table: "orders", schema: nil, options: [:], flavor: .mysql + ) == ["OPTIMIZE TABLE `orders`"] + ) + #expect( + MySQLMaintenance.statements( + operation: "OPTIMIZE TABLE", table: "orders", schema: "shop", options: [:], flavor: .mysql + ) == ["OPTIMIZE TABLE `shop`.`orders`"] + ) + #expect( + MySQLMaintenance.statements( + operation: "CHECK TABLE", table: "orders", schema: nil, options: [:], flavor: .mysql + ) == ["CHECK TABLE `orders` MEDIUM"] + ) + #expect( + MySQLMaintenance.statements( + operation: "CHECK TABLE", table: "orders", schema: nil, options: ["mode": "EXTENDED"], flavor: .mysql + ) == ["CHECK TABLE `orders` EXTENDED"] + ) + } + + /// The mode lands in the statement text unquoted and reaches here from an MCP client as well as + /// from the sheet's picker, so anything that is not a declared choice falls back to the default. + @Test("A check mode outside the declared choices falls back to the default") + func mysqlRejectsAnUndeclaredMode() { + #expect( + MySQLMaintenance.statements( + operation: "CHECK TABLE", + table: "orders", + schema: nil, + options: ["mode": "EXTENDED; DROP TABLE orders"], + flavor: .mysql + ) == ["CHECK TABLE `orders` MEDIUM"] + ) + } + + @Test("A MySQL operation with no table produces nothing, because the engine has no such form") + func mysqlNeedsATable() { + #expect(MySQLMaintenance.operations.allSatisfy { $0.scope == .object }) + #expect( + MySQLMaintenance.statements( + operation: "ANALYZE TABLE", table: nil, schema: "shop", options: [:], flavor: .mysql + ) == nil + ) + } + + @Test("TiDB and Databend refuse an operation their flavor does not offer") + func flavorGatesTheStatement() { + for flavor in [MySQLServerFlavor.tidb(version: nil), .databend] { + #expect( + MySQLMaintenance.statements( + operation: "REPAIR TABLE", table: "orders", schema: nil, options: [:], flavor: flavor + ) == nil + ) + #expect( + MySQLMaintenance.statements( + operation: "ANALYZE TABLE", table: "orders", schema: nil, options: [:], flavor: flavor + ) != nil + ) + } + } + + // MARK: - Every declared option is read + + /// An option the descriptor declares that the statement builder never reads is the hardcoding bug + /// in its other direction: the sheet would show a control that changes nothing. + @Test("Every option a driver declares changes the statement it is declared on") + func everyDeclaredOptionIsRead() throws { + for operation in PostgreSQLMaintenance.operations { + let base = try #require(postgresStatements( + operation.name, table: "orders", schema: "app", options: operation.defaultOptionValues + )) + for option in operation.options { + var changed = operation.defaultOptionValues + changed[option.key] = try alternative(to: option) + let result = try #require(postgresStatements( + operation.name, table: "orders", schema: "app", options: changed + )) + #expect(result != base, "\(operation.name) ignores its own '\(option.key)' option") + } + } + + for operation in MySQLMaintenance.operations { + let base = try #require(MySQLMaintenance.statements( + operation: operation.name, + table: "orders", + schema: nil, + options: operation.defaultOptionValues, + flavor: .mysql + )) + for option in operation.options { + var changed = operation.defaultOptionValues + changed[option.key] = try alternative(to: option) + let result = try #require(MySQLMaintenance.statements( + operation: operation.name, table: "orders", schema: nil, options: changed, flavor: .mysql + )) + #expect(result != base, "\(operation.name) ignores its own '\(option.key)' option") + } + } + } + + private func alternative(to option: PluginMaintenanceOption) throws -> String { + guard let choices = option.choices else { + return option.defaultValue == "true" ? "false" : "true" + } + return try #require(choices.first { $0 != option.defaultValue }) + } +} diff --git a/TableProTests/Plugins/MySQLServerFlavorTests.swift b/TableProTests/Plugins/MySQLServerFlavorTests.swift index efcb1d0f6c..3f3436cf41 100644 --- a/TableProTests/Plugins/MySQLServerFlavorTests.swift +++ b/TableProTests/Plugins/MySQLServerFlavorTests.swift @@ -56,8 +56,8 @@ struct MySQLServerFlavorTests { @Test("TiDB and Databend offer only the maintenance they support") func maintenanceOperations() { #expect(MySQLServerFlavor.mysql.maintenanceOperations.count == 4) - #expect(MySQLServerFlavor.tidb(version: nil).maintenanceOperations == ["ANALYZE TABLE"]) - #expect(MySQLServerFlavor.databend.maintenanceOperations == ["ANALYZE TABLE"]) + #expect(MySQLServerFlavor.tidb(version: nil).maintenanceOperations.map(\.name) == ["ANALYZE TABLE"]) + #expect(MySQLServerFlavor.databend.maintenanceOperations.map(\.name) == ["ANALYZE TABLE"]) } @Test("TiDB sequences cannot be browsed, so they are not listed as tables") diff --git a/TableProTests/Views/Main/MaintenanceSheetIdentityTests.swift b/TableProTests/Views/Main/MaintenanceSheetIdentityTests.swift index 88f9b92b46..34d55a09b4 100644 --- a/TableProTests/Views/Main/MaintenanceSheetIdentityTests.swift +++ b/TableProTests/Views/Main/MaintenanceSheetIdentityTests.swift @@ -9,17 +9,28 @@ import Foundation @testable import TablePro +import TableProPluginKit import Testing @Suite("Maintenance sheet identity") struct MaintenanceSheetIdentityTests { + private func operation(_ name: String) -> PluginMaintenanceOperation { + PluginMaintenanceOperation(name: name, appliesTo: [.table], scope: .object) + } + @Test("The same table in two databases is two different requests") func distinguishesTwoDatabases() { let online = ActiveSheet.maintenance( - operation: "OPTIMIZE TABLE", tableName: "role_ability", database: "banshi_online", schema: nil + operation: operation("OPTIMIZE TABLE"), + tableName: "role_ability", + database: "banshi_online", + schema: nil ) let test = ActiveSheet.maintenance( - operation: "OPTIMIZE TABLE", tableName: "role_ability", database: "banshi_test", schema: nil + operation: operation("OPTIMIZE TABLE"), + tableName: "role_ability", + database: "banshi_test", + schema: nil ) #expect(online.id != test.id) @@ -28,10 +39,10 @@ struct MaintenanceSheetIdentityTests { @Test("The same table in two schemas of one database is two different requests") func distinguishesTwoSchemas() { let publicSchema = ActiveSheet.maintenance( - operation: "VACUUM", tableName: "orders", database: "app", schema: "public" + operation: operation("VACUUM"), tableName: "orders", database: "app", schema: "public" ) let reporting = ActiveSheet.maintenance( - operation: "VACUUM", tableName: "orders", database: "app", schema: "reporting" + operation: operation("VACUUM"), tableName: "orders", database: "app", schema: "reporting" ) #expect(publicSchema.id != reporting.id) @@ -40,10 +51,10 @@ struct MaintenanceSheetIdentityTests { @Test("The same object is the same request") func matchesTheSameObject() { let first = ActiveSheet.maintenance( - operation: "ANALYZE TABLE", tableName: "orders", database: "app", schema: "public" + operation: operation("ANALYZE TABLE"), tableName: "orders", database: "app", schema: "public" ) let second = ActiveSheet.maintenance( - operation: "ANALYZE TABLE", tableName: "orders", database: "app", schema: "public" + operation: operation("ANALYZE TABLE"), tableName: "orders", database: "app", schema: "public" ) #expect(first.id == second.id) @@ -52,12 +63,37 @@ struct MaintenanceSheetIdentityTests { @Test("A request that names no database is not the same as one that does") func distinguishesAnUnnamedDatabase() { let named = ActiveSheet.maintenance( - operation: "OPTIMIZE TABLE", tableName: "orders", database: "app", schema: nil + operation: operation("OPTIMIZE TABLE"), tableName: "orders", database: "app", schema: nil ) let unnamed = ActiveSheet.maintenance( - operation: "OPTIMIZE TABLE", tableName: "orders", database: nil, schema: nil + operation: operation("OPTIMIZE TABLE"), tableName: "orders", database: nil, schema: nil ) #expect(named.id != unnamed.id) } + + /// The identity keys on the operation's name, so two requests that differ only in the options the + /// descriptor declares are the same sheet. The sheet seeds its own state from those options. + @Test("Two descriptors with the same name are the same request") + func ignoresDescriptorShape() { + let plain = ActiveSheet.maintenance( + operation: PluginMaintenanceOperation(name: "VACUUM", appliesTo: [.table], scope: .object), + tableName: "orders", + database: "app", + schema: "public" + ) + let withOptions = ActiveSheet.maintenance( + operation: PluginMaintenanceOperation( + name: "VACUUM", + appliesTo: [.table, .materializedView], + scope: .objectOrDatabase, + options: [PluginMaintenanceOption(key: "full", label: "FULL", defaultValue: "false")] + ), + tableName: "orders", + database: "app", + schema: "public" + ) + + #expect(plain.id == withOptions.id) + } } diff --git a/TableProTests/Views/SidebarContextMenuLogicTests.swift b/TableProTests/Views/SidebarContextMenuLogicTests.swift index 627a770ae4..93bb0c96f5 100644 --- a/TableProTests/Views/SidebarContextMenuLogicTests.swift +++ b/TableProTests/Views/SidebarContextMenuLogicTests.swift @@ -124,12 +124,16 @@ struct SidebarContextMenuLogicTests { // MARK: - Maintenance group disabled rule - @Test("Maintenance group enabled with selection, writable, and supported ops") + private func operation(_ name: String) -> PluginMaintenanceOperation { + PluginMaintenanceOperation(name: name, appliesTo: [.table], scope: .object) + } + + @Test("Maintenance group enabled with selection, writable, and applicable ops") func maintenanceEnabledAllConditions() { #expect(SidebarContextMenuLogic.maintenanceGroupEnabled( isReadOnly: false, hasSelection: true, - supportedOperations: ["ANALYZE", "OPTIMIZE"] + applicableOperations: [operation("ANALYZE"), operation("OPTIMIZE")] )) } @@ -138,7 +142,7 @@ struct SidebarContextMenuLogicTests { #expect(!SidebarContextMenuLogic.maintenanceGroupEnabled( isReadOnly: true, hasSelection: true, - supportedOperations: ["ANALYZE"] + applicableOperations: [operation("ANALYZE")] )) } @@ -147,16 +151,16 @@ struct SidebarContextMenuLogicTests { #expect(!SidebarContextMenuLogic.maintenanceGroupEnabled( isReadOnly: false, hasSelection: false, - supportedOperations: ["ANALYZE"] + applicableOperations: [operation("ANALYZE")] )) } - @Test("Maintenance group disabled when driver exposes no ops") + @Test("Maintenance group disabled when nothing the driver offers applies to the clicked object") func maintenanceDisabledNoOps() { #expect(!SidebarContextMenuLogic.maintenanceGroupEnabled( isReadOnly: false, hasSelection: true, - supportedOperations: [] + applicableOperations: [] )) } diff --git a/docs/development/plugin-development.mdx b/docs/development/plugin-development.mdx index d471008fde..43315b4a8d 100644 --- a/docs/development/plugin-development.mdx +++ b/docs/development/plugin-development.mdx @@ -13,7 +13,7 @@ A plugin is a macOS loadable bundle target with `WRAPPER_EXTENSION = tableplugin | Key | Type | Required | Purpose | |-----|------|----------|---------| -| `TableProPluginKitVersion` | integer | Yes | The PluginKit ABI the plugin was built against. Current value: 28 | +| `TableProPluginKitVersion` | integer | Yes | The PluginKit ABI the plugin was built against. Current value: 29 | | `TableProProvidesDatabaseTypeIds` | array of strings | Recommended | Database type IDs the plugin serves, which is what makes lazy loading possible | | `CFBundleShortVersionString` | string | Yes | Plugin version, read by registry update checks | | `TableProMinAppVersion` | string | No | The loader rejects the plugin on an older app | diff --git a/docs/development/plugin-registry.mdx b/docs/development/plugin-registry.mdx index d8c922514e..393441a559 100644 --- a/docs/development/plugin-registry.mdx +++ b/docs/development/plugin-registry.mdx @@ -68,13 +68,13 @@ Themes carry no native code, so they match on architecture alone. "binaries": [ { "architecture": "arm64", - "pluginKitVersion": 28, + "pluginKitVersion": 29, "downloadURL": "https://github.com/TableProApp/TablePro/releases/download/plugin-oracle-v1.0.26/OracleDriver-arm64.zip", "sha256": "" }, { "architecture": "x86_64", - "pluginKitVersion": 28, + "pluginKitVersion": 29, "downloadURL": "https://github.com/TableProApp/TablePro/releases/download/plugin-oracle-v1.0.26/OracleDriver-x86_64.zip", "sha256": "" } diff --git a/docs/features/table-operations.mdx b/docs/features/table-operations.mdx index aeb9a64a07..f57aad7593 100644 --- a/docs/features/table-operations.mdx +++ b/docs/features/table-operations.mdx @@ -68,7 +68,9 @@ No other engine has a rename, so the item never appears on Cassandra, DynamoDB, ## Maintenance -Right-click a table, choose **Maintenance**, and pick an operation. A sheet shows the operation's options and the exact SQL before it runs. +Right-click a table, choose **Maintenance**, and pick an operation. The sheet shows the operation's options and the statement the driver will run, rebuilt as each option changes, so what is previewed is what executes. + +Each operation lists the object kinds it applies to, so a view offers only the operations its server accepts. On PostgreSQL that means VACUUM and REINDEX are absent on a view, which the server skips or refuses, and CLUSTER is absent on a partitioned table, which can never be clustered. An operation that acts on the whole database, such as SQLite's VACUUM and its integrity check, names the database rather than a table. | Database | Operations | |----------|-----------| @@ -76,7 +78,7 @@ Right-click a table, choose **Maintenance**, and pick an operation. A sheet show | MySQL / MariaDB | OPTIMIZE TABLE, ANALYZE TABLE, CHECK TABLE, REPAIR TABLE | | SQLite | VACUUM, ANALYZE, REINDEX, Integrity Check | -PostgreSQL VACUUM carries FULL (rewrites the table and blocks access), ANALYZE, and VERBOSE toggles. MySQL CHECK TABLE offers QUICK, FAST, MEDIUM (the default), EXTENDED, and CHANGED. No other engine reports maintenance operations, so the submenu is hidden there, and in read-only safe mode. +PostgreSQL VACUUM carries FULL (rewrites the table and blocks access), ANALYZE, and VERBOSE toggles. MySQL CHECK TABLE offers QUICK, FAST, MEDIUM (the default), EXTENDED, and CHANGED. The options come from the driver, so an engine that adds one shows it without an app change. No other engine reports maintenance operations, so the submenu is hidden there, and in read-only safe mode. ## Views diff --git a/project.yml b/project.yml index c8943891f0..7dbf4c81d8 100644 --- a/project.yml +++ b/project.yml @@ -491,6 +491,7 @@ targets: - Plugins/MySQLDriverPlugin/MySQLSessionFootprint.swift - Plugins/MySQLDriverPlugin/MySQLGeneratedColumnClassification.swift - Plugins/MySQLDriverPlugin/MySQLKillTarget.swift + - Plugins/MySQLDriverPlugin/MySQLMaintenance.swift - Plugins/MySQLDriverPlugin/MySQLObjectQueries.swift - Plugins/MySQLDriverPlugin/MySQLSelectLimitStatement.swift - Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift @@ -504,6 +505,7 @@ targets: - Plugins/SQLiteDriverPlugin/SQLiteCheckConstraintParser.swift - Plugins/SQLiteDriverPlugin/SQLiteCreateTableDDL.swift - Plugins/SQLiteDriverPlugin/SQLiteDefaultValue.swift + - Plugins/SQLiteDriverPlugin/SQLiteMaintenance.swift - Plugins/LibSQLDriverPlugin/LibSQLDefaultValue.swift - Plugins/LibSQLDriverPlugin/HranaHttpClient.swift - Plugins/CloudflareD1DriverPlugin/CloudflareD1DefaultValue.swift @@ -530,6 +532,7 @@ targets: - Plugins/PostgreSQLDriverPlugin/PostgreSQLCommentStatements.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLForeignKeyQueries.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLIndexQueries.swift + - Plugins/PostgreSQLDriverPlugin/PostgreSQLMaintenance.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLPrincipalQueries.swift - Plugins/PostgreSQLDriverPlugin/PostgreSQLRelationSQL.swift From 7bd3a06c9ba746237d7277035c1d62d2c492b54e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 10:16:57 +0700 Subject: [PATCH 44/54] fix(datagrid): offer only the structure edits an object's kind accepts (#2726) (#2778) Claude-Session: https://claude.ai/code/session_013prPDi2xCGd2JqrfEnTELn --- CHANGELOG.md | 2 + .../QueryExecutionCoordinator+Helpers.swift | 1 + ...yExecutionCoordinator+MultiStatement.swift | 1 + .../Plugins/PluginManager+Registration.swift | 7 + ...uginMetadataRegistry+CuratedDefaults.swift | 4 +- .../Infrastructure/EditorTabOpener.swift | 2 + .../RecentlyClosedTabReopener.swift | 1 + .../Database/StructureEditEligibility.swift | 268 ++++++++++++++++++ TablePro/Models/Query/EditorTabPayload.swift | 14 +- TablePro/Models/Query/QueryTab.swift | 5 +- TablePro/Models/Query/QueryTabManager.swift | 6 +- TablePro/Models/Query/QueryTabState.swift | 25 +- TablePro/Models/Query/ResultOrigin.swift | 5 + .../Models/Query/TabNavigationHistory.swift | 3 + .../Models/Schema/ColumnReorderSupport.swift | 15 +- .../Models/Schema/ForeignKeyEditSupport.swift | 35 ++- .../Models/UI/DataGridConfiguration.swift | 7 + .../Main/Child/MainEditorContentView.swift | 4 +- .../MainContentCoordinator+Navigation.swift | 10 + ...ContentCoordinator+NavigationHistory.swift | 2 + ...ContentCoordinator+TableRowsMutation.swift | 1 + .../Views/Results/DataGridCoordinator.swift | 4 + .../Extensions/DataGridView+Editing.swift | 20 +- .../Views/Structure/StructureEditGate.swift | 112 ++++++++ .../Structure/StructureEditingSession.swift | 9 +- .../Structure/StructureFooterPolicy.swift | 90 ++++++ .../Structure/StructureGridDelegate.swift | 63 ++-- .../TableStructureView+ColumnReorder.swift | 2 +- .../TableStructureView+EditGate.swift | 67 +++++ .../Views/Structure/TableStructureView.swift | 115 ++------ .../StructureEditMatrixCurationTests.swift | 66 +++++ .../StructureEditEligibilityTests.swift | 262 +++++++++++++++++ .../Models/Query/TabObjectKindTests.swift | 159 +++++++++++ .../Schema/ColumnReorderPolicyTests.swift | 12 +- .../Schema/ForeignKeyEditPolicyTests.swift | 19 +- .../Structure/StructureEditGateTests.swift | 128 +++++++++ .../StructureFooterPolicyTests.swift | 140 +++++++++ .../StructureGridDelegateAddRowTests.swift | 70 ++++- docs/databases/postgresql.mdx | 2 + docs/features/table-structure.mdx | 22 +- 40 files changed, 1626 insertions(+), 154 deletions(-) create mode 100644 TablePro/Models/Database/StructureEditEligibility.swift create mode 100644 TablePro/Views/Structure/StructureEditGate.swift create mode 100644 TablePro/Views/Structure/StructureFooterPolicy.swift create mode 100644 TablePro/Views/Structure/TableStructureView+EditGate.swift create mode 100644 TableProTests/Core/Plugins/StructureEditMatrixCurationTests.swift create mode 100644 TableProTests/Models/Database/StructureEditEligibilityTests.swift create mode 100644 TableProTests/Models/Query/TabObjectKindTests.swift create mode 100644 TableProTests/Views/Structure/StructureEditGateTests.swift create mode 100644 TableProTests/Views/Structure/StructureFooterPolicyTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index d364d21888..58e15b3059 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Editor Font and Data Grid Font moved to Settings > Editor and Settings > Data & Results, and kept per Mac. - Editor font size range of 10 to 24 points everywhere, including zoom. - Structure editor options the connected PostgreSQL server does not support left out: generated columns before 12, BRIN before 9.5, and the MySQL-only FULLTEXT and SPATIAL index types. +- Structure tab read-only on a view, a materialized view, a foreign table or a system table outside PostgreSQL. (#2726) ### Removed @@ -235,6 +236,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Maintenance SQL preview showing a statement the app never runs. (#2726) - `[` in a SQL Server filter value read as a wildcard. - Non-ASCII text turned into `?` by Copy as INSERT, Copy as IN, Preview Referenced Row, compare scripts and column defaults on SQL Server. +- Structure tab offering column, index and constraint edits that views and materialized views refuse. (#2726) ### Security diff --git a/TablePro/Core/Coordinators/QueryExecutionCoordinator+Helpers.swift b/TablePro/Core/Coordinators/QueryExecutionCoordinator+Helpers.swift index f2748b7b9f..8d8ecb4144 100644 --- a/TablePro/Core/Coordinators/QueryExecutionCoordinator+Helpers.swift +++ b/TablePro/Core/Coordinators/QueryExecutionCoordinator+Helpers.swift @@ -484,6 +484,7 @@ extension QueryExecutionCoordinator { primaryKeyColumns: primaryKeyColumns, isEditable: isEditable, isView: context.isView, + objectType: context.objectType, keysResolved: true ) } diff --git a/TablePro/Core/Coordinators/QueryExecutionCoordinator+MultiStatement.swift b/TablePro/Core/Coordinators/QueryExecutionCoordinator+MultiStatement.swift index 97f8f5faf1..be0aa3e3ca 100644 --- a/TablePro/Core/Coordinators/QueryExecutionCoordinator+MultiStatement.swift +++ b/TablePro/Core/Coordinators/QueryExecutionCoordinator+MultiStatement.swift @@ -80,6 +80,7 @@ extension QueryExecutionCoordinator { primaryKeyColumns: [], isEditable: resolved.isEditable && producesRows, isView: tab.tableContext.isView, + objectType: tab.tableContext.objectType, keysResolved: false ) } diff --git a/TablePro/Core/Plugins/PluginManager+Registration.swift b/TablePro/Core/Plugins/PluginManager+Registration.swift index fbb91a7268..8f98d68641 100644 --- a/TablePro/Core/Plugins/PluginManager+Registration.swift +++ b/TablePro/Core/Plugins/PluginManager+Registration.swift @@ -555,6 +555,13 @@ extension PluginManager { .structureEditing.foreignKeyEdit ?? .unsupported } + /// The fallback is `.tablesOnly`, never a curated engine's matrix: an engine nobody has measured + /// must not be offered an edit on anything but a table. + func structureEditMatrix(for databaseType: DatabaseType) -> StructureObjectEditMatrix { + PluginMetadataRegistry.shared.snapshot(for: databaseType)? + .structureEditing.structureEdits ?? .tablesOnly + } + func supportsDropDatabase(for databaseType: DatabaseType) -> Bool { PluginMetadataRegistry.shared.snapshot(for: databaseType)? .capabilities.supportsDropDatabase ?? false diff --git a/TablePro/Core/Plugins/PluginMetadataRegistry+CuratedDefaults.swift b/TablePro/Core/Plugins/PluginMetadataRegistry+CuratedDefaults.swift index 558d6ea777..6b900b61a0 100644 --- a/TablePro/Core/Plugins/PluginMetadataRegistry+CuratedDefaults.swift +++ b/TablePro/Core/Plugins/PluginMetadataRegistry+CuratedDefaults.swift @@ -372,7 +372,9 @@ extension PluginMetadataRegistry { brandColorHex: "#336791", queryLanguageName: "SQL", editorLanguage: .sql, connectionMode: .network, supportsDatabaseSwitching: true, - structureEditing: SchemaEditingSupport(columnReorder: .rebuild, foreignKeyEdit: .alter), + structureEditing: SchemaEditingSupport( + columnReorder: .rebuild, foreignKeyEdit: .alter, structureEdits: .postgreSQL + ), capabilities: PluginMetadataSnapshot.CapabilityFlags( supportsSchemaSwitching: true, supportsImport: true, diff --git a/TablePro/Core/Services/Infrastructure/EditorTabOpener.swift b/TablePro/Core/Services/Infrastructure/EditorTabOpener.swift index 731c6e701c..26d176bccb 100644 --- a/TablePro/Core/Services/Infrastructure/EditorTabOpener.swift +++ b/TablePro/Core/Services/Infrastructure/EditorTabOpener.swift @@ -113,6 +113,7 @@ internal enum EditorTabOpener { databaseName: payload.databaseName ?? browseDatabaseName, schemaName: resolvedSchemaName, isView: payload.isView, + objectType: payload.objectType, isPreview: payload.isPreview, allowsDuplicate: payload.forcesNewTab ) @@ -126,6 +127,7 @@ internal enum EditorTabOpener { /// work the user did there while leaving the grid on rows the new filter never ran. guard didCreateTab, let index = tabManager.selectedTabIndex else { return } tabManager.tabs[index].tableContext.isView = payload.isView + tabManager.tabs[index].tableContext.objectType = payload.objectType tabManager.tabs[index].tableContext.isEditable = !payload.isView tabManager.tabs[index].tableContext.schemaName = resolvedSchemaName if payload.showStructure { diff --git a/TablePro/Core/Services/Infrastructure/RecentlyClosedTabReopener.swift b/TablePro/Core/Services/Infrastructure/RecentlyClosedTabReopener.swift index f4c24eaa55..9eec6dbf97 100644 --- a/TablePro/Core/Services/Infrastructure/RecentlyClosedTabReopener.swift +++ b/TablePro/Core/Services/Infrastructure/RecentlyClosedTabReopener.swift @@ -70,6 +70,7 @@ internal enum RecentlyClosedTabReopener { databaseName: tab.tableContext.databaseName, schemaName: tab.tableContext.schemaName, isView: tab.tableContext.isView, + objectType: tab.tableContext.objectType, skipAutoExecute: true, sourceFileURL: tab.content.sourceFileURL, erDiagramSchemaKey: tab.display.erDiagramSchemaKey, diff --git a/TablePro/Models/Database/StructureEditEligibility.swift b/TablePro/Models/Database/StructureEditEligibility.swift new file mode 100644 index 0000000000..578b370953 --- /dev/null +++ b/TablePro/Models/Database/StructureEditEligibility.swift @@ -0,0 +1,268 @@ +// +// StructureEditEligibility.swift +// TablePro +// + +import Foundation +import TableProPluginKit + +/// One change the Structure tab can ask a server to make. +/// +/// The vocabulary is per operation rather than per object because the server answers per operation. +/// Measured on PostgreSQL 17.11: a view takes `RENAME COLUMN`, `SET DEFAULT`, `DROP DEFAULT` and +/// `COMMENT ON COLUMN` and refuses `ADD COLUMN`, `SET NOT NULL`, `SET DATA TYPE`, `CREATE INDEX` and +/// every `ADD CONSTRAINT`, while a materialized view takes `CREATE INDEX` and refuses `SET DEFAULT`. +/// A single read-only flag for the whole object would withhold four edits that work and still offer +/// several the server always refuses. +enum StructureEditOperation: Sendable, Hashable, CaseIterable { + case addColumn + case dropColumn + case renameColumn + case setNotNull + case dropNotNull + case setDefault + case dropDefault + case changeColumnType + /// The column attributes an engine can only change by rewriting the whole column definition: + /// primary key, auto increment, on update, charset, collation and generated. One case rather + /// than six, so none of them is ever gated through a proxy that means something else. + case redefineColumn + case addIndex + case dropIndex + case addForeignKey + case dropForeignKey + case addCheckConstraint + case dropCheckConstraint + case commentOnColumn + case reorderColumns + + /// What the edit is about, which is what a refusal has to explain. A materialized view refuses + /// `SET DEFAULT` and `ADD CONSTRAINT FOREIGN KEY` for two different reasons, and one sentence + /// covering both would be true of neither. + enum Subject: Sendable, Hashable { + case columns + case columnOrder + case indexes + case constraints + } + + var subject: Subject { + switch self { + case .addColumn, .dropColumn, .renameColumn, .setNotNull, .dropNotNull, .setDefault, + .dropDefault, .changeColumnType, .redefineColumn, .commentOnColumn: + return .columns + case .reorderColumns: + return .columnOrder + case .addIndex, .dropIndex: + return .indexes + case .addForeignKey, .dropForeignKey, .addCheckConstraint, .dropCheckConstraint: + return .constraints + } + } +} + +/// Which structure edits each kind of object accepts on one engine. +/// +/// Curated per `DatabaseType` in `SchemaEditingSupport` rather than asked of a driver, because the +/// affordance has to be offered or withheld before the user starts filling a row in, and a +/// capability the app only learns from a failed statement is far too late for that. +struct StructureObjectEditMatrix: Sendable, Equatable { + private let operationsByKind: [TableInfo.TableType: Set] + + init(_ operationsByKind: [TableInfo.TableType: Set]) { + self.operationsByKind = operationsByKind + } + + func operations(for kind: TableInfo.TableType) -> Set { + operationsByKind[kind] ?? [] + } + + private static let everyOperation = Set(StructureEditOperation.allCases) + + /// The default for an engine nobody has curated: a real table takes every edit the engine's own + /// flags allow, and no other kind takes any. Conservative on purpose. Offering an edit the + /// server refuses costs the user a filled-in row and an error at Save; withholding one it would + /// have taken costs a trip to the query editor. + static let tablesOnly = StructureObjectEditMatrix([ + .table: everyOperation, + .partitionedTable: everyOperation + ]) + + /// Measured against PostgreSQL 17.11, one statement per cell. A table and a partitioned table + /// take all seventeen. A view and a materialized view differ on `SET DEFAULT` and on + /// `CREATE INDEX`, which is why one row per kind is the only shape that works. A foreign table + /// takes every column change and `ADD CHECK` but refuses `CREATE INDEX`, `FOREIGN KEY` and + /// `UNIQUE`. A system table refuses everything with "permission denied: is a system catalog", + /// and an external table is a Redshift Spectrum relation whose columns live in another catalog. + static let postgreSQL = StructureObjectEditMatrix([ + .table: everyOperation, + .partitionedTable: everyOperation, + .view: [.renameColumn, .setDefault, .dropDefault, .commentOnColumn], + .materializedView: [.renameColumn, .commentOnColumn, .addIndex, .dropIndex], + .foreignTable: [ + .addColumn, .dropColumn, .renameColumn, .setNotNull, .dropNotNull, .setDefault, + .dropDefault, .changeColumnType, .addCheckConstraint, .dropCheckConstraint, + .commentOnColumn + ], + .systemTable: [], + .externalTable: [] + ]) +} + +/// Whether the Structure tab may offer one edit right now, and what to say when it may not. +/// +/// Mirrors `ForeignKeyEditAvailability` so every refusal in this tab carries its own sentence. A +/// control that dims without saying why reads as a broken app, and a control that stays enabled over +/// a statement the server always refuses is worse: the user fills the row in first. +enum StructureEditAvailability: Sendable, Equatable { + case available + + case unavailable(reason: String) + + var isAvailable: Bool { self == .available } + + var unavailableReason: String? { + if case .unavailable(let reason) = self { return reason } + return nil + } +} + +/// The single decision about which structure edits an object's kind accepts. +/// +/// Pure, so the rule is testable without a connection, and ordered: an engine that cannot edit +/// structure at all says that first, then the object's kind, then the engine's own statement for the +/// operation. Reading the kind as one `isView` Bool is the defect this replaces, because +/// `TableInfo.TableType.allowsRowEditing` is true for a materialized view, so the Structure tab +/// offered `ADD COLUMN`, `SET NOT NULL`, type changes and constraint edits that PostgreSQL always +/// refuses. (#2726) +enum StructureEditEligibility { + static func allows( + _ operation: StructureEditOperation, + on kind: TableInfo.TableType, + matrix: StructureObjectEditMatrix + ) -> Bool { + matrix.operations(for: kind).contains(operation) + } + + /// Why this kind of object refuses the operation, and nil when it does not. + /// + /// Handed to `ForeignKeyEditPolicy` and `ColumnReorderPolicy`, which used to decide it from an + /// `isTable` Bool and then name a view in the sentence. Only the matrix knows which of seven + /// kinds is in front of the user, so only the matrix can word the refusal. + static func refusalReason( + for operation: StructureEditOperation, + on kind: TableInfo.TableType, + matrix: StructureObjectEditMatrix + ) -> String? { + guard !allows(operation, on: kind, matrix: matrix) else { return nil } + return reason(operation.subject, kind) + } + + static func resolve( + _ operation: StructureEditOperation, + on kind: TableInfo.TableType, + matrix: StructureObjectEditMatrix, + engineAllows: Bool, + engineName: String, + canEditSchema: Bool + ) -> StructureEditAvailability { + guard canEditSchema else { + return .unavailable( + reason: String(format: String(localized: "%@ cannot edit a table's structure."), engineName) + ) + } + if let refusal = refusalReason(for: operation, on: kind, matrix: matrix) { + return .unavailable(reason: refusal) + } + guard engineAllows else { + return .unavailable(reason: engineReason(operation.subject, engineName)) + } + return .available + } + + /// Every field of the Columns grid this kind of object lets the user change. + /// + /// Keyed by field rather than by row, because the refusal is per column attribute: PostgreSQL + /// takes a view's `RENAME COLUMN` and `SET DEFAULT` and refuses its `SET NOT NULL` and + /// `SET DATA TYPE`, so Name and Default stay editable while Nullable and Type lock. + static func editableFields( + on kind: TableInfo.TableType, + matrix: StructureObjectEditMatrix + ) -> Set { + let allowed = matrix.operations(for: kind) + return Set(StructureColumnField.allCases.filter { field in + !operations(expressing: field).isDisjoint(with: allowed) + }) + } + + static func allowsAnyEdit(on kind: TableInfo.TableType, matrix: StructureObjectEditMatrix) -> Bool { + !matrix.operations(for: kind).isEmpty + } + + /// The operations that can express a change to this field. A field with more than one is + /// editable as soon as either statement is accepted, because the grid cannot know in advance + /// which direction the user will toggle it. + private static func operations(expressing field: StructureColumnField) -> Set { + switch field { + case .name: return [.renameColumn] + case .type: return [.changeColumnType] + case .nullable: return [.setNotNull, .dropNotNull] + case .defaultValue: return [.setDefault, .dropDefault] + case .comment: return [.commentOnColumn] + case .onUpdate, .primaryKey, .autoIncrement, .charset, .collation, .generated, + .generationExpression: + return [.redefineColumn] + @unknown default: + /// A field this build does not know is gated behind a full column rewrite, which is the + /// narrowest answer available and therefore the safe one. + return [.redefineColumn] + } + } + + /// Why the engine cannot make the change even on a plain table. Worded per subject rather than + /// once, because "cannot edit a table's structure" over a dimmed **Add Index** tells the reader + /// nothing they could act on. + private static func engineReason(_ subject: StructureEditOperation.Subject, _ engineName: String) -> String { + switch subject { + case .columns: + return String(format: String(localized: "%@ cannot make this change to a table's columns."), engineName) + case .columnOrder: + return String( + format: String(localized: "%@ cannot change the order of a table's columns."), + engineName + ) + case .indexes: + return String(format: String(localized: "%@ cannot add or remove a table's indexes."), engineName) + case .constraints: + return String(format: String(localized: "%@ cannot add or remove a table's constraints."), engineName) + } + } + + private static func reason(_ subject: StructureEditOperation.Subject, _ kind: TableInfo.TableType) -> String { + let noun = objectNoun(kind) + switch subject { + case .columns: + return String(format: String(localized: "%@ does not accept this column change."), noun) + case .columnOrder: + return String(format: String(localized: "%@ has no column order of its own to change."), noun) + case .indexes: + return String(format: String(localized: "%@ cannot have indexes."), noun) + case .constraints: + return String(format: String(localized: "%@ cannot have constraints."), noun) + } + } + + /// The object's kind as the subject of a sentence, because every refusal above names it. The + /// sidebar's own label is a bare noun ("View"), which reads as a heading rather than a sentence. + private static func objectNoun(_ kind: TableInfo.TableType) -> String { + switch kind { + case .table: return String(localized: "A table") + case .partitionedTable: return String(localized: "A partitioned table") + case .view: return String(localized: "A view") + case .materializedView: return String(localized: "A materialized view") + case .foreignTable: return String(localized: "A foreign table") + case .systemTable: return String(localized: "A system table") + case .externalTable: return String(localized: "An external table") + } + } +} diff --git a/TablePro/Models/Query/EditorTabPayload.swift b/TablePro/Models/Query/EditorTabPayload.swift index d2735d792b..d4e76f1c31 100644 --- a/TablePro/Models/Query/EditorTabPayload.swift +++ b/TablePro/Models/Query/EditorTabPayload.swift @@ -37,6 +37,10 @@ internal struct EditorTabPayload: Codable, Hashable { internal let initialQuery: String? /// Whether this tab displays a database view (read-only) internal let isView: Bool + /// The object's own kind, which decides which structure edits the tab may offer. Carried beside + /// `isView` because that Bool answers a different question and cannot tell a materialized view + /// from a table. (#2726) + internal let objectType: TableInfo.TableType? /// Whether to show the structure view instead of data (for "Show Structure" context menu) internal let showStructure: Bool /// Whether to skip automatic query execution (used for restored tabs that should lazy-load) @@ -61,7 +65,7 @@ internal struct EditorTabPayload: Codable, Hashable { private enum CodingKeys: String, CodingKey { case id, connectionId, tabType, tableName, databaseName, schemaName - case initialQuery, isView, showStructure, skipAutoExecute, isPreview + case initialQuery, isView, objectType, showStructure, skipAutoExecute, isPreview case forcesNewTab case tabTitle case initialFilterState, sourceFileURL, erDiagramSchemaKey, objectRef, intent @@ -78,6 +82,7 @@ internal struct EditorTabPayload: Codable, Hashable { schemaName: String? = nil, initialQuery: String? = nil, isView: Bool = false, + objectType: TableInfo.TableType? = nil, showStructure: Bool = false, skipAutoExecute: Bool = false, isPreview: Bool = false, @@ -97,6 +102,7 @@ internal struct EditorTabPayload: Codable, Hashable { self.schemaName = schemaName self.initialQuery = initialQuery self.isView = isView + self.objectType = objectType self.showStructure = showStructure self.skipAutoExecute = skipAutoExecute self.isPreview = isPreview @@ -119,6 +125,10 @@ internal struct EditorTabPayload: Codable, Hashable { schemaName = try container.decodeIfPresent(String.self, forKey: .schemaName) initialQuery = try container.decodeIfPresent(String.self, forKey: .initialQuery) isView = try container.decodeIfPresent(Bool.self, forKey: .isView) ?? false + /// A raw String, so a spelling a newer build invents decodes to nil rather than throwing and + /// losing the whole payload. + objectType = try container.decodeIfPresent(String.self, forKey: .objectType) + .flatMap(TableInfo.TableType.init(rawValue:)) showStructure = try container.decodeIfPresent(Bool.self, forKey: .showStructure) ?? false skipAutoExecute = try container.decodeIfPresent(Bool.self, forKey: .skipAutoExecute) ?? false isPreview = try container.decodeIfPresent(Bool.self, forKey: .isPreview) ?? false @@ -146,6 +156,7 @@ internal struct EditorTabPayload: Codable, Hashable { try container.encodeIfPresent(schemaName, forKey: .schemaName) try container.encodeIfPresent(initialQuery, forKey: .initialQuery) try container.encode(isView, forKey: .isView) + try container.encodeIfPresent(objectType?.rawValue, forKey: .objectType) try container.encode(showStructure, forKey: .showStructure) try container.encode(skipAutoExecute, forKey: .skipAutoExecute) try container.encode(isPreview, forKey: .isPreview) @@ -168,6 +179,7 @@ internal struct EditorTabPayload: Codable, Hashable { self.schemaName = tab.tableContext.schemaName self.initialQuery = tab.content.query self.isView = tab.tableContext.isView + self.objectType = tab.tableContext.objectType self.showStructure = tab.display.resultsViewMode == .structure self.skipAutoExecute = skipAutoExecute self.isPreview = false diff --git a/TablePro/Models/Query/QueryTab.swift b/TablePro/Models/Query/QueryTab.swift index e94279226c..0ea6b0c79a 100644 --- a/TablePro/Models/Query/QueryTab.swift +++ b/TablePro/Models/Query/QueryTab.swift @@ -203,7 +203,8 @@ struct QueryTab: Identifiable, Equatable { databaseName: persisted.databaseName, schemaName: persisted.schemaName, isEditable: persisted.tabType == .table && !persisted.isView, - isView: persisted.isView + isView: persisted.isView, + objectType: persisted.objectTypeRawValue.flatMap(TableInfo.TableType.init(rawValue:)) ) self.display = TabDisplayState( erDiagramSchemaKey: persisted.erDiagramSchemaKey, @@ -377,6 +378,7 @@ struct QueryTab: Identifiable, Equatable { tabType: tabType, tableName: tableContext.tableName, isView: tableContext.isView, + objectTypeRawValue: tableContext.objectType?.rawValue, databaseName: tableContext.databaseName, schemaName: tableContext.schemaName, sourceFileURL: content.sourceFileURL, @@ -413,6 +415,7 @@ struct QueryTab: Identifiable, Equatable { && lhs.display == rhs.display && lhs.tableContext.isEditable == rhs.tableContext.isEditable && lhs.tableContext.isView == rhs.tableContext.isView + && lhs.tableContext.objectType == rhs.tableContext.objectType && lhs.tabType == rhs.tabType && lhs.isPreview == rhs.isPreview && lhs.hasUserInteraction == rhs.hasUserInteraction diff --git a/TablePro/Models/Query/QueryTabManager.swift b/TablePro/Models/Query/QueryTabManager.swift index 25d7f1c6b7..7131737823 100644 --- a/TablePro/Models/Query/QueryTabManager.swift +++ b/TablePro/Models/Query/QueryTabManager.swift @@ -299,6 +299,7 @@ final class QueryTabManager { databaseName: String = "", schemaName: String? = nil, isView: Bool = false, + objectType: TableInfo.TableType? = nil, isPreview: Bool = false, allowsDuplicate: Bool = false, quoteIdentifier: ((String) -> String)? = nil @@ -330,6 +331,7 @@ final class QueryTabManager { ) newTab.pagination = PaginationState(pageSize: pageSize) newTab.tableContext.databaseName = databaseName + newTab.tableContext.objectType = objectType newTab.tableContext.schemaName = schemaName newTab.isPreview = isPreview tabs.append(newTab) @@ -445,7 +447,8 @@ final class QueryTabManager { @discardableResult func replaceTabContent( tableName: String, databaseType: DatabaseType = .mysql, - isView: Bool = false, databaseName: String = "", + isView: Bool = false, objectType: TableInfo.TableType? = nil, + databaseName: String = "", schemaName: String? = nil, isPreview: Bool = false, quoteIdentifier: ((String) -> String)? = nil ) throws -> Bool { @@ -486,6 +489,7 @@ final class QueryTabManager { tab.pendingChanges = TabChangeSnapshot() tab.hasUserInteraction = false tab.tableContext.isView = isView + tab.tableContext.objectType = objectType tab.tableContext.isEditable = !isView tab.filterState = TabFilterState() tab.columnLayout = ColumnLayoutState() diff --git a/TablePro/Models/Query/QueryTabState.swift b/TablePro/Models/Query/QueryTabState.swift index 91c29b5768..7a0cef3658 100644 --- a/TablePro/Models/Query/QueryTabState.swift +++ b/TablePro/Models/Query/QueryTabState.swift @@ -31,6 +31,10 @@ struct PersistedTab: Codable { let tabType: TabType let tableName: String? var isView: Bool = false + /// The object's own kind, as its `TableInfo.TableType` raw value. Optional and a raw String so a + /// file written before this existed decodes to nil, and a spelling a newer build invents decodes + /// to nil too rather than throwing and taking the whole tab aggregate with it. + var objectTypeRawValue: String? var databaseName: String = "" var schemaName: String? var sourceFileURL: URL? @@ -61,6 +65,7 @@ struct PersistedTab: Codable { tabType: TabType, tableName: String?, isView: Bool = false, + objectTypeRawValue: String? = nil, databaseName: String = "", schemaName: String? = nil, sourceFileURL: URL? = nil, @@ -84,6 +89,7 @@ struct PersistedTab: Codable { self.tabType = tabType self.tableName = tableName self.isView = isView + self.objectTypeRawValue = objectTypeRawValue self.databaseName = databaseName self.schemaName = schemaName self.sourceFileURL = sourceFileURL @@ -103,7 +109,7 @@ struct PersistedTab: Codable { } private enum CodingKeys: String, CodingKey { - case id, title, query, tabType, tableName, isView, databaseName, schemaName + case id, title, query, tabType, tableName, isView, objectTypeRawValue, databaseName, schemaName case sourceFileURL, erDiagramSchemaKey, objectRef, queryParameters case sortColumns, sortSource, restoredPage, restoredPageSize, cursorOffset, cursorLength case collapsedFoldRanges @@ -119,6 +125,7 @@ struct PersistedTab: Codable { tabType = try container.decode(TabType.self, forKey: .tabType) tableName = try container.decodeIfPresent(String.self, forKey: .tableName) isView = try container.decodeIfPresent(Bool.self, forKey: .isView) ?? false + objectTypeRawValue = try container.decodeIfPresent(String.self, forKey: .objectTypeRawValue) databaseName = try container.decodeIfPresent(String.self, forKey: .databaseName) ?? "" schemaName = try container.decodeIfPresent(String.self, forKey: .schemaName) sourceFileURL = try container.decodeIfPresent(URL.self, forKey: .sourceFileURL) @@ -564,6 +571,22 @@ struct TabTableContext: Equatable { var isEditable: Bool = false var isView: Bool = false + /// The object's own kind, carried beside `isView` rather than replacing it. + /// + /// The two answer different questions. `isView` decides whether the *rows* may be written, which + /// a dozen Bool-only carriers already speak (deeplinks, the URL parser, scripting, recents), and + /// it comes from `allowsRowEditing`, which is deliberately true for a materialized view because + /// a matview does hold rows. This says which of seven kinds the object is, which is the only + /// thing that can say which *structure* edits it accepts. Conflating them is the defect. (#2726) + /// + /// Nil on a tab restored from a file written before this existed, and on any path that never + /// learned the kind; `resolvedObjectKind()` falls back to what `isView` can still tell us. + var objectType: TableInfo.TableType? + + func resolvedObjectKind() -> TableInfo.TableType { + objectType ?? (isView ? .view : .table) + } + var primaryKeyColumn: String? { primaryKeyColumns.first } /// A tab opened without an explicit database carries an empty name and follows the window's diff --git a/TablePro/Models/Query/ResultOrigin.swift b/TablePro/Models/Query/ResultOrigin.swift index e1208ffeb1..cdf986a821 100644 --- a/TablePro/Models/Query/ResultOrigin.swift +++ b/TablePro/Models/Query/ResultOrigin.swift @@ -19,6 +19,9 @@ struct ResultOrigin: Equatable { var primaryKeyColumns: [String] var isEditable: Bool var isView: Bool + /// The kind of object these rows came from, so a result switched back to restores the tab's + /// structure gate rather than the table `isView` alone would imply. (#2726) + var objectType: TableInfo.TableType? /// Whether anything has actually looked up this table's key columns. An empty /// `primaryKeyColumns` means two different things: a table that genuinely has no key, which @@ -33,6 +36,7 @@ struct ResultOrigin: Equatable { primaryKeyColumns: [String] = [], isEditable: Bool = false, isView: Bool = false, + objectType: TableInfo.TableType? = nil, keysResolved: Bool = false ) { self.tableName = tableName @@ -41,6 +45,7 @@ struct ResultOrigin: Equatable { self.primaryKeyColumns = primaryKeyColumns self.isEditable = isEditable self.isView = isView + self.objectType = objectType self.keysResolved = keysResolved } } diff --git a/TablePro/Models/Query/TabNavigationHistory.swift b/TablePro/Models/Query/TabNavigationHistory.swift index a87c3aa485..3d4f3c9b3d 100644 --- a/TablePro/Models/Query/TabNavigationHistory.swift +++ b/TablePro/Models/Query/TabNavigationHistory.swift @@ -24,6 +24,9 @@ struct TabNavigationEntry: Equatable { var databaseName: String var schemaName: String? var isView: Bool + /// The object's own kind, so Back and Forward put the tab on a materialized view rather than + /// falling back to the table the `isView` Bool cannot distinguish it from. (#2726) + var objectType: TableInfo.TableType? var resultsViewMode: ResultsViewMode var filterState: TabFilterState var sortColumns: [PersistedSortColumn] diff --git a/TablePro/Models/Schema/ColumnReorderSupport.swift b/TablePro/Models/Schema/ColumnReorderSupport.swift index 7c665981ff..f74ae43d36 100644 --- a/TablePro/Models/Schema/ColumnReorderSupport.swift +++ b/TablePro/Models/Schema/ColumnReorderSupport.swift @@ -82,23 +82,24 @@ enum ColumnMove { /// the drop, while the drag itself was offered unconditionally, so 30 engines lifted the row, /// opened the insertion gap, took the drop and did nothing. enum ColumnReorderPolicy { + /// - Parameter kindRefusal: Why the object's own kind refuses a reorder, nil when it accepts one. + /// Supplied by `StructureEditEligibility`, because only the per-kind matrix knows which of + /// seven object kinds is in front of the user and can therefore word the refusal. (#2726) static func resolve( support: ColumnReorderSupport, engineName: String, isColumnsTab: Bool, - isTable: Bool, + kindRefusal: String?, canEditSchema: Bool, hasStagedChanges: Bool, isRearranged: Bool ) -> ColumnReorderAvailability { guard isColumnsTab else { return .notApplicable } /// Every mechanism emits table DDL, and the SQLite one looks the table up by - /// `sqlite_master.type = 'table'`, so a view drag would end in an error rather than an - /// explanation. A view's column order comes from its own `SELECT`. - guard isTable else { - return .unavailable( - reason: String(localized: "A view's column order comes from its query. Edit the view to change it.") - ) + /// `sqlite_master.type = 'table'`, so a drag on anything else would end in an error rather + /// than an explanation. + if let kindRefusal { + return .unavailable(reason: kindRefusal) } guard canEditSchema else { return .unavailable( diff --git a/TablePro/Models/Schema/ForeignKeyEditSupport.swift b/TablePro/Models/Schema/ForeignKeyEditSupport.swift index f2dc67a02f..fc1afab234 100644 --- a/TablePro/Models/Schema/ForeignKeyEditSupport.swift +++ b/TablePro/Models/Schema/ForeignKeyEditSupport.swift @@ -51,13 +51,29 @@ enum ForeignKeyEditAvailability: Sendable, Equatable { if case .unavailable(let reason) = self { return reason } return nil } + + /// The same answer in the vocabulary the rest of the Structure tab speaks, so one gate can hand + /// every call site a single type while this policy stays the owner of the foreign key wording. + var structureEditAvailability: StructureEditAvailability { + switch self { + case .available: + return .available + case .unavailable(let reason): + return .unavailable(reason: reason) + } + } } enum ForeignKeyEditPolicy { + /// - Parameter kindRefusal: Why the object's own kind refuses a foreign key edit, nil when it + /// accepts one. Supplied by `StructureEditEligibility`, because only the per-kind matrix knows + /// which of seven object kinds is in front of the user. This used to be an `isTable` Bool + /// derived from `allowsRowEditing`, which is true for a materialized view, so the "+" was + /// offered over an `ADD CONSTRAINT` PostgreSQL always refuses. (#2726) static func resolve( support: ForeignKeyEditSupport, engineName: String, - isTable: Bool, + kindRefusal: String?, canEditSchema: Bool ) -> ForeignKeyEditAvailability { guard canEditSchema else { @@ -65,13 +81,11 @@ enum ForeignKeyEditPolicy { reason: String(format: String(localized: "%@ cannot edit a table's structure."), engineName) ) } - /// A view has no constraints of its own, and both mechanisms emit table DDL. The rebuild one - /// looks the table up by `sqlite_master.type = 'table'`, so a view would end in an error - /// rather than an explanation. - guard isTable else { - return .unavailable( - reason: String(localized: "A view has no foreign keys. Edit the tables its query reads.") - ) + /// Both mechanisms emit table DDL. The rebuild one looks the table up by + /// `sqlite_master.type = 'table'`, so anything else would end in an error rather than an + /// explanation. + if let kindRefusal { + return .unavailable(reason: kindRefusal) } switch support { case .unsupported: @@ -97,4 +111,9 @@ enum ForeignKeyEditPolicy { struct SchemaEditingSupport: Sendable, Equatable { var columnReorder: ColumnReorderSupport = .unsupported var foreignKeyEdit: ForeignKeyEditSupport = .unsupported + + /// Which structure edits each kind of object accepts. Defaults to tables only, so an engine + /// nobody has curated never offers a view, materialized view or foreign table an edit its server + /// would refuse. + var structureEdits: StructureObjectEditMatrix = .tablesOnly } diff --git a/TablePro/Models/UI/DataGridConfiguration.swift b/TablePro/Models/UI/DataGridConfiguration.swift index d11ed5b666..965a571247 100644 --- a/TablePro/Models/UI/DataGridConfiguration.swift +++ b/TablePro/Models/UI/DataGridConfiguration.swift @@ -21,6 +21,13 @@ struct DataGridConfiguration: Equatable { var showRowNumbers: Bool = true var hiddenColumns: Set = [] + /// Headings whose cells this grid must not let the user change, even though the rest of the grid + /// is editable. The Structure tab sets it per object kind: PostgreSQL takes a view's + /// `RENAME COLUMN` and `SET DEFAULT` and refuses its `SET NOT NULL` and `SET DATA TYPE`, so Name + /// and Default stay open while Nullable and Type lock. Name-keyed because that is the handle + /// `isColumnWritable` already works in. (#2726) + var lockedColumns: Set = [] + /// This grid shows rows of a result, so the Data Grid sort preferences apply to it. /// /// `tabType` cannot answer this: the Structure grid runs inside a `.table` tab and lists columns, diff --git a/TablePro/Views/Main/Child/MainEditorContentView.swift b/TablePro/Views/Main/Child/MainEditorContentView.swift index 50f2d85b25..c8a529da63 100644 --- a/TablePro/Views/Main/Child/MainEditorContentView.swift +++ b/TablePro/Views/Main/Child/MainEditorContentView.swift @@ -665,7 +665,6 @@ struct MainEditorContentView: View { connection: connection, databaseName: scope?.database ?? "", schemaName: scope?.schema, - isViewObject: tab.tableContext.isView, toolbarState: coordinator.toolbarState, coordinator: coordinator, selectionState: selectionState, @@ -679,7 +678,8 @@ struct MainEditorContentView: View { connection: connection, databaseName: scope?.database ?? "", schemaName: scope?.schema, - tableName: tableName + tableName: tableName, + objectKind: tab.tableContext.resolvedObjectKind() ) } } diff --git a/TablePro/Views/Main/Extensions/MainContentCoordinator+Navigation.swift b/TablePro/Views/Main/Extensions/MainContentCoordinator+Navigation.swift index 34ab2f9f3b..6be29f998e 100644 --- a/TablePro/Views/Main/Extensions/MainContentCoordinator+Navigation.swift +++ b/TablePro/Views/Main/Extensions/MainContentCoordinator+Navigation.swift @@ -34,6 +34,7 @@ extension MainContentCoordinator { schema: schema ?? table.schema, showStructure: showStructure, isView: !table.type.allowsRowEditing, + objectType: table.type, forceNonPreview: forceNonPreview, activateGridFocus: activateGridFocus, forceNewTab: forceNewTab @@ -46,6 +47,7 @@ extension MainContentCoordinator { schema: String? = nil, showStructure: Bool = false, isView: Bool = false, + objectType: TableInfo.TableType? = nil, forceNonPreview: Bool = false, activateGridFocus: Bool = false, forceNewTab: Bool = false @@ -97,6 +99,7 @@ extension MainContentCoordinator { currentDatabase: currentDatabase, resolvedSchema: resolvedSchema, isView: isView, + objectType: objectType, createAsPreview: createAsPreview, isInPlace: navigationModel == .inPlace ) @@ -150,6 +153,7 @@ extension MainContentCoordinator { currentDatabase: currentDatabase, resolvedSchema: resolvedSchema, isView: isView, + objectType: objectType, showStructure: showStructure, createAsPreview: createAsPreview ) @@ -168,6 +172,7 @@ extension MainContentCoordinator { databaseName: currentDatabase, schemaName: resolvedSchema, isView: isView, + objectType: objectType, showStructure: showStructure, isPreview: createAsPreview, forcesNewTab: forceNewTab @@ -233,6 +238,7 @@ extension MainContentCoordinator { currentDatabase: String, resolvedSchema: String?, isView: Bool, + objectType: TableInfo.TableType?, createAsPreview: Bool, isInPlace: Bool ) -> Bool { @@ -243,6 +249,7 @@ extension MainContentCoordinator { databaseName: currentDatabase, schemaName: resolvedSchema, isView: isView, + objectType: objectType, isPreview: createAsPreview ) } catch { @@ -260,6 +267,7 @@ extension MainContentCoordinator { TableLoadTracer.shared.stage(.addFirstTab, token: token) tabManager.mutate(at: tabIndex) { tab in tab.tableContext.isView = isView + tab.tableContext.objectType = objectType tab.tableContext.isEditable = !isView tab.tableContext.schemaName = resolvedSchema tab.pagination.reset() @@ -281,6 +289,7 @@ extension MainContentCoordinator { currentDatabase: String, resolvedSchema: String?, isView: Bool, + objectType: TableInfo.TableType?, showStructure: Bool, createAsPreview: Bool ) -> Bool { @@ -316,6 +325,7 @@ extension MainContentCoordinator { tableName: tableName, databaseType: connection.type, isView: isView, + objectType: objectType, databaseName: currentDatabase, schemaName: resolvedSchema, isPreview: createAsPreview diff --git a/TablePro/Views/Main/Extensions/MainContentCoordinator+NavigationHistory.swift b/TablePro/Views/Main/Extensions/MainContentCoordinator+NavigationHistory.swift index 6914e24b3c..aee86b9c0f 100644 --- a/TablePro/Views/Main/Extensions/MainContentCoordinator+NavigationHistory.swift +++ b/TablePro/Views/Main/Extensions/MainContentCoordinator+NavigationHistory.swift @@ -66,6 +66,7 @@ extension MainContentCoordinator { databaseName: tab.tableContext.databaseName, schemaName: tab.tableContext.schemaName, isView: tab.tableContext.isView, + objectType: tab.tableContext.objectType, resultsViewMode: tab.display.resultsViewMode, filterState: tab.filterState, sortColumns: tab.sortState.persistedColumns, @@ -170,6 +171,7 @@ extension MainContentCoordinator { tableName: entry.tableName, databaseType: connection.type, isView: entry.isView, + objectType: entry.objectType, databaseName: entry.databaseName, schemaName: entry.schemaName ) diff --git a/TablePro/Views/Main/Extensions/MainContentCoordinator+TableRowsMutation.swift b/TablePro/Views/Main/Extensions/MainContentCoordinator+TableRowsMutation.swift index e154f1e9c2..96b2b8bc80 100644 --- a/TablePro/Views/Main/Extensions/MainContentCoordinator+TableRowsMutation.swift +++ b/TablePro/Views/Main/Extensions/MainContentCoordinator+TableRowsMutation.swift @@ -113,6 +113,7 @@ extension MainContentCoordinator { tab.tableContext.primaryKeyColumns = origin?.primaryKeyColumns ?? [] tab.tableContext.isEditable = origin?.isEditable ?? false tab.tableContext.isView = origin?.isView ?? false + tab.tableContext.objectType = origin?.objectType tab.schemaVersion += 1 } let tab = tabManager.tabs[tabIdx] diff --git a/TablePro/Views/Results/DataGridCoordinator.swift b/TablePro/Views/Results/DataGridCoordinator.swift index d367280bbb..7b592681e1 100644 --- a/TablePro/Views/Results/DataGridCoordinator.swift +++ b/TablePro/Views/Results/DataGridCoordinator.swift @@ -38,6 +38,9 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData var changeManager: AnyChangeManager var isEditable: Bool var editRefusalMessage: String? + /// Headings this grid must refuse an edit for while the rest of it stays editable. See + /// `DataGridConfiguration.lockedColumns`. + var lockedColumns: Set = [] var valueFilteredIDs: [RowID]? { didSet { bumpDisplayRevision() } } /// Ticks whenever the displayed row order or the value filter changes. /// @@ -245,6 +248,7 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData } self.isEditable = isEditable editRefusalMessage = configuration.editRefusalMessage + lockedColumns = configuration.lockedColumns tableView?.toolTip = isEditable ? nil : configuration.editRefusalMessage dropdownColumns = configuration.dropdownColumns typePickerColumns = configuration.typePickerColumns diff --git a/TablePro/Views/Results/Extensions/DataGridView+Editing.swift b/TablePro/Views/Results/Extensions/DataGridView+Editing.swift index 38c85fe920..5c59aafb8d 100644 --- a/TablePro/Views/Results/Extensions/DataGridView+Editing.swift +++ b/TablePro/Views/Results/Extensions/DataGridView+Editing.swift @@ -47,6 +47,7 @@ extension TableViewCoordinator { /// statement can carry, so Set NULL on a MongoDB `_id`, a generated column or a /// `GENERATED ALWAYS AS IDENTITY` column marked the row edited and then wrote nothing. func isColumnWritable(_ columnName: String) -> Bool { + guard !lockedColumns.contains(columnName) else { return false } guard !changeManager.generatedColumns.contains(columnName) else { return false } let immutable = databaseType.map { PluginManager.shared.immutableColumns(for: $0) } ?? [] return !immutable.contains(columnName) @@ -66,11 +67,26 @@ extension TableViewCoordinator { /// A grid that will not take a keystroke and says nothing reads as broken. When the refusal has /// a reason the pointer already carries it as the grid's tooltip, and the beep is AppKit's own /// way of saying the attempt was heard and declined. - func refuseEditIfExplained() { + /// + /// A locked column beeps too. The rest of its grid is editable, so there is no grid-wide tooltip + /// to carry the reason, and a cell that swallowed the keystroke in silence would read as a dead + /// grid rather than a refusal. The explanation is on the dimmed pair under the list. (#2726) + func refuseEditIfExplained(columnIndex: Int? = nil) { + if let columnIndex, isLockedColumn(at: columnIndex) { + NSSound.beep() + return + } guard !isEditable, editRefusalMessage != nil else { return } NSSound.beep() } + private func isLockedColumn(at columnIndex: Int) -> Bool { + guard !lockedColumns.isEmpty else { return false } + let columns = tableRowsProvider().columns + guard columnIndex >= 0, columnIndex < columns.count else { return false } + return lockedColumns.contains(columns[columnIndex]) + } + func beginCellEdit(row: Int, tableColumnIndex: Int) { guard let tableView else { return } guard tableColumnIndex >= 0, tableColumnIndex < tableView.numberOfColumns else { return } @@ -78,7 +94,7 @@ extension TableViewCoordinator { guard column.identifier != ColumnIdentitySchema.rowNumberIdentifier else { return } guard let columnIndex = dataColumnIndex(from: column.identifier) else { return } guard case .editable(let value) = editEligibility(row: row, columnIndex: columnIndex) else { - refuseEditIfExplained() + refuseEditIfExplained(columnIndex: columnIndex) return } showOverlayEditor( diff --git a/TablePro/Views/Structure/StructureEditGate.swift b/TablePro/Views/Structure/StructureEditGate.swift new file mode 100644 index 0000000000..daea3e356a --- /dev/null +++ b/TablePro/Views/Structure/StructureEditGate.swift @@ -0,0 +1,112 @@ +// +// StructureEditGate.swift +// TablePro +// +// What the Structure tab may offer for one connection and one object. +// + +import Foundation +import TableProPluginKit + +/// The Structure tab's single answer to "may this edit be offered on this object". +/// +/// One value rather than a flag per call site, because the footer pair, the grid's own keyboard and +/// context-menu paths, the reorder drag and the per-column lock all have to agree. They did not: the +/// footer read the engine's capability flags, the grid delegate read them again in its own guards, +/// and only the foreign key and reorder policies asked about the object at all, as +/// `isTable: !isViewObject`, which cannot say that a materialized view takes `CREATE INDEX` and +/// refuses `SET DEFAULT`. (#2726) +@MainActor +struct StructureEditGate { + let databaseType: DatabaseType + let objectKind: TableInfo.TableType + + private var matrix: StructureObjectEditMatrix { + PluginManager.shared.structureEditMatrix(for: databaseType) + } + + private var canEditSchema: Bool { databaseType.supportsSchemaEditing } + + func allows(_ operation: StructureEditOperation) -> Bool { + resolve(operation).isAvailable + } + + func resolve(_ operation: StructureEditOperation) -> StructureEditAvailability { + /// The foreign key arm is answered by `ForeignKeyEditPolicy`, which also owns the `.alter` + /// versus `.rebuild` distinction the save itself reads, and which words an engine's refusal + /// as "cannot add or remove a table's foreign keys" rather than the sentence every other + /// constraint shares. Routing it through here rather than beside here is what keeps every + /// call site asking one object. + if operation == .addForeignKey || operation == .dropForeignKey { + return foreignKeyAvailability.structureEditAvailability + } + return StructureEditEligibility.resolve( + operation, + on: objectKind, + matrix: matrix, + engineAllows: engineSupports(operation), + engineName: databaseType.displayName, + canEditSchema: canEditSchema + ) + } + + var foreignKeyAvailability: ForeignKeyEditAvailability { + ForeignKeyEditPolicy.resolve( + support: PluginManager.shared.foreignKeyEditSupport(for: databaseType), + engineName: databaseType.displayName, + kindRefusal: kindRefusal(.addForeignKey), + canEditSchema: canEditSchema + ) + } + + /// Why the object's kind refuses the operation, ignoring the engine. Handed to + /// `ForeignKeyEditPolicy` and `ColumnReorderPolicy`, which own the engine half of the same + /// decision and would otherwise have to word a refusal about a kind they cannot see. + func kindRefusal(_ operation: StructureEditOperation) -> String? { + StructureEditEligibility.refusalReason(for: operation, on: objectKind, matrix: matrix) + } + + /// Every field of the Columns grid this object lets the user change. A view keeps Name, Default + /// and Comment editable while Nullable, Type and the rest lock, because that is what PostgreSQL + /// accepts on one. + var editableColumnFields: Set { + guard canEditSchema else { return [] } + return StructureEditEligibility.editableFields(on: objectKind, matrix: matrix) + } + + var allowsAnyEdit: Bool { + canEditSchema && StructureEditEligibility.allowsAnyEdit(on: objectKind, matrix: matrix) + } + + /// Whether the engine has a statement for this operation at all, which is a different question + /// from whether the object's kind accepts it. An engine with no `ADD CONSTRAINT … FOREIGN KEY` + /// refuses it on a plain table too. + /// + /// Exhaustive on purpose. The column attribute changes carry no capability flag of their own and + /// are covered by `supportsSchemaEditing`, so a `default:` arm here would silently swallow a new + /// operation that does need one. + private func engineSupports(_ operation: StructureEditOperation) -> Bool { + switch operation { + case .addColumn: + return databaseType.supportsAddColumn + case .dropColumn: + return databaseType.supportsDropColumn + case .addIndex: + return databaseType.supportsAddIndex + case .dropIndex: + return databaseType.supportsDropIndex + case .addForeignKey, .dropForeignKey: + /// `resolve` answers these through `ForeignKeyEditPolicy` before reaching here. Stated + /// anyway so this switch stays total over the operations, which is what makes a new one + /// fail to compile until somebody decides its engine half. + return PluginManager.shared.foreignKeyEditSupport(for: databaseType).isEditable + case .addCheckConstraint, .dropCheckConstraint: + return databaseType.supportsCheckConstraintEditing + case .reorderColumns: + return PluginManager.shared.columnReorderSupport(for: databaseType) != .unsupported + case .renameColumn, .setNotNull, .dropNotNull, .setDefault, .dropDefault, + .changeColumnType, .redefineColumn, .commentOnColumn: + return true + } + } +} diff --git a/TablePro/Views/Structure/StructureEditingSession.swift b/TablePro/Views/Structure/StructureEditingSession.swift index fb6b307492..c0abfe3aad 100644 --- a/TablePro/Views/Structure/StructureEditingSession.swift +++ b/TablePro/Views/Structure/StructureEditingSession.swift @@ -43,6 +43,10 @@ internal final class StructureEditingSession { internal let schemaName: String? internal let tableName: String + /// What kind of object this session edits, which decides which edits it may offer at all. A tab + /// retargeted to another object gets a new session, so this never has to change under a session. + internal let objectKind: TableInfo.TableType + internal let changeManager = StructureChangeManager() /// Built here, not seeded into the view's `@State`. `State(wrappedValue:)` runs only the first @@ -105,18 +109,21 @@ internal final class StructureEditingSession { connection: DatabaseConnection, databaseName: String, schemaName: String?, - tableName: String + tableName: String, + objectKind: TableInfo.TableType = .table ) { self.identity = identity self.connection = connection self.databaseName = databaseName self.schemaName = schemaName self.tableName = tableName + self.objectKind = objectKind gridDelegate = StructureGridDelegate( structureChangeManager: changeManager, selectedTab: .columns, connection: connection, tableName: tableName, + objectKind: objectKind, coordinator: nil ) gridDelegate.referenceMenus.schemaName = schemaName diff --git a/TablePro/Views/Structure/StructureFooterPolicy.swift b/TablePro/Views/Structure/StructureFooterPolicy.swift new file mode 100644 index 0000000000..3cf115738b --- /dev/null +++ b/TablePro/Views/Structure/StructureFooterPolicy.swift @@ -0,0 +1,90 @@ +// +// StructureFooterPolicy.swift +// TablePro +// +// What the add/remove pair under a structure list offers, and why it is dimmed when it is. +// + +import Foundation +import TableProPluginKit + +/// The single decision behind the "+" and "-" under the Structure tab's list. +/// +/// Pure and SwiftUI-free so the rule is testable, and one function so the label, the enabled state +/// and the tooltip can never disagree. They did: the labels came from one switch, the enabled state +/// from a second that read engine capability flags alone, and the tooltip from a third that returned +/// nil for every tab but Foreign Keys. So a view offered an enabled "Add Column" over an +/// `ALTER TABLE … ADD COLUMN` PostgreSQL always refuses, with nothing to explain it. (#2726) +enum StructureFooterPolicy { + /// Nil for a tab with nothing to add: DDL is text, Parts is read-only, and a trigger is created + /// through its own editor rather than by typing a row. + static func operation(forAdding tab: StructureTab) -> StructureEditOperation? { + switch tab { + case .columns: return .addColumn + case .indexes: return .addIndex + case .foreignKeys: return .addForeignKey + case .checkConstraints: return .addCheckConstraint + case .ddl, .parts, .triggers: return nil + } + } + + static func operation(forRemoving tab: StructureTab) -> StructureEditOperation? { + switch tab { + case .columns: return .dropColumn + case .indexes: return .dropIndex + case .foreignKeys: return .dropForeignKey + case .checkConstraints: return .dropCheckConstraint + case .ddl, .parts, .triggers: return nil + } + } + + static func labels(for tab: StructureTab) -> (add: String, remove: String)? { + switch tab { + case .columns: + return (String(localized: "Add Column"), String(localized: "Remove Column")) + case .indexes: + return (String(localized: "Add Index"), String(localized: "Remove Index")) + case .foreignKeys: + return (String(localized: "Add Foreign Key"), String(localized: "Remove Foreign Key")) + case .checkConstraints: + return (String(localized: "Add Check Constraint"), String(localized: "Remove Check Constraint")) + case .ddl, .parts, .triggers: + return nil + } + } + + /// - Parameter resolve: The full availability of one operation, which the caller supplies because + /// it owns the connection the engine half of the answer comes from. + /// + /// A refusing object kind keeps the pair on screen and dims it with the reason, the way the + /// Foreign Keys tab already did. An engine that cannot edit structure at all hides it instead: + /// there is nothing to explain per object when the whole tab is read-only. + static func resolve( + tab: StructureTab, + canEditSchema: Bool, + hasSelection: Bool, + resolve: (StructureEditOperation) -> StructureEditAvailability + ) -> StructureFooterCapability { + guard canEditSchema, + let labels = labels(for: tab), + let adding = operation(forAdding: tab), + let removing = operation(forRemoving: tab) + else { + return StructureFooterCapability() + } + + let addAvailability = resolve(adding) + let removeAvailability = resolve(removing) + + return StructureFooterCapability( + canAdd: addAvailability.isAvailable, + canRemove: hasSelection && removeAvailability.isAvailable, + addLabel: labels.add, + removeLabel: labels.remove, + /// Never the absence of a selection. The pair dims while nothing is selected on every + /// tab and on every engine, which needs no sentence; only a refusal the user could not + /// have predicted does. + unavailableReason: addAvailability.unavailableReason ?? removeAvailability.unavailableReason + ) + } +} diff --git a/TablePro/Views/Structure/StructureGridDelegate.swift b/TablePro/Views/Structure/StructureGridDelegate.swift index 9edc44ca7e..7d2d7b1b4c 100644 --- a/TablePro/Views/Structure/StructureGridDelegate.swift +++ b/TablePro/Views/Structure/StructureGridDelegate.swift @@ -14,13 +14,31 @@ final class StructureGridDelegate: DataGridViewDelegate { var selectedTab: StructureTab let connection: DatabaseConnection - /// Whether this engine can add and remove foreign keys, which is not the same question as - /// whether it has them. Every path that stages a foreign key change reads this, not just the - /// button under the list: a context-menu Delete that stages one on an engine with no way to - /// apply it only fails later, at Save. + /// What kind of object this grid is editing. The footer pair is not the only way in: the Edit + /// menu's Add Row, the grid's own shortcut, the row context menu and the empty-space menu all + /// reach the methods below directly, so each of them asks the same gate rather than trusting a + /// button to have been dimmed. (#2726) + let objectKind: TableInfo.TableType + + /// The single answer to "may this edit be offered", shared with the view that presents this grid. + var editGate: StructureEditGate { + StructureEditGate(databaseType: connection.type, objectKind: objectKind) + } + + /// Whether this engine can add and remove foreign keys on this object, which is not the same + /// question as whether the engine has them. `supportsForeignKeys` answers the second, and reading + /// it as the first is what offered an enabled "+" on SQLite over a driver with no statement + /// behind it. Every path that stages a foreign key change reads this, not just the button under + /// the list: a context-menu Delete that stages one with no way to apply it only fails at Save. var canEditForeignKeys: Bool { - PluginManager.shared.foreignKeyEditSupport(for: connection.type).isEditable - && connection.type.supportsSchemaEditing + editGate.allows(.addForeignKey) + } + + /// Whether a new row may be staged on the list the user is looking at. Paste and Duplicate stage + /// the same add the "+" does, so they answer to the same gate rather than to the pasteboard alone. + var canStageAddForSelectedTab: Bool { + guard let adding = StructureFooterPolicy.operation(forAdding: selectedTab) else { return false } + return editGate.allows(adding) } let tableName: String /// The lists behind the Foreign Keys grid's reference cells, shared with the Create Table tab. @@ -58,12 +76,14 @@ final class StructureGridDelegate: DataGridViewDelegate { selectedTab: StructureTab, connection: DatabaseConnection, tableName: String, + objectKind: TableInfo.TableType = .table, coordinator: MainContentCoordinator? ) { self.structureChangeManager = structureChangeManager self.selectedTab = selectedTab self.connection = connection self.tableName = tableName + self.objectKind = objectKind self.coordinator = coordinator self.referenceMenus = ForeignKeyReferenceMenus(connectionId: connection.id) } @@ -137,7 +157,7 @@ final class StructureGridDelegate: DataGridViewDelegate { } case .checkConstraints: - guard connection.type.supportsCheckConstraintEditing, + guard editGate.allows(.addCheckConstraint), sourceRowIndex < structureChangeManager.workingCheckConstraints.count else { return } var constraint = structureChangeManager.workingCheckConstraints[sourceRowIndex] StructureEditingSupport.updateCheckConstraint(&constraint, at: column, with: newValue ?? "") @@ -177,7 +197,7 @@ final class StructureGridDelegate: DataGridViewDelegate { switch selectedTab { case .columns: - guard connection.type.supportsDropColumn else { return } + guard editGate.allows(.dropColumn) else { return } structureChangeManager.performAsOneUndoStep { for row in translated.sorted(by: >) { guard row < structureChangeManager.workingColumns.count else { continue } @@ -186,7 +206,7 @@ final class StructureGridDelegate: DataGridViewDelegate { } } case .indexes: - guard connection.type.supportsDropIndex else { return } + guard editGate.allows(.dropIndex) else { return } structureChangeManager.performAsOneUndoStep { for row in translated.sorted(by: >) { guard row < structureChangeManager.workingIndexes.count else { continue } @@ -204,7 +224,7 @@ final class StructureGridDelegate: DataGridViewDelegate { } } case .checkConstraints: - guard connection.type.supportsCheckConstraintEditing else { return } + guard editGate.allows(.addCheckConstraint) else { return } structureChangeManager.performAsOneUndoStep { for row in translated.sorted(by: >) { guard row < structureChangeManager.workingCheckConstraints.count else { continue } @@ -315,6 +335,7 @@ final class StructureGridDelegate: DataGridViewDelegate { } func dataGridPasteRows() { + guard canStageAddForSelectedTab else { return } guard let data = NSPasteboard.general.data(forType: TableStructureView.structurePasteboardType), let jsonString = String(data: data, encoding: .utf8) else { return @@ -348,10 +369,9 @@ final class StructureGridDelegate: DataGridViewDelegate { } case .checkConstraints: - guard connection.type.supportsCheckConstraintEditing, - let constraints = try? decoder.decode( - [EditableCheckConstraintDefinition].self, from: Data(jsonString.utf8) - ) else { + guard let constraints = try? decoder.decode( + [EditableCheckConstraintDefinition].self, from: Data(jsonString.utf8) + ) else { return } for item in constraints { @@ -380,18 +400,15 @@ final class StructureGridDelegate: DataGridViewDelegate { } func dataGridAddRow() { + guard canStageAddForSelectedTab else { return } switch selectedTab { case .columns: - guard connection.type.supportsAddColumn else { return } structureChangeManager.addNewColumn() case .indexes: - guard connection.type.supportsAddIndex else { return } structureChangeManager.addNewIndex() case .foreignKeys: - guard canEditForeignKeys else { return } structureChangeManager.addNewForeignKey() case .checkConstraints: - guard connection.type.supportsCheckConstraintEditing else { return } structureChangeManager.addNewCheckConstraint() case .ddl, .parts, .triggers: break @@ -578,16 +595,16 @@ final class StructureGridDelegate: DataGridViewDelegate { let label: String switch selectedTab { case .columns: - guard connection.type.supportsAddColumn else { return nil } + guard editGate.allows(.addColumn) else { return nil } label = String(localized: "Add Column") case .indexes: - guard connection.type.supportsAddIndex else { return nil } + guard editGate.allows(.addIndex) else { return nil } label = String(localized: "Add Index") case .foreignKeys: guard canEditForeignKeys else { return nil } label = String(localized: "Add Foreign Key") case .checkConstraints: - guard connection.type.supportsCheckConstraintEditing else { return nil } + guard editGate.allows(.addCheckConstraint) else { return nil } label = String(localized: "Add Check Constraint") case .ddl, .parts, .triggers: return nil @@ -711,6 +728,7 @@ final class StructureGridDelegate: DataGridViewDelegate { } private func handleDuplicateItems(_ indices: Set) { + guard canStageAddForSelectedTab else { return } for row in indices.sorted() { switch selectedTab { case .columns: @@ -730,8 +748,7 @@ final class StructureGridDelegate: DataGridViewDelegate { let copy = structureChangeManager.workingForeignKeys[row] structureChangeManager.addForeignKey(copy.withNewIdentity()) case .checkConstraints: - guard connection.type.supportsCheckConstraintEditing, - row < structureChangeManager.workingCheckConstraints.count else { continue } + guard row < structureChangeManager.workingCheckConstraints.count else { continue } let copy = structureChangeManager.workingCheckConstraints[row] structureChangeManager.addCheckConstraint(copy.withNewIdentity()) case .ddl, .parts, .triggers: diff --git a/TablePro/Views/Structure/TableStructureView+ColumnReorder.swift b/TablePro/Views/Structure/TableStructureView+ColumnReorder.swift index 6ca7a46a5c..e8b23fade7 100644 --- a/TablePro/Views/Structure/TableStructureView+ColumnReorder.swift +++ b/TablePro/Views/Structure/TableStructureView+ColumnReorder.swift @@ -20,7 +20,7 @@ extension TableStructureView { support: PluginManager.shared.columnReorderSupport(for: connection.type), engineName: connection.type.displayName, isColumnsTab: selectedTab == .columns, - isTable: !isViewObject, + kindRefusal: editGate.kindRefusal(.reorderColumns), canEditSchema: connection.type.supportsSchemaEditing, hasStagedChanges: structureChangeManager.hasChanges, isRearranged: !searchText.isEmpty || structureSortDescriptor != nil diff --git a/TablePro/Views/Structure/TableStructureView+EditGate.swift b/TablePro/Views/Structure/TableStructureView+EditGate.swift new file mode 100644 index 0000000000..773e5947ef --- /dev/null +++ b/TablePro/Views/Structure/TableStructureView+EditGate.swift @@ -0,0 +1,67 @@ +// +// TableStructureView+EditGate.swift +// TablePro +// +// Which structure edits this tab offers, for the object it is open on. +// + +import Foundation +import TableProPluginKit + +extension TableStructureView { + /// Every "may this edit be offered" question the tab asks, answered from one place. The footer + /// pair, the grid's per-column lock, the reorder drag and the grid delegate's own keyboard and + /// context-menu paths all read this, so none of them can offer an edit another withholds. + var editGate: StructureEditGate { + StructureEditGate(databaseType: connection.type, objectKind: objectKind) + } + + /// Whether this engine can add and remove foreign keys, which is not the same question as + /// whether it has them. `supportsForeignKeys` answers the second, and reading it as the first + /// is what offered an enabled "+" on SQLite over a driver with no statement behind it. + var foreignKeyEditAvailability: ForeignKeyEditAvailability { + ForeignKeyEditPolicy.resolve( + support: PluginManager.shared.foreignKeyEditSupport(for: connection.type), + engineName: connection.type.displayName, + kindRefusal: editGate.kindRefusal(.addForeignKey), + canEditSchema: connection.type.supportsSchemaEditing + ) + } + + /// Published to the tab's own session, which the bottom bar reads. Nothing is cleared on + /// disappear: the session outlives the view by design, and the bar only reads this while the + /// tab is showing its structure. + func publishFooterCapability() { + let gate = editGate + session.footer = StructureFooterPolicy.resolve( + tab: selectedTab, + canEditSchema: connection.type.supportsSchemaEditing, + hasSelection: !selectedRows.isEmpty, + resolve: { gate.resolve($0) } + ) + } + + /// The Columns grid's headings for the fields this object's kind will not let the user change. + /// + /// Name-keyed because that is the only handle the grid has: `isColumnWritable` is asked about a + /// column's heading, and the Columns grid's headings are exactly + /// `orderedColumnFields.map(\.displayName)`. Empty on every tab but Columns, whose rows are the + /// only ones that describe a column. + var lockedStructureColumns: Set { + guard selectedTab == .columns else { return [] } + let editable = editGate.editableColumnFields + let locked = StructureColumnField.allCases.filter { !editable.contains($0) } + /// `displayName` is a `String(localized:)` lookup per field, and this is read on every body + /// evaluation. A table locks nothing, which is the overwhelmingly common case, so it never + /// pays for twelve of them. + guard !locked.isEmpty else { return [] } + return Set(locked.map(\.displayName)) + } + + /// Why the Columns grid refuses every keystroke, when it does. A grid that will not take an edit + /// and says nothing reads as broken, so the pointer carries this as the grid's tooltip. + var structureEditRefusal: String? { + guard !editGate.allowsAnyEdit else { return nil } + return editGate.resolve(.renameColumn).unavailableReason + } +} diff --git a/TablePro/Views/Structure/TableStructureView.swift b/TablePro/Views/Structure/TableStructureView.swift index 5e290f0e43..a768c3365e 100644 --- a/TablePro/Views/Structure/TableStructureView.swift +++ b/TablePro/Views/Structure/TableStructureView.swift @@ -30,10 +30,6 @@ struct TableStructureView: View { let databaseName: String let schemaName: String? - /// Whether the Structure tab is open on a view rather than a table. Every reorder mechanism - /// emits table DDL, so a view is withheld rather than allowed to fail at the statement. - var isViewObject: Bool = false - let toolbarState: ConnectionToolbarState let coordinator: MainContentCoordinator? let selectionState: GridSelectionState @@ -53,6 +49,16 @@ struct TableStructureView: View { /// view because the view is destroyed whenever the tab is deselected or switched to Data. let session: StructureEditingSession + /// What kind of object the tab is open on, which decides every edit it may offer. + /// + /// The real `TableInfo.TableType`, read from the session rather than passed in beside it, so the + /// grid delegate the session owns and the footer this view publishes can never disagree about + /// what they are looking at. It used to be an `isView` Bool derived from `allowsRowEditing`, + /// which is true for a materialized view, so a matview reached here as a table and was offered + /// `ADD COLUMN`, `SET NOT NULL`, type changes and constraint edits the server always refuses. + /// (#2726) + var objectKind: TableInfo.TableType { session.objectKind } + /// Where the user was. Two tabs on one table are two editors, and a trip through the Data view /// must not lose the sub-tab, filter or sort either, so all of it lives on the session. var selectedTab: StructureTab { @@ -153,7 +159,6 @@ struct TableStructureView: View { connection: DatabaseConnection, databaseName: String, schemaName: String?, - isViewObject: Bool = false, toolbarState: ConnectionToolbarState, coordinator: MainContentCoordinator?, selectionState: GridSelectionState, @@ -163,7 +168,6 @@ struct TableStructureView: View { self.connection = connection self.databaseName = databaseName self.schemaName = schemaName - self.isViewObject = isViewObject self.toolbarState = toolbarState self.coordinator = coordinator self.selectionState = selectionState @@ -326,80 +330,6 @@ struct TableStructureView: View { .padding() } - // MARK: - Footer capability - - /// Published to the tab's own session, which the bottom bar reads. Nothing is cleared on - /// disappear: the session outlives the view by design, and the bar only reads this while the - /// tab is showing its structure. - private func publishFooterCapability() { - guard connection.type.supportsSchemaEditing, let labels = footerLabels(for: selectedTab) else { - session.footer = StructureFooterCapability() - return - } - session.footer = StructureFooterCapability( - canAdd: canAdd(for: selectedTab), - canRemove: canRemove(for: selectedTab), - addLabel: labels.add, - removeLabel: labels.remove, - unavailableReason: unavailableReason(for: selectedTab) - ) - } - - /// Whether this engine can add and remove foreign keys, which is not the same question as - /// whether it has them. `supportsForeignKeys` answers the second, and reading it as the first - /// is what offered an enabled "+" on SQLite over a driver with no statement behind it. - var foreignKeyEditAvailability: ForeignKeyEditAvailability { - ForeignKeyEditPolicy.resolve( - support: PluginManager.shared.foreignKeyEditSupport(for: connection.type), - engineName: connection.type.displayName, - isTable: !isViewObject, - canEditSchema: connection.type.supportsSchemaEditing - ) - } - - private func canAdd(for tab: StructureTab) -> Bool { - switch tab { - case .columns: return connection.type.supportsAddColumn - case .indexes: return connection.type.supportsAddIndex - case .foreignKeys: return foreignKeyEditAvailability.isAvailable - case .checkConstraints: return connection.type.supportsCheckConstraintEditing - case .ddl, .parts, .triggers: return false - } - } - - /// Why the pair under the list is dimmed, for its tooltip. Nil when it is not, and nil for a - /// tab whose absence needs no explaining: DDL and Parts have nothing to add. - private func unavailableReason(for tab: StructureTab) -> String? { - guard tab == .foreignKeys else { return nil } - return foreignKeyEditAvailability.unavailableReason - } - - private func canRemove(for tab: StructureTab) -> Bool { - guard !selectedRows.isEmpty else { return false } - switch tab { - case .columns: return connection.type.supportsDropColumn - case .indexes: return connection.type.supportsDropIndex - case .foreignKeys: return foreignKeyEditAvailability.isAvailable - case .checkConstraints: return connection.type.supportsCheckConstraintEditing - case .ddl, .parts, .triggers: return false - } - } - - private func footerLabels(for tab: StructureTab) -> (add: String, remove: String)? { - switch tab { - case .columns: - return (String(localized: "Add Column"), String(localized: "Remove Column")) - case .indexes: - return (String(localized: "Add Index"), String(localized: "Remove Index")) - case .foreignKeys: - return (String(localized: "Add Foreign Key"), String(localized: "Remove Foreign Key")) - case .checkConstraints: - return (String(localized: "Add Check Constraint"), String(localized: "Remove Check Constraint")) - case .ddl, .parts, .triggers: - return nil - } - } - // MARK: - Tab Label with Count Badge private func tabLabel(for tab: StructureTab) -> String { @@ -472,25 +402,27 @@ struct TableStructureView: View { } } + /// Only offered where the add behind it can actually run. An engine that lists an object but + /// cannot edit it shows the grid, so its real rows stay visible instead of being replaced by an + /// empty state whose only affordance is disabled, and a view whose kind refuses the add never + /// gets the empty state's button at all. private var shouldShowIndexesEmptyState: Bool { tabData.hasData(.indexes) && structureChangeManager.workingIndexes.isEmpty - && connection.type.supportsAddIndex + && editGate.allows(.addIndex) } private var shouldShowForeignKeysEmptyState: Bool { tabData.hasData(.foreignKeys) && structureChangeManager.workingForeignKeys.isEmpty && connection.type.supportsForeignKeys + && editGate.allows(.addForeignKey) } - /// Only offered where the engine can actually add one. An engine that lists constraints but - /// cannot edit them shows the grid, so a table's real constraints stay visible instead of being - /// replaced by an empty state whose only affordance is disabled. private var shouldShowCheckConstraintsEmptyState: Bool { tabData.hasData(.checkConstraints) && structureChangeManager.workingCheckConstraints.isEmpty - && connection.type.supportsCheckConstraintEditing + && editGate.allows(.addCheckConstraint) } // MARK: - Structure Grid (DataGridView) @@ -536,9 +468,12 @@ struct TableStructureView: View { private var structureGrid: some View { @Bindable var session = session let provider = makeCurrentProvider() - let canEdit = connection.type.supportsSchemaEditing + let canEdit = editGate.allowsAnyEdit let customOptions = provider.customDropdownOptions let allDropdownColumns = provider.dropdownColumns + /// Resolved once. It reads the engine's curated capabilities and the object's own kind, and + /// this is a body property, so asking twice for the pair of values below doubled that work. + let reorder = columnReorderAvailability // Build the row snapshot fresh on every call rather than capturing it // once at body-evaluation time. After a cell edit / undo / redo the @@ -562,12 +497,14 @@ struct TableStructureView: View { tableName: tableName, databaseName: databaseName, schemaName: schemaName, - tabType: .table + tabType: .table, + lockedColumns: lockedStructureColumns, + editRefusalMessage: structureEditRefusal ), delegate: gridDelegate, rowReorder: DataGridRowReorder( - isEnabled: columnReorderAvailability.isAvailable, - unavailableReason: columnReorderAvailability.unavailableReason + isEnabled: reorder.isAvailable, + unavailableReason: reorder.unavailableReason ), selectedRowIndices: $selectedRows, sortState: $session.sortState, diff --git a/TableProTests/Core/Plugins/StructureEditMatrixCurationTests.swift b/TableProTests/Core/Plugins/StructureEditMatrixCurationTests.swift new file mode 100644 index 0000000000..994b62658c --- /dev/null +++ b/TableProTests/Core/Plugins/StructureEditMatrixCurationTests.swift @@ -0,0 +1,66 @@ +// +// StructureEditMatrixCurationTests.swift +// TableProTests +// + +import Foundation +import Testing +@testable import TablePro + +/// The matrix is a curated per-engine capability with no `DriverPlugin` static behind it, so it has to +/// survive `buildMetadataSnapshot` the way every other curated capability does. A capability reset to +/// its struct default the moment a plugin loaded is what silently disabled MongoDB's database-scoped +/// authentication (#1970), and the same shape here would put the Structure tab's whole per-kind gate +/// back to tables only for every build with the PostgreSQL plugin installed. (#2726) +@Suite("Structure Edit Matrix Curation") +@MainActor +struct StructureEditMatrixCurationTests { + @Test("PostgreSQL is curated with the measured per-kind matrix") + func postgresIsCurated() { + let matrix = PluginManager.shared.structureEditMatrix(for: .postgresql) + #expect(StructureEditEligibility.allows(.addIndex, on: .materializedView, matrix: matrix)) + #expect(!StructureEditEligibility.allows(.setDefault, on: .materializedView, matrix: matrix)) + #expect(StructureEditEligibility.allows(.setDefault, on: .view, matrix: matrix)) + #expect(!StructureEditEligibility.allows(.addColumn, on: .view, matrix: matrix)) + } + + /// Conservative on purpose. An engine nobody has measured must never be offered an edit on + /// anything but a table, so the fallback is `.tablesOnly` rather than another engine's matrix. + @Test("An engine with no curated entry falls back to tables only") + func uncuratedEngineFallsBackToTablesOnly() { + let unknown = DatabaseType(rawValue: "NotARealEngine") + let matrix = PluginManager.shared.structureEditMatrix(for: unknown) + #expect(!StructureEditEligibility.allowsAnyEdit(on: .view, matrix: matrix)) + #expect(!StructureEditEligibility.allowsAnyEdit(on: .materializedView, matrix: matrix)) + #expect(StructureEditEligibility.allows(.addColumn, on: .table, matrix: matrix)) + } + + @Test("Every curated engine still offers a table its edits") + func curatedEnginesKeepTheirTables() { + for type in DatabaseType.allKnownTypes { + let matrix = PluginManager.shared.structureEditMatrix(for: type) + #expect( + StructureEditEligibility.allowsAnyEdit(on: .table, matrix: matrix), + "\(type.rawValue) withholds every edit on a plain table" + ) + } + } + + @Test("The snapshot's copying helpers carry the matrix across") + func copyingHelpersPreserveTheMatrix() throws { + let original = try #require(PluginMetadataRegistry.shared.snapshot(for: .postgresql)) + let expected = original.structureEditing.structureEdits + + let copies: [(String, PluginMetadataSnapshot)] = [ + ("withIconName", original.withIconName("other-icon")), + ("withExplainVariants", original.withExplainVariants([])), + ("withBranding", original.withBranding(from: original)), + ("withIsDownloadable", original.withIsDownloadable(!original.isDownloadable)), + ("withSwitchRouting", original.withSwitchRouting(from: original)) + ] + + for (name, copy) in copies { + #expect(copy.structureEditing.structureEdits == expected, "\(name) reset the per-kind matrix") + } + } +} diff --git a/TableProTests/Models/Database/StructureEditEligibilityTests.swift b/TableProTests/Models/Database/StructureEditEligibilityTests.swift new file mode 100644 index 0000000000..29362ead7f --- /dev/null +++ b/TableProTests/Models/Database/StructureEditEligibilityTests.swift @@ -0,0 +1,262 @@ +// +// StructureEditEligibilityTests.swift +// TableProTests +// + +import Foundation +import TableProPluginKit +import Testing +@testable import TablePro + +/// Every cell of the PostgreSQL matrix below was measured against a live PostgreSQL 17.11 server, +/// one statement per cell, rather than read out of the documentation. The pair that matters most is +/// `SET DEFAULT` and `CREATE INDEX`: a view takes the first and refuses the second, a materialized +/// view does the opposite, and that alone rules out sharing one row between them or collapsing the +/// object's kind to a single read-only Bool. (#2726) +@Suite("Structure Edit Eligibility") +struct StructureEditEligibilityTests { + private func allows( + _ operation: StructureEditOperation, + _ kind: TableInfo.TableType, + _ matrix: StructureObjectEditMatrix + ) -> Bool { + StructureEditEligibility.allows(operation, on: kind, matrix: matrix) + } + + // MARK: - The uncurated default + + @Test("An uncurated engine offers every edit on a table and a partitioned table") + func tablesOnlyAllowsEverythingOnTables() { + for kind in [TableInfo.TableType.table, .partitionedTable] { + for operation in StructureEditOperation.allCases { + #expect(allows(operation, kind, .tablesOnly), "\(kind.rawValue) refused \(operation)") + } + } + } + + @Test("An uncurated engine offers nothing on anything that is not a table") + func tablesOnlyRefusesEveryOtherKind() { + let kinds: [TableInfo.TableType] = [.view, .materializedView, .foreignTable, .systemTable, .externalTable] + for kind in kinds { + #expect(!StructureEditEligibility.allowsAnyEdit(on: kind, matrix: .tablesOnly), "\(kind.rawValue)") + for operation in StructureEditOperation.allCases { + #expect(!allows(operation, kind, .tablesOnly), "\(kind.rawValue) offered \(operation)") + } + } + } + + // MARK: - PostgreSQL, as measured + + @Test("A PostgreSQL view takes exactly the four edits the server accepts") + func postgresViewMatchesTheServer() { + let accepted: Set = [.renameColumn, .setDefault, .dropDefault, .commentOnColumn] + for operation in StructureEditOperation.allCases { + #expect( + allows(operation, .view, .postgreSQL) == accepted.contains(operation), + "view disagreed about \(operation)" + ) + } + } + + @Test("A PostgreSQL materialized view takes an index and refuses a default") + func postgresMaterializedViewMatchesTheServer() { + let accepted: Set = [.renameColumn, .commentOnColumn, .addIndex, .dropIndex] + for operation in StructureEditOperation.allCases { + #expect( + allows(operation, .materializedView, .postgreSQL) == accepted.contains(operation), + "materialized view disagreed about \(operation)" + ) + } + } + + /// The one cell that proves a view and a materialized view cannot share a matrix row. Measured: + /// `ALTER MATERIALIZED VIEW … SET DEFAULT` answers "ALTER action ALTER COLUMN ... SET DEFAULT + /// cannot be performed on relation mv", while the same statement on a view succeeds. + @Test("A view and a materialized view disagree about SET DEFAULT and CREATE INDEX") + func viewAndMaterializedViewDiffer() { + #expect(allows(.setDefault, .view, .postgreSQL)) + #expect(!allows(.setDefault, .materializedView, .postgreSQL)) + #expect(!allows(.addIndex, .view, .postgreSQL)) + #expect(allows(.addIndex, .materializedView, .postgreSQL)) + } + + @Test("A PostgreSQL foreign table takes every column change but no index and no key") + func postgresForeignTableMatchesTheServer() { + let accepted: Set = [ + .addColumn, .dropColumn, .renameColumn, .setNotNull, .dropNotNull, .setDefault, + .dropDefault, .changeColumnType, .addCheckConstraint, .dropCheckConstraint, .commentOnColumn + ] + for operation in StructureEditOperation.allCases { + #expect( + allows(operation, .foreignTable, .postgreSQL) == accepted.contains(operation), + "foreign table disagreed about \(operation)" + ) + } + } + + @Test("A PostgreSQL system table and external table take nothing") + func postgresReadOnlyKindsTakeNothing() { + for kind in [TableInfo.TableType.systemTable, .externalTable] { + #expect(!StructureEditEligibility.allowsAnyEdit(on: kind, matrix: .postgreSQL), "\(kind.rawValue)") + } + } + + @Test("A PostgreSQL table and partitioned table still take every edit") + func postgresTablesTakeEverything() { + for kind in [TableInfo.TableType.table, .partitionedTable] { + for operation in StructureEditOperation.allCases { + #expect(allows(operation, kind, .postgreSQL), "\(kind.rawValue) refused \(operation)") + } + } + } + + // MARK: - Per-field locking + + @Test("A view keeps Name, Default and Comment editable and locks the rest") + func viewEditableFields() { + let fields = StructureEditEligibility.editableFields(on: .view, matrix: .postgreSQL) + #expect(fields == [.name, .defaultValue, .comment]) + } + + @Test("A materialized view keeps only Name and Comment editable") + func materializedViewEditableFields() { + let fields = StructureEditEligibility.editableFields(on: .materializedView, matrix: .postgreSQL) + #expect(fields == [.name, .comment]) + } + + /// Primary Key, Auto Inc, On Update, Charset, Collation and Generated are all expressed by + /// rewriting the column definition, so they travel together behind `redefineColumn` rather than + /// each being gated through a proxy that means something else. + @Test("A foreign table locks the fields that need a column rewrite and opens the rest") + func foreignTableEditableFields() { + let fields = StructureEditEligibility.editableFields(on: .foreignTable, matrix: .postgreSQL) + #expect(fields == [.name, .type, .nullable, .defaultValue, .comment]) + #expect(!fields.contains(.primaryKey)) + #expect(!fields.contains(.autoIncrement)) + } + + @Test("A system table locks every field") + func systemTableLocksEverything() { + #expect(StructureEditEligibility.editableFields(on: .systemTable, matrix: .postgreSQL).isEmpty) + #expect(!StructureEditEligibility.allowsAnyEdit(on: .systemTable, matrix: .postgreSQL)) + } + + @Test("A table opens every field of the Columns grid") + func tableOpensEveryField() { + let fields = StructureEditEligibility.editableFields(on: .table, matrix: .postgreSQL) + #expect(fields == Set(StructureColumnField.allCases)) + } + + // MARK: - Reasons + + @Test("Every refusal carries a sentence, for every kind and every operation") + func everyRefusalExplainsItself() { + for kind in TableInfo.TableType.allCases { + for operation in StructureEditOperation.allCases { + let availability = StructureEditEligibility.resolve( + operation, + on: kind, + matrix: .postgreSQL, + engineAllows: true, + engineName: "PostgreSQL", + canEditSchema: true + ) + guard !availability.isAvailable else { continue } + #expect( + availability.unavailableReason?.isEmpty == false, + "\(kind.rawValue) refused \(operation) with no reason" + ) + } + } + } + + /// Each refusal names the kind the user is looking at, which is the half the old `isTable` Bool + /// could not supply: it made every non-table say "A view ...". + @Test("A refusal names the object's own kind") + func refusalNamesTheKind() { + let matview = StructureEditEligibility.refusalReason( + for: .setDefault, on: .materializedView, matrix: .postgreSQL + ) + #expect(matview?.contains("materialized view") == true) + + let foreign = StructureEditEligibility.refusalReason( + for: .addIndex, on: .foreignTable, matrix: .postgreSQL + ) + #expect(foreign?.contains("foreign table") == true) + } + + @Test("An accepted operation has no reason to give") + func acceptedOperationHasNoReason() { + #expect(StructureEditEligibility.refusalReason(for: .addIndex, on: .materializedView, matrix: .postgreSQL) == nil) + #expect(StructureEditEligibility.refusalReason(for: .addColumn, on: .table, matrix: .tablesOnly) == nil) + } + + // MARK: - Ordering + + @Test("An engine that cannot edit structure at all says that first, even on a table") + func readOnlyEngineOutranksTheKind() { + let availability = StructureEditEligibility.resolve( + .addColumn, + on: .table, + matrix: .postgreSQL, + engineAllows: true, + engineName: "Engine", + canEditSchema: false + ) + #expect(!availability.isAvailable) + #expect(availability.unavailableReason?.contains("Engine") == true) + } + + /// The kind allowing an edit is necessary, not sufficient. An engine with no `CREATE INDEX` + /// refuses it on a plain table too, and that refusal has to survive the new gate. + @Test("An engine flag still vetoes an operation the kind allows") + func engineFlagStillVetoes() { + let availability = StructureEditEligibility.resolve( + .addIndex, + on: .table, + matrix: .postgreSQL, + engineAllows: false, + engineName: "Engine", + canEditSchema: true + ) + #expect(!availability.isAvailable) + #expect(availability.unavailableReason?.contains("Engine") == true) + #expect(availability.unavailableReason?.contains("indexes") == true) + } + + /// An engine refusal worded once would put "cannot edit a table's structure" under a dimmed + /// **Add Index**, which tells the reader nothing they could act on. + @Test("An engine refusal names what it cannot do, not just that it cannot") + func engineRefusalNamesTheSubject() { + let subjects: [(StructureEditOperation, String)] = [ + (.addColumn, "columns"), + (.reorderColumns, "order"), + (.addIndex, "indexes"), + (.addCheckConstraint, "constraints") + ] + for (operation, expected) in subjects { + let availability = StructureEditEligibility.resolve( + operation, + on: .table, + matrix: .postgreSQL, + engineAllows: false, + engineName: "Engine", + canEditSchema: true + ) + #expect(availability.unavailableReason?.contains(expected) == true, "\(operation)") + } + } + + @Test("The kind outranks the engine flag, so the reason names the object rather than the engine") + func kindOutranksTheEngineFlag() { + let availability = StructureEditEligibility.resolve( + .addColumn, + on: .view, + matrix: .postgreSQL, + engineAllows: true, + engineName: "PostgreSQL", + canEditSchema: true + ) + #expect(availability.unavailableReason?.contains("view") == true) + } +} diff --git a/TableProTests/Models/Query/TabObjectKindTests.swift b/TableProTests/Models/Query/TabObjectKindTests.swift new file mode 100644 index 0000000000..e00329ec20 --- /dev/null +++ b/TableProTests/Models/Query/TabObjectKindTests.swift @@ -0,0 +1,159 @@ +// +// TabObjectKindTests.swift +// TableProTests +// + +import Foundation +import TableProPluginKit +import Testing +@testable import TablePro + +/// A tab used to carry one `isView` Bool, derived from `allowsRowEditing`, which is deliberately true +/// for a materialized view because a matview does hold rows. So a matview reached the Structure tab as +/// a table and was offered column, index and constraint edits PostgreSQL always refuses. The kind now +/// travels beside the Bool rather than replacing it: they answer different questions. (#2726) +@Suite("Tab Object Kind") +@MainActor +struct TabObjectKindTests { + private func tableTab() -> QueryTab { + QueryTab(id: UUID(), title: "mv_sales", query: "SELECT 1", tabType: .table, tableName: "mv_sales") + } + + @Test("A materialized view keeps its kind and leaves row editing alone") + func materializedViewKeepsItsKind() throws { + let manager = QueryTabManager() + try manager.addTableTab( + tableName: "mv_sales", + databaseType: .postgresql, + databaseName: "shop", + isView: false, + objectType: .materializedView + ) + + let tab = try #require(manager.selectedTab) + #expect(tab.tableContext.objectType == .materializedView) + #expect(tab.tableContext.isView == false) + #expect(tab.tableContext.resolvedObjectKind() == .materializedView) + } + + @Test("Retargeting a tab writes the new object's kind over the old one") + func retargetReplacesTheKind() throws { + let manager = QueryTabManager() + try manager.addTableTab( + tableName: "orders", databaseType: .postgresql, databaseName: "shop", objectType: .table + ) + try manager.replaceTabContent( + tableName: "v_orders", + databaseType: .postgresql, + isView: true, + objectType: .view, + databaseName: "shop" + ) + + let tab = try #require(manager.selectedTab) + #expect(tab.tableContext.objectType == .view) + #expect(tab.tableContext.resolvedObjectKind() == .view) + } + + // MARK: - Persistence + + @Test("The kind round-trips through the persisted tab") + func kindRoundTrips() { + var tab = tableTab() + tab.tableContext.objectType = .materializedView + + let persisted = tab.toPersistedTab() + #expect(persisted.objectTypeRawValue == "MATERIALIZED VIEW") + #expect(QueryTab(from: persisted, defaultPageSize: 1_000).tableContext.objectType == .materializedView) + } + + /// A tab saved before this shipped has no key at all. It must still decode, and it must fall back + /// to what the Bool beside it can still say, because the alternative is a thrown error that takes + /// every tab in the aggregate with it. + /// + /// The JSON is built by dropping the key from a real encode rather than typed out by hand, so the + /// test cannot pass or fail on a spelling the encoder does not use: `TabType` has no raw value, so + /// it encodes as `{"table": {}}` rather than `"table"`. + @Test("A file written before the kind existed decodes, and falls back to the Bool") + func missingKeyDecodesToTheFallback() throws { + let persisted = try decodePersisted(droppingKindFrom: tableTab()) + #expect(persisted.objectTypeRawValue == nil) + + let restored = QueryTab(from: persisted, defaultPageSize: 1_000) + #expect(restored.tableContext.objectType == nil) + #expect(restored.tableContext.resolvedObjectKind() == .table) + } + + @Test("A view saved before the kind existed falls back to a view, not a table") + func missingKeyOnAViewFallsBackToView() throws { + var tab = tableTab() + tab.tableContext.isView = true + tab.tableContext.objectType = .view + + let persisted = try decodePersisted(droppingKindFrom: tab) + #expect(persisted.objectTypeRawValue == nil) + #expect(QueryTab(from: persisted, defaultPageSize: 1_000).tableContext.resolvedObjectKind() == .view) + } + + /// A raw String rather than the enum, so a spelling a newer build invents is dropped instead of + /// throwing. A tab that comes back gated as a table is a smaller failure than a session that does + /// not come back. + @Test("A kind this build does not know decodes to nil rather than throwing") + func unknownKindDecodesToNil() throws { + var tab = tableTab() + tab.tableContext.objectType = .materializedView + + var object = try jsonObject(of: tab.toPersistedTab()) + object["objectTypeRawValue"] = "GRAPH" + let persisted = try JSONDecoder().decode( + PersistedTab.self, from: try JSONSerialization.data(withJSONObject: object) + ) + + #expect(persisted.objectTypeRawValue == "GRAPH") + #expect(QueryTab(from: persisted, defaultPageSize: 1_000).tableContext.objectType == nil) + } + + private func jsonObject(of persisted: PersistedTab) throws -> [String: Any] { + let data = try JSONEncoder().encode(persisted) + return try #require(try JSONSerialization.jsonObject(with: data) as? [String: Any]) + } + + private func decodePersisted(droppingKindFrom tab: QueryTab) throws -> PersistedTab { + var object = try jsonObject(of: tab.toPersistedTab()) + object.removeValue(forKey: "objectTypeRawValue") + return try JSONDecoder().decode( + PersistedTab.self, from: try JSONSerialization.data(withJSONObject: object) + ) + } + + // MARK: - Window payload + + @Test("The kind survives a trip through a window-tab payload") + func payloadCarriesTheKind() throws { + var tab = tableTab() + tab.tableContext.objectType = .foreignTable + + let payload = EditorTabPayload(from: tab, connectionId: UUID()) + #expect(payload.objectType == .foreignTable) + + let decoded = try JSONDecoder().decode( + EditorTabPayload.self, from: try JSONEncoder().encode(payload) + ) + #expect(decoded.objectType == .foreignTable) + } + + @Test("A payload with no kind key decodes to nil") + func payloadWithoutTheKindDecodes() throws { + var tab = tableTab() + tab.tableContext.objectType = .materializedView + + let data = try JSONEncoder().encode(EditorTabPayload(from: tab, connectionId: UUID())) + var object = try #require(try JSONSerialization.jsonObject(with: data) as? [String: Any]) + object.removeValue(forKey: "objectType") + + let payload = try JSONDecoder().decode( + EditorTabPayload.self, from: try JSONSerialization.data(withJSONObject: object) + ) + #expect(payload.objectType == nil) + } +} diff --git a/TableProTests/Models/Schema/ColumnReorderPolicyTests.swift b/TableProTests/Models/Schema/ColumnReorderPolicyTests.swift index dd16991a5f..13e72eee04 100644 --- a/TableProTests/Models/Schema/ColumnReorderPolicyTests.swift +++ b/TableProTests/Models/Schema/ColumnReorderPolicyTests.swift @@ -12,7 +12,7 @@ struct ColumnReorderPolicyTests { private func resolve( support: ColumnReorderSupport = .alter, isColumnsTab: Bool = true, - isTable: Bool = true, + kindRefusal: String? = nil, canEditSchema: Bool = true, hasStagedChanges: Bool = false, isRearranged: Bool = false @@ -21,7 +21,7 @@ struct ColumnReorderPolicyTests { support: support, engineName: "PostgreSQL", isColumnsTab: isColumnsTab, - isTable: isTable, + kindRefusal: kindRefusal, canEditSchema: canEditSchema, hasStagedChanges: hasStagedChanges, isRearranged: isRearranged @@ -76,11 +76,11 @@ struct ColumnReorderPolicyTests { /// withheld rather than acted on against the wrong column. /// Every mechanism emits table DDL, and the SQLite one looks its target up as a table, so a /// view drag would end in a statement error instead of an explanation. - @Test("A view is withheld, whatever the engine can do to a table") - func viewWithholdsTheDrag() { - let availability = resolve(isTable: false) + @Test("A refusing object kind is withheld, whatever the engine can do to a table") + func refusingKindWithholdsTheDrag() { + let availability = resolve(kindRefusal: "A view has no column order of its own to change.") #expect(!availability.isAvailable) - #expect(availability.unavailableReason != nil) + #expect(availability.unavailableReason == "A view has no column order of its own to change.") } @Test("A filtered or sorted column list withholds the drag") diff --git a/TableProTests/Models/Schema/ForeignKeyEditPolicyTests.swift b/TableProTests/Models/Schema/ForeignKeyEditPolicyTests.swift index f5a3f4b149..e24e2cd95f 100644 --- a/TableProTests/Models/Schema/ForeignKeyEditPolicyTests.swift +++ b/TableProTests/Models/Schema/ForeignKeyEditPolicyTests.swift @@ -11,13 +11,13 @@ import Testing struct ForeignKeyEditPolicyTests { private func resolve( _ support: ForeignKeyEditSupport, - isTable: Bool = true, + kindRefusal: String? = nil, canEditSchema: Bool = true ) -> ForeignKeyEditAvailability { ForeignKeyEditPolicy.resolve( support: support, engineName: "Engine", - isTable: isTable, + kindRefusal: kindRefusal, canEditSchema: canEditSchema ) } @@ -43,11 +43,14 @@ struct ForeignKeyEditPolicyTests { #expect(availability.unavailableReason?.contains("Engine") == true) } - @Test("A view has no foreign keys of its own") - func withholdsOnViews() { - let availability = resolve(.rebuild, isTable: false) + /// The reason comes from the caller's per-kind matrix, because only that knows whether the user + /// is looking at a view, a materialized view or a foreign table. PostgreSQL refuses + /// `ADD CONSTRAINT … FOREIGN KEY` on all three. + @Test("An object kind that refuses the edit is withheld with its own reason") + func withholdsOnRefusingKinds() { + let availability = resolve(.rebuild, kindRefusal: "A materialized view cannot have constraints.") #expect(!availability.isAvailable) - #expect(availability.unavailableReason != nil) + #expect(availability.unavailableReason == "A materialized view cannot have constraints.") } /// Checked before the engine's own capability so a read-only engine explains that rather than @@ -62,7 +65,9 @@ struct ForeignKeyEditPolicyTests { @Test("Every reason is a sentence, never an empty string") func alwaysExplainsItself() { let withheld = [ - resolve(.unsupported), resolve(.rebuild, isTable: false), resolve(.alter, canEditSchema: false) + resolve(.unsupported), + resolve(.rebuild, kindRefusal: "A view cannot have constraints."), + resolve(.alter, canEditSchema: false) ] for availability in withheld { #expect(availability.unavailableReason?.isEmpty == false) diff --git a/TableProTests/Views/Structure/StructureEditGateTests.swift b/TableProTests/Views/Structure/StructureEditGateTests.swift new file mode 100644 index 0000000000..e4f9430d67 --- /dev/null +++ b/TableProTests/Views/Structure/StructureEditGateTests.swift @@ -0,0 +1,128 @@ +// +// StructureEditGateTests.swift +// TableProTests +// + +import Foundation +import TableProPluginKit +import Testing +@testable import TablePro + +/// The gate is the one impure half of the decision: it reads the engine's curated matrix and its +/// capability flags, and every call site in the Structure tab asks it rather than reading a flag of +/// its own. They used to read them separately, which is how the footer, the Edit menu's Add Row, the +/// row context menu and the grid's own paste path each got to a different answer. (#2726) +@Suite("Structure Edit Gate") +@MainActor +struct StructureEditGateTests { + private func gate(_ kind: TableInfo.TableType, _ type: DatabaseType = .postgresql) -> StructureEditGate { + StructureEditGate(databaseType: type, objectKind: kind) + } + + @Test("A PostgreSQL table takes every edit end to end") + func tableTakesEverything() { + let table = gate(.table) + #expect(table.allowsAnyEdit) + for operation in StructureEditOperation.allCases { + #expect(table.allows(operation), "table refused \(operation)") + } + } + + @Test("A PostgreSQL view refuses a column and an index but keeps a rename and a default") + func viewSplitsByOperation() { + let view = gate(.view) + #expect(view.allowsAnyEdit) + #expect(view.allows(.renameColumn)) + #expect(view.allows(.setDefault)) + #expect(view.allows(.commentOnColumn)) + #expect(!view.allows(.addColumn)) + #expect(!view.allows(.setNotNull)) + #expect(!view.allows(.addIndex)) + #expect(!view.allows(.addForeignKey)) + #expect(!view.allows(.reorderColumns)) + } + + @Test("A PostgreSQL materialized view takes an index and refuses a default") + func materializedViewTakesAnIndex() { + let matview = gate(.materializedView) + #expect(matview.allows(.addIndex)) + #expect(matview.allows(.dropIndex)) + #expect(!matview.allows(.setDefault)) + #expect(!matview.allows(.addForeignKey)) + } + + @Test("A system table allows nothing at all, so the grid has nothing to offer") + func systemTableAllowsNothing() { + let system = gate(.systemTable) + #expect(!system.allowsAnyEdit) + #expect(system.editableColumnFields.isEmpty) + } + + @Test("A view keeps exactly Name, Default and Comment unlocked") + func viewEditableFields() { + #expect(gate(.view).editableColumnFields == [.name, .defaultValue, .comment]) + } + + /// An engine nobody has curated gets tables only, so a MySQL view's grid is read-only rather than + /// accepting edits MySQL refuses on a view. + @Test("An uncurated engine withholds every edit on a view") + func uncuratedEngineWithholdsOnViews() { + let view = gate(.view, .mysql) + #expect(!view.allowsAnyEdit) + #expect(view.editableColumnFields.isEmpty) + #expect(!view.allows(.renameColumn)) + #expect(gate(.table, .mysql).allowsAnyEdit) + } + + /// The gate answers the foreign key arm through `ForeignKeyEditPolicy`, so the engine that has to + /// recreate the table still offers the edit and the refusal keeps that policy's own wording + /// rather than the sentence every other constraint shares. + @Test("An engine that recreates the table to change a key still offers the edit") + func rebuildEngineOffersForeignKeys() { + #expect(gate(.table, .sqlite).allows(.addForeignKey)) + #expect(gate(.table, .sqlite).allows(.dropForeignKey)) + #expect(gate(.table).allows(.addForeignKey)) + } + + @Test("A refusing kind reaches the foreign key arm with the kind's own reason") + func foreignKeyRefusalNamesTheKind() { + let matview = gate(.materializedView) + #expect(!matview.allows(.addForeignKey)) + #expect(matview.resolve(.addForeignKey).unavailableReason?.contains("materialized view") == true) + #expect(matview.foreignKeyAvailability.unavailableReason?.contains("materialized view") == true) + } + + @Test("A refused operation carries a reason and an accepted one does not") + func reasonsTravelWithTheRefusal() { + #expect(gate(.view).kindRefusal(.addIndex)?.isEmpty == false) + #expect(gate(.view).kindRefusal(.renameColumn) == nil) + #expect(gate(.materializedView).kindRefusal(.addIndex) == nil) + #expect(gate(.materializedView).resolve(.setDefault).unavailableReason?.isEmpty == false) + } + + /// The per-column lock is name-keyed, and the only names it can use are the Columns grid's own + /// headings. If a provider ever respelled one, the field behind it would silently unlock, so the + /// two lists are pinned to each other here. + @Test("The Columns grid's headings are exactly the field display names the lock uses") + func headingsMatchTheFieldNames() { + let provider = StructureRowProvider( + changeManager: StructureChangeManager(), + tab: .columns, + databaseType: .postgresql, + additionalFields: [.primaryKey], + serverSupport: .unrestricted + ) + #expect(provider.columns == provider.orderedColumnFields.map(\.displayName)) + + let locked = Set( + StructureColumnField.allCases + .filter { !gate(.view).editableColumnFields.contains($0) } + .map(\.displayName) + ) + let unlocked = provider.columns.filter { !locked.contains($0) } + #expect(unlocked.contains(StructureColumnField.name.displayName)) + #expect(unlocked.contains(StructureColumnField.defaultValue.displayName)) + #expect(!unlocked.contains(StructureColumnField.type.displayName)) + #expect(!unlocked.contains(StructureColumnField.nullable.displayName)) + } +} diff --git a/TableProTests/Views/Structure/StructureFooterPolicyTests.swift b/TableProTests/Views/Structure/StructureFooterPolicyTests.swift new file mode 100644 index 0000000000..0ab86e7711 --- /dev/null +++ b/TableProTests/Views/Structure/StructureFooterPolicyTests.swift @@ -0,0 +1,140 @@ +// +// StructureFooterPolicyTests.swift +// TableProTests +// + +import Foundation +import Testing +@testable import TablePro + +/// The "+" and "-" under a structure list used to take their label, their enabled state and their +/// tooltip from three different switches, and only the Foreign Keys one asked about the object at +/// all. So a view offered an enabled "Add Column" over a statement PostgreSQL always refuses, with +/// nothing to explain it. (#2726) +@Suite("Structure Footer Policy") +struct StructureFooterPolicyTests { + private func resolve( + tab: StructureTab, + kind: TableInfo.TableType, + matrix: StructureObjectEditMatrix = .postgreSQL, + canEditSchema: Bool = true, + hasSelection: Bool = true + ) -> StructureFooterCapability { + StructureFooterPolicy.resolve( + tab: tab, + canEditSchema: canEditSchema, + hasSelection: hasSelection, + resolve: { operation in + StructureEditEligibility.resolve( + operation, + on: kind, + matrix: matrix, + engineAllows: true, + engineName: "PostgreSQL", + canEditSchema: canEditSchema + ) + } + ) + } + + @Test("A table offers both buttons on all four editable tabs") + func tableOffersEverything() { + for tab in [StructureTab.columns, .indexes, .foreignKeys, .checkConstraints] { + let capability = resolve(tab: tab, kind: .table) + #expect(capability.canAdd, "\(tab.rawValue)") + #expect(capability.canRemove, "\(tab.rawValue)") + #expect(capability.unavailableReason == nil, "\(tab.rawValue)") + } + } + + /// Shown and dimmed, not hidden. The pair disappearing would read as "this tab has no columns", + /// and the tooltip is the only place the refusal can be stated. + @Test("A view keeps the Columns pair on screen, dimmed, with a reason") + func viewDimsTheColumnsPair() { + let capability = resolve(tab: .columns, kind: .view) + #expect(!capability.canAdd) + #expect(!capability.canRemove) + #expect(capability.isActive) + #expect(capability.addLabel.isEmpty == false) + #expect(capability.unavailableReason?.isEmpty == false) + } + + @Test("A materialized view offers an index and refuses a column") + func materializedViewSplitsByTab() { + let indexes = resolve(tab: .indexes, kind: .materializedView) + #expect(indexes.canAdd) + #expect(indexes.canRemove) + #expect(indexes.unavailableReason == nil) + + let columns = resolve(tab: .columns, kind: .materializedView) + #expect(!columns.canAdd) + #expect(columns.unavailableReason?.isEmpty == false) + } + + @Test("A foreign table offers a check constraint and refuses an index") + func foreignTableSplitsByTab() { + let checks = resolve(tab: .checkConstraints, kind: .foreignTable) + #expect(checks.canAdd) + + let indexes = resolve(tab: .indexes, kind: .foreignTable) + #expect(!indexes.canAdd) + #expect(indexes.unavailableReason?.isEmpty == false) + } + + @Test("A foreign table refuses a foreign key, which is the constraint PostgreSQL rejects on one") + func foreignTableRefusesForeignKeys() { + let keys = resolve(tab: .foreignKeys, kind: .foreignTable) + #expect(!keys.canAdd) + #expect(keys.unavailableReason?.isEmpty == false) + } + + /// Today's behaviour, preserved on purpose: an engine that cannot edit structure at all hides the + /// pair rather than showing two dead buttons on every tab. + @Test("An engine that cannot edit structure hides the pair entirely") + func readOnlyEngineHidesThePair() { + let capability = resolve(tab: .columns, kind: .table, canEditSchema: false) + #expect(!capability.isActive) + #expect(capability.addLabel.isEmpty) + #expect(!capability.canAdd) + #expect(!capability.canRemove) + } + + @Test("Nothing selected dims Remove without dimming Add and without inventing a reason") + func emptySelectionOnlyDimsRemove() { + let capability = resolve(tab: .columns, kind: .table, hasSelection: false) + #expect(capability.canAdd) + #expect(!capability.canRemove) + #expect(capability.unavailableReason == nil) + } + + @Test("The tabs with nothing to add have no operation and no pair") + func nonEditableTabsHaveNoPair() { + for tab in [StructureTab.ddl, .parts, .triggers] { + #expect(StructureFooterPolicy.operation(forAdding: tab) == nil, "\(tab.rawValue)") + #expect(StructureFooterPolicy.operation(forRemoving: tab) == nil, "\(tab.rawValue)") + #expect(!resolve(tab: tab, kind: .table).isActive, "\(tab.rawValue)") + } + } + + @Test("Each editable tab names the add and the drop of its own object") + func operationsMatchTheirTabs() { + #expect(StructureFooterPolicy.operation(forAdding: .columns) == .addColumn) + #expect(StructureFooterPolicy.operation(forRemoving: .columns) == .dropColumn) + #expect(StructureFooterPolicy.operation(forAdding: .indexes) == .addIndex) + #expect(StructureFooterPolicy.operation(forRemoving: .indexes) == .dropIndex) + #expect(StructureFooterPolicy.operation(forAdding: .foreignKeys) == .addForeignKey) + #expect(StructureFooterPolicy.operation(forRemoving: .foreignKeys) == .dropForeignKey) + #expect(StructureFooterPolicy.operation(forAdding: .checkConstraints) == .addCheckConstraint) + #expect(StructureFooterPolicy.operation(forRemoving: .checkConstraints) == .dropCheckConstraint) + } + + /// An engine nobody has measured falls back to tables only, so every non-table dims rather than + /// offering an edit its server may refuse. + @Test("An uncurated engine dims the pair on a view") + func uncuratedEngineDimsNonTables() { + let capability = resolve(tab: .columns, kind: .view, matrix: .tablesOnly) + #expect(!capability.canAdd) + #expect(capability.isActive) + #expect(capability.unavailableReason?.isEmpty == false) + } +} diff --git a/TableProTests/Views/Structure/StructureGridDelegateAddRowTests.swift b/TableProTests/Views/Structure/StructureGridDelegateAddRowTests.swift index 436d568b94..8bc5b07ebd 100644 --- a/TableProTests/Views/Structure/StructureGridDelegateAddRowTests.swift +++ b/TableProTests/Views/Structure/StructureGridDelegateAddRowTests.swift @@ -16,7 +16,8 @@ import Testing struct StructureGridDelegateAddRowTests { private func makeDelegate( selectedTab: StructureTab = .columns, - type: DatabaseType = .mysql + type: DatabaseType = .mysql, + objectKind: TableInfo.TableType = .table ) -> (StructureGridDelegate, StructureChangeManager) { let manager = StructureChangeManager() let connection = TestFixtures.makeConnection(type: type) @@ -25,6 +26,7 @@ struct StructureGridDelegateAddRowTests { selectedTab: selectedTab, connection: connection, tableName: "t", + objectKind: objectKind, coordinator: nil ) return (delegate, manager) @@ -179,4 +181,70 @@ struct StructureGridDelegateAddRowTests { #expect(manager.workingIndexes.count == before - 1) } + + // MARK: - Per object kind + + /// The footer pair is not the only way in. Cmd+Shift+N reaches `dataGridAddRow` through + /// `structureActions`, the row and empty-space menus reach it directly, and none of them consults + /// the dimmed button, so the delegate has to refuse for itself. (#2726) + @Test("A PostgreSQL view refuses an added column, whatever reaches the delegate") + func viewRefusesAnAddedColumn() { + let (delegate, manager) = makeDelegate(selectedTab: .columns, type: .postgresql, objectKind: .view) + delegate.dataGridAddRow() + #expect(manager.workingColumns.isEmpty) + } + + @Test("A PostgreSQL view refuses an added index and a materialized view accepts one") + func indexesFollowTheObjectKind() { + let (view, viewManager) = makeDelegate(selectedTab: .indexes, type: .postgresql, objectKind: .view) + view.dataGridAddRow() + #expect(viewManager.workingIndexes.isEmpty) + + let (matview, matviewManager) = makeDelegate( + selectedTab: .indexes, type: .postgresql, objectKind: .materializedView + ) + matview.dataGridAddRow() + #expect(matviewManager.workingIndexes.count == 1) + } + + @Test("A PostgreSQL materialized view refuses a foreign key") + func materializedViewRefusesAForeignKey() { + let (delegate, manager) = makeDelegate( + selectedTab: .foreignKeys, type: .postgresql, objectKind: .materializedView + ) + delegate.dataGridAddRow() + #expect(manager.workingForeignKeys.isEmpty) + } + + @Test("A view refuses to drop a column its own grid is showing") + func viewRefusesADroppedColumn() { + let manager = StructureChangeManager() + manager.addColumn(.placeholder()) + let before = manager.workingColumns.count + #expect(before == 1) + + let view = StructureGridDelegate( + structureChangeManager: manager, + selectedTab: .columns, + connection: TestFixtures.makeConnection(type: .postgresql), + tableName: "v_sales", + objectKind: .view, + coordinator: nil + ) + view.dataGridDeleteRows([0]) + + #expect(manager.workingColumns.count == before) + } + + @Test("A system table refuses every add") + func systemTableRefusesEveryAdd() { + for tab in [StructureTab.columns, .indexes, .foreignKeys, .checkConstraints] { + let (delegate, manager) = makeDelegate(selectedTab: tab, type: .postgresql, objectKind: .systemTable) + delegate.dataGridAddRow() + #expect(manager.workingColumns.isEmpty, "\(tab.rawValue)") + #expect(manager.workingIndexes.isEmpty, "\(tab.rawValue)") + #expect(manager.workingForeignKeys.isEmpty, "\(tab.rawValue)") + #expect(manager.workingCheckConstraints.isEmpty, "\(tab.rawValue)") + } + } } diff --git a/docs/databases/postgresql.mdx b/docs/databases/postgresql.mdx index a12790c402..1ec304caf9 100644 --- a/docs/databases/postgresql.mdx +++ b/docs/databases/postgresql.mdx @@ -83,6 +83,8 @@ A view's definition is rebuilt to run anywhere. Every table it reads is schema-q An SQL export writes those statements back for tables, views and materialized views, so a dump and a restore keep their comments. See [Import & Export](/features/import-export). +The Structure tab of a view, a materialized view or a foreign table offers only the edits PostgreSQL takes on that kind of object, which is fewer than a table's and different for each. See [Table Structure](/features/table-structure#what-each-object-accepts). + ## Cross-database tabs PostgreSQL has no in-place `USE`, so a tab bound to a database other than the connection's active one runs on a second connection opened for that database. It shares no temp tables, session variables, or open transaction with the query editor on the main connection: keep a multi-statement transaction or a `CREATE TEMP TABLE` on tabs bound to one database. Binding itself is on [Tabs](/features/tabs#where-a-tab-points). diff --git a/docs/features/table-structure.mdx b/docs/features/table-structure.mdx index ecd11c004b..ee3c0097bd 100644 --- a/docs/features/table-structure.mdx +++ b/docs/features/table-structure.mdx @@ -16,6 +16,24 @@ Open a table and switch the result view to **Structure**, or right-click it in t The tabs are **Columns**, **Indexes**, **Foreign Keys**, **Constraints**, **Triggers**, **DDL**, and **Parts** (ClickHouse only); the first five carry item counts. A tab the engine has no concept of is hidden: ClickHouse has no Foreign Keys, Redshift no Triggers, Redis no Constraints. Every grid has a filter field, and clicking a header sorts. +## What each object accepts + +A view is not a table, and the grid offers only the edits the server will take on the object open in front of it. A refused **+** or **-** stays on screen, dimmed, with the reason in its tooltip; a cell the object will not let you change beeps instead of opening an editor. + +PostgreSQL answers this per operation, so the tab does too: + +| Object | What it accepts | +|--------|-----------------| +| Table, partitioned table | Everything on this page | +| View | Rename a column, set or clear its default, edit its comment | +| Materialized view | Rename a column, edit its comment, add and drop indexes | +| Foreign table | Every column change and check constraints. No indexes, no keys | +| System table, external table | Nothing | + +A view and a materialized view differ in both directions: `ALTER TABLE … SET DEFAULT` runs on a view and is refused on a materialized view, and `CREATE INDEX` is the other way round. + +Every other engine edits a table and a partitioned table only. A view, a materialized view, a foreign table and a system table are read-only there. + ## Columns tab Columns are edited in place. **Nullable**, **Primary Key**, and **Auto Inc** are YES/NO dropdowns; **Primary Key** set to YES forces **Nullable** to NO and holds it there until the key comes back off. **Type** opens a picker of the engine's types by category: search to filter, or type a parametric value such as `VARCHAR(255)` and press Return to use it as written. On PostgreSQL and PGlite the picker opens with a **User-Defined** group of the database's enums, composites, domains and ranges, each listed schema-qualified as `sales.status`. See [User-Defined Types](/features/user-defined-types). @@ -67,7 +85,7 @@ Add a column with **+** at the right of the status bar or `Cmd+Shift+N`. Select Flag **Primary Key** on one column, or several for a composite key in one `PRIMARY KEY (col1, col2)` clause. On an existing table that becomes a drop of the old constraint followed by an add. -Drag a column row to reorder it, or right-click one and choose **Move Column Up** or **Move Column Down**. Both are dimmed with the reason spelled out under them while unsaved changes exist, while the list is filtered or sorted, on a view, and on an engine that cannot change column order. +Drag a column row to reorder it, or right-click one and choose **Move Column Up** or **Move Column Down**. Both are dimmed with the reason spelled out under them while unsaved changes exist, while the list is filtered or sorted, on anything but a table, and on an engine that cannot change column order. What the drag does depends on the engine: @@ -100,7 +118,7 @@ Everything that runs goes to query history rather than the change queue. Right-click a foreign key and choose **Open [table]** to jump to the referenced table. Right-click any row in these three grids for **Copy** (the cell under the pointer), **Copy Name**, **Copy Definition**, **Copy As** (CSV, JSON, SQL), **Duplicate**, and **Delete** (`Delete`). A row already marked for deletion offers **Undo Delete**. The same menu appears whether or not the row was already selected, and its row commands act on the whole selection. -**Add Foreign Key** and **Remove Foreign Key** sit under the list. Both are dimmed on a view and on an engine that cannot edit foreign keys, with the reason in the tooltip. +**Add Foreign Key** and **Remove Foreign Key** sit under the list. Both are dimmed on an object that cannot carry a key and on an engine that cannot edit foreign keys, with the reason in the tooltip. What the save does depends on the engine: From 7d44702e9e4252c93a0c4656895ec278a02d00e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 10:20:53 +0700 Subject: [PATCH 45/54] docs(weaviate): name the filter operators the way the filtering page does (#2782) --- docs/databases/weaviate.mdx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/databases/weaviate.mdx b/docs/databases/weaviate.mdx index d1dfc1a8c5..0c847bc217 100644 --- a/docs/databases/weaviate.mdx +++ b/docs/databases/weaviate.mdx @@ -48,15 +48,15 @@ Unfiltered pages load through `GET /v1/objects`. A column filter or a sort becom Filter values are typed from the collection schema: an `int` property filters as a number, a `date` property needs a full RFC 3339 timestamp such as `2024-01-31T00:00:00Z`, and an array property filters on one element. -| Operator | What Weaviate runs | +| Operators | What Weaviate runs | |----------|--------------------| -| **=**, **!=** | `Equal`, `NotEqual` | -| **>**, **>=**, **<**, **<=** | Numbers and dates only | -| **CONTAINS**, **NOT CONTAINS**, **STARTS WITH**, **ENDS WITH** | `Like` with `*` wildcards, text properties only | -| **IN**, **NOT IN** | `ContainsAny`, `ContainsNone` over a comma-separated list | -| **BETWEEN** | Two bounds, both inclusive | -| **IS NULL**, **IS NOT NULL** | `IsNull`, which needs `indexNullState` on the collection | -| **IS EMPTY**, **IS NOT EMPTY** | `len()`, which needs `indexPropertyLength` on the collection | +| equals, not equals | `Equal`, `NotEqual` | +| greater than, greater or equal, less than, less or equal | Numbers and dates only | +| contains, not contains, starts with, ends with | `Like` with `*` wildcards, text properties only | +| in list, not in list | `ContainsAny`, `ContainsNone` over a comma-separated list | +| between | Two bounds, both inclusive | +| is NULL, is not NULL | `IsNull`, which needs `indexNullState` on the collection | +| is empty, is not empty | `len()`, which needs `indexPropertyLength` on the collection | **REGEX** has no Weaviate equivalent, and a filter Weaviate cannot run reports why instead of returning the whole collection. From ac96638310b8e68d403bb918cde69dea2f634de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 10:21:16 +0700 Subject: [PATCH 46/54] feat(settings): theme the content panes outside the editor and the data grid (#2781) Claude-Session: https://claude.ai/code/session_01EKDGt17u6TaVBDHm8rzSEj --- CHANGELOG.md | 4 ++ .../Core/Autocomplete/SQLCompletionItem.swift | 17 +++++---- .../MainSplitViewController.swift | 6 +-- TablePro/Models/UI/JSONTreeNode.swift | 11 +++--- TablePro/Models/UI/PhpTreeNode.swift | 11 +++--- .../Resources/Themes/tablepro.dracula.json | 8 ++++ TablePro/Resources/Themes/tablepro.nord.json | 8 ++++ TablePro/Theme/BuiltInThemes.swift | 15 ++++++++ TablePro/Theme/ThemeDefinition.swift | 37 +++++++++++++++++++ TablePro/Theme/ThemedContentSurface.swift | 27 ++++++++++++++ .../Views/Components/SQLReviewSheet.swift | 3 +- .../Editor/FileModifiedOnDiskBanner.swift | 4 +- .../Editor/History/HistoryDetailPane.swift | 2 +- .../Views/Editor/History/HistoryRowView.swift | 2 +- .../Views/Editor/QueryCompletionAdapter.swift | 5 ++- .../Editor/QueryDiagnosticsController.swift | 12 +++++- TablePro/Views/Editor/QueryEditorView.swift | 1 - .../Views/Editor/SQLEditorCoordinator.swift | 7 ++++ TablePro/Views/Editor/SQLEditorView.swift | 1 + TablePro/Views/Import/SQLCodePreview.swift | 2 +- .../QueryInsightsActivityChart.swift | 2 +- .../QueryInsightsGroupList.swift | 6 +-- .../QueryInsightsSummaryBar.swift | 2 +- .../Views/Results/ArrayValueEditorView.swift | 2 +- .../Results/ColumnValueFilterPopover.swift | 2 +- .../Views/Results/DataGridCoordinator.swift | 1 + .../Views/Results/ForeignKeyPickerView.swift | 2 +- .../Views/Results/ForeignKeyPreviewView.swift | 2 +- .../Views/Results/HexEditorContentView.swift | 16 +++++--- .../Views/Results/InlineErrorBanner.swift | 4 +- TablePro/Views/Results/JSONTreeView.swift | 2 +- TablePro/Views/Results/PhpTreeView.swift | 2 +- .../Views/Results/ResultChartCanvas.swift | 14 +++---- .../Views/Results/ResultSuccessView.swift | 2 +- .../Selection/GridSelectionOverlay.swift | 2 +- .../FieldEditors/BlobHexEditorView.swift | 4 +- .../FieldEditors/FieldEditorContent.swift | 4 +- .../FieldEditors/ImageFieldView.swift | 2 +- .../FieldEditors/JsonEditorView.swift | 2 +- .../FieldEditors/MultiLineEditorView.swift | 2 +- .../FieldEditors/PhpSerializedFieldView.swift | 2 +- .../ResizableEditorContainer.swift | 2 +- .../FieldEditors/SingleLineEditorView.swift | 4 +- .../JSON/JSONRowInspectorView.swift | 2 +- .../ServerDashboard/MetricsBarView.swift | 2 +- .../ServerDashboard/SessionsTableView.swift | 8 ++-- .../ServerDashboard/SlowQueryListView.swift | 4 +- .../Views/Structure/ClickHousePartsView.swift | 4 +- .../Views/Structure/CreateTableView.swift | 2 +- TablePro/Views/Structure/DDLTextView.swift | 2 +- .../Structure/TableStructureView+Schema.swift | 2 +- .../Views/Structure/TableStructureView.swift | 2 +- .../Views/Structure/TriggerDetailView.swift | 4 +- docs/customization/appearance.mdx | 2 + 54 files changed, 214 insertions(+), 86 deletions(-) create mode 100644 TablePro/Theme/ThemedContentSurface.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 58e15b3059..a6e23aa622 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Header, grid line, selection and focus colors in the theme editor. - Themes that name a system color for a slot, so the built-in themes keep the system's own contrast settings. - Reason shown in Settings > Appearance for a theme file that could not be loaded. +- Panel and status colors in the theme editor, covering the results, inspector, structure, compare and query plan panes. - **Refresh Materialized View…** on PostgreSQL, with a concurrent refresh where the view qualifies. (#2726) - **Show DDL** and **Copy DDL** for views and materialized views. (#2726) - **Edit Comment…** for PostgreSQL tables, views, materialized views and foreign tables. (#2726) @@ -70,6 +71,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Query history preview ignoring the theme and the editor font. - Theme editor changing the active theme instead of the theme selected for the slot being edited. - Malformed theme files loading as Default Light under their own name. +- Content panes outside the editor and the data grid ignoring the theme. +- JSON and PHP tree values colored differently from the same values in the row inspector. +- Autocomplete icon colors ignoring the theme. - Color with a typo in it rendering as a different color instead of being reported. - Text past the first 64 KB of a UTF-16 SQL import arriving byte-swapped. - SQL import failing on a file whose encoding is not UTF-8 when a character lands on a 64 KB boundary. diff --git a/TablePro/Core/Autocomplete/SQLCompletionItem.swift b/TablePro/Core/Autocomplete/SQLCompletionItem.swift index 39e7030e3a..378d170948 100644 --- a/TablePro/Core/Autocomplete/SQLCompletionItem.swift +++ b/TablePro/Core/Autocomplete/SQLCompletionItem.swift @@ -36,16 +36,17 @@ enum SQLCompletionKind: String, CaseIterable { } /// Color for the icon + @MainActor var iconColor: NSColor { switch self { - case .keyword: return .systemBlue - case .table: return .systemTeal - case .view: return .systemPurple - case .column: return .systemOrange - case .function: return .systemPink - case .schema: return .systemGreen - case .alias: return .systemGray - case .operator: return .systemIndigo + case .keyword: return ThemeEngine.shared.palette[.syntaxKeyword] + case .table: return ThemeEngine.shared.palette[.syntaxType] + case .view: return ThemeEngine.shared.palette[.syntaxType] + case .column: return ThemeEngine.shared.palette[.syntaxNull] + case .function: return ThemeEngine.shared.palette[.syntaxFunction] + case .schema: return ThemeEngine.shared.palette[.syntaxType] + case .alias: return ThemeEngine.shared.palette[.syntaxNull] + case .operator: return ThemeEngine.shared.palette[.syntaxOperator] case .favorite: return .systemYellow } } diff --git a/TablePro/Core/Services/Infrastructure/MainSplitViewController.swift b/TablePro/Core/Services/Infrastructure/MainSplitViewController.swift index f1b3c867f8..f6802b77e0 100644 --- a/TablePro/Core/Services/Infrastructure/MainSplitViewController.swift +++ b/TablePro/Core/Services/Infrastructure/MainSplitViewController.swift @@ -714,8 +714,8 @@ internal final class MainSplitViewController: NSSplitViewController, TrailingPan /// intermediate value instead of letting one run-loop turn settle on the final one. private func refreshPanes(of workspace: ConnectionWorkspace) { workspace.panes.sidebar.rootView = AnyView(buildSidebarView(for: workspace)) - workspace.panes.detail.rootView = AnyView(buildDetailView(for: workspace)) - workspace.panes.inspector.rootView = AnyView(buildInspectorView(for: workspace)) + workspace.panes.detail.rootView = AnyView(buildDetailView(for: workspace).themedContent()) + workspace.panes.inspector.rootView = AnyView(buildInspectorView(for: workspace).themedContent()) workspace.panes.assistant.rootView = AnyView(buildAssistantView(for: workspace)) refreshTabStripPane(of: workspace) workspace.panes.markRendered(workspace.paneRenderKey) @@ -903,7 +903,7 @@ internal final class MainSplitViewController: NSSplitViewController, TrailingPan /// publishes those actions. func rebuildTrailingPanes() { guard let selected = workspaces.selected else { return } - selected.panes.inspector.rootView = AnyView(buildInspectorView(for: selected)) + selected.panes.inspector.rootView = AnyView(buildInspectorView(for: selected).themedContent()) selected.panes.assistant.rootView = AnyView(buildAssistantView(for: selected)) } diff --git a/TablePro/Models/UI/JSONTreeNode.swift b/TablePro/Models/UI/JSONTreeNode.swift index 8ed335fdc7..1b6ccd3b6f 100644 --- a/TablePro/Models/UI/JSONTreeNode.swift +++ b/TablePro/Models/UI/JSONTreeNode.swift @@ -27,13 +27,14 @@ internal enum JSONValueType { } } + @MainActor var color: NSColor { switch self { - case .object, .array: return .systemBlue - case .string: return .systemRed - case .number: return .systemPurple - case .boolean, .null: return .systemOrange - case .truncated: return .secondaryLabelColor + case .object, .array: return ThemeEngine.shared.palette[.syntaxKeyword] + case .string: return ThemeEngine.shared.palette[.syntaxString] + case .number: return ThemeEngine.shared.palette[.syntaxNumber] + case .boolean, .null: return ThemeEngine.shared.palette[.syntaxNull] + case .truncated: return ThemeEngine.shared.palette[.panelSecondaryText] } } } diff --git a/TablePro/Models/UI/PhpTreeNode.swift b/TablePro/Models/UI/PhpTreeNode.swift index 3683a5e417..11eec35a0e 100644 --- a/TablePro/Models/UI/PhpTreeNode.swift +++ b/TablePro/Models/UI/PhpTreeNode.swift @@ -35,13 +35,14 @@ internal enum PhpNodeType { } } + @MainActor var color: NSColor { switch self { - case .array, .object: return .systemBlue - case .string: return .systemRed - case .int, .float: return .systemPurple - case .bool, .null: return .systemOrange - case .serializable: return .systemTeal + case .array, .object: return ThemeEngine.shared.palette[.syntaxKeyword] + case .string: return ThemeEngine.shared.palette[.syntaxString] + case .int, .float: return ThemeEngine.shared.palette[.syntaxNumber] + case .bool, .null: return ThemeEngine.shared.palette[.syntaxNull] + case .serializable: return ThemeEngine.shared.palette[.syntaxType] case .reference: return .systemGray case .unsupported, .truncated: return .secondaryLabelColor } diff --git a/TablePro/Resources/Themes/tablepro.dracula.json b/TablePro/Resources/Themes/tablepro.dracula.json index 70ffe0a603..1148a8f2f9 100644 --- a/TablePro/Resources/Themes/tablepro.dracula.json +++ b/TablePro/Resources/Themes/tablepro.dracula.json @@ -42,6 +42,14 @@ }, "text": "#F8F8F2" }, + "panel": { + "background": "#282A36", + "controlBackground": "#343746", + "secondaryText": "#BFC0C9", + "separator": "#44475A", + "tertiaryText": "#6272A4", + "text": "#F8F8F2" + }, "status": { "error": "#FF5555", "success": "#50FA7B", diff --git a/TablePro/Resources/Themes/tablepro.nord.json b/TablePro/Resources/Themes/tablepro.nord.json index ef58c5fe3c..7448128435 100644 --- a/TablePro/Resources/Themes/tablepro.nord.json +++ b/TablePro/Resources/Themes/tablepro.nord.json @@ -42,6 +42,14 @@ }, "text": "#D8DEE9" }, + "panel": { + "background": "#2E3440", + "controlBackground": "#3B4252", + "secondaryText": "#9DA5B4", + "separator": "#434C5E", + "tertiaryText": "#616E88", + "text": "#D8DEE9" + }, "status": { "error": "#BF616A", "success": "#A3BE8C", diff --git a/TablePro/Theme/BuiltInThemes.swift b/TablePro/Theme/BuiltInThemes.swift index 61481ad8d6..560c37bd84 100644 --- a/TablePro/Theme/BuiltInThemes.swift +++ b/TablePro/Theme/BuiltInThemes.swift @@ -39,6 +39,7 @@ internal enum BuiltInThemes { deleted: "#FF3B304D", deletedText: "#FF3B3080" ), + panel: .systemPanel, status: StatusThemeColors( success: .hex("#248A3D"), warning: .hex("#C55B00"), @@ -77,6 +78,7 @@ internal enum BuiltInThemes { deleted: "#FF453A26", deletedText: "#FF453A80" ), + panel: .systemPanel, status: StatusThemeColors( success: .hex("#32D74B"), warning: .hex("#FF9F0A"), @@ -125,3 +127,16 @@ internal enum BuiltInThemes { ) } } + +internal extension PanelThemeColors { + /// The semantic colours these surfaces already named before the theme owned them, so a default + /// theme is invisible against the unthemed app and keeps the system's contrast handling. + static let systemPanel = PanelThemeColors( + background: .system(.controlBackground), + controlBackground: .system(.textBackground), + text: .system(.label), + secondaryText: .system(.secondaryLabel), + tertiaryText: .system(.tertiaryLabel), + separator: .system(.separator) + ) +} diff --git a/TablePro/Theme/ThemeDefinition.swift b/TablePro/Theme/ThemeDefinition.swift index 4fccb5f3d5..39cddb54c6 100644 --- a/TablePro/Theme/ThemeDefinition.swift +++ b/TablePro/Theme/ThemeDefinition.swift @@ -55,6 +55,15 @@ internal struct StatusThemeColors: Equatable, Sendable { var error: ThemeColorValue } +internal struct PanelThemeColors: Equatable, Sendable { + var background: ThemeColorValue + var controlBackground: ThemeColorValue + var text: ThemeColorValue + var secondaryText: ThemeColorValue + var tertiaryText: ThemeColorValue + var separator: ThemeColorValue +} + internal struct ThemeDefinition: Identifiable, Equatable, Sendable { var id: String var name: String @@ -62,6 +71,7 @@ internal struct ThemeDefinition: Identifiable, Equatable, Sendable { var appearance: ThemeAppearance var editor: EditorThemeColors var dataGrid: DataGridThemeColors + var panel: PanelThemeColors var status: StatusThemeColors internal static let builtInPrefix = "tablepro." @@ -115,10 +125,18 @@ internal enum ThemeSlot: String, CaseIterable, Sendable { case gridDeleted = "content.dataGrid.deleted" case gridDeletedText = "content.dataGrid.deletedText" + case panelBackground = "content.panel.background" + case panelControlBackground = "content.panel.controlBackground" + case panelText = "content.panel.text" + case panelSecondaryText = "content.panel.secondaryText" + case panelTertiaryText = "content.panel.tertiaryText" + case panelSeparator = "content.panel.separator" + case statusSuccess = "content.status.success" case statusWarning = "content.status.warning" case statusError = "content.status.error" + internal var since: Int { 2 } internal var group: ThemeSlotGroup { @@ -134,6 +152,9 @@ internal enum ThemeSlot: String, CaseIterable, Sendable { .gridNullValue, .gridBoolTrue, .gridBoolFalse, .gridRowNumber, .gridModified, .gridInserted, .gridDeleted, .gridDeletedText: return .dataGrid + case .panelBackground, .panelControlBackground, .panelText, + .panelSecondaryText, .panelTertiaryText, .panelSeparator: + return .panel case .statusSuccess, .statusWarning, .statusError: return .status } @@ -178,9 +199,17 @@ internal enum ThemeSlot: String, CaseIterable, Sendable { case .gridDeleted: return \.dataGrid.deleted case .gridDeletedText: return \.dataGrid.deletedText + case .panelBackground: return \.panel.background + case .panelControlBackground: return \.panel.controlBackground + case .panelText: return \.panel.text + case .panelSecondaryText: return \.panel.secondaryText + case .panelTertiaryText: return \.panel.tertiaryText + case .panelSeparator: return \.panel.separator + case .statusSuccess: return \.status.success case .statusWarning: return \.status.warning case .statusError: return \.status.error + } } @@ -220,6 +249,12 @@ internal enum ThemeSlot: String, CaseIterable, Sendable { case .statusSuccess: return String(localized: "Success") case .statusWarning: return String(localized: "Warning") case .statusError: return String(localized: "Error") + case .panelBackground: return String(localized: "Pane Background") + case .panelControlBackground: return String(localized: "Field Background") + case .panelText: return String(localized: "Pane Text") + case .panelSecondaryText: return String(localized: "Secondary Text") + case .panelTertiaryText: return String(localized: "Tertiary Text") + case .panelSeparator: return String(localized: "Separator") } } } @@ -228,6 +263,7 @@ internal enum ThemeSlotGroup: String, CaseIterable, Sendable { case editor case syntax case dataGrid + case panel case status internal var label: String { @@ -235,6 +271,7 @@ internal enum ThemeSlotGroup: String, CaseIterable, Sendable { case .editor: return String(localized: "Editor") case .syntax: return String(localized: "Syntax Colors") case .dataGrid: return String(localized: "Data Grid") + case .panel: return String(localized: "Panels") case .status: return String(localized: "Status") } } diff --git a/TablePro/Theme/ThemedContentSurface.swift b/TablePro/Theme/ThemedContentSurface.swift new file mode 100644 index 0000000000..16998c8479 --- /dev/null +++ b/TablePro/Theme/ThemedContentSurface.swift @@ -0,0 +1,27 @@ +import SwiftUI + +/// Re-resolves `.secondary` and `.tertiary` inside a content pane to the theme's own text levels, +/// which is how 184 hierarchical foreground styles across the content surfaces follow a theme +/// without each one being rewritten. +/// +/// It never branches on the theme. `WorkspacePanes` depends on every pane builder erasing one +/// stable view identity, so an `if` here would tear down the grid, the editor's undo stack and the +/// scroll position on a theme change. It reads the engine inside `body`, so the palette it applies +/// is the current one rather than whatever was captured when the pane was built. +private struct ThemedContentSurface: ViewModifier { + func body(content: Content) -> some View { + let palette = ThemeEngine.shared.palette + + return content.foregroundStyle( + palette.color(.panelText), + palette.color(.panelSecondaryText), + palette.color(.panelTertiaryText) + ) + } +} + +internal extension View { + func themedContent() -> some View { + modifier(ThemedContentSurface()) + } +} diff --git a/TablePro/Views/Components/SQLReviewSheet.swift b/TablePro/Views/Components/SQLReviewSheet.swift index 9796e0d8b8..05e306b4df 100644 --- a/TablePro/Views/Components/SQLReviewSheet.swift +++ b/TablePro/Views/Components/SQLReviewSheet.swift @@ -223,8 +223,9 @@ struct SQLReviewSheet: View { .fixedSize(horizontal: false, vertical: true) .frame(maxWidth: .infinity, alignment: .leading) .padding(8) + .foregroundStyle(ThemeEngine.shared.palette.color(.editorText)) } - .background(Color(nsColor: .textBackgroundColor)) + .background(ThemeEngine.shared.palette.color(.editorBackground)) .clipShape(RoundedRectangle(cornerRadius: 6)) .overlay( RoundedRectangle(cornerRadius: 6) diff --git a/TablePro/Views/Editor/FileModifiedOnDiskBanner.swift b/TablePro/Views/Editor/FileModifiedOnDiskBanner.swift index e8cb0ebde2..c11b033544 100644 --- a/TablePro/Views/Editor/FileModifiedOnDiskBanner.swift +++ b/TablePro/Views/Editor/FileModifiedOnDiskBanner.swift @@ -13,7 +13,7 @@ internal struct FileModifiedOnDiskBanner: View { var body: some View { HStack(spacing: 8) { Image(systemName: "exclamationmark.triangle.fill") - .foregroundStyle(.yellow) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusWarning)) .accessibilityHidden(true) Text(String(format: String(localized: "\"%@\" was modified on disk."), fileName)) @@ -41,6 +41,6 @@ internal struct FileModifiedOnDiskBanner: View { } .padding(.horizontal, 12) .padding(.vertical, 6) - .background(.yellow.opacity(0.12)) + .background(ThemeEngine.shared.palette.color(.statusWarning).opacity(0.12)) } } diff --git a/TablePro/Views/Editor/History/HistoryDetailPane.swift b/TablePro/Views/Editor/History/HistoryDetailPane.swift index 9cc5aa74c8..30cc5ba1a0 100644 --- a/TablePro/Views/Editor/History/HistoryDetailPane.swift +++ b/TablePro/Views/Editor/History/HistoryDetailPane.swift @@ -66,7 +66,7 @@ struct HistoryDetailPane: View { if let errorMessage = entry.errorMessage { RevealedTextView(errorMessage) .font(.caption) - .foregroundStyle(.red) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusError)) .textSelection(.enabled) .fixedSize(horizontal: false, vertical: true) } diff --git a/TablePro/Views/Editor/History/HistoryRowView.swift b/TablePro/Views/Editor/History/HistoryRowView.swift index 37151159af..7bc2ac4603 100644 --- a/TablePro/Views/Editor/History/HistoryRowView.swift +++ b/TablePro/Views/Editor/History/HistoryRowView.swift @@ -71,7 +71,7 @@ struct HistoryRowView: View { .foregroundStyle(Color.secondary) } else { Image(systemName: "exclamationmark.circle.fill") - .selectionAwareTint(.red) + .selectionAwareTint(ThemeEngine.shared.palette.color(.statusError)) } } diff --git a/TablePro/Views/Editor/QueryCompletionAdapter.swift b/TablePro/Views/Editor/QueryCompletionAdapter.swift index 915c16e2c0..a87138ec7d 100644 --- a/TablePro/Views/Editor/QueryCompletionAdapter.swift +++ b/TablePro/Views/Editor/QueryCompletionAdapter.swift @@ -222,7 +222,10 @@ final class SQLSuggestionEntry: CodeSuggestionEntry { Image(systemName: item.kind.iconName) } + /// The suggestion protocol is nonisolated and the panel only ever reads this on the main + /// thread. The kind is lifted out first so the closure sends a value rather than `self`. var imageColor: Color { - Color(nsColor: item.kind.iconColor) + let kind = item.kind + return MainActor.assumeIsolated { Color(nsColor: kind.iconColor) } } } diff --git a/TablePro/Views/Editor/QueryDiagnosticsController.swift b/TablePro/Views/Editor/QueryDiagnosticsController.swift index 5f4237932f..ce15ccb4ed 100644 --- a/TablePro/Views/Editor/QueryDiagnosticsController.swift +++ b/TablePro/Views/Editor/QueryDiagnosticsController.swift @@ -75,6 +75,14 @@ final class QueryDiagnosticsController { apply(produced, in: controller) } + /// An emphasis bakes its colour into a `CAShapeLayer`, so a theme change inside one appearance + /// leaves an existing underline on the previous colour. `refresh(for:)` cannot repaint it: the + /// diagnostics themselves have not changed, so it returns early. + func reapplyColors(in controller: TextViewController) { + guard !diagnostics.isEmpty else { return } + apply(diagnostics, in: controller) + } + func clear(in controller: TextViewController?) { pendingTask?.cancel() pendingTask = nil @@ -104,8 +112,8 @@ final class QueryDiagnosticsController { private func color(for severity: QueryDiagnostic.Severity) -> NSColor { switch severity { - case .error: return .systemRed - case .warning: return .systemOrange + case .error: return ThemeEngine.shared.palette[.statusError] + case .warning: return ThemeEngine.shared.palette[.statusWarning] } } } diff --git a/TablePro/Views/Editor/QueryEditorView.swift b/TablePro/Views/Editor/QueryEditorView.swift index aa6bfd91b3..6ca5dcc3b0 100644 --- a/TablePro/Views/Editor/QueryEditorView.swift +++ b/TablePro/Views/Editor/QueryEditorView.swift @@ -97,7 +97,6 @@ struct QueryEditorView: View { .frame(minHeight: 100) .clipped() } - .background(Color(nsColor: .textBackgroundColor)) } // MARK: - Toolbar diff --git a/TablePro/Views/Editor/SQLEditorCoordinator.swift b/TablePro/Views/Editor/SQLEditorCoordinator.swift index ebbab9e1ed..4a92746fe6 100644 --- a/TablePro/Views/Editor/SQLEditorCoordinator.swift +++ b/TablePro/Views/Editor/SQLEditorCoordinator.swift @@ -27,6 +27,13 @@ final class SQLEditorCoordinator: TextViewCoordinator, TextViewDelegate { private static let languageServiceLengthLimit = EditorHighlighting.maxHighlightableCharacters @ObservationIgnored weak var controller: TextViewController? + + /// The editor configuration carries the new colours, but an emphasis already on screen baked + /// its own into a `CAShapeLayer` that nothing else repaints. + func reapplyThemeColors() { + guard let controller else { return } + diagnosticsController.reapplyColors(in: controller) + } @ObservationIgnored private lazy var diagnosticsController = QueryDiagnosticsController( databaseType: databaseType ) diff --git a/TablePro/Views/Editor/SQLEditorView.swift b/TablePro/Views/Editor/SQLEditorView.swift index ec3db9799b..022862a380 100644 --- a/TablePro/Views/Editor/SQLEditorView.swift +++ b/TablePro/Views/Editor/SQLEditorView.swift @@ -147,6 +147,7 @@ struct SQLEditorView: View { } .onReceive(AppEvents.shared.themeChanged) { _ in editorConfiguration = Self.makeConfiguration() + coordinator.reapplyThemeColors() } .onAppear { initializeEditor() diff --git a/TablePro/Views/Import/SQLCodePreview.swift b/TablePro/Views/Import/SQLCodePreview.swift index 2789b33323..669a10ca0e 100644 --- a/TablePro/Views/Import/SQLCodePreview.swift +++ b/TablePro/Views/Import/SQLCodePreview.swift @@ -19,7 +19,7 @@ struct SQLCodePreview: View { var body: some View { if text.isEmpty { - Color(nsColor: .textBackgroundColor) + ThemeEngine.shared.palette.color(.editorBackground) } else { SourceEditor( $text, diff --git a/TablePro/Views/QueryInsights/QueryInsightsActivityChart.swift b/TablePro/Views/QueryInsights/QueryInsightsActivityChart.swift index 8470242aa3..8252d6689e 100644 --- a/TablePro/Views/QueryInsights/QueryInsightsActivityChart.swift +++ b/TablePro/Views/QueryInsights/QueryInsightsActivityChart.swift @@ -53,7 +53,7 @@ struct QueryInsightsActivityChart: View { } .chartForegroundStyleScale([ Outcome.succeeded: Color.accentColor, - Outcome.failed: Color.orange, + Outcome.failed: ThemeEngine.shared.palette.color(.statusWarning), ]) .chartLegend(position: .top, alignment: .trailing, spacing: 8) .chartYAxis { diff --git a/TablePro/Views/QueryInsights/QueryInsightsGroupList.swift b/TablePro/Views/QueryInsights/QueryInsightsGroupList.swift index 8cdd2d1e60..4f3e392275 100644 --- a/TablePro/Views/QueryInsights/QueryInsightsGroupList.swift +++ b/TablePro/Views/QueryInsights/QueryInsightsGroupList.swift @@ -48,7 +48,7 @@ struct QueryInsightsGroupList: View { if let error = group.latestErrorMessage, case .failures = metric { RevealedTextView(error) .font(.caption) - .foregroundStyle(.orange) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusWarning)) .lineLimit(2) } } @@ -86,7 +86,7 @@ struct QueryInsightsGroupList: View { private func headlineTint(_ group: QueryInsightsGroup) -> Color { switch metric { - case .failures: return .orange + case .failures: return ThemeEngine.shared.palette.color(.statusWarning) case .duration: return .primary case .callCount: return .primary } @@ -160,7 +160,7 @@ struct QueryInsightsRegressionList: View { .font(.system(.callout, design: .monospaced)) .fontWeight(.medium) .monospacedDigit() - .foregroundStyle(.orange) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusWarning)) .frame(minWidth: 76, alignment: .trailing) VStack(alignment: .leading, spacing: 3) { diff --git a/TablePro/Views/QueryInsights/QueryInsightsSummaryBar.swift b/TablePro/Views/QueryInsights/QueryInsightsSummaryBar.swift index 24f099283c..c7d09b1c09 100644 --- a/TablePro/Views/QueryInsights/QueryInsightsSummaryBar.swift +++ b/TablePro/Views/QueryInsights/QueryInsightsSummaryBar.swift @@ -30,7 +30,7 @@ struct QueryInsightsSummaryBar: View { totals.totalCount.formatted() ), systemImage: "exclamationmark.triangle", - tint: totals.failedCount > 0 ? .orange : .secondary + tint: totals.failedCount > 0 ? ThemeEngine.shared.palette.color(.statusWarning) : .secondary ) metric( label: String(localized: "Average"), diff --git a/TablePro/Views/Results/ArrayValueEditorView.swift b/TablePro/Views/Results/ArrayValueEditorView.swift index c720bcff49..03d3df7a12 100644 --- a/TablePro/Views/Results/ArrayValueEditorView.swift +++ b/TablePro/Views/Results/ArrayValueEditorView.swift @@ -162,7 +162,7 @@ struct ArrayValueEditorView: View { .pickerStyle(.menu) if ArrayValueEditorModel.isDriftedValue(row.element, allowedValues: allowedValues) { Image(systemName: "exclamationmark.triangle") - .foregroundStyle(.orange) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusWarning)) .help(Text("This value is not one of the type's current labels")) } } diff --git a/TablePro/Views/Results/ColumnValueFilterPopover.swift b/TablePro/Views/Results/ColumnValueFilterPopover.swift index 007afaec75..f6159949d5 100644 --- a/TablePro/Views/Results/ColumnValueFilterPopover.swift +++ b/TablePro/Views/Results/ColumnValueFilterPopover.swift @@ -102,7 +102,7 @@ struct ColumnValueFilterPopover: View { Text(label(for: value)) .lineLimit(1) .truncationMode(.tail) - .foregroundStyle(value.isNull ? Color.secondary : Color.primary) + .foregroundStyle(value.isNull ? ThemeEngine.shared.palette.color(.gridNullValue) : Color.primary) Spacer(minLength: 8) Text("\(value.count)") .font(.callout.monospacedDigit()) diff --git a/TablePro/Views/Results/DataGridCoordinator.swift b/TablePro/Views/Results/DataGridCoordinator.swift index 7b592681e1..08466bc598 100644 --- a/TablePro/Views/Results/DataGridCoordinator.swift +++ b/TablePro/Views/Results/DataGridCoordinator.swift @@ -626,6 +626,7 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData /// the width was already going stale here. self?.resizeRowNumberColumnForCurrentRange() self?.repaintRowGutter() + self?.selectionController.overlay?.needsDisplay = true } } diff --git a/TablePro/Views/Results/ForeignKeyPickerView.swift b/TablePro/Views/Results/ForeignKeyPickerView.swift index 85b6f64b8c..2d2e5b7211 100644 --- a/TablePro/Views/Results/ForeignKeyPickerView.swift +++ b/TablePro/Views/Results/ForeignKeyPickerView.swift @@ -96,7 +96,7 @@ struct ForeignKeyPickerView: View { private var content: some View { if let errorMessage { RevealedTextView(errorMessage) - .foregroundStyle(.red) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusError)) .font(.callout) .frame(maxWidth: .infinity, alignment: .leading) .padding(10) diff --git a/TablePro/Views/Results/ForeignKeyPreviewView.swift b/TablePro/Views/Results/ForeignKeyPreviewView.swift index 4dad919716..e1f52d8de8 100644 --- a/TablePro/Views/Results/ForeignKeyPreviewView.swift +++ b/TablePro/Views/Results/ForeignKeyPreviewView.swift @@ -104,7 +104,7 @@ struct ForeignKeyPreviewView: View { .frame(height: 60) } else if let errorMessage { RevealedTextView(errorMessage) - .foregroundStyle(.red) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusError)) .font(.callout) .padding(10) } else if values.isEmpty { diff --git a/TablePro/Views/Results/HexEditorContentView.swift b/TablePro/Views/Results/HexEditorContentView.swift index a66ae62a3b..b24a121953 100644 --- a/TablePro/Views/Results/HexEditorContentView.swift +++ b/TablePro/Views/Results/HexEditorContentView.swift @@ -99,11 +99,11 @@ struct HexEditorBody: View { if sourceIsTruncated || isTruncated { Text(String(localized: "Truncated, read only")) .font(.caption) - .foregroundStyle(.orange) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusWarning)) } else if !isValid, !editableHex.isEmpty { Text(String(localized: "Invalid hex")) .font(.caption) - .foregroundStyle(.red) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusError)) } Spacer() @@ -227,8 +227,8 @@ private struct HexDumpDisplayView: NSViewRepresentable { textView.isSelectable = true textView.font = font textView.textContainerInset = NSSize(width: 8, height: 8) - textView.backgroundColor = NSColor.textBackgroundColor - textView.textColor = NSColor.secondaryLabelColor + textView.backgroundColor = ThemeEngine.shared.palette[.panelControlBackground] + textView.textColor = ThemeEngine.shared.palette[.panelSecondaryText] textView.string = text return scrollView @@ -239,6 +239,8 @@ private struct HexDumpDisplayView: NSViewRepresentable { if textView.font != font { textView.font = font } + textView.backgroundColor = ThemeEngine.shared.palette[.panelControlBackground] + textView.textColor = ThemeEngine.shared.palette[.panelSecondaryText] if textView.string != text { textView.string = text } @@ -265,8 +267,8 @@ private struct HexInputTextView: NSViewRepresentable { textView.isSelectable = true textView.font = font textView.textContainerInset = NSSize(width: 8, height: 8) - textView.backgroundColor = NSColor.textBackgroundColor - textView.textColor = NSColor.labelColor + textView.backgroundColor = ThemeEngine.shared.palette[.panelControlBackground] + textView.textColor = ThemeEngine.shared.palette[.panelText] textView.isAutomaticQuoteSubstitutionEnabled = false textView.isAutomaticDashSubstitutionEnabled = false textView.isAutomaticTextReplacementEnabled = false @@ -288,6 +290,8 @@ private struct HexInputTextView: NSViewRepresentable { if textView.font != font { textView.font = font } + textView.backgroundColor = ThemeEngine.shared.palette[.panelControlBackground] + textView.textColor = ThemeEngine.shared.palette[.panelText] if textView.string != text, !context.coordinator.isUpdating { textView.string = text } diff --git a/TablePro/Views/Results/InlineErrorBanner.swift b/TablePro/Views/Results/InlineErrorBanner.swift index fd174460de..5c604273ef 100644 --- a/TablePro/Views/Results/InlineErrorBanner.swift +++ b/TablePro/Views/Results/InlineErrorBanner.swift @@ -21,7 +21,7 @@ struct InlineErrorBanner: View { var body: some View { HStack(alignment: .top, spacing: 8) { Image(systemName: "exclamationmark.triangle.fill") - .foregroundStyle(.red) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusError)) ScrollView(.vertical) { RevealedTextView(message) .font(.subheadline) @@ -63,7 +63,7 @@ struct InlineErrorBanner: View { } .padding(.horizontal, 12) .padding(.vertical, 8) - .background(.red.opacity(0.08)) + .background(ThemeEngine.shared.palette.color(.statusError).opacity(0.08)) } } diff --git a/TablePro/Views/Results/JSONTreeView.swift b/TablePro/Views/Results/JSONTreeView.swift index 049e99f901..332e26dc54 100644 --- a/TablePro/Views/Results/JSONTreeView.swift +++ b/TablePro/Views/Results/JSONTreeView.swift @@ -30,7 +30,7 @@ private struct JSONTreeRowView: View { if let key = node.key { Text(key) .font(ThemeEngine.shared.valueFontEmphasizedSwiftUI) - .foregroundStyle(.blue) + .foregroundStyle(ThemeEngine.shared.palette.color(.syntaxKeyword)) .lineLimit(1) Text(":") .foregroundStyle(.secondary) diff --git a/TablePro/Views/Results/PhpTreeView.swift b/TablePro/Views/Results/PhpTreeView.swift index 7722b604a0..efdb111ab4 100644 --- a/TablePro/Views/Results/PhpTreeView.swift +++ b/TablePro/Views/Results/PhpTreeView.swift @@ -30,7 +30,7 @@ private struct PhpTreeRowView: View { if let key = node.key { Text(key) .font(ThemeEngine.shared.valueFontEmphasizedSwiftUI) - .foregroundStyle(.blue) + .foregroundStyle(ThemeEngine.shared.palette.color(.syntaxKeyword)) .lineLimit(1) if let badge = node.visibilityBadge { Text(badge) diff --git a/TablePro/Views/Results/ResultChartCanvas.swift b/TablePro/Views/Results/ResultChartCanvas.swift index 799b3e871f..4632248492 100644 --- a/TablePro/Views/Results/ResultChartCanvas.swift +++ b/TablePro/Views/Results/ResultChartCanvas.swift @@ -41,27 +41,27 @@ struct ResultChartCanvas: View { .chartYAxis { AxisMarks(position: .leading) { AxisGridLine(stroke: StrokeStyle(lineWidth: 0.5)) - .foregroundStyle(Color(nsColor: .separatorColor).opacity(0.55)) + .foregroundStyle(ThemeEngine.shared.palette.color(.panelSeparator).opacity(0.55)) AxisTick(stroke: StrokeStyle(lineWidth: 0.5)) - .foregroundStyle(Color(nsColor: .separatorColor)) + .foregroundStyle(ThemeEngine.shared.palette.color(.panelSeparator)) AxisValueLabel() - .foregroundStyle(Color(nsColor: .secondaryLabelColor)) + .foregroundStyle(ThemeEngine.shared.palette.color(.panelSecondaryText)) } } .chartXAxis { AxisMarks(values: .automatic(desiredCount: 7)) { AxisGridLine(stroke: StrokeStyle(lineWidth: 0.5)) - .foregroundStyle(Color(nsColor: .separatorColor).opacity(0.55)) + .foregroundStyle(ThemeEngine.shared.palette.color(.panelSeparator).opacity(0.55)) AxisTick(stroke: StrokeStyle(lineWidth: 0.5)) - .foregroundStyle(Color(nsColor: .separatorColor)) + .foregroundStyle(ThemeEngine.shared.palette.color(.panelSeparator)) AxisValueLabel(collisionResolution: .greedy(minimumSpacing: 8)) - .foregroundStyle(Color(nsColor: .secondaryLabelColor)) + .foregroundStyle(ThemeEngine.shared.palette.color(.panelSecondaryText)) } } .chartPlotStyle { plotArea in plotArea .background( - Color(nsColor: .controlBackgroundColor).opacity(0.45), + ThemeEngine.shared.palette.color(.panelBackground).opacity(0.45), in: .rect(cornerRadius: 8) ) } diff --git a/TablePro/Views/Results/ResultSuccessView.swift b/TablePro/Views/Results/ResultSuccessView.swift index 3954698442..1488dcae13 100644 --- a/TablePro/Views/Results/ResultSuccessView.swift +++ b/TablePro/Views/Results/ResultSuccessView.swift @@ -28,7 +28,7 @@ struct ResultSuccessView: View { Spacer() Image(systemName: "checkmark.circle.fill") .font(.largeTitle) - .foregroundStyle(.green) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusSuccess)) Text(primaryMessage) .font(.body) if let time = executionTime { diff --git a/TablePro/Views/Results/Selection/GridSelectionOverlay.swift b/TablePro/Views/Results/Selection/GridSelectionOverlay.swift index bd1cd85a65..f12f6d0709 100644 --- a/TablePro/Views/Results/Selection/GridSelectionOverlay.swift +++ b/TablePro/Views/Results/Selection/GridSelectionOverlay.swift @@ -37,7 +37,7 @@ final class GridSelectionOverlay: NSView { let totalRows = tableView.numberOfRows let editingCell = activeOverlayCell(in: coordinator) - NSColor.selectedContentBackgroundColor.withAlphaComponent(Self.borderAlpha).setStroke() + ThemeEngine.shared.palette[.gridSelection].withAlphaComponent(Self.borderAlpha).setStroke() for rect in selection.rectangles { guard let frame = frame(for: rect, in: tableView, coordinator: coordinator) else { continue } guard frame.intersects(dirtyRect) else { continue } diff --git a/TablePro/Views/RowInspector/FieldEditors/BlobHexEditorView.swift b/TablePro/Views/RowInspector/FieldEditors/BlobHexEditorView.swift index d2f150327d..20ab3e650e 100644 --- a/TablePro/Views/RowInspector/FieldEditors/BlobHexEditorView.swift +++ b/TablePro/Views/RowInspector/FieldEditors/BlobHexEditorView.swift @@ -94,11 +94,11 @@ internal struct BlobHexEditorView: View { if isTruncated { Text("Truncated, read only") .font(.caption2) - .foregroundStyle(.orange) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusWarning)) } else if BlobFormattingService.shared.parseHex(hexEditText) == nil, !hexEditText.isEmpty { Text("Invalid hex") .font(.caption2) - .foregroundStyle(.red) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusError)) } } } diff --git a/TablePro/Views/RowInspector/FieldEditors/FieldEditorContent.swift b/TablePro/Views/RowInspector/FieldEditors/FieldEditorContent.swift index affe056c61..3f19742212 100644 --- a/TablePro/Views/RowInspector/FieldEditors/FieldEditorContent.swift +++ b/TablePro/Views/RowInspector/FieldEditors/FieldEditorContent.swift @@ -106,7 +106,7 @@ internal struct PendingStatePill: View { .frame(maxWidth: .infinity, minHeight: minHeight, alignment: .topLeading) .padding(.horizontal, 6) .padding(.vertical, 3) - .background(Color(nsColor: .textBackgroundColor), in: RoundedRectangle(cornerRadius: 5)) - .overlay(RoundedRectangle(cornerRadius: 5).strokeBorder(Color(nsColor: .separatorColor))) + .background(ThemeEngine.shared.palette.color(.panelControlBackground), in: RoundedRectangle(cornerRadius: 5)) + .overlay(RoundedRectangle(cornerRadius: 5).strokeBorder(ThemeEngine.shared.palette.color(.panelSeparator))) } } diff --git a/TablePro/Views/RowInspector/FieldEditors/ImageFieldView.swift b/TablePro/Views/RowInspector/FieldEditors/ImageFieldView.swift index 369a9da12c..d0c4bfbe0b 100644 --- a/TablePro/Views/RowInspector/FieldEditors/ImageFieldView.swift +++ b/TablePro/Views/RowInspector/FieldEditors/ImageFieldView.swift @@ -34,7 +34,7 @@ internal struct ImageFieldView: View { ) .frame(height: 220) .clipShape(RoundedRectangle(cornerRadius: 5)) - .overlay(RoundedRectangle(cornerRadius: 5).strokeBorder(Color(nsColor: .separatorColor))) + .overlay(RoundedRectangle(cornerRadius: 5).strokeBorder(ThemeEngine.shared.palette.color(.panelSeparator))) .task(id: context.value.wrappedValue) { data = context.value.wrappedValue.storedBytes } diff --git a/TablePro/Views/RowInspector/FieldEditors/JsonEditorView.swift b/TablePro/Views/RowInspector/FieldEditors/JsonEditorView.swift index 65428a310f..c4da8a40f0 100644 --- a/TablePro/Views/RowInspector/FieldEditors/JsonEditorView.swift +++ b/TablePro/Views/RowInspector/FieldEditors/JsonEditorView.swift @@ -29,7 +29,7 @@ internal struct JsonEditorView: View { ) { JSONCodeEditor(text: $displayText, isEditable: !context.isReadOnly) .clipShape(RoundedRectangle(cornerRadius: 5)) - .overlay(RoundedRectangle(cornerRadius: 5).strokeBorder(Color(nsColor: .separatorColor))) + .overlay(RoundedRectangle(cornerRadius: 5).strokeBorder(ThemeEngine.shared.palette.color(.panelSeparator))) .overlay(alignment: .bottomTrailing) { actionButtons } } .onChange(of: displayText) { propagateEdit() } diff --git a/TablePro/Views/RowInspector/FieldEditors/MultiLineEditorView.swift b/TablePro/Views/RowInspector/FieldEditors/MultiLineEditorView.swift index e2b38f2a64..f0a875d36f 100644 --- a/TablePro/Views/RowInspector/FieldEditors/MultiLineEditorView.swift +++ b/TablePro/Views/RowInspector/FieldEditors/MultiLineEditorView.swift @@ -26,7 +26,7 @@ internal struct MultiLineEditorView: View { movesFocusOnTab: true ) .clipShape(RoundedRectangle(cornerRadius: 5)) - .overlay(RoundedRectangle(cornerRadius: 5).strokeBorder(Color(nsColor: .separatorColor))) + .overlay(RoundedRectangle(cornerRadius: 5).strokeBorder(ThemeEngine.shared.palette.color(.panelSeparator))) .overlay(alignment: .topLeading) { placeholder } .overlay(alignment: .bottomTrailing) { popOutButton } } diff --git a/TablePro/Views/RowInspector/FieldEditors/PhpSerializedFieldView.swift b/TablePro/Views/RowInspector/FieldEditors/PhpSerializedFieldView.swift index cf499ad52e..0d919505b1 100644 --- a/TablePro/Views/RowInspector/FieldEditors/PhpSerializedFieldView.swift +++ b/TablePro/Views/RowInspector/FieldEditors/PhpSerializedFieldView.swift @@ -18,6 +18,6 @@ internal struct PhpSerializedFieldView: View { .frame(height: isExpanded ? ResizableFieldMetrics.expandedHeight : nil) .frame(minHeight: isExpanded ? nil : 80, maxHeight: isExpanded ? nil : 200) .clipShape(RoundedRectangle(cornerRadius: 5)) - .overlay(RoundedRectangle(cornerRadius: 5).strokeBorder(Color(nsColor: .separatorColor))) + .overlay(RoundedRectangle(cornerRadius: 5).strokeBorder(ThemeEngine.shared.palette.color(.panelSeparator))) } } diff --git a/TablePro/Views/RowInspector/FieldEditors/ResizableEditorContainer.swift b/TablePro/Views/RowInspector/FieldEditors/ResizableEditorContainer.swift index 6438601394..ad065ee488 100644 --- a/TablePro/Views/RowInspector/FieldEditors/ResizableEditorContainer.swift +++ b/TablePro/Views/RowInspector/FieldEditors/ResizableEditorContainer.swift @@ -39,7 +39,7 @@ internal struct ResizableEditorContainer: View { private var resizeHandle: some View { Capsule() - .fill(Color(nsColor: .tertiaryLabelColor)) + .fill(ThemeEngine.shared.palette.color(.panelTertiaryText)) .frame(width: 26, height: 4) .opacity(isHandleHovered ? 1 : 0.5) .frame(maxWidth: .infinity, minHeight: 11) diff --git a/TablePro/Views/RowInspector/FieldEditors/SingleLineEditorView.swift b/TablePro/Views/RowInspector/FieldEditors/SingleLineEditorView.swift index f960266bb5..d6abbbe425 100644 --- a/TablePro/Views/RowInspector/FieldEditors/SingleLineEditorView.swift +++ b/TablePro/Views/RowInspector/FieldEditors/SingleLineEditorView.swift @@ -29,7 +29,7 @@ internal struct SingleLineEditorView: View { .frame(maxWidth: .infinity, minHeight: 16, alignment: .leading) .padding(.horizontal, 6) .padding(.vertical, 4) - .background(Color(nsColor: .textBackgroundColor), in: RoundedRectangle(cornerRadius: 5)) - .overlay(RoundedRectangle(cornerRadius: 5).strokeBorder(Color(nsColor: .separatorColor))) + .background(ThemeEngine.shared.palette.color(.panelControlBackground), in: RoundedRectangle(cornerRadius: 5)) + .overlay(RoundedRectangle(cornerRadius: 5).strokeBorder(ThemeEngine.shared.palette.color(.panelSeparator))) } } diff --git a/TablePro/Views/RowInspector/JSON/JSONRowInspectorView.swift b/TablePro/Views/RowInspector/JSON/JSONRowInspectorView.swift index 94ec4eadd6..d6926bc4da 100644 --- a/TablePro/Views/RowInspector/JSON/JSONRowInspectorView.swift +++ b/TablePro/Views/RowInspector/JSON/JSONRowInspectorView.swift @@ -66,7 +66,7 @@ struct JSONRowInspectorView: View { ) .overlay( RoundedRectangle(cornerRadius: 6) - .strokeBorder(Color.red.opacity(0.6)) + .strokeBorder(ThemeEngine.shared.palette.color(.statusError).opacity(0.6)) .opacity(viewModel.isFilterInvalid ? 1 : 0) ) .help(viewModel.isFilterInvalid diff --git a/TablePro/Views/ServerDashboard/MetricsBarView.swift b/TablePro/Views/ServerDashboard/MetricsBarView.swift index 89f4c503d6..61d9839754 100644 --- a/TablePro/Views/ServerDashboard/MetricsBarView.swift +++ b/TablePro/Views/ServerDashboard/MetricsBarView.swift @@ -17,7 +17,7 @@ struct MetricsBarView: View { Image(systemName: "exclamationmark.triangle") } .font(.caption) - .foregroundStyle(.red) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusError)) } } .padding(.horizontal, 12) diff --git a/TablePro/Views/ServerDashboard/SessionsTableView.swift b/TablePro/Views/ServerDashboard/SessionsTableView.swift index 93300d3e49..e211f48cb8 100644 --- a/TablePro/Views/ServerDashboard/SessionsTableView.swift +++ b/TablePro/Views/ServerDashboard/SessionsTableView.swift @@ -19,7 +19,7 @@ struct SessionsTableView: View { Image(systemName: "exclamationmark.triangle") } .font(.caption) - .foregroundStyle(.red) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusError)) } } .padding(.horizontal, 12) @@ -86,10 +86,10 @@ struct SessionsTableView: View { private func stateColor(_ state: String) -> Color { switch state.lowercased() { - case "active", "running": return .green + case "active", "running": return ThemeEngine.shared.palette.color(.statusSuccess) case "idle": return .secondary - case "idle in transaction": return .orange - case "waiting", "locked": return .red + case "idle in transaction": return ThemeEngine.shared.palette.color(.statusWarning) + case "waiting", "locked": return ThemeEngine.shared.palette.color(.statusError) default: return .primary } } diff --git a/TablePro/Views/ServerDashboard/SlowQueryListView.swift b/TablePro/Views/ServerDashboard/SlowQueryListView.swift index 5c2358ef5e..12aa31a35d 100644 --- a/TablePro/Views/ServerDashboard/SlowQueryListView.swift +++ b/TablePro/Views/ServerDashboard/SlowQueryListView.swift @@ -19,7 +19,7 @@ struct SlowQueryListView: View { Image(systemName: "exclamationmark.triangle.fill") } .font(.caption) - .foregroundStyle(.orange) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusWarning)) } } .padding(.horizontal, 12) @@ -49,7 +49,7 @@ struct SlowQueryListView: View { Text(query.duration) .font(.system(.caption, design: .monospaced)) .monospacedDigit() - .foregroundStyle(.orange) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusWarning)) .frame(width: 50, alignment: .trailing) VStack(alignment: .leading, spacing: 2) { diff --git a/TablePro/Views/Structure/ClickHousePartsView.swift b/TablePro/Views/Structure/ClickHousePartsView.swift index 18874f9dbb..7b50340c39 100644 --- a/TablePro/Views/Structure/ClickHousePartsView.swift +++ b/TablePro/Views/Structure/ClickHousePartsView.swift @@ -30,7 +30,7 @@ struct ClickHousePartsView: View { VStack(spacing: 8) { Image(systemName: "exclamationmark.triangle") .font(.largeTitle) - .foregroundStyle(.orange) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusWarning)) .accessibilityHidden(true) RevealedTextView(error) .foregroundStyle(.secondary) @@ -99,7 +99,7 @@ struct ClickHousePartsView: View { .width(min: 100, ideal: 160) TableColumn("Active") { part in Image(systemName: part.active ? "checkmark.circle.fill" : "xmark.circle") - .foregroundStyle(part.active ? .green : .secondary) + .foregroundStyle(part.active ? ThemeEngine.shared.palette.color(.statusSuccess) : .secondary) } .width(min: 50, ideal: 60) } diff --git a/TablePro/Views/Structure/CreateTableView.swift b/TablePro/Views/Structure/CreateTableView.swift index 1131978c7c..b458e3ed4f 100644 --- a/TablePro/Views/Structure/CreateTableView.swift +++ b/TablePro/Views/Structure/CreateTableView.swift @@ -178,7 +178,7 @@ struct CreateTableView: View { Spacer() } .padding() - .background(Color(nsColor: .controlBackgroundColor)) + .background(ThemeEngine.shared.palette.color(.panelBackground)) .onChange(of: draft.tableOptions.charset) { _, newCharset in if let first = CreateTableOptions.collations[newCharset]?.first { draft.tableOptions.collation = first diff --git a/TablePro/Views/Structure/DDLTextView.swift b/TablePro/Views/Structure/DDLTextView.swift index 3f16dd064c..858f8492e9 100644 --- a/TablePro/Views/Structure/DDLTextView.swift +++ b/TablePro/Views/Structure/DDLTextView.swift @@ -32,7 +32,7 @@ struct DDLTextView: View { var body: some View { if ddl.isEmpty { - Color(nsColor: .textBackgroundColor) + ThemeEngine.shared.palette.color(.editorBackground) } else { SourceEditor( $text, diff --git a/TablePro/Views/Structure/TableStructureView+Schema.swift b/TablePro/Views/Structure/TableStructureView+Schema.swift index ea56cc249c..1a9c4c9fec 100644 --- a/TablePro/Views/Structure/TableStructureView+Schema.swift +++ b/TablePro/Views/Structure/TableStructureView+Schema.swift @@ -110,7 +110,7 @@ extension TableStructureView { if showCopyConfirmation { HStack { Image(systemName: "checkmark.circle.fill") - .foregroundStyle(.green) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusSuccess)) Text("Copied!") } .transition(.opacity) diff --git a/TablePro/Views/Structure/TableStructureView.swift b/TablePro/Views/Structure/TableStructureView.swift index a768c3365e..c81ba75f00 100644 --- a/TablePro/Views/Structure/TableStructureView.swift +++ b/TablePro/Views/Structure/TableStructureView.swift @@ -527,7 +527,7 @@ struct TableStructureView: View { VStack(spacing: 8) { Image(systemName: "exclamationmark.triangle") .font(.largeTitle) - .foregroundStyle(.orange) + .foregroundStyle(ThemeEngine.shared.palette.color(.statusWarning)) .accessibilityHidden(true) RevealedTextView(message) .foregroundStyle(.secondary) diff --git a/TablePro/Views/Structure/TriggerDetailView.swift b/TablePro/Views/Structure/TriggerDetailView.swift index 54aae67b7e..ca27c0b2ef 100644 --- a/TablePro/Views/Structure/TriggerDetailView.swift +++ b/TablePro/Views/Structure/TriggerDetailView.swift @@ -252,7 +252,7 @@ private struct TriggerListPane: View { private func enabledIndicator(_ trigger: TriggerInfo) -> some View { if let enabled = trigger.enabled { Image(systemName: enabled ? "checkmark.circle.fill" : "xmark.circle") - .foregroundStyle(enabled ? Color.green : Color.secondary) + .foregroundStyle(enabled ? ThemeEngine.shared.palette.color(.statusSuccess) : Color.secondary) .accessibilityLabel(enabled ? String(localized: "Enabled") : String(localized: "Disabled")) } } @@ -274,7 +274,7 @@ private struct TriggerDetailPane: View { onOpenInEditor: { onOpenInEditor(trigger) } ) } else { - Color(nsColor: .textBackgroundColor) + ThemeEngine.shared.palette.color(.editorBackground) } } diff --git a/docs/customization/appearance.mdx b/docs/customization/appearance.mdx index 97ae4631e6..e85b74eb77 100644 --- a/docs/customization/appearance.mdx +++ b/docs/customization/appearance.mdx @@ -39,6 +39,7 @@ Custom themes get color wells here. A built-in or registry theme shows a lock an | Editor | Background, text, cursor, selection, current line, current statement, line number, invisibles | | Syntax Colors | Keyword, string, number, comment, NULL, operator, function, type | | Data Grid | Background, text, alternate row, header background, header text, grid line, selection, selected text, inactive selection, focus border, NULL value, bool true/false, row number, modified/inserted/deleted rows, deleted text | +| Panels | Pane background, field background, pane text, secondary text, tertiary text, separator | | Status | Success, warning, error | A slot holds either a hex color or the name of a macOS system color. Default Light and Default Dark keep the data grid surrounds on system colors, which is why an untouched theme follows your system accent and its Increase Contrast setting. Right-click a well that a built-in leaves on a system color to put that system color back. @@ -54,6 +55,7 @@ A theme is one JSON file. **Export…** in the gear menu writes every color the | `appearance` | `light` or `dark`. Decides which slot lists the theme | | `content.editor` | Editor colors, with syntax colors nested under `syntax` | | `content.dataGrid` | Grid colors | +| `content.panel` | Colors of the panes around the editor and the grid: results, inspector, structure, compare, query plan | | `content.status` | Success, warning and error colors | ```json From d4273f6b3ca9c1be141684efc22a178d3d084bfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Nam=20Long?= Date: Sat, 12 Sep 2026 03:27:32 +0000 Subject: [PATCH 47/54] fix(ios): share PostgreSQL catalog quoting with the iOS driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nguyễn Nam Long --- CHANGELOG.md | 1 + .../Tests/TableProModelsTests/DatabaseTypeTests.swift | 2 +- .../TableProMobile/Drivers/PostgreSQLDriver.swift | 8 ++------ .../Drivers/PostgreSQLForeignKeyQueryTests.swift | 7 +++++++ TableProMobile/project.yml | 2 ++ 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0619f5ff13..322be80791 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- iOS PostgreSQL foreign-key listing after catalog quoting moved to the shared helper. (#2726) - Empty Columns tab and no autocomplete for PostgreSQL materialized views. (#2726) - Discard restoring a different row than the one edited under a column value filter. - Add Row under a column value filter selecting and opening the wrong row for editing. diff --git a/Packages/TableProCore/Tests/TableProModelsTests/DatabaseTypeTests.swift b/Packages/TableProCore/Tests/TableProModelsTests/DatabaseTypeTests.swift index 445023bb80..26245ef7e2 100644 --- a/Packages/TableProCore/Tests/TableProModelsTests/DatabaseTypeTests.swift +++ b/Packages/TableProCore/Tests/TableProModelsTests/DatabaseTypeTests.swift @@ -61,7 +61,7 @@ struct DatabaseTypeTests { @Test("allKnownTypes contains all expected types") func allKnownTypesComplete() { - #expect(DatabaseType.allKnownTypes.count == 29) + #expect(DatabaseType.allKnownTypes.count == 30) #expect(DatabaseType.allKnownTypes.contains(.mysql)) #expect(DatabaseType.allKnownTypes.contains(.tidb)) #expect(DatabaseType.allKnownTypes.contains(.databend)) diff --git a/TableProMobile/TableProMobile/Drivers/PostgreSQLDriver.swift b/TableProMobile/TableProMobile/Drivers/PostgreSQLDriver.swift index 58945a8619..e11f97681f 100644 --- a/TableProMobile/TableProMobile/Drivers/PostgreSQLDriver.swift +++ b/TableProMobile/TableProMobile/Drivers/PostgreSQLDriver.swift @@ -312,18 +312,14 @@ nonisolated final class PostgreSQLDriver: DatabaseDriver, @unchecked Sendable { static func foreignKeysQuery(schema: String, table: String, serverVersionNumber: Int32) -> String { PostgreSQLCatalogForeignKeys.query( - schemaLiteral: literal(schema), - tableLiteral: literal(table), + schema: schema, + table: table, excludesPartitionClones: PostgreSQLCatalogForeignKeys.excludesPartitionClones( serverVersionNumber: serverVersionNumber ) ) } - private static func literal(_ value: String) -> String { - "'\(value.replacingOccurrences(of: "'", with: "''"))'" - } - func fetchDatabases() async throws -> [String] { let raw = try await actor.execute( "SELECT datname FROM pg_database WHERE datistemplate = false ORDER BY datname" diff --git a/TableProMobile/TableProMobileTests/Drivers/PostgreSQLForeignKeyQueryTests.swift b/TableProMobile/TableProMobileTests/Drivers/PostgreSQLForeignKeyQueryTests.swift index 240af440e8..73a17cd9cc 100644 --- a/TableProMobile/TableProMobileTests/Drivers/PostgreSQLForeignKeyQueryTests.swift +++ b/TableProMobile/TableProMobileTests/Drivers/PostgreSQLForeignKeyQueryTests.swift @@ -49,6 +49,13 @@ struct PostgreSQLForeignKeyQueryTests { #expect(query.contains("cl.relname = 'it''s'")) } + @Test("a backslash in the schema name is quoted as an E-string") + func escapesBackslash() { + let query = PostgreSQLDriver.foreignKeysQuery(schema: #"a\b"#, table: "t", serverVersionNumber: 170_011) + + #expect(query.contains(#"ns.nspname = E'a\\b'"#)) + } + @Test("a Redshift server never receives the PostgreSQL 11 clone filter") func redshiftKeepsPortableQuery() { let redshift = PostgreSQLDriver.foreignKeysQuery(schema: "public", table: "t", serverVersionNumber: 80_002) diff --git a/TableProMobile/project.yml b/TableProMobile/project.yml index 5958c8994f..132ef22846 100644 --- a/TableProMobile/project.yml +++ b/TableProMobile/project.yml @@ -64,7 +64,9 @@ targets: - ../Plugins/MySQLDriverPlugin/MySQLLatin1.swift - ../Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift # Foreign key catalog read the iOS PostgreSQL driver shares with the macOS plugin. + - ../Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift - ../Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogForeignKeys.swift + - ../Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift # libpq COPY handling the iOS PostgreSQL driver shares with the macOS plugin. - ../Plugins/PostgreSQLDriverPlugin/LibPQPendingResultDrain.swift - ../Plugins/PostgreSQLDriverPlugin/LibPQCopyState.swift From 09530ed4c2f8458f6583506f36d644480a099185 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 10:29:10 +0700 Subject: [PATCH 48/54] build(ios): compile the PostgreSQL literal quoting the shared foreign key read calls (#2783) --- TableProMobile/project.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/TableProMobile/project.yml b/TableProMobile/project.yml index 5958c8994f..5dcabf0e07 100644 --- a/TableProMobile/project.yml +++ b/TableProMobile/project.yml @@ -63,8 +63,12 @@ targets: - ../Plugins/MySQLDriverPlugin/MySQLConnectionEncoding.swift - ../Plugins/MySQLDriverPlugin/MySQLLatin1.swift - ../Plugins/MySQLDriverPlugin/MySQLServerFlavor.swift - # Foreign key catalog read the iOS PostgreSQL driver shares with the macOS plugin. + # Foreign key catalog read the iOS PostgreSQL driver shares with the macOS plugin, plus the + # single owner of the plugin's literal quoting that it builds its SQL with, and the version + # gate that owner projects against. - ../Plugins/PostgreSQLDriverPlugin/PostgreSQLCatalogForeignKeys.swift + - ../Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift + - ../Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift # libpq COPY handling the iOS PostgreSQL driver shares with the macOS plugin. - ../Plugins/PostgreSQLDriverPlugin/LibPQPendingResultDrain.swift - ../Plugins/PostgreSQLDriverPlugin/LibPQCopyState.swift From 4376381b5886a92793ebb600da2aed4ba53f9995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 10:49:57 +0700 Subject: [PATCH 49/54] fix(datagrid): clip the row-number strip to the grid's scroll view (#2784) --- CHANGELOG.md | 1 + TablePro/Views/Results/DataGridView.swift | 16 +++- .../DataGridRowNumberRenderingTests.swift | 92 +++++++++++++++++-- 3 files changed, 99 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6e23aa622..4ae84389db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Row numbers and their divider painted over the find bar, the filter panel and the result tab bar. - Empty Columns tab and no autocomplete for PostgreSQL materialized views. (#2726) - Discard restoring a different row than the one edited under a column value filter. - Add Row under a column value filter selecting and opening the wrong row for editing. diff --git a/TablePro/Views/Results/DataGridView.swift b/TablePro/Views/Results/DataGridView.swift index 5fbdbd772b..a57c0e08da 100644 --- a/TablePro/Views/Results/DataGridView.swift +++ b/TablePro/Views/Results/DataGridView.swift @@ -208,7 +208,7 @@ struct DataGridView: NSViewRepresentable { } installSelectionOverlay(tableView: tableView, coordinator: coordinator) - installRowGutter(scrollView: scrollView, tableView: tableView, coordinator: coordinator) + Self.installRowGutter(scrollView: scrollView, tableView: tableView, coordinator: coordinator) coordinator.attachScrollObservers(scrollView: scrollView) // Intentionally do not prime cachedRowCount/cachedColumnCount here. // They represent what NSTableView has actually rendered. Leaving them @@ -587,11 +587,23 @@ struct DataGridView: NSViewRepresentable { /// /// Its heading is not a view of its own: `SortableHeaderView` draws it, because nothing but the /// header view's own drawing can match the headings beside it. - private func installRowGutter( + static func installRowGutter( scrollView: NSScrollView, tableView: KeyHandlingTableView, coordinator: TableViewCoordinator ) { + /// The strip is document-tall, and nothing between it and the window frame clips it on its + /// own: measured on macOS 27, AppKit reparents a floating subview into a + /// `_NSScrollViewFloatingSubviewsContainerView` whose `clipsToBounds` is false, and + /// `NSScrollView`'s is false too, which is `NSView`'s documented default for the macOS 14 + /// SDK. So the strip painted its row numbers and its column separator over whatever the + /// window stacked above the grid, every one of which is an earlier sibling and therefore + /// underneath it: the find bar, the filter panel, the key-pattern search bar, the result tab + /// bar and the banners. The scroll view is the view this code owns, so it is where the clip + /// belongs; clipping the container instead would reach into a view AppKit owns and would + /// stop working the day AppKit reparents somewhere else. + scrollView.clipsToBounds = true + let gutter = DataGridRowGutterView(frame: .zero) gutter.coordinator = coordinator tableView.addSubview(gutter) diff --git a/TableProTests/Views/Results/DataGridRowNumberRenderingTests.swift b/TableProTests/Views/Results/DataGridRowNumberRenderingTests.swift index 94ed94fb4b..b060cd2c37 100644 --- a/TableProTests/Views/Results/DataGridRowNumberRenderingTests.swift +++ b/TableProTests/Views/Results/DataGridRowNumberRenderingTests.swift @@ -74,6 +74,22 @@ private struct Raster { } } +/// A band above the grid, the shape the window itself has: the find bar, the filter panel, the +/// key-pattern search bar, the result tab bar and the banners are all siblings stacked above the +/// data grid, and every one of them is an earlier sibling, so anything the grid paints outside +/// itself lands on top of them. +@MainActor +private final class StripHost: NSView { + static let color = NSColor(srgbRed: 0.15, green: 0.45, blue: 0.85, alpha: 1) + + override var isFlipped: Bool { true } + + override func draw(_ dirtyRect: NSRect) { + Self.color.setFill() + dirtyRect.fill() + } +} + private func matches(_ lhs: NSColor, _ rhs: NSColor, tolerance: CGFloat = 0.02) -> Bool { abs(lhs.redComponent - rhs.redComponent) <= tolerance && abs(lhs.greenComponent - rhs.greenComponent) <= tolerance @@ -87,6 +103,7 @@ struct DataGridRowNumberRenderingTests { @MainActor private struct Grid { let window: NSWindow + let host: StripHost? let scrollView: NSScrollView let tableView: KeyHandlingTableView let header: SortableHeaderView @@ -103,6 +120,15 @@ struct DataGridRowNumberRenderingTests { scrollView.layoutSubtreeIfNeeded() } + /// Far enough down that the strip's own drawing reaches past the top of the viewport, which + /// is the offset the escape shows at. + func scrollVertically(toRow row: Int) { + tableView.scroll(NSPoint(x: scrollView.contentView.bounds.origin.x, y: tableView.rect(ofRow: row).minY)) + scrollView.layoutSubtreeIfNeeded() + gutter.synchronizeGeometry() + gutter.displayIfNeeded() + } + func pointInScrollView(_ point: NSPoint) -> NSPoint { scrollView.convert(point, from: tableView) } @@ -128,7 +154,8 @@ struct DataGridRowNumberRenderingTests { private func makeGrid( titles: [String] = (0..<8).map { "column\($0)" }, rows: Int = DataGridRowNumberRenderingTests.rowCount, - appearance: NSAppearance.Name = .darkAqua + appearance: NSAppearance.Name = .darkAqua, + stripAbove: CGFloat = 0 ) -> Grid { let coordinator = TableViewCoordinator( changeManager: AnyChangeManager(DataChangeManager()), @@ -176,7 +203,7 @@ struct DataGridRowNumberRenderingTests { widthCalculator: { _, _ in Self.columnWidth } ) - let scrollView = NSScrollView(frame: NSRect(x: 0, y: 0, width: 600, height: 300)) + let scrollView = NSScrollView(frame: NSRect(x: 0, y: stripAbove, width: 600, height: 300 - stripAbove)) scrollView.hasHorizontalScroller = true scrollView.hasVerticalScroller = true scrollView.documentView = tableView @@ -187,13 +214,28 @@ struct DataGridRowNumberRenderingTests { defer: false ) window.appearance = NSAppearance(named: appearance) - window.contentView = scrollView - let gutter = DataGridRowGutterView(frame: .zero) - gutter.coordinator = coordinator - tableView.addSubview(gutter) - scrollView.addFloatingSubview(gutter, for: .horizontal) - coordinator.rowGutter = gutter + var host: StripHost? + if stripAbove > 0 { + let stripHost = StripHost(frame: NSRect(x: 0, y: 0, width: 600, height: 300)) + stripHost.addSubview(scrollView) + window.contentView = stripHost + host = stripHost + } else { + window.contentView = scrollView + } + + let gutter: DataGridRowGutterView + if stripAbove > 0 { + DataGridView.installRowGutter(scrollView: scrollView, tableView: tableView, coordinator: coordinator) + gutter = coordinator.rowGutter ?? DataGridRowGutterView(frame: .zero) + } else { + gutter = DataGridRowGutterView(frame: .zero) + gutter.coordinator = coordinator + tableView.addSubview(gutter) + scrollView.addFloatingSubview(gutter, for: .horizontal) + coordinator.rowGutter = gutter + } tableView.reloadData() tableView.layoutSubtreeIfNeeded() @@ -205,6 +247,7 @@ struct DataGridRowNumberRenderingTests { } return Grid( window: window, + host: host, scrollView: scrollView, tableView: tableView, header: header, @@ -490,6 +533,39 @@ struct DataGridRowNumberRenderingTests { #expect(!matches(even, odd), "both stripes drew \(even)") } + // MARK: - Staying inside the grid + + private static let stripHeight: CGFloat = 40 + + /// The strip is document-tall, so without a clip it paints far past the viewport it pins. On + /// screen that put row numbers and the strip's column separator over the find bar, and over + /// every other sibling the window stacks above the grid. + @Test("The pinned strip paints nothing above the grid") + func stripPaintsNothingAboveTheGrid() throws { + let grid = makeGrid(appearance: .aqua, stripAbove: Self.stripHeight) + let host = try #require(grid.host) + grid.scrollVertically(toRow: 6) + + let raster = try #require(Raster(of: host, in: host.bounds)) + /// The band's own colour where the strip cannot reach, rather than `StripHost.color`: the + /// cached drawing lands in an HDR colour space that shifts the fill, so the only reliable + /// reference is the same band measured beside the part under test. + let untouched = try #require(raster.color(at: NSPoint(x: host.bounds.maxX - 40, y: 4))) + let leadingEdge = NSRect(x: 0, y: 0, width: 120, height: Self.stripHeight) + #expect( + raster.inkPixels(in: leadingEdge, unlike: untouched) == 0, + "the grid painted above itself" + ) + } + + /// What holds the strip in: nothing between a floating subview and the window frame clips on its + /// own, and the scroll view is the view the grid owns. + @Test("The grid's scroll view clips to its bounds") + func scrollViewClipsToBounds() { + let grid = makeGrid(appearance: .aqua, stripAbove: Self.stripHeight) + #expect(grid.scrollView.clipsToBounds) + } + private func rightClick(at point: NSPoint, in grid: Grid) -> NSEvent? { NSEvent.mouseEvent( with: .rightMouseDown, From 27e570f81c2c28ac258e9a8d43994763fc11732e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 10:50:43 +0700 Subject: [PATCH 50/54] docs(claude-md): record that NSAppearance is the only native lever a theme has on chrome (#2785) * feat(settings): theme the content panes outside the editor and the data grid Claude-Session: https://claude.ai/code/session_01EKDGt17u6TaVBDHm8rzSEj * docs(claude-md): record that NSAppearance is the only native lever a theme has on chrome Claude-Session: https://claude.ai/code/session_01EKDGt17u6TaVBDHm8rzSEj --- CLAUDE.md | 2 ++ docs/customization/appearance.mdx | 2 ++ 2 files changed, 4 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index a86f64d6b4..ec0fe83e60 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -199,6 +199,8 @@ To ship one: add the record type or field in CloudKit Console (or `xcrun cktool **An installed driver is a handle, not a live connection**: `ConnectionSession.driver` is held from the moment it is built until something replaces it, and a socket the server closed is indistinguishable from a working one until a ping asks. `reconnectDriver` and `reconnectSession` both disconnect it and leave it installed, so `hasDriver` stayed true for the whole of an outage and for good once the monitor gave up: the window went on showing rows, tabs and an enabled toolbar over a dead handle, `ensureConnected` returned early so Reconnect did nothing, and the connections strip painted the failure from `status` while the pane beside it disagreed. `ConnectionSession.liveness` is the single answer to "can this driver be believed", and `ConnectionWindowPhaseMachine.onSessionChanged` reads it before `hasDriver`. `status` cannot serve: it is `.connecting` throughout an ordinary database switch on the four engines that reconnect to perform one, and `.disconnected` is the struct's own default value. Four rules follow. The driver is never nil'd to signal this, because it is the handle every metadata read, every query route and the reconnect itself still goes through, and taking it away makes a database switch look like a dropped connection and trips the `exists && !hasDriver` arm into a permanent fake "Connecting". `recovering` is not a failure, so a blip that repairs itself inside `DatabaseManager.unreachableAfterAttempt` leaves the window untouched; the threshold is the fifth attempt because the 2, 4, 8, 16 backoff announces it a full 30 seconds after the ping that failed, which is one whole ping interval of not answering. Every give-up site and the threshold go through `markSessionUnreachable(_:startedWith:info:)`, whose driver-identity check is the generation guard a reconnect blocked in a C call needs, and every path that installs a working driver calls `markSessionLive` so the mark and its reason go together. And everything that reports connection health reads `ConnectionSession.reportedStatus`, never `status` directly, or the strip and the pane drift apart again. +**A theme reaches content, and `NSAppearance` is the only lever it has on chrome**: the sidebar, the trailing pane, the editor tab strip and the window background cannot be painted from a theme without fighting AppKit, so the app does not try. Measured on macOS 27 against a plain `NSSplitViewController` in a `.fullSizeContentView` window with a toolbar. The sidebar's material is a framework-owned `NSGlassEffectView` two levels above the pane's own root (`NSView > ContentHolderView > NSGlassEffectView > _NSSplitViewItemViewWrapper`), so painting the pane means covering a view AppKit owns, and `NSSplitViewItem.h` documents that translucent material as standard sidebar behaviour with no knob to turn it off. The pane is also full-height (`allowsFullHeightLayout` is `true` by default and its root reports `safeAreaInsets.top` of 66pt), so a fill pinned to that root paints the whole titlebar and toolbar band, which Apple's Liquid Glass guidance tells apps not to do and which is what broke native window tabs in Sublime Text. Sidebar selection is the same story from the other side: under `.sourceList` AppKit inserts its own `NSVisualEffectView` as the row's first subview and calls `drawSelection(in:)` zero times, so the documented override never runs; setting `selectionHighlightStyle = .none` does suppress it but collapses `interiorBackgroundStyle` from emphasized to normal, and that is the channel `NSTableCellView.backgroundStyle` publishes as SwiftUI's `backgroundProminence`, which every sidebar row label answers through `.primary` and `.secondary`. An absolute colour ignores prominence, so a themed label paints the wrong colour on a selected row under the default theme too. The editor tab strip is titlebar-resident (`NSTitlebarAccessoryViewController`), so it falls under the same rule as the toolbar. What remains is the one lever macOS does give: `ThemeEngine` sets `NSApp.appearance` from the appearance mode, a theme declares `light` or `dark`, and `ThemeSlotValidation` keeps a theme in the slot whose appearance it matches, so choosing a dark theme gives dark chrome. Every theme slot is namespaced `content.` for this reason, and `ThemeSlotCoverageTests` fails the build for a slot no call site reads, which is what let the old `ui`, `sidebar` and `toolbar` groups ship with zero readers for two years. + **The app runs the AppKit lifecycle, and AppKit owns the menu bar**: `main.swift` assigns the delegate before `NSApplicationMain`, and `MainMenuBuilder.install` runs in `applicationWillFinishLaunching`. Do not reintroduce a SwiftUI `App`. SwiftUI reconciles `NSApp.mainMenu` once shortly after launch and removes every item it did not build itself, and no hook can undo it: `NSApp.mainMenu` is not KVO-compliant, `didUpdateNotification`, `didBecomeKeyNotification` and the `applicationDidUpdate(_:)` delegate method never fire under `@NSApplicationDelegateAdaptor`, and `applicationDidBecomeActive` fires before the reconciliation. Only a wall-clock delay worked, which is why #2057 shipped a menu bar that vanished half a second after launch and had to be reverted (#2071). Every window is an `NSWindowController`; the Welcome window is one too, so closing it is an ordinary `close()` and the old "closed, never ordered out" rule no longer applies. **An emptied tab manager is not the same as "the user closed every tab"**: a coordinator torn down by a lost session has already emptied `tabManager.tabs`, so any persistence path that reads "no tabs" as "clear the saved tabs" wipes tabs the user never closed. The fix is that the teardown path cannot clear at all: `TabPersistenceCoordinator.saveAggregatedSync()`, which disconnect and window-close call, opens with `guard !tabs.isEmpty else { return }`. Clearing requires explicit consent and happens on the `closeTabsByUser` path instead. Keep those two paths separate; the moment a teardown path can write an empty aggregate, the bug is back. diff --git a/docs/customization/appearance.mdx b/docs/customization/appearance.mdx index e85b74eb77..502011b2d7 100644 --- a/docs/customization/appearance.mdx +++ b/docs/customization/appearance.mdx @@ -44,6 +44,8 @@ Custom themes get color wells here. A built-in or registry theme shows a lock an A slot holds either a hex color or the name of a macOS system color. Default Light and Default Dark keep the data grid surrounds on system colors, which is why an untouched theme follows your system accent and its Increase Contrast setting. Right-click a well that a built-in leaves on a system color to put that system color back. +A theme colors the panes that show database content. The sidebar, the toolbar, the tab strip and the window frame stay on the macOS appearance, which is what the **Appearance** control at the top of the tab sets: pick a dark theme and the window frame goes dark with it. + ## Theme files A theme is one JSON file. **Export…** in the gear menu writes every color the selected theme sets, which is the shortest way to start a new one; **Import…** in the **+** menu reads one back into `~/Library/Application Support/TablePro/Themes/`. Community themes install from the [registry](/features/plugins) under **Settings > Plugins > Browse**, Themes category. From e5e0e3675cfa4a4e0d2446080289632aae55bc5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Sat, 12 Sep 2026 11:09:09 +0700 Subject: [PATCH 51/54] fix(hig): show the whole statement in the query confirmation dialog (#2786) Claude-Session: https://claude.ai/code/session_01CsJzH4VK7mTEBBye3f9LhL --- CHANGELOG.md | 5 + TablePro/Core/MCP/MCPAuthPolicy.swift | 46 ++++- .../MCP/Protocol/Tools/MCPStatementGate.swift | 19 +- .../Execution/DefaultExecutionGate.swift | 16 +- .../Execution/ExecutionGateProvider.swift | 12 ++ .../Providers/OperationConfirming.swift | 125 +++++++++--- TablePro/Core/Utilities/UI/AlertHelper.swift | 107 ++++++++-- .../Core/Utilities/UI/ModalDecisionGate.swift | 96 +++++++++ .../Utilities/UI/PairingApprovalGate.swift | 54 ----- .../Views/Components/SQLReviewSheet.swift | 189 ++++++++++++------ .../Tools/MCPStatementConsentGuardTests.swift | 78 ++++++++ .../Tools/MCPStatementGateTests.swift | 35 +++- .../Execution/ExecutionGateTests.swift | 6 +- .../OperationConfirmationPromptTests.swift | 186 +++++++++++++++++ TableProTests/Views/SQLReviewSheetTests.swift | 73 +++++++ docs/external-api/mcp-protocol.mdx | 4 + docs/features/safe-mode.mdx | 12 +- docs/images/safe-mode-confirmation-dark.png | Bin 0 -> 616891 bytes docs/images/safe-mode-confirmation.png | Bin 0 -> 807108 bytes 19 files changed, 869 insertions(+), 194 deletions(-) create mode 100644 TablePro/Core/Utilities/UI/ModalDecisionGate.swift delete mode 100644 TablePro/Core/Utilities/UI/PairingApprovalGate.swift create mode 100644 TableProTests/Core/MCP/Protocol/Tools/MCPStatementConsentGuardTests.swift create mode 100644 TableProTests/Core/Services/Execution/OperationConfirmationPromptTests.swift create mode 100644 docs/images/safe-mode-confirmation-dark.png create mode 100644 docs/images/safe-mode-confirmation.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ae84389db..a8960a4cf9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Query confirmation shows the statement syntax highlighted and scrollable, with **Copy All** and the name of whatever asked to run it. (#2759) - 5 MB smaller app bundle. - 7 MB smaller DMG download. - Connect progress reads as a labelled bar, with a step named only where the app is waiting on something outside itself. @@ -59,6 +60,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Query confirmation dialog cut to the first 200 characters of the statement. (#2759) +- Statement folded onto one line and cut at 400 characters in an MCP client's approval prompt. +- Blank line under "Are you sure you want to execute this query?" when confirming a rename. - Row numbers and their divider painted over the find bar, the filter panel and the result tab bar. - Empty Columns tab and no autocomplete for PostgreSQL materialized views. (#2726) - Discard restoring a different row than the one edited under a column value filter. @@ -248,6 +252,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - BigQuery Google sign-in accepting an authorization response without PKCE or a state check. - PostgreSQL sessions inheriting `standard_conforming_strings = off`, which let a backslash break out of any quoted literal. - PostgreSQL catalog, comment and password literals escaped by quote doubling alone, which a backslash can break out of. (#2726) +- An MCP token without Full Access approving its own write and skipping TablePro's confirmation dialog. ## [0.73.0] - 2026-09-09 diff --git a/TablePro/Core/MCP/MCPAuthPolicy.swift b/TablePro/Core/MCP/MCPAuthPolicy.swift index 3439c1af4e..3318e824d6 100644 --- a/TablePro/Core/MCP/MCPAuthPolicy.swift +++ b/TablePro/Core/MCP/MCPAuthPolicy.swift @@ -282,19 +282,16 @@ public actor MCPAuthPolicy { sql: String, connectionId: UUID, databaseType: DatabaseType, - capabilities: CallerCapabilities = [.mayWrite, .mayRunDestructive, .mayRunMultiStatement] + capabilities: CallerCapabilities = [.mayWrite, .mayRunDestructive, .mayRunMultiStatement], + operationLabel: String? = nil ) async throws { - var effective = capabilities - if !principal.has(.admin) || principal.isAnonymous { - effective.remove(.confirmationPreCleared) - effective.remove(.preCleared) - } try await runExecutionGate( sql: sql, connectionId: connectionId, databaseType: databaseType, - capabilities: effective, - callerLabel: principal.auditLabel + capabilities: Self.effectiveCapabilities(capabilities, for: principal), + callerLabel: principal.auditLabel, + operationLabel: operationLabel ) } @@ -309,7 +306,8 @@ public actor MCPAuthPolicy { connectionId: connectionId, databaseType: databaseType, capabilities: capabilities, - callerLabel: nil + callerLabel: nil, + operationLabel: nil ) } @@ -318,7 +316,8 @@ public actor MCPAuthPolicy { connectionId: UUID, databaseType: DatabaseType, capabilities: CallerCapabilities, - callerLabel: String? + callerLabel: String?, + operationLabel: String? ) async throws { let decision = await ExecutionGateProvider.shared.authorize( OperationRequest( @@ -328,7 +327,7 @@ public actor MCPAuthPolicy { kind: OperationKind.from(QueryClassifier.classifyTier(sql, databaseType: databaseType)), caller: .mcpClient(label: callerLabel), capabilities: capabilities, - operationDescription: String(localized: "MCP query execution") + operationDescription: Self.operationDescription(for: operationLabel) ) ) if case .denied(let reason) = decision { @@ -336,6 +335,31 @@ public actor MCPAuthPolicy { } } + /// `confirmationPreCleared` says a human already confirmed, and over MCP nobody did: the client + /// answered its own prompt. Only an admin-scoped token may substitute that for TablePro's + /// dialog, which is what separates Full Access from Read & Write in enforcement rather than only + /// in the settings UI. Reaching the gate without a principal skips this, so + /// `MCPStatementGateGuardTests` checks that the MCP path never does. + static func effectiveCapabilities( + _ capabilities: CallerCapabilities, + for principal: MCPPrincipal + ) -> CallerCapabilities { + guard !principal.has(.admin) || principal.isAnonymous else { return capabilities } + var effective = capabilities + effective.remove(.confirmationPreCleared) + effective.remove(.preCleared) + return effective + } + + /// The same words the client's own elicitation prompt uses, so a user who sees both reads one + /// vocabulary. The connection is named by the dialog's own subtitle rather than twice here. + static func operationDescription(for operationLabel: String?) -> String { + guard let operationLabel, !operationLabel.isEmpty else { + return String(localized: "MCP query execution") + } + return String(format: String(localized: "Allow %@?"), operationLabel) + } + func logQuery( sql: String, connectionId: UUID, diff --git a/TablePro/Core/MCP/Protocol/Tools/MCPStatementGate.swift b/TablePro/Core/MCP/Protocol/Tools/MCPStatementGate.swift index d262af9e4a..7e74bd1256 100644 --- a/TablePro/Core/MCP/Protocol/Tools/MCPStatementGate.swift +++ b/TablePro/Core/MCP/Protocol/Tools/MCPStatementGate.swift @@ -52,10 +52,12 @@ enum MCPStatementGate { capabilities.formUnion(consent.capabilities) try await services.authPolicy.checkSafeModeDialog( + principal: context.principal, sql: sql, connectionId: meta.connectionId, databaseType: meta.databaseType, - capabilities: capabilities + capabilities: capabilities, + operationLabel: operationLabel ) return classification @@ -114,12 +116,15 @@ enum MCPStatementGate { ) } + /// The only text the client shows beside its Approve control, so it is the whole of what the + /// user reads before saying yes. It keeps its line breaks: a statement folded onto one line is + /// unreadable at the length that matters, and the cut used to land before the `WHERE` clause. + /// The cap is sized for a form field in someone else's interface, not for a view we draw. + static let previewCharacterLimit = 2_000 + static func preview(of sql: String) -> String { - let condensed = sql - .replacingOccurrences(of: "\n", with: " ") - .replacingOccurrences(of: "\t", with: " ") - .trimmingCharacters(in: .whitespacesAndNewlines) - guard (condensed as NSString).length > 400 else { return condensed } - return (condensed as NSString).substring(to: 400) + "…" + let trimmed = sql.trimmingCharacters(in: .whitespacesAndNewlines) + guard (trimmed as NSString).length > previewCharacterLimit else { return trimmed } + return (trimmed as NSString).substring(to: previewCharacterLimit) + "…" } } diff --git a/TablePro/Core/Services/Execution/DefaultExecutionGate.swift b/TablePro/Core/Services/Execution/DefaultExecutionGate.swift index 88b591a7ab..e662dd7c93 100644 --- a/TablePro/Core/Services/Execution/DefaultExecutionGate.swift +++ b/TablePro/Core/Services/Execution/DefaultExecutionGate.swift @@ -10,6 +10,7 @@ internal actor DefaultExecutionGate: ExecutionGate { private let authenticating: OperationAuthenticating private let safeModeLevelResolver: @Sendable (UUID) async -> SafeModeLevel private let forcesWriteResolver: @Sendable (DatabaseType) async -> Bool + private let connectionNameResolver: @Sendable (UUID) async -> String? private let auditLog: any ExecutionAuditLogging init( @@ -17,12 +18,14 @@ internal actor DefaultExecutionGate: ExecutionGate { authenticating: OperationAuthenticating, safeModeLevelResolver: @escaping @Sendable (UUID) async -> SafeModeLevel, forcesWriteResolver: @escaping @Sendable (DatabaseType) async -> Bool, + connectionNameResolver: @escaping @Sendable (UUID) async -> String? = { _ in nil }, auditLog: any ExecutionAuditLogging = ExecutionAuditLog.shared ) { self.confirming = confirming self.authenticating = authenticating self.safeModeLevelResolver = safeModeLevelResolver self.forcesWriteResolver = forcesWriteResolver + self.connectionNameResolver = connectionNameResolver self.auditLog = auditLog } @@ -76,10 +79,15 @@ internal actor DefaultExecutionGate: ExecutionGate { return .denied(reason: String(localized: "Confirmation is required for this operation")) } let confirmed = await confirming.confirm( - sql: request.sql ?? "", - operationDescription: request.operationDescription, - connectionId: request.connectionId, - isDestructive: isDestructive + OperationConfirmationRequest( + sql: request.sql, + operationDescription: request.operationDescription, + connectionId: request.connectionId, + connectionName: await connectionNameResolver(request.connectionId), + databaseType: request.databaseType, + caller: request.caller, + isDestructive: isDestructive + ) ) guard confirmed else { return .denied(reason: String(localized: "Operation cancelled by user")) diff --git a/TablePro/Core/Services/Execution/ExecutionGateProvider.swift b/TablePro/Core/Services/Execution/ExecutionGateProvider.swift index 2c65d5114d..64eb686d0c 100644 --- a/TablePro/Core/Services/Execution/ExecutionGateProvider.swift +++ b/TablePro/Core/Services/Execution/ExecutionGateProvider.swift @@ -29,6 +29,18 @@ internal enum ExecutionGateProvider { await MainActor.run { !PluginManager.shared.supportsReadOnlyMode(for: databaseType) } + }, + connectionNameResolver: { connectionId in + await MainActor.run { + switch DatabaseManager.shared.connectionState(connectionId) { + case .live(_, let session): + return session.connection.name + case .stored(let connection): + return connection.name + case .unknown: + return nil + } + } } ) } diff --git a/TablePro/Core/Services/Execution/Providers/OperationConfirming.swift b/TablePro/Core/Services/Execution/Providers/OperationConfirming.swift index ed380824bc..22ae9dc27c 100644 --- a/TablePro/Core/Services/Execution/Providers/OperationConfirming.swift +++ b/TablePro/Core/Services/Execution/Providers/OperationConfirming.swift @@ -4,49 +4,110 @@ // import AppKit +import TableProPluginKit + +internal struct OperationConfirmationRequest: Sendable { + let sql: String? + let operationDescription: String + let connectionId: UUID + let connectionName: String? + let databaseType: DatabaseType + let caller: OperationCaller + let isDestructive: Bool +} internal protocol OperationConfirming: Sendable { @MainActor - func confirm(sql: String, operationDescription: String, connectionId: UUID, isDestructive: Bool) async -> Bool + func confirm(_ request: OperationConfirmationRequest) async -> Bool +} + +/// What the user is shown before a statement runs. Everything here is a pure function of the +/// request so the wording can be tested without presenting anything. +internal enum OperationConfirmationPrompt { + internal static let confirmTitle = String(localized: "Execute") + + internal static func statement(of request: OperationConfirmationRequest) -> String? { + guard let sql = request.sql?.trimmingCharacters(in: .whitespacesAndNewlines), !sql.isEmpty else { + return nil + } + return sql + } + + internal static func subtitle(of request: OperationConfirmationRequest) -> String { + let connection = request.connectionName?.trimmingCharacters(in: .whitespacesAndNewlines) + guard let client = clientName(for: request.caller) else { + guard let connection, !connection.isEmpty else { + return String(localized: "Review this before it runs.") + } + return String(format: String(localized: "Runs on '%@'."), connection) + } + guard let connection, !connection.isEmpty else { + return String(format: String(localized: "%@ wants to run this."), client) + } + return String(format: String(localized: "%1$@ wants to run this on '%2$@'."), client, connection) + } + + internal static func destructiveWarning(of request: OperationConfirmationRequest) -> String? { + guard request.isDestructive else { return nil } + return String(localized: "This may permanently modify or delete data and cannot be undone.") + } + + /// A rename has no statement to show: the driver builds it from the names, and two engines + /// perform it without SQL at all. The review dialog would render an empty box, so this case + /// stays an alert, which is what an alert is for. + @MainActor + internal static func makeAlert(for request: OperationConfirmationRequest) -> NSAlert { + let alert = NSAlert() + alert.messageText = request.operationDescription + alert.informativeText = [subtitle(of: request), destructiveWarning(of: request)] + .compactMap { $0 } + .joined(separator: "\n\n") + alert.alertStyle = request.isDestructive ? .critical : .warning + AlertHelper.addConfirmAndCancel( + to: alert, + confirmButton: confirmTitle, + cancelButton: String(localized: "Cancel") + ) + return alert + } + + private static func clientName(for caller: OperationCaller) -> String? { + switch caller { + case .userInterface, .importPipeline, .backgroundMaintenance: + return nil + case .mcpClient(let label): + return label ?? String(localized: "An MCP client") + case .aiAssistant: + return String(localized: "The AI assistant") + case .appleScript(let client): + return client ?? String(localized: "Another app") + } + } } internal struct AlertOperationConfirming: OperationConfirming { @MainActor - func confirm(sql: String, operationDescription: String, connectionId: UUID, isDestructive: Bool) async -> Bool { + func confirm(_ request: OperationConfirmationRequest) async -> Bool { AppActivationPolicyController.shared.activate(ignoringOtherApps: true) - let window = WindowLifecycleMonitor.shared.activeWindow(for: connectionId, preferring: NSApp.keyWindow) - let preview = Self.preview(of: sql) - - if isDestructive { - return await AlertHelper.confirmCritical( - title: operationDescription, - message: String( - format: String(localized: "This query may permanently modify or delete data and cannot be undone.\n\n%@"), - preview - ), - confirmButton: String(localized: "Execute"), - cancelButton: String(localized: "Cancel"), - window: window - ) + let window = WindowLifecycleMonitor.shared.activeWindow( + for: request.connectionId, + preferring: NSApp.keyWindow + ) + + guard let statement = OperationConfirmationPrompt.statement(of: request) else { + let alert = OperationConfirmationPrompt.makeAlert(for: request) + return await AlertHelper.response(to: alert, in: window) == .alertFirstButtonReturn } - return await AlertHelper.confirmDestructive( - title: operationDescription, - message: String( - format: String(localized: "Are you sure you want to execute this query?\n\n%@"), - preview - ), - confirmButton: String(localized: "Execute"), - cancelButton: String(localized: "Cancel"), + return await AlertHelper.runStatementConfirmation( + title: request.operationDescription, + subtitle: OperationConfirmationPrompt.subtitle(of: request), + warning: OperationConfirmationPrompt.destructiveWarning(of: request), + statements: [statement], + databaseType: request.databaseType, + confirmTitle: OperationConfirmationPrompt.confirmTitle, + isDestructive: request.isDestructive, window: window ) } - - private static func preview(of sql: String) -> String { - let trimmed = sql.trimmingCharacters(in: .whitespacesAndNewlines) - if (trimmed as NSString).length > 200 { - return String(trimmed.prefix(200)) + "…" - } - return trimmed - } } diff --git a/TablePro/Core/Utilities/UI/AlertHelper.swift b/TablePro/Core/Utilities/UI/AlertHelper.swift index f692b40f8f..13904534e3 100644 --- a/TablePro/Core/Utilities/UI/AlertHelper.swift +++ b/TablePro/Core/Utilities/UI/AlertHelper.swift @@ -5,6 +5,7 @@ import AppKit import SwiftUI +import TableProPluginKit @MainActor final class AlertHelper { @@ -74,7 +75,7 @@ final class AlertHelper { alert.beginSheetModal(for: parent, completionHandler: completion) } - private static func run(_ alert: NSAlert, in window: NSWindow?) async -> NSApplication.ModalResponse { + static func response(to alert: NSAlert, in window: NSWindow?) async -> NSApplication.ModalResponse { await withCheckedContinuation { continuation in present(alert, in: window) { continuation.resume(returning: $0) } } @@ -97,7 +98,7 @@ final class AlertHelper { alert.alertStyle = .informational alert.addButton(withTitle: confirmButton) Self.addCancelButton(to: alert, title: cancelButton) - return await run(alert, in: window) == .alertFirstButtonReturn + return await response(to: alert, in: window) == .alertFirstButtonReturn } // MARK: - Destructive Confirmations @@ -114,7 +115,7 @@ final class AlertHelper { alert.informativeText = message alert.alertStyle = .warning Self.addConfirmAndCancel(to: alert, confirmButton: confirmButton, cancelButton: cancelButton) - return await run(alert, in: window) == .alertFirstButtonReturn + return await response(to: alert, in: window) == .alertFirstButtonReturn } // MARK: - Critical Confirmations @@ -131,7 +132,7 @@ final class AlertHelper { alert.informativeText = message alert.alertStyle = .critical Self.addConfirmAndCancel(to: alert, confirmButton: confirmButton, cancelButton: cancelButton) - return await run(alert, in: window) == .alertFirstButtonReturn + return await response(to: alert, in: window) == .alertFirstButtonReturn } // MARK: - Cross-Process Approval @@ -155,37 +156,108 @@ final class AlertHelper { } /// Pairing is a security decision, so the attached case uses a critical sheet: it must not - /// queue behind whatever sheet the window is already showing. The detached case runs the modal - /// loop directly rather than inside a continuation-installing closure, which would block the - /// main actor while the continuation is still being installed. + /// queue behind whatever sheet the window is already showing. static func runPairingApproval(request: PairingRequest) async throws -> PairingApproval { let codeExpiresAt = Date.now.addingTimeInterval(PairingExchangeStore.exchangeWindow) - let gate = PairingApprovalGate() - let host = NSHostingController( + let gate = ModalDecisionGate.pairing() + return try await runHostedDecision( + title: String(localized: "Approve Integration"), + fittingWidth: 520, + gate: gate, + window: nil, rootView: PairingApprovalSheet( request: request, codeExpiresAt: codeExpiresAt, onComplete: { result in gate.deliver(result) } ) ) + } + + /// A statement the user has to read before approving it. The alert vocabulary cannot carry one: + /// `informativeText` is a proportional label with no scrolling and no selection, so a statement + /// long enough to be worth reviewing is exactly the one it cannot show. + /// + /// The windowless path is the ordinary case rather than a fallback. A request arriving over MCP + /// reaches a Mac whose TablePro may have no window open at all, and that is precisely when this + /// dialog is the only place the statement is visible. + static func runStatementConfirmation( + title: String, + subtitle: String, + warning: String?, + statements: [String], + databaseType: DatabaseType, + confirmTitle: String, + isDestructive: Bool, + window: NSWindow? + ) async -> Bool { + let gate = ModalDecisionGate.confirmation() + let presented = Binding( + get: { true }, + set: { isPresented in + guard !isPresented else { return } + gate.deliver(.success(false)) + } + ) + let sheet = SQLReviewSheet( + isPresented: presented, + statements: statements, + databaseType: databaseType, + title: title, + subtitle: subtitle, + showsStatementsVerbatim: true, + warning: warning, + primaryAction: SQLReviewSheet.PrimaryAction( + title: confirmTitle, + isDestructive: isDestructive, + takesDefaultAction: false, + work: .immediate { gate.deliver(.success(true)) } + ) + ) + let confirmed = try? await runHostedDecision( + title: title, + fittingWidth: 560, + gate: gate, + window: window, + rootView: sheet + ) + return confirmed ?? false + } + + /// The one presentation path for a SwiftUI decision the user must answer: a critical sheet on + /// the window they were working in, and an application-modal window when none qualifies. The + /// modal loop runs directly rather than inside a continuation-installing closure, which would + /// block the main actor while the continuation is still being installed. + private static func runHostedDecision( + title: String, + fittingWidth: CGFloat, + gate: ModalDecisionGate, + window: NSWindow?, + rootView: some View + ) async throws -> Value { + let host = NSHostingController(rootView: rootView) host.sizingOptions = [] - let fitted = host.sizeThatFits(in: NSSize(width: 520, height: CGFloat.greatestFiniteMagnitude)) + let fitted = host.sizeThatFits(in: NSSize(width: fittingWidth, height: CGFloat.greatestFiniteMagnitude)) host.view.frame = NSRect(origin: .zero, size: fitted) - let sheetWindow = NSWindow.titled(String(localized: "Approve Integration"), contentViewController: host) + host.title = title + let sheetWindow = ModalDecisionWindow(contentViewController: host) sheetWindow.styleMask = [.titled, .closable] sheetWindow.isReleasedWhenClosed = false + /// The HIG gives Escape to Cancel on every alert and sheet, and a confirmation that came + /// forward over the user's own work is exactly the one that has to stay dismissable. + sheetWindow.onCancel = { [weak gate] in gate?.cancel() } - guard let parent = resolveWindow(nil) else { - let delegate = PairingApprovalWindowDelegate(gate: gate) - sheetWindow.delegate = delegate + let delegate = ModalDecisionWindowDelegate { [weak gate] in gate?.cancel() } + gate.windowDelegate = delegate + sheetWindow.delegate = delegate + + guard let parent = resolveWindow(window) else { gate.onResolve = { [weak sheetWindow] in NSApp.stopModal() sheetWindow?.close() } AppActivationPolicyController.shared.activate(ignoringOtherApps: true) sheetWindow.center() - defer { withExtendedLifetime(delegate) {} } NSApp.runModal(for: sheetWindow) AppActivationPolicyController.shared.reevaluate(excluding: sheetWindow) return try gate.result() @@ -194,6 +266,7 @@ final class AlertHelper { gate.onResolve = { [weak sheetWindow] in guard let sheetWindow else { return } parent.endSheet(sheetWindow) + sheetWindow.close() } parent.beginCriticalSheet(sheetWindow, completionHandler: nil) return try await gate.value() @@ -222,7 +295,7 @@ final class AlertHelper { dontSaveButton.keyEquivalent = "d" dontSaveButton.keyEquivalentModifierMask = .command - switch await run(alert, in: window) { + switch await response(to: alert, in: window) { case .alertFirstButtonReturn: return .save case .alertThirdButtonReturn: return .dontSave default: return .cancel @@ -247,7 +320,7 @@ final class AlertHelper { alert.addButton(withTitle: second) alert.addButton(withTitle: third) - switch await run(alert, in: window) { + switch await response(to: alert, in: window) { case .alertFirstButtonReturn: return 0 case .alertSecondButtonReturn: return 1 case .alertThirdButtonReturn: return 2 diff --git a/TablePro/Core/Utilities/UI/ModalDecisionGate.swift b/TablePro/Core/Utilities/UI/ModalDecisionGate.swift new file mode 100644 index 0000000000..39c3052eec --- /dev/null +++ b/TablePro/Core/Utilities/UI/ModalDecisionGate.swift @@ -0,0 +1,96 @@ +// +// ModalDecisionGate.swift +// TablePro +// + +import AppKit + +/// A hosted modal can be answered twice: the view's own button and the window closing both arrive. +/// Only the first counts, or a continuation resumes more than once and the process traps. +/// +/// `cancellationOutcome` is what closing the window means to this particular modal. Pairing treats +/// it as a thrown cancellation; a statement confirmation treats it as an ordinary no. +@MainActor +internal final class ModalDecisionGate { + internal var onResolve: (() -> Void)? + + /// `NSWindow.delegate` is weak and the sheet path returns while the sheet is still up, so the + /// delegate that reports a close has to be owned by something whose lifetime matches the modal. + internal var windowDelegate: (any NSWindowDelegate)? + + private let cancellationOutcome: Result + private var outcome: Result? + private var waiter: CheckedContinuation? + + internal init(cancellationOutcome: Result) { + self.cancellationOutcome = cancellationOutcome + } + + internal func deliver(_ result: Result) { + guard outcome == nil else { return } + outcome = result + onResolve?() + guard let waiter else { return } + self.waiter = nil + waiter.resume(with: result) + } + + internal func cancel() { + deliver(cancellationOutcome) + } + + internal func value() async throws -> Value { + if let outcome { return try outcome.get() } + return try await withCheckedThrowingContinuation { continuation in + waiter = continuation + } + } + + internal func result() throws -> Value { + guard let outcome else { return try cancellationOutcome.get() } + return try outcome.get() + } +} + +internal extension ModalDecisionGate where Value == PairingApproval { + static func pairing() -> ModalDecisionGate { + ModalDecisionGate(cancellationOutcome: .failure(DatabaseAccessError.userCancelled)) + } +} + +internal extension ModalDecisionGate where Value == Bool { + static func confirmation() -> ModalDecisionGate { + ModalDecisionGate(cancellationOutcome: .success(false)) + } +} + +/// The window a hosted decision lives in, so Escape has somewhere to land. +/// +/// A local `.keyDown` monitor cannot serve: measured on macOS 26.6, one installed over this sheet +/// reports Tab and every letter and never reports key code 53, because AppKit turns Escape into +/// `cancelOperation(_:)` and sends it up the responder chain first. Inside a hosted SwiftUI view +/// neither `.onExitCommand` nor a `.cancelAction` button answers it, and the window is the end of +/// that chain. +@MainActor +internal final class ModalDecisionWindow: NSWindow { + internal var onCancel: (() -> Void)? + + override internal func cancelOperation(_ sender: Any?) { + onCancel?() + } +} + +/// Closing the window is an answer, so it has to reach the gate rather than leave the caller +/// waiting on a modal that is no longer on screen. +@MainActor +internal final class ModalDecisionWindowDelegate: NSObject, NSWindowDelegate { + private let onClose: () -> Void + + internal init(onClose: @escaping () -> Void) { + self.onClose = onClose + } + + internal func windowWillClose(_ notification: Notification) { + onClose() + } +} diff --git a/TablePro/Core/Utilities/UI/PairingApprovalGate.swift b/TablePro/Core/Utilities/UI/PairingApprovalGate.swift deleted file mode 100644 index cb90e9db10..0000000000 --- a/TablePro/Core/Utilities/UI/PairingApprovalGate.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// PairingApprovalGate.swift -// TablePro -// - -import AppKit - -/// A pairing prompt can be answered twice: the sheet's own button and the window closing both -/// arrive. Only the first counts, or a continuation resumes more than once and the process traps. -@MainActor -internal final class PairingApprovalGate { - internal var onResolve: (() -> Void)? - - private var outcome: Result? - private var waiter: CheckedContinuation? - - internal func deliver(_ result: Result) { - guard outcome == nil else { return } - outcome = result - onResolve?() - guard let waiter else { return } - self.waiter = nil - waiter.resume(with: result) - } - - internal func cancel() { - deliver(.failure(DatabaseAccessError.userCancelled)) - } - - internal func value() async throws -> PairingApproval { - if let outcome { return try outcome.get() } - return try await withCheckedThrowingContinuation { continuation in - waiter = continuation - } - } - - internal func result() throws -> PairingApproval { - guard let outcome else { throw DatabaseAccessError.userCancelled } - return try outcome.get() - } -} - -@MainActor -internal final class PairingApprovalWindowDelegate: NSObject, NSWindowDelegate { - private let gate: PairingApprovalGate - - internal init(gate: PairingApprovalGate) { - self.gate = gate - } - - internal func windowWillClose(_ notification: Notification) { - gate.cancel() - } -} diff --git a/TablePro/Views/Components/SQLReviewSheet.swift b/TablePro/Views/Components/SQLReviewSheet.swift index 05e306b4df..36ba33dd61 100644 --- a/TablePro/Views/Components/SQLReviewSheet.swift +++ b/TablePro/Views/Components/SQLReviewSheet.swift @@ -11,23 +11,68 @@ import TableProPluginKit struct SQLReviewSheet: View { struct PrimaryAction { + /// Answering a confirmation is instant and must not wait on a task being scheduled. The + /// windowless path holds the main actor inside `NSApp.runModal` until this button resolves + /// its gate, and the loop only unwinds once it does, so work deferred to a `Task` would be + /// waiting on the loop that is waiting on it. Applying a plan is the other shape: it takes + /// as long as the server does and wants the progress the task form gives it. + enum Work { + case immediate(@MainActor () -> Void) + case asynchronous(@MainActor () async -> Void) + } + let title: String let isDestructive: Bool - let perform: () async -> Void + /// Return belongs to the confirming button only when the user asked for this dialog. A + /// confirmation something else raised steals focus to do it, so a Return already on its way + /// to the user's editor would answer it. `AlertHelper.addConfirmAndCancel` takes Return off + /// the confirming button for the same reason. + let takesDefaultAction: Bool + let work: Work + + init( + title: String, + isDestructive: Bool, + takesDefaultAction: Bool = true, + perform: @escaping @MainActor () async -> Void + ) { + self.init( + title: title, + isDestructive: isDestructive, + takesDefaultAction: takesDefaultAction, + work: .asynchronous(perform) + ) + } - init(title: String, isDestructive: Bool, perform: @escaping () async -> Void) { + init( + title: String, + isDestructive: Bool, + takesDefaultAction: Bool = true, + work: Work + ) { self.title = title self.isDestructive = isDestructive - self.perform = perform + self.takesDefaultAction = takesDefaultAction + self.work = work } } + /// The one way out. `@Environment(\.dismiss)` cannot serve alongside it, because it is inert + /// once the sheet is hosted in an `NSWindow` rather than presented by SwiftUI, which is how a + /// statement confirmation reaches a Mac with no window open. @Binding var isPresented: Bool - @Environment(\.dismiss) private var dismiss let statements: [String] let databaseType: DatabaseType + /// Replaces the default " Preview" heading. A confirmation names the operation. + var title: String? + /// The sentence under the heading: who is asking, and which connection. + var subtitle: String? + /// Show the statements exactly as they will be sent. A preview may make MQL easier to read by + /// rewriting `{"$oid": "…"}` as `ObjectId("…")` and by ending each statement with a semicolon; + /// a confirmation may not, because the user is agreeing to the text in front of them. + var showsStatementsVerbatim = false var warning: String? var failure: String? var primaryAction: PrimaryAction? @@ -73,7 +118,7 @@ struct SQLReviewSheet: View { } .frame(width: 560, height: 460) .background(Color(nsColor: .windowBackgroundColor)) - .onExitCommand { dismiss() } + .onExitCommand { isPresented = false } .task { await prepare() } } @@ -93,28 +138,41 @@ struct SQLReviewSheet: View { private func prepare() async { guard prepared == nil, !statements.isEmpty else { return } - let isJavaScript = PluginManager.shared.editorLanguage(for: databaseType) == .javascript - let result = await Task.detached(priority: .userInitiated) { [statements, isJavaScript] in - Self.build(statements: statements, isJavaScript: isJavaScript) + let isJavaScript = !showsStatementsVerbatim + && PluginManager.shared.editorLanguage(for: databaseType) == .javascript + let verbatim = showsStatementsVerbatim + let result = await Task.detached(priority: .userInitiated) { [statements, isJavaScript, verbatim] in + Self.build(statements: statements, isJavaScript: isJavaScript, verbatim: verbatim) }.value prepared = result } - static func build(statements: [String], databaseType: DatabaseType) -> Prepared { - let isJavaScript = PluginManager.shared.editorLanguage(for: databaseType) == .javascript - return build(statements: statements, isJavaScript: isJavaScript) + static func build(statements: [String], databaseType: DatabaseType, verbatim: Bool = false) -> Prepared { + let isJavaScript = !verbatim && PluginManager.shared.editorLanguage(for: databaseType) == .javascript + return build(statements: statements, isJavaScript: isJavaScript, verbatim: verbatim) } - nonisolated private static func build(statements: [String], isJavaScript: Bool) -> Prepared { - var full = statements - .map { $0.hasSuffix(";") ? $0 : $0 + ";" } - .joined(separator: "\n\n") + nonisolated private static func build(statements: [String], isJavaScript: Bool, verbatim: Bool) -> Prepared { + var full = verbatim + ? statements.joined(separator: "\n\n") + : statements.map { $0.hasSuffix(";") ? $0 : $0 + ";" }.joined(separator: "\n\n") if isJavaScript { full = convertExtendedJsonToShellSyntax(full) } let nsFull = full as NSString let fullCount = nsFull.length + /// A preview may stop early and leave the rest to Copy All. A confirmation may not: the + /// statement's `WHERE` clause can sit past any cut, and approving what you cannot see is + /// the whole of what this dialog exists to prevent. `execute_query` accepts 102,400 units, + /// which the text view below renders and a SwiftUI `Text` does not. + if verbatim { + return Prepared( + display: full, + full: full, + mode: fullCount <= treeSitterCutoff ? .rich : .plain + ) + } if fullCount > maxDisplayChars { let head = nsFull.substring(to: maxDisplayChars) let remaining = fullCount - maxDisplayChars @@ -148,31 +206,47 @@ struct SQLReviewSheet: View { } private var header: some View { - HStack(spacing: 8) { - Text("\(PluginManager.shared.queryLanguageName(for: databaseType)) Preview") - .font(.body.weight(.semibold)) - if !statements.isEmpty { - Text( - "(\(statements.count) \(statements.count == 1 ? String(localized: "statement") : String(localized: "statements")))" - ) - .font(.subheadline) - .foregroundStyle(.secondary) - } - Spacer() - if !statements.isEmpty { - Button(action: copyAll) { - Label( - copied ? String(localized: "Copied") : String(localized: "Copy All"), - systemImage: copied ? "checkmark" : "doc.on.doc" + VStack(alignment: .leading, spacing: 4) { + HStack(spacing: 8) { + Text(title ?? defaultTitle) + .font(.body.weight(.semibold)) + if !statements.isEmpty { + Text( + "(\(statements.count) \(statements.count == 1 ? String(localized: "statement") : String(localized: "statements")))" ) + .font(.subheadline) + .foregroundStyle(.secondary) } - .buttonStyle(.bordered) - .controlSize(.small) - .disabled(prepared == nil) + Spacer() + if !statements.isEmpty { + Button(action: copyAll) { + Label( + copied ? String(localized: "Copied") : String(localized: "Copy All"), + systemImage: copied ? "checkmark" : "doc.on.doc" + ) + } + .buttonStyle(.bordered) + .controlSize(.small) + .disabled(prepared == nil) + } + } + if let subtitle { + Text(subtitle) + .font(.subheadline) + .foregroundStyle(.secondary) + .fixedSize(horizontal: false, vertical: true) + .frame(maxWidth: .infinity, alignment: .leading) } } } + private var defaultTitle: String { + String( + format: String(localized: "%@ Preview"), + PluginManager.shared.queryLanguageName(for: databaseType) + ) + } + private var emptyState: some View { VStack(spacing: 8) { Image(systemName: "doc.plaintext") @@ -214,23 +288,17 @@ struct SQLReviewSheet: View { ) } + /// A text view rather than a `Text` in a `ScrollView`: this path carries everything past the + /// tree-sitter cutoff, which for a confirmation is the whole statement however long it is, and + /// a single `Text` that size lays out for seconds. It wears the editor's own background, text + /// colour and syntax palette, which is what a hand-themed `Text` here was reaching for. private func plainTextEditor(_ text: String) -> some View { - ScrollView(.vertical) { - Text(text) - .font(.system(size: 12, design: .monospaced)) - .textSelection(.enabled) - .lineLimit(nil) - .fixedSize(horizontal: false, vertical: true) - .frame(maxWidth: .infinity, alignment: .leading) - .padding(8) - .foregroundStyle(ThemeEngine.shared.palette.color(.editorText)) - } - .background(ThemeEngine.shared.palette.color(.editorBackground)) - .clipShape(RoundedRectangle(cornerRadius: 6)) - .overlay( - RoundedRectangle(cornerRadius: 6) - .stroke(Color(nsColor: .separatorColor), lineWidth: 0.5) - ) + HighlightedSQLTextView(sql: text, databaseType: databaseType) + .clipShape(RoundedRectangle(cornerRadius: 6)) + .overlay( + RoundedRectangle(cornerRadius: 6) + .stroke(Color(nsColor: .separatorColor), lineWidth: 0.5) + ) } @ViewBuilder @@ -266,12 +334,12 @@ struct SQLReviewSheet: View { ProgressView().controlSize(.small) } if let primaryAction { - Button(String(localized: "Cancel"), role: .cancel) { dismiss() } + Button(String(localized: "Cancel"), role: .cancel) { isPresented = false } .keyboardShortcut(.cancelAction) .disabled(isExecuting) executeButton(primaryAction) } else { - Button(String(localized: "Done")) { dismiss() } + Button(String(localized: "Done")) { isPresented = false } .keyboardShortcut(.cancelAction) } } @@ -281,16 +349,21 @@ struct SQLReviewSheet: View { @ViewBuilder private func executeButton(_ action: PrimaryAction) -> some View { let button = Button(action.title, role: action.isDestructive ? .destructive : nil) { - isExecuting = true - Task { - await action.perform() - isExecuting = false + switch action.work { + case .immediate(let perform): + perform() + case .asynchronous(let perform): + isExecuting = true + Task { + await perform() + isExecuting = false + } } } - .disabled(statements.isEmpty || isExecuting) + .disabled(statements.isEmpty || isExecuting || prepared == nil) .accessibilityIdentifier("sql-review-execute") - if action.isDestructive { + if action.isDestructive || !action.takesDefaultAction { button } else { button.keyboardShortcut(.defaultAction) diff --git a/TableProTests/Core/MCP/Protocol/Tools/MCPStatementConsentGuardTests.swift b/TableProTests/Core/MCP/Protocol/Tools/MCPStatementConsentGuardTests.swift new file mode 100644 index 0000000000..de73e8483d --- /dev/null +++ b/TableProTests/Core/MCP/Protocol/Tools/MCPStatementConsentGuardTests.swift @@ -0,0 +1,78 @@ +// +// MCPStatementConsentGuardTests.swift +// TableProTests +// +// A client that declares elicitation answers its own approval prompt, and TablePro then treats the +// statement as pre-cleared. Only an admin-scoped token may buy out the Mac dialog that way. The +// enforcement lived in an overload nothing called, so the source scan is half the point: the +// regression is a missing argument, and the behavioural half cannot see one. +// + +import Foundation +@testable import TablePro +import Testing + +@Suite("MCP statement consent guard") +struct MCPStatementConsentGuardTests { + private static let gateSource: String = { + var url = URL(fileURLWithPath: #filePath) + for _ in 0 ..< 6 { + url.deleteLastPathComponent() + } + url.appendPathComponent("TablePro/Core/MCP/Protocol/Tools/MCPStatementGate.swift") + return (try? String(contentsOf: url, encoding: .utf8)) ?? "" + }() + + private func principal(scopes: Set, tokenId: UUID?) -> MCPPrincipal { + MCPPrincipal( + tokenFingerprint: "test", + tokenId: tokenId, + scopes: scopes, + metadata: MCPPrincipalMetadata(label: "Test", issuedAt: .distantPast, expiresAt: nil) + ) + } + + @Test("A write-scoped token cannot pre-clear the confirmation for itself") + func writeTokenCannotPreClear() { + let effective = MCPAuthPolicy.effectiveCapabilities( + [.mayWrite, .confirmationPreCleared], + for: principal(scopes: [.toolsWrite], tokenId: UUID()) + ) + #expect(!effective.contains(.confirmationPreCleared)) + #expect(!effective.contains(.preCleared)) + #expect(effective.contains(.mayWrite)) + } + + @Test("An anonymous caller cannot pre-clear even holding admin") + func anonymousAdminCannotPreClear() { + let effective = MCPAuthPolicy.effectiveCapabilities( + [.mayWrite, .preCleared, .confirmationPreCleared], + for: principal(scopes: [.toolsWrite, .admin], tokenId: nil) + ) + #expect(!effective.contains(.confirmationPreCleared)) + #expect(!effective.contains(.preCleared)) + } + + @Test("An admin-scoped token keeps its pre-clearance") + func adminTokenKeepsPreClearance() { + let effective = MCPAuthPolicy.effectiveCapabilities( + [.mayWrite, .confirmationPreCleared], + for: principal(scopes: [.toolsWrite, .admin], tokenId: UUID()) + ) + #expect(effective.contains(.confirmationPreCleared)) + } + + /// The stripping only runs on the overload that takes a principal. Calling the other one from + /// the MCP path is the bypass, and it compiles cleanly. + @Test("The MCP statement path always names its principal at the Safe Mode gate") + func statementGatePassesItsPrincipal() throws { + #expect(!Self.gateSource.isEmpty, "MCPStatementGate.swift was not readable") + + let call = try #require( + Self.gateSource.range(of: "checkSafeModeDialog("), + "MCPStatementGate no longer reaches the Safe Mode gate" + ) + let arguments = Self.gateSource[call.upperBound...].prefix(300) + #expect(arguments.contains("principal:"), "MCPStatementGate must pass principal: to checkSafeModeDialog") + } +} diff --git a/TableProTests/Core/MCP/Protocol/Tools/MCPStatementGateTests.swift b/TableProTests/Core/MCP/Protocol/Tools/MCPStatementGateTests.swift index c4f301f61a..d1e68e4401 100644 --- a/TableProTests/Core/MCP/Protocol/Tools/MCPStatementGateTests.swift +++ b/TableProTests/Core/MCP/Protocol/Tools/MCPStatementGateTests.swift @@ -175,14 +175,35 @@ struct MCPStatementGateConsentPolicyTests { #expect(!requiresConsent("DELETE FROM users WHERE id = 1", safeMode: .silent)) } - @Test("The preview a user sees is one line and capped") - func previewIsOneCappedLine() { + @Test("The preview a user sees keeps its line breaks") + func previewKeepsLineBreaks() { let preview = MCPStatementGate.preview(of: "SELECT\n\t1\n") - #expect(preview == "SELECT 1") - #expect(!preview.contains("\n")) + #expect(preview == "SELECT\n\t1") + } + + @Test("A statement a user could read is shown whole") + func previewKeepsAReadableStatement() { + let statement = """ + UPDATE accounts + SET balance = 0 + WHERE customer_id = 42 + """ + #expect(MCPStatementGate.preview(of: statement) == statement) + } - let long = MCPStatementGate.preview(of: String(repeating: "a", count: 900)) - #expect((long as NSString).length == 401) - #expect(long.hasSuffix("…")) + /// The cut used to land at 400 characters, which is before the `WHERE` clause of any statement + /// worth confirming, so the user approved a filter they never saw. + @Test("A long statement keeps its filter and is marked as cut") + func previewCapsWellPastAFilter() { + let padding = String(repeating: "a", count: 600) + let statement = "UPDATE accounts SET note = '\(padding)' WHERE customer_id = 42" + let preview = MCPStatementGate.preview(of: statement) + #expect(preview == statement) + #expect(preview.contains("WHERE customer_id = 42")) + + let overLimit = String(repeating: "a", count: MCPStatementGate.previewCharacterLimit + 500) + let cut = MCPStatementGate.preview(of: overLimit) + #expect((cut as NSString).length == MCPStatementGate.previewCharacterLimit + 1) + #expect(cut.hasSuffix("…")) } } diff --git a/TableProTests/Core/Services/Execution/ExecutionGateTests.swift b/TableProTests/Core/Services/Execution/ExecutionGateTests.swift index a459402735..050ed9e3da 100644 --- a/TableProTests/Core/Services/Execution/ExecutionGateTests.swift +++ b/TableProTests/Core/Services/Execution/ExecutionGateTests.swift @@ -11,15 +11,17 @@ import Testing final class StubConfirming: OperationConfirming, @unchecked Sendable { private(set) var callCount = 0 private(set) var lastDestructive = false + private(set) var lastRequest: OperationConfirmationRequest? private let answer: Bool init(answer: Bool) { self.answer = answer } - func confirm(sql: String, operationDescription: String, connectionId: UUID, isDestructive: Bool) async -> Bool { + func confirm(_ request: OperationConfirmationRequest) async -> Bool { callCount += 1 - lastDestructive = isDestructive + lastDestructive = request.isDestructive + lastRequest = request return answer } } diff --git a/TableProTests/Core/Services/Execution/OperationConfirmationPromptTests.swift b/TableProTests/Core/Services/Execution/OperationConfirmationPromptTests.swift new file mode 100644 index 0000000000..54ac22f2c3 --- /dev/null +++ b/TableProTests/Core/Services/Execution/OperationConfirmationPromptTests.swift @@ -0,0 +1,186 @@ +// +// OperationConfirmationPromptTests.swift +// TableProTests +// + +import AppKit +import Foundation +@testable import TablePro +import Testing +import TableProPluginKit + +@Suite("Operation confirmation prompt") +@MainActor +struct OperationConfirmationPromptTests { + private static let escape = "\u{1B}" + private static let returnKey = "\r" + + private func makeRequest( + sql: String?, + caller: OperationCaller = .userInterface, + connectionName: String? = "Production", + isDestructive: Bool = false, + operationDescription: String = "Execute Query" + ) -> OperationConfirmationRequest { + OperationConfirmationRequest( + sql: sql, + operationDescription: operationDescription, + connectionId: UUID(), + connectionName: connectionName, + databaseType: .mysql, + caller: caller, + isDestructive: isDestructive + ) + } + + // MARK: - The statement + + /// The whole point of #2759: the statement the user is approving reaches the dialog intact. + @Test("A statement past the old 200 character cut is carried whole") + func longStatementIsNotTruncated() { + let statement = (1 ... 40) + .map { "UPDATE accounts SET balance = balance - \($0) WHERE customer_id = \($0);" } + .joined(separator: "\n") + #expect((statement as NSString).length > 200) + + let carried = OperationConfirmationPrompt.statement(of: makeRequest(sql: statement)) + #expect(carried == statement) + } + + @Test("Surrounding whitespace is trimmed but the statement's own line breaks survive") + func statementKeepsItsLineBreaks() { + let carried = OperationConfirmationPrompt.statement(of: makeRequest(sql: "\n\nSELECT\n 1\n\n")) + #expect(carried == "SELECT\n 1") + } + + @Test("A request with no statement has nothing to show") + func missingStatementIsAbsent() { + #expect(OperationConfirmationPrompt.statement(of: makeRequest(sql: nil)) == nil) + #expect(OperationConfirmationPrompt.statement(of: makeRequest(sql: "")) == nil) + #expect(OperationConfirmationPrompt.statement(of: makeRequest(sql: " \n ")) == nil) + } + + // MARK: - Who is asking, and where + + @Test("A named MCP client is named, with the connection it is reaching") + func mcpClientIsNamed() { + let subtitle = OperationConfirmationPrompt.subtitle( + of: makeRequest(sql: "SELECT 1", caller: .mcpClient(label: "Claude")) + ) + #expect(subtitle.contains("Claude")) + #expect(subtitle.contains("Production")) + } + + @Test("An unnamed MCP client still says a client is asking") + func anonymousMcpClientIsDescribed() { + let subtitle = OperationConfirmationPrompt.subtitle( + of: makeRequest(sql: "SELECT 1", caller: .mcpClient(label: nil)) + ) + #expect(subtitle.contains("Production")) + #expect(!subtitle.isEmpty) + } + + @Test("Every remote caller is distinguishable from the app itself") + func callersAreDistinguishable() { + let subtitles = [ + OperationCaller.mcpClient(label: "Claude"), + .appleScript(client: "Raycast"), + .aiAssistant(sessionId: nil), + .userInterface + ].map { caller in + OperationConfirmationPrompt.subtitle(of: makeRequest(sql: "SELECT 1", caller: caller)) + } + #expect(Set(subtitles).count == subtitles.count) + } + + @Test("An unknown connection name is left out rather than shown empty") + func unknownConnectionIsOmitted() { + for name in [nil, "", " "] as [String?] { + let subtitle = OperationConfirmationPrompt.subtitle( + of: makeRequest(sql: "SELECT 1", caller: .mcpClient(label: "Claude"), connectionName: name) + ) + #expect(!subtitle.contains("''")) + #expect(!subtitle.isEmpty) + } + } + + // MARK: - Destructive + + @Test("Only a destructive operation carries the warning") + func destructiveWarningIsConditional() { + #expect(OperationConfirmationPrompt.destructiveWarning(of: makeRequest(sql: "SELECT 1")) == nil) + #expect( + OperationConfirmationPrompt.destructiveWarning( + of: makeRequest(sql: "DROP TABLE users", isDestructive: true) + ) != nil + ) + } + + // MARK: - The no-statement alert + + /// A rename has no statement, so it stays an alert rather than rendering an empty review box. + @Test("The no-statement alert names the operation and never trails a blank line") + func statementlessAlertReadsCleanly() { + let alert = OperationConfirmationPrompt.makeAlert( + for: makeRequest(sql: nil, operationDescription: "Rename users to customers") + ) + #expect(alert.messageText == "Rename users to customers") + #expect(!alert.informativeText.isEmpty) + #expect(!alert.informativeText.hasSuffix("\n")) + #expect(alert.informativeText.contains("Production")) + } + + @Test("The no-statement alert keeps Escape on cancel and takes Return off execute") + func statementlessAlertKeyBindings() { + let alert = OperationConfirmationPrompt.makeAlert(for: makeRequest(sql: nil)) + #expect(alert.buttons.count == 2) + #expect(alert.buttons[0].hasDestructiveAction) + #expect(alert.buttons[0].keyEquivalent != Self.returnKey) + #expect(alert.buttons[1].keyEquivalent == Self.escape) + #expect(alert.buttons.filter { $0.keyEquivalent == Self.returnKey }.isEmpty) + } + + @Test("A destructive operation with no statement is presented as critical") + func statementlessDestructiveAlertIsCritical() { + let alert = OperationConfirmationPrompt.makeAlert( + for: makeRequest(sql: nil, isDestructive: true) + ) + #expect(alert.alertStyle == .critical) + } + + // MARK: - The review dialog's confirming button + + /// The alert this dialog replaced took Return off its confirming button on purpose + /// (`AlertHelper.addConfirmAndCancel`). A confirmation raised by an MCP client activates the app + /// over whatever the user was typing in, so a Return already on its way would answer it. + @Test("A confirmation raised for someone else never gives Execute the Return key") + func confirmationExecuteIsNotTheDefaultButton() { + for isDestructive in [true, false] { + let action = SQLReviewSheet.PrimaryAction( + title: OperationConfirmationPrompt.confirmTitle, + isDestructive: isDestructive, + takesDefaultAction: false + ) {} + #expect(!action.takesDefaultAction) + } + } + + /// The Users and Roles review is a step the user asked for, so its Execute keeps Return. + @Test("A review the user opened keeps Return on its confirming button by default") + func userInitiatedReviewKeepsTheDefaultButton() { + let action = SQLReviewSheet.PrimaryAction(title: "Execute", isDestructive: false) {} + #expect(action.takesDefaultAction) + } + + // MARK: - MCP titles + + @Test("An MCP operation label becomes the dialog's title") + func mcpOperationLabelTitlesTheDialog() { + let titled = MCPAuthPolicy.operationDescription(for: "transaction begin") + #expect(titled.contains("transaction begin")) + + let fallback = MCPAuthPolicy.operationDescription(for: nil) + #expect(!fallback.isEmpty) + #expect(MCPAuthPolicy.operationDescription(for: "") == fallback) + } +} diff --git a/TableProTests/Views/SQLReviewSheetTests.swift b/TableProTests/Views/SQLReviewSheetTests.swift index 63b881ad7d..0c37089818 100644 --- a/TableProTests/Views/SQLReviewSheetTests.swift +++ b/TableProTests/Views/SQLReviewSheetTests.swift @@ -78,6 +78,79 @@ struct SQLReviewSheetTests { #expect(result.display.contains("501 more characters")) } + /// A preview may make MQL easier to read. A confirmation may not: the user is agreeing to the + /// text in front of them, so it has to be the text that runs. + @Test("Verbatim mode leaves MongoDB Extended JSON and the terminator alone") + func verbatimModeDoesNotRewrite() { + let statement = #"db.users.deleteOne({"_id": {"$oid": "507f1f77bcf86cd799439011"}})"# + let result = SQLReviewSheet.build( + statements: [statement], + databaseType: .mongodb, + verbatim: true + ) + #expect(result.full == statement) + #expect(result.display == statement) + #expect(!result.full.contains("ObjectId(")) + #expect(!result.full.hasSuffix(";")) + } + + /// A preview may stop early and leave the rest to Copy All. A confirmation may not: a `WHERE` + /// clause past the cut is exactly the part the user needed to read. + @Test("A statement past the display cap is still shown whole when it is being confirmed") + func verbatimModeNeverTruncates() { + let padding = String(repeating: "a", count: SQLReviewSheet.maxDisplayChars + 5_000) + let statement = "UPDATE accounts SET note = '\(padding)' WHERE customer_id = 42" + let result = SQLReviewSheet.build(statements: [statement], databaseType: .mysql, verbatim: true) + + #expect(result.display == result.full) + #expect(result.full == statement) + #expect(result.mode != .truncated) + #expect(result.display.hasSuffix("WHERE customer_id = 42")) + } + + @Test("A preview past the display cap still truncates and says so") + func previewModeStillTruncates() { + let body = String(repeating: "a", count: SQLReviewSheet.maxDisplayChars + 500) + let result = SQLReviewSheet.build(statements: [body], databaseType: .mysql) + #expect(result.mode == .truncated) + #expect(result.display != result.full) + } + + /// The windowless path holds the main actor inside `NSApp.runModal` until the button resolves + /// its gate, so a confirmation that deferred the answer to a task would deadlock. + @Test("A confirmation answers on the button, not on a task") + func confirmationWorkIsImmediate() { + var answered = false + let action = SQLReviewSheet.PrimaryAction( + title: "Execute", + isDestructive: false, + takesDefaultAction: false, + work: .immediate { answered = true } + ) + guard case .immediate(let perform) = action.work else { + Issue.record("a confirmation must answer immediately") + return + } + perform() + #expect(answered) + } + + @Test("Applying a plan keeps the asynchronous form") + func applyWorkStaysAsynchronous() { + let action = SQLReviewSheet.PrimaryAction(title: "Execute", isDestructive: false) {} + guard case .asynchronous = action.work else { + Issue.record("applying a plan runs for as long as the server takes") + return + } + } + + @Test("A preview still rewrites Extended JSON and terminates the statement") + func previewModeStillRewrites() { + let statement = #"db.users.deleteOne({"_id": {"$oid": "507f1f77bcf86cd799439011"}})"# + let result = SQLReviewSheet.build(statements: [statement], databaseType: .mysql) + #expect(result.full.hasSuffix(";")) + } + @Test("Empty statement list returns empty display") func emptyStatements() { let result = SQLReviewSheet.build(statements: [], databaseType: .mysql) diff --git a/docs/external-api/mcp-protocol.mdx b/docs/external-api/mcp-protocol.mdx index 8fc9a54f5d..a62836ae71 100644 --- a/docs/external-api/mcp-protocol.mdx +++ b/docs/external-api/mcp-protocol.mdx @@ -255,6 +255,8 @@ Without `elicitation`, TablePro shows its own confirmation dialog on the user's } ``` +The `description` carries the statement verbatim, line breaks and all, up to 2,000 characters. Render it as a block rather than a one-line label: it is the only thing the person sees before they approve, and a `WHERE` clause that falls off the end changes what they agreed to. + Present the form, then repeat the **same** call with the answer and the state echoed back: ```json @@ -272,6 +274,8 @@ Present the form, then repeat the **same** call with the answer and the state ec A call that carries `inputResponses` or `requestState` is never cached, whatever the method's normal hint says. +An accepted form stands in for TablePro's own dialog only on a `fullAccess` token. On a `readOnly` or `readWrite` token, and on the anonymous loopback principal, Safe Mode still puts its dialog on the Mac afterwards, so a write is confirmed twice: once in your interface, once in TablePro's. Ask for `fullAccess` at [pairing](/external-api/pairing) if the second prompt is not what you want. + ## Errors TablePro's own error codes live in `-33000` and above. The `-32000` block is frozen by the specification and TablePro no longer uses it. The three codes in `-32020` and below are defined by the specification itself. diff --git a/docs/features/safe-mode.mdx b/docs/features/safe-mode.mdx index 1f7d83de40..31b55746a8 100644 --- a/docs/features/safe-mode.mdx +++ b/docs/features/safe-mode.mdx @@ -18,7 +18,13 @@ Six levels, one per connection, set in the **Customization** pane of its edit fo New connections start at **Silent**, which is the right choice for a local database you own. Move a shared staging connection to **Alert** and anything with real customer data in it to **Safe Mode** or **Read-Only**. -Four things the table cannot carry. The confirmation dialog previews the SQL it is about to run. Touch ID falls back to your macOS password on a Mac without it. **Silent** is not a free pass: `DROP`, `TRUNCATE`, and a `DELETE` with no `WHERE` still raise the built-in dangerous query warning even there. And **Read-Only** goes past queries to the interface itself, disabling inline cell editing, adding, deleting and duplicating rows, table truncate and drop, and import. +Four things the table cannot carry. The confirmation dialog shows the whole statement, syntax highlighted and scrollable, with a **Copy All** button and a line naming the connection and whatever asked to run it. Touch ID falls back to your macOS password on a Mac without it. + + + Confirmation dialog over a query tab, showing a fourteen line UPDATE with Cancel and Execute + Confirmation dialog over a query tab, showing a fourteen line UPDATE with Cancel and Execute + + **Silent** is not a free pass: `DROP`, `TRUNCATE`, and a `DELETE` with no `WHERE` still raise the built-in dangerous query warning even there. And **Read-Only** goes past queries to the interface itself, disabling inline cell editing, adding, deleting and duplicating rows, table truncate and drop, and import. ## Connections that are always read-only @@ -100,4 +106,6 @@ A write from an external client (Raycast, Cursor, Claude Desktop, any MCP client 2. **Token scope** (per integration: `readOnly` / `readWrite` / `fullAccess`), issued by the [pairing flow](/external-api/pairing). The effective permission is `MIN(token.scope, connection.externalAccess)`. 3. **Safe Mode**, per query. Everything on this page then applies, Touch ID prompts and confirmation dialogs included. -`DROP` and `TRUNCATE` always go through the `confirm_destructive_operation` tool, which needs a `fullAccess` token and the user's approval every time: through the client's own elicitation prompt where it has one, otherwise through TablePro's dialog. No token scope skips it. See the [External API security model](/external-api/index#security-model). +`DROP` and `TRUNCATE` always go through the `confirm_destructive_operation` tool, which needs a `fullAccess` token and the user's approval every time. No token scope skips it. See the [External API security model](/external-api/index#security-model). + +A client that answers its own approval prompt has only answered its own. Only a `fullAccess` token stands in for TablePro's dialog. On every other token the dialog still appears on the Mac, so a `readWrite` client asks twice. diff --git a/docs/images/safe-mode-confirmation-dark.png b/docs/images/safe-mode-confirmation-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..35ed401406f49cb13a4907ca518678007c924e35 GIT binary patch literal 616891 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

      {KnN1w)nXR4cGB-0@LI~WQFy3*w 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

      n9i#K{Uqd&M=c2Kp;S883Gq}1BA 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

      %OvzaRWqkKAB;z5n&;aK~O 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
      MMp0M#2?rs1D^QD`6>Hsl)?{fEXh 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
      U zLt{JEdYiu_6&36XoQS)781tE6YV;B>5C&Y_f!ZK%SD?Soeler$$Kx*jO4U~8UDbPU zZ?awt4ijHFU-j17Aew4i`f-cN9d))wg^IIwPf_l1WNIhyV;ieL_$bDC3M`#5GU;;88FY9&r{ zb1}=dI&njT;i6w#n97mthZ+~VlWP9b2jumdysRc@tH!leRbo{?XQEC|PWwxU9~+VlCX-5XG2;5f=x{z~F+XK%)f{yu zWqI*`9+yTv5xt1#(3)d~g?p#=C{Gp_GLM#1{LcYhNc~@ysF?rXkKpS@3Uk~ShevQf zZSQQ{@Lf-8i;~=v_iMR{e5QkxML)sM0QpS-a8Brf3W{4QY2VmN%2Lk|Zyd**E z^^fNo!)y~Op)*5L-1vMQqmot}f0ij&%RT3oLB(f&}Y`V3sy z91d;7BRbT;TLT}IlAUs(s&8;gpLXsP%Z91sK4&4)Huv)TqL_eZ{ZH_dxy6X7ndUWc zfKK=nB?u;Gw{Ld^oF|eSou$tLT|%mP>(8ozJn9&5MX3N^-?*Jli$Up!`zfRcz-zxh z!A~pBVVFp2_@AfjuP}_&9x;qd{SxY0YFH##m4uI?bw*Bd%wvZ#fgRSZW4D`p?89)x zEFLxPZamoOwqVqMji_nWN5jq)XkG6yw-~oxr2$_#+u8+<4zIz3b6&C3W?t=-4QvhsFOx{`EwphT0qzuij-vp)OF|{XI)K$lGBLeMT;r;r z^w~iO!{(oxJGYA~D>qy72-?{dqAI>gHqiP(RW5SErA`>7WZcq;kwS5s0i$5h!tSk+G(iDo3s&3Ke;|j7p%RkpEsv# zK)#RY%>mr5_9haYpbVaF=F^qxsZ@!TUL<#@tD&yBRuf1jfcsvz8HoWTlD z^E6|-rDjhavqo*Jp@|#Q=W?ofK+nGBa9`xJSoAh_G!;Ow%(u#g4#^(E2Tjv^XtVwa7iz=tJPaeOaqxH?vZnx_cQ${mIg1+un@pGAc9gD3^|cl za`p4Jb9PQk6ZsM@NbVgP=nc}z?u+9$I`Id>cQ;Hq!_NAqKvb)@^(YpnRsR^LDpy=# zz}eJ#oNXuF&mFJ&w)W%Ip(tQkgG+j~OJ2Ml!&GPb7gm1pm?^K@l~=PaOB}>TU0G{> zd;zE4V9mOZSGBfVPanQtU)4aw4mPiR)SkkDyVgBEJ{k zB&fM^M5!0`y}~6Jd=L|-;lm_csaJyeZN@Hbl1?oy-Ysr$9W*x7 zNq4>e53u_mU0@PH&91vI*PQKp#IJnRmDHj%gN5F*W{y=ckkv}4u!?jfx?iv?Ic+KY zOM0CKcj8SE$Mi(>Tm1ZIg&@Rpf=#jwo)ArZ+5@(C+8WlHgh)9^5R2J*%XE<-X{g1s zQ3|K%5%$1qq~)O1)bg*A9hw|z7zxuB^?mFWHoD}Mr^7!af6d1v4ODVS=g-?*V72hD z`th(w+s=W7f$u^iHaUf=3v=LWlcqY8M#lI<<=B0b{-L+LVO!if57g3YP(@#?zcJRm zP2ea+&{3=*i%M!)T?;*}=vGP1n{UKeB zw6+XwLM@6>en=V5{IQjyF$;52iR#`1#uL`oFDW4w&(auB^S^voq^d`EYtJyQR2o0n zLc$Z+>DPw_Qru3KThCzR)!YGcdkO!#m6-j;-sA5dYC#p3@CGQdBoIHksX5eeDl*a7 z!n4Cv!{E|>%jP;k81Y;_wG8AOCrEm1Xnx#0ygNt6Bm1Y$@g7!>kp5MDJ=uwDQ(8rC zeb56sNnSO#EA>u~5LJKiH>G!HYL{7J2r zFL*I)FUw)Z>U(P|qjLa6u&?TQ1bsZxbl!dV-pOG$P1Msh6?Y!38YcH%;kd09%9`wF zmhZ*^qA1tItA!elVzh1o0r%{QnOKyLvtf-|AJ4988zy9XYA4N0=0Qkyl=?K2)noto z_5@^;CwnCM(afp|#o_IV>TOY!+g&`WV0Pw=L>sEuZ4%K(=@UvlBHE$imn)wgmh-(Pi2oQhMLLWf-=?olNg;asi4Tm7y2 z@!{Is?HdJ6V_)3X*6!b!-%2z`q<&nOE(9Bl%j5vm!FS4cXt9d1`4*kH{Ek)qB0WeweXm z)0KQcwcd+lP%03){ zk1Q|x(5{9ZV8q`&2gMO1Q_JGuD{e!*?gNHwYu-S&8@+_yb?-p$h!;I_fFl9z2aV1miP8rsm<^Zzo3z6s>CrxLa?G{e2{7j1 zO~hgR9$<#9jvK9%(LITtFshB>pDOomDENNr3-Oo!*}m`N<1>$>6!+mdTJ11i#gr(F zhqFhMlB+yokNTuuwApqRhdaq{*Um*H#QxFxuAri%JY03x!vWa1$l>j}OeHa(v$A$? z)FR+k{CjhME*HnL5G_W)iHURZb(AEroH-3WMfQQ7M}Q4ht-zO6#@16XNLUr_ zVceV>DvW1(&UN(gX#Yh-(0WPtNr<<^4pSYK!VnCBBe}DRpd%GmGRCjJ|c}5jc^4Wc*;;h=R=|a9%Et zFJP>a;JB-ACVFK0^1AE2SpC4QyjbOIEookRfn8FS8Z^7uJ2o*c{JndtP78c7_KKbY zln}zl=B|wW1uzC!B)T{!^nbp)CYJ%)ESYoMHU8T6CG16?8x)`AJw(d_+88Ft^e?0= zo%+$8uIGM;f=9~mm5^2-)^(j=G|X%VO5~qf!pEvVqx6G#I-OGj!+(LSH|#9Ft$-?3 zJ&(8x0H^y7qLo4lRn4Qwc8C%4Hm;FrU_K%eqn(e)T0=$k=vDRCY3VsH7aQ>@2b)Ke z%Z3-vMl}km<&HL)JOz3Zjua@dk}QG{3A*RGS<&KoEgs#R#!aE<=yo7x1-2G+(R$VbXEEE_(6l=>B3eb17?=gFN9PPW3uq4L>4;Y+NhzHx|QzLp{kL*Rccx_N(xfP zXzr`2p20dEx3}FqT%JQ=Z^$|@nL&LPGtNggm+N^MuzZ#?rdx>d1LKQhMWju zO)Ib|WLe!?YuUbGvIpM}UkjR^yZV{lcKu|ZJ&zzmEEVOBUNeJee<5vGeu)}HZ?5$b z?dCcK^tf!?J{$wj${lTeP_#&X+5#+#y#)`bivDr?D42&P50UMl?=M1Jx}Xu4@z+m8 zb?>ouh;b)?0zsUk;6*CYs&BYgwG!e$ms2He-Ue#6NrL}Jr9*u^@c#@ z4z?Ndo7gu=q?4tG#2<-GbooNM!IA7Tp179#wXS#O9B@u+BY~o;nmMV90a+-Y9T%Wb za?hRBoV?x3HroUsGK~6-PQYSFhv*@*grd`=!qD4pH#aW_7>W z#=Uf8SS1qzdK=Gs4I|9wDo;sPTGqGPoqVXN#BHsY#C~pY%4wx>6WuJkMVoZ`ycHT( z8QntNe9_fYC@+~VFRG-^_BpSuIsK(zy$KIoFLFf$&HHt)H0AEx;jF#5KY?pjfM)h| zi>ZhMW-V=IUB{)_C^1%>kiDP}ktuF*UvpXVslr|v|1x@+c@l_J z^tt%}B3MOS0*DsH-gJd`{Ol54m^Kx&dZFK^fV@Hjpb%86?Khv3u)oz0-!h^(sOw<1 z-qO+jaRf6pZM{( z`!z%}n7nD(GjMOUj@8L`_nPPTe@rp|w8+XB8@tbaMVcaf29*y_xw!3Bq=i~E2B?Q( z9A7U)BoM{{#=>gb-HOXMljA!jKkHGRuQ9A}u@kgedmjggM zn6SS67=nL)Werj>e&iabTGLnknB13%dLsQ6@L;Y>(eI?NAQ|+lJA$-SN2WPHq4ym8 z=j_5Xz9T>}T!D~7kVF6wArGMB*xfYrj#Rt3 zQSJ-y^bR6+)8K{kTU=;oh-rm7FN!E@w-NIic^#vPsH+i4%)z-((jBGYbiawI}tdFj`F-bcPpPYqQxXm)wuf`lD*$8dMH5V+OEp(nT( zh80yK=M|rR)tYFb#?xfB=BoG!k(js zC7{EttdSZN$dB`&vse46f*FV(;2rx)S0`7)-9Yf2cbALr{m%=27ro7wW9?T)cQL5V z+^maPV;4m<;2!4+&=sO7D~y+*JW0X5G73s+XY6dtSb065UXTWcjfU5i#J6X@Yzmzr zpB3Da`Rd@>kb55w1xT8CLT=#JrY|=9cUvRT{7u&AAKLyLrX=abZ~JBZMqZr&!}U% z?fB$TPlgY!G1)?~4WCbXF@k>6eky(qdeZhx^#<@Z2}W=alnv(6!i`ba;n}=vYuZYHJeW|Zge5ft%6w`97Eg0e^!Bc8@4d{pR_}~ek>{g_ zALfvEy@gGR;E`7qV*P5osD&M$89@X`PiWZ;JEi7GSQ#!?Vnf*=Hd3%s!5aB(62#GH zF$U{q4P0ucf{0(ny5`JX9ae*>{QUj9(J{5%vz5lJ!KV3VG{Gs#zl!ypbeggCi&t70 zO?H9CsAT9z>7eWkY9XTgb}nea6deRu?7A*1g1TW}j{@AKpuxool17g@QPWfI%F5BT z6?5M~P&+j|A+6B71WIE z74F%=&!S2v?$uO_n4_HU$FmMi4Xs%xm058mHUUTalCMt7{$w>Y#1a6(wh?JD33mP# zP6E$!zPO%2h{Er=4V02n%2Uf*Q3=7n-O#=qjgOucrj%m-vv%}d$a}o7_fK7jym+bD z?d9IgRS{>s6*|5R9Xk=cutDB6AqJ25{@b);#z-(;A}_Ak_jLBIr-H+ROefD8f;@k_ zq$^Mc8Fr_{vhMxZgmla`XWJf`6+mS1mse$*DZGCx6o#75o-QVwhC!TTd@H~+u!wI% zu(W-L-ntu&Ij|5b6;Dplgx)kh+ZFd$jBs~N(`VuE1yqAZPt~vU2=|2W2&T=gj4&ou z<|k>?i97IDyRXN{Ol)!a|Z)Mw8_$DeJQW9L8P zf6~5P4Aa~`C~$NqvD)T;uG-ODBXO$yXz)yZpeF#tzMc?+a8HU9udXusSv#BdOy5f-XMU>feJY>3M;f+i zr+~xZ(X-9X!u;E!)9?=OK#>Noib=Y4bp23Q^M2B3OlTq9>SIYlOxnnz1N5Ck5V~vz zaaSBf0d%yW=$=bwZ=rVPV9#$7vxB>F0M`pGDVq~o_%kxUmgo^HIZ z^NbWrmjmj$Hf&E$TzxAM3q3Xrqm< zX=jb4P=c%hpUx?$__zeb_}~{-(sQLyOq^x>oozKKET55MHFiby#S}1Lb_+t zlM50q{&WMfi6R$JB1kKtf!zpk)}$!wZD_jL%VNmG>unGthG2}BNqYWp=??Z_&3=lKIJA1) zF>?CX4el$ysA-hm5*`El=D_w-oFT{Y z0abB_u0W9kgT|eKVjO*-JF@I8#_&J}fIE6Y#+;1$T;} zCJ}4CqkHGwih#uISuxax!)Y;9jkB$KyK)!B_7??LYiz8fHvygD$DDRthM~)ARzlm@WU%RRDR{l0SWP|v^!vva9!V7#H5P%bKWu7&7Y)Ulcm-9MF z_;$F%MRh(1&4@Fsu4y&>CNH4tSxVQW>4W~}A)?8N(Ayna`D z^$?2l@ZfTr8>Q>BUw*EDE%&he>q=aIk#idNb7I5Tg#Xwu|1M=xbT4zs7|roTXDU$h zGK_?mPmN=2A5GMPpIJBY`*J#OmGE3r1G=TS^5sj;(1d(;$re-K?pgnrue1bddr3?@rjR|Ud`B$rc@dS0FvO>G?F7)D4@o1?n_R8ac9!*XHW zx=T7|c*(QohKyRl5a($ccNUo2$ao+|0s8ccbT;QVXV_m!%U_<~qH`O;JeK(<*dM1@ zZM4yc>C;#=7{x;2U-?zu2mJv!a33vLH43mb967xGJbaQ^+x0=w%=!itSeGOt>>%{! zsyj&%KlMS>b9>xM9~=6ZOv5Q%+GiPrPe_(gZ8=os!(qQ0f=w5}>cTTB*O*+-^E`Mf zoWVk(f*zzzU^_F1?q@%dP5>;E`?D-s-42GZ2JjA0_W6TRfu|*JnGkxmq>Kh ziZZT?qhozDq+D}N77~JXxNZ}q*KohG`q;SJwf|upY9JiA*LMW>*?t3h?P=LKHd=Xn zy#DPLWtGF3)uLh0raM%*($4O*dRwK{$#gT&cb_^dlr=U3@73u$QMu4lUM5usBc0H8 z)rp~808;t&!5dQNjL(D|`kXuOdwtK6;SZ!nm8@@8yfrGrZmM+i{SW2uU3_Yq?|%RK zQ&!)!P@=ZTFDXQZxq5O9LZtWvOa(5q3z^p~Wpr2rlYf0TAuGF+iBQ62oS7J=U%&Xo z_YLct_5%kBWxGdEoUB%ChW<@ies1=#it!|HEc zZ>EV=?d_0!C5F>iYWiU;gq7bv6X@X30As#;6cy0P7|F2bEDRLb40`HDN;Ap5MbAXf z$iA-#jr4&QR$NL_6-7t8O-^!8!|6|%RnOiHd}kRzyHO%uOuY7hW4|I5F3P93#J0zE zZnqBMiXqed_rwuJ!wKWGWHMg>=5(9I0-jbJw3YdB%}(Ri?;bm}vB}aV70~prMU#Q< z_W5BCx>MBh#0)E($S#-s>T-lTW#72k*{5Tqz77^x-2BldK4*j11eG;A=YSaJ*Qrh< zW|$IlUdissX<0o)P>Z-}_?$hauKDXvse`TgT~@xk`4f`wKT4L+80y`=Ny+pRy@!c* zph}z)1{MyAH*f70u`>(bF3C!S#`;@y*tWRa{XRFy>8L5X~_Mev1xP@$>AWw&lzd8svd z6gurZg6jUaF4nkVu+O{|y0>IB<0f|(FeLvDsmh55yx({>BG$}a_d@A`j zIHh%z-!%YWLUk~=uo}I3KCp&cKIeQ6$9=Pg?-ICYTh!huC=uHEsyZ}gcLVMDQ60W( znHE%sx6vZlQAe&}0K^O!zY}^2*c3VvqPf;WeQ?kAIjM0Y$hA1TL0uH)J9Z$=8UvQk zlX9^tIWKGiCiW4(V{$~@;K>cWNW4?nd3+m1g4*0EE;SN>>OVUN-fz3D1U{v0(loYr zuH}|cHZ+uu(^%1~FDkL8AW>KRw%w2KzvfSKb+o*wxsd}#2zT`dUDvP6pzhZk2MYhU zk2?F41SmCkC`K^5hGpOWj~tCkG!zzpCi1MZevlK0%z6>FAncwa&7=#8%UvM865M3nLHGXb!cVY3HZ4zYM>sdB5S$7Bm0oM zA|l9VgxMe-4L9Vsn0wbF!;jsZVi}Cr$zM2zko`y!|1i&Ic~Tg+6{O;*R?d0NhxfTP zqnPiBIrEZ06V_S^82mS2k&3G$OTu$4TV+4CVM5M~ed`HnJZmOt|GKWf_WB9zWckB_ zxp1PteOPdj8qH`1u6Bty;Wl2~(Po;S)O>aW3ZCRD%cRD;;j2xlDAL6dax#~k~ zN=nL!pdXe$i)WarzB8_Jxjwwc6)FWbsue_VuvfEU{b*D9j*x%tC2K7qfr9S?u|!S@ z&jp|gkNA9ce37i3pGK{k(DKr~WJ@ZOBolgKX<>tRJ2m4@|0sl2vDb+6jk# z#S@+NL`RFG!{N-)!5-%5z1jbT6pS}d9%8~~^%k~R`}rZ_uhhRy#wCjXm9B9;T=`N3 z0pTX?ZYj#H?5t#3R0kYhnx8u383sA}EBN%^Bg@Z1s*$M+ZkhoRQ15g;vfiC$YBiCv9ybn$8<4A_5OGIN2; z>bs-c1L^q4LE*o#P;)Bb9ntuvDJ&iZ%*6%3yY#!E!mH1|tvGh!;&lig`Jb-rxJs{f zuH6UJ1|zR?-gL#`f#-6bn!@W{Lu(TfYPO3HyWay4mgb{OP{(&#o1KOI z?2Sp~1pv2FMHMB-((H@f=kM&C9aG|v4*DC%&NhXCy0!-OzA`)oicw5}=CIv@f~h!fActdZS-QJO91A-9G_UnFii9Nrb9ZIAyW56PqX z^wcmgTVa{5l_thf2X8LL#|RbW>e9R{O*_?{wW0#)9e|j$#SUuFf^S*!9@5MHVuly{ta`E1B2aPeb|K0G24DugExNgN?~gtWbY%nP%^Y>A^(z zxp{+mG)BkTuRrv~ZN_hEh$+{1qP2WxkL5pY+p9|PrHUXQ6#nT$|0e;`>Prz=HWa;C zZT3{20^}YmiuYV}3@~>E&*I`29xnv*GX&ccjJIl?R{os|=pW*w2a?;0k$56ZT^#Ry z>lzt`>^d&t?Xi1X)W6DqtXj<{x&^}l*H=^d=&*;Qm7l^#%dPZR*VhqgrhbDC4QTgi zjqPm?kBAR1g(Qb7B$+90i`<%QF?Ve^RpFkpLykBHfY`+t0F2S%2qRNEgP+)*t zF~pp1Q|XN$<<9`9$6Y<(zWyu^E|`ekDlinS26sID^CxeGIVa#^(6J5SM1j^A3Siv@ zI0%2WCyZp{^y^M&U5K$|e5wv6^#cac9kuLBd;~3m&MeorT~Tja0%{=*s{uQZ?k4gV zp~u10Ekw(}6>pt|#V%E$B4H zd=uGG7aXKw(BUrAatprC^79tJ^8;#8Y@)L`ToGU}W%yW*_wZ(2KC)~Li8wn0+{rBs z1Z{?#Vhc;MkneAs3g+Jm*-wS`0HKS`(kSEe>TnPs2aJ0ttVUnxehqaC zuy5K7Y-BtVKdU->1xCipskN3uPD7c44nO$v#(>X{OS+IxPjG*}SSD)|a>n{gqQn(7 z@e7KWkhZ+eL3MKrCl~$qO#XyHhIPj;o&&-EQQWtgF78>|R%T?gzLrQxvl$g2c(dBTIN_YuJ0-*ud*xe>3EF4Gr zA-1ZzR0KzSkC^};Qr8xke)=2XH4{NIBcU(lu068YdqYC;yRX$cyB+w67y5>Y#{GA|HGni>G5$E6 z9?7$7E~$A?4F+RVAIlp!fXS01S+;B#*N;m{K{@)uD1-YX-n*IctyV}1(VTxzTIUtx zeSS)36f)ZB?CA6qX!vs82z~D<#$ejQJ>jf$PUOBky))46aOi8<@1y3}XF5MPPjpJ} z$Ar$_RMnhT;YFl@FMYMismXEI5C{;3i_dL*L>4tXV|-$U(<7t8`I#$r8VoW-ehA{v z7P+7lF3)OaW|Eh2R52cJZrAu&iok|is(QJW$2-Q4AEYEf6KTEFKW* ze!A4bMZT=i-`y&_`n+urncVK)>6a}ASH8Q1ARR=mK7jb0I<_hKsGC(Bw=e}I@i8@W zvC%|aZiH|rRJJkQX&|lnFa|HsIBa0dZ@O+6!gS>j)?@^q$ic6f@SD;`CkgEiFK*C#Q#!kG(s+5fdb zn-#rMgcOF;a!nK7%P`;_O0rH1=BDSS#rVB@a$z?-oBYyiy7d7pGh+4< zdFS$|s%qb}7|odZgtXzSWz!vjn7+D~c5Kb`7vf52BSTOG&&NDvusQ0|{opZ{rD_)k z+4 zeJhVoo$IO7#q9|u16Qes73%V&`<$fz^$uldU(urL#W@L)k>uI0$70gmWmEeaZN|@@ z6cUW(=;q=I;;F#6#p4)!1d9)$Y)X*^K+STu378^9Q{cC0w;k(X0dDrM1eIa+G7|z7q|$NN~#J z_0po(&2gBgepS>3^qRCtY1DO)ZUI-mRZ_{0Q$ zjz98#{ivLJiZK#4B$ zVybOrNd_|J+!O_0cI@vmuzu{%e}|^H^KI{E$5$KKOhnxIOcHSSRS*UMVdp=@ z%ax`o+MW-*wE4(kltLd@^MiZ8*wBmgD{aMM`A~wq!AuG0B27{=Q)XP@0QTGpD?g@& zO@WN|s;(j!7XKUK%6}b~=K0Tw^p17W<5O{fHYli2|GCTB`SnXg+JIB<|9J83rC*?WX>+dd`;JQKZH=A0A7^mx&1{W^fDn8I<&Iu!k8uebaThA60HA@J$3O^8cjhirs$+8 z-XmURG(Wi>!H6`{W-zx`lIo1DMkCO$65w!(7a|aq>E#&q;3XFSgzgon8LxsY(_T<- zv-{fN!UI)RfVmkHWTi_C~q1&@ziXg8F)GIFy+SpJE@o1}LuLp8K}Nh0q)?9Wuy z%ES5)=nD22XnC@g7*%`D;})bKW=?D z7q>RImS8pp&8E>OM;pjJ3tUP+Ws-9-)auf0XkZff>NA+mXhAhrmJMz6vlE5tYmK5m zQYQlkC-y+48T|0w#f5MElm&OUW&~p)8_N(0CZF-UB8E@7tZ;>;0xQ3>n3o^-*Q%+Z zDz=J<$AKe1m6)Wabr}C%ksKJ9=-bVmwxvrRVVrL1U?FNC7GAVeha&2JYN_-yqQ^OV zUI_zhv$T#MreXeRlRL|Wu1xh)X@2tG(G%STye;Mtc*)f_s7@zk*Lsc-^yF78;}wNV zf^D(vmy4ZGBPcG4X8}K+rosw$#~TN1G&_wVoi&?4HkR&vo%UxTjN*b7Gp<4@c~(rDksVtL{k3SLSHBFY)2w zDNcz-Zj{Ba{1QX{yEo$K-2j=byN?L$KtJ9Q`)og35WnEgrjbX{tkXhqq6IoVP2ZB# zzO=-F7DRKuCd#vxQF!8!*DlMWCfC~8I%Kgu#c_9-7Js3B8!f@mLHF|e4@ZeQJ};yM zwKIG3nu@WIXF*nhWE`@C&Q})k^S5}2`~MQ1{GZ$#nqXhrPjc+Woxc~=O@7u@gkM)H za|SFh%Wo`g*Z$hfkjqEA-$zH`OJZs1rMK~7Oi6=bP|o&b{tr+AxT7^%fud3#PBzgf z;ciuRh;Yp4E0h;fLrtU^IQ`K;G0uLOr(duxO-KNr;d9N#F<{W)Of-LmAp6gm1G|_k zj&T;f#uXTBHWwO3$Za6l9|Ya?t@W)a0*TzqVI2hu=xDg&Xm< z@R9cC{`v){qrEf4Y8oKX{l~}DgKb4R3V`vS%sMSv{wHQc(JX`DS3Qic5;>!54ES_c zLKx+sg%@V-jzu%A`QkpW#9V%~z;Kc9I(exy*-#2qGM0_atda9PEu7nMG@KjQbTyb% z(luUmS3H29@=eSh<)?9_caYP_*$7Bth-Hj|8nPX0q_6_(pKNKMqNF5k27q~1mYCXM z(K|lKiMWF%!}oXh#n+-+KqtN1oE$nk9p&OfU_geb?|sZk;=bAkt zA4X-)KLj5C-$n^a`?b1{@KB(WX$$}SWPwUam(9rxF?^U=39@HZ%WPuQDQCfXdb6R@ zVs{q*{PqtJ|1Q(mlJHc4q2A=HO()+w$(T%;Rd&*dxvi)H>o~-?H}_zq5S0e>V--iiFV`oF%r8OkJ9m|GCpS%@ z@fg&qc8ST&?2@Z}n8N|r##R1srf#;Z3pSok{i^)r@KSk!cwpSQFrf%%*L8#=&OTsc z;C@MP73JC8hD2L-w_r<{H=<79g{<{Eje4neVzs-ar6w|B-)N}*8kU}_$e;zWfk06q zy)MaH^MWlf+YR5pGcNvL2@>c(M;<>kj4P{JiA=*r#gt`gHfv6LRdSRWwv8v%ZIY$z z{QMbK~s&MRHhQ^DJ z{~@HaC&~j|fqf*jO2%b_I#LXCa(2+Vt|w71`jI696cLOf$RY7$jRR(=51OEYC*3|B z1M_Jf?7aA<^ZbkaqzM{F3Hc2rS^1qeeN8(C##ghZa7RXUD?-AHt4@7vrW>n5U!+Mh zs1=UMYYq68vuHp{K<+7sE77J9+y9xT20|ETHP(2lGe#=KgSxD&de;KSI55^%U`^c* zZ3dQNnTiT%?bpaou2Q~@#06`MmA-He3JCB^_J#U@!?N;5oRaET{Q_PyRR`smzfA{=4n~H=a z`u#VrG*!e*KP0VR_2<I87+h8hJfEtj2h=tiRcXPy7q z^8PwyLX6aLJng?r<9H3Km^rA7g4!Y0pJ*HW!ClRrW#X(bXrC@LvS?>>xhwW0^9`I| zm}T3KBXjWnsa@(9V0Mhnt00}xJNH>t+{LK==xEccSS-gTQvs8INBddgLT+CLl0SGxiO zyL?Ptwey=dZ>!<)@~+n!ad`y>JwDhKKcBqTz3X;n0L#k+m%iQMs`Qe};0gc7gaffd z|I>uGRF=$m7D(c%uhLr<|F4VjfxzgULigr9n9d&1s$RDp{g9Pk_;|Q+4Emq4Rdo+* zH@W}K0#J-^Hhb4;~}H@G9{QUn?s|V z@s+oME;?OHvplPuM^~GZ0(RTOB=Ty!IWrnJu=uKpV5P{&U{T|)*$F>({0Gj5i8gc8 zZ|)0s9DID(kR_L6iKQM)oMa6v_9!3DXabDR4En>W~#*C=Ba%3wRmA-1WnH>0gUC zKN~!P!F=LZyqtzMD-eDVKajm^760&G2;MS~0Lxqnmw?D!Zs3 zM%D0hnEXj6q5T<{&>x+6ljyMpI(-m2B@&;YszK%{}Esh=@%$mGI4GoPLohxMffsdFIqn7^fXKoGECLo9UjcHIG zNyt?my=Pd~E=X+7CSPS%e&rX>oLDXcx8lIO6yyCj`L{S^&#Phmkp63DePO>QwzH&K2$gZ_8W zkDm?NzmG`UH(d-DS0UrNaM#ZwXx1U(5$vH@C~D|Gp&(^}YH6;InuByQVz~T21W=RQ zELDz(!{60A;`e3~3QbG*JE`wiVR-2>F0T0NuPln1-?DAGjH8UEv58S$T3}c#mgmLe)x7)MvodsT40CJ zkxo_##_&4HkM#eG#257rU6zLB={dJSdv!;f1>2MlF4azD(Ke(XrIfB<1E6AfbPvmW zda*zY++Zla=Z8}pwg~hr1YCB6Cq_Itx(T)uaBYY_UU22#XXnmmOcSMA#rrc10W895 z`y)*sAsWUiq=w-Veh>>nc1*&Lk)-J`sbC!~i^AApa%5ozIO3)O7mf-&c?&#tNI284 z>qVQ;?7odo5Nl{FYOQyZoH;P5~+U z4U;&WT}hS6J7wt1k|DhukxdT_1b5AW>mGatgfZ`6h1dy95_{c$p>iX^@?txB*55GM z{2=#4{=7c*dn{zh^S_FO$=pZ`dM{%T`A;Xj^ z)t~jx9B5o}|MPZB$LaQ$i-#r3lDyE34eKH(ZZIX8r89Xd%R+$kGu=Tsjv)m`=OeP3 zUD+w8^^9~tL+{TPV`W9dDaJt5e$>y6Fy%XV9qYgls~gdhRny*I#uEWFU>cexEkQAj zflx%qBH|UEnW>HzTq61K&s$ft1y9(Nz$KqD zgdmL**!~L(_(s_=(%YqmpM%pkyG8Q6@+s4%zU2G>(OR}U`l*9Q9*ju3CQg}XWe3fK{!s1TKyG%T?>BWaqD|0!&Su{e z`$)_{wdQ={7pk$skC`rcZ{PPar5f{=zvB?`18Nz5fz`dGVW5r`K9F2+~+G=|vN|Ad+)NS=q zU8UKsuI|3!_H_1MKkCZk2s*NUc&FUS>wD+|!KEpGl0aR0RM@K62blBLWCQ0Bd8)g! zp(XWIa>=CqzMspjveWeQfvIT!YsBkE!&!RgV+dj9Kv67jzGJMTGSrQ0qlVR2`D=QE zD^JYhvemSvr*&4KC34TKF%_At_E(~AEYK6PAPi0}E=uULm0iWjW=?ho)fL0Jz!fh@ zy#svPfVhA(+0Ya+!ERC@4{2K8GNAyn2*{!8L?(mHv(kK->gdK_vSQypI4oF0d4z+k zpq>PMLV3IDS?-Xg1kD^bLFnG16S-g>FfJ&?Cxh+%eA)q+@#C93KPWtEw#SWlbI+mq z`yvi@R_p(AS*PM9?#bPBXQ>QIiyUyT*{0EUim9-DAKhK)le4D@8pdNnr$3`^(N<>? zcVEs`S?b}i6aDDdpIgBL!TZRz0-K%|`yU2mkD*hEKu{=WFRt>Ip|Er0RZqx$RdCB)!#l-IK$WTK@FM12Q;3DuCZsC$u)5yh z$E9A<95MLwAE+^T zh%LLsBqY-xGuVMU(YZNgraSZh1xOj?i+MJB5_=RR(`g3tcCF)IWyXIC+&B=HkPYj5 z#iDJo>oDJ?^axV`8)e~-9Leq%v?+fld8$6DyBas0tFPpqCsNNXwaxBIf9LxJ&0M)# z;n*-TGT!IuG079k2jU@PSM)(hxXol}y*-^3;Xn44meXVz7n9#9nVXbIKZDSJvE?lQ zE2jRb+y0|S5GCZ#pFfSBhcnQ^-izRt)2ct>>z^)Q$>0=S7s6U&h4(2NaO*!`yI2iG z1~a3g2B3!Tv6e|FD5wOXhTBPTk-TZdY~N?;s(JWbzI317uC)FTc$nAad9m^GXZ_(f zk>eDp<7TVp%rvNSdQhTy{$*xJff3SzDPW*7)%}V2VT;DYx zEi@yzB`19Z`Ea%!e)1|p`?E3JNb{i+h0T<_UsjN%*{1hUYB?ZG0A?yw<2e5-7dD}9( z2-R*U1Xr>1I!39Nq}8U;1motBQHU;lP0Ep=1FcOR=&KDNG;nTtnF#*yh(S>)I;wR~=IHEC$Z~ta{4WE? zd}_{Ulq3%uHUHQKnH*)_O1WC&eh2;l-*cLvI%DoYJkYQ<2liK3<8gW^51L-I{V0vE zL1MkVb6(ZI60mi*l!1`LMw?ZwqvPX~hnSx91wSUAYPaJ&urp35&*%UHfZrvEx0;YW&ut%VT=OJ|Ou32^iJU9^~N*Q9-N zr+w7^A|&0Zp{7Ik6a6e_ZY-Ke{G&L35 zj+$uHbyo1)@Fpt0kE(}Tv@kd*oCb)Q*+AyYhJ-?Hq-I&)yqOuG;u$PTeLA!#ecPNt zCN&c>res5gf$ac>k5&pPVC6OeqTme4!+t&oAwC9;cQaqN>uu7_t5%Y> zAJ=*HxeZXgRHVn`=d!;xc|k)rs=B;AsfQeJiZh2vSn2VcC37 zyDYyVEig6H!m2EDlIY0$mLYq_rG>QJku!NACO^olYi-44M@#Rx_9u@@Q@H>u?mhLsj4A!8uVz41Qm1^kdXA`NbV7c&-`|9il2T?qw4GSv ztRnROa_?$-&CaJI>89SH>h`)>xkB2*?n`pGt^53+>sM8edU38EU*5b{P8-aIH4wR5 zF`qT)ecXxDFgK^73rYKO(feQ)J<|4&o@pMElXF6y)0C8C$V;l#f?i)y1JS3DQS9!p zF6z3+xNiy5l!G8DOugH0TGsNxVmGZr3uUFRg=>zjwDO0`sZo#ThR!|?3_0{aJO_GFS$6EAW@E;p9domhhA7?DmzefLkqJ!}D= zhuA0gmlQvPe!0i%#Da65JCe!|(fDeseeNed@X`Z<&H=bUQTO6~yu9izl6J)A?!b5V zTs~ayRM!l(Lo?O_D_M)b+Iump&E^CP7IS-u?RfDc-B?;l zvfFI;G&nj%#y;Eq^lm2a4oKUs%-9=-LXKPoDf15Lg39Cu`~5wMMf>l9JEAr53yo67 z5-Y1{(2!Oghnr0c`#t%l3r#|m@ytpc5_Uis7DaC^K2bte%w=@#%~-YYwxv96oRLtW zciQTMDfG(0%kd2X`>dBgtrI6&40Wo|uNvip8v?z!emq2w{Fp=!i2p`)A(qT=IFjk2k{In*%+lWb8D6sUcj@=22%!TCQWn$osy{5eeH^?}`)+Oy zxSINqrTF96(=Y;Q9XC7i-$IV#S_#vyNhJn1u0B`*=7q9<^eI|6P=I0~wOAPz-!BG0&wsm7+P8t(w9OQPb|DC2nyEio;Uu zG&LjDdr3dZ*Asth6_*rdXJ{16Fn86oOH52WOyRSE+dc^E?GW*o08oyP0Q+u{n4!?w z?+vD42U2ig!#lXShR1LERn4L?RM-rpy!0pVa?P#(!peob%vwwY0$)iW2W>S!M*+K$ z7e!3D7j8y}wf45t2?!MmUS7VQfu@HhK0f)Em-FQi*_p*(MWxLjL7smsA8rjy0UG@p zdUrjO3PeI2y`N5mE9sK2U%JE^2DSx)Ugu}#x`?Aq_gz^h0c_!8_q95~v2jKR?9d2c z5L~w~d)MO&zG1f)v#2}tRkSW#ELz;wI`sOSnoCGX=yERX2QoYpz~}um%iOGqHz3WV zC55Wi3;M}Fl1sSzNm20mfWwuXk)sQLlE`(-SNo3nCnyYHEu0JYs=P&iC@&W<5gQLH zB&E#zeTB^PNn=R6LL~&&@%r*G7?YS|fFlUE>w0fPk^b^0g}~(_^hCWd%Cil#&zlBm zx4-j+VR|^ZHnQ%TkB_0Sx)%j{bHXpEr&+7r(5LP_BJA0ZRmAT}Qn|!d%aQk5<6BXS zc=LOqv_0E_1na|Xk$xa;T|hHGq#XNqG&nY2QOW0r(QoHQ1Fmyc07Oj3%)P93PR}*3-ihqtvY7FC72h-Oj6`o%SPbIB~Iwx4u@Uv5mFX zMHNk?LATdLg1*aOc$`3{`Q_?{23`iMxAa_CVg))zpsL%=pFRlbi(}GOQsh0JN4JeG zyZbZjog2pit;AHs=%|mCcJIA(gKWgU5DFrHBP46zxN)p)!H$`&bqt}GNJSi~dgenY&rCYm+*Y z@^&8|=LqFZJaeQgsE&{~s@aEAOhKh8^wphyL*RJmK>#>;oxvCfJrwT9Z@}yFc&8d3X5p3Idh1@is^dV(* zk_I32i)8iE0Dg1^Q6maA3Bfx|F{S-XHv$P_e0*oa68#TTHKKK3ZquKO)MLFab~eNaKV>3y;|*-xX$b{ z-``q5%3&kYZ~_A$l7^^5z{{YKHKa0%>prgR0WF91nSyRv( zePhf4!zj8aD5(SwonbsqeR2zJ0Pp!#eM_ZlE!9S+1V1o(r-7j`)YiCya{E{$t0#f% zQCiFx~(!*4mYu4g$ zU4^&{wkKqf(>`u8%h_u^3D*TGX(KFwu_Kt(MTn{tIW^}!*y9@a96qRgp*bN{IM<&S zFYw5jyEe?rh;jT_{?3C%y~RDHVg#kqI6G%_rX7I+#siU>vgiID?x@v=#1<9-h>nl^ zoXV?51WRN$jG^A-Ab9<}Mgm4~S;u9KKeoIkdR5XmFCCd`19G&n0hexDVq%HOoo!np z37XpDdB6;%8G;jyh#~w5`%S|Lv05(?9_^eo?*PCLZ`7 zmj7H8H>56PBL)FKN|FjEpxK(!qf)| z7g%GtV?RO(BroCX?843ZuF=>}yq{lx0Ke5`HYT0f$i6a!>X_0nnX}Gnn)W7izp=fU zJET&FE*cbhJ$s_*XbEETh@R_nSP)JaJlEIPM=%z8v7R2?rFMdhh5>&) z6iJl1oK62?gl5fE!Cc%BEeimAbtS@OK|N%N9JQGD)#~ z9W`i{!zKY;cZSoq^r790pTs_ASeP`hV!1?)PVV+p9IAD`j;&x1?ex{5kwfoQbX?_x zw$BdSS3)PYE1jeF$ygF3ho5MLWBXF&snqX$*-qYs&m%o`hb}a^NS!3hi=&!@PgX*0 zE^Sd!rHV*p0A%?L=$h#}8z3*H?Dy?Cz}e+Rw>TuVpDOxFT>XO{v%5QJ1z zp@^%x2QkF-s7={t%BY0yOh~i~iiw>aLtW6OQ(wG;V;4p)ziVs_K@CwNy!Gcu0*kiY zN(Wm={VPV-=Fe$#1|mS=jb0Do- zv`M$(s(7J~ExFq=wiIKjntqVMwm6IPHXdsDhNwb=4vfC5z0t<};wfxp!6DShk!M28 zNH57D$@#)W$w&5DDvI@=KT+KJ!TcNkH}4)TWr=z&0x!bi-wY=fJLJ%}h7K%A4gjTo ze&Wq@oxkjbXHMJgE$S{FV)=S=*11Yz4IRr+PBqxf%5ByAS#gu0zQ5{d^7dfv#Vz(% zO=^a7T0`oOh=L>0RwDTH*$2WbiZH6g=F%Ohw1z*xHnwwC{tK91dHxklR5`Dwl6;Me z_y=d7b&gO+lz{ion!aHuAj~?XSd0`HSPvkhZxc1xRXm^?qPdwR#UJh2DKhhEb&D?v zG6BL&^=v%zY0P2#xpWi(8~Hi;=`iO_06>*ic9}|Q@MANChM<5;(z7!0kONr+&9H~o z1snsDA=d3WjQ*+*oV+MU=nr!WRNu9by5={&F0}XIkhHAW`#UNNI3WgmQ&qTMmvvq9 zrVyoO;L2FjJFKp)ob5UPE)r$lTw;{`$?f|nE%?^=N0cP5Ug)Ua%eR{R1I$U5% zC-a*oH(UqOzatr?f!dL<0ckUycMANdO(?COsmYi(&loT>QTxR{s?=p$cx|gs-q^i7 z?Z1hq)>H93WDXE@B*Fan=c@AjS=fsx6*hSe+}Jz%YN0yOgzH3>!du)QbUJBj;t^>Q zB8*iDbi!VkOBaDCP zIXgv3u*S~!T@C67MPG+Gk~{H)r#EJttfhV}3fMf&^YfUxm`@4fW&;gm7TGL&m`%mm zvkfnD?-X~eXi<+&R(<>?@vGX@-DZ(PWl$O~;Vp&&Hy^gQ$(OJ1;n|E@Q9l0JIA%#S z-i#VF(wZya_C|v#0I2?#{-zOBoD@PHi0r1_dnwY%p`i#_{H|nk!ls&6U`D5Y07l1QkiuzBof!eK2Oq@<+CVL%lUD3+wW z{1HAn#(h;N%)TW@9(=MGYkgT%WRU#HsJy_HeJAIrwjo)s5d%LU?ere%+}jkJ>q_ds&cs5r_OE zawmRhwa0??TcSgI;)LOYDN8oS)I1B^VL${N6$Y{7iz4%W~9T<}y7;q2ouUHMSfG63zjFFp^zGWqJ|G+ZLtS%hIbdS zNr0TE-FNE=@~`Vv)!=g@-shEg$T=(VV0!L?~<8_WP%C8w7A*mDEE zze!`<|N2aaV*DB#h{A|CO9@T;lD{>paMV;Dh>86~_O(cq6vz#64>v62)-pj zD`~>J{khP`EPeBO|7}Ay5nXOLY&CK?@oBRf&g5+zk0K~XP59yQp8;aMBy~kyven$s zJxJIAYQn27sK=M|`xBZKsz|AZ`n8Tr*pBpjG%Y+D|Gxxkc*!j%8VP~EJrHHmG;iRI z_3!?lJ>ucd6>Dkr6N0mojkX#ayS!rb%1oCesI6c5PwKAC33Kc9nj922p0#)tW| zX6UWYD?CrbJJvsQo#qzXd|Kr=(t)d>s%l%VqV%&L*q_h-S3@W9LusV!{ADy^_#fIg6K*g3IGpb@#wbQbDFFEpQXF(}U=JeF}*Ql@{_g;Ar>ngN{y6&xXlq4*9F8jN*}9w}4^#Fq)2E z?eOB@YISKTs}j}*FYjSH0GNVNz3LXRqQ>#KsufIjWu>{_#gU$v*w6FAUns!_f$NO@x@t^0_42a=y#gj#P8V~}} zSPp~m>P=?zbr6o3C+_p8ksi;-W(H@?HxqW3`e|YwlLw;S8^E0s&*<$YU+F!#=XCT5 zJ(gnqN(|zG+|zq*(K-`-SoEP}jk*9q;x$yYk3YVUw)HtiDYNS@Q7u;0kjQ;Iiy67R ze5Y(-@}6IMW>4@4yRbI2u(zFJW{D4xP@tF-8FIBPvNT8Q()8uNo@dn0w8U#K;AkD- z8IQRGj*7Y%5^Y=N;ZPpplI+nTQ}2cgI4k_sBT3lwbrB0O8KV-hhJF=%XWY?ym-m_I zXyP28eXLcm;uXH={3)>sL5x{KZNTr-MzcnPqe|gqJ79*JCtxV1N&=#pXU=-45|S2< zSW%?gTwfXo==8IEc?)5hiXsFIDTYM7@21R{&I@<-w&P&_-S2rs0J?3fuR6MbHYFXH z3b&|WQnCe)%3x!C@xdyP`Ryv%qpf_s4HfMi^Z|)=IWmGiyh!#tbuZX`W(}7Ys0&`m zQ(1X*9>NwZ2y({mX~I^oN8PqlXNpYRY$i~;=6(vJ#FGGjI&$G_hzq)5R3PxdD!)F$ zp8Ufq*-}$$V4gPU_g9O9rFX_BXTqOu4w3K`VyQV1aEpWn6Dsg!>l{Z4D^67UMwz%v zwnblP?58>9YGveq;0dn&H|ek$#d2K&^XWRKP5!qmYG$Q7=0 z2h~)&J_&|MnVxL?^|^}b5BV4G`7>w#*rWUP2rHxT^UP~fRm%6|c%XM|?!l|p<3r=O zHXtE~agesP+%lED%1_TR`;zfzs-AX-EE{n8UFH}9@j+`)qq}Ke zHaYwBbt7dl+on%j={0);R3ZEuY7BFNf=VTJCON;NhHf=e=}YZEZGpP8OM z_+22i++eKwG_$zV+BWcjr!WMW^0BdARGp~Y+A5hWH!~v{s}Q-;&9a&BD+&Z`&Q+}Oat#8i6X zr+haLxSf;!+r^J~)B&KGe zR%H?>3>jPYo$(U-OQF5d<{2m%?jFcgS*Jt`4}O@VFXcYh7x&^}%N0Z7)=F*agKx)B z6Fjsj8xYp{44po&^>y*xPp#|kz98y6e_qAGmv_ZvnmQO)0ma#??0|mIJs=YsVeMX2 z&(@>c4@N1%2!7ak_2JOR;oKb2vWr&pVxkmx5?l8cKT|S;@+#~fIe2XL`+VA4wGW%2 zlQ%*eSEgc}dYnh_ov#T`p=2-YtnY-PlSk3Pjz|D3TEa^0v7%BB#jDj*0=I^pF_q^_ znqa%tm^8{)UQaT_zYTW*cng<9k$IuDiU9G>tcbB)c?}_l?ZWOI8{OXQeKacOhLFSd zv#8Df4nR*^5DO7B!t=vp-UF1f2lKrdXKMPPBg)6S5<(vnsCFv;He?BXJB&5p3l)=~ zI6G0F*MpIPaP8;xiHYZzRikI7T4bvakWEe>mVhg;b3kp8U*`9mZ%;N)V3#{twy(qu zw&Nmh-5ebArlX5^?4`Ov!hGA@EKjTvdVH?~(RuI=)!8E&fWBfzQ?pX9U7XbgVBp@H znw;PQuacYH}~vvv1hHd51h1wn2kk`vO20c;NvR17Aev zF1va02Ix4|gtx?vL!nx-kkqVQZ&Ol!D!QRzbcmp&ML4ZRgC}qK_`FoCrHE;{aKG=i zrgjpEVA*vYH9%wz>77FmS?jm$n6*8Wmy zXW6DQpAL-}r|&|!ZNQqlGO+v%(XFpWm0-UI)HWU;VLVGlE=eHm47I#C^)4!TP7s!m zDILq5?$_jjmNZLTWUKibM022Eup|7Auy-$yZghel3lV3$&;lu^+{@ znQxiNOZ3VH=_$wg%XS5oaQHHdrl$1YEcIs-M5BomQI2Y^q}YtZ3ENTxG1l@e;TZl! zA+^~1YKM>lg;!OAKF3ysW%~w`%L?)=iCw$)k{m2G$&1P^{=Wt32(REfRnX=mY1`q(vyLc0ZDqoLlIB zVr``9%U^)Ptq`sruRYe9L($&%-sz2xPg@|}3JAD`Cd{Zw3o;i7pHGgD2j{wVXWzgY zLvI&Cj;Smk{`}G~FhKFy3>2u_Y%I8W-+#{kv%{_MEpk{!9x>z*4|Lx#J5U&SHEZz) z)P)l_>5Ys{84d%yliLR1EZ46O1oD6JBG=K?ZTg&+MgU`)iq9%7P`FZDHf%oW`@$Lx z3%X6D&|mI11RyOeXl*x*QSN#*hXV)_yvZ9Iq*;`*BWSoZ3w#d+IDLMV;=CzDS=9fH zZtvq7{sn7_ruz@@eba>Kr8@&F>+7PnazbI#K(cI?8nW*N3Tri^K!+}6JGDJXWwMTU z)2i$vqX0()=`NaYUT@DS3h4Q}>0AO@g`tDvGkynqnCv3M!1ZdXq2@jI`o?mBTNV$Y zAG)6dg-qPR=F6_g+?+qDlIHg9{psOA&eLKMV!in0M=;;z?fNH^eXHTR5y`eRZnvI~ zuZ=p)LOYzf+^c%fAa~gU!2}M&UGC@DV?e%ZKVf0j3vkxpU=pM92hXx3Q1-gMwH_SEH_Y$H@;xdTJ=!)~cF@o+A(T1jZnx(DPXvlbiGXia2m6WAZ44p;Q# zi9b^);t1J7mWR1qoh&H)i81cI_|u9$?6Iu=W+@-9hLFgK%OuHP!D^&jlEpg-6mb#d zun-2RQs;J}X0Cs*ILOz%VB`UMfCaN< zH5~dNw{pj+xU{IAwvml#S+0gqN)h&^!qrHJQxZ2vhc^92J zy4Mrh(k9<~pEIy}>JRt+dE>!#1W&7TktiePeCa|wROyoMHDh``JJE+KI*P*Z$ruM! z0k;JcCfWU`6lcA+^+wP)EC~{yPG!T0JsbPrb$If7_OP--fi+G{i`@{-r~Mc6h+ngi z+_;8*+%L6D%gUMT#dzS<%cIi5P!P!EaR3>B(hs?7NOxGG8`aHRT3SK^25cj>|NQE6 zLHV=Wo7Fxa0Hh28?NSZHR3em^m>A9vTG@7%g>lw?@V+P2=F+aN?_7dTRkK9g*gK%* znP#Ea*B;bB81T{eSYAfsN#iRik6qE-wy#bGlHT*mpH*hHF5tI|F;tFUB|_W z!2&T#TgP_}5`8E8<8@(J2K&>iHIZ}#r~L?q z#|c(r%lmLErg60>=gQCMdPSAYj@#-HU*t}g3Ol`-Gl69#WPRZ2(=FYteU({kX6g$O z3Q{%7-cg&3cL+JTC|F+;zCSlazts=iywy!t_BR=wb~limbh zN2JOH6*Da(do!Ih#>25G(gW;^V#g5=o?(gtBP}@Du2!s9K&H#(!Bp~!=l6h*SPQAC zTgi7*!2~A_*&5-_)b+HJnq>9;FSwZ$qQD>BiZ_Rjd4P-II~M$RKh>GWm)VK~dk=|o zXl!PRTb49dejqTiN*C(jq>%C)JrB>eR!OU)-R>ZU%!k0$)3vTS7Fzk=E%rH8S6CT| z5x>KWT_Dsse}&sC>v{%kvg(PNWfll{VoRO4l%Fat@iNM~)@|{Mh)K?4*MFf~E73%h zBVY73%#lmIj(A0ThEHot-82tTnCggavk~OVVBTl_j0EK4v;i3k8r~j70VX>DQ@cAV^%FGC4etX=2J2j zZqA_xb2mRLJBf6n%(c0@%)q;J_2JHmODj7#=y*lmqq0pOBJ-+_sVon_iAc_9nGX2g z5E!Q>-!@yqTX_G@Xl9s-+59r|N**5``Z>m0o-2O%W2mJ49DYNB6BRQ>R}d&I{+N~k zs3p8dr1j=?7ubky%JwSgu`3uWu3yVbVBhzW@k5&G48yPthBomro10|&h`A}nIjiDz z9LjXAK;j3%4?BphZEdIwf3pHZxE9XWm`h0o07}BWc?2=`6vJ}uD)wXpG+V0R zvlPdqtQ@2dRVu2d494{xYxPU3KeVP;7_&-=jLoz)DG#ss77PPje{wQgn22~Au>Pv{ zCTkn`oSy5Oz7SoK16;S}gx-&75F<{>8@772_=}B-unP=A;-RW+>|>KWX$$gC1vI80 za11BjhF`lc#s%^~u7n#Zp2>8LTt&7Jt%$Xg-?MDOWy5 zN@#3I1ubg0ytVWz)>&<{r!G$wsbl#>%KghO&;7H-DUoLhC6ScsA6}ofVY}blM0@|! zcY*C>b+K3~ZNx~8kb>CZ3>@|VX-i@%0*y|?+an5T)?0kyy4^(93brnEHP=sOSJcJ7 zppsgzGv-DZIk!4bkBpzhbeP9joVJbC`-xaYnDTG)$5XCh^3}lOH^y(03`Y6~_ixSG zRO>GvJ#$TohCO+--VzfUSNALWEuZ@Pf7-qa9Q&(h4Yw{JIExGElvm{`-CX<{u5{h^ z%U_RIYK1=jn39NXsXs4H4|jA)iFlD;X&BI8GggEiZuX2Sbs6cI2ek^`(Vr^q&yOL6 z?KrT{2}@D?lN z@Pq3Dc?FgrK)B`~z%~mIpjnn2W-eKHtyVU=Q=5#s6LfRjIo=soBI@vMy@+_(D?Dww zJ3-DkweqOH7lJEmEeKiWQ;}ZWvEnLYY9K?npRR$|lSJxDUh`OI#KO~2Uv6#(3t$oA z9<2nvQvafl9(>N>iC-{d-Y=CLAeV19jmV70HFH@WEpqh}pfY!&r&}v@_yR|ZyJAt) zXFpeS+FEa<;UxCyY&w*)u5`_w%=F7W^ZZ+st?sg^l@~vD{t~{)L($yLbYlnPt zH;$Vn`=X%aC&nA~11eQS5D!BF#RxCfI_m3uN%bD#n!qxzz2_@!{)$9*&@Wgi%}njK z6&^JMvN;{yo@w&JD~h(c^+t3N&Y#z#gw??Wf2(Vx;|7+DrXt&QX-r`uC??!sHdOm!o-A9LTL#9_PBk$OXpXhGf z8ked38TJk3u`5VOr>`n)w1HiO0MIAhhE#=m(ypm6eWzbg6HnH4f|>xI zuGcptXc_70l6rbX9llTq*t%+eK}XWUi*`;cO3zR;M4XuqzZs2DT1rb8R`xs8)!R^l zbnzhlab8DZirLbZO{%1PM)R9?q{|PMPmqD!PPtt(k}thwKjlxE4I4S~K8n#7OA(j* zlCvH#Kl8v^?s~BeP}6>y;qPcd>-H!jMUSQ*^o`fj$J6;Tzk-ssZs3j4E_R1K_j{+k zO8Hv1_tji5FDBtwCojub&x|Qs;>H3u`q2&J>-4N8!r1Zdd74Z0LSF>PNdttqtVDJ_ zG3d7Ra++tB)2@ef`prF)xRYBz%G3K=ikPhrWkEjQJ=G6KemORKkQN&LEI49v@=DbL=xQw1*Ib z<$FzT`ftB3QnmL_@1{+_n$gM%k)#3}iIpTjv{Fe98+StYqSTKh>lELssqGQ<4J+SO z7X2=|DpXTy*kEv`w8+B4DqZqx#<^(wC?*bAr-UvMr_)q-gga?*jzpFf@x5$(=Ixv- zN#nHsU}9HUUgD)QBkz0?^aU&Z{+Q4$DebFzH%D}6HC($$W zp~3^1DlV149v3}Q6$t?AyNDMq)E92n?^+;CK(;$+Y{=N3PI$ByZg&jtVV{Cu1Xsvd z)1MBV_EZnA9^5o96HXv)U)0~zPeM8j>idi3LX6*w7O*$t0SdB=Qn2ZTvXf$|1f&i zjw!zcQnKxPhlvXpB?^5kMEQQ2E;~hrX>9hpCtFSw@G9Q^?Tiki)+O(m+}Xcb01v|5 zzx~wrE*FlTq=T?#3T?hIF*9Q|UmB^JR{as^G5I5CI^-zZexbOrDowU~ik+dp0u+{o z)%SCzz|`?|*opLd^;RXM1_Z7$lSK5AZ0AVb7iOf1xtjyO-B>kK>tRJ(Bfj+|4#MCW zbq4##y@(RsV>|Ysq;Kf`8D#;zP+P4WO95~9UsCfmUOX!pB3k7E-cZ*P>qv?+FJPDa z2PUKR_Xjza@-1f;<5VB$A!CbMk+7*mzKwgF8%#_g#|#*5n+Lu7us$75ap`S~P{sg4NmU}E3ziaQRKTvT@^ z#>QhA)sf9T8qK@-JC;qRiT;8gHkuH)J(t;9_4p`^jB~C?j?Nt>Eav{j9zZDEptwZ0eY zyfI7=6{}O}B49Y&cow;3$fwnv)K?G@6hdL4(>00e_3Az(C`qejDu)tkVVSX%xu;y& zV-h&$>Lk+S*Vr|ZDcTuv=Bts;>|(!(dC2TsNNR@@IoCc%=7%cyh3{eMzEpSn?`e_F z_#Q+)mN_`>i`=RycqZrqA)u#?+t^sNPWQpuBw;8ZfV3B z^}ZiXDQlKT8>7!~vMQj%O8W5lG^v}c+T*wX>AT0RUp~Xrr2h|NUlmYSva}0?;4Z=4 z-61#xcXtmS+}$05dvGVXySux)ySsCD=FFU#$@w4d)3&wO>Mrf7uKJouuRHMeV$IE9 z6~oOZ7#7<^=Uij`>C;G8D^pXFTw8)jn|S6iML&73qh$ZXl9*_D`GyguLslZfb!o1F z#VU{DBab206!@oH#-9$IqjrP4cSJPxi`m?byJ|_cuQ-6dig11X52>rQh_z61m=P*M zhe!+?qD*IIpEiGjG_p5BFeM6FcTEulF~`%&4^U#`E7+z7`@%<7G%M$ z3PjarJyK+f3!>2Tg4p&ZU1`1(JYiJ-xVa@^B6UNI|2o(;jsAYyzF;-Xc25SQzh&KP zlLq3pG9X2w_e?9KCDt^O0|@XPP9fA~Rv_NFiBwLbs9nfKK_q5bE>#CSM%z^3R^d$-MGhd+p=5zr4I4qVDr zDAGfPb4*U5q!o?>%#;*j7k=QW7j>TwWX9CkeesBw$(wxrPBdHKUYsDFE%4LKDnUjC zTF5wFrmECUJV<(WQeZHoXE$$};*~OE_h(FtZJxV|4CGs|H((Qg+4-|7@3*~y7oyJ) z(6%+Mpcr$PBVds+ zcvZRLSXpgvATx6_d=g>HAhIBBapZl8 zY&)(t)3FhbZJ4wKJiy2Ns#dY?lY z{kzfUySehr(#Ex3aVT)SvSYsruE z%U11a@%xA06t(0a%iHcK0ocsQwAwAfVB||1FvvT-v!=2$jFHMCk%IjeIDRoArPa#yXXh&5t|lDd*Qnm z!uV^=l~|83YNP zd^H(LC%DSUz9&_=nSVW8y8j2`qD+kEh7U9^y!O+#6|Q3_BlosVl^VuUXNTQnlN1T4!l>Gc$yz$Ba`C-6NV=O%qS@`_YHFc&7ElX zR+|ub6TaL(t!)#?xMsSa3B5qxr(PYxQf1;J%OrF*zRbOCS3sBcWfYrjFhmF1y)I|C z^A1-fNFkltmIC%VTG7@5GuoO^X(rIRzh4Sf81xYjj7$3M_=7szzd{wZEP(b?9cj9w zTwaY~t3UwuEPT02;5`lmT9gLdMuO(4sAKYc=GZVB)F>vsa_QZ^Fu3dX)&>g!jS=x! zZNDs9jb&ijyp5zBl_prFKKWZQJP3T$i6M}n#$k&99Q$p>*3N`owZ45L6iQYjS*;AdpSqyj#>CnF4@q7_uwy3$bw zS*_Q>78Mr@M8h@PFUd-Fj4Gctf${UV0_n()W`w2O9z^8iJ=^V$8F|>+GU7HbwkL8` zHVlRbMZ-7d1Z1D9UVH0*5pLgg>~50 z6XZix9_f9dzH=a1c%<{J<-@1n3cMGZ6*7w=p!-2YeRN$a%ymiA{tPJqY*M1whlWWR zDR7qC7$rv^O@kNnWNy})!&jbQxCK#JHqG(v&qJ2nW+Qij!E$?ciE^PspAkQEK73i`gR zZ46FQ8L#eNTZ*Vu2}Eu%PgEOD?ax|XLIJzmN6$5z0jEJ5b04c4#s^}mRD9mdE&RSf zxJX=AWfl=Ee7S7k;?hGk;|raKEghrC%3aZ3w}%|ab`Y~nu)-lj-TSIdT9X~{^ud_Y z&%`8GThMUp{N)Vx;OsB}O)likQSl)oBDB`&t4D^1l?m^ZMwLOxQcxe**-9ny(y|{f zK19(CswDo$Bly({ZwYsodBo3Jr#zR&q?B|D;8PD4_kak-7|HWsAQm4C*UOSgQQO3J zmWz!WRqdzo;rP1Ty2sv~Qo~wL=9M+c%iihgn?KLb9tpfJQ8%x~(f6g?Jc?44h|01CkvHX6onb`rb zjXE+`TH*#jNn)HA^OYMWwY2xtt+(isz6?r9s1Ckx?7$ZAjpuyw`ckhLuecl>m={G3 zDYG%qd1+auBgkK1Po3^_&xFn+ul*rBafV?juKyZ5SwH%{`Lh>g%Qg5usZ6$x zI<~p3wcwnnUap#i>}oF5$@Whf12RfD|KB0bAm0a0L_Nz2e zsnKS#x)V*J6?&>vC#2{vNmY)Kr#Ix)3Su%ZJ7g2n)8PsA6oEQenN~3*J^jVqDhOm% zP*zRxR4QLQJ$=NlD(!~{z#L!*BBV{h)wV9CA>fnt$1_AY3~#SH!Fe%j?&!2@AlmL< z&pVNMUn$HNDmr7B7I5cKj)hhQx9Lg*Fx#9MAl%%VHV*c5u0$ZewuYifiAR})K->-pYG#`UCIL+1yo;fP&^|XHoFNnJ0 zYAje=f!(KLzOrs{>*d1#_>yHyVG{pj^?r7~VW#tp`7)}~4#s3G&l!|xc775VZ$jdE zn`&weuikyvbS(FncyZ2WXjJvhvZ==41iq)fxIT!+E5#)@X?*CO>+Mw-j*pQN=Y0`; zj?Y#eWQI-0_uUzHehOkgWJ?R0!nufF%Z}=*4TGUvZTv0pSKq|ReEVjb$Ihh46P1zZ zc{@{o?ZnRoo%c7CYg$C({ z0@my#Y|(}_taahW?Q%WXH3l4HNN$6&_;+X0-}nuzpuSFH!Wz)!)@}nF&u-@ykd!Q( zoLHZzRe_QVnWe>Vs*OhjkBXx81KQf!a1YMKKg-V)@YX|jFxJ2*X?{;|oj6@R;RCgb))FjRZ<@XZ>NlCaS7FwAdfa$cJ#W z8-Q7?*0?;!h^b1uN3)F^nk3o))jR$o-Y8pQ3_LVJ-x)GvSo<`N;%aS_bNhqz3~N7o zAC5tKQ70$JO4uwrvFr-I5MZveV8ol)(B!i`=l6Sda2StlEw+7bz6Kz;o=pquQ}61L zvc@ntgB$|-{kj?TC$}DIQ13f@!g=X~3u$vH(Y*&HEQ2oX<`-P~ z%n+y*nS|}NV9V&$9M>Bz4I5tTmMd`8117ULgC3y(WwmE^k)6lJG=hHSBa4sjaFKb@^MXH^v;h1r1W6orL_{!>#n^d3)==xmnQ zeN<0WWimX;M=ULzXaMupv7yTvo7!Cf!S zeq^-O!6IESYaYo=Pf~zN@q{jfvV}drd1)`74NHuF%I~#OIOFREbf|Ya>MeiO*F8_q z;_l6Cckr+r<^gnuQF<0e4L|{40Yuwx2QYY|^#JW0?k2MivdaE=QMycbsgC7X%=$6b zW689v-cYBXWd?`1JX*4GMk!u>pu$u3>R1PQ0N{`#8DM0^M;D5r;scUWff}F2{58tD zBSkB?ZnsAyXs9qyx6!0~6{Jm;HdrnjOTjbCLZ}aoyTB85hKFe`GcHr(_+D~b+D$mF z2!SyIT-SDbBLxmzMa>=$kHVTh-c55qwrjbd8drEmU+nnj_UcWbz@yYCsx*J)tL)TN6&n{>mqi*s9EBh`TdozK#V&O-vnGI$kJkFZ?b*T>|vL(N+AOYX~LZ{gR z-;W6^7e7t-YFKx8NtGu8>TYV8uK&XlL4f%AbzI12%4EZex-*E3)lTjLaw_O6J5`#J zU(?|*+k!+ywqsy_P@$QdoBNlV^m?2wVc8Hdq@x}l3JDkNlh4btWW%0;w6TrR1t^inwpz$C7SUVILdRV zGfPTH?83To7{#--oNA(qb|%^`vM)x(CkLc-a8LN&nsq%Ti=2|`H>xebRq>Q-xw>Ma zpi-Dg%%n%u0k=H#ps@!8JW@9`Hhx^9+XiD!h}VgVq>G5jEGzp&EBgxD?=aNGVQ921 zY(~Ac1S7SelSrqe|ER5Dj>7O3CPk{mebh~HR8xS{aJ;1fQWwdjOTiYR=Qg<;Bqlb zsNK<})4xNBHaL*Ppbr*{12~X+;K_#gXl;oqUqLEn<~>?0>ZS99GqVyr9v#drDMFYerfYp5TyfY>Yp_ay z1B5uf<1dF9jI2c;fzU2ddRtbwYP784voLCjkMPTL?wSYWIwwCE85@(m?0dbDy;#*O z-~_paLw}++*v9D*Myj2e*YWa@04XJZ4qEr*juZ<MJ$#&5-_1zwyOfl zlS7^X_eN*HPOGqXo*vg5Z1pM)mQ62y1Uu#PRlEZn>;|jzvbA3s!EkZW&kN@jiH8dl ze{G+vB?+j|`2{NTNjd}Knl!$G@oy>2&>@bg2nOuESMw6X5sh?q$yJJ#DB(Xm=|*jNRAtyI^Bq61D#O%D97J^X|5 zH`*?%_0=HdW3&!Xd17r3oR_Qcw59?6>jLTIA_Kkm^YwOk4mmZC&rJpEYoiIx$Tn-y zzSpC)1QuGDQsa#K5 zd$8n+BDSv&P;CgcBW=hKn0N^&(RO7}dEJC*)Ol)MxE$AEJ+7aVu%-P*aA4-2k0 z%A}&vn8t|PWbF?7xf$!Mr+A6PNTOZtqdYDh#)Zf$W3l3E7u>+Kx3BS;`DX6-w z!ZaYhAH?|+bCvQX%9srU_Wp24sd8Pe8K*W#w^|)J>>ckjdtF|K=z;n##I;`1%j+!rbWQ+zqF;n0 z#`C!B)>PAaO9Zr1Oki>^M3jtA2N72~m)Dxj<7UD)^+1B?LjrU6gO!ec`yxUjjk28M zD-rz9wbh>hY3NK42dfo&lN$>sy{|MT{+|PwtAr z?QlB2c?DFv->UNra18Ftv}8ToQe&Z^p*NmLpd$MM!zxU#jbc~e#?w7uC6hi!Z$ICk z2gQtTftHtmR2oUgjlcmX5OfCh$P0Rsb+YEHDAEQmjG|xa=Sz5xAQ;`mTtK ztMX?PJ=^^@)q)*rO<21(D#&C91uRfFr(r%oWqe$85B>Vo-@n`SARP z?(Fu)0sw`0kK)bVpYGR}uW;?Rp~cE`;DG==qI=6^_L}!=+|8ROi`Ck7QI{|;NqV!e z#RM3rmxHr2irvjt?Km;ojK2q{Q(q?O2nO-Y=kby?@k&G=mdG7~F6=$(Lm%QPhxtfu zwZ^Q+J+?x~0^LyaJbwj`e4sz%eA=v^kTjp%vMPsGy7|L8S;z?5&3Vd#ETL}ZeE^n+66~$l&SucGvSOn<$OSD?27s-QxYeW&9n-y4Y%wFcevfFIG0t%^Af;XN8n|y&hi#jC$MH2!g-$ymD0ZK3v*yb1~ob=HZ#Kd0URAh1u4`V}=uNxsh8ft5? z(T>a=Zus>?KO=y>x{RNC8=VOShGmxJVn(4oFwq*%iXJBtgBqy0|I7=BGvfAz(;%|h#Xs!@C&9?xFpd9&VAbogM- z>G|o+`z33|Df&Jkpjvg2nF{tE(?zl`)7G4=CGgXc*Zo=>{;p!o>~zi^%A@xEO2Vt^ z`XzmB1JE2@y5G=q|DtPCq9y+2&jt~RZ9EY)^L5-3Zytn2zrp5rNz|9^avdL;)jA~c z$tgAm)^f*&z|@}>-gqrHa5K!HShWPlx9d-%#TOwOiQ6GSA4f!9b!@T_)0b_%O9NvA z?08>hTe>_q0Y!H`$8;KV9ol`6jPsKOqi}j|Wk& zNEGaYa>(5+RBpdU*&3>@aan_m&1(6}=≀jLW@#>zoblb97Am94UUcYz}?Zr2MiX zh`yE4WK?vFM;ABuGCeNV+6vmXt-W9qEEDqtq^=|LMdDk8H$DrA{#-NL%nfX zm{P(;dgkiK3|=Xci_jU8O8@9t%r)@X8&MM#6ARRsFWs*>I-*=?GAv$waaXL;X|z>Z z0Dt0s$lf1WWJ170gFj|7*QL5AzSs@N+N{btkv7d0Yy;L=AyE~vXluD7$u$+AQm3e} zY*mP)Ik({d7SLO@JN$xrAU79oqLfk6a=$B`!4n|9>vjQg$WE_MsD zk)v!wZQjQ<=WPcr+*Oywl++(kW^*O{hWBy!u1uSSa-Z_(R2v|MhK7=MZs)c2sqRq- zj^EfaKO&WK>4XhkpA+1zC614f^Xef^*fCOPAwYoSzyQ~(M^*{nPNvf8Yn}N?R{dds z(H$U?=(a`@y*Rj>Vf(1Up73f1f{(hYh?-q1zxciS@95xAUW24>)Hqi@kpoaT`!cK{ z6s9i(DQpwFQVm%Al@KQX3>Q=|faQ^-#KphvI&p-{b1DFifrqV=0izX{kZ|!je0jXK zeyq}e`C2iId3aUUxQF?$Z{>k}%d)+}g-P;wVvJ{(cEP@~l$ekT!G8Etc6kOWO=}F- zkoZ~@{nld z940GDG}X%LDN!MI)$Y?Pe?=VV}~2PeEpT;74(ZZ-@&AZV}R@2}?%F z;B=CC!wgt1K3;^#FeXHK!X#dXv;z51-?WF^VS9e%M^P~zr1|-mte}O>x)JV|i*D<6 zkNa)tQJ|N*Ig$qp#o|*$)vooEL)j4z{84Xe#Y(sQuJWd}VY6 z=ZVkRlP=W7RyIFo?sB57n1m3~zdgz+3W@$7D+~lsLOwp;bvP>M8y{$U_X5Myq1wdr z(89gm4Td5P&NT(uuW80xoD3@>fFYAgdM77TapCBB9N<&-=a9HojY!ko3_Ni*Dv-%! ze|(9>wlq8U(o*%l6d1a$5p&|ce_5jb+h_sGtk0p@ zLq&?v5pjrL9Fa4s0}tTBwC#oQIb!OBz94HY2dMvretUoiB4whrIIb09ro`rH;C{Bk z-o8aL>erDa5VUc5{sxZu)BskBdJl@RaS^3+OHQGhB0e{%7>u%iXw|^E6qM#)kOy|L zcIWQ$2nc4#BsCD0{Y)sh)X|D$%6rriEwsSJc@2k9JllQhTJ`$rdDJ?VrRDc{T;GN~ z;w13u71;`%(2TSmqA7fht1JOYoVbZYI(0ULHIre+L$`?~w_Tz4<9xAw*vOhk0X$bL zcNZf24GJb(+oXCn5*|zhS=W;zHUl>k251pqGo09sRzB7K0$o8qV~A|C5+|9_0bE(x z^HJFN7homnr2kX$o&+~2DJMiSX(o+lMYQ*Jsu%}`l$EcWFCe5is+d!W^6cfu@`*T{ z&e!}zSg1bQ$!C}UEEO2OJ$~@vrQ!@iZMz+=f_&)mS$VL@2sbyV>S zufq|sqM~BO$y|cbXZHhqs_UKDk0ADyCUUvO#o#oI*|o$qGv!)jU-?Z1HXY5^!B9;c zhL4dZip03nn!L-3ilC&^KkLP6w#dT&YDsaqLXjRGr>a0bfQEv`=SGg)6B1Evzh7&1 z8H^pi==Sjw#NC;il5@c=-8GZA^IyHQDC9b~!!|>xCjO^m z1GF@nf|mK)N_h<(zysRVV%Cx)TKk8AyGcR*TJ8E&e(w3vEhI_T=0$<|`V;Bch)M#?sU?5)-82zx#xehTVCz_;NwuyY?(MzYoh;>KGgNHw-w42ekFFz_{}*>6(Z6RGk*jf!kBn5f ze7z*s*wg z`}U2}V1MTeWxg5JwSiu1Zmz#j42bhb^W8qz=Q*jCLtQXBj2|$a(rU1ut=rhge zXxq@WB4QPJdFjxz(#guAT^&d(4^;F)RkfXkZI$}@D}*nr4gjGB7@17!E63AA=XhR0 zL1)Y3Jjg8u`%{!2*e1`7dfiv<9}qW(zC1I!x; z1F30YqC?p8U^U?LUtP0-e5z&_25RYd7GTRlWU=>+V9ihoT&+Q@f?Gl*|0kId2=SqA z{9r5r#qK4om-#$-+I%1Hx!vw=#I{Ez1sfY1*`t!<1Lh_H(8xNJ#Kfe0!bS;+DBHj_ z{@QQ=B%Pg>DVuEzs+$0z06qs|6)mk%29q+q@!XA5owhG#8Fv6(;c)EU(8e#yh z>n{raDOWJapb>byaPT}g6ZAjB74_*69{|{N>`7aK3IDmMgI)l?^!OcDojDJp^zZxqLtJI?>03|^wx=&Bn#igg`+64b8AgmnPQ5cQ zg(RtQKf1+ZtGSn#mhR?=yU}BZ5D7gBg`x4=R90c)LBdZaLEUWk$1nY|ArYuAS9Zok zsAw@|m6gDEoBcr7<;`RHgTv$CPal$CPft&+;f4v!PFq`BSx4g`5Y{}{IZ$;wyM!M2 zzkJm(C~Fy!6!B?mY#fY7lkzX2G)+v724--!<1{Y6wz0=^)SyPr?e&paN0 zLt1R!gT#nrZ6gI!>$6LCa80#ZM)bB?L`1@S-d)>iVZsdl)`5Ss1e<0}Pd00zCH}QY z$Q*F`Q7;>cWNwYe$pK>GLHZgHb5^#?2VAA4uuW@eg`VENj_0`&pPL)|lmOh8Wm=s; zX|AUltaoxcc9Pz)c^?39y9pok343GXuMYX2q5?xFBqVu~UpAMPIHY*+-)9aLWEE7P z0Z!ika=VY8gVNtDF*Oy2$!J9I__6WgjPqR6hQw71zMR))iWr~jBLDd0#9z86z+L`! zd_NLM63SZbgiPWs+7n_kA^WQ^^xtHL0Qn%`?dXYL zlF&*?L@04K=ZQWXp8f49%^ZaqF?#9QMmd1+n}8tTEUCXd`=8mHKVCM(@##xY4zlXG zn^^lvnLO|*+t6$7xb2k>+$KUFF1N|D%|sxMR$90;T+&gloz52ESXfvl0Q+cwQvDSb zpLD^549{o!FbCBut2N!r@F?D$84m&CX@P@w=Jdc!5ffw8g8 ztE+41%!&%2qGGepxUVub8U!ARznUtgWaZ?5pYKlt?&?@MX*k*7=QjGGwdaHJ_z&PQ ztEw5Z09}hycc{FsH{_b%Onm|hKg(FYJY4csMdESJp{4BnTa_U|SV8V2I3yY34=sF) z5$KOm+8!>(iEdC3A}GP)_rpbUFM6Q@{x4PiQ}{YM5HqDxc(gZ*xYK}QZun>FA)Ih* zJ`}c#9|>d$@}e-V!X_mBU;porCHzHEx8t>*y1T-=rW#^R#CSYp_)4LA+lKl(2fR`! zJlyOEiGYT#TJb*mcNUt=3_y=*QBkoLOGH?Bz)Fj|$`1^79UI)ekrZ$n8yj{-i<6VU`$OZG>r;8dnYoH;t>a^Z*Gif5;;(*k8KMR~ zJ$?MRo~fCuZLMxuIjeH%1vi9>clUN^ShQUakjS6SULHc)PASOAy)l@KuZ$)J705D+ zswhPjKi(ND=o1<2?{&mcD6o5ttu#(7%s@D>)biiN{9!El$UzC^s9}1k4*!x%z&GXr z?i?JPP=Hzk(OKv@gh&g=Rzh;#B1Vf&q<>1>f9p5?N+Ny(H8CSA*?z^#4fU>T7e9Vg zYJpd|f14vq)f@!aqyH`ZKz9ZG8q@|sk<|`i@8qytqK1Ltm;_SU5N*Bc8-Rd^_k&$8va2UVR#`be=Y))y zv~%mYT*T~INLE%AVsP+hnY)$2`kIGzR$F?k>9)~eOkUKFggug2XHW>iih@r*C4X@z=tY=&*b!&N*k48B8*Q< zD=ke>e6?7)%=hRArt%LuTH3&q6LU^pMQ`fP#0Z7ZYxTwSDX`($uQ+zLb_AbFH^-ar z)N2aUp>J;;%so6-0D5>!EP@3NK=^d5OavUn+l`^7R$(-%Zi%I~WMy%uaE8~T1zRGa zWl?H@;WfF{YeLe7^rLd+B-I?9*Aqlzww}ralvcX|=vRKWs)|uMFA|+pG6{mEmL)1Z z9ZpC{sE|3M%f%q%{bZ2|8}1gl10JT%auteg&7SC*gp{=F%5ZoiTq-5AzW>pi5T*Se z3#woG{M`aHHPQYi!3N5r}X)B z3gVLn-eo_n#X`#XAU%EBR7}42dTM+}HN}uNMGP=`{~j(YC`cptmp=T%g#mWHAbs?* z`DEq>Ceb}L3HfA}qqdL*3^SoYv7vVa)Hi_q*;rWkrKDIW4XH?OUVK3^d8eZZUB7)Z zq1p#zLnqeOB8C73kqmZ^T@%OTNj{8h=pVYc<1qtExbDTwJqC$AKSX(QfbLG|ZI3iizm{U^8cWH~xdgY&So}vI?G% zISHIdai-n#^v6j4VjvJGJ`gYj9}ozFHy@@CPqbTlY>?@kxD`>2O8NkAjlrPIonqR6cw2T!+*1w@EtM?xHj2ey#Zlt3^hahbF8C1#RDP(^7v_<7| zM3089#IrM=&RV!nB`&VvfSNucDfhD5@ia~{v-y%}R%9_Pw9@tE9C*T9I?V9Pi7Y?u zY^WWZYt0f-kDgB{!eYrHhKrPB zhK85xpR3I^%;vc)UUCVY78Ir$DiZ~;!VOv@cdo*%rD_t-Y^IVtk|KjgI{=t`wB)Ve19e&qV zds>M2wP3X~-(uk`FE7`^;M~I*u|V+a4YL@tcKoVnw7i>4S>hU;hMZZV4i4cnGc)MCRNn{QODLya7un}oTwCW3SwU`29íy0;v157n?CRCJ_7r~KZ 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ⅇD8biJfoMez0usc4Ih|KDiv7diH%#d~+ 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 literal 0 HcmV?d00001 diff --git a/docs/images/safe-mode-confirmation.png b/docs/images/safe-mode-confirmation.png new file mode 100644 index 0000000000000000000000000000000000000000..7f30a8ae3429282229dac97389de5adfab4bdf79 GIT binary patch literal 807108 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Ð<&-t0KEyrj!Jg!S^v^P`_0C@C@LO&aGa?xv^t1p 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 z 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%0D_9qERA|&-a!nsZsNoHjrZq~ap zmyNSS=IIYe*^Orww=*y&?=un}7UEMz*oq?@2eP2kQ=LiK(|t67mV>aKBJv*p zc(3&v`nEQx5B}qEfZ?asWQ%ihR7Wl(M<7Kw2}h?dHi|<4e{>tjW#wsz+z!UjxIm=l zOJEEyH>;`1?y2&c1Q<+SYE2I^jRVVt41(Ap4zub3_t38-dEhIOX?Rt)pWMN9G~ludv&FYRoP-M|q#mqJ6vdx7 z+-9`QJq!3OyGLT(semA4J$zkJYj2#S^%;H!5}Qe^ z9E^D5eR>p?aFx8S@&;xA0-!Nqy=H=W9<4r^#)RmUG?4H8dJ;#L=Z?O&ka|B!=>*JJ zN*m2>jvZteV)SeLkD0%^MFa=fC z!6=JtfwSsY&-=Z_%Kn;Bm$L;6t+|L^1`-5cs7?H$w-cWB99bbACJhMo3l_kk z4z25fU9SxUSdpvRp~_?P#(o+e#nE$&7rMBRg^NGLfw*0`8?B+)YxLJ-b_l)`p)u~E zjMv`Jekdx!=5fz|?F!$l`r~|`uMh#r_-A*kw!nGt=xw=H@=+J3jn2ru`;coX@Vsaa zXqu#pqi>*+>ELqmS(M{BS|8sAV!?F%k|J30`s4f=Qk}#p(a2w|^MLj>1b2tVGCo~i z;d>dCJFQX3aKC0}7~`W>O}|B20KqeUf>cD`zuDIo$-F5HX)$G6v=ASn)BHtkFNWxr zc)&9o*>)H}C&h0T+F7pMul|Fcsm9pYcO>g4LVzEFjZAGEz!@i~Gt1KS{3_Jw2Uf}y zD?Xg7FOiW~UGm9>S9`BE9pjYlOa${+Y1SQF{aS`hjvq87LzOOk8s21XY@sn4-mp!3 zQ^0IRnuUi;07zI1!n=z6Qby!!%~)R>(-nt5w2tKf5{u82DUEll$An5wTV_TGnrAH_ zz?GQ-Q-F}-S868U1M59w`0%h4Y5-6?T&_PnfHnYB$ z0g*YoQv?Itz_q$5;#F>j&7$o$3Y+WHM94|Nhkr$I^Z&xTMZGcE<>Mc!;|?a=iCx3m zG=cQ_4f!|JxB_At#< ziTPpjBr~~t>Y6H8;!VitF6{2`I}icW;|k+RVA}!3REE!b;5DCy;LS7mj$w%T=HfPE z9v}S)YG+ZRdk?_U$k@>xk(F~EF@cH{m#4|k@qf@{;ASPeua3U{FV4&dDQS;ZvOE*w zdt^gXhbAJj%fy}RM=NaJ5PjJ=FnQ~BJ+;?D)i?hv?Tn)t`z@XwI#Y!1N`=sZ9aKI2 z?@?1WcPK1_+udsvo;Qrm|E~F?3bF+ilIfe+{ucZq#96ISU0J{O>E%)XSr_g89hy4& znRZ&N&gr9F&9RK%5zM^FV9p(cK@W==X!=cMt5m_vqpKz$&NP5@Muo5HAv`jBbJtlN?%Dd2b%+(BM-44#eV zFXzS!w{tZGpLGtZhb}b-t+}`mfu|9xvx1}5h70QZq(u;y1FKhA#$DJlUOa&QW$8w7+yr>pp8t_9JVV|r#^j;6-TuQwGPiY1k4oBB_umI}cS9SHjv$XsaF_%L^>?Sw`R?cE$c{mgUa zno9oGY*^`1N*1R=f;Z3i*s@FUOFu!KL`9q^5 z_7nlNa7tma~c1xHD&mx+zO*?qSZ~v-KKTc7E>^qL0iNC0tcX3qcKkV=-@WQwGx;75}TMZgynoR+*-)I9=g+rlWsV zL+RGvsRjS4wr5vXnufKPi#?oDDhB%4MJflB4BG8W{N-kn2sN33UyE$C1PQl_A67@; zHGJRf^-^|40S}dqivFg4S7Jg!Dlp+K_RG>?5+oPdmQjPA<`4&3f0pe&9d$3WvC|L` zs4z5CY^l>Y*7m#_h!_>Q*9z9cj^DanVmIJvPr#c_JI$Uafo!~iQ2IxNhJ&+V6aj&+ z7m(hdKL^=pQ>>Yk69QYYyO-B}3@|S4Aqaa2pT5pC3izNCn61{h)n)Er<+2!<;H69? z09<-Ka`iiq;0vO!Ys)p=N{mYb;0+D#V_`9YUmVmb{^qs$zxS)N2fj2F)+Q6JE|Yf9 zJ|t0M5Kk{Zi&^t~=BJv`(EnXZ!!D9fh=uk>C2D@_mU2!5()USc`dpS&uit?KF5 zbeQ5r-^D0DrC>DsLZiKWY&a z=AZ0l+^j*|7d)1gaZvr(89Zs!R`;dbOulBJdF@#WMaHk?Y2b+|qw?^ksK_(&b_?~Z zs?Lr+uavTv7W#*XOtBho7BhIBxa3&Cmqc)CI!-ez^>AL z+z*)+29Ox4PaGVD)nxzN&8$N#vLk$| zg!Uyae|C+3CGCD`s+^24BCieOvfp5h1K&g5EcT>vIi#C&t$6p9`&`4dIu8$C27#CH zFp^LCltItK91El1XF52*d2*iFS`Wv|A1sOmh5Chz3xbI;KsJJ5gV0%*NZUisdu-5a z=ulxHP-yS)UIg$}``S>>N<<$!$(tZb$ko~9<}0_AM0TtO8<2*c|GO-VjFJ%|nhTts z(?9oJlCBei)(^$L3cw4u@~Lq*@o%Js+RzWt2-jysIwG-bzLOa^y9-|7vJ-YhSLub) zyr98->OfFV`j)FAgAUrF2XY#KHB!1Vb;~=(&`Zbx#ycX_c9gfNiJFSc!XOaD%Nv#<*Ew}=;v+A@<^LkGz zA=O6Jm$c&;B(mYk+>*L%G`vb!nK=(!?ksQr!sQ<{N%%%pn`wgQk7gP-N2?PN|*W zf~LjGY?ot>e%)qj`Ocl+@ALAdxA!nDVC5>0Od`=9&^P_lw{HY-FMrLKvI zcPN&M{?fe~_;Is9?mh#b6F>~+>#4_15UVnc;hbyNuDx_2cGxr1^=vYxHKz?)JSys- zZxdYrp~7x=%tnsldSHvF`_+)k-j5+0^SM?$;m>BTX@Q$dxyI8udUD|Z^aAkw9V;&Q$BhOb^|Zf&ukh#cOFba~qX!->zeISYLyjldmmV;O z^OylE7NvsvfW;OIC-2{a#%EuYy%oR;qv>CfCQ2}6UTh2<`J{H$7?m%8rD5%NYgHYK zE#e)f!N~0?eb>XKLBOY=yRJzTIo8n+8SvHz6!O>Knb_8u+XCs7WNAHXM^0=cU7wwN zM4d3X{!$8N3|l_1^+Zw8$h$RpbF37WV9AB8^=y;%Zo@RaTe~=E0L@*pEE04vS_RFF zHi`>dWFQgU``~uQZFuzBLQP-Yi+{aN5xUmtrvj*V#B{!3o*-d|;u>vXMOX;aMyXpT zTbk);>hU=U3y-TQZSC*o$=@Xs|Dvg&c*efByncuHJ$%=@ z-%t^=5*;oaxF9GLP`8%7ov;^*GL1~ayq~X@E1k9*3sy4@_&DX;Di+l;(8p>KwgWD2b07sF^KG%^04TC!VtxGX!&eCi}t1m{bLoJX0tsS9w#tuds~}go}*Z@iFNdY@;jGx-_Nyr zkpb76@IlV(flZ#=PIWNL5dK=QacI%P!u(p5f06~raLfKKD;Bh#DXW0>&m}G7RnedM zwOMvF^aq-tvIBDRPf&a(kN+f_2aIhk5sMi8t1*O0xUkB6+#$a8I>$&nO~U8lZJc*5jN)9Y%+l1ZQi z-11#r8IH~0d`|u~*lbcFNZF38&AC!)x0aW<-w`m3pH(VwUljZU0{jSo-+_#P@A?6F z0^%1fAp9Fh?sRZZ7}JZ1RmJsDnGI~HAY^OK=R(G^Pi?Nv5NY9;L?=q_0&~)dQ;KN%5@WIT-v>r{iR@Xo;5PezHJ(C0BT_>H-}O4Exu(zPCLcf(XOk7bH~3#tWU2jr)pu<1 zqrg=YGq2SAF?iT#r_%YfzORl|8BNg*S-8~F$KftIVM-E@S3>PH{rWnC@F6?rLU+lM zM1$M&XG(iSTs~M>%HNthg};rX1()0=>#jrsEvJ+wmU_3psLvV={Kub%_R<48H4}WD zW1EjjtAHDhcU=aIN|v-VK)4u^i&~^C4RNGHmu@0&@E@!fP`W0*8z!T;yBg*+J%iOk zH1-^#AUZUZb%B@6i!>0p{@{s**l2T4Y;NxdX;byV)^FSrh=k9N7=WT&C+zE&M^x{+ z<+qQt@)&8Fm439|D#zG2Mt4!^LHKkHd@Wo|&ptLBOj@aaf9v?SY@YL(dZaqe)G z1^m<8;SE>&_8S57JR zzuY)}8}Q z-E*1~TkeLOo$;yg&cKWSyx0n+|Xzv;%diS z=91;#tP%bM&hd6?HShI5W2jXd52>{VhHG!J`~pDXc^$b@S=%Qwa}$pwZr#7Wkm7N2 zZTL+NYcm5@wO*?1taCahhMv0ZJ_G2_9HCgS&2~CE3rH{ymUc%70ecL|E5HP>Qq}7l z^5?G5=YU!~PrkD?CUNK3`TcBq;>*4aA9oEBSm22S3}Ec*XtluL{!xyi;*h~ABkmg@ zv;6^p27Q^V4z}Oflx=E*Cpk+shW0lAS%kz3H~*VuPid*i)B9V#mHFoJ6PlS9z0Zy> z`5w`fR)F1nt&V1;)7L?5mghPnR#CX2#X>OhX#~8Y5%}U!VX?7+?lr^?{(Gvf_jwuT z+!Ed^kGG)BvP%8DC?%0$M-0|su)1{!({fD_*`cr)ms3Aa|E0Xl*>Rf4j>x@|_jz@_W z8MrEKRjQuWPSaAIFWLk;!gPBrf-C4{=^fQDX2^kq(lnf2){5)M@GnK7fwd4x8#ZRr zk>ko2T7b&N&Ua~R*W{NvDg>aqCkt#82{^rv$_hl$yx|)A_h|Yu%Y@9alZCgL>VU8M z&L_3(U;migzr(EK!0^SElmP7-dID!IMOOQT>VkA4GV^aG+g~ zT4EfhQmKoTWT#fuB;ZrO#@k55zyQ!#a$E~~je;ULx3j<)K&2M$*uC!Svp>@`tm;60 zkQeh3(rX688L^ddegH7`@*CD$WWxb#wIaZ~{)gk+qTGtL$!c5!yMJ=%Q|4=`V9dMEc!)fMr61O&<>Py{?>2DHHcW^v18>gj`)O|&*&R5#-U>i**WF6TUBrh#abxe5}Uz+E;h}&q@E^ zx&<+?7MNDYQDEQdj19mtSbu!vDQoD&`XnecWTD;MI1y06wlpT?OZzRP#wV)6Y?UlR z&O~q7Ls2glE_c9uH+rHquZDBuBCW!mXH#UrQCiEC0=<0r3OR>ADX%Mr5r%Rs)Qx`9dKOgn(beso?2ASHO1* zZRC3wg9NCY&-4e#9nXF|m99t&%jlFa2{mazb%ftVm(@Ez57q9 z=)(+>oV#8ejZ$0yLS~o!=~=XxT@Tq%20Ol*J>Y}pS|)dG9G?YIk4{j!eznF94hCOlNsl=V&xlaIp$?f_FPvk z*eGee5$v}>+-J~nIRo`VJy;how`II<&pf=QUx#SKQ%lJ#la9)h$L6ywIC)m#T%`P5 zHoQt&71iR-X+Ek42rQUk<&yIRiF@D24%F%bKLbC042~J1Nan*5aEEv-pi6~(kdhmf zW}Y#9~K=lPKqnqStiie;|B*ta#K9rdVak-JJ-atX)ifpem)pmMe4YcGlCTFRPVd3^|L@n5~j zpQXmObXMoKOzAVZO|!loVSUYC7JIj@-!X&zkjHnsB%0pdr{e^g#VqB-bdxY*_P(Kq zDE$R9dji^VyfIASA$$hKPTh7U)>r9B{G`<)VWkni2w=#i9G?ps!b0eUm&~^r-X|xk z3FN`;LT2-`P&}t0&S?iY_&r=aH-wic*?Qzb;EX!-Jrq^jPh;2cVGe-kj98ivHm=Lh zB3ol7OdNq373Fwn8<3GZ!5YCqMNyBJtp8SUHMIvlRskug1lMlep-3FW{(*sCk)!LLq#Op>^>Q+hL8C@b8}dIaYBt?k6Zd431F}#rX77%54+M(l&&|5nI8>p=96@ti znQ`jumhTGX{ofk$_A*sHi7$J+3|sb}U;K^g2e>tS%MERrj@Haf=G0?SH#-G1WAs&D zX0>ni+&^9K1J$sfWAA+n4aPsG$QdZ_)mHrMjJMA)oTqA)o!9&5M$=F3u??j6iJ zA+S-Sa;8gT131tl<{JM5Z=kShQ;tpnm{&-a+Lv>wXT*Q~|rcNdJ4I`#>$u8lEe$&Xo#W>^> zk73_?3n}Ve?X~bAui^RGuEK~-qn22^Pje$jkc;fvx;4Mbsoe+@TAGzN{e}iu)st5s zhz_M)R<9XrJE*3#&nsl>$o^~xzXL7q#^9^MLBzi%PydE^QzDwPhOtAO=LwtWJL~aTW%%MmuJR&L!YzMV$Yz%-ONnKq`eX?>@-fYu)H-;tER zgX|H5a! zXqp{tV*}O$;v8yutXs_srDo3tBQr3LAcKtb;z-j$2}li9H%bwK zK}JD=geJWRp%aJiT3D{HNL-S>T6=XG99Be)Z{uL=Rm&m27q6bN2&A%4?Ii4*R1JsN%?GP(argr)IQ zG8;4Zr1LzCRR}C<6GW0_@zhPwRDa$X5x;jwU%Iv{)Uc9xmQxFLF5&MqRcU_Hl3`*7 z6*8urrAU&TuMwbIhw(F<5NF2Ib1=xp{<4fb;w*m!`01K9<9A#Oxi7 zA)u7fWmh*Sko0P7=R*JrvEBs-`ZNNOqrR3y7`!p2vm>?|Yx|_!(h8;@WtTZiF?T!Z zO&jWyM^-!Te;)=Ayge3IDgWd9Zh15q0!L!+2meH9k&~igVJMVqA7ULIY?2Ciqf;DD zJVZXb@1Adqt>-$4V`Lm)U^m14AgnU6N1sBWiMYGM;NPiav1NP&djk!MTs?5f1J%|8vN=v0bPLFuGvj$y_ftNvl` zYQ6Ad#8}{vgbJG6=$k`2AJf75(>LEn{46n$>);XBZLm=P2y?mpQ3a)sD!D7XTr7F0 zm+)tj$Z>wcZp=pIgRVRqhvEt0o^c5K|PW&5MNi`v0 z^yzUBO^s#U7d<05bkF5O?W*g}m~|FJc`Q}MI;TnBJ*tz7vNzb;F~z~Z;TmA3T9aCk za#4X8JLcd%G`UdGuG-{PF5`>S3PjCtA#V~_^Fm`VA_^0edo_M8GKL^QmtMh&ftmc; zcAF^wfK^MI&4`!-g{GTAX1zmtEc`I-|Hp4h&iLpUr@3pyQqkn36`0vj8q6Q8q983( zuy!vnD2RjKV_#VwS%I^%zsNl%wzx_j0A*{H@H@-R5HCLfp~&uy$aYTikNP0~gNQ`e zhMbMS`f1a}-WR;mOm;1-so%<4GXMQxu1of9^Sa=`ZM5Da&Xacjpyi~asp6fxVKixR zEy7@08~b2hL@BotuM{ET+ELhf)^W+zK2dKq9nuiwFNMu!b`-^5xV^-GX(_d z{5H!EUfIJXroQeGYoOlO6a%_03fMVuRm)$F}FIt0bjdMNzV6|V3p@IqJMul+f(r$%|64yg!= z@Rs1_P0?m0q%uQ0x%=JxG5!$R=v!ACceJ3ob|n1h*YL0{jakIb%>2yX7NRJHi-_Ng z1o-fj6BB5|(F?O&7ry<*3I%jGQ}#gY3=v74pyS-cFk#xI!jywQp_7wD8Fpt&{oQu* z)Q=6k>K$5{Plw;IqxK}8V9Rm>_^Q?V`R`Vh@fG`{_b+ij>piYRVfrY=^x2z3q?_@GEV1G zdJ*3>9_H`EM0S=~>`?=}bNNwN>3HJXNCB0*lZS5DtkES0@1MPpdy5osl5_z62w z$`Cc`aBy$^Aq0OvAP#XHFgr6ZSM7VP$q#;2-+)!^camcEjDD14al3lFbI|cRZK95= zlroif3??P0EBDAZ?XR`ENv&x&y10^)*cx`7URanz`n{zJ(lD>&YRlt1sN4+{C?9_h zLXG^X^<;H#$7Wd;<)^zKmIgHAxflJMZ`j=qg$3$f#?Gufif)$R8{|bTTQ_kSX2AEc zRP!onBc#mWiVUNeDb)!SUKO3=kj$fXR+Ajsh&JA9Ouk1GXB zJpVva$y<4FzR51#<_*haPI&JYE%PN{)>7kgHHnGj@r#eat)28rOtS`Jp^0M)S#zAjiT^j&pnwxV5+m;Ad z3|#b))m^vaIsS?;uq54j%S?;Wp5B61FM+@#D*yWooO$ zOpF)hz+4$Yh0yx-SO&)v0|`u3K06Z+(xIkZ9L_}=1f@VH=o&tVR_{{=O`&wz`wk8| z4bj!&zIA$Qe;4v|4p_l!{q-+sujh)JGy2$uZU3kJ^0tzx8G3|UwRLgor@Qy-1IRuB zR4~rPmyou-BxPbtVXhp(ORC6K0`5Z`v@NJlq zZLeWpL_62B-t$}<)oCI*nSL%hG97-G(C{koSL^MNqbt3h3gRw(gXj5;el==3IqHg-Gk+ZqG&W`wKw(46B8eWNuclvw+X@ zVXIi20o*L3{3ws$oTMLWKG+2;O2|Wzj)xZ_vENYi&>0+10?;x@6SDhD&TRdE=#&=L zbt&dQYhF&5`|*i=7>!~7e!@g}XCorK6e>oXzftq0`fKCo=UJUFm> zG07tdEzAFYspDv54+X0o>cqrbh>T*rToq217RlFz?XtBqMevlh5b6Y8FjzpFl9N$!1ZfI8i`=iY^~Jh@36n1AQB z-V)*kq+xmaLDe}lpjZP6)YSX|_Jkhw$2`p@Yh%r|!Xw7je~l+|Nn-M`hqqMwFy^I^ z(7Ja&kBG48xQN1<+45`Cwa)5}^c9&fx=g-4Qf9YyIiZQW%p{uZzJ+-Jf;b1Nk&bN{ zlUq+_5zVK2GhsKdX35N1;C?W#s8$kd27t_macN%~>;J&3f7p`dZX zQi`(1!G_M-T^9?^?DaVj@riPg%Td{?pCAW37al+KvA(LM5OmLMm@MF7(Ci@c_>!PT zwH#22ooHE`u=M9*s^0s=D4xEZ+7a|(#MZM;cgL@(vZxT!_ICklQxh|xpQrar_niKP zB}kbe0F|AeYycxha&}VA_cv_&ie(?VzemrqsxmWw*ePIB%YFD>q@vx^<=l@sM))YT zhKmo_3fwb46*Q9gsCf}QImR=KE974O-lw!S#n{})idI(tIIa|-+=jz9u%YAWsoS%- z%pTeW?T*2BMezxC@`_8R#HxlT`1YQ`(Lu?A!-7TL9Qm0#c_`o3$cwUlxF^F+IS9T* zyH3G0n^UXlTWc{GudAIMJIgWSsvD9@rFyTPqBWRZ-%CCwNEV?DL6FVg4Oc%giuNW} zhp4gvnFWEe;X@z|wG_hwsP2%g?CQjZ%BllH@~TIR$A{|G;d?)Z#^SgZ$>bQ=>g!S# zo?RKFpBLPcY+fx0H=C|89WT5Lvog-AF&|(Ko4|Dha0ruixFJ}-pB6upre8HYy&Y~qE_WJhPV#tw|BiQ#fxSUeNY zNxf=N&s=kBweg5zzlaFeR>!5BU84Pvjb^u{F$3kuQDWOfKfS~$R&6a%vw;gWf?H^e zj>j5EttA>(98K)bF`>cWm)f0BQiPxM60U&9Wo7Am;D)KRYN_|zZae6BNK zyL#j*L|q;6UcUk-vLiwc=-uHoncUIqX1U1gYPlmL@%W*7`>=OJ(T0q6Gay$Bw zwLGMD`ZFJ%Ia?H1wIBte(WR)3J8r+?S3R4PI<&(FyKFe?6q5fuy`tDcD($0V1+uZ? z5@CbQk*%A|%R6mFa&4y@;ZPq1jla-2GSx!T1{vY-(`YxfG+Ff$g*Ho%z#aXsHB!Xd_PDO>c|__F=AzE_tfON_?C zRE~@*K1Hq%a0RV=8i&*9rK_s~vngTW%tQS4_#{)vOH>ArAt+NhUcIXTFL~IMHa>WJ zwwN&psH(uzV7EG`{&7dgAnwRCykXz_A=I0TD`n8Bc_k!-A*Wghh3GgsJ`wl6^ewB&rtTy^8F;`UAARDZFV7@ zP_VH1z3T^dB;wHCx(gpK-+kjiiHC@OJquginZ@tj7Q)oze<&h#A72w8mMs<{ldv7` zwZW71Kl8&R5g9om7PItYhI2Y;5AykQph#@ZVH(}lr@iCw&2x{~*rZuH>eLUkIujv6 ztErS!m@)g<308g>d?v&e)bfGzS0=m5#{AsR3zJrKs6nSxM$}>IW{lE%cgY58fX#pd zcUV3=IUL#4@GxQD;lsF6$j7{3?q(s^nh2wd(lXgDv^8&hT&QVZD?tHnbe|Bh&)?Hl zlgj=8b(84aqjy7z=t?N0)0`+A61;?O)w?4~Vby(;);4Ur_cC@JV%ef?&0O}X!j#`A z(TA^asU|#iRkCiufvGt+7q)Ac+nKdIjL@)vuVVJl5Q~Z1AkTeEE!3=jROk&9`!*_P zUH)H&SBsnN-0rgEvvDUE)nNLoX}|Lg_I*w*z5Ms^E_DpWtW$l(xu?yi^6GBaw4fhy z^g1|p26qmZhsNc9Z>Bye8NY@D6^B_bgwX<;8!;2N6&f$0!)Thv;X^T#`Xa|oMAri4ngSYD0pPxoF3+@whL%@Ex21&iUR ze99zmLwVi9mXnjfN)5$ulg3X))$2xtpiXY;yz+z#j6xAReCqZ)VrM1(J^A|^72yT> z_nDgDha{4y0_*(dRJJY_>vz46lux&l(_m+3Wlc)lfco$J{)80PqDnogqBx3^evhe= zfa+k6_Nw50J=CYeKR|!DABtH$*{>=XVodcy$^aGSK9gyHZQ90gS(IVvUYYw_O^m0G zFHiRt+6Q~_@D$d9Os3n0N^5rSI!L4YpvZ=H;>j95388-~h$y6N>52~V7XVU@nf5OS#q!i;rnU($tT(pJ$ zBo@%95p-IrD0@#Tz=Ln2`4lLfo|Uk~h}=T2Xd{EItySwBL^=R%jNpzCjsd(|bxw`s z;PL@?#tGGAR%1#cVM=&PmO~P&^??c?J7i!UMrCx1eKUE5#7F?GHEk9-pedZf6k|@8 zo00KqYZV5K1q03qGl=JCGlXJ_?ZA=Pt3mxwgaxj=iVQG|cEKI)YBzX|KG=lpc$;T* zrWS@eR?X)$6OE7z1q+4Ut2r^L4xDbqcchMfQeQi=5!&t8x8XDhKyM*>*&f$8pkeof zWfCew?{$}P1jV$Y{|(sx{h)l3XC(tuJNf415kaq~V^pITG4f-q>=$cx$ZoDbvtin< z`{ejA@Az;td1xhta=u;2@I?rqwmCmFHYJr|)v~gFc4FBUR@{HzFV@M{G=VqgS>@pO zrndZwHn@(TOdNls_yZ+!6Gs5AVXP^wk{h4`ko%NQHjzjRNb6AL zj#J`~qq~PL>OcdXn^HcDs0{MqRr8jcRATr;n4~0$WmDdmU?fbZ^wZg0ro$W8U{9e9ND*b*Qm*p$V}N`09|eG8k$l5#}G$ zW|--Rzh|+-p{H(}$*m&O>nspVI6Q_P-fkqlFFTf)k(@I8L~H(Nz)Il@hdzW>*bQG6 zu2|Ci$CXotO-gvZ+qG{{`l6x7p|2*WO%n=#ByO`L21x?(QMOTcqh9rM?th81o z<@pdv8-UpCoS)3^(GuEC$jQ=XEE@|{bZasc)E3t0M^5K2s!*L(VANMZNwn8u8vZx_ z2~z(BOe_y&%A*Y5a*qd?zTfZ(a)m!nU=#XcPaSp0zGXQklv$8#0%sb%3yR4Loe~{G zX+t3K%m-Um%)Kp&p&@m5xcB|MT`p=NhIb^jd=$=$h|_W}h+z2^A|)O(0$zZECNNYr z6UUPxeeh$LF(WguZsMgj7t;+{R0wcTF=CDh(3uHx^X0lNrNn|v<`fT<3B`M>zkL1G-Z`zik0f( zgu)dfE^BDu9e1uPZnIz30i=%hF6d5s>;BCfHC(~m_Kv>g}JOH^EUXCR*RoTQCssArEMj($`2U(zAo$ez$pNkPql^2c9M zd&iyX{q~nUGZ9JX(5t8cO;r`1k-MtQd)xG*+ zZM^Xr3Ypl9^4q$L_;7qekp3K%{V91bLh}$XyEHam9bp8vGFOm3*i$-yN}~7t5W@kD z$j>KK3LL?Bj=X{arTdPyq347SK zKVJkbIa3xz41XY}fviiu2AKP8=fLZ^Pfzb4?1S|hfBh%d+rsLS9Rh?u7WfU)ZzB+V z_`bwU&B!4aw>OPmtGfrBe1P575^Mj~HHU-$A%B2}v7rwC$7;@KJR4@l^PsqC~aErsFaESp+XrJ+ys4-WQduqV?d~UdjT`6^e0*PW=Zd6 z?}fW=2kz;lSEx?~6IkjX@8ug-wFL!Hxxr~mDGw!kjJ4Sd+_8Rt%Hc0m`ND4mk@Bjj zuTg&TgD}AoL#3c(|0Blg2S52X#8$P*VA`TKfcTFGL%O=W4qn+fy4)?GqLC=yt)#A% zIZIloJ2oS%Dz`r^njr7kOB&kQzre(I)RRl8Oe-w`A&?VV=sE?J9oJ?Blmc0Pscp7H zBlTR__Skz-!efOqdRiM`0Z%&Z!!!`-2>j9dOK#hf;BUE~;jG=Os1!mrcK>AQFnbmO zw|nk>H*)5{|8M3fbRY4|o*O3dN!Q`SWY;!38-hj0zqn z9VHt=(`}f-GnJ15OTR_nLfa*HT?hBYR8k@PIfB!JU-}LH$2#-jW@?~+7Z6|Cw-du| z=S!$bl1C&AzhSG%I_7CdU6ni=p`K4ezUNhRrpy5|FrJR=ABwS_+)6 ziEn|MD<#U1yjb5-(QM!cc7;fEvA?qOE4LI)F?oE8)U(V7`6Mx$vgOn)w5yk;hD4FV~Z(9{)>&@6mwIH*cCcP>OW3CuS{fl5ba9Q&hTOz4aJG;1``O=+uMiS z!AqeUb>{%WSkT;Nnnzo`+!Y3Y-3iKUL{UWy>b0UpguxTUqo1R&{W*XPN{I;=lus3@ z(7j}+-#3txomxugkgy1?*KtWGLn9pcVnu5gd?ht7bMpOth-2)9=c1U)STkzZGY0Bd zdH2l6BD{5B`T`$t6M&08wwFcVbO{k2uKO)I-Pk9LQu@++gN&++E(vpmm`7)a;_ev@ z&9jIp?w#O8q4=pah7%=GZ-=jGQ}(%x_GCcIbrW1o-!o_a9nxc}O%|kn&Fyl5xw)`& ziawJ{Wkt>8tAQ)p899sYD9PBdglpIriMVim%2PsPGi3R-lBW&Q|2_J^SolFSIq&c( zJ6JSQOan$Wt+oBo!_A`pd_W>o_2a7KMQi84Xc3UVb)%Q(un+!gP{3Yho6X@Z_d8l^ zjZ3S0;T;dQMJj1qU zNDW-{w43v|^^@XE%|r%y*)@7c*DWX?X=Ywxr~>-qb%(3x8=Hwnv9Q9$S_Z5hm*dPeuphNeAVbV z2Z&c(5Y(+j!^h!<#nCRL-p5%=F_*+lYkVofq7CCb$(mZpypt&wpUr2UNc3odez+HO z@@u7h$&;9U-(4t&)ekKEQJ7!UN3-z-ADs(BPVc+jGHFxujx?Z=5ac-zbn4(p(g`I|- z?gT~6$~L1>)BN=k6V~O4DS_csyIZ68B(lH>%DrNX0iRznMU_;HiS4{|j*Y$XcKfOd z;gt~Sk6ZQ@I@E|?G)$>-<%(6rPQ`dvl#X&C`h4$7t8Z7&aBR zYQ9im71;bhj$w_`unS}EPWdvkpWvo?wXafUw**c$9b#_4xbLW>*eZKp&>#jx9pTM} z-3NupT`I}z+IhDJnhpA8pQPmzBkul2zsI-YCP>#UE#;}FNRayP&Aft` zKaDpjN**q%nON0KJEGTMfSWSD0wlnDvw38MIY+*Oj8r{8_E;EIzLF3WxO=Yh=fq;_ z?}v>3>jw!ENCBz7%~#0A1G4XCZgM}L*U2`vZYtwPY~6>X;6rMA<>)2j!av$#!6px7 zPkvJ`ZC3el+1c@}%}{-vxO8u|L5wN3!mG?|S(zZKt{hz~xwzj`Nd0sB&$LtD<&K!W zWwszFFDECqFb3y|S1jG(T%?w)f0zT(X3HYXTxC2!~` zDV{c;)^V>LcWh~3PwN!p>a`c_4Tj0b_Eli2=zw$MnOAv=UuRlmCo3u-=+s3)B3m>d z=J13BFa%6Rfub`oBlK2wA8{%1E_$c=wE4-Q@T`4q^X$r}BQ+!tkQUTcFyM1~&*fWh zNV)Ut*zdRjgRD-81r#Y5iJYodqqWAdK$AE`0vm~ioJ>NPCqeB$NIX!p7Qn>K1-6f3 z3waX`Ln(h z+|R77(>CKU+i*E_zuaUo_1J%1@e7im%Idbn-$*1%-uQ1ZyRJ6R%N^fBEk?R#6 znKx=1Mf8{N+L~1PUA+OQ?$WnMO(y<)a9kzn=w>ChAt-!fXP94@U+2&s#^m3eM17SX zuUf_}M1;8%Wuizd$HzUZyUPLTS%L9!s3F22K;h&~TOXE#O) zs@dB%NN5R^xc!G;nVxxoi6UFr}^_bE<5TI_s_)AKK`8F&Y5X4ePNQ9LEj-EH@}T3RrlS| zF3~`oP|aq!8Hb&xj3o9X*T(fE1Y#}l4PIU<1WaDe>bz)B*?&2xT8J`FewJeg%2=3S z_OXp=H3%lol{?2GorhIvd5a>!lDx3{_6BOZiHf6l(atyl8N--13EfO(E}%gY%j{#> zi9&5bqUG5?rqXk?;V2>3rFgbX2mP=hTie_b_Z&dDHH3#iP@ZGsD~Yxuh9=>elI>9U9~RIy zFC_~Ki`7&PZ?8n%aa)T|^zV9P@Rnp>O||(;v}?=EIm;Ybk3dejlg18VaJO zwg5RqmA956RTx~t2TXwJ!lS?4BB<9h~s1| z?&Gbi1`2CE{f!+CGj>sa3puV;w7FJkP}C>TSekaE;iaYnStOb3G1C)rdm7X_+9llv zD0KkYcQ(h3?stJ$bNcnvsX3rE87@Gz;#4a+p^N35W}P8u4;gzDx}PZwKHSz1m*k~f zii)n76LnTwn6UmY9_<^aDOk98$TrtVuk8+26wX^MLGIosL#&9Uq53qQMS=!bKUl7 zM(hFwpw0>X99v~ru&uY%ONP@Zq-W*o-#mF!F4aT!?&t=2$b+|*jSqPHl+#smS7<`s zYxm!4tNP@^_xA}NmZCNpL{{s#F|i5`$?HPp7dW?0c|_DMdfr8OdHw=e6xRTkQDFIfBh^=@^gcN->A55weVXNx;19NrWHOw-Hqd%03Mcez&y~w?x=v~p zhf}r8VH2qCYHLi%78t&I5uQ|S;F9!b0U+U`+dxkypAB6RR=xz!2#sm3Z{FtnI9E*Q z6gaOybggtTucgE13z+3A5~KLWCPl{-glkN@LHFzbQ47Gg!LQw|KwbW84C36lED$_r zf2y|q;}=ml+sV9R4YiJ{78Vxz+*0uPVI4GcuZnN}P@Z0jUXLAAea(N0Z4a7e!;&5% z(c0ppFl%iwKmO7=5$JXX?X|h+wP4e)AgrJ(Z=#4HlrF{J!>qweLc)%tyH8CL+d8zu z-ATqP&r;+~bg>Q34X-y4jt8SKt!k%Be;UufqHdcI27BrE2^!e)1jancL{Ae|6mK-E zTIl)jE| zIL3?G(HHI+F*|F~m>VT^9h?W@To&LL>M}_V!eAIvDJIt@lO-jKSF;h6$-UDP3TRM+ zzOd*PJo>0`>%DMuSmi-179N!we(caz?HD5%-0h@7n6dQCXzmk44eAK<3Ft5_|4d7g zf@0H%6i3?9cYzxRnR|yCr_Y+hkb`+-MTO@@b`^ch;1+4^ZV1_OGPm3V2M(A#Oy`kK zSlN9i(yINW^CxXJ>$Jtreu42GDa7P+KvK$jh#JiCtN-iEpVT{k$N}$f%XA_$!Idc% zjGABI(HvT^wRxLZ03_Rj8tAT?M?50Y#NoD10SzDGCx{PqGHhE$i>I$B90?9y?~QL- z->qevw~3ZcH)a=x(Z|w60>_u#`9F5@SjiO#sS}SXWVH_}duA10B4s{07^uN}cWmrq z*Po?eU4Ia^c{z{~aFqJbr~H59fhzR0EEo_b0Y+&s1`CV3Cb*s)F* zz{hN*Lm4ZpA1c1LmV<5C@WzUW0reJOgKcKvdD+4|j=#%hrHSZ?#(2C!lt>mWl9~92R!2q7=Ir>w9Sg7H4Q} zQt{~bNeE?AEPbVlI?HF#H#k^X;+f33b9_vb&4;si=Flzq)-$q%ov(GSE_M#u0}-IZ ztUFbP>iYJE0{GdsiVsPK!`WGx`cQMs8-&r~oweDal#3+9WFY`kb?t}M$8)eI<{vs! zYv2`+hr8~mjrOPletoa)IqT*Li3cBakw+`OC;P`a+@R+Y8ch6`R0ip2MA*@pr}i*1 zmwAhwxPL4@5&6AHBpYwgU>EYD!6lR^#kv=SyQflNDO&MMj-j&u=T=?oL|aHS^;MmN z1Xr}Eg6*EJ1iP}5u1i8M;D`8$djt1JJT5F+eRb&$i$tV;g1-!rd*OYisdU0v+!?>L zGACN0dkfS-|C{*-&I?+X_;1m26Ilc^L=|+2?Wxd+C?D%q9cxXkY_Hw7p@}&0u0|fp z1&;xP8$7x$pH>nLguI?7jESak+XVjt5Fh_|*wFvKJuLj=sJgVP|HSsvLjh$aPb)P4 zqDXAOQY38mT9)~4r=N5JYCH!Cuax;5KlUiaRF__&tt7pIyBaBCr?TJrE6e_XSW%>{ z#jeaJ4ss~Bc*k44OWH!CJ&heN+^c%>(Mm1%8a#2TsQE}1&PD62W_l0(qU{sYaH@A#y|GH@@{{=Vp5<=!Yfj!}suFYA$X0nS6_)2qbZx<}Chkq&fvQg+x%v za0~smbL5keg6w3zZt=-+`qn^Ej`sassqANO?iV1 zs>}^_#2#iZ7r|J7#o}-GEzZHJnuDzrC_$GI7AnNJ{z5`@lm6&fJ#+AS^|1UdqZ6=P zRS$13Y_%H-vKV+AtqJrxV~MW`g%ljv*}07qN-BfBxjLd}rhcb9vC1UKs>m=ylu7tf zgD7UXm^=cLmXRV>ek}|L|K?l8&l+Y7i|H>^1@cu0kd!1Ibo1uTW#Xq~xm&j~Xq4+6 zXWrv=H|DWI8`#C7Vr$Ne(Jn{vmfJEC%-6AD3s>{W_`vu2#lFxr=ePXZt;3H9Fz*Nc zAag2>Mo?@o@^)|%-I!I(*qkxDbj<>=Nt-FVA@Gj@p&R(!V|QU)>?vG1=%C%}sX3&t zZoNlhq8Juv`4$vJUa}1+9a2TVo~HS?>Qmrvlq;lcFjBeOCHLwTisavCV-%p&_w(kk zRh{+`+HW-*f&x0+XbZgyQF>y&TF=rRBFYrs80Kg^-*c#k??i1LR+vHMY^NBlfVr(6 z2`OkLb8`%bl=)@Snh~B?^_MuOK^Ynad2T!@QWg&=lnah_E^;w%xELLRXzJjyBsJxd z-R|{Wrd40fzMOMF%~JC5Ez)myPJaDEYyNlHo3}+~Rf6=Q95**J!$%D6k6Zu%!%tUTaP2^VnarTP^#hqD z?&tE%4bP2`u=P)8czFbA3Lk5|8(7*2#>Ba*yCe)pssiPPv@V@}!()qLN9B@_kA=4` zZ?bJ(*o=2T?<+}gSN4VLCnz_cq7cY=X2{&N31_wbdBJgFo4BqZ#hu};;qZJ*$LYDd zWy;MpkJ!I{SUt0_$=VeiT6lw4Z(k0+~S9Cn}Ja3xq6x;LQMx4don9HEcJ)|^4W0YHDga!r`hhF)?B%lewVr4Rk#&XI0tXIJ_4Hmbc~g_5%EgpT zAnfBGTIZjUBr2$HPkPrmS9}i+KNWuwYxUQOb6}gd1Ur6|XA}MX`Rv^70dYaIn-`?9 zKjAad(>a;K{P#F&(_*TB3ACyp?8^!B3qHun%%_@iy7b0C6_!q^a6Um0brre2HLcgjcN@A++p4o@sngt8JXCAcCj9x|zb*BX!by(qt$;T98{*pR}y zH^x$dgskp>>DLm7;iAhyfX?qbbNBwQX|S`jzct6X5*Q3sV2B49rV9R3S+^M5w@7@} z@b30?z2hq2pBggV(URj^$ea8s|A)tnbz>=DIYV}_!H1u8piYQMIb3fgW{$B)|BPaXSW?zz5nXD}hm zUb_D4B@9^sSzdnTp%*AAS5LG z)Km?B|NXl6ynGl5BrlY)J{a$c_iWL6a<0ZN@~AErqU<;LM;k=%xsg`%`qFJJmp#H) zovU-JXDo?6*q7-fe{bv`*4P~HtuyXKhan|-0(5Qm9e);p!JlW^Cz?%~|L#CB&Y2(KDk`Wlb4%5Sr2NxO&i)5rn zMQFSC=&3DRf0+NoA%mL}xfm_#d{;|Yc?Z?E9JQZXJ0gnA`;XNR=>G@IQ@63JhwVTz z-=Iyw|C|wG{|P{-*}qU5Nw$=f$m;fdn{Esf-@YtA zF~L=Ywom^aP(5v(jrs|O%^P!yJsgXZqg79CG(*UaJ>0HF5-DFDiU9K-Y`YDS;z}yP zOUnEQ?p93!B0XvfqoS2kgjo1P#}>t*IM=*RzK=D_@0c-bsR4jnB6j1Mu|?)3VRB;a zO>GNJkNw}K78b0jiObqZA$^UbR`vvj7bg5G@9{4&pT*4#@n25%TKW{fw^| zTE#_j=A|_^2WMfgEF45H0wMPG|VsiV`3hv5fLXD88Yi)2Z zw{tvymv_jjSkY{cd&5`mruu}LmgN#)|G(rYkhfVkzH{U87L8p|O`~tCt!fU+Z|A`& zRral*hIx6HI0E-puOl@=gyo@9IfphId~Q29qRy~2-FZzq+L@Huf6cKu&*`o{|xn!w=B*VgYvVwGL|Dk#4Bw z6rBXje59m6c-rqi=#^+79(CbWtrdIFbrH{`ip=3w5-ID0MG^=#>zN3o2dZ5%o6ezm zQvZhZPZ{(tnZ51B^PK5qXny?BzwH(u4kizg9M^Hf09f0;V%DD!1bcHNot$1L)qJW` zCah85A%j#JPZfzIG}g=;3s658@l^m!8Q)Z-Ya)(7j>JSnRX?-IQLxUd0yz9uLV|K7 zzPC3Qgr(mK+6tW2L+oiIK9oBDGV@<$(yScwUdA#|Z%gNFRi6>3gX`-qWQs^u?emj# zLQN@Lb&@0Y2m-#!1yH?Z7-s*xPJuz{If-%S;R=t;U6~YHA)ATaZtUg!oBay1mj9u& z{cf?=g)q9d*Gm5Fwai*Fk6rP9oU%egDUNBZZuKM*v*|8{G6Zj3lTiN+CXqfCQ84GJnm~Q z|G!kHYAtIc&=Yla+IRLQ3;PQ1{YeUUR;x~jy<)taw5qnX6sz(>o?T0(&J5MzZ_xh3 zJ0g)H>^{2VPAV|Z4gd>-Tkc)gfC30IwPUdHpi(>9`)k9k{A;+o^j%!USw_11oTyyxZ;H9nn;A56UWhue;%kQD-`{L` z{|kfn1lga}^qxQtM>8fbR#>mBO%CB#9+V#DaK$z)XvK)sxLQGMjUoaT_}mfJJKe))i7{`!f( z2{~~VFO-$G2WD%0<_mR$ zty?rqEiSLWqYcM+%-z2&!Q5o72iYn$s~sH3(H>$C-exj?^B-&Hp9olu#}6o@HyAIX zJ=lj*9CGqAV9KzUOQ)!6E93pjZ5E&WwGc>FaXAU zKdV=nrTivCM#_3%nZ*nm3jZ<;`>$Pc#?*N6o(Zev$&r6sSiphbMIOH-{qnk1ai=kz zM4=#$Dt#Yf!f;#7lM*=VE+hbMk3zq`$-HXv<$L|-0RP%43e0<~e+eZDg`$gpEVm$=Qb=KCe(8N}}X+43jBG_i9_-pEi?QB-%Onun?_uaE3 znb-Pi`lKLZ5lEEXK$*a<6;pV0u=Ma{@rCjWo!mRFO54@H-@wGn2!rFBJSFo1ZcPU{ zb}0#37z5=wN!vLSLqHK7MM0(K-xPjrMg85LYT;sips$|?2rR6s*?{bu8j`GP&M%i! zpDwU~GUB(|cQy`oiDh@#fm;)*B25v=YDDOv z>HoHY&cuvF*V!%=ZRmIXa+g}39gK-Hxg=Gjb#(B<@*%DErJm$c8Tbciv$092~4?Mkx`vgc|YWZV8fS=*ODMcgGfw~`g zra*f4H=M3OZpZVI^U(_n4sF_4FQ-*oIoHkR|GUaa4RO7-eK6@>0JQc_!R~4QfQQPV zv&q|ZW?`7ED?0mhIJl2|=YhHQ@M3yIscUc7We<+T% zq?I)rr=~vJDh~LEy>IwQtCH_@gEIL(tw_8vPjFQjziiT3VX~hH}cKBoG;#S zfxAXcM{M_g!PfmlZe@MP#AJB22$ufkwpR6Le*E|`U(tB263zJvT7#s=YH zUi0%8^q9%0)!qH$anuPFq5lW`rhl9F$+W2c9p_bc2snubJ2zquvCzXZ_I#eS30W{g z#s9YdN|2XNhjWo>wPi_%k9X6M=F;d*ejETu;`_Y+jV1x!1>BqYtY`e5B7&mm=;ZV( z8!M|*V}h_OaZs}(9q$1w+Vy5%Y1x%K1@L% zPoWXU4HT*RF#$2WHMZD}&}WQ`IyWct8%DWL-iYG&yoYBa@p16WcrZP83l0YMXnmRvbSaF+f{C+TNXHRH2Lb85$p9)sM3f>W6zRR!Bp?DJO#!77kP?yJJ3+ei-g^zb zhCu3ndGF1eng7jNcd-l$SCV_rcgjBdoUI;-vD47T85FTU%SBGo#=)>eGh_9W_#3_! z)iqyO`5C*a-`(8&=p1P2kKcTTKDys4wyEm1-Fjqrk>zN_HzN0_)yJPW zn%DTS!S*-RAZ#;wRhhr(wmzfYle6P&y(N7%Pv;4-e{6Xm`p^BT{Cc7FpZ+wkqq#|u zq&S6y!Fc0YwQK|(RyMnAYrVkqd8yRHU(ebAKWz0=apq>Yuc5ZXxU6F%U7l1>uY~?B3zI!{}?In#cR}9ngBh8H4Hzo{U_+` z-$!%bgGJJ9?OCn!;v-frF2R29rK613(G@GMHpAzVG`W-idOeF&n2Y!v7+GA9??ozXPOL1HM@KC!LPP$xx>petL6{tk!y0t%14_V{z$m=VKIja#OIM%{OtE8Le>He$L2|8Q`BIcO&TwhAyjP{gVa z@Icsm9P<8>XbdJ^bq{+M_dQ>sd+_#G?3rd6gXw2LM&Gj|<>O3n zd!`Ee9EQ8$Y{}N<8?5|s=3j1dvCPc@cw&RcmM1hJE!i3qg;@NwI9uXeG<4a&h2=e) zA<8~VD3qdixd}WSti`b188$ehSj1K0ns(Oqd2QgN&vJHM*K(-q&^AoQ&(%o+>IoHF zR)21*Squh~qb)M1jm4VcGa?5KmElSd0*8U8==j9S=-sWKnahl;+zK^`+L`VX>-bov zARAj@iGl7fM}(n&j}OU<~~4G;DFnskJ60Y(iq!b#g_4dTD3sJYr2L$mY*4++zK(L?>j;w zJj@M~jl@-Z03M!SuboT{kNK{3)jwr3(d|u9*6E~UTkxrO$;PJQYcv$O z;s4zsB+;=GKTV7c5%FW@fTDylYad!Qce*~`+}367pYq>(7b zO_CD3dygg+s)}RU)u@NMx`K|6=4T#=x3SBKCbfS6+G0g3)YzFM`2-VJRu~qQ zFW1TY=Ci(bXf1uZK6t~rAJJhaI?>)eb?h_pz-`&aaEpirQ{0o9uzo3=Jz5`&JS{88 z{W8=z^Actu1pv znNi3}r+Wj5t<~a4`+OC>4G$>3RV4Zvm_IiFCz zOH0ejiuV9>|M*-g{u1ti(s|cRfpn&3L08m>eJZa3;K4wDZ*l66Q^gq^m@MJ+xo>Fk zQ-(hUp*8azE8EQhc~y0=tD>y_C>p7c@6agzR%V)0XOo$Bn5$R*UIN3K>`?LMD3bkf z%g*c>{c-mlZ%fY_(Si9?{VsXJOg22{P>`knK|D2fQe`p8_rum4tZhVJZJl0;5K|qS zJ1sUpNw$rB`YS~6bLQD3NP4_$imNLzV-vOTP-&{Stp;xT-JZYxzHA z#0h~#Z2?fC;p^AG(Y!(xUxe78ezA+JgoDCc1T9UHFYo(j3Bo@J7`=csfDrXt>PM-< z=h!P05QhDNGv4~X2U|0Yo#RDy78I&T9&(4Zbr{yX%Uv(6GPT$f`}PXAg+KjSBvtZw zjLE!&j?1H$rD6M&|1S>ZKUQG5a3EZKn-%3D42)JoQghyS_(ign=C&hrU%b|Hv~_fb zM*akJs4Hg`6{MwW`B+g%Y7T}!XWi0nQ3AaMJ~qEiZS=+wc#lmB3qcxxD7wCb1&22l zap0@ZU~w7`9g4NUF1`NC{pu5+3?J%E^0tSR`V>~LF(+#fWro!i%M8`Mj_}^{!B8la zz#NN-Vl0%{TbFIl^&Rb>pUrw;cRgJ(*rK#CY{KQn$FcSSU$G^R)-4c(!#?CXPswEc z7v`+$(Fc1o;7&N?(nfZf;K!+d1j_)9gCehkpn$*{a;5U{vzz3=W&1X=ewEYJi1%FV z?9YIX8e{4yrw~Ycylic9a+1D3*E@{~jxH~FGCmoyhy^ycsP%wxzN;=((K+c66WnBZLqSDGk_4TKmPGumxe|pX)H6`mWWB zXp-klO9hgR|K!=$Rtsyr$!&x43Lj7Q=EoUI&)KwyF2#m}>k_kH85??|qk~1_^Jxxj z-wB%czXq0p-De9J#xMiQ7?GDT*}-j}-EnjNX?yB!lk>+7KxAcVnbpup8hN#zIY0A^ zi*VxEo@a@0yuqgXktFNsF@z5)C&stmh}Rt=VGrV^EN8#Ou4+jy4Ts%k+88aQ8%~@QcHF$0Mf<; z0zMxlJFCtl;jp2ARnoop*{S-4q)192+HC)L2G>3+O>r14pJ z*)p&S9~4tRba30ke8i(zZSo7>)Vn*3VhJ6xr(b*ju`pwy_WT`4rfbTrVm*MAov;BX zZj{~M{r-p3=xK864-m&#T8&=L8(zn(haSqTgYfd0d3L6KLy>{XTX!EV<=pg*6SFyN zySk3fNpZGK@Ar$S=}Q|@6r4`=vrPx91EosNd|F*>&Yoa*%Gz4lgNX`%SAwFKNU5ay zY(@DC-#HoHJu%3R)GLNAdTe%`k#C<-G@hoD&9ATQi(606n%GJ|!nL3+GvV%{zvCv% zTNK&=#c%A0icaWic7l!d)iIXttP4Ry)(Vm%@SL1>E{3Wish|-1v)}YkBn_+o(x2ESl4s3iI`L_cI%AO6py#UH#STN^ zrOvB_kq?r#s*`*=HxE_(M-DJuT1AOIJ*IzUaQt!O(ikXZz6TQf?BTxmD%ov+dKcF+ z)X5z=e`MvGQkCC!*1as3k_?CU_i|~kD*fJIP4JODLnjk`pO+9yzU7;@8+!H5h$xQogw^JXlIu~tOa=38wsr) z51K)1GWlya42u?#c6E$G(!pluzYy6-cz>_||l!@?Ee9Q;q^| zS*+_$#HRXOZ6^5IHTjO8B>5y$mvxzJbn@_q!nGUb+gx;@NM~a zNXiJWpqukb)4X~Nqbz#U--WYer0k!-U*3+UDBE<>*_oORmD6LbqE-di3CaZ&HKf*E zU;GeGJc1EnPX};&NH|+9&2T^Tq-=&;eq7`Duv-wpD1XXLfB6^zh;8sdP8UI4@J-5x zVikgfpK$z>sVb+7+Mi$~3=A$$I38w~_(*JlorWKGgNecf{5qFI(>Enxp*4w{L(bPe z2qF{9CQ%q)F;negPU-LMeUI>i3$KLj^O~D6A;C#UB%tpO)3=8mFvC72W2TeGNrwQv z@|-@jH5pID_mk?Al^M-jdx4eKGY&C7&f3|Wvi5*x2_xZ&0{-=KC>K#1&;+=f^D7`} zkT3@$H2^KKL3&Tn9~u9)D!>z4KR#|Kbthl~iPJw?&P%;+vSbtc03kJ7kJGOLY?K^8 zXP*?w?zY$>E}0;q6G}7Oy!1jUuu;kZ3Swnrd6s#b(nc8m93}yO46sJcfSIrE$U{m> zh>d$S5;s31TCEPJv3JHUF#egy1v@|95pcDY-ZnJ3#%&d%nI^FzWs z%-u{57N$S{GSX!=Nv1?aH%PwsNWV*mbqgcgIX)aO?|syE)A659WKUBi%Rv7`csMrC zf%BYBkiL!t!k8RJ8Q%WAqrLqQOkwErEkkZ>ttKujZ8pwInk8MT^4|4JIkH)2V~?)()4`qzuJ2j`vu>T1}_ zIL&68TrDx3j#;hViK1cgg*n!}s!T@bEpu8crMjRuKOeU-GbegxCoQ0xcAEkT8-P~y zU`6IkgG?$B2P5rm%oFMq)TLjg{cs``6&B`@04o$Qs&*#V)dhTo1OcT6OC@gi6Z2C% z=RNE*W*Q-Ugi$adT4%(}vG43B2%40<5I-!lS3lgABIQ;&tw=gsXCC4!s-Hq<7$Tt! zqWyNzlkG%&t^E0te|gBsWQ~XNz_}FlI+N1cF!Gd{B&^5wYW!3ehSp`Aw5SGPAuJbZ zS?vrd2xRuFGu+6O-4)BT8Bh3KUg}H!wys&C{dr+fM@K2A!)(#C4K{{G6H5yxC$mK*MJt5@t^V-Ye;ED09$V$lfTXwRRa0uu-zc$p z3$<#azmxJqh^#dy1wNIxe~R!Fgw^o)?$GFhDJ7StoUaCPCBHFvKztuvjiO<)IL_pg zH|yd-eq=^&w>~Z+9IC)tAJ5xm6ra(wj#LBv;_N{ zJjpyP2t5eT(xx?rRM^BR_?RfEUlLn*5*a-9fN4=#wql%h5TxG|LG*A1i4ZIo?968RC!P0%=iQ3?)SWtaG zNpKv$!;HyR*WHb`&tudX>Y+&dr(&Y%vMej5V;W4fF#;-nS$2!scZbl|+v@>WIl!yM z{5ax#LjNZ64zxERk<&mjOzwYoK`) zRaK(@FWZ(r+yC1mk&V8*-J^MEgin2b8#9mZ1v~j(aB4v7I0h)peK=cWBsl;v34E|2 z>LZp-La8Zinvsq{BvB4o@8V_nGtwHcjPE!eb{1~|C14{33N?WL0!v`);SE>UKnXT_ z*P?6-fkDj9NEC9;+05U7VG;<2u-&w#gFcyg4X1{Rx#C6`i8zxE{f#hA!h+RL6^P3U zYpQ3uT`fUGVxT+VafYg4J5v>|(m$L>XVfSO8OotCnhysO;P7rSn9gxn*uk+AX@_xm z!DM*HV!AmUg8o3%OcC@jsK=L8p36wYzG!sRJ9Sp;XZiQtp&CuaA2O~Iu!?nh0 zzR{sTM7VAefFPLCh-vV;H1=O)%ae^#!fF0KBer5!IW&o+GvP44fKCcr4-E9xR(BI0 zv<1(|+6}kqmWxD7StQ@IOIpdEZ$K~{$!#<>t}&}IK8sx8DHZ&Vl&c$y(aay`_HtRd z>l-=5IX{UXVed)Xw(iSya%L3HQ4sA~S6)|7y_Wel^~dW(^{%|^j|RPmTeoU76i9c; z8cPO=?%Vr%wXV0FW-M`C-*o_D4VzoDmyQH^UwUe$f8{xk>RNc$YVsq#sa1T?9iAIbC{ zO&s%LM=lq&6E-$%dKiE1!AQ8-wKEic8FhqKT;Jy56HC zJJg7O>J$kOFsrhF;!X+x;&RJ0dTacH2K`xyPvgy_Zo8reW2lQFVzWc~&nkYKn);ZV zFjin-k&9g|Z}8*wY$>ZuE8Izji@Yd;@L56vckHm#XKK?zHbW^rj#z&CTI11qVf6cVjQxnSs=!LaiG<8y>G?^+ZL<$C z671^el)FU|#`E0>%x7v}qn6VI($`<=_5ao%`gfwxlqobY)=IQy;iNBshmnS1SkML% zA5V&zIzhP)j3KeQq~8b~q*Jb=qsE5lFEc2o2b3V3d_maAkyU{bMzG(?TZgJLK6+iT zd0eRV=`}8gi96;Gq<(bib_6NOKZTfeB4@G9B~b~K28O(qH?_wHXZ|Ti;S@Z7)b;*r zToc+aZsRS@T}!1*8`}Xn4PgH%4H+dR<*LLPBfE9dfZaz;TisY+{9;`@yNqYK_~#nn zwKg%5O~P$?c8va5dUSzENW7*V>uazyaaz>w&WeiWkof}W;CAKi12JKKU<69U*EoJJ zJBz=3^EI0??<%;~JyJ&wM;-JC!cL zP^E&%m&g+fneSBftbFk9%88gFEmboUl_>4|58ZwN_poX%%r5h30jI5q_uTStKB*|` zH#dgdxkCGdn~mq)Hct8p5tEm;*SC@6=T~dxYbh-Pegb-xD!u-47VOp0_zJQ4A%ONh za5Zr%n(Rz@6q>08bLDEn=PBnN(wFEn6^EOXnKF0kRRyH?|89V*oA1gOu-Dt05WrOy zL3|SVoV3?)?HjvB(iI+dV@`p=@gB6t5Yph!V@I#GmAWiqrpNF-l}m{IMf&eVMHoh4 z!s>OUSgiKKTCY0GjOnd5|#Vnvv^@!A<7va!O754WsYKZ zpg;{)L>eGH5q8s!_211u|E@^&|F3j13VMzNf1qVo3jni1zN{W~D7v4^nUtBrAn@A9 z_1@(5T_g!A;df#W%sP$ZC@Us%>d&qfyZsueL=M-+87<bp%qVq>= z7F8o|Zdmpvt;*x~Tkd^?CNr9-E#uD;$*_PX<8+1XE03o+avnj59$jhm9&ZXj>)USW zBwJm<*?aYA!uDjnPnq3(BSb)~BJAJBp!oBuUYTV9mv)|xMWMm*8`kVvCdD4tRq3a* zsiVz7SSMfn&Q})Z=KRZCOkD@Wy+=(xam^RR1oPvR;XCEokq&kSb6piSvqKK^f%h;s z3Jv0W=#Gwqhf%sk)7Q{k{0~&+WxVW{2}54)vXE@s(WPIf6U=)a4_11b`pgmM!~>df=N5%ys7a=;B^068}T(sGb1 zkV15$Ed!5r43+)9ueqVg)>r}ImSsxvA|}L5E2YSk!~Al0+%1G0K}kpZtA>EwG%ujC zb)Y|;B|c>UG04+6{U3)>pC^&qYs< zmb+VzXcy#4ZCc-7l@H)7RSCa=)kf*&>v3M#+uOIbuCf^~Omz{1hy7sS5GLOrW8fXA za+nr4$$a~-V;ev#dWS+el)>?7y!N&6Yec9GN-38VayM-j4B20&U~@a}ydbt__&}Ky zr!QBj9g;$a)l*c7VrJ@2ovL!l8(YlPs52Vxn^anxttg>vFi<5tktcYoH% z*n_xbhTFgAJsu49thd0wTrmWKo+K8QgYRDrD)k9OIK+mA{|*q=$hXTVqo86B-xO z)-9F?5MaWl?rv$fz>(7NxRF;XQq8o^^{TZsg}1BpdU|uC6u9N=UZq=9XP<+XD#z4U z$DM+-(Tr3FM9-7~i~E7uS5CLior)5Ll@U`|{xCC8ElOK-0>5Tl`>4%q(dob;eCO{^ z6L`3ROTYu|JUSd3q&I(+^80RH#7mzff1l*RS`3Z5>jOS>0KGgUYJ-nG{-BH^+URWSaXaL3vDu3Rh<>Vc?o&JW1zW~^S)U~@t zR}xIL`_me}4vPr~UeZQrdWgYC;3d0*nYQ_~T?(fQbYlfwzj9Ojc@5m7+HTgBzhpX~ z_Emt!VQY-HyOQwj0Ai!V&oxoiz*es7xi5};cNk|*({xqW6`c!$bkVa*J}i`Yxfm%ixBuf_w??-W`j1@zU-Ps zpS1$ zT85R|Ev;nO)WIh)c{&Bhg?=ab7bQVkmws#|#7zV6Sb1lItOozZ8@aZZC{d=Ot}Bl* z06Xh6J;q_W@@$yEt(NX5dDUbGV3uxRk2fesS+(``^StvfHx&&&zWArH0EY9tpQ>3! zgh*UnO4^y*4B5%QUFBPjVE5Q8?Ol692(3JJ+DSJjObH*OTDtTt8RSl)gOmiG=E?Phm7^6%8XZOB#ZZcj$fZU z2KRuF8|P)aP_DG&2lYF_`s6O~Rt< zm+Ab{KW?|8$en<;56(iFx3s>Ia$4Zw20dp|rI*Z3%BZD`#jWde`Y9okDFh)kq+HfZf^1h)&v<>#sKL;g?emG5cxx`eMF>(IeC*!Gh)Xk$1hC3P_OQg+R86; zWw?YE6#^nKM{thayhKNU5bZT#8d?*^ z#QP$vUXg+}o!X0P?p@%4B$`xMx9dtfVcNVF{5;yhjuyX# z|2v!e%g>R>01DJrdr=Y^C=O?3_ImQ}R#7}SWnh=={J@%p2M%vFCBw~CuIL8S7GKyV z4iHs^%sWhfQFEYK5sPwJW^fH>My?lo6M)lD%WqIwtrSFE3#46jn0fFLkbqvtDJd!q z(aYUE-cJDJSzroF=&13%p=`IMOfHwV?NHp#x@CXbPSBzY$G7FUa1I&I-!E;3&j2a= zRm^13ys?W9{xk^xGeFXY1lXq+kOo9^UX^e1*qxayFm9M?IPBtM2(NuCIjj7a6i=~9 zz?$dkkGQ5-?AcQ%s<=rcO{j#{OXvS4Sc<`^tb-)7491^VExKQ zDQ3*nmzU+KL2G7jVN^cT?{E)h6oC8C12=xpG|MQBO0TB~a)F29c%m+V=%#@HX;jUU zOfVG@*`@nb>#_C4TNoU}K#_ITJ+Nfzoiv`Co<*4F;LT>OA$;eO1r#Vd~~RI@sNw;a4bAzBRu2d2K$bUvyWfMKQ+TeM0Hh zc$mh9_=LZ6c`iF%n!^k z?yfUEYzL_69fYsvRMnNPa9Nz*bIdA{6gamYWnNAK#*l{uf zXaR&huY5ZrfIF#=2|1-F455yb2TK;Ahg)D$EmEOFj#50B%VR`~I7e&e zTQ%bv?zdgifmb!3vExoh=JL#3TJ-vD7?^JPM&{f6t><8}t$_(_Unm}J{nsREbbVOk#*eP%{V%y|{YaC;;~JfLE2z)dq@C3K9tq`;I= z6T5332t1-($DirQWN)KfgYFP^!#>@FOCK|>jZT#eu--3$Rf>el;mR5Z96jtgmVav_ z^OYecbxF*+$F}@jdnWm_pZeDYR>4}-uM$>$>_u<=y3gG)(Z>7=w>8ENj7tJ=V!@gkNPc^b^de!+6u{h*DxBXFAbd-Yn9oqd@g z?4%6t;r&kTnul}g5}>&(Cs+n+Jcx8^9R*ZydAHI^3&)vd3LkJk!~yxj`?iAD6^G+a zLF<$6`%k7-9tPxN3<87Oj>r7zO9Rxf?vGh?wY zmYT_#GF(q~YTS?~9z=III-3#U#ADuhu3*~QAC`we=!O64_2U9_HIS_QR#+C$-y97+ zzOBO{pFF`0&OaVANW{7Ju#`K_N_&QDTnAd5r1hY`D zI(*n+B-$;D#A_5*?)z?LlCtC&Q) ztVFoUygTg-PN=+f4XN?TJM}mg6s3_^4YKQe=O>zv2F$P#dUOEnhal{|8u=_twQqa~ zxfAOQ<;{)q`S4uRZ{^9(h#Ksk0f(Jkw+@X357snQYIPuk16LybzyNH@f_|tkGYyzE zY2eayOD#J4zq!GGgN@=2o#=MHa+jpcmpxCm%5rBn1?vsf?TYS-T+^2me8!&=oens? zcHi;H+zB4x_9muUBr?&-lxqxio@hPhueIuzsj%12PSL6CLnYTZC?`sckLgxwUJ4yP zG=@PekH1Uja!BjRcKj*{I=!@`XT_E8wKvy7lLLsvN7(+j?l4szrTLLNf3 z6hPDpP*<;Vvs&wAmzN!<+vlGt>EL9$Kti%>yzGs-%TQ{x^oAite7?W{vmNqnEK?1{ z#UpIqu0E)zYf)jI!5LlO+B%-bX&>uh`u!X)`{RmZC&wkTS_nXetm+&xFH4VQGB! z+a4-k&89?u`Lt4+*7tO*s?kD4--5~-?$#%@3usJhXi?^tN&nQ!-9q1~fdUC&X5>`z zQjSQ!>@b{)<PSH+F}u9sa>{A$CcF0Ae%9M59@zqhKtbBRc2$}goH-L+;e47m zscxPiu=UPw~U>9NTO@4!BTQ%Ht2c4BlVKi4f_tmDtRhc+L`>f6bD~g?cr&^}bhR zkY}I^f1I|!oTp?+j}}B|@c0Km0hFn^2*vV29Vdpp+KFy2Ot5ad)Z5Jog%I#ac^EzK z_xK!WD0{nJFb{%ZhoQ<6X{ccOAuilR$CBmD_zVOy%YckN;IYecS#DR^@?Iv`;1*-Y z(!7`Gyjtibs)fwkPfh&e;C{POq?b0GQIbovP95BkQ^Gku!bsh6AAjN{4k#htklZM#vb{lAGeegQa$PPT;mS$<0ykOiCSz@$D&2WsnRCpP>26+- zIQA=7mtKclc11?x=N}=2vS)sq%2B_|@F5;#ej>y}6NhQsIvv0dL_*W}c}H()U;BSB z75UX~GJ&j*Mz`jaCF|BZ-) zr|J!U7#HoFX9wZEY!Z(9OtjT$3>*t(wy}yygeZ>dF8i`K(z?5+b8>xsy1!UJ2cgaH zf(UPJ-FPQ-KSX=Y?qb}JM`r+mLdAUc2EViwXGT<5rE`qHI@!p*{~`naw7*|s8H`SD zuQNu^zd3bt=@syI`9v@L<-j!4vHa;;5q#$)=&^#VPj_WT&k2tKmJydlKW$)=QF8cB zva1=2x^2&hqn}>v=>Dpn?CAEl}2dA<$+U3*x2irJ&ItQ2nNrnLywZ@-GQAV&Uk%uSnwLHeA5#YZL`XN;P4aP z)D_BlEh|MwqoU}>7WTjrl z$Bwl%;^;XlBbCjMT?)c+K7Wju@-+Z0G8K3WM&asFVZ+H6Ia0uUkBYnI|( zQj6+S4`?i1lme6?s7p3}$VZaxJpHp)8(^nf`1yhs-_DdJ&~W_1Yu01@j6UVoC2FD2 z!`d;p@8B{LHYBh3PgY>vIuL_6DLF(cf zJCkbLGg`Bbu;btyU2wt0-J3F=&*s+nUzZ;%9nq!;idNWYb6zlwW465u`LFwwi&ONb z80GY3VfAFX^Rbe)T}8yO(#TuA#e^{MCET?*<3Ty7G#s5tU;VfewmF@G)#+zTQZOau zheEBFrulFPShCfI%IACTbApcMwK!jCS6Fk`cp_EG%~I!zG=%`bw%GGF!b|PdAI$(YXbvzHOc%zW2z(#XTlMb+T~wcn;NW&m>S zLMGQ96+7xcCa1Zk*2FNpfq?g!X}MAb-M+PO*PoS>qL}5K(R82lBbm203+rz$2{=nC zalxISV;`5P)a?bDm@Yiz^k4hbcv4YxM&^DJ35&i`9@TV->ZiE~`P-l?dPhLJd79?T zB$kd6bwFsl1PWK=mc^PD%R_#Zq@7oaut5?|jsm3?0+<#}L;LTz`a89}TR0omluy`|(`%^7szIb`n=Dp!Z;x=YSQrC99N;24x!!C^P{iu(*PL@9>FLL<{ zY*U-c&|F|o*~>`rm<|!9oNgi#acxQ$hTh~Ve{d*u=L}RbAT%}SJ)!mPG zvY(F|Q=;#ibNE5(i>)|DNg7}*#?awUs zsUw0xOAgbYb&WUD{12ZXA2Uk5UA$V|_m1qtE#;8n&GSjb>IkO#t63()3qOKp+nB-I zP@p37D;e#;1uKGcfP|2jAq{a^sZ(-?F|g`!_znK=Ze((h_1Niy8@`YleCS>`fR(!D zb~w;J&*9gc643c=&BKg|TGJKul=g&E$~7xl#;edt6)S5v?vlOMc>8i^`x-0N?(y#Iv=c)yDa~g!4xnf~B;(wZ33A&1MULut zA?{g^6L*5#{P4Z2?op8s_5(3tp1|51_u(9kBc&I#FKG}A9MW$hF9*slcSK`^CvK&4 z0f1%)hgS*=tku5u?n&(3GcsR)r$H|9%iN>cF#j9XHPnp^QY%+TdlZ_dE7}*h`z1_8 zt`uGc$u*%530>pHzJG}fadiHNvG8N0$a%$7-7ScmA)Hhpdwrj3L5yVfJPsQaN|zOz za6mq{u0s1!0mvekE#nSWvbX@+q4Byp82h54xAA$%Oqzf6d{6aW?Lj-+EC35{QKB+v zIH(4eU;4?S!$Pf1+<3(SDOl!1{1E`J`D)<5s5Y}xzTGb&zu|B(9iz8o;xZ#R>65T8 zAMPes{9Qa=TZ$B1=?z7=&V@l^?9-!vPtGdUr6mq9qZ8dC>_fpPj2zQ_^10>?Fh5bcnz>+5<#-(~ul1Yxh~$5} z=t&IZ57O_80gO;t2Wtww?NYjMlaE4--5G@iWj(>7V=Xh4WiUQv7QyLumzBfMBdRi3 zD~8$PXdc{iMh|QjG>NP0({ga!Pj!iawDGtv(`}ZU3%RC}E{uVPk1ySLU=qtFW*evQ zO7_O@7pPi=Z#_TdRXC%|bBRj#y33YwX`Z&wBI%(iMYv0p;_Oyooj{?4dxpSxyj{Mj zv#{p%%N9>gPDXsF@9=J1|BY|WV`=5ckPb26rhGv{ZNV*+j8=9hz@{ti{(~F*R)BFv z=10Hd_TjO=yfN2MC$rx~$sumc9eGozdHsy|14D;s4W(lBY7X%{e_>15jtH>c2)?%Sw@h9jLgi)=)_#XI>029i z69oNR^DDiC&Ur9Gs@=T%o7-ZKK!R4tiT^doP#^X!WQxM-8#A^9QpO)w0_xP)JWL)_ ztwF0NqL~0A@A~EhiF?F?&;>Ogy7BOK9PZ7K~YmH~rW4~fKHOjirI`WEagEGtgA z5bQ(iU)d4GvE@AEcZ<&7vL|6tqLllT{m0zLQE{OF!g+VfJ3Bjz44XyIiI;fCJ2}in z>{T;3buu@?f_!bs*1R@jPNf#szX~+I;rlag`29*wHNfSI%GfnE5M*XW_#1*rl%L4=q&DOize(KqZ*Bti%OTKb{%Eg$9%6JsUhjhw1`QinJ=Id~oQMT8B`( z&c%KVEtnRb%5_?;Mn0PDvX}ZP2)V`R(IUMwZ12rqvpvDs0Rle}_aye7(9dQy#=Lm~ zm7?Af$xX3L&f-h_6BGG2I3nsraWUPg86E({C)MZ&T(4i~R%7OZG6UZIxFdF#UiEKq z>xU-+;Wj;s$rfvIlhBq60%NAy+HVWdz0%uys&%6o^P)Zz3TU^;V2BVxz~R%hcvo(y zY+Om-%;sxIx%sEkUzqf7NQ-?D{pH9Dj8S-w@ZoQg5eMJICzUfdDA)~J?`yqa7&6c$X}zVbrI&Ja0NoK z2Xc`-Q2e|j30us1n&O|>kGW=!2YNtjH)Y@TlWW%e&L#PYX};qT6Fe#?_ON9Sj{f}1 z1E*;_gFBnbdg z{XLn6%l|p~@l}?-2In+tAMYYX7LP~iaV=3rqR9gi{z{hU0><((dJCSDP+@`=Z@z&M zDm2V9uB=ZeLzBhhqjJbECmpp;5yW@CaiKmhxH6(P|2GWP(A^7=m*A@S57F!o;OxDk z5>@qnTd>HA4z<;ja6=u{X+sWecn$gzODw+|`xD{K+g7A835%XdOUS{)v32^{0r z6W>L;{_XK;GojKUI{UM)^En^qJ;sgBdl9*w_Z6^%(fG^_7YeRn)L+ivu)7Z^>6iNR0Zvr?B{0eB@l_UVYE&qw%O#ufQTlvs3vL7Bwzz8w*7Wkh$83cJgCd z;oNWEoN2SHn!}FKpKji4wCMhVb>4%R1<`sh1;f;D2pVsv0mu*R^&N_hgBmVbZ|6vY zpk6UILz=>RirWl8Oj@SrlN4$YCqJHW58Pv+I4cRu$j~;&a2X3K(BS8ScfSAG)l+oi z4v0)Tg(Q4w_S+C`Fza+-C4z~E%vDf=Zz$r;qJ+omTJ)F!Ar=n6%O(;oORe5z5^o1w z;G9ux$le+$v6-7u@&nWy)YfHS`v-a@X2C^KH-+Ask*I|5l^smqfIWa0kmRgLK_O0i z|6Ym3Ikxd|gf*{R@TDKbYBd_h8H0r^{94++{3J$VgHRcfZim(ip})574kWr;#|~~2 zC8<(xYOWDpr}9km$W1ucKhPEgbB(NfII|yjpA2xJ6NjU)`F#ISxuz)EaQ5q-dUQVe zo0nh>Q7ms7{`Q0*@f*=!dcB$1-R^bITLJI@g8z`mfX_Tp3YW<^;&x|B3l0#26g=`H zd@CafiU1(noU$`wky^9UJ@qveVixwi-uru@R}p~Uolq9UuLbNYPB zBjb-k`!uWNzhHwn;rw9mOH=@_2vx$LsU$fqAA+ez%hatD`|p1^-3N8*{|YI zr0)6G^W1jJc_ENS+MZh#yC#85^i{x&893DdRo~eBZGel_yXDrhQRy&^r`8b^g*ivR z6UP^ZI3^5yDgTth1}WKyL0Z}PZRR4dOPSH~tWE(r5z=C-jI#Ryx>CE<%QNwf$Jw?; zBn*iNu9qT14DeadE@1p6E zIqchcI4IayY>6DVRX#)r<~eyxr17Y;!AD>HB`^C=wtLR4Pz3vVmj3cbb_4MAtfQ#D zwtZ36*hFd_tPlGPH8XE-KVos;{`Kb6t+GmM##nS<<@1iQjc^~0$`Nz;7;~3(mGFtv zPO~TK-A;Ze;-==E#i&VDA(@)ex-RFN%ZjQ5$ZT)ra-V5Uglt{CIEsa zwF-m{kSH2KA^`1G_w#hJ#b$X!qo7pn!ZwD?!BM+;TJI@jv7m-hq(`>&CJ zK57>$8><7XqNXvQ;cXYtb8CA*_g0`-iCl>Uut=O0aFhK@{rfR@)Jxq3>-Qg#h|jA@ zL|hrljY?;tm-1h{1XM<7sk?o)e9`bpiz`5Bo;~Q`>i>?^(YgC9;rY(7f90sy9>Cf2 z3hcdhYJWopSilF_1r{>~!CnUt98HgCgHEnq=^rUHlDR?n`T1mC$T7XiFIwZ5XW!N@ zreuJqCPfreDkW{0ln9c+oNPM9H5cdzW=vfGZ45=kuPex;lZ~fvkG(3b#dUUe6T*~+@O59}N zgOM^>{TzCaTULos2ThqS`_#sX8`um1*Dt0m!mDFZ4mzr&&dDfOc|r>#E<;Kzx`tLvVC_FPRxeEAZ*fTdas|c5iltg;0j4@8fzS$0{8O>0b z%H)hs{s2S3b zm|bCz*?w5`mTc>sb)Z86>}~rB3J)ip!Q~}WmFmwoNzMYDpe1LDd2$-|1z=IEtk+gS zm2cfSZEJC*9-woM+*0I-F73!2dnWm0mYUBWm}x?jA6`Bo0yB9_L8z;=fhHHaOryD- zs1}5Sm6jzl_Sce~Ja?w6Fyz;4ctOKZXLsRh4O&&jffj%$%1(iyx%_{0U1dO&>(&KC z5fM;PQHcRTLTPm90YM2721N;J5dmT75*SiIB?ScO?yjL5>F(|rx@)NKnS1U%$8(O~ zzxf3-@B75sYp=ETExCo|ywh5)TUbrl382@#!>Trc@@9+i?%j*GlIVts3FPVyZoLu} z3!j}RwKjHa7JkR8bsQfcYepyTwc*UTUU>$4O}1T9;rm6_;0hMsuT7kt77k475`6~* zS;mEyVV?cfkpbriFbZBm*zx7war63XxB@oM@St{+d0v`_U%y_$O4kmn&i8H>zpZIn z7)*9?a>%aw5_|xo#>y19op2}(Ns2+b;YlJM{)rel1hq6^1 zygfs%OjK5efjF-tVAYvAX9+AmPtS@UR|%dw-YmvX!blSLIkIJzvB3y&C~j;Rhy2R8 ziSXl&p3^>e7pgzQ1IBC&+vQob)TmquJjKd4RE&y$8gJDZD+{*i12OzwW!^_$UcFA5 zeQ#rXx-{2y`vrm1(;It(7G8{ww6wP%`V+`~%ZbyyLL}d@>qOT<2D0lZ`Qb$E0aeFQ zpjNFrUpPL5VU(RNJ2I?wv-e?X2zM{(auI=ua1mpb_;mg!91N(}+p!9msiwDprh&^N ztjz48tH;F6&kc!mz#+LrmqgssxES@(pJc~Rv@*GeWVQdMWxV}JhPqO_&9imLDq0}L zF~3XWrND6DpM=DpAHKpx7(2?n?UZR-r5*i)_}E0APWSnG}(Ztao%T{LXmD zY4W74C<6$#Y zOZ%KGx$YZaStaG2s#H!2H@g&eZ5vb89#7&cw5L@0xE3{4*AxJU4SoIkrrz2bi4@M`FXJ#H^|v0#DVUD;Z;c=81ODk zS2oZ(VszUbzRA}MMxor7guNd$H10=55j21Q3#~d`e8uQAk&+Z?n_9~-n3h#B{2<)% z^sw)SCw=j(zcl5V@s)?ZpW0$T&eG2Q=Yt3@nZm)#K2=s>8>JLsF`IVexSJQl8;Eoo zv#YQ3OA%J@6%Et`v~P@1RBspQ)*-L2IriYqTz%N_Zrzi)<@-#EoFrqoiOYir52RoJ z1d2pb!Op^&CLKws%4+kb@)z6(wR|M=MehO;5nR*Rh{@1+$Z+S)VkEns0W#NcH@zIe z9`A^Dhb=zXA?347(bg&Rk!!$ch3x$fuO?GD-()Y}nO=+kIXPTx@JwO2X)JJDM$Pj- zHL*y~T_;WYdsiDhoE#SB#q>M6Lmn9f3HOo5iFdNfcFRcbeOi4OAv!x1s}PDv)?L=R z4O^-C!OD0jA>hK1LO`_~U}<15QfuZluqm z4qC}$ti(rnk@_*!^8=rndHEx?ivaBgOi zzDiUF%}R%EGyKPsnc0#B0Jc9jCuA zPLthEQ4L$Jb9V(4wg($lT|8g!O+h|jeq)1rio5nx68Yrt5;v9~83O`ClE+LoC8EfC z;q+fbAo%F`^NWKOo9kB`1SZdfSHv%(MSKFF0+vgG1w(bijNdmMrc1;2&ZG{?X6Rqw z)6Q|%$HSKH8hkztC=zv_WDcM9b)>r@m+%Y0?=6Ev0a<=96?qAMRm{mIX0egZcPC8l zYO9akz3>aZN3w>a>Fb{+at9ASdk-BTg)Go=j*j{ZL}uR3jE(y%L)@>4_Z@_fr$|rc z4a2v5K22;6mhszcOx7K-Eqm=1S^o@(teMzSC`<|5e3D-O+$JhJ2Mjve%exZvqCxkw znMx9iVS}ZzkUHZ#1?u4;ek4tynE|{~e^o(N&A``+zR@oo*3!FwsSDDtFD5V>*cHS# z?Ef-zPZc3mK~MGz;>DU%oaZHR;Iu$Zuq2R$gL(Dv!+#ws&f*NwIG82lszjNvu@WXH zQ|arU@{vbA=qHIN*u^xJ!b}ojOsK(29AuB(!c`NG$yfNC)3Z6;?Ywl4{5V;aaw?MJ zS!ENN_(<~UOs{&Ig{eSLm#KziG%F2u#3IJoc@Da|bra%i39)InYqiZ5DphchWlilFueh=Q)Zi3h7Ey zFo1jO-(x#dW1s=JSVVoZ>Z(JD_4=Btt9iuxTf?#H69Y{!QyFZeMcNu>IcqlP%8EHGLsYanP+`nF@?(fEk5>7C9ESQ1$jDYuDLQhI=jm5)FWaPK7Gx~ zi85>va^$=AJNh2sGw&Szlp!cDXyQY@k-we9e;~+N37ni)O%3gHy6mjKFuu;$Xqq+u;oPLvwivP*r7qVPk$9&q-3eO>> zws+!(RfdzlwR>Z<@X?U3&3D(}C?(~rljryomw@>4$dbE`Ps7qk?rxJotk+2o!7Pgh zj43JOH|DWnGC3UN>QK|mzbKJA5!f9%J$V?!8rS0y+pr&0sJ{v|8oeITSw6lx_+o0l zLt}DpB+Cfb+uI?=`=OJbchZXh47}bqAo}X)SNT{h16mKrYMu%H- znLxGo(~MR4o-9ta>>$2%-BpQrBN66J>CTNmAz&yI?znD$!<^;na9{b+TB#BE6X%6! z|HIUeQ&3oheOMaIiNjjP0H>lj9$aKPBaUSz4v7Z=BDKc4f8x$PY2HRn1l-8kEPMF! zeLKNSb=l=g;l|p!Jvkr#5k0^ch~HjT2tFBt0w+(t8_d5zEW`{0YF;vE;81R#2j!RC z=d9ZU!=i7GW|V%!MPQ^VIx~N{75+<;$k_qTJ4;AF`7g985=W*~=^!TPPAhhyA!%=# zvqC!9VNxOE&8o?z9-v~GK@EzWzdGnjNV9Pbcjv&q1NdIN?>tJ4&ty>T%_Y*f#YA4& zeE~62>~|9*xg|E%ne|;|qEmWHdIB}J)J0&9=FDNAm*Vf#5m+@eLJYFI?&cZBJsMIg zz4I~2ld7osZnno2rQCN?3LAp5pDKayb@U5k0x%%_U4NIW9#xRORfP54q5M;p?MWZM9=)>O1kOLF88`}{!9R;ix zH;?JlfsnkEG14Y>2)}J)pURxUJAy;8_VA8CC7DzlVbsm8GR45BXL;HQu=;kh?qgp> z-atqnTxX+n7p|etg-L*?={8(nit(<{Z^?;2j8@MSY=bJE#mKOoefa0q1w?8gz{_Cp zo}T!xql-xyPX%STt6fVd4Qk1bJG#EqV`I(W{c}t-4z5ywdd{{ z=)?$(&?o}g9Ftd7mGe0&7t{aPhKQxG*cM3HRJCN||8%GQryDEdB?5cAT2MaQ!dBWk zK}LtRtM|J7vAEg>IJ0K1SP1KP$Cnv~2D~)qGlkj1m$%LD?0r{Q2=|JpbvC-r4{5vl z`a+|`9LHyBer)a3Nvc!9iK#8VHy_A2)OEAOP`4dAuiyb2au-aA;981lf7cS|##irB z$C(ou-%#PVFe9)N^NU3Mzx;uS5m>ApZ4w!OaeQ*!_|36y`Kn)f_A^wLbv4*zKa6Z& zoXmfR@5H8*UB#+VF&cG6F^cH3YHxG!D;TCXhe${DRvy=mlv-fG&DLbN9eU{9YDV}R zy&Xo>2=18VO+~Oe^nN=Y+B`_GoS(OweWq4w{Zu4be@l>u<`&V7r_n>#02V#%GR#sV zXZx$y0ltzxKF5HZ1|fllJ-Ax;voK3y4q*h&nB(wy>CSe-YWHp4@P!r3W{MUg&9l5slE2H>UlMR+plzZC0(|ja{ zh^&213tdg1{pE{ve#YmwT$`PdH2u1g*cO&2o_n7kN$q_x7I0qX3Ssx}c3!_Yc^w)L z$bmxOfUzy7XL)I}2_HoNk{=D_>PV{^HM*!J=jwPl z6KOD+zwqLFCyA0pvW2^?Cd+&1%u4RmQgWq9^MTbeNRtDKFU#Q<4G&(O67HsWzTayZ z1wP%D{Kx7Eo^C(Y#uZV5c3n3SzexT5CwsUn$ApW|FyrP8ayaF_;=d_0S{07-hN1MD zKW{&h+7`BXMn8-4)=s?4M>g;JV`cQpyI#2eh}Ez>#PY(D%GpXV->RQHyP@moo^cCG zxcM91(CK0TCS87j;)$au#7~7vCDHqL*Yj05`q!&PP0#+io}ankP!9>%56TU|F45P2 zI&NnAaq4;x^3G);?&==!ZtN}>DoT01cD>^KmJA%hVk>3SsE<71)7c4upJi(~?vM>XZYSRzQcRZCXgrK%GxKR{_P5U#GIXUJ(3mSV z)9Pc(7UzGxx)c9zPm2itB}S*{iLI@z8e$zJf*(&RKV03h#OBb4YW+ z$2{B+Y$l6uyl1Xvp+>wC7u4cSPMi7{Cor?O^gSuLj$FLHpjw$FNY20`N)GFF)br&( zdOx((8Qhn%`a9!UqzK`t)_}vtFRZ)syetk8!8SRIMOfS72t#QkdA}D?o`&gh#9vBc!V!l1&0UbCd#nuZB`E4W zUnq*Z5GfahXrKb9p3{7h5&Sy=RY&XW zmLRQmQw$9TG5{EpWI!g=Opd#YeE=%gpH$X>4pTp{!4-3Qq*gqQM&nzp3|>8A`O;Gu z+hy{YrIk~zv52YuJg15;J41p91tyWTSNT1K+F;2l2xQPE;oJS;QBrJ?OflSj0rwQu zw&%$;Tw~SyEj_bu(;Gwg%W?O=UG(&BX9d!3JtZf~N-@6WTNr}~PWAS&YEaFbN#+IZ zp#lN!0kM#XyeU=Rh@Po~6kl7J)qJhUmi|5X3H_N~-V70PnE!-+ZU?cu7>w!F8k@H& z(;8YD%3W<~e*GJ@ofl3ABWvrk;lHjT8a!`VP0(#H8Y{7Mpo|c(HUo*E<~Cl&*O5!) zuiS~LrXh=-j7ynsic7j0(r`bEv-E$r0-FxkpLtOKw(yziCWf zaTX<>)$Xyclv^tHq5$dfbV~B{WGc`4GH-|RzWohrq zC9*Y3?r62d$i9rgpde^kTKHBAH0#wNqZIo}$FLg)<%kCNwC+i?*OPLS){y?x$}-gb zFTXk2ENP>aqe?mhGX7Uw0^jppXF$HzmorANY4oSI5_B7n7Ih)UL-`V5P&rygXT6Ar zZ{9Vfyv*`m5*9v%I#s|RS?WF0H(-}l(V`)k)_|LBMUy|Fm}p|NCAs%V6=YzDo-2RL ziYwm;I@osSu~2hL12`HkHZ^yyts{_69iK$s#OGb;RGf4EUlxFK(t}v9vh?&;t?diy30u8S z?erZg82DFknmW3oue6R0exz8^>E+7fEi*czioI+Lec`d1F6N=LCqdO8Llz_!vg-_` zHwgIl?j4i-L{JK3K0kqYID|>tXaqe1oUpLKUm3_hkWX(U7CCmv2K}|#I+O8vb9@TE z7O5hhe19?Nee1G1LekDDn$vZ`S>j}2pLUAuR`eLygvVYVVqT-CU-`pyS~)M<8*jRJ z=`^o$=!>c4ce&eYje!bW$c%oNqtKQ`o|JEuDbKR;$0R$e8`8~I3Z`ER?Pc~{HQ%|t zoczCy_Sbiy!8?Dg>O@ytcsH|(R$2}JPNWD2yX(5Q%#WUGah&$mXkwiuPPo5{&~neP zoa}A$=0&;{;T2L#L!THSv*B28%fN3+g_uCQ^V=RJR+sfqr^-pU5$LE@l&sos)PZhf zddfv#SpLNO;KMU#5f75pI4O)CeHW2)-PEjrY{M3#g+xv+6~7ge8?C|RyK=Aah{)M? zPC<)X!QXSpinGN*7{RA{F%L?cp54};0Uyr6R{H#A=xplY9G~zK(Be`MS6k+08R6eu z^yHg^>QbyK7xFVb_;1wApK_4@eRxQT+uj!~5qLO#k;CI$NJLAHjsc_@A+*zA`@`cT zPH06qUn_#~)ciT>Oiny1kXzSr=XU=T_l~s60}nMB%Mp*}U!Uk7pWUv4(pjtQS5SUW z3@6|a+i;p0Dl!dFDLW8?a8znbxTye+9SE)-TfCLME(AG0Xbo!1cl8<0pG7z?rmGfr zBf$PDT>^nToT~l91ms0OdcI|7=MY&o*9hio39JtKgdVpyRP##e`HVrKS%Mg__6kH{dbgzTbOeK-MSrihe;%G&wFwwlISp3)V@IR!#3ND?9 zko3R5>?$YRlQF=!j_s`q#6}+ypWg6E1MZwmpyi8E+NH$L*6aG=d3CAs{V9-eex9fX zQ>p6b>X}TwdGa+>?RU)^5(#Udj7~(_ZIu$)F#s;iKVUR(%kE4wiWkNk@s(8j|Ww+-&6 zCmW$+R4DnVy}&rqz1kc(@rX`Fq};^P5Z5jf(JmsQq;;qs5V#$Usj^E+Y}>Osy?WpJ z_+R{6vhYXpP4qb7yLkiNvsX9pNk0k(yC&NvChIM@CX>y-g17YS&?Y%9eS&pTFDVJ2 z^CCW?UHMmB_gVvXnB(BH{nV?;Di8&aJuO*CjOs5o)Bh2^#~`Olc}|z^?>yk$&eZf) z;yVvJef5Ck(Mb2F>_B3fx3s`&(kJ(d29ksva>h`*Gxmyu*tF#2ji{&`?FQ)5!sqq# zcsHCnA7)R*Nb@RHo;|$M zJ$zf-#49&L-d&KnD{GzorDSSP)GpOhb>a7+Two*p;((yi8FZh?IaNxeLil-DrOWfA z%Nv=GRDMrm`4?RKKtw|95Z1PDL3lE8ZfDr!M7#t1Zoiy^JWY_J~7;bIb~ z%`mal%dO=k3JP&&(XPRWJgfe!-<)HAoMyWcPTLQqgf!O}nBBH{t$YaPRIN~~JFfgA zA#sjDDN*s@B_w(a7#3Ef%OsQg)S}|TdmWjimmWyHZ_sK%!G9MxB7(bvx%}VL;=e%E z5>E-uiCfoqV@WyoRQ`}%Ik#>Xw8z06*iHpRbi2pmug<3|jC@lIoOU5c42koRH;eM^ zev=Q@Nt3oq>#%ATwOjVs%a37O?oD8y&zDa1KuEy`eG8JPhf{YUKer^NwqNb9@)8QC zWGPAg>BanKhr*UtbHS(+cfmG2+*~lc^085im1cgD7h{iDyX(DlMUHwfck3aT6c*o}d7heZ3l`fw5 zZ9&qtCE?v39*5(DUKB>}B6++&CfoBB$`Co-PIbQ1*kHQ4pwJ;b z+#&t4LpsbtbOI$iBIgV9KhE)nR;b?=th7_SLANw?YIu9^H?Z!HxB8Q@itpBQUD^uD z?T639*QHW*cesI2d$`u;lUNw6dgNYp&L`VsIyY2)o>?GmVTDqn zL%m900b|o5w_#lP?;y{tM6`~>hwguuKazJf$y5Aq)@f>6W;eQ#`?K0T-eK&O36S^Y z+mTCz&jvaWB+xqF_ZFNWMy|}Ur(xqC3 zU%2vLFPkUP4uqO)4BR{cA%!{H4^g_!-{hlK!#h&8zK4*-QrhNA3^nV^&yn95;=e65 zpS4@db)u{hLyCSQgo(dwDRAKdFy9(d=`7uaZ&&9Gn|AgOf2w%>@5{5%7XZ8M8TwyO zvHvV6$$M4jS(!AaJUum4Ti*(pp*WL>Bjke}lq5VxjUxGg5s7;w#U zNStC`uaG~G+k>k4xk41bp||R5hG$Ay;7i_n@&EqDii?_T_3bCo5P<>h7D_Syiip*z zW0LJBC(VcS=ug{HQ@0E&r78v^gL>QtYD|Y5lErRY_SnDq=+CCpm|+|=L?Z0>!ssOR z-^Y-jFz)%zg^p*T|AaPvk~E0wuUjTBJk5B;LWndKd?cju#>nqmD!(^E(70xq#1L=|Ky?t0%P-hWj^v2e?une7DUvJHj;5y ziUJiQtFj|zhhp57fwabGBR@fRq=fpB5T*5po{{SBi`*(+{d-;f@tgFN@IYm;a?4 zu4RhTK_g4%xXd>50%f7^zZUR+EcI@z&^f~U&EFP2R=*{VH|27JysPNo2FimZg_N%u zWrWBW#bopEXqk^h&byk;vedE#vyS|Tg9mECZ<_^mwLb}2B}J@^EPVG&%YW>%jZP7R zXc_JPrgHw{r!leNw*J&~sBdq|rrg6XM+;|l@KK>nd>BLdzMgzSsk1M&%(LhoJ_~W& za_@qqN#8d28u1a58CZ&@TpF^%h?59aFeR~?4R%3;H2{cEQv5p=i(Phdyv_=4VgC^1 zhH~PjA3PzV@DA#A96v5Jo=`t7WF|ee%1KK!D>`^R;{?o|6ZCe?MHho-xtk)b6e>em zmK^sp)n4E4Qp6>SklfLSl*<5YynW$2G$c#@eGUgDxBZLxlS0GABVCPB>zMtq%-GnP zO7w3~?SJp7lPguK#Pf#D&CRKnReWLD)g8pI+YPECw}n79Nr2z7c8v4_2`s86URrPZ3 zxDE9ev-Z_0MV7R1#~IbDvn(n?ffVKK~sCW$@pTRQbp?^D@Il%XY{u{C}thhYkLl8t5$5BXbh33dfo zEu|tlEjJ0tD?5#_u_D9fS}Z9MdyN?|OXei%St*_2ZW6wRhEdcI*NM*J)0r=Vb;uV4 zR{A=_BUXFbIw(pE5mJOa_oWnQ_E}qxf7G1@;dyH-AQ5o#0x9(hfb0RubXuqQSVeOp zaBA>dF3rM#CxGD&7;E1x1ccT`plf9WaJzaEw$cGH-9`Yq8AT!YQr;K7{dsA>Q;f8j zTF4fg((uXveoYX#{?>pD+Z2SVnSgL@3y>=!_3{C;G9r^ZipU0tnMbjDP+9)P_zz1! z?`;aiUqvb<7AduMuDuy5JitgVY`xPZ!SiMPX-*LeKqny#I*#PjSZ{2W=a36Fd4hQoiTT-KHi?U@^R12Hg1e#PI%t@oLwiS(__H%4KMi< zzCdQ8qilX<*#{4H^heM{T+6;C0Q@n>k(j5Qa|B_8dfKtO2HCHMg@a|$>k!uhXM;y4to<4o5 zAmHM?X}jIVGxkD)YK}oR96b@hl7ROB*u;VhML2BI6z)ChdpY^NR|dJe)aOu(2W6%N z#wz9Zapb-lR^{|Ag5P%?&t+*dlv~$FV8)AkH2Fnb?n8Sf8k>&3{gvo@$0%dC)dE!ztMnkO3g5TzS1%eTDQ%=frV~YnZCRp z`x?PI+Ullb)K(v_GFQXK1X)#Avnqb!YQ>M=`!5bfPo>T{Na?{- zzLQQLOH@x*Mvrfw4&M%0Ki^GE9F=(*WKT?`dDY6vBzz~h-xnbJ1LqzwmDN!KcuMNDpmI&LWlv8G$gEe-bFBJmOlBch1!xLdZQPsf- zHL7>poM|}1!RSVQ1R_oWpiA@?&s=}}NQdxW7w|>=D=d)q2AX8p-jG!{AXS1XJ!nJ%38W`6KZM1sIcsO)qg?dcNoUR)`WOm>jDU&bO z&NYk(IT^`OhA2R+v|_1_bcK55)&A=E{P#c82;<$$Nj+-M4GNh&M8k>=JjO_H*AB~$ z?}{MIh$`59ts-!Ngu8GCyv3svU8?F` ztP7j54TQCg80+Dj0qI>s)EaRZQ0CoRer2)T5M*$N(Iss4ZdpOWTKbVu&HDNW25%vSRcwuS_YCJ3Yfi8yxNT`FZCeZzrxaFN4&0* zr}-u?&Q9WYqfe#79E*}~u&L%mnDuWuAA~py>|twnm0wIzZ05uJY|76gD=8tDBf~Rl;!2uaKIuZF znj{-x7$6MdpLQ0FfGFH5DZ(n$SWJXf_Lv%2g9LzSlxi3ZQdz+UWtepH%RUtbIW#lp zHTa)Ib6a3zcj4L+ldNmmFP$7eo&(D7h6 z`rJ)0R>QtuYF{s}b(5-E9s*+67mw=q@!@n;@-!P2)7;o8LF=TC&m^cUudCL5so;fr zozt!hxBx=hrz+WRNzm#y`QIZ6!|&W*>PtJ3I>suZ2&gRN?k)g^71MzWWtBtun}>vFcU%Qi#sD>nOq|Js!GH@tx6I zJ4-22YUX|lci8xsenjC~*<&LY(GQFH)83Q)KhgjSWq|s7!&0GhC2m;Z@Ms&=%MYk@pc? zfpB3&`JQW0tkf(w%&@Q}rQ zJ+w%%99X3(U0T0g>GX24!XKYG5B?D`*`-biCr-TZZ=F1uxLLQk-}4&c-+HJg7j&=Q z^OV|dh11d4OWX@Gz+*fvDD3{9c;ngC&}%N4-+(dCxjzs)0b=?CAD$1OM&CM~jc2Nr zegM4&W9!0k+q6n*Rf?NaIh(lb*}`*y@^2|jeinQW4sPJO{=vK)y#VYqJGe6&xG>3! z(e*?WkahrDKO~I}%%5!dxC;O1u{k|lpmJFd-uwcmzhFtgP|@78aQNwbnydGD$ph85 zvhRRG3pEt%@x&QzGlYNB@puLzWZsyAdp^pzg7l)eFxWD=uygNx+U{L^xv-CD3w^W( zViY&ld05+b3bKG?R!5#4`JazPhS2k zf9{9BeJ(2q-`XP!dV$qo{f)1{O0q(NE>(b|Ba^zwfaua=A)0NV35^2`wPTnIVx z1wgce;A`Tpi^$N&?eR?vujwsDQf@cTx2koyTP9kUcjd$#q3|s&9aT+jl9Bk+jPO&$ zS-uv9*`791KC&yT*N0=x$7K*JVRnt8#f}{Ux1m^qD1-Di**Na|#i!x1L|?PMFn-p- zWZ9-$2FWO7C8$)VEK8Q#?%r>vF=hXH)Qla#clyZ!|K&`)A%46tsBG528R-Q-ssA#1 z@w&JZKi(+k1^n&1ns*q@=!B;~)8)bzq+FlS>|oXN2vbog^z+Os6Z{T3Uh3*zJqah< zZXtG;WK&yS*>eqcpVyi2A~%(5e!xLp6K|CF?jU^Xq2mSJysOULl0{I5prM=dY9$t? zHuvt~V`j{)v6i8p&0xTWA5QLUkZag?Og|iYFaWfVr4~TU z%Qmn;ZyLs!gYrpqMP6-!6jKdSyDv|E!2!nC3hfQ(i22+B<=uNjlgxxRsdzt5f!oUx z8|q&BW&NTce7LO2q3TZcmZm94`V0# zH3s=xx7f}SaIkS)j(Veo zO#T;b_mf_(QT6hIso`0m+x|+j2O^!@0}_-`UZA6aihxQXK$3FDhjKNX(9noXxvK5CwPZ{Pephm^E-} z7Gq6#>|1Yf_dx=XNdTi_#2az}xyOHlP%kf*?d>(|btU9-e&wX*&h>a;aQnu!?$iR6 zv1uKOxYu_Unn&`@fZIMadTuoLyUHlR1Lz^jp`5=6Cd8e@ndP-IaYU2rVYhethKe{5 zlxn!pEJ7ftw4LfrF=~$3&cJ!{HNMc@H$8hKoQmgQ<|S=|DkbsYqfEE z4NdHQ>MFcMD|f3p9ROQj@|haW!BfQTB##;T_l+eMtNu4$JwMxUvog><5hEEZ5=!OH zP%msNuQYVc$`#tWt|lt(xX^y7&_XIP0-E4AlUFMrvw0{c!jAWoob}DDhsWgR+k5z9 zTyj+Fbg(oqTDs$8fjUW#&gnK`b-m=lDEAfe2|D~CIvnc#ls%#CW*i$gcay$y^Q#BLk!=D=J0R*u}I2KS!vqoAH-1;I7@n~BZVHi%LY{VOx z8%eHoS}c|_*g&Bf`JJn`e4MPp@hd|m{y2WlS< zaNlMn@qv*nuxTFEh!dIQQ*c+2SlVZH)vvQ2)jZnbXO{mLyXY;8v(5h;<<`mbFggmG$q6#_2|{ZhZK*YAo^8s$A(&_*eJn ztMO388wuYs;g~lYg2N`wL%LLOOlE!I$}7BXGQc)je8X$oGyC&lho70Tpi6GM8vK5M!)YrNdn z$^`k~+_+fYE`@c`Q-3z93{r!vNRVBjR^48C6Q!5sh3)3ps7HM_e#WtBsOH;=)mX0j*9;xj*^pP`;ZT3it z?0wm!YWs+H!f_0zyM06Zdp(P>K%uTgVd)7&RAXhh@L{0LEyj(z%)#fs1Q6Y`z5Ak@ zq0`sL=Rn>O&i$l~e=I)M^bz0AB16Qg`L-ulFH3JuM<@zCpl!UWDa^rp#b4}p)*J6n zvp@rOp&&wfcT?+5z#tzxeZhz*--r4bFYRpOlVmX=L9V%R0iO9j23*MKvD`*PScoN( zJX%9-j$-0KeCpFi`IV+JAV_-9%dYU5tT#juu0elZY#oWfuec z5&cTw1@(I2#8LSKk<^N$gD~JQl+vo$?@l`N32rsgO}!`aaqHOI*`~^3cSyk*@Szap zWkV_@wSs6)igB_cLR_AZ!MA58ll6WNolkuP)*1sA76}x1rN976jm+gl(h6~2WE4+7 z$IZ;E=2do=44(479>2+@b+U4{MUl3;aS2H zR~T|S7HtRkffm_uSHGlo+7#Lo7q2#ja5i^hOO@;)@1ExDt4D*{zSs*7dK}IhK%nW_ zLvNa^SrUUlo^_lZ_L+pj{EuF|vF{!`JE=^Fx>6Zf>?UISCuCH*iAT;(QcBhUf0xp0 z`uW?`H$OeMuqmUmP0ZIP89E`KT{15^_aG&&)r%8a#ZJ374ed9iGITbmF%JtAo^6O| z;UU8XSKq2OnlxKeK6q2N@T^oDc6fT?Ot`-(fGWytZ;^geKzF0yn}t4+EJT)!C4+j^ z7rCOX6AQ{`c6c=WY@CgIC*qB*(W~kPRB^~pe(xq3c8V}A18L+pw(rU+b=jD;HKRf> zh0xxIcZxzPR?ndDa#!?e z6q!_G$@s_l;J1AxYtKLwKu=fircm8eGtPz;rQq@?PC8SZ=YXUqP4*&>kE)mtB-I-T zw^<}J9e4W_sbGbsJvgVVeewseY}E1o4~A@4g9FuOm~T4i@T{VYPyD{yrJ)&dT*1`u z9|(7{7jz{bX*B&>mSSl-&3hN)Cp=d7Q#Q&UsKicLbF??H&&^Jhqs79q>uU?BZ(;nG zZV{jks2e`M%FEk|wV@>Aug~QYpnm&ULg*-6-@w3!RQZu`V@ly8b z`aKf$uLE;tsrLJ_9QvY2-jr-sVNNU0_T#dd5hsR6FX!K%^!=&2RpQ5!jOPbaEhR;N zCRSs1g)-Y1pOa`%5;7j#ZCV-ZnpwLL^@Oy%xeq@193p!#H&K}*j#qB})6uoQ(q4ak zbaEqJz|yF9b+B6*hc1ts@RNf<{m2w2L^k-Wk(ENs(a?VQObE8hvDcaof4`SWr`@wg zzOHUUI(h^CjqR4E)DuuJod*eIRGz0GT+zBIhkRHmHKC9nRlMm&_`*GuLMJ5>*}o@> z?ofhWSVb5PzG%P06@K40Oke+~7INGf!Dq)n--_j^ihXw%2EANiHry8s^d zu(X-`u2^%9#{fI{fZZN}u(w}-k~8rjBhqYGnQGWG#C)k#E{ey6X4AGH&^9Z$tT9XP zw72Uf)KESc^Fp@tm2bS|v5a%r11m5J7Txj6o?83zaW{diO;*yzC&%zDUy75nY4+2* z;S9d}3}k3vZba-GpY0hR?oK6M80B!=->j+itj^MMdjxy!4zLAE_B}*G3B2!*K=%1{O^23i(s`Q1UGWsM*#KIzN3Z8^KTI|IVm* zPK=}pGpOVMXpvfXURk%=L|$2PmixS2#7Q%&V|H>)IG1;BOyNLOuWj?L-N_GO9a}^D(Wp!6fgH$UZoji<*F;<}jY`KO z)-raUVWE-4P0M5f+(w#u-5KlpX+LBIA6KZ_Z=j<`DvG&}S=BNhvm0H1L47h~cR4gd zr8N1{qxtRWuK6>Waxa@* zH&RH*;auDJ>6tk&A>tV@y2@~4WaDWVBX^Gvr!pPXFuU60i42DBHkDMcWcMdZsZiwU z?4srAx+T3|4GE|FiK_eYKK^K{G~e6dgM8wgyx@?gwQQZKLA1Ov@|%p(%NC;5Hj=kuxxV#Ep{ z3az15YU04iszYdhmhm)cTkNj6?OQ(MVOa!wg75w{IBtW1SC||JV>rIg6U>NFY1=Ab z!{4I;E$5~oQY(c9b&0tfE8G!GRcK1LF>Wl#OZ3)3Mg?c&Q2!IsQi1gzzil56-Dp5 zb#mQN|7Va``RO`E5O6HM z{do;-%3TlAZ|Y*UL(SFDigJ@q185NKF-3l!+^z>qski)o#={%+`Ocp!=)WIK+%A54 zL|Msji*)L9K$W#(SY7*iq56unDn(8A^?}dXP-p0XtIKPYdtiMmsiE9gOv2`LD8o^9 z;U-#IXesvX!g-;SL6k$jPDH(QgGAJ6itnll1qB)O{y+Z_4PLOgNQ0mHokA{lqj#c8 z9gEvK?NYk-_AJL1e06GS5o?ZT>k_r%oU+QE6!lTtU+x3BLBW7J5#d9r&z)d!xQ87W z7jeQIAV3ApF`fR;0IboSbYVp9n`-wx@`{a*QG(g*hN0$kHYxK82-Ux?%$smcLqkeC z64>nw0eGZtAmB0&y@@KL*CE<*yfLbC9~ey%Nwc&^8;8nb#tTVh3jW; z)P-^)j-xk?*_Up)o@`xApx)UY@)n!AKx&vh?WkDoJ_SS?w`3#5MK=I{`nn`J{b${D zoP@6ey2_FH(lzJJmUn{06j=k2LUyCrbWY<6b#nJAJ4B3&#zT>6!l|+@7Z_U1=WRe) zipJWVFB8un)-TTO36xTSblM)0bpY)h`0R~QB@g=Q_l?UKYmFCPJ=L!!zH=~&9Rw%;dOQg-!Od$KvHlZo zKTW37v~5zOJNE3mD*>rOSqEn&*fBiMoq1rrp`=+vJgL`_?NcWb9Ibb5dqk1UIT&VVudw*MIi+L#+WfIJb9lLcWDU zj5-`q-Oy+@ou-9zQr_8Wc%;D0yPJ`dvz3Gs^ug%0`*)@PF=d+H@ckyCoQr29n}o@{ z#gAAeGi&t+m}VsN6^oY$!-)xZPPvW^DlD~=M*JB&d3eJc)s)IurHvg#k*)$J@2Yh8 z8eg=P9e!Mw3;O)rjj+y1*_$4-8s^7)8^PxDobjggfKIHS|5MYidwVQjg0~VVQh2ZV zQ)t+4x(S9{RTxYceS2))Ar#D5X&y)Ph^Nr-iIK@r=xT3d4q$$x=A=44yVY5S=OTfg zMerevT;29C!4KVJQ{4S9*;VM$k)FArfNvgb5d(rTo8Uj)sV-d$Fx6%ckc@j+;nw{F zs-C~SPF_)7=Cnr{l_Mwb!C!}~$WHoYJA@XIyOx?hJUl#_1lvvFD8wd?el+7?ECm9i z&N}u7G+hzrlWOP|t(cp!qnY-xplHgSq~i3mXV{}3RjSK%R_(Y+?K73!SVp$!i!0$_ zvT5A;*-r8Z*^XN+ueDXjMSSQ@=v`+n;2%*}dvlx}_@3QLbgG;G8HuV;HE&qB6LQkv zcq}nwhu<{o7gKei@_BXc^(=yEBnS~B=9!&RyyCav^X|l!$nkuG14Gw79pq3_Z(4D6 zL)j(FQE8)Oa+~;!LC(Ym=aNz2v>&WMbW6|Nj{K&Y-6Duj{KKhzO{Nf}vOt zPy_@ep#~KN6#)^YSLuXMr4tYlP^n6h9uR5LOG59G0Mbhc2|e`QLJ0)k<8$j@@11$S zFc~J3K0okC!dpp3}ZabA#=LRjj89&zpwz5P%MgG?Bx+ca^Wc`5i#kz-U2GxbTH=-*9l@N%!+O5NGJz%cHPRd6+J|fO; z2OTYgrz1chXB=+M+LMUhjA#fgc)t-*kcRx1GP?1Ug?@ZlcHps>FN>$gXJ<1j;UN44 z)4M*ADZxC)c^kLLjVxC$V*RgwWa<``kcbI1tg-Bws_c+Qg|FCurPkKI8u84jrmr@V zTUGi^Q4G?qiu#k+QhWMjQ@F~y{QV~uQ+uB)TKbd>9jtI;}(>W+^Z0S*763vfI+1Sk4w?{U6BK^TZ)g> zHhCG}s#5ofO7lcHU7EO!f)DW{7T}HxHG{9;C=d5G(-_1@1$}YmX=Y+#nre;;WQU2w zDT({B(I<#Ax{)x!W4500$Ebjsku;ABbbaCGl0cOKJ$*({oK2KHOOOLzOQ*$+afajr zGX2qv3V;D(1?CN|4zX@ansCo5GG z*!^A$%8)Y=z62;IJ1j0P8gUF>Z|%Vtb@Ys#ItR6s#(z6K@~K!(($mVIyU|S>QQF@S zkS{8)-$wqS`3@+h`mK0TeGbHY@(_!#otO4EZ=Rm~Abs!&2sir`!@LK}mZFtYrR?WN zCWT6VEY2M}cV=aIO66cfg>zr<;=}XwQxDMhxoZs3PwsT@XjHGUZY|n+OAX!#Q5zI7 z*aMk%3vEa{c_h0k=8TlsA{*Wf|ImYMF#iVRK_e6cM;(^^p%)?2k<}$7{fM3K2KsYj z!UDs2do6jTH3z#j%+2fGWDRdtTI?VEQTQD70@U!f z8s@FBUvbrA{-FBZbAvsvC+wwHw0zWN>>Ex&Q^I&cx1{)w?^=8uk*g{xqMm%=uA?yrJiEPb|&+#x-GGj zSlanqAd{2AzhP7pTQl+VhhI2MW_eHqo7>W*{a%nsdvL$Jx^^mG6e6kRZPq^Vl8Pp` zecNeUxIWt?Whmz{kAt)3R=6x*lS(~JD;_CG^$H3X(6ZB}-c7YAVl#+eeE1S9uco&6 zN!n{x$gKE`W09k(&Yyl_bnTeok;qe=D3k$jrmKwbWbSe`bQEBpp zKkO%{*KAGdoDKF~s&_@Jc8`KLig$bZK@BNIDUE#Xq%%Y}@8i^HVuc4>^ia)3U&tM_ z@cI}C=hrh=FuS%?aM6XjiGnf-vDtKG)R|Npldhdf34Ogb9kSUy5_5xdy?IYOX8-A< zF7oAeK)>Uz_+H!ld-u-pP(Fvw-?_U2V4PLud=N>LT zSh;taU-?O5LJav~y1D0P3ztpzNO05m2*LggW@7Mz-DAYS)Fr-2Sdg!Y0Z;JwhT9$@ zr0450ply_Y(G8&By`gb0y)c_#oD>QsrF6V5$mW~~-X|m1U2Z=KF?pVNH&|pPiOF$i z(qP|o3*r5BXQk=EvF}?a;I6?OH*<^v6p96cnWg6NY0G<+(~~0>99c62i;8Z*yTTp0 zwsSXQIy`yfc|x|X+q}L#E^_>I&0f`d#iM^Yo+HE?>6$kxQ)b@5%Sl=df47-omBy0m#dxA2=aMX@Kv!lZUc95z+yCOGFW% zxqw4ipX(m$H}(SdT@J~Rd)3Aq8Q*pCZ*MW9T@O~ynXxgDUl=gAM~WGbt&;(V=P7Q) znJ1_`Jx#w>eD&+l+Qbrw(Yt&a}(X8U`A$)iPdr@J$6+O$5W-RbroihV8f{ps@Qvfs6h?eN`fKOXB$c zuJ4w_{t&(%Ky;Zl`A6T!sW&C1r(=Im@0L=ysTpF-@csJZ-Z4q_7fy|ii0|u>(m;dO z$(MfS@hd9*Hj?lpU&wc2=kxN@ZRIlydxgfu@3{7Izr_|LwIMpM@@FzHUQK71Zon7& zCZg5N7TJzColk$D5ED$tjx7+ur*R>qpJ)asNAh95R4rN*-PpGqxqRLYHu6QBm| z5KxwDYBo`jY+E7SG>lauQB<$6{*MWu+OK@CcnUL{ExlPr@+-up7jVul(~g+Tlpwb-m^4#6mLRJoqbx7~+D_Z-+_@#e|CWRK#f^^^dUZrCG@1D$#w6m~C&PWcNab8x%5d5gm)D&G%ygv1)MPK{}W+b#f*0c}A*^QSuWk}5Y} z5y}3lU%%-5vIExR=);OWn;H2%*==9h49Qkt&Fwi8jlQz?hu7s^NbFaQYOf|@Ye22x z%T>Ls=}G*Xr_lsIy)pA%zOCyZz|&W%0%w)y@w}RTKrM zyf+lQBVwnivil_2cB18xWy>JHxN~-Layi~NQKgrJKF+Mx*06u8hv_Yja1ZD0ZY?wS z)G;0>pZSLIIOWKj?!IU8i+V!fm6QF91tDtH;D+T(*{9CI9`bMN(@DUZI@5C^bv%mU z$yJdBN}RB!E_pyMIRsS%R<|*}ojCV(2iU2J-UOo~8@Ld?8#y@h6Z-#_0Q%8CGxNH> zP-J};F1W7<+u53*Gj>x;6jQwnv4E?TWrxmvwbNnTzOqP_vbH22FN=ttt{6F5{( zPHyLFNL3Zcp$MST?X*o*cVe4;QKy+5(pjytr^<3p9%lUWda^=(Q})IPkB-{Lhw~{@ z-qbqf=H$pU$;-==JgaQr9rci@obte)Hx7r3iq@B?`>T~TrgB%ioWA=rAy0UV%uoV& z2YXxNVdV6l=_}SJ#zL(RZhd}GUL11DGCAbfuF;IYC}-s8$tlqt{xyXeE!T=75>^N*;;_Fe2x$ z_u0hT%mytzt8Ox-b)QI=Xb__TZ*Y}2yf&R%CaVwWNH4H)d~ya0nPyx~Z$0pe@z&T4 zpQ*YKd?zle472N6usqqQFRZUJ7*ufP=yFx+d(@fr0+E&BJKfS;8pfG?_Ry+a0kS(# zj2;>5X9d-CGT#UPrR^`&xXQYmRpaZX5#O9) zi4o8BHan_UNo#P3860!igP`$pb4rkSJKbtig1#<3HvnQ%949k zH3Uk0+X#iVJR!ayhY_pcfb1sFblgayZ>4iMi(Zt@ED~FM(qEXGNctjXESlJ-qn9IM zk*@t`Qu=4{dN1i?ZMPZf8K%aJ$7O`t6?Qw6!3)?<&v6=NQ@t})KdZQ2- z0%hK|Y0>&41;8rKc@=WzBu^s`EKdS%7&{1nT-ojege*5;Znx|BpA;#LLq5a9 z`u)ShOa1{0o|jhN8qC;k@;y;0d-tyS#%_*|MhByt#-a8b_if~LGk4NR$km6d*P*5o zJk?mJb5f}QE5y+d#xg^qRYZ3ggNtkkJtUP}ZYKH-1uFff6!`M&Fwrf}A7gDU5Xgo7 zN|lywQR|r23zS7vmzAAKL7S(7tGqNhWWA&z(yl9p!^)t19qYp~kYqLiPHse0?^%aA ztsZdj5ee}4`w!Ji1St({l7tiI>a|nj-OAU5?HY5@z8-VXuhqV+YW3C9)FJ+#0re{2&nva zaQ4FjHOCh5{l{v14a8v?FD;sRu%MuT_vLYbJ2bStUHXHOKLpHP)GQhg&`(y?VxxN)O&h(NjfA_6B`tQ#U6T z7m1>089;>Osl80$!t@|7w2F7jv!84Y__AJw+w>b`d+pBSd_utZjKW}6-o7**da$>? z1fY>Nz+R;>zA|%jbAawYJ?OEV;J~LG-$eS6Ft#V+@B;(0HdSPGm(kio0pVgu&$V}* zBYthn7!Yks;noRC|{5M736ZGZtzoysuxD%PTnPs^V*5 z_*Yj%qR)b^j$$~`LoZay)ugsaSPMiYf^3R|HbhPCD~tQ`W=nq;DZlm2|fLrvx@Ay z!TX4Mu+!{zC6_)@$!=QHu>G_xZSCwvWPh{B4PN3(5%r}fCRHir;Ap-bb%0p-_9)`V z5B?LH2Tf zXsl@O0$sAk&gGM9tT`|B`0;E=QG;tmu_RU9HgF^nik;qL&&rr`#c@0Ld9q8Pm|^ak zH@-DI)w;n>V51xZ}IgpO{UZn zPXF+mT^Xm+&kEU>Q8%SL3m*r101MycOya#PRazbgRFFcXez=LJ1;9>nkA~R-z=B@- z`pWGW?;xM!Z?F8I{^M}yyF(828ta2m^RcWNe;7$F_;C6jqld2a2wI6RN(eiTRSKJY zn}Av1j(y3}Gr(P-zcZ>(LaC7`7XTT zTmj3Gq73K9#m721rY;H`VBN|zq*pSLMTHpw+yL>oHE$LHiG$bViT?8-S@8`N_81-xilh54=!Rn znQ$}M#=5YMkJ{_idY7Bo^hD2XS;Uz}HgW-T0{l2MVUfY4S$F*C_{O%d*J>b>?7Ci# zH6XI{1I2RY-f2?!8hxwu$ENMEiJfTAr#5I~EYnu1Frr{Qz0=;E=lHxs9^P0QSDefY zYY~`NjMFjYc=%T@I?DI9w|5PQGceuIcDS-@#Jaznqk(_w_-XN;X_ZZ;3Pr};^sGL( zZvPT)=lo(~?%9&uioV4`!en^ts*BJ*SGdGw(pNeo0XVj0gl`Hxp)GR$Phj)BK~nMSwRAz zcV)~Y3hCGGL!+?!)ZL+b&fU`1$qh$pPK$|%un$7ugfmt)Hcl=IT=`PKs7>c8Jy<+) z9~k~+zJy8P5;NfsIwv{60=}FnT-5BDEx5SAw(gkPe+JzJC zouoiYPGsF##N13A;YseV$%Uakjd~;fMg_R7jLH|QJMzTX_4?H5Js0_{jkv&?AU%*G zJ!c?$9v2Zv5s;(%R|3LM(b3Y@H+WYuJ|qJIiH=H23>_r}1;nB(YmB4O zD;!!q;EP72BF`w~#@^DmE0V%KaqI_=xx>e%ho*+bp8MJ^E!w5G2h&gown$26l6~io z(XR|*t})wJsW{8N9RCbLMsFVHx$NN)gpB;yUs==T1jNc&(j6A%L(DlJ1$DO;^=yaO z&FoQS`|QZ#;GPau=cPfdn@k%4Oq>ql!Cnpy-6&L~R}Q_mN{XE?z5ChXQac`UF${4H;FCmUxPdW#lR?9i80urY2(ttL_9z zr)%Pud8_kY=IO=N92fs*&Ql)an(hRkt&!tPFsK8P(!cF47kz)aQdOB{JiNF{zZ-`W>bYPxwSBh+ScI~2WBk4t zXm4oqK`ho771<|U(uaAp{s-^aC-Q=6H({CK<2Cnuy82~)(egX^Ss`Q2>-l=&lSA$el3R28TZjb< z^YEe%$2cdF>qqAHq$I-|un?k-&Y;XLxIB2Cbamx9pLS?{>-vwD@WT!M3g^YIvsFFw zA8v;#U5?lG?oonFZvGIyUUw$A0+UWH_a1!np7@~P5Hl1}4lHM6w*LUbY1&@V;_j%9eLVF{sU-&2G1zQN)I; zkQ+7G@ivgoI)qzxN#AQ{(&5Mmh@IVDMTYz=tYHaYquQ0qpWVLfwhxTmIsaI!Ru8k^ zUNH)wJB|(DR_PMn`TSf`DG(j6)@imbu;c1+z*U6q96Q&PMrGt^zn>ucskOwId%SEw z!rPZ_ByQ!&&m8YRDc_pl!_>YBHu7mWu3@d=)44M2zBYP_ww@^`^`s`y4$~w9$*d>7jqk6=lTLetnRH zwf=Cg;~u5lTv+ZO>6OoIL+h8VdX?fFn{2o|gHL=b$27?Kb`0L0_g)1*H*O&9lIia|XL-dVhnBvokne+m>afhcR8-Cpuo=#F0ww zulT_i1w;*26xHzg^_FBn4BH79ISV8LOq=TFqu!!5OXc%}z<#EQ9}TO$V&@=VgS;Or z0>9fZ@t?0LNWS`QoL0MQ@Ipg}UV}d~VE`D-G=>|$s5bG71)2qZTn{%&ZQ@r#!?#z3 zW>@)eq+1k#J2g$ev0?7ns~)wON9!c1LKv3`h1|jldn;1fT9TMA>dLv=(ysG&7X6Cf z{@;IU3t2{EPva0zG}DhXguvvAjTm+28t!m47xGYB77Fh6+41R{`OQ3ktHU`sCVQz_a7s|1BLkW#KxTdTu&BEp4u-IxYK=!QH&f z@3_W40pI7he@nlZ_4YQflG?>aCc?xqlP2sQR8n#dm#Y_N+nriaddO^&L?YR^x{C93 z^gpsrS2^Ec^HB>hF#9M(AUQISC|jN8nXT(WBz4kzrWC=J?y<{?me}+G!&P|V00{-bmI^gJnBLR zB{SZOVL)37W2iK82_&FM+%V?Il}L5i?1}Ztj7QA$ME4HFI;;DGCpqW}_?d&R0r|RC z^4J+JlWdVpmFiYu`WsjypysWSS6DYewDf4 z#cdL6Tz;e6{a@gP-*E=R$zz5?Y1Voe;f^2gc(G*=$xtd z$ReN>Gs?klj18C;R}^OxFFy2e$Hr>81kJsa76#t9=77i?U|d2k#)?W&#+Jcpdn}H zR6n3ah?N1e`9I&n+$)D4CDlaf!}YTM_xftDusnd&m(G4W@6(mW38~3W1UsKD4roP> zDHz}~87aM8!rzjQA=B`Bi2~kKp^Xi%3|+7hva{p2p^aq zK={dv)X?t#r&?70Et;?@k1K%~182&8kjhSyzwDxB11;Rz!d^{aYn`#_sm@GJ4(e(l z+`_tbG1EL)(}L(4R&brC#GNSrI7Iapl$4Td?g@&k4!iI6PPMD1SiIUiD)|1tl{3HR z#sUgS7KnfpM^1WbzWM|#mug3)lPv!5*5F#IlOSeVTkU?Ur(otpu=-m|+;WCrJag0g z@oq3@paX8hbOhIjNe@ntv-)nY)ex{)?4S4kf1es~{%R*rJvmIBTn+!H!PcVWM;`%7 zKzjnaA>YA7@pqrwuKl<~24}P_1oPgL{gardkwVQ*Sy@uyS}$&MK6fgeEiTTq9To*o+yA|QkM~zjEVzBM^ zoZ8b?*Lv@1m;X_`V}^xUee~lgOn!l(rKyD@*QQlYD7;4&g%V-o_Ogug>K$+e(_+8K zQY{Qj7&u9v&Egz-(ReoX5HMC{@)r{Ft78!?PYxp_n8`mG*S#d(Llt*SiFV_(tdMek zQksSpax;)NjnVi9uhm>Ow`n{B&^#2}&AyuVya#7Xnly8c*PQ`Hq+pIzZ=~xH(wWI< zbb5Oa)4sKi4(ey(|DWeI3RyeI(f`(S@c@~7@CLLI`o*U0k|$90~6lk@>4* z&*16Qz54Oq&qw%P()mL+x>|^9ijc2KC2=|%f*)0}1Wc}(EqoNK1jgLf``%CJvl2ez zyPn^#f-Ihj=NCTz=^dq#3qM{5MOZZ^1^-G8`aLJ|NxfW4=8og;5Q_~H9bsdcralc3 z_L502ShKF_KF|CS_nkS=(6i#~J&)er%aX*MZRe*qGKy|MTiL^Now*`d2hPmSC?@3e zNB~U*2mM)B%Mr}4F6dqo*r&xd6SbK7*L2%ovFyPyyQ24TT7xsMwaV|%f(SQHQ1R(V zG71h00Fy+Nb5?&qk6j&@LieVwY4ISS|Bf*ld}eUw2o#8F+kR})->x5jogh;bMADQE z$^1`G>vqgg$$wr{v-%D(cVPQI$H=rW9Y*ZRjBmn28}k#k?7S^rUD;*(4Ng43{h$*0;@hZZ@h6e7 ztKzhXt~@YQ?kKlSZsBIjE!xHBzoM?c*GSnX4)L^T2+R@~DY~H7%;f41%>u?<{;&re zfLAeH6}>!@k%!(lAqVL_bM%xtc-eX@YSD4;Gd^FSy9Wv7kcw2x`}Ni(c>$3l4;gv= zpT{CsMnaw96=Q@L>Z3E42M2Y{RLhx;Ss(?9X!Ax|B=p}dvM!v{D62bmB z@`kg=>|_GwWoOoT+(YV}KpU38G*bgOcRAu#P@6cImRMYXKrd=PyJ|J5YwfvR$jnVN z)9tlR2j{0(H}$t4fny5L)+tlIUd84}^uoWSRT)U&@y(lGQT#_D)`JvQTaJ5nCR?)96M zI^686iRr_bFT)r^onLX~+IpIZ+ch^XYyFHF+&+59#xphUIjeunE9aFI+Yf?H_nq&H zVhlYu;f#7;Rd(MpYE_YlWoH_vw>bg|*hgB76y3CMGQq`dY^Ik54X?wp(7#0B-veN+ z!>I?NGYtN91jc@A&FOgw{eXHeACJyEw(ygD!S@ZaibS_{xQpSBiT>P_hywpge&_^$ zP)Dp6N8p-;-fkIT8&&nlQL{o zTAr-?xLWtL<2XXAdsW*d0nPw%$~8ZoLyQ>I09{Zt{?@Z*DF^TgESbGq;GRuvahttr ziTzsA_{^U_`>&ubdnosN@6C^>`*Dbh{Ub4pH*-+|LGurK)1AHwzo$ojUbXnX(-mTT zTLskAX$B{Ti9m@NJ$JdAEJI^S=VmPfW8HCK|MKa*DnHsoMIZm6r~Ug+h&VM0#O^YD z`l-nUAk(@WwD}erjfRth9?C!l7Q~Cql|Yy@4#Zsc2{cw$6M@>qK3Ht!S zUsBBxCyHAM-Y<}klceBdjkRJ3KcC#+FYUr%MU_{uTiGIq`)xEk+9GktQkx?lbF;os zvbqKgn7wj3f28_BuR=ljOV2r9qe#B?U@IwwkUI&%q38r|`1^7D5Os5)sc2>FWc@E5 zQS(PYJ7>nj@Uwv)qgkM3{m@Hj9p`1Y9t*4vHX>W6ySHdL>f*xI?`WyQu?ler0%1Ge zH+Wv*U7DBlSxkO)W(Y7JM#4upUf&on3s!p2ekkQ>NNmA-jG6Vn)Z)Ki@OOn*Ffoog zAZAa-J?Tb)C@XJ|ZcVYaR?Ao;eS4>M(h3_w;S;mD4~)#pVxC1k>YmdI!!s z53YRX5Itj4e9>pGswgGb+hUMWH{RiLN>6S|RWtczNre+kXJ{!$FSpUN;X8GY7g&h6 zRiS0DJ8X2sJnox6ti-yf{c?p#apMDSK zx}OSksS=hz?;1RgSo^lufkCpzJh?$xMP5+u>Vkf;ozPrS-eGg+>N-vti5Y+SJ#wg0 z#k*$q{$audfp~rp->KQv`SCv^(nX)oWbWKk1tASaNBMIhs$Bi<;}lg_rujShH?Pb) zaNtbm?|GeiCo*P9N^zPDDcKB!c4ktyAqLU2Ghmfq zbN`ae^eWVT(deDN@XxlS&m`XsY3cD{shz~Q)#i16)ae;M4Bz0`WrcO*7eDH^-Y;!Iu}bAy#q&TF4{@d-M*F6N4C0daP3UB(ye9y|^uLEL4$>d%90?Hfdc zSWXi_dMWd3^cx%!?dFCSEu6A9Io?#sEH0(ZySIRMEZWM9IYO9+8oM&X_PDVq(yrU~ z)o)s(?ET_xc7)0%Tln*?hyXlyuU)4-iRAADeo74BncE|gyQYv`gJ zI!uO~Z)(Ibr>PctUX+lm--MwQ!l`V5KxaP&hm-%c_Xo_~&xm*Xu{YoSy97}W`t9tu zj(Car5KgH?zK(!8lGoivX}cF2t1NtL6FZC`Ttz~KGcdz0R_FYp9!Xgs{c!$3X;=}{ z2nH9d+(wGF9){c4CEF5vQ{;VY+NYxrCMMOOZeF6tt7O6KDF%mJBoZvtdG$Kl>ny(#MF;q5O(Qy?;&g|5bndk)Rwt ztjqlsrT@+8@(G0s@t1}E;d!$5RRTrFVTN50J@5BtQ_b74IOoSiWn(Q)Vy2Sim$kCz z;SJmcYytL0% z?p5sR1=mn^jCyF4)dx6hNVnSk~6JJM2DZ;};;#s^7S~y^?d~wKzRKA(PYzs!d zT4H4kj!s|a!TiF; z!Sli2$QOIBo5JKYcUMzIq%0GG=`bZus#cFbG$O^H$w3}JbvR9~ z_f2%(6e1LpqGyVfqzL)`+{eiU=a933T*d|HLW>;ppJN%IHgSwU(CXsd?!T+6+T*9A zW8OV1l#ziAg(MJ%%8I53`A^R%?lPGcv9ob(WKHT%kUhk1b9+nWf|5<0FWd~-Esbnhyek#XGyp%OqWL*2x$ z#fqQ9#Rn#M_xjytjdQK^@0AT@fqwgJ8$QB6RGlg?a_W0fVmpl*d<&K~; zdxq>CZHJc^G)XvTu?j$OvI2;4lQm6u{u{|sluOe7DD@dYvIK5d`ZR2!Yk=&u4D3~zpE8>s!bg{=0iB=H>xXA~pP{OUnqGj8q=O9OgCgakFq~_A z*#YB_@3C=ZfJD@c$9Km0J{ht*U){pPUr)hFNy`l)!3ac#7*8YWh9;o(}( zF?4ScT9nA7ZzRVO{(|NnS*ED#9hAz?&4D3*0&Ca~qRyI?aS{Z9b!Ne^&S(GGc)EC4 z6MLs_jVabhh7Vlm#G8F2lJ9dvqL)QVEwd=kjHA*q2bcn=N!3~wE~jG9tF9tp{REh^ zRx^WNErP0ZzcyX%Ok+ZkQxkHM6_N!P*?rLq8a+MA|6her?fX-uOXWkX#-@tXtZTEg zmXMneQ2WZm@M)t#JbqMLTYG3?@C%4r<1pgrZTfqL?~d6uyccUoL$s*MX=G^{@B{$V z_2FgYOF*6>7pA1hbp)-)*|vnPnqOB!-*RSa9)m1Fj&w(*BEYQ$KF|Em+&ze<)ZaIL zN89h+Nb#7v@(1b2x&UAp&fXA7>7Bbt3jpN7PN8=eY^A~H2Dt>b&?o8?REVk%{~b za$#;uQ(G~(rZ$AwJ)ZkkJ=nWk>%IcvTpy0kozU5jD{g$KQS56?C2S71rbhvB47xZB z6$KKlwAbFRh~bxRcDFxS)A$+NqV`)l#>M;+SDGU|T9D!0p!OiSJ7=VqB# zcFm7ic+@=K%i5Q3{*d&=0R~`ni+Br1rB*_(m5v9cC$V6lL~Kvoh47=`20-{K6yx!A z6Dk`qLm-xne;=U__Xetx6kY_>#=`6Hk z0}rxcmLc!RMMaO2_)6U8{J^IdF!y9u&%#nx72_=LFXW!_4hnn<_pG!j9)mp~S~=)* zlV>{G+K!5lhDx)roKj*7@>tTtg`S)1OQQvcTvoP|4oXHQz&S8SBG{!|5G3hYvu2*# zpnJo``YGjrTUvCK30XQ5H?c6icyJE0PUc%8ED*Hg))-})R%P+uCbqf}_{!=VV+&V< zrio~q6C?%S%vpACmRfd5z|Nc3`2F&tC9pTAN1jgHZb!R3SH7jC)d|^2M)}prm35}d zr04&6tmzLMRq^W($0#TJOG`gYiT9_gOgT=LE7&BIJj$qQ2wEK<2DH*@8Zn&Qv zZj4dq?#=3R`iG~ad;8laU$iKpvq^pDDA;VxS~x{FbNC92rp5aB$0Pl-8LKg_dVKj; zZYd5F*+Q~z#194CjdPBFlmmSU*7ubyqxw{olxhrDjtc2=guYujHX-s@sjXCP+I$co zXygv?b&Pne)0TMXXbiX-3EiIJe((kvAMXTcTG(I1H=hu1P+N&xk6DQKwoHr}?lAR& zDq3{pW|^?at;L9R3L|LiM#{!i;}e%b1KT40%ex0EFH0hVLnQ)UXHp8>d=Htd1QNRA zQwkFQi8B6eVYg|3{*hiqJ)17wxa27>qx|gFU2=gnJqTP3Fq_72&^lQn9ds`1=alA~ za^Rvb6E{pb@QxwHK0$txn?2?H%7P%E4Pb%}1#?|TE3xPKBL1b;?4#%Rsg?v;{{6Lv ztS8?xjB8OW20YJGAGU@yyfEWc^cO7RZ#K#Ta&)^Ln(pAtVp~Y2b)0iVvRQHv0o~8~k7%y#&Di9 zLmqRRD^q#Ioc_I`sUs^h^Cd-kda-Jp*W8k@Lwgy1WBSIj^&^X-T3QI@&7jA~X4!rW zt8!uo2Adw^Vp(slbCy9pnDNGxUlf>$o%=k%75*JT`suGvhgqP%pMlVvHrtj!tbjKo{Cd)dR7J4B2MVpf5>_rB=d;x@Xi zv=89VES?Mnl+SnWk{aZHZPywa0g$ml^oM_}a~M5-`YnCNefrOB(B?=W`i#?1EWIVg zj$1!Jd*^~8kNz8McdV7?0*#)GtESji9_`GT~4qxmmXk3Z@Lufs-4nCn&@h1brur zh!soz$Oz9d5M%e0IJ>|eD7u{r$ET)u$YDe@dzdA4GSah~m_*M=K`F(l08BtgY1=OL zYdt%6H3jHmuIKQYU;o8c?F3I9o8H$`JeLjoyO-jV75Hl4-2>j??!obMJ=F2?Pbw-Z zd<1+#;+>~CjyX9ws!7w7VP#+1Wf}JVSO&WRu%O zBwRuoC)}DOZ16N>1W$Jlv)J)nYr16b7t)xw&C97Bwg_r)FRiK3f{U{F&K5@U z4!g+(!{Y&!n|;&CFcDsBILLWs{Q|?LWrH}5SyX3XJIv9ucs9V*HJ_RDIQAj7L~^?` z6y6K?0$G4FO)z+%T=h$DtTgHvzt6t5JId+redih%4_UKrKh@^$$V;v}7=$Z$D2U^y z#~Y1mW(;g@iAv6;nVb1iW5r+&vSNT65emL715(K^0O<^N7FI_Xokh24)kSSS@CPcN z)`VG*BS02Sf2b9#^oXZBz_;2HWNLD2Sh``GasQc1|ErE;2Qe?80>DW$2nlu;+AD!2{`!*^jZDK)>`NMIew56|kQ{?Ap;0(UQb z$w-UI8hBjZ@9Z~7(ei#l2IQ#*_9&F$(49hkpcZ3d};^F1qYZ_g)^jt3~z8Ccx~PcD(%U}u5r%-EX#OMm^$k8ZcfxrcxM zj?u3d07`fsNo68Yc4S(fnz`<{?zmL%=LHd!9@pqbtj)$U9dy!fXf!f>eW;J3Db4hY z1!+597Jw5OQu88{gT>*3!9ez&wcN;9XHYq`?5~ji{V`v<*^n@k{;{+9cN5(Kp0OUbSB4P1sY6<`}GwqGNwgiz+muX?Rt)Jt)5KipO~Cv=HO zPm^qiJ7*;cd*nBnka9Ub|G}6oY^ADYd`h}d`F?WqOvbNO_aBW8(<`-3mn$&7ht{F} z9;II*as(Uu;=6nA#+TMc>`sY1GP|Q7G5=DKVM=;ns8s#dn5}W`E9!C5;X~GL)Jy`V z08U8tvgC&1Li?jz*oAX)Y`^}huyHRb{`Rb9y+fJ%U)e110+=jHOEUwcwbfmI5HfGx zBmtx=b?`g}LtA2u-4u)tKr8XBK*M2vMD0tFq zqbNML3e^Z-fV*5yQM0iyY1!E|yDM47jf2lF0)+3>Ja>B``w2JikGu19BfuQX(5FO#_qL6h4Q2emX=y<8e9v0i+DZ0$YAhNfee=vBYLXU+hWa}tt zcYV1ixX}$FF*z9Ck+^c+mivI4m`^@vP`b_RZ5;r!+-#;m&*sif&3g>O=!Th{#Ul@# zyc=qXIZDui>VaS-~!L;rI>f49RRm;5{ z1=bg?B~QlaLBZ86xdN>t3WI3-;Q5i^N#%H6U$+iJjI3D|!|VG7Bmd1ZRX(h>2KMLI zIjFmOEFzhy%Hl}H=Xx?9=HX%~y79b-b=;=9`Yoo#r<{9Fp2|=R}MfZ~IaoYo;z0(a0s zoZhK3_8sfpImxno)ZjeTc_LO!&;}c&>@v?dzvkLGpefSD(H(6){A$9*8|+z~z&_l+ zx^Yd@-m`dhy&rloEas}g(-UxdIIx;E&4;gv8ZXC5tYhjn4Bv^|AyE{oBl?05bA#zQP z;B*XkdnX+vO;LK@p9Nvjc(C5A+LshY7@-h}yYDU_aNd`4i8GJINi}&8!~e1ClX1TP zAf-@c*Uzfm_M+76-wyWob1<>oTcBz`yJznZz(7YK>Uy{B}XW<$-WcB)GRI z^n7TsW>s(l7@^rPGS|r@dhlijC&a&}Rvh3EGL56tQtPR#u}>0{9)(EV)S2lJ|L@4{ z|6A0%QjG6g>l92%1|UJhfeu`_kdg?yKclgp5|0LV4PnMLi>KLe{*o|787B@p2egDN z;j{kZf_)CUeM`@F2~@JDh;fVh->s29%Ej8U=aIK%rH4o5`9PkZv1^sLl=kJfazotu z2h?Ns3ZySz`}z;K3BYV>>4IMkeW^#;hkv(G9{^jAHYf>iXuUV-EkKi42l{V9U$E|^ zi4x6qx7Xa0u)aX+8z^A$;>7~tTE;y>18?-S0v0twn2SCRf2SUFYWycUVRP6%Zz#8M zyLaaXe}Ay1Bkzw=`6idOYG?Wh>Mj4iJE3<+04g9n4mztDmcGgkl8ku99E0*nq`rKN zFYNSR?S?L}1%fw}b|e0^IsAj{j*NlZ)rjLJXyw&;$BfiE;w#`=*>ZQQegUg`<&tpn z=O9_7F@CNQUBW|qFOcZXZ>~+*i3kw4=-H6xUrI`do|!NM_R&p4;s zU9;iRzc|9Eiuf0QY61L7z>4~GdyK-&1iA5WL!2HeIA-_e+03r)y3cXA$NS1YBVC}< zGL4|~ZS{v^l91%&;2cYHQwuel`Cfm76fHKO9StKJDacrTGj9F73fCnv-Pz#znaOqO z$pgdZJe}N`qwY)Vhjaqq6Cxbfu$(3(MIRYw|%%&8?S)-&oa58~Jh*=(z* z(wSSoDd&|G2MEgz0$YzJ!PfXupue-_Q?0HS|39{IJqoalYipC3voG(1v?5sHFIbz! zxyDo7F|R`!LsVjN;L=S!Y$(d?Hdu&YZym2}ko(X$3a04DA1j4WU7tEkxZ_{%MPPa) z^EW{BC$r;sCvp9VkIA8?Aj5v^yHY}9Gz_lEfn*NCj(n6evZ?A;iOBz>>)hj+{QE!t zEtN{BRL-W8LzF`~Gf7fOBRSqAIUmQ&*+{k=N6wq`a^9Q`o7wN` z{@wTeJ=Fbp^v60p9$j`_pX+^mJzuLm$UPJ*e}JIY^j!JpnpZyzqEV3={EJTm%$cx{ z$MNObycFHuG({l)$7hlI?!$iRI0T&x(tmq>T<#QF0q!$fNEkD*ct9&ut=Mx+Kg^C( z+UiIwb_g0ktVb?&zZZJeM7v_UpDtEXHwEA#MryoNeo~|#S)M7-qmOvvs)K^mo^8zO zrr#W2M7fNj6ovDR|NO}skDj<5RXl8BoT01L?6BM4sXAIZ6=E=dx^SdBldXZ}blsk( z=d||*AWRrq1z@{?0Lg>58AYZ=qkwvb(oKw=2)?0$RpYmnv{ZT*k~3!!Sj3kub$382 zFv1Xj8|nAUWB1=jExa-7LM2us)7K*5!A#E;3)SX`>N5|a38irVPuBw5THHj)@ zc_D124BfFE3^b@`ZEYU$F6ds(PFSrm?k&zm*<4Sjoc%en_(#u1L`Y|c;Mn5beyOE( zMI^Gbl8rts|?UPDwms#?l!+FNI#C<3}I>6_-Q;Vz;MB}4=#dx)9jvVx)@CaU{WGElq$ z-p7!uw`cij(^AgY@p_n5(Mp>}p>K5g-!Ml1Kdlqf5;S9oMha|AyuX0Mm*^afd!Slu z>|PJ7>Sf6z4py7lU;1uhtjia*ul6Ct?2`RGB``G4q@!*wZUB%859jbt&#BvQI+&<9 ze+NJQ&HvK!FAZRaufx5Q(rT$q6w?H6aXSg&E0IXay8n@q91pTR_p_pQx8f>R1t736 z2^!peO=;H(!iaT6LfHMv{ch%{;>Gh=e?&xkzh(a+Zs1D)Xz%Q#rC_TeLwAOfMM5Kp z5qAzOo0SJSGl`rO~EMB`plQoa= zg&*(O9E$6dJziAwKi7@g)dYn+u1Y8Rm0kA)|KLv=Of&g6`L@-fnduZq#Jfa2=I}MISz1vKfpBH_$I^`z0w6x?=R0Q2r zXuJDoJiiju*w@#0(Wh18z!}JMUj2>7=-h19CoZ3ijdfGpKdLKTj?Y@1(*zj25OPLN z7YY!z0E?I+rMAa_g-qxRcNfrSwVMRN)?%-&bc5*h?T{#{4y{BMsMKBT>@btH(Z2-6 zf9GwDYbPfZ4w+^)IT(GpGx$C?bi`y^ldSS&s96?&{)w+>wBdJMwj(fI!*ESA(Ho9S z-Nq_-l%&vOXTs{R-7&mmNTjC8oCBo3Kg-XlS(f;lV4a)Zn1A;poIE$h(Yk88+ut0% zRRHRlHr~TAcB7S^&c!&nxOfAedhh%J7UC%2!KuEce13Td(X0XxX^cH;J?V7%lK(i( zTxXe3i5mqF9@j1xjQcHK-U1x-n1|0tD^DE{%_>>0^PkU3GPAG%X=J!KIeGo``Xp2? zqofrS0e`bkN^TR^W8h>bi-K+(?Q_CU_axx>(!popR|YGQ*J=S1<7(P6<7WS3zYbzn zlKIBEuj-b%4d8nB)9AqqusRlvEBMO+2hO-5(>|9M?r|)hC|*N@uEh+2hIu{To?t#l-Rj$A~Q;g6qtv4fpM*-KW{Hy-PH?) z<0`ZYU98-5AT(@hro56ZJX`7Bg9-Mdgp;`Rex2F^ScC-4%0ZNc0U6)rJE%9ygc9GR zHWvG9w?^-^8=ucOa8URh7y$S$ZLbmm{%$uQ!fk`iDvht+nO`-c|CB$!9%D;T3fOkb z4Nn957$?6PB@LmVPA=ca;Y}*5U*k@E7U5;*3D$(RCrd2v8tliwYakF7>e)w{I*=rSMw6n6YJ>34sV6Y(a54k*f zfH9qcixk6`qCAjiD-|);#}?-8oqh_uO}IePft+e79(c}3cJ9rMJG7Yc&y*NXKBU4S zyvRVBB5ykNAv3ROR^$hay2bzOPV5{RlHn;PTJ}A3@k&iFW2}ljRy(G8Y9J#{rDv?I z@B@D^u{@g%MwJxsdhN71XTpn`hxmWnd4BAmEV8oZT0^9UDqbfPk2%cr*hXiIQNAUl zlPF;LVYajWl2}2RLI0&ZWTLlm_+?}B($SE&QW)NlnTbdN2g;1(JzhC&cGlFi>`BS1 zp>_x<6}OK;8H6FOVgvXkjlU{ zf>TNTK$_3g5ng`&P2Txv0={DL%O&xhiEO|4g5nxHx-+c_xTD!GpYm7$AZ_pYEW)lg zZ7DvN(WeLT>p+~Ut*s>htB-2E3X1?aM3+$QX;?NtZ*29`EfhLj*1|CX*-qMTj#Tld zWZ$F$$2PTo(M;7STt-pR8t|dWc|uQdsS)jDeo^ngl_diJXQ`EFI#k=WG&J(>??G|d zAfMx}nDTurPkTA{9$E)LtKX*1azf{MH#-A9vEmWkIhO>;Q`_+^iVHTi@3rGS1KQeP z-%?sWL;5oL2Twvj@lXHHy07bU5OSOtwz5NI8fUCc#&C_}AE2@93S;uU5}ed)g!M4W z2u*aERe!U6wT;fjN%nBY+;eLF5v;v%3W5xmMk)vp%RpWZSHX-g=N}_JWG zzlo46=XDrAY9#%QVax{r57Q^EKFz$&0QwVU-SQ^>9vpxi51bQFd|Eot09cSdA%9Tv zobuD2h%~ERDC1WuF3JPkA{XaT{)b&^$+q5uX3u;-(F{z=?IO?m(#QPAAC|)a&$cJL z`(>;&Yv-K-!ZQM3)@7AsS|+8^-LP0}c!99G>h2G?>pcm4^0y{J;{&1N>HiY)Y*>}nwI)hrfQrlqAlZmv$UDfs(PUn}wt_QJOHPkb`$i0+wS zN*^Md&ub&n18K!hzi||*;2oi5#;1xZm{NzN$cJ(ztz9w(Wax#NK^2^?fdGo=q)Lt@+ zm%7iFPId@2#(?Rc#EZk$JhXYEni_shdV`+qC-+<5!5s|pTJ*RPpx_O`9aZvO`>cKM zo@{P$^~@tcd#(lu{3`&b*CBj`Q(WNV$3uYj|1Eyd+yo5^eDb92(4j+d0nH&=Jk~8; z7nAzDZa>13H#`$;unR{vfG}Ttjl8gMx3XRH;!N+jYRt_KANTHkgz72<_$;OoHM1waAGmnuS z!olGnvw?uK;obw5jj(Y05+}yAWtZ9(RBW zJly?LrT}cYf)d7ob%Npt4rH9*n0dm1V8eQGC zv4Lb|XXkb4|4WA{sO7?QPmpSk5%SY&5*RMvF{%BXq;pBY8PO@HPs)sBCL${;@EcD9 znQkdjKSfbCoa|Us$i_)F8VX}@KD4sIM!^%TLTTq}Cd}AS2K*Qq-tamU$0q8sD)*%T z^ZHkH_J5iesj&Scy^~}23WVGAW+JT{{bCgvu?nQ#mcuP$Y{xR1?||zCwY(jCtWszi zd>k@_;j&eQ1qUq_%v9=dG#F{C&ATzLX$FAJ;xi&2-0#bQD%?+yaF)NaXeW*NjdDaX z<+|4l#kn@==34*keYoQG2z}ye&hl2Q_?!~o=lc5QE9hMh0)SwwU-@z$JxT962d2{<9KSGj*UEqhtm{Go5zmR-0Vh9i6}Q6VxQAB%H*f#g-hdaaTDB?zvWZ) zZLWu$B$t1_LaagptRd_h*?8UPWWO#>=`(FcdcWcLd`xbPZBt%eSYfZ4Y<{{K&ytt2 zCc9JIwcF%#-@m4Me*4_$4Rp*-0u*?8B*$M@m6o;^hNRuTGlz|yO_^zz!!q!@^?z z-AKrNLa)U3Y}}Uvm4qBLo)yH{tt`y!M01T;IT?68N~#=1fTNhFl_jwmZ;uc>ExQke zVv68CU$W`#hr~uJ{f)yTqx;c~?bYHfJm}t4Tc$oEUeG(S!J1REMGAlRzW#GCfT*3y zzkeiDt&@2#Rw1?{g|4w)esyg)?8{D$LwOekvG2#1PcK+Wh*>rCLrpYN^M`nuRGQN( zuuPDgNVrsH8chtT&JPuppk2SuPaY1vY>VLEjNruPush-77t7emC(;$S-Rg2Bus71F zmp(lH>n!j8KfiB`1qcK7%qQ#5P`=;Ot{7s1plG2t%Lh$Wt0jdidH7us5-Rnd6IEtM z-fj%^^tfyvA9*34l(;w*On+&6$cLW&hv z#V%FwwEE$|w0l&^2H*8FKxrCFkxxIb88zVC|KHZxyY$A!#*YB;ZhU3jC{+eYgU`-t zh2-E~(k4nXii*6<(|7F80Yavr9k$e5du?k(w72+lU|$A5tVaTrsD_cY5XU22&WK^G zl!pDj(0VvBy|=d|)qTi|cNjB@Vx^cfCOxBxC+E0rtgZ1B0ls^R=p68SJHAqhH*$nW zCZskkLp-IZAfWyg8)*BeH*?f6ydEyS><%Ou7d&gydVeDlkKoYr-gVgfB&B{O%g@=l zV}%O@f|Oil`?~ta`1VBV?^=Ptk5^TC*sbJ%*G`ZGff%F`)O8>I_+x>XN}_U59siHs z)cT|#8QD>yn<|NPp}s_6m}-8f`YRVgyY`Z?u^~z={UDKe!nUs^S*p!DUeg4X2|dkB z^#~Z)(Cp+YJR8hUlsfbSp#%Ee62i5U@^I-^-dWg*%}1nUr{W4%*rG|=b;b*?XU}pf zfN-pGF*ixg)T1>d{yKc&VLDJ|a(K62uDtecV{>zOuz^yM?7X?q52Q=C?tNqccz`nHQY8~6gRLG1{Hy6WS?qyPdjxWAqa4C1byYW`Hy(-OkaZzbn z%AeHf8t55p&j0VQST%ImvKi1pDtT{kdFbig@%?P2hwiwr!>4Gi8O`5LdDYa>K~fJd zE1~uu$Y&GFzl@7~NW{S%yj;G`=GyKlyFHowO`Rr5vyvU0EQ`rJEMSQA1m(x8I3$dz>bIi zaJx$d7R0!9_s33O4%k+1%qMuRz;|hUfkz2I$ zW6{~ANk-C6Vu^PnWtuJ#UhO=% z2PTvjw+|FA+--)ON9?uio%0n4O|>(0HgQZUG;t{!Q<#z?!u<#D9D9(m^uS>v#^1p~ zWRxdV;z~L@`~^(Zt(Wi5-1onE@Pzfn=de>F;ArM9`_-&~)S@Zta=>TcvZ(kFEsUn> zOUsesu2-I{V%)SCx~YKQ&M~!wC=Hb6#a@*q8)1Pl?`1EfhFO*vttkqe3Q;%%FtPCN z#|C;T#WSO1W&zg!@AznvazPgXm>3I_3aA+)Y~t+83pP)$m7Y=H7Acz5yMYt7)^-m>cZhdAZ+h)G?*?Zl&;Jk;aE8!#+HajoC9 zozD&iY~Iga3{u`*IbV#)GzS=oq>2(4)NG!G1lGPHk`&1+v3h|{ zXtUn@_f&u4(|JjS_YC{2%4Z4idFSx)TX1>dZk*Z+aDib7@@EqzLw%(wX~_eV4 z{9ZxH@yQm)mx|~0BH=EoSK}>C3EWbP@~&oAV9WKn{YnvE%C2-~&ITYH*&x_WFjg;= z9`_jzt4H5JkF?`@qM;7fwQab|&c^lyP(oka{+8+=-!{3V&YUDphL`2%G#eDS5sqY>6Ad(&ROepuT$O7&hLd23g^5FQpGts^wx`Om!y@G6V8lRRnfgKjE^U}eBtNk zU*$br+ndhnJfpsYiF}9K+6lloTUttnxtjzUCJDFxx$Dw**fem*w!+)x2g5#ZujCo( z9XW2=b0_|gZsol{?o@AsI$JLBz+2a6C-rwOKLCGz!~CdEHzY7Z-M0Y#*3Rz9rB~Sz z#CTw^n!Ng{ki^c9{R~sE(<%^dr*$s%<#28LuE6Q?S7E7^5k}`_VcoZaz_iS`o1(IG zw_p|Q@&?)=VY+B(<{S9d;xOyq zyFUM)H*+4|N0Pd?V}63dx02M(S?eYdvOWQ32L_WwbKQbvIfM@OywirUC5Tww$>WWP z1QQWa(nGftp6Xx3O9sYkfELaMv$9~{c(l!_`>$9k;WPQ6?R&b>vPX&C(PcxBkl(DW zI{@^__p_`^_BrLY+70&umwODFFR!MZcfWrWoU|pLjv%L%qOJNBcz&dI>~;j7b7zwK zp5FQ5rr!lL(Y+?Cyu5v&NbmdZyhmL9zxEayTkc(VTnS%W2n}YBL?1qoC<5oZrO*FJ zm+b+9pFK}7x@Jg|_Z6jAV=W*)LmPy&u`G)mbcT?+;g&t zxop7A%Uccx zM4gEZY?J^8g5cIi5|+oN-};PfOahC|ErJ7+!ch{?FPiSt-{}o$$Q2C+9kofMi$*8i zji+;qwb`T&McHHpg$qY<{62#=I(cN{-O1Rw_qWI8HU0vxny?m%`K}L}-FwO<*|YgH z;IY{LbCRHa0?LSN7%8(;y*M{|E!SR2AV7Z@BgK^@<5hS<3=?b?aYwbU6O+TbIY*RZ z2|Um0cZ1edPX}zeBvc_es)!GPdRf8PGXxZZ@FmMy^dS!j{cWYzIXmrR^mbezVOLKH zf|oow4Lg;ZRcukO-0Az|34XIGay)JcidU>%s7!Fz2K4WmW=V(4UJ46XSMFGx_#a!2 zLFF2M__N+logHf)e&a9XUd7oAJ5R9@pA&(253L-Lo-0j{Ux-!4SREVa)<~DXj|^M8 z7I@;6Y)=$|OK!nB;){y@Mn>AIsJ%95LE%<)cA5<^C`ROFNX*`lXL=V)SSp{T$owNCnn(C!lis6TuQ_y zA~!PveyHXy*7vLY^eT5K>gsJjiI-KP4JB~#&9aVk`t@krUaD46!R0;fCl@x!XVBZFGAL9=e!)TGSL~z9aE^((vqTXGMmclEUSwUI4>i z^r+&=3Hy&3|6DHoSDtp|;r{J*A}~%3Z%|%pb{iME_=N_BRO{Ra5;2=&RqiFs9)M`s z%ot)Ek9}u5&Q;mQR^}m!jq-~E0UR~$!m~uv?zED4IsogDne7+9LQ0ec95~M8rO~PcrN&@X0T(Lu@ zaH$f`%Dz$3HDNx^^U*;#_WbZy*LM&lfDcV61mv>1!BKSm{Ekzjc5sBos=h`jnl+R@qnS69U+f zm^Aa4yxlOr(BYYSVdXRRy(8aeyXm&2`~K6=ltP({1pE6%MRm5vY=Mb5Z#pYiVQj)r2 zv-7?8mr}) zjPHhQK?T1##Qo5i@*y9z9)5FQTP4hdQQ>^E z4>EkO)YcRabUVR6XD|!$E`{8|GG0AN&|j2Vg8Ms<^r5MvBe!_|egOBKJj^U{s{V5Y z27bpK$0NQnyU(c5w@RiRcd(PKTu{^MgW}%9C>CF>s(P`7Oo#%Tm#qRlQvl$mhcslh zs47z5+t7zjlnu4(=07$LmYE7l`Mx_@oLe$7usFqs)kL{2DXz#P;S7IP&C*EPBE`Um}#k4MV@gfOodO=Dy@u{-2KTVd5F0CPgGd#-*;(#yzQNaBc;yE>?x?%er#+3rocq2)3)-+ zH_V1WK7m=8McIUT$EzO#Q9BQS+8o1q$~?l{^Xx|)Sd0@cJG(K}TL`2-n4mAe9Aw*( zm%vyBP;}34rM=(s_1<}QYGAx~)P+}0{27yj9jO~(g@%HKTd#WKJQ&T6^M?Y;ZG<(U zmZfPoAt?yN9i?H_8L2ZRZdbzPm?Hn7*2@2?B@Uv$P-Qp)a zKS(HZC2@$@ZsgRB*msmEQ!}+y@Vc4|u5?sd36x<`CyG?%p1- z$0?N8J-eVqKSTZ0IQy!eiIh!UD-!F4Zoc~?kRQB9l7f__-}Ag4aRTkThp@jt^c4Dn zbxFdQ*>g78yi83d=FfZj=M=e7L*qH^N_e%yQqadPvfnxRnZZ)kDOmice6ncEj@%IE z(Y7fgpkSHPUGQur>Z&?{UtQkJRWOLpFpJ_QcW0-eax+<}ETTQkQp5HEQ7uL>nK}>! zCu;fcScS>YEv9q+O3!h#I$`uf{5uOvw!!)R<%hopi;MWaKFywE%`4l@nBoy8 zHB?*{8s+)MkE#QV0J92}WvLtLwf!Y;w}=p&)t1S+ik`~C$7px!fH{xVajo6{ha*Ce z&iphs6Eunt^?^%GP|4@%x8erpgv-lMw1jdcMv>pWL40nTNLE(JP!c-uo541DQ~o4B zA5Udit7wQxUvdYh*GV4JzYH$_Y~H-MSQ<|e$e%g6_3D#=!Z^ZWbH9cP@h0$2rNrnb zIB2DC0fXR;*WA$V9DclrtqL%aXN6U>r+8$r{^$|L8#DBp1vhTCZqEU%HXJ5%ppRB<8iY&O@r9nG-LI5p7_Z}UGsuRul%xU{j;6X z!(l{Hc};D&zo`|pT5LiUhkiKFR2>YhNR>kHT zuPP?vvP~&&ryG?IF`<4D>Ix@bJwzUoz=Ntx#3i0QEu$LGmnN3YT>{mNuyV@8omH*g1m5Ub~ahg8tVu1Cr~P08#x8p6>de08vpgp{doCp{iF`Ys@^{8*{j2+9xL zX+H#oUiF@hra`K7 zg6?d{aGzWZ*E((8DdNZwy@2Z#S{P0%$Ob)8*5OiG5X=F$wfmcvs%NCiz{+J+uiod2 zZs<;c0edej&;w=A}UW}>qN9-pGZWUVvAk?V-&WCxsave zgzrW3aZ*pWE0H=&>g!~meVfBotA$93Xr?dP-}_cPRP!C>I*;f<+*t&rKL6%dLns>M zAX)fWUD)JY5990V;#Twd;H& z$euGXEBiOEsZ{KNuBEZ&_b=XkINWvH9VCp3YZ#jOczK~p?xw<4sF9w)pa4Lwin76Y zU-gdyLAj%ehC2@oD47u7D@c3i0X}p-$OfQjkQKnwBy|u0`I}7?ou7CcMV5-c-NcVU z*Wa3q2>OdE@i4MJ1LkL!_Esmtm`y$Tb(+$^xtx#6EKoD@w(vINW*}2LV(grWjyZ`9 zh50&vlN{JUjvrX|LY0i4!$^tdz!cbMubXawrrxYNq6-T~S0=VOI27KeNnMG+S5t4C zPA`O+KoVsm2bz#7`?^V% z45^$^mS>|ys4GzW+&l7D^MYZ{nZKc&b>IHD%3+&%|1Zbz-;=$d7uU25GhvH|KQi{0TRqfcobd?=4J zT?jWeS`nFd}dQfR1&gX2PvA1ugt?UCe7K&!w~o5wMa&=n>y}A3X;HmP)lk8Asf!F%OEma6sRZO&J7&&*=NEbv@Ghfm>W1Zp+ zR(kV5+c)_5k%@+=oue@0-oUdBNV6I*dbdL7+xMgj3Bj1h6A!QP_RhYaixP3s2@h^~ z_GYi+7_qeLD8<3hbH&Kmu>AIpO>zgb5&sdRgpeHnpX6neX_$q>voMe}B zXRhV!lb#|_9_H%?<}|V|(zNO3*12aNtjyw0lEYIeiC^-T?l!N(cW){F1y=Q+F4NCh z{N?>4<-n|EB*`ig@j!{}IQ@3^8#m-osirdqXTE7a=cw+;)2vh|IvaSBI_)zJhH};3 z#Z@8IRHIsDoiMK{e4#Q>8&Kc|aGrnxav)Nz_I;gmPQyPRM^h32yoDpsOvu1LBiGL( z6LeLmkx7)#G@}#D^dJh%Ua3=VhSEeAX0kp(aRcuvVx}1?%u{sHS{20|S|*Pj3Q2?Y z`CPxH+69;kXqsGrXLhs85W7J#wh^bjW<3c>;r%jWlVd-!w;#8WwqABBDLfy1zh7@E zuF;k>s|dEIvDod_@u~dDPW$VZVY`2%U^0+x%kDck+EwOrVDp|~+Vk)yG=-Q8wC^K= zHUYWE#VC0>yt9pgg~Ymv&<9bP{!zN8(;I9}C`9@AjHorP^C(B)kw8s?X4}2{lCWVg zjKQz4D4n12so(U%KZJ+JgNzUOT-P|r{-rxQ^wC_eY+DNd(#_zT1@;I=t- zV?GewDF11E6B{&23%z6Ao91q$seq4&PKLF4z$t2Hp$a9p{5P(oJ`gW5%@RF1>^8?!4em9~aCmy2twW`||Itn{u^3XmUfD zcNnL_=3l2!ysF6EF^A1TGD~EgHu~AV2yHWD4j6wOcSFHxVUAe|lgU<=nP_B-yiE2@J|@_Lr50=>la=hy%w=oRW_wS zdLxwiVeYVykbqx;*PLO?Yk)7tN;gg-4}~_E9?uj{FTuGR3)9ZY;^WI_w)Jg#Lu@|b zWXbKYHlRhP12jPTVtR$zaLe9-Do!Q&>B9r~ytnM`)tJ6!z3;YK%1Q`)h*$jftBUXnrNHHldvC#DTBZ zc>np;$!qT)@^V0pb8NXyHL%7m89OxB^Dl@1`+fME-1zC$;bcBCpj|x-#jj(Is0De*X?;-kM8P=H_f&w>N zf-imZ&DBr5>M|UH_@n~Wy=q>qoic|t>dT0d#!Cx14e4^uGFOW|NJ!qhX6D{~n<+|0 zEQI%_TvU7V-gM2~=pnvPN@+9khKT$v%)V<~am3h1e;j{Ncq74?CsHt#oYIx8UK+2p z3~@{?6t_ks^AiJjRhguJrh*vZ?C+O=>fXuh1N3>H&Y=(tlrhky)qWp%9 z>VSTY$FU0=(%^thNdLBOI*A@8)vh>aEPo5BJ^Qg`_&ls#hMt*<$PJegRo6}zQ34S} zb>FqFx$l!#rUc%#ZGc1c|2~1c z2X&t$vX}YX)}WOM-0#*t>8HJw_>%687G zu4RnY076ta*^i$}n>r=+wm$WwpTgn&>66=$B|Il9ob)vN9{J{BAWVKJxtX_jO*w6I z!;fV3dDOi(wv2WuQ1$(CRq?h!sL$ho?*dee8f}4t8M>UYkCu>L6KCYh``CZZM6!m+tAY1$?`*P94oWpt_w9N}kjd=p6BQ^VH_WwXTrKlqbp=?^~zdFMI|B714mQ=W#gz+nUq3$rkfO z`2%6KiDmgTuDgq)F~-tJH|A9O1FY43|98P}+GED))LPW=2RYZfs=Un6$MBq>QCEL9 zwhJ!soh=Bhb7hobvs_bshJU$pW6ygQRP!v<%L_HU*Bngg=;A<))1@lT3*RE;1a5+9 z9dQ3pD8BU53@>lGzZ--ny+rlolnKzA{^|12#lv1@dMLIBwr2Mq-lC758x(e0B`m9)|x2}_VLt#US^d8OF zfbuU~8#a;eoSQl6`)!VDpv6njl08^^&qv3SJKbBqAv)qsQ^Y#N!k#S4@aR}kRQG1F zAyPztJ^|v9mRLzx<)Z;*)X<>S~hQH_A@uHi%Iu z-0k1QX#?KoC~@eE1+2Y{CS_nZU5|?`G6F5 z!N`A>U#b54-J^45li^X5U^b@(OWaHMZ*#ydT^|CM><*MxdG=-lR?6Q1eSrg37J4Ea z+=qbhW5ouMp?s@cal{7#^l!rWhmo2vzF>C|8|~`fifsCYL;F!bchmpusRN%IHMBkk zZ1)x7)TQQpa}PQo_|GOzN0?lcXtz!+1JQa8LBEPDcIVU$b0MwjhH@l`z1bt7W=Puz z53^|qZ&x&IazfAM#t^Q}j zgs~MxT9N9Gr@z&51Ag(1K7C1o?&{q#aG6zWd#2K&lpVHVgIbx()A*Jt6F;?Y3kQXRd2_Wu(P1#Rpgo?O}%d_*l|DyItE-{X5o ziKZ#qnpImw8D`Dem*l269sBwjOm!0n-cn)YG8M1fJav9ph8X9Zu7j38#S!;T7h+bJ z7cKpp+J@)IwX{Fv7Jiv{?>q4>_z$+smFrg8o&pb7EyLF?5ppvH0yi|wq9CAe#Pe;# zQJVn>%XY-4%eE0MQYo9Fvpf&%@>yoXkD%9#^ri8qw#8r*&jL@^C2n$aYUX$aRmOJU zQi9(D8jG&LxzNDIC7)_JoLDKy^|Ulu%Slo*pOl#QG|1ePni%wi+=(3A{S)CU@6aC^{#fw`T| zzz>pDcgI4VOW^x#@fHXQg_;CPTlq@0*a=pZzEEM9V6j7ICyawvaC?Ra)}T8o?MXSS zt5eF`UpWM}qMd!7K1~$+MuogL*}2jD2*P>{k7ks>9hlibo9Hv$cIaK=vfM zKAi;i^fuVbPw+xfO*8P^8|m!{q1AcE3$}J9m^&}t2+!$qB~cI|4bIHmEP!7bPr7%Z zBgkgvtIneztEFss!Fjoh=g+59JUq_MJ~ZVnv?%dP8B%+%=FoZ9oJ*DKFCIKXp@$|| z?hMq^Mj6rt^y-VNm&Z7skLg&e3Wr?1*VPU#U*%5lYK~$3;NTvGWmgZV z2TYh^hO_U)!uO=bI(+ei?8cAweR*z^zXNtWIj3}d5VL+~ed}Ji+j0PLk(E8(V)f>> za2jk(z@N$u?8sO;8J3higKhDW7PKmjLxl&IN8pXJR8DQ9(kS#^2P|YTux0HuWjT;k z@7M8lTWDNAzWgo$v@Ok2#j&GzIK^Vq$njB5;-W|Wb=W-V+& zbKK_Hm>aAWV)oBQi_xP4D?6+gVNvTigF-~f*BiVP;ut$QBQrIfDb8Z`{SiNmm04mB z$m0|yiV~p>GsXr+0E>tZR;G?fw5^@v{e$Ze&OF) z>JU%10X&;{rb(PZnQ5-ELwT)CB4wh zk7*=1_kLPPEfe2*d+grJy@Z3V{%z&5FB#)!ie`1A-M0snvOp9z3_BfeED9th3aHy2en3Q5Z`wC!<_^X z&w6vYvaHJCpH+0qICz12M#=4QZt=>1T$+M4mUgSI|H-q_n&G%c0_n7z>)L@u*%Yqy zvJw@qA?hJ)QKfM7@Pz48Nq8ZMB}{J7aQMa{J!MHEkZ);zXM*lVOdAPwkDDy}FS1ga z(tR|_lnD?=anSlkIIefr`-^J?+Imrl7MV`JW8bUC;+Y`)9V;!RFn?!ZaF{%}TxvMx zQ9k-~GvQ8slPi*O0^)~W&d^L<{#akduzadTW)=wSi(wiklz$K0!H(It*VM%Be%IzD z3y*KI!L`#X)v@<|q#5O>k8JEMt@wVjOaSsF3W%|C9z}3%a&>~1TLg?p51Gl0zuWj_ z3pFU~-XH1XRl?0M{-t%xvG^95o7}K+=;#~S&C&3hsLS||>0r$n_LYZ&Gx{7p=cymf zC^qTdNMKrjWpR!PMyy##cg@sB0@T7e2VUElB$kcRES1Hw57a-)xc}61{Xmo4qEq9+ z-yU;^yOs^j;n`94cQRHz*Cvg>_&%~~ObgX>`{ASuE_@@~-4h+$Q!i$O^K)J0rm^3NBx)h8yw9C)Xt!1z=aXCns=dS0-&&|o=)&OJRckeXx= z+@VnLw4km8ZBWPUH`au^nYdlsIsAz%b7|pC&5UMJz-B<1eZ;bJ0Q+hC$^#hOwbHK( z(wX#Tx|art)~T_)LNnP)CdU-X*J z!mXptS$zgtW)p4)rc>@YgECz$#q&v?V1rA={+s*?lr>v2MH(Hp_g0wA_r@*~wpZX! zDq>9iA7$Si)%4bFtAK*itn?zH0)iCjEujdAG!>=yA|Qm`TR;RMA&`WSmvis^?sv|2&U<6Lzd{%zBd~vauRYgXYt6ZH9o7{|oq>0A!i8Op5XlN% zqSh%Z@7DL)>BLmNHdvr1z7Sn7bhXS(=EC#Q{yx_Hz*k@X*f-d#aT^Er z!=7mumJkq*{mCy39C%znNg?WAd6kOv!W~V6|Iuk{-&C6*1(&JcyA<``;Mm*hjlB&1 zcK_a#EyP+c*@cOPxf;KE1~h{oENu3kJVS*Y;7pq~CsPs7kN-LD*mj2_pd~qE1>$xb znj!a%I>wSw+ezcgC4Wb#14yOhzY;AF-{xR_H7(&uVs<{rJo_%1&C_fVU zoP{83s~c~K3vH*;VM{$6jN zMmy{zi_dXGY({-XtX`diu1yPfm_9TtNcEgLLUs1U2lL%9m1AbnbFgvNiwoJU9y!x) zF3)u}L%9s_@>T5mxs5Zge8Ya9aK`JD6cKS@bNH^*Hnfa;NOT6prLV12Oke<}fBho5 z^Vy{*7aM+h|7%;C#U0ZuqqcA5UZyE)3a{)-DGj-avf3NJTvd+znvlpeYsr#J#;|HR z7aSE8tw1N#a_>Z^Z0A|Xh|4f3s25uqpgO9wYFHtK-O;)7{D7oXET z{XJ8SOr?-ZobiIF6_FoCy#2++W?ijY;2cmV7UpB$^!rZJWl`-mP76!_Y!O^uZ|MR8 zST&8TfFptqfT}pxoBn=wMzBTuh7V!VVS!6G9c zbcE=;hL?Y1np7fX_FT-oKAfv=v;J7UyrxD7Vjzd?^E738(6T1fG_BzyW;n#JE8^r+ z*?c}LqKb08gdXBIj^wHnC&j#IvQ}y0%%-;BbXwGX3+A1h6#m<>_+xsR=a8g!H}B7N z!nTG-{QP3pSOOK(+uJLos&9KjkP!H7I#-M6jH^$nuDZ|~i-|#Q9UN2>=5X!P)5U+E z8VsR7eT%SDwpe+lHFB@zI%a#19wv9->hpZ92uYd0`x1Sb9q!Os^=$q9>GE*S z-Xd`MDex9@GXjyoA=p*IfImE9n{#pO35B56&}prWn{6_UP7J*{jFav@M1Dr{NLKpP zsuog#1jL0C@g0Y;=g07o!oWB3Ox6gX-nsZmjt9l+ha}p&TIDl~h#SaKWf6dYC6xeKYp_8lsR*Z6?eBtJl18 z0%Jsmr>vCyx5-<_16|#AJEqRz3iLqgbY3HkRUcMklESBG>1_(B!iKu*YPk2P<(%1hqutt*m;M{hHOx9EJeC;vVu4^CQxDr+i!Tx4VdjzM@=xjn)g)2(%LT4)o zupZ~c)3=JrCd`sTcUeydFF383knjJ}(DGl^vJZqtMV#G}@BhwZ+J4+_yN=0{58a!t z?0WI~5$yf_N7DzhwUUpoJ@j(en{|Vh6pvv@ub05UZC%|Qb_a`o?i25|wHj0=!)3(I ztv@)cuQTA&R?dzRN^7PJ(Qq-hrrEKq%5Jok)SqH_c0fL zdc)$A_X>~w7puaEyOYGsYcD@59ZUIYxqEC7H>E9YKXka~67X#ECxgHa_lxJxA30{- zBkIY&-K7#EMa}4H7-2Cg1t9TKw`ujVPOPU6$6ZM{S)*LkRCp_WF|L3gT%~Iyvgb@r^EvU=!%^;_7DLTtk4+b5m-7 ze_JbJeePpx<;V)&INitJ_Wor&r>E_Wjb_Y{zG+2i`((ouUZ-HBgm^!Pojs-PYd zpQKvRd$hadKo{ex7T=Q(J~;0Ein+3;Ndk$BnyTvu9E(CKu&n+h;676=8<36QMeFtn zpJax;a`{)-)ZxkOy0QJmGR(W&ZzYg#dKE5Z3-LQFc0U^wo#}TNRYT_YzeoMY-sF20 zh%t%+-{aon&Vjq0hbI8qy8J>gOuvKRU}S`_nIK^8)bCp(*lt9$Z#b`cmvy}+o5F8a zwAeIA&JQ`5a-k}|SCHM@>_1&uL8%WVwAOx*!c^Hm$^VCO<^Wxsg^tjl_bg5NmG28! z3`X-<$4a}&&DC{w`PLomXkkYQnzDiSacaW{L_#UlTg{3l$>tTBNM454P>Zj=se6{}^UFXb5S zh;p*&*Xdx_RG767E8W@daTkNBz=GbgC;y~gouI;I9vf>u6BMuXn~hb`4_nf&ueGquBwM${=7Hu za+4!_1}z2ddUZFg#_Zts&0jWOz0%PQtvaui`@U{St!+`C+#+6>`A8>o6F&`iK&g%7G2{XbF^E02Z zV!k>`gjPLotaG8?UaHb=a(eez)H(s;f>LB4;MNnw%x;)xt*mCY=U}s;@TTIN%a{tj z{JX#Qz@?!C{)>OL>H999;8oEKtovTeSs<%lonfPmdCO4GrQ zlD;dS_kd}w$+ss8TU?g>=fG>$ue!i9k+zJdorrJR>o^C$>IJ6`H+S@g8p;KRmb?u9 z@&?<2KgdS;;P+`4Xv-V^s#Hb@YCLL07XwKsJKt}+)x2;9_uuYh95qf_Yyjw;R zO4OIgE;oX}DhF1}XYR;^g&LO#ytV6&S!L6y`5mYeAAb2piT*;%`@7du z|LG7C??=Sg;PJv;fY@5^_RA=dxz^gtCevYu8g->_`>>x5nM%D%;isEogyzWj)B#Uu zVG~Vg3IX&1_o$71zlAPo>x+y#>~CDWv5K`LUA+hNny_qIvym zR8**uYQpBpU9B7b7r9aQP;$%9pF0Lw=oBwU-~6>LEW?+?@fczdY4I`dRldNe`A)>_K0PD&8tD*0z>c1FH-^;T8{}+DY2;jSyi*N%MXWf0(YasP?w$E>Ay;AWXXMAZ9swliZ!aBzBD#Q8ih$O_o85! zYL6yA|G}HF2DwuYU@YXxekmM3-*tW@^WB$7zJKR8?ekTBYSHpR;Fnb4P-$Iel}=i3 zZ=W3)u_<_WoXck?IK4~>b+PMZ*I*IEd`yCYgKBR-gYC!4mQ0BMq(lpzB~){NHNiyjldQ2$+tsSLy$%XqqVB zu|9cG2GSQLXb+yIT5o1-g+D{=R$2BZ4nDWF?TCQu&NqJPb*z5!B#?|Spy|oqDbK?b zQ|0N{*-`c-08kU=AFjFHO^39Cxap^IwEL{=4fB6rv9h!C?Mv{eompE8mp5$u4h6N3$(t z+AUI$9+2S#Vg9gMEPT9Gp4eXyZSqZVv$nWtZ^5A<(hz&mfju^McZAKA!7Q|nr6>*> z{8Vn6cSWW#RXPAX2JB}lvuLs>4{h>u(VF@y`fBqfG5(jCNHjiJP~O=ebL|#W8!_JJ z2!9E|t3+okJn=_`C0eux9=%#OrcU~Ou|BGnxU3yR&~%#%1!A0hx?!FzFb&kzI$Bk8Vnrb14nN?2|0rjJvG063s_=yYfm5#;zZC9rY&+V(06=RhmQqHnr9b zCk3cL{YP|ng+ZGP*?o}8f3TevxdcX}WzPLq8&Ei+qnfIw77>UP)!V}psnz;gC@a;*itzW%(hRAn z1~qog`*@6$V+zBjPS~4|j%vM+qxP@vv_3wG%QQ$x2jd0=IHa}VfF(Psp&O){PKYku zc&bvw&-p&&NLTS!VnkJ^E**^NInucADC|CFZ^aPB4RlMy%`IU*sbOeeXLtl zB6g3uxvQ~*^5hI`>5)QhG_AcGXT&$|S9iTf%8ZbpM<}23--ZFQ@(;_wx+CIEt@!1f^MzLaE>a7X+ zAJi{dv3makoJ}Z6e?IfeAh7FGiR`U;rPq#GYAYm zihZDSfuwF3YdyVCmlWr>1|tb5SHG;KYZ6saTa$mmv#>^rVpN!)1T!4>O~m zs23Yvc>siF&V`O<2AA`8(`!cTt)*Qp+KGGU!VhBCWZ zcLUaI6x940)EI{n{l?!{6=?r&;QX&d>W|?4;BEof`Tp%cv6q45Aq0);IA);J!%{1S zGiO_esk0}1NwnJJxE=nXo6I_!+ z;@zWu8jS6g?dGHS1KkjW+aC zuxOOVrmU&mm6xsY=nve=%%wkn1{B^KN-r|No14T-SQ;zQU~Bg%|y9lSc?QN=*q zE9}Wq;}q0jRFhnC4{GdnVS*7q%4^v{4GJ4J92H3(UTbXb!xEo`5Z6Y@nN@4 z;wLRu0bV%wE{keDA+aD6#<2 z#13^6+}ftUX3q_onNgEdu&&GO?)`#uFkkc8D1%?U^X_|Yt!enhVbf?mF?$D!19EOL zG5q~+yyuU*FCll2u2ynxpXkm?wpsOE=nDIB@*?N4%8>5u&+wWrzade}@KI}dn`|{E zR@CWHwX~(1gKx&OE*Dd;@S-Cdd1l*RFH*h7w=^}pcICTBFKjw=Y7`*BBIBJ5pq)3G z+NggLCYBKnOi*I+^8Db-bmQLB2$CIE4CDI0JKqV?y=7%#noBOfgl^Pc{C9d$~LZ=S=a)rKBY%!+9AD1Lf++3v)-vtryq z>+u#-#8JM8P3a$vI6UlL4VK2C2FiT(p-sAH&mZ-!BzVJ8SY0wiov@RdL|?XGEg3=aOC?dCrek9TQR62{dq)lc5Gy_mFWF1GYUAk0PdPWH zsqqDX^9lf%c-|P~;S9S;JX@LPR62CCNH=j@LDX7478>#6hZ37D!_-bmW{R7#p=*$c zkj)(DQ}26Kc}}t3Cf4)r`+L>d9Eya5pJlEU6p!cGQu(0fXn1d>oj^GgV4tm4>GMaE z)ytEY=y z@kLliD{ys=ZkqiS-pst4{H&HRHNa`26{}!a^Q=GCp_kf6ZY1BX1JKGtr5{IEH&2+S zNktDk@Jie1^i_%-ppk?=HXPT#o3oGg_(r z!dSoBHT2@*ds@)(#izjZGE=8z=SF+0L8DcOaGce>9&|Tx(e#Eaqit6dsbzE}a8Gx8 zLWZz z&2_dbufifqK9|*8?k0tJxo>hIw%SUE1w}+8ev862W|P3T+elyeZ=Psg>dEObydH0$ z3HxYZx{vPM_-a#qD)_{&9Y|_5>Ju7Zz1!ljE8O!T8{(>_Uy)lYKR2XlohniihE!V#B_-eM*jSE zxK@+m{{P30g@Bq#!b>BS0&@p-li9BB?gXKEeXE(5f3)ObNLJc4r84Ctccv8we~N&( zlwdqTR8>Vk#RwC~Tk`a~Cu(~cNWg+wwtp=4R~$!q)B`8KF5ab4b2z&6CR(c9AJJA5~@mk6bjqO?5W!&@u ze1;0u+vnh*_*v&$Yw?K02rwnBs#fKj_@?ZSCG=ETX&Pn4lldAZPJ@K%4NXCqVV}*B z8|>UNMD=rfY?IQN|MT)(_$HgFFH2NZ9br6iqZXn2?+pCkS=F-S0&a}pl3>Qmwsh3Nbc@C3*z#?@N{Y{XI)l8OUZ-kJ2OI`e6 za(hoGq(-(Pzpg4tukGzUBP328inu%!8>|rb4zeV2fafuu{C!MlikPd{@RIXhYD?l6 z-b`JZo6{@t(Y-9_@f2TgoUm{5F9j`D`~=sn@llyjRfs#A{bKQ7;rF)DLw~6Jkxuoh zCB0E_a$>~Zq25-ds^e}q=aew95dT#||ER!xz(L?e-UW?DTDRWoXw1SMLi~U{K~qJK zpz4hFPPZI@lo!TYI-_V1c41cc4hIjiT?f()G+jmEN6j8rBVYk1XbMI6e-MfP{nqM5 z0QS9W1{bg47oYdzS-f+a-Ra*7$`8zkpYDUkEeG{RAU^5>{z%(AzPYhT!o2WWjj5VG zvUoR}dbT3Vp@uL-ZSMOI)xdlW6J-lJRrT6wQ6szR*dSFZFD>LER8q`cU5)qGk(1YkS3OA{S=Yqr-2Z1T}Af zZI4ZV2Y=sjqVW#o>kk$YCKyjX5K+~d-?ZQWfm8^<0$J+n>U4@rb>qQ6B+8Shg#&&@ zsX9$&pLsSqwvfEz%=DwO=dXko&MKQa{3JPt9X?C;1vI8o3Oox*tTq3cc=h8K+lIqhMLjLG zrHUS&T-d5I-&F*IK0Lv}lX9Vy2F{4o$g=I2WY`=$NB3W$3>g2riP0aSpPYmsLg&Y{ zFV6qSLuk|}+StGC&Y71?~JpCO7b;;?bQg2yi@w;La6v zw6jl-u!i6QJyGL>ktj5&!`Vzlk-*W9KANhdUK#}BM`iz}$f4;8M%s-jp2grNK&O>@ zY4n;VK_pJ1>8OhlKDTbji4b!zzM}TugvT<^-NTMAD~Bd!ZK2f6m4Sin7FGT@34%)h zslmo50kx$)3G_Vt)luY3#$qQs6jWj@uN$u57ta%U*Ic`k4?$0R+P6<7>F)e%44#k6 zJ2!=MXF!FyCBG~4-Pxu_&5dYw5Q<&N-}94Y;OL+HV7X#I^MJR1$O%K}cd1j=?0Xvi z(rS>F}mU37Cyf+?^ zDy5C8nLQz$+pWiD43c1!SpCMYlahi?cZ`}&Cldz+!*UBR3F5LA1jXnog3h_u9h}}= zjm^mqb);%CZ><~8(-)NgEiT}A^_Iy`o0DAR>DgRNwo6FmlxyoolYc{FRXrnLM$&=!r8;b zsH(WH-l3TxvY^)OZRJaMO;B&dZ#KO*ZaFDJv>1)1yLP+8`kyUUFJdQ3y-)Y0-HIzJ zTvCFsOggL#`lsYh>HXY?;g%t_hrfdPSq{1^c8L<7X#&$%&!;97$iFYQ15Tq?qX5sM zERTI$`Ka>{6O)smS`1^+3vVsOt4KfZhkWs%xw8V|FB7(Hen`QQNLZVkP?PQ!h2knT zBfmqxNp-|X@4Y=hmw!d+BuzhATsQ9t#yH}I7)eWk09ye}f9g5?ba`rtZXI)Efp^kc z{bjZWhL&HZj)GEnPtb=l?WaJH;zMfY)CbH0K^gw9mtHAYu5wpeSyzmg;W#4fr-k#y zh#~{nm&yM2(suPh=E?1A8>V8c*H)oSX_l&T7K4;di(kYUKl;r+N5^r%F&q(91G1rM z@sIgHQLbw>iIde1Ni|Y^`iwR5z-{jo_10Qh)*5(Y{880EeS?e$QG-XmHlS?bR^Yg$fMU$1UmGGA3{ zyX{CK0U+w!k4Ejzuybpd+)U?r_Uwiv++iwxtInZ3VQ&HxYJf-WFU%bUijhc@1vZ7Y z@fkLPA39kd^IVLPYeO@5=YoqjP*f^)H}s^xY%`^T@_kNus4p_& z4Ij;8LKWbgbOfj|)Xs}5HX&>1s_ik8!w$?S?ed4Tc?`!)i;(P$flcUGEZCTf*U;1s z7gR&$r8-~yqZmd7Kiq55>w3uiG|Z7&P0R7eqC!#?V*|sX$kqnkJz?>^jl-L{2Eqxs zXpH8B&1WuN(n$uCsujyiSV!kdArh$d8mUq^{%aYT{(Ck5 z^%7`DGTTXoJUVzwnQvWT23go4&P>P!$Fl~M5+pr$tKl&XE}JixTKz1S+ajA>_I{5> zb%1=m!2k1ky>Bud3fF9HIzrSKEQ+byw?X$l8ETj4*vu$;}*xD3}{Fc!= zrg*0#?i?1Aw+=~{zUo`C@~(7gl?b0LHb^yLq$We|Y4Reb^wqn0iEksvQ6f)IUcQwJ zmb*PaFEIH{Sy3cU5&DqXvwh@Rm+E-Wo9TqeElA7pJYoO+YsLPuetN`#&FK7!Vb(zj zr~Rkr!^+o&6m%g;Enl7p^54HbC^gL_va9G&qYSA~U^umgxK2KU(ZOdwr=3z~)XLAu zx%NHJH{KZMV0C+RoUAmyb+;;0@J(JcWuMpn-_L0P`)j5^_uDeY&0mM4b;uq#UJeMt zC3N;@2jGOKB0}6lDf!=<$W@9&&LEr8e87$Et4H_@g?A1KV!PM%SlWYxDKLS(t+S}+ z8n1OOT$0y429m2pzoGj)M;DKbw`@|`e9Lt(u8i8BW2Kq%J`HzI%8vp_Kb5;8{b{OS zNTyX^VG{nrKnUJbylmU@AYO*V*~yGiI0rBqwLP+LX22gov>D{LK4l~Mkg<9H z4KFl2z*`N<%wFu>_vu<3^)3}Aur+yoz2Mv8b?-+$7bODy@D$f#836wW2qk4 zviL>)QZ$pDboLf9vAeGCR4vqxCSD!JQZv8MloJ2Hos&7XfUnm`JP_O@0+2Rz9)Hj+ z4Sq*|&W|J(C#kXUQ1Joz7toSNc4Ms*vh=bC<3W+@*;LX5NiHGyWGOFBAAk!|1kC-E z01flG*oIo}RH++o*Z@E=8q)Cpi9dgR{@>W6@6*2_ta5|C`wlh2GqK&w{_q594^}rj zi41u)0^doaP^rc0NYtPS9z#FvD+#KX3E6t3sQuAg6|b>-bFXjGffgFyV@F$h z{jOe@^w_5mb45%Fo9K_mwa<3` z;vdF0;teH>BQn2FKOM=$U~ptnT?fLrFf5~TXVsS)D!-7beX;WOx8$GB;e@h#w}rilx8 z9(td<_xjsqNsCaF+br3o*vx&w-fSM{QBDnGt?QQ1+v5E>b4-?xxPv5i=cL}5HO4E5 zr}yMjPLlWLZW|E}$zP86f4%Eb$~3$-46Cg{2dB($a#6uitpF2TKxQMezH~2jM*uE?y%S_ z1KV#zFdSC0uMZ>(TJFy`Fhm#Q@ z(a3m2Ov)0Y1dM)_<-fbwqQc_2+-~B1yw=OMg^Lhf91ghL`zpzlKc+7EJ`&*lPOkde zZrlxu06*^)vy1a1=i^=uQO{Dy#MxhOcbV=N0pyz7lP*~|eHU5vW`xp@D}tW8S&I(l zrwwwcq?}rvw&&voH9mU6)bR3AC2^)fjil93X&wz}A01+ry-{P>;{D?+mk?6%L&v27 zciD{sHtDskEa?*rxr85y0Jc(8-P7`OJx3-VxKE#p`W^rHCs6VS7OG((N=j{? zzlOIKA9h;}I@AH43$Uly4mW(!3B?Q)MllIJ>UmBYAvvHA*t^yqPCfe)k*Ury@iLod zJDNR8Xp&1sKSzFO^joiPDyJrmrENz-FMEVIu9`|*;~%kB@NMgQHy_g(kxgVtNurV3 zMG%jsrrU$5Y<=}83@BOY>Vt<^)LyL3SVsJMf8ypfc*j}M`{FeZ7&iTSuF~Aj+1{Ks z@d&qEH4UGUL4}t}0?!Sp0agkISBr;rUMEkyE{-@DNZ|4&@QfA)SG*z_k;c6hBBHgh zTzbI|Jtex;C!aRijEm9E(j|p_i-+lDMS@Ec7O2j$-eaErJdR*-#%*P(Y^BcP{LfEcO+M3bPX>J4&BLk6CdfHTYO=18PM5YXo|9%sZuZ^h-eoU7LK%` zq}lj=2p&6GeCA!@F$4*9CHI5HQpr(=@2!5=_0!uD(}gTInsO5p6x#@`eC#ASn&(O8 zkuikMzO8-Kf?Vchnt1iZMutg~ex3bu_g$TDG=odNCzQHX7B7Qi>8UXZ*w?Ndixx9~zPNkXUmS7**57=&%3i-YX zb@HSt!9mZ6KQw)7gj$ui8M`mHUrPo_dd!(WbU+wZ_Dw3Wk*^YYFDzJ*g4K|=k*uOA;sk# z(%NjfRw~QcSbRbGZq(*Ko^Qf0hiA!5CIel>(#Sti4@@|AdrtOFCI7I1KFl)RzoE=Q zXD#?}4Ir-cg4y{sX_RZKX7@2DS%lNdtvwqQSB>PPZdHrRHJoJYc~T%LWnm zDiEA`Zi8%Z{O2#7A*(57-l|UZJbxWZQTUzU`Kn!16!Oy2(vmC>cKDM#ma5FK=?Pa9 zy`TgapKg^9S9OJ}O{9qXF5P!GE3{|_@6LlXg8!uRAMSzyp7F@-F{NA0{=b81A6JzV zj0(?VGH%_x_wl29Ncv{`{&=Bko_hMz)vky{qZaS}H%iQp55V|_=f3BMnTDFxDq7`6 z@jBkC5uzPsXAjc+F*bi(9{p{BN}qvo8q#jg(F;u;q- z9OYQcwVs%)8%a79O)Cep?_+moqe#gz!>;&jJ%nxjAkWpWE0aAdty_Gx_{5PPyW0Ba zP~%8K#X?kXZ1Gd>K5cQmj3t^g9}#Cor4Ln|v++)#u)e7Fx9%7%fDDzg_6cgQ3I)3j z3@3h0bo@cIz0G7mtUIa=CHCFBR@H2QwrCUCi@n~!qkAm*mL-CxQ;wV_<_-~E#a#JzgX1x+*>=Y#;ei({C)H^YJu$O8CYLkzaOS|ghy1paJPTKr3$Hs++7wM=yZE?3(5<-2j3@5OvLy@L-S)1S45waJ|XCd=(j7Y2!BJ)XluK-0e#Mn{tklX#|^%XGglaGlrP6DED;Z zDhnq$E7R>!YYx}lhf6U0mG2$)TLsAd1(isG=fWVs^yAg5OZjQeujGD~ZAavuB19iO zB%qxS(}MuEU%_JwN1h)tB&PyD&KS_YnqY1c?jRj+y%`z=}Y0b`(G&Yi8AS?mC5p$Nu-8tYHHFC2Qlj?Lc|>*O2b$ z$!0>EUGXv)=K64u*X&J#)YdSKi%NB)4OXj_OA0YJo6EeRdkON{CPyUIDC=pd8*5Ge zRDf-#L3yMXsBB}8dkW2Mm@AnS?|+&Y>mU#7-lod63?R06$S%Ge$K;-oco;)gtZpIw zR(jxKGy3p5d-T_~AZkE?3ukv|=&D2g?-14Gj^Hn?E2Unn7t5sUA&da0de?qz7TNN2 zh9gnb-f!th)|;#6BnzBta?IVK9>#u-|C6fy7a23ma(mf;(s`h}A`+^&ZXFruB0MnW z*ZU(V1ZXQ*YK72BAXM>&N?9y=>s&|M@}>K&l6`yh#S>y;l~RW-lbt77`p2uE>spQ` z>H8)8$0htfn~O7CCjTeTW{n6D4x@1O$fjv}#Ft<=^H#r!FG|=ONjFn}WI0o7TW7b} ztcyYIF`iFT`i8y4<<6S*{TAu5Zv_WXu>h2CG=xl!> z*^dApG|X-ucSg!S+`9G`aw3o_NXA>>8>I%HZ!T@asP9&LLat`0&@2>CN`>wzRZmc* zS?Zg4Zc!?Q3rI*{=le*EiCZYIX{mWO9breeRAKqBCqDLEV=mjC-?`rRSJLNwlR@!M zoL|H0?A+;Lu*ougj$-Yy5mH}CL@K-}2Lgyof6O@0DRSG%xV-&@=0Ga<2}YYcD@!O$ zk@3BV;2LQ^IAe@TuW+%@!B)RUdE?n)iGxIOthv%z;!!q68NQFEcB}TW71@mgO`L;n z#yP1gbiS6?wRxPI`?lz_0K2ox)ssZKp>(W-^^c=l_r9|;rZ-ivVP1PBGfCHIzq9$x zvG_vNVNt5)?UQgwrii4KUQts)om^bmwoeB}%KY#%6NfneD4_!NlSp2*n^PGAdYco1&R)PJ)Xf5#fC|YfU(kz=67gw5AItE>j)#A*LlJm{~^Rf9~D)R;50;FF{X?fh}<26PV z(RKZi&1Oc$MaFp8ebl&!Av7s{d%wxondv$Uk`1)-%jB97p^E52pY?R9;aKobg8 z3Vs|f$g%SvC~o}}y2i*Kwd~3G+2PmshaSe=4_QAgq^2CczB0BmVM_w;d~0ZEsPnR` z3pVSY{zVyWS(9y*rt<1BHEK2CQBgpe z(t5g1DQUCapEQJj-YxEkRC2_)46ha0*u$m4fV2)3>Wj8IEiv4AQ&v*)ZfD1t zl?VKDi@?K`Bo)kf;7uRYequS!F+}R%meQhb+s6Y& zkXqKEiF6Tz9e%jlRtlC{8h=Tr?ZVmwD6pS_>hofE@xjhQ&B(h`k9)2a`L~51E!BAh z51d16dqHnnP1=bTo?(BP`0h71JXc?Oofw}%01XX0ecZJ-9#=USgW4P7c^2|U0p1Hr z9s3KO^>}kutd8cy8u)S(?7AAT=X{CY`~!we6fEA?Hejp%F!(K?)9D7;>hhOx3GcWx zKh(@IK_Elp_thlDh}zf7?5yZ7QipBCjaTJs4Zyh5XEiGy3EIm)gPm8t(se&{+1wFh z(KcZMp4J$6O~lLE6R1zn^GM)vj5X8hw1_PeUa$KIy64<}jkc#JhFzX9%nQRAD*oANvl!8Y3T^*@!{S5z#bo+cYK)qM;ZXA? z>>GD25v~7H<7si#_MT|RL?xapzmNXx!sAVU?Oa{23goihF8MUlNX1QP1&iPA?(mq- zJWJ<`#jh*9{e*q+r!-^u1KD!c)*;pyJY|yc1X1UC?DI}P@Hzegyn$JWzf`{`V}k3E zxn$Zp#CP_oMK|=TtcXMK~9ih~TgsioHrBlT<^h{HZJdsD2;rJ@? zbpjM!zgo+1E}U>k%u?8Dl&zBzL)h0E;wGfOzI`hj9JV+90p*kSLD|(f#m9s2w`8&- z9RHL^S_=@VH7I?oJbJ>}h<_3=P7=dwSmj}D|LJ4i7sKdJGFr^8O-WiM6n=fx;oh^n zHa(zM{kn|N)fYlhzO&W7aguJ|h>o8DLGYcNy{yPguRI=I75QYhHDA>9s7{Dl9EcgF zd)Rhh8pF@yIzkWbi6-KrRW6T9$_@uHG-D6hVPnhag~k)#1`0;4T!-^nF2rP6;(czd zKJzF5SE7--(~moaikRPmBEd=3ZRTajr1#_ChcABTxP@fa_%?i@1(;WAok5nbZ8CF% zmMXOY=m@K|J@m-jvg6B#7q0W%ugO%;mw>$AEsLT3U|+1%_M7CU$*ehXgZCnw2)dh| z*1;Ezbmw#oJ!~eefER;|;_IY$Wu-QO9`4=O_0qC{u5YJbTFZ}r|0ze>mh6nV=eGr} zH4!~BYDsCWz8n-?;^EdVjl*Ns!NObtENX;OOMla=sj~aOv1U_chM0|Z!%qvnw9oW- z_*B8N8L23P)N8C7$)i=RELWOCYoEe484(sYjIfzp7(3NQ%L~Dwq=&YXCAXW!D|J`T z`z0bzOJiW;PEyWmJ&Ngw_y-1b72?-K+S|?qe4Uy2CM%`p;$Vq``~XX>>sg1HFz-9b5h#yNcj_?i zhX$XVdOv+D?plvzkW?3eNo%@0=y2HPOS6M9EBWg+P5bu6c}<4@f)UGbnyZo=u>qOJ zi_O3f>MU#Y{8S95T-|9>lgVR|rE|~G17lL>#1a0<1R%vlu0PHe<#xQqm#)d;I-RYC zdAzW5o0U6uJ<1mmB+JF)1UYo%hefGS5C}bSu6%O+x()XbrCa{yg|Jp$55lP3 zZ?_|BrKvJC^3MlTd{ZpQ)i}*3!W%^k$ARsb(>I4dA14}&K9LNrog4D$_-h_SM6}(R zFXzVlEfB8ojIP3x+$Kf6N!L{+n+a5@o?HX&3)IjZ)~WN3d(7%ZaHs}B+-yVFd3oHm<(X{C-GuXgJp@p~@mytphXKotJ$P5=1~itm>#O^1dv?=`dAPYl=i%3EGx zPzYwau{>!$he2PZ1YWQP%G$)->w<>2=sD@TELGZpcCx~H@T<-rvro*$xt;{)Y>U5Q z#K3J0x(lU_e!lfm3EFhxl<;^OuL9tIH6)Sy>K0gXPlJ2y49*)ri*tKgZNvihFEkKz zvnzA)=Djr+%fZC9s&u9;ne#j4bDeD5MhmW7e`?5iVf}8LlHlpv7MJo1RI-9>wWdw- z#c61_!qhjN93{)KC3U6ZVCP@Eb)lb4mgO9ZxyM_FktB6;Z^b3b-rs_4=kfLI)h%W4 z-)aUQNT2n2*u&IlU`;RoNOK)vID$mOo}3D1b`~UNuzMu=w2_l`|NeT4fWb{h?w{?c z?5QWHm$o;r_NXc6dQ-|`R@6j$L4{7faOpG7J?Np#m#Ede%o(9%JZ=de-^~g(u&@7p zJz2`jc`Po4s}^+0wBUBhT?Gofo?UETXmq#9^?<8Mq|6~NcjK!=x~P&zI!pn|n?#F# zrVW!`_DG)$qwaeTm%4ooj-c&5>@SbI+e&Y!jX*x5=0lVr8IAqkOsYfjn#N$y{327Q zn?o9E{>`J@Q^;IqqVU)GFt6iG73w{({c8x3+ zo>`rizyaTp3pviTdVCnesp2(RC=X81$QbOc6XN?v7`DbfTt>8&AKu9we!{3z00o1; zs-`Y*U0es+&bP{$QEoMzCG>=Q?G?>Y&RX9fR3&m6Xkw1CF4y#`x5=cRpG}0i+v@AO^P1bAJ6rioBh25c`KH?&ogC%uCQvwv-j%z*E~E5niv8ohV5tgL z{AqC7KRFgM#O1J!gmhLr*QklFjR!OJpB_b`1lGRZC{Da3X?N9c z%CS<+h$5StS&GKGFUs>_u~zAb^Ve`@Nkt425sSRYxvLRfx9ClJrLSnhmXHR;^z~os zU@u^pj4|`j``8NJ8hbn4Jg?J#fBW|Xj8*n<8&!glugm)@wMOh44vqVd(9`$3pGb>2 z^f?ypPU`xjo4f*117ZCq#9OQF#5wTP=c;8*c5*-T3tlhgsAygqbTD#7O6(LIE^7$P5U)>k(mpZ@WvC8q zwa9G`BJBtIud?P^m1nSVqSHMVZ%D2LEyjILKcVH(dGH6Rmn16j`}5tO&8nKNsq8@w zkj^mLP_O(q*^0upi7w}|*kLWZD#!C&#p}+3lHsdgNv8r_vYf_LV@sb59St36bkLPA zop*`;tglxNLI^}^m+DQd)p41KqPwZ&+nJ@Qq82TQlsy)>eXe9vr?BHF9rA4U6Rj)`m*TLr61@C9otG&?hFU#?{95!6Ju zNa=Ch-G03<(js%P+K;#~6@UB3v(qrQ_@yuI#;M|b-dJ5_!xjqW@oZTipx5b<^J%d8 zsY7@;{fuZ7YhwflJ@QM6XMj|4-n&~oH}LK1n)mcLJ38L&V(ygPeyRhJI0IjvKva_V zBk`?g>34}5ftZn~9b#ON#eBUJn@p3>8O!m)fxq@rUL8ypL6;W3OtIS&g-}i2-x^lN z?-M*suOB~BO%-`&cQ0U&=&(+aRlQw2%rNWC!3g`0j_^DA?U%lEvTfEoT_ln+QK;SoJP?Cm(+i~IX#R*)0cbAa%a-ka!-us)(&yHs5=tdIN#4| z#iJpDT~2mMk|X&z6Q*qGmx3P#ddw3M`zuV~H%2rYw^_Zn*y#TcT~`?v)znRnykj+64BbB4Hawsdp$Jx+9y@eT>U8^eC>NO=W{Np$uJ z8lRb%#n4!sGcb;Ya56-`F-@(U!Z)3u1iMdsudGHUJ};5goSMrMoXOIraz2=Q)fI$+!OvZ)-SFwL?_M$TTa*V$M|1|z^1YZ0g{*W@B?0EmAmhP@4it#3euR7vRZ3@RG`o$$$zH3J3m z(9@cl8e*0RvC)Nu8-{`@O641h0}tHHr#Ws z*ajsO*O#>VEAB=#n^^)5D*h$tn&ELQ8eZv9Utm4By{+-k)J!C^tkP_tY;<4m-rKMF zvD$!`CWBw>KJKw}Br{`{@keuF+%9LX?1lqfa^=s@t9NKO#E7AW({E7yl0Ogp;ML~% zX;ooguR1k3y@POA15@)kSA%WmLOwxEx~^yEFo%8l z@&#+O2{<<#sbfPt7=66<0IhYZM2BSVu1EMm;r3zLKo|a_J})fubnNXi=8Tg6huGYM z;w4?OO_$N-ZfF{>!}{5{oSNr1f73eaMX{*I;dK7>$!T2-xZ5OZu@!GVtGVj8!)+_@ z$$9+IR0geu4qL-~!Ikd;@c^9LefadoMxw5D&2^gI-7f+@n;;o5F_Bz0=L_*5bX2%W zyBf)4ve=y?MhlkXPJ=!&lH)xmbgF~dDmDM_kI=BScVrfvbD6}~b82m`)A^l-Jy_uR zTv@&rAdz=DUy-A)xq9%_I!Q(_ZlZT>5)wYzIUHZa09ggv(xlTZnsPk@5Gs%7G%M3+OwGrg zj)|!{VEaBiwv*I4>7TxSAxuFKLMqBHLX>sp20x6|q}zNN#rtnTy|Wky6<4jooEEBY z1zYzx$lNX(cy$;LG@CSauNT5A9j;-%^Fl4wM~k&8joWwM|B&*T3L@ItbbD|u5uCQ- z>Pl6SGln-tTgrZ6YnTlsjeOOgg~?wlOKhC1MHDygUZNDiHc{u60wL>Nzoc)}gInxZ z=j~^&t4u(0=ko(KRSyX;ZaMu`|NgHG{_o|tPEhhmi}ghw&e98y%Xq2j%Dcea{f~8N zjV5}zTK#xm6H@t1Q`9MT7n>51Qf$zK0FBert&RWh{e#e8x3hu}=pL@=GxuJUV>OfRlt%APU{(~%<|@Bx#s z$*^{Z9v_+A4-pKgFslrv6XIyw)i3E}f#;A2(rmP{t%|wV*Xw<;)kplD2+w%%T`4H& z4aVxF3HC3x|ERl|YCs`sHr?}XdaS)4lHb3=_F$5lH53I)Sxzvxct^;pik&-y`T&*k}SA1er-&*N_) zFAC3(`N5PT_!T!9XGtTr=>a|Kfbc1Q!`&xVwv8X6Z04>nv}v1Cy`yUTPVj5 zo?(qv=my7m`PSaz`z5IF3;;-37LJ?x4E427OZAHtDEq=H9)eZ0J`gpY#31Zl< zhz!0FJ_(Tv5V1Y87$V;P0&Yf3E@}NhaDDA6t?$fUqIJEnB}C27;Y#kH1Z0Xw0;hv- zP+nc{6l5lhcy3lTdR#wi06JX9Q^frb8K-De)7lQc zE5$9sSbEOrecUw~cMtc4ulwY1NA|kj5E9O#eA6rQn_Ipfc3BVAyZhjJ{QVyIPAtgKT;%-)2}Neg!^(6Qzaj3_6fV2zxF5xnCKOu2Dv@ z02#h5cVFn?kwyeg!y?v30)~Xk#_QBeG+P?|c$*mwruJQoj#oNXJ0jUf!n#?PjzdmD zxr1t_c)Go&tm+nDyT)!Q$qBy#@MNvkdUjiK{?Q!p@?AIg`m(oU;!@&4;?crIx+-c` zd859$f2+T5Iotw4wFk47l&^Zyk`Ic!`TV z5}BkC;a`+J_Q{KXR3GP5rFXT9FHzK$>2;n||7Xwh4SeIAbr% zoD!ff=*8f7&AXMB!>`nm9U6VwnFcbBHl*gf+||&C15`-Fr&9bdIHEfZa)2&k?q$)K&sB(U z>aVc&@>MM)FZbIt5FsJs>KRcE96=gERtzipDS(fmQv;)D<~?Q9X!@wb!nJ|ESR}yq z+~_1)EgYnVk{lVX=@D)Dazgp>d-6=??k4YhmH7o9=mDnE)u5hCTtPl_?0Kq1r!4G< zY5DbX)7E6giO8}p9?Xxn%V>9&YNHwliE|rgMIws|#((Iob69`L`Gdf`+81g^3SXdG z*5uf{V83RB^(>#Ftm!tv@e4>%v=5)n^*OgFS;w#esfLCiGrY!u=aGj?0EK#`oZz`~ zgSeTRoxL|FRMR<=*25b1GM=7aKY?2x@0 z6T07# zqn7DRr8=tjUvsrUfswO*kmzJq_GO+QVc_N0mHyQ*Fx)uc*5P}NPIYm+RC%(AoXfUo znzO>gwe@&LG_J)Ffp%SICCW?G^Tmg-=jIscdH2arU|%^?PZef}G1s%O2MBH8!C=Ck z5y3}o9=&5*1plp$t}ZyjdGO7saHrUvmSt(5 zL?vWLn1~@6ukmPS^?M~v8M6LL*`_nd?GE30Qk6`#INvD)pA&`QfF*(x!$`m4FtiYX zIL69FqR%Ve7}&}Ft5`f2+w`TfAmb9(c{akX(V>TNrGb{&l|=+WNgV)J-dUp`EH|=0 z0{pP#$0}^)h_(+qfD2+QeSU=Y^^3KhNRW?YAiBd!JC!5cmbd|T9vT0)F3=7@V|`Lf zcChRC9Q*=5=|qi&QtCc8RyF}gPC$Vm%G}YqKMJY8tQ2F@{HY7{XC;MO)M>iA` z2_N#^K`~nyWn2uFOR$T4levT)!8bUT_<=1i&-l~R)wi*-sG+9nMqNzuGiKmW?LYRX zD=eZ<{A6BNY-L^c--9*pQf=GO7?tw~ilCvoEHcCd{e^}*mhfgJO8ES7K-+FFExlJc zOj=2!L@g662$la>=?*B|MWW1gUZJ*W5JAyC z9I6La!eELonf4sFmUoyXY>xRZX6)E3x1+EwgDQq90=e<4N?(*YJ^Pro!LAG(IAOqN z^4c8tQzoeKkq|UL8KHPMnWIg9eewzx`N$`p;o}rf&MVLkuP<$Mda(#Qjz#NQ4m1gm zv+*(bqU=2I)KQ#)^w<`+I)BBG`vyy*Wb!$qNIsK9t~d|>Dj|#qDRuTkskjP6U<8dg zjKrXvH7@*u?x(y7Jw@1JFRR4ZTs{VV(5xIU(?gCJ@LhiV{VPSS4H&(|man9%Rf% z@JZ)ze1{H0;!VX7pk?anMoEaQd$M1=NWi5jQsKp?<2WV>RYK6NQ?p4-W;ZeSz1J{{ z{y3cp)j0u4KHDvY@`3PmInX@q!cyEMoZ zutey&ik63-V=PTw?-rMLuhlCuwVXk#zgg?sM`slCMbz0O0%$Znb9<|wEe@)y;Wi-q zc){Fq7PH`aI&`BtOz_kuqy4SNw2sSDdcdCCu;6@ag)uiTK_Ek*^uF_6?Ji1k91ryV z`IfSyHSPn_oL&wn*{t*GAlISQ;pnE7p?PcTS#0a7b1xR}eVK>8#OA{`CLUe1W;*!t z54Bcl@RK7$Ggh17H%D6SJxAaYM#zS#tiO9yT~j%v&EbW``WTm!`bdANPk-#kd+|ia zINH?wSQBH>fp<{`UzsP~Qir!n)!o;@XtZXlTQ>-xRO!z0e}2I~kpC!_-zFr3yV|Zj zuEXnVd19{sz3-od4ph;8y z4FSvmEKmz%Bz#%;#+64E0qHE>Vc7>$ot2O7342Gb_x5*Ch?}zXF=uDLU&#aKFFlA7 z1Dauj{rX#Bg(pPdvjI{g8D!|Az+?1yuPO4~{&bU=xBH%3rTe|CoBfTVo7*OFGOtO? z#D0-VRCNI#W`?Ul5z>eYl)@bY*W_76&Z(0*LBR{}fM$lzMPk<&W`|G|ogCbi zn}+4N{6_uP9j3V0ZI^>!6>EpEk;Ak|zrg~CgiAnRMwZy2nKsf86K*Lye?r|-S@-E@ zB_$&&BC86zMVDnS`(>Xc0$CH%bP@D>+y>Ye`VE4%D@oDVq)3rYyZav)+_-V{-R*8j z`yUdYN&*^#=K+A+)#wAdWD`{#Cx^*!T2^RQ)Lwa;uEuc!P)HoCkcmH0>`$R&)jfdB ziPSe6RoiPKR@7hLEPeSQMUrnLRngQr-rMfSqn2~hW|P^fSv7{cx{xMA-Z`qqd3(Q{ zL=x6^`_T3{VRx6gI{Ni7;0dFM{LTI4;C)T^QB#+dcA_VzW+3z&&8C5f(^!iIG2 zpkD-mmD43xM{LA>NH+jvHscR!tOG&sB;LfR5h>lj00S z8PCprH=fI3Iu-kmo9u6>^lzwO6hm_k4F%<^35A!3S!~_k_we^3KSux$=+5J(^?U?5 zc0ZvpMFG4MxEjfRHH4RJp08hfrqUCd91EE}>m=A)*8)#S%JM=1QG$7CO9q=ZP6jehceGo87)rlg>NO^&!$V+p9XRu2MA(w*|Pz0M~;>71h#X#2d0 zB-c?dVU0-Xh?xJWXvIiAgS9hVC&&8zy)Mdy>U%(PNqPAQ^VU`UDv+mubM!L(1$R>; z00CE!cspvpaJo&8;rjf2TvN1{M{oCnV5uahOcwmBUH+{ox$}my{g&(n>2M9lvw#uu zN8TcBRM8&Wj_>hn9EwoG$%!nFh^w;3J?^E8&&+h%?B9^o`r_F01A-}!@dH1s&15|0 zya_kYwVU0C9C)%%(g%Lfy5(H8K@|LzHt5u^j(XP^jVTg&o%rOY zy>aGJZW`{!7S-t89;fR=9t%>iwr5e=Rrq|a@`zRLoRwCttmL~hO|_-AD}O`e34Jx^ zzw9Xw=-4ZQ+(-NxCK*A9_RZV{=nlOxk(GH>n5`{(d5p)=g_?%F z6Qzv(es7upe1Bczc0y(=E>Gx6Dl7I4I4icB?f-Fm3_-GHzG$D8HU#~Hg8%Kkw))(D zb+Wbrlsi1cKAB7*9ih8bkj1g8B#FCa%1+5sMka68;8$9;2?sBd;#WVZ<73>ckK=Dt z?)xFTYX(LuV*#=?k9XH>7;o`>eBrMgCC|MEq~oGb#%=D8>PZA3Q}$uOG7U zIO)|50`uD=pdA--ZNZ{Tc@D{G9&;?bU-j~|uLB`95aNpBHJ>pLt&JaccKZ5`+hP^^ zY(|<;ml~XKVbcCi(GEsdnRI|Ic(rDDzB|cgAm&{0xI0<=>7B80UR->_D|q^(O32i0Cnd>2Eg-28$Sp zt2Pn_-?1IK$K%7%BU7FCo~lNjvrhdcoC)G1mHtD9$5AwOhN~F)!;sDTxX+~v%pZIw z0=WDz8_uB8u@AN8qVxVfKqiCA_|LFF4{S1U^pRyB%p0Mzk2HPcobBOM4>;82(I~_A zJm%-yaeAb}=0BlePDIzEUJpu7o3-qI+dZu1tq!82M4Fy7$6jCjL%v_jR&fTh8hf!E z+f?7JjTy*{=fsIZ_&R*{`F}}dCg@5{_vgHS92Aw_`=m;fcP>vI&O5Kt%e4ON`4B8}TvlznT0U2-x`Erk9_li7el1X>pErJ1@!~kGeF`6pTU^9c}qWAer|LVjg z_`Z_P(PaDcC(}INuKe)sm}~;Mm3$^Zy^~kukVywO=P3!xh^JfSyjPVK9LOQJGU|&$ z7L22fwJxq9>8I@f23I5gT&&$5x0V!M0MB+jvM`K=E2b}<+sALv)8QkJkVyuoq>{!s75FE`elDVb4U%{|F@mO#jr+pC)}D&Au3^t)0G0e@e2URQDkI z&hd89F6X9CaJeB%REaw5klM>br8mKmYztX{H*8<%*SD_%bGz=t!?AggJ% zPLi0*GRbjoPNw4air<~_H@3*WIGDo8AJ)oh*u%9Fd~p(B+CGH6FB`~f?j15+Uo!E4vq~W_PQ+2$sf6Rxq5=e5n)0gBe1oo~ZGmcIV}n-uMS07GX1y92 zw{==T@QV*2(NvJ2=j0Jj%31X=(Cd7$SQJ`J&xjG;wa3$ro+G%`D?a@cZ6RuRb-cQ2 z1>fWhxqKPeb5f%3HJHSDt$XZM5clCKpqAUd#58U>y@dOf4HJ4ctxPjD%`R9EW$yNa z7xOnT<_Cq4_8PS}W)TVfX4tF^%j7oI0GYuF`ZF8!V+Q+FC`NWU>$EGqN#jGkq{-tm1vTR-H>Zy3pk(q>j^yx{q`0 zt1~Vn%CC%FwZx)-I20s}yx1MK|9dgm$C7GgKlfte=V^uz)Ov-#nX+W`(}r{$zWye{_Y^&%kfpcXpI$_O)qw zkS6Vwub_!4$G*DSLW>Pr2>HE8q=1FLW52=(ATKwgQA*%7J%b}Ym!i_6lyOzX^qi>L z_j9?*H_aw&Dta@Pj^UvRKN{tm{&A1nGD=v09fR^Sn;1e&PXrm&Oha?3g;PMbF0$TO48gMRSkG@4>HYOYT31m+aEc*B(VPPI|0w)J^p|l$V)~ z)(bbEWmql|KOMQ;)1fqkT*w&t+VPZkW)Je$hrCyMHg=8jcE)#dO77ThkhKS~OL#&j z4qGZy7VxXY0%cV%2><;kca%}Vi~BH*i@8`Ug!)wmbKTwXx=6aXUhv~p&ucoaY4KVO zU8H?ZHZ8W)FQ-(*^gko5aQAhXZ!eBwZx36_{k|_hT-33-!HVo}b_&p1Bdx?LSf4Dm zc+}nPsH>TzwgYbxh?|R$d;mwqyM8o$ruY45 z%Q`fL07=+p9g-?QMv8!_gD}b;3V>+52vKLL_&i+6TSSrcJn!l+2x9woIDNv-4@h*x zAFhIh*9UQF?e6ff&EoK8X@nk#IiDjEA02Iv<#f3&x3$S0HkGgPc&|r8I=hmT97#tq zg@s2LyID0GAmF({;+}eI1At4D){Eg@a;1{1dxaNPka@RG4Rcrw{B6#C1`Pcw2si=L z?XKyt6OB2Jx5{LouJybWzwIdnq2(FX1D92|Xt_p{=10$8<;FYWZ80uKZEE>Gcg%UR zU|CaDMbfWh3a(*}yQ;J*TXGoosk*nZ?d3A_n?ngQHf=;#;><0bmBev&jP&EkGA9+2 z1w!XVNS@Sxw>S|Z*obG&VV6bqiK59qtH`1yDLEUK(Lqn{7Hm>GFI%FrNgdSv$#NMq z^?!iRg1<42GXZFVg}?EQn5-LAz0O-?O-~ck2@2&a)XHG=4>r1&jI$(m%lK!h`6JC{ z9gAf?ZsW7=-?RFErx*_hihid@=^;mL1Vi{6wALRD${ zlQ^+fdbZ>#%WwUBOn3U`EM~D%FM;v6TLP%R!YeM@2hfFK0${rgHZ8&38?yBoxWU&j zsT`fnFDM#hTo4dEF|X9u)@^lZLe_{v@%_Lp6RCsNIeFdIJHdvn!^gp+wr?4Z&=C7! zUX!4skk3V-RUyjzDpjT~uEy(0(aPA5Sf3dsDtF{q)_&x7i4IH7U)7Osw^6MNHo8Q! z%Mvq;FRKT}Y705+RW;&x>G7Vf)9om$(v9osy{aOxmg?>@!$D47qkGQvFrJFEz4KOFF0OS{;AjJD- zJhLCD)C@H@qdkD>l=}DR<9y-~>9{-bwiOm%&T)(rPQ~5}ea=e1>ywhK2bv}f8(I(< zBIqql_ntF@4bLC-B7g)afZa`k=dnK+cV8+3*C2^xN7+V-vf$e7hHq9GO+c7kvLsR(4Fsvju5s`*R30O zfH3E(0&UNepV=WZ@edA-9v4(?UN4&iS1j~yHI-6zm92k##+JOc`YG|`{I_?c*oidr zw_W5k^HBg%XpMa1dMgvOMhLof+MQ_V;Mru=*DVZR-M50yFxU&>vP2+L0MQL(*XRDA z{#keO4+LHxk~t&RqIOxj(UL6VNE<)JW?v5t&0;o&lk|qKnb{98)=9N_->>)6m!pI9 zg-!?A4Lm!yvH2pt?={I7kY*+dM%XRh+-(UnqqHAQm8N>07wgr0V`OT3ygwqio2{2yF~z63bgeMQ_>`Z0qvr8) z=U7KwbL#CIZD*%^o9D~!dyHgXOzphtH=_^#@N(n6q43H~x?LoE%<1Mulz8tbEVbp1|B2PoT^^1^2~#w8|S$?Ma}8kevM_CAUnrkKQW0Us(f%T=Y_h zdu}G!7`GRIHrLq;(5;NFUyeBZt8Rf5o?Ilet5ftDl|<5jSVxa%re%@Sszl z+B})wv5W%f&35D~+IOP0vMv*n6ePo;3oep}(mA;t&k{b`dbVP4iUxhF{vn)#oig2S zYg)-hg)}>8Xgz-`N9vT;>C)zypnZP5Jg^(ikGtfaTxD7{sMCxZ%)^|{VV&i9pmg1l zvFgVc-)W%JP|J7sl=B`%4_twTDP|qEP83eRdiTtjCc!wQ`q@F{023PA8H$J(p#O2= zKJELIC9e&^k^tw$V4bBnrGvcaq0haIVU40=8dV^!TlzjPNq0)W^?WPi=j?KnFvuh8uw7Yh&xwx9BHmJ* z@3Jf)peT)4`@-_k!qLP{TbtjBE>>@sXZRgqPr*(X8(~l4Hcz)}>BQnlBBNfy=QV?@ z2fo&Mx)XO(gl(<)=`?^loaekNx4%OOg(WoM;`*YtYl;V^q&M zI!MgzpH<$k8ylsK=!8n;ag82)X&^P$V&UjRjN*rX@^x7~F3gCwE3J(_$=`ZF74xFk zP*%vH*ER>09y}+O%~QuEpO3yXNSU#zMSfo528Ft7)KX|kMR4^2kzDH@{~EwG%7G~0 z+iJ$s5clVH82Kq2B7)&!wo7@2BA~6@n<|Y@C(goUWaqFHt3k4)bfP^{f@8%Ril+Hxv07};>4-;%`+*-HFJZ(-aPvPkvh$F zJJvlw;;O<{w9^6_rR#Zha#qV^Dz? z$Xc9r{7li|e8P~MexsTxwiCua90icI8m$-S<$Zv3!Dy#4uhH<~aD{n~A9Y!WQO1?U zKG}Qg=Mc167hx8KEP*^@&@Ztb#aJSfkQF7d`^#8R4~0eoP^rp<4APd?U~8? zPC-VD4hl~M&ZjSJmn}!h!PvbauIITA`-X-SN)giJhFT{OtTuO%MK{&%V3ykm?GvS zHh_ks3cWk?>`Bsp7hzTMsZI&+ok@mUelrY4Z-9Ib#P9V3N3nGBbn~jF*jYhRSBqyF z)Ox1@QL9m3%un80E?(juQyTc$D!X=@Tr2nCP4^^rzf-5ghbe={1H!xs0B7t{zZ*0W zq5}APBY(TF@1N_Wj9!JU0Tp_Hz_IR{I>S?p%W{U|D!BH8%dJ0a#K}rWu99r@c)|NV z^AE+N@6I|7uIOJhJRplz42y7QmDr#{N1(&AJ>Ql?3VM4jgz1j%54msdR6lS^sx>~g4HPDRMctvo%$M|!@73o3BqE0aJe4o(PS+nI`(tTFDT&>(}o&GCX# z$`Lz^Li_p)-2R`qFG_hB5TP|yw{ghHt43BDcRRK?rg?ba^w$m^(*?1DeP=bLg32V4 zd@;{vnWpy%zlF_Q^((}}FtE>ie`_icWd1=ao{XjuCDW!u5u$@*S~mN2TOeSEU&Dv1 zVR?&uDcJqt?ivPkg8{O-K$i+F*K2FWtlJc)`iY;x5NW)=^COUBb7kIMvo(p4J~bg{ z$dN=Un8_{oyKZmUM%7>%Uu}eaqpaRp=4MsIXvwj#ZdxuQtf(AQ%oleX1xu&eG};r` zAAWGabdMk_jMlu=47J03iifnu08!Y3D-cn9{fdfrDhV=iX3~ifnEUaE6!1Lj@(`}3 z4Wb$7AXZ07nScRY&N-$Bvu`cpkRAZF90!Lvpyr62E7^sBXD9GB1r_IYKrkwaf`ytT z;^rFY@*5*6leJoUpDB7-&F^$7{=?rYa`&TIc5%AYfVI$eOM#buS%&*YK0L3_a0pk) zpI%a;EReHFxU3(Fpk9vfOcC~=^X-ZZ*;E&8laz5zPEJB&?9g@YkoePj>~bi$M6-15 z-q6v)qLgq3IW!O-YKK!9o2JU*54(b-BNYto{oEx>RZ@TNZ zjerN2XzCl3;3zcXjgg#}mGf^oK2JpaA4QHJh>}?bj$GrrS zX^p1v+K=FUFY4KSKB=6x(Hp?UX{__yat?7B;cXf&WkU+;XJV7Z-`OM5(*38lTlnM)^{} zt4RY?#B0+y&QZDK4#nVAFj=CnwLHd@ia=#SO;$?Yh_fT<;|Z38Kfhxq<|zcUNA|$y z2uT@rMcjRngy%!XY48=pC)lD>91bPM>}}_X;BH}#=GVDw$I%hM9TwPzIcYmSGv)bY zEXj&n5{RY9NqDJSp!xN7E8n34ek+9j?wr^8!xdF2?KO~U=TCU(2neX=aPboD{+e&3 zaQ;uWe5Ahh6c3&WZ`nfc90kX^1h5{G!KX=k-<^6tj+s)WYiSIVC17f%zY+RHEb-lof-B`8d ztnskqK{@T__S;~XTRmuVoAM+()R6_z^2z<-V$*!{xps5E{g0pYOdmxPV7-08O#OiJ zdc$ma?n$^av@w^U%FrtRzTjXC(g{Ob6(2>F6U7%9f+UoHva(2lL->_@;1> z$lL;et-WxzTgPvRv#_vGsIvt&uL#nKC zmrnfrk3>O^h$kQMh~K~cQEmE>^75g{lpO8-;G%77&!*_uu|@&?p)uy|b_!N2AU=9f~M@0(CCoAG6K>dX)fphI>bMgwC zwQD-iJ3xRDf45uh!^o(9k$a3CKVMFm=+tIEC}v*q{8(@cC*c^ZkZ!IWn^St$m{B6#LZVm=~h&pm#~>8 zEKSsk2BV_sSBn$dLzA_Lz48x?c9cL3@g}o#)Zu(3?8xbTyU{_~iPszf{L{h%;>iMY z5@EG|R8`ASd7g8+J*5Z*JndwJ0rn5?9Ln$+b2YC!@ADTW_$t$jyT8SS5|5qSZH>}~ z1v>mW)&Fb3d4*!jgp{hOzl3zk9sX(%RTSL;{e99vH>o0DboX^$uN=ptDEXW|_ap^b zZDC^VfV(?+2y7~-#&CzB3u&M_wJcVb#)LmBm~AhPnhc0VKyXSZ6&Uz;sKt|S#lh6pC1qJWNAM4y}z1*8F zrRHV6>^l|UX|_+ItN>CqM{|G)zSs3)!)lH{O?pR?W-5B#A^gnIpT=-Ubt-|fi_iXs zdI+X~l*v{?1^KE6tTZ>dg0SD*xYZ1wX)UIg1yv=vR}4g`Fjs?wrV3MNAWrV;gfrTS zp1^ItH?w)AC$!Lxvo6;hVeRx*BL+t?=mSv|LNZ=npomMUzwUGT4P{zFrC;U|%XW7? ziENhI*p+8%8-i+MXG}Uve4+!{?ZTb@LJ#;L zRyK7)ZY!>!g=2YY$Dh}A3ba=(IZuZ-D6gtTyn9txJfK7607GpO$3J7SfEr?7@=rY5 z#|2BEiuy{@N5ge~9EArZG0)267dqbJ^=b?7#*jr)ciSI0vGktpL<70fcAO z-3=5L5ZA3^LS_?oru-utH>_1X}+_Mr62qsoU?4aeW1#y=7P_xp9;h(VWyk z%y1fC+`rp@vg{D~IGKJu|K|pNzu#a?I30AFU(GhlLX}D`t4pmdnm}r4->+BFPO5r% zzc^8Fkugar1l=8(Km62)5a|)q2jY(^^*cU|Zh!kmw=-TaBDx2p%&uUeDHl3q_rrjo zUy@!vrz9;88ZEEg7}@k{M*75rSInj2TI*H9gL}KXz0Y{(1HaV7*CGg6WerM@O@!{q zPv7)>Ww?)x6rfhxH}AuDj1y>#qE2*Z$*10s|I7@ta}mP;`w_hTg`$O-L44V;2UwiGfw*HsgpZfdxIz&%gp0WU=^ z=|q9;%J8K5{z^$92ltA~+V?_U6@PLz|1?R!IUcPDUR+GFf8!v)(wUV`fyGE|BomP1 zm&Z3ITWP0vf^;$WU2OeT%z zyHgm~_%nj`tf14_EgFJC2JnVsI&9F4x|m3VZHoLVjxybCj(j7@-^SRANC4>gU($E6 z9b^yNzf6BbC3k{{l&h6!2})Cusfq6b1I*LPsjA0%HG}fw392j}Q%Y^i+0p4MbCxo-S{v!uUW#XlG|(4l$CimsXm1*9^#;l55S2 z?ICSu;N5loKS25TvC4(aSA`Vff%sYXr8~RS*%C%~cMG>A^5yes9;TONAs!1B-uynl zmIa-k*VX@Etc5eQ)ZR{73N`y0N{5PAcz-&yxG?Y1SRjVyioZ0!Xx4PQxU{shxSvL; zk3t9^o;zBW@OMV>3lX^Dw)D#fpqHr~Zc zE3@ZQ+OoW;a6Zt~Y;-JgZ1K1}ybB7vuM#geuA zQ2GJcizzbNP22OyubxgP0Z2qnw~ByW^hwx{Tyc9zZMhic?W^~~Vl4&kpKFdp4VVA= zRsZ+n{=QTYV2v(+JmV%U?W%?zd-y+0<+#=F(73N32^&Zj9L|k;(+mxf;nA84t3a;5 zb1av=fJU@UIR~XNiDS8u5JW(K*dC&LWiw4gc7gQ4!R}N}e zXdIZXEH2=C=Z_vUH)@{*YLxbGo>EcU>y0mOm{Z}8Qg9nxz^&baX_GNF!I)$QQl#}( zh$9~Js>}IOPJIhM>p6J!z9LtPVriM^A(JR;+7}siDUUQ`<6@mmN`fk5)mNQ*Y9sR0 z!S#GDB$YVm!I-1_*Ixqsv0@tg^R1v?DRSGat%eVYSdO)Zv53Qt0q?{jqTr<60Non2 zx^MqWtFVcW4x#b&hWH30J-A_)R&Q^vb+cbhtBkZ?Q*B;T%_|SGVH_O-Wl#C9 z(f6Mh)W(5GcMnCfT;u%vq5bFCy%TRgCu5Xx);lh}|4|5(f<#&V0}jAcWEd)_FI`e| z$$K;UEa60+Znq;&X#d@haowUc3u!0qjD9MYc{vF+otixN!loO8hIjGJ!Z`8d2~Own zTeaEu3SOm6?(fEh@bKJ0A_|~+C>QWJ6MrZr`*Q^w^7Dat8a+TR{_d{&pJ|S$<(|u) z$igNCa|(Zay<9V>t3<$fjUp3%1xj2CM}jhxd}<}P=%In8Q8T}E?-|S5P-(&EG2TAVd}ZCelqSczk~>@S$<~L5+?(F` z&D|yr#$wF%h05YBSQav`+7wwEeKA)xaQDR`A%N;x?F+G^8Q7+ZwG@mM=1$O--)2r_%UtQA4 zM)RPwQ0MTn3(~eFE6#xe{PUIPk3OmX{+HcR9r$e8X1VfNq=>UK7a*1P2LeWDPwRmr z#3o9$>h2$Eqo0A|oGQeqDqcGv4CytdC6wvPXjM5Bnsp&fe3@Q*SZtKHr?m-5sWT$F zAGDd%Xtd`XP|dGp)Ka{i3RciO{b)>lIu}l2cD-9;?{&2BI(>JtEMA_uEz385Sc_u% zV%Q3*Uh6D2%VKzdR8FRG=~f!g-EsUWVn|)ey`@|whtJ7knyZBAeBWx`OyLa@qi%*M z{d8%;YYbxfCRN5FCHFnW+e&w@*Np15pICLpwHyf7kj{51@?}g#F3V6^GuT{&3mcLk}JM=dRTLji!&){7s( zY6tQr)E&dG*SaGufOH=YvkOp>UOt!0;o`5G%Ogch_eJ0-S`z)Toflp0vE`gT5IpI= zGN#txiI8T$UZ@)jky#I(F>m{!)*v|~-9Ywh-{LIwm$#x`crv*YC}Y%%+^z776mvAs zuC#4g*p1-5rlrH)uOBv~tmFaFsx+$lu7p$O^HF;)dw3(Cl$x&AA_1``MUFPR**Ku% z5&7%KMV6r={X2rnFM)U2WbOUwef&dDcEc$pcBsSDgzhFssDQi9j4r(1rLM$#s8gV( z5N>(cZ=r2!h*4e8cv{_J52+Oih0cpW{xAjQUDZ3=P$n!LyAgdD)T!BFhIv5Mwlc&pJL!)*W&%O)` zK8l$=72sN?AET;#l3w?5I7zQ}I5fli)S!O}8ss2yz#TJ|n#MK4YxhCDED`j)xM-`K z-gG%}{^^ojZe3YyI%Th;(#sd3Gsf{gv%aIOjB3tLg&wYqZvb_HSPGX-EPcTl$~6%C zBMn42yr{7ug@=6}>-~CvYx>5&;bv7cduM5ts+(R9qE}C}qK;i`UKN75n-}RT(Zc6S zhuT-WsC%=}L@`=VQWbcOJu~%j>{C{IFPWGorchi_xvG!ME}SJ~;!-s)GJ0S{AevbK zk@IcsvwLU1aT%171-s$4h;gR?CWzl3LXu6Zxar_4F)yVX6}u9Uo+Eg1$n?6(_;w$A ziAW>g;*4l~!me3n!R_Gtg((V=98%|=dfaX;BXcg5mn%yi+9zSqHPgLUm$X9&cHMHd zGQ*PhN$_NqSd&pBcI(~c>^*p-+f=bJIs|AGDNWK7r^VvY-BUK0{p5~N*Ni;#e(c1~ zw}Ld#$iB}sly3rRZ?0b7%ZN;TOyhIe38&4-OtEdI4}%s73}6O~7TxKvREtSKE9*nyC}t`uaP>EZg4Sf&ELgdqH3OKy$vtQ%MtHSNGfp4 ztsKj1?r&AP-i=w5n;S?{I$Kx#{ov{t;)b;dH2r; z@!}max?j+V-wb+PY3pi1`WD0X0|b97cz+a0-X-hGQTT8GI1&4(E4Sx0f5mPjgzCC1 zJp_^`EDB|p*c3wc3gnZ@1h_S!a#jB|75+7_MFf!Dr@#F9AJ6wcn+KBE7jB$UG#w?0 zIr*DRSqkf54_iT9to;y*#KPv|*q@!w7ir{Q zhaUqP?j7T;_6Fseny2{+^0Glwr?uEXGw0hYR2x>R4<*lB;AnC+po*3`-@#_AiPIMm zPe3gpFG=1GpY0d{;fOn7RNzcc=oyTA*;@<+4J#)aq_+@Dsicg1wa zzh*~`(I}gOnRRMjaM^X|S4^0(VU>-!LcdZ@NkbTv_pGK0DD{>b7-P~s@8w@}Iyg4J zoq4z!MmxVKH(V3I{(A4}QYf}Rt(L8$?)r_zD2jWmlciOXq`9!fJz^;?vvr47C?U6Q zr^$_}NVj1_{>AJ;6%cjJ`dGJ}!7_H@17vtj7HhKHoa5_;hW{Oh%G>Nr zLLR{6UI(nJ3rUnpJjw+{+G@pS%q^fXQlMZ)`c*y@0o%qM9?tO$OUt1-IeFtaXRptP{u_QA;KL}O zJKe}gWJ@)OvET}CY!-K|me*uil+@C65s9%ByY3f*aMa|wY}_c5J8m{{#7}+wY3uSI z-(O;6!T_O=;DrCVe!N5yeY0oS{qU`4p5>w3+;1(TfJxx{3t{gUGrx;_M}`u>0(bYSVWxwy}5KfKRe;W^0%-tO(sTC;9ICq#gc zB*Xk*7QGrMjGeDE#mEg~uZ+aYFngarB=bsNOB1=@)ZE~Pp6RCc&e6G+V!gUo`((Fba81hcCG8KH#5SI>PVh8 zdLN#y;c8Vn5=0Y*9=)~HVo5lJUd&9gmL@#kJY1Bq^S


      E3tn6%}eZhWYLM`E2{* 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 z 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

      Sn-yWj#m{{6VOdY_l=Nl@vmL&py>@h;{)oxv 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 literal 0 HcmV?d00001 From 697150a2768b76e1233b4ee16f9a027b47d8559d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Nam=20Long?= Date: Sat, 12 Sep 2026 04:26:47 +0000 Subject: [PATCH 52/54] test(plugins): pin Weaviate PluginKit to current ABI and theme-colored chrome MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nguyễn Nam Long --- .../Plugins/WeaviateConnectionFieldsTests.swift | 5 +++-- .../Editor/QueryDiagnosticsRefreshTests.swift | 2 +- .../Views/Results/DataGridBodyChromeTests.swift | 17 ++++++++--------- .../DataGridPendingChangeMarkTests.swift | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/TableProTests/Plugins/WeaviateConnectionFieldsTests.swift b/TableProTests/Plugins/WeaviateConnectionFieldsTests.swift index 3046f3bd04..9aeebb21c6 100644 --- a/TableProTests/Plugins/WeaviateConnectionFieldsTests.swift +++ b/TableProTests/Plugins/WeaviateConnectionFieldsTests.swift @@ -127,7 +127,7 @@ struct WeaviateFieldParityTests { @Suite("Weaviate plugin manifest") struct WeaviatePluginManifestTests { - @Test("Info.plist declares PluginKit 25 and the Weaviate type id") + @Test("The bundle pins the PluginKit ABI and the Weaviate type id") func plistDeclaresType() throws { let url = URL(fileURLWithPath: #filePath) .deletingLastPathComponent() @@ -135,7 +135,8 @@ struct WeaviatePluginManifestTests { .deletingLastPathComponent() .appendingPathComponent("Plugins/WeaviateDriverPlugin/Info.plist") let plist = try #require(NSDictionary(contentsOf: url) as? [String: Any]) - #expect(plist["TableProPluginKitVersion"] as? Int == 25) + #expect(plist["TableProPluginKitVersion"] as? Int == PluginManager.currentPluginKitVersion) #expect(plist["TableProProvidesDatabaseTypeIds"] as? [String] == ["Weaviate"]) + #expect(plist["TableProMinAppVersion"] as? String == "0.73.0") } } diff --git a/TableProTests/Views/Editor/QueryDiagnosticsRefreshTests.swift b/TableProTests/Views/Editor/QueryDiagnosticsRefreshTests.swift index dd2e4f15c5..37d0c2e8e3 100644 --- a/TableProTests/Views/Editor/QueryDiagnosticsRefreshTests.swift +++ b/TableProTests/Views/Editor/QueryDiagnosticsRefreshTests.swift @@ -193,7 +193,7 @@ struct QueryDiagnosticMessageTests { let emphases = manager.getEmphases(for: QueryDiagnosticsController.emphasisGroup) #expect(emphases.map(\.range) == [range]) - #expect(emphases.first?.style == .underline(color: .systemOrange)) + #expect(emphases.first?.style == .underline(color: ThemeEngine.shared.palette[.statusWarning])) #expect( manager.toolTip(at: try center(of: range, in: controller)) == "Full-width semicolon (U+FF1B). SQL reads only ; as a statement separator." diff --git a/TableProTests/Views/Results/DataGridBodyChromeTests.swift b/TableProTests/Views/Results/DataGridBodyChromeTests.swift index 7a3fff2e94..2d657dd715 100644 --- a/TableProTests/Views/Results/DataGridBodyChromeTests.swift +++ b/TableProTests/Views/Results/DataGridBodyChromeTests.swift @@ -168,14 +168,12 @@ struct DataGridBodyChromeTests { #expect(!grid.coordinator.presentsColumn(atTableColumnIndex: rowNumber)) } - /// The colour has to come from `tableView.gridColor`, which is the dynamic catalog colour AppKit - /// was filling with, so an appearance change carries the separator with it and there is no - /// second spelling to keep in sync. A hardcoded colour would pass a geometry test and be wrong - /// in dark mode. - @Test("The separator is drawn in the table view's own grid colour") - func separatorUsesTheTableViewGridColor() throws { + /// The colour has to come from the theme's grid line slot, which is what the rest of the grid + /// paints with. `tableView.gridColor` is not consulted: AppKit's grid lines are off, and a + /// hardcoded grey would pass a geometry test and be wrong in dark mode. + @Test("The separator is drawn in the theme's grid line colour") + func separatorUsesTheThemeGridLineColor() throws { let grid = makeGrid(columns: ["id", "name"]) - grid.tableView.gridColor = .systemRed let rowView = try #require(grid.tableView.rowView(atRow: 0, makeIfNecessary: true) as? DataGridRowView) rowView.layoutSubtreeIfNeeded() @@ -189,13 +187,14 @@ struct DataGridBodyChromeTests { x: Int((boundary - 0.5) * scale), y: Int(rowView.bounds.height * scale / 2) )?.usingColorSpace(.deviceRGB) - let expected = NSColor.systemRed.usingColorSpace(.deviceRGB) + let expected = ThemeEngine.shared.palette[.gridLine].usingColorSpace(.deviceRGB) let sampledRed = try #require(sampled?.redComponent) let sampledGreen = try #require(sampled?.greenComponent) let expectedRed = try #require(expected?.redComponent) + let expectedGreen = try #require(expected?.greenComponent) #expect(abs(sampledRed - expectedRed) < 0.15) - #expect(sampledRed > sampledGreen + 0.3, "the separator has to carry the grid colour, not a fixed grey") + #expect(abs(sampledGreen - expectedGreen) < 0.15) } /// `NSTableView` continues the alternation past the last row one row height at a time, numbered diff --git a/TableProTests/Views/Results/DataGridPendingChangeMarkTests.swift b/TableProTests/Views/Results/DataGridPendingChangeMarkTests.swift index d867d39fa9..51bc39df43 100644 --- a/TableProTests/Views/Results/DataGridPendingChangeMarkTests.swift +++ b/TableProTests/Views/Results/DataGridPendingChangeMarkTests.swift @@ -190,7 +190,7 @@ struct DataGridPendingChangeMarkTests { ) #expect(struck.gain > textWidth / 2) - #expect(selected.gain > textWidth / 2) + #expect(selected.reach > textWidth / 2) } /// The two lines have to land in different places, or they are the same cue twice. From fe1b97f92b2b79e2e1d04919e718e401f4188501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Nam=20Long?= Date: Sat, 12 Sep 2026 05:31:53 +0000 Subject: [PATCH 53/54] fix(ios): keep shared catalog quoting off the iOS main actor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nguyễn Nam Long --- Plugins/MySQLDriverPlugin/DatabendCatalog.swift | 2 +- Plugins/MySQLDriverPlugin/MySQLColumnDefinitionSQL.swift | 4 ++-- Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift | 2 +- Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Plugins/MySQLDriverPlugin/DatabendCatalog.swift b/Plugins/MySQLDriverPlugin/DatabendCatalog.swift index ae0d45615d..46bb96d821 100644 --- a/Plugins/MySQLDriverPlugin/DatabendCatalog.swift +++ b/Plugins/MySQLDriverPlugin/DatabendCatalog.swift @@ -6,7 +6,7 @@ import Foundation import TableProPluginKit -internal enum DatabendCatalog { +nonisolated internal enum DatabendCatalog { static func quoteIdentifier(_ name: String) -> String { guard name.contains("`") else { return "`\(name)`" } let escaped = name diff --git a/Plugins/MySQLDriverPlugin/MySQLColumnDefinitionSQL.swift b/Plugins/MySQLDriverPlugin/MySQLColumnDefinitionSQL.swift index ed0adf664a..46e2a5b6ce 100644 --- a/Plugins/MySQLDriverPlugin/MySQLColumnDefinitionSQL.swift +++ b/Plugins/MySQLDriverPlugin/MySQLColumnDefinitionSQL.swift @@ -6,12 +6,12 @@ import Foundation import TableProPluginKit -internal func mysqlQuoteIdentifier(_ name: String) -> String { +nonisolated internal func mysqlQuoteIdentifier(_ name: String) -> String { let escaped = name.replacingOccurrences(of: "`", with: "``") return "`\(escaped)`" } -internal func mysqlEscapeStringLiteral(_ value: String) -> String { +nonisolated internal func mysqlEscapeStringLiteral(_ value: String) -> String { var result = value result = result.replacingOccurrences(of: "\\", with: "\\\\") result = result.replacingOccurrences(of: "'", with: "''") diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift index c69aefabd0..898ccb8562 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift @@ -5,7 +5,7 @@ import Foundation -struct PostgreSQLCapabilities: Sendable, Equatable { +nonisolated struct PostgreSQLCapabilities: Sendable, Equatable { let serverVersion: Int32 /// libpq answers 0 for a handle it has not connected. A catalog query built for that has to diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift index 28b7c64a1b..725bb13405 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLObjectQueries.swift @@ -9,7 +9,7 @@ import Foundation import TableProPluginKit -public enum PostgreSQLObjectQueries { +nonisolated public enum PostgreSQLObjectQueries { /// The single owner of literal quoting for every statement this plugin builds, which is why it /// returns the quotes too: the `E` prefix sits outside them, so a helper that returns inner text /// for a call site to wrap can never be setting-independent. Measured on PostgreSQL 17.11 with From 81597db0059bff6ee918e9d59088e1491446f1f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Nam=20Long?= Date: Sat, 12 Sep 2026 05:31:53 +0000 Subject: [PATCH 54/54] test(settings): scroll the Editor pane to the Vim mode toggle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nguyễn Nam Long --- TableProUITests/Support/UITestCase.swift | 17 +++++++++++++++++ TableProUITests/VimNormalModeChordUITests.swift | 5 ++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/TableProUITests/Support/UITestCase.swift b/TableProUITests/Support/UITestCase.swift index fb9f4db6a8..9781c6b5ff 100644 --- a/TableProUITests/Support/UITestCase.swift +++ b/TableProUITests/Support/UITestCase.swift @@ -182,6 +182,23 @@ internal class UITestCase: XCTestCase { waitForPredicate(timeout: timeout) { element.exists && element.isHittable } } + /// The settings window is 720x500, and the Editor pane is taller than that once the font + /// pickers sit above the SQL toggles. XCUITest reports the Vim switch as existing and not + /// hittable, because it is below the fold; a swipe is what brings it into the window. + internal func waitUntilHittableByScrolling( + _ element: XCUIElement, + in container: XCUIElement, + timeout: TimeInterval + ) -> Bool { + if waitUntilHittable(element, timeout: 1) { return true } + let deadline = Date().addingTimeInterval(timeout) + while Date() < deadline { + container.scrollViews.firstMatch.swipeUp() + if waitUntilHittable(element, timeout: 0.8) { return true } + } + return element.exists && element.isHittable + } + /// Switches the result to its Structure editor, through **View > Result View > Structure** /// rather than the `Structure` segment of the results status bar. /// diff --git a/TableProUITests/VimNormalModeChordUITests.swift b/TableProUITests/VimNormalModeChordUITests.swift index 542160c710..891843477b 100644 --- a/TableProUITests/VimNormalModeChordUITests.swift +++ b/TableProUITests/VimNormalModeChordUITests.swift @@ -65,7 +65,10 @@ final class VimNormalModeChordUITests: UITestCase { editorPane.click() let vimToggle = settings.descendants(matching: .any).matching(identifier: "vim-mode-toggle").firstMatch - XCTAssertTrue(waitUntilHittable(vimToggle, timeout: 10), "The Editor pane must offer Vim mode") + XCTAssertTrue( + waitUntilHittableByScrolling(vimToggle, in: settings, timeout: 10), + "The Editor pane must offer Vim mode" + ) if isOn(vimToggle) != enabled { vimToggle.click() }

      =_wFy?=D<-su|4K_eez$g*_rC{`Q-Pe~N$VQjDY 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⩔hTpCV^feZ$>bjEi?ySu!@AOdDU~1pe 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ƻwD@PaU6IzsB;+SZM>b!ZWGz*p?u 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

      C{heljC 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 z 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 B^ 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 literal 0 HcmV?d00001 diff --git a/docs/images/highlight-rules.png b/docs/images/highlight-rules.png new file mode 100644 index 0000000000000000000000000000000000000000..21febb50adf8348486c3b7373d8e99885fea1b52 GIT binary patch literal 1873775 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

    bF}kERK{1H?xtRE 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

  • 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 n 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℘vW?L3Y1;DY`8r$WUDc3 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%0D1>s_At&TjyX+ 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