Skip to content

Commit 535e649

Browse files
committed
release: v0.9.0
1 parent 0504d07 commit 535e649

11 files changed

Lines changed: 88 additions & 29 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.9.0] - 2026-02-28
11+
1012
### Added
1113

1214
- Vim keybindings for SQL editor (Normal/Insert/Visual modes, motions, operators, :w/:q commands) with toggle in Editor Settings
@@ -562,7 +564,8 @@ TablePro is a native macOS database client built with SwiftUI and AppKit, design
562564
- Custom SQL query templates
563565
- Performance optimized for large datasets
564566

565-
[Unreleased]: https://github.com/datlechin/tablepro/compare/v0.8.0...HEAD
567+
[Unreleased]: https://github.com/datlechin/tablepro/compare/v0.9.0...HEAD
568+
[0.9.0]: https://github.com/datlechin/tablepro/compare/v0.8.0...v0.9.0
566569
[0.8.0]: https://github.com/datlechin/tablepro/compare/v0.7.0...v0.8.0
567570
[0.7.0]: https://github.com/datlechin/tablepro/compare/v0.6.4...v0.7.0
568571
[0.6.4]: https://github.com/datlechin/tablepro/compare/v0.6.3...v0.6.4

TablePro.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@
381381
CODE_SIGN_IDENTITY = "Apple Development";
382382
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
383383
CODE_SIGN_STYLE = Automatic;
384-
CURRENT_PROJECT_VERSION = 16;
384+
CURRENT_PROJECT_VERSION = 17;
385385
DEAD_CODE_STRIPPING = YES;
386386
DEVELOPMENT_TEAM = D7HJ5TFYCU;
387387
ENABLE_APP_SANDBOX = NO;
@@ -411,7 +411,7 @@
411411
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
412412
LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/Libs";
413413
MACOSX_DEPLOYMENT_TARGET = 14.0;
414-
MARKETING_VERSION = 0.8.0;
414+
MARKETING_VERSION = 0.9.0;
415415
OTHER_LDFLAGS = (
416416
"-force_load",
417417
"$(PROJECT_DIR)/Libs/libmariadb.a",
@@ -460,7 +460,7 @@
460460
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
461461
CODE_SIGN_STYLE = Automatic;
462462
COPY_PHASE_STRIP = YES;
463-
CURRENT_PROJECT_VERSION = 16;
463+
CURRENT_PROJECT_VERSION = 17;
464464
DEAD_CODE_STRIPPING = YES;
465465
DEPLOYMENT_POSTPROCESSING = YES;
466466
DEVELOPMENT_TEAM = D7HJ5TFYCU;
@@ -491,7 +491,7 @@
491491
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
492492
LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/Libs";
493493
MACOSX_DEPLOYMENT_TARGET = 14.0;
494-
MARKETING_VERSION = 0.8.0;
494+
MARKETING_VERSION = 0.9.0;
495495
OTHER_LDFLAGS = (
496496
"-force_load",
497497
"$(PROJECT_DIR)/Libs/libmariadb.a",

TablePro/Core/Database/ConnectionHealthMonitor.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ actor ConnectionHealthMonitor {
121121
}
122122

123123
// Wait for whichever finishes first, cancel the other
124-
if let _ = await group.next() {
124+
if await group.next() != nil {
125125
group.cancelAll()
126126
}
127127
}

TablePro/Core/Utilities/SQLFileParser.swift

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ final class SQLFileParser: Sendable {
6060
char == kSpace || char == kTab || char == kNewline || char == kCarriageReturn
6161
}
6262

63+
private static func markContent(
64+
_ hasContent: Bool, _ startLine: Int, _ currentLine: Int
65+
) -> (Bool, Int) {
66+
hasContent ? (true, startLine) : (true, currentLine)
67+
}
68+
6369
/// Append a single UTF-16 code unit to an NSMutableString. O(1) amortized.
6470
private static func appendChar(_ char: unichar, to string: NSMutableString?) {
6571
guard let string else { return }
@@ -146,24 +152,15 @@ final class SQLFileParser: Sendable {
146152
didManuallyAdvance = true
147153
} else if char == Self.kSingleQuote {
148154
state = .inSingleQuotedString
149-
if !hasStatementContent {
150-
statementStartLine = currentLine
151-
hasStatementContent = true
152-
}
155+
(hasStatementContent, statementStartLine) = Self.markContent(hasStatementContent, statementStartLine, currentLine)
153156
Self.appendChar(char, to: currentStatement)
154157
} else if char == Self.kDoubleQuote {
155158
state = .inDoubleQuotedString
156-
if !hasStatementContent {
157-
statementStartLine = currentLine
158-
hasStatementContent = true
159-
}
159+
(hasStatementContent, statementStartLine) = Self.markContent(hasStatementContent, statementStartLine, currentLine)
160160
Self.appendChar(char, to: currentStatement)
161161
} else if char == Self.kBacktick {
162162
state = .inBacktickQuotedString
163-
if !hasStatementContent {
164-
statementStartLine = currentLine
165-
hasStatementContent = true
166-
}
163+
(hasStatementContent, statementStartLine) = Self.markContent(hasStatementContent, statementStartLine, currentLine)
167164
Self.appendChar(char, to: currentStatement)
168165
} else if char == Self.kSemicolon {
169166
if hasStatementContent {

TablePro/Core/Vim/VimEngine.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ final class VimEngine {
122122
let digit = char.wholeNumberValue ?? 0
123123
if countPrefix > 0 || digit > 0 {
124124
// Cap at 99999 to prevent arithmetic overflow from rapid key repeat
125-
guard countPrefix <= 99999 else { return true }
125+
guard countPrefix <= 99_999 else { return true }
126126
countPrefix = countPrefix * 10 + digit
127127
return true
128128
}

TablePro/Core/Vim/VimKeyInterceptor.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ final class VimKeyInterceptor {
1515
private weak var inlineSuggestionManager: InlineSuggestionManager?
1616
private var monitor: Any?
1717
private weak var controller: TextViewController?
18-
private nonisolated(unsafe) var popupCloseObserver: NSObjectProtocol?
18+
nonisolated(unsafe) private var popupCloseObserver: NSObjectProtocol?
1919

2020
init(engine: VimEngine, inlineSuggestionManager: InlineSuggestionManager?) {
2121
self.engine = engine

TablePro/Views/Editor/SQLEditorCoordinator.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ final class SQLEditorCoordinator: TextViewCoordinator, ObservableObject {
2323
/// Shared schema provider for inline AI suggestions (avoids duplicate schema fetches)
2424
var schemaProvider: SQLSchemaProvider?
2525
private var contextMenu: AIEditorContextMenu?
26-
private nonisolated(unsafe) var rightClickMonitor: Any?
27-
private nonisolated(unsafe) var inlineSuggestionManager: InlineSuggestionManager?
28-
private nonisolated(unsafe) var editorSettingsObserver: NSObjectProtocol?
26+
nonisolated(unsafe) private var rightClickMonitor: Any?
27+
nonisolated(unsafe) private var inlineSuggestionManager: InlineSuggestionManager?
28+
nonisolated(unsafe) private var editorSettingsObserver: NSObjectProtocol?
2929
/// Debounce work item for frame-change notification to avoid
3030
/// triggering syntax highlight viewport recalculation on every keystroke.
31-
private nonisolated(unsafe) var frameChangeWorkItem: DispatchWorkItem?
32-
private nonisolated(unsafe) var clipboardMonitor: Any?
33-
private nonisolated(unsafe) var didDestroy = false
31+
nonisolated(unsafe) private var frameChangeWorkItem: DispatchWorkItem?
32+
nonisolated(unsafe) private var clipboardMonitor: Any?
33+
nonisolated(unsafe) private var didDestroy = false
3434

3535
/// Test-only accessor for destroy state
3636
var isDestroyed: Bool { didDestroy }

TablePro/Views/Editor/SQLEditorView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ struct SQLEditorView: View {
101101
coordinator.onCloseTab = onCloseTab
102102
coordinator.onExecuteQuery = onExecuteQuery
103103
editorReady = true
104-
}
104+
}
105105
}
106106
}
107107
.onDisappear {

TablePro/Views/Main/MainContentCoordinator.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ import SwiftUI
1414

1515
/// Discard action types for unified alert handling
1616
enum DiscardAction {
17-
case refresh
18-
case refreshAll
17+
case refresh, refreshAll
1918
}
2019

2120
/// Cache entry for async-sorted query tab rows (stores index permutation, not row copies)

docs/changelog.mdx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,36 @@ description: "Product updates and announcements for TablePro"
44
rss: true
55
---
66

7+
<Update label="February 28, 2026" description="v0.9.0">
8+
### New Features
9+
10+
- **Vim Mode for SQL Editor**: Full Vim keybindings with Normal/Insert/Visual modes, motions (`w`, `b`, `e`, `^`, `_`), operators, and `:w`/`:q` commands — toggle in Editor Settings
11+
- **PostgreSQL Schema Switching**: Browse and switch between schemas (`public`, `auth`, custom schemas) via ⌘K database switcher
12+
13+
### Improvements
14+
15+
- Query history operations converted to native Swift async/await for faster response
16+
- Export and Import services consolidated to reduce UI update overhead
17+
- App startup uses structured Task-based retry loops instead of dispatch chains
18+
19+
### Bug Fixes
20+
21+
- Fixed cell edit showing modified background (yellow) but reverting to original value after pressing Enter
22+
- Fixed undo on inserted row cell edit not syncing data correctly
23+
- Fixed Vim Escape key not working when autocomplete popup is visible
24+
- Fixed Copy/Cut (⌘C/⌘X) not working in SQL editor
25+
- Fixed Vim yank/delete not syncing to system clipboard
26+
- Fixed multiple Vim motion and visual mode selection issues
27+
- Fixed event monitor and memory leaks in SQL editor lifecycle
28+
- Fixed unbounded memory growth from tab registry, sorted row cache, and schema provider retention
29+
- Fixed background tabs retaining full result data indefinitely
30+
- Fixed crash on macOS 14.x caused by missing libpq symbol — now uses vendored static libraries
31+
- Fixed duplicate tabs when inserting SQL from AI Chat or History with multiple windows open
32+
- Fixed various coordinator lifecycle issues (teardown, destroy, cancellation)
33+
- Fixed DataGridView unnecessary column reconfiguration on every version bump
34+
- Fixed ConnectionHealthMonitor slow failure detection — now supports immediate health checks
35+
</Update>
36+
737
<Update label="February 27, 2026" description="v0.8.0">
838
### New Features
939

0 commit comments

Comments
 (0)