Skip to content

Commit 2b18987

Browse files
committed
release: v0.15.0
1 parent 7be6563 commit 2b18987

File tree

12 files changed

+96
-73
lines changed

12 files changed

+96
-73
lines changed

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.15.0] - 2026-03-08
11+
1012
### Added
1113

1214
- Oracle Database support via OCI (Oracle Call Interface)
@@ -708,7 +710,8 @@ TablePro is a native macOS database client built with SwiftUI and AppKit, design
708710
- Custom SQL query templates
709711
- Performance optimized for large datasets
710712

711-
[Unreleased]: https://github.com/datlechin/tablepro/compare/v0.14.1...HEAD
713+
[Unreleased]: https://github.com/datlechin/tablepro/compare/v0.15.0...HEAD
714+
[0.15.0]: https://github.com/datlechin/tablepro/compare/v0.14.1...v0.15.0
712715
[0.14.1]: https://github.com/datlechin/tablepro/compare/v0.14.0...v0.14.1
713716
[0.14.0]: https://github.com/datlechin/tablepro/compare/v0.13.0...v0.14.0
714717
[0.13.0]: https://github.com/datlechin/tablepro/compare/v0.12.0...v0.13.0

TablePro.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@
386386
CODE_SIGN_IDENTITY = "Apple Development";
387387
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
388388
CODE_SIGN_STYLE = Automatic;
389-
CURRENT_PROJECT_VERSION = 27;
389+
CURRENT_PROJECT_VERSION = 28;
390390
DEAD_CODE_STRIPPING = YES;
391391
DEVELOPMENT_TEAM = D7HJ5TFYCU;
392392
ENABLE_APP_SANDBOX = NO;
@@ -420,7 +420,7 @@
420420
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
421421
LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/Libs";
422422
MACOSX_DEPLOYMENT_TARGET = 14.0;
423-
MARKETING_VERSION = 0.14.1;
423+
MARKETING_VERSION = 0.15.0;
424424
OTHER_LDFLAGS = (
425425
"-force_load",
426426
"$(PROJECT_DIR)/Libs/libmariadb.a",
@@ -480,7 +480,7 @@
480480
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
481481
CODE_SIGN_STYLE = Automatic;
482482
COPY_PHASE_STRIP = YES;
483-
CURRENT_PROJECT_VERSION = 27;
483+
CURRENT_PROJECT_VERSION = 28;
484484
DEAD_CODE_STRIPPING = YES;
485485
DEPLOYMENT_POSTPROCESSING = YES;
486486
DEVELOPMENT_TEAM = D7HJ5TFYCU;
@@ -515,7 +515,7 @@
515515
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
516516
LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/Libs";
517517
MACOSX_DEPLOYMENT_TARGET = 14.0;
518-
MARKETING_VERSION = 0.14.1;
518+
MARKETING_VERSION = 0.15.0;
519519
OTHER_LDFLAGS = (
520520
"-force_load",
521521
"$(PROJECT_DIR)/Libs/libmariadb.a",

TablePro/Core/Database/OracleConnection.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ final class OracleConnectionWrapper: @unchecked Sendable {
140140
lock.unlock()
141141

142142
do {
143-
let statement: OracleStatement = OracleStatement(stringLiteral: query)
143+
let statement = OracleStatement(stringLiteral: query)
144144
let stream = try await connection.execute(statement, logger: nioLogger)
145145

146146
// Read column metadata from stream (available even with 0 rows)

TablePro/Core/Database/OracleDriver.swift

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,7 @@ final class OracleDriver: DatabaseDriver {
155155
var i = len - 1
156156
while i >= 7 {
157157
let ch = ns.character(at: i)
158-
if ch == 0x29 { depth += 1 }
159-
else if ch == 0x28 { depth -= 1 }
160-
else if depth == 0 && ch == 0x59 {
158+
if ch == 0x29 { depth += 1 } else if ch == 0x28 { depth -= 1 } else if depth == 0 && ch == 0x59 {
161159
let start = i - 7
162160
if start >= 0 {
163161
let candidate = ns.substring(with: NSRange(location: start, length: 8))
@@ -177,9 +175,7 @@ final class OracleDriver: DatabaseDriver {
177175
var i = len - 1
178176
while i >= 5 {
179177
let ch = ns.character(at: i)
180-
if ch == 0x29 { depth += 1 }
181-
else if ch == 0x28 { depth -= 1 }
182-
else if depth == 0 && ch == 0x54 {
178+
if ch == 0x29 { depth += 1 } else if ch == 0x28 { depth -= 1 } else if depth == 0 && ch == 0x54 {
183179
let start = i - 5
184180
if start >= 0 {
185181
let candidate = ns.substring(with: NSRange(location: start, length: 6))

TablePro/Core/Services/ExportService+MQL.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,5 +204,4 @@ extension ExportService {
204204
}
205205
return name
206206
}
207-
208207
}

TablePro/Core/Services/ImportService.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,6 @@ final class ImportService {
313313
}
314314

315315

316-
317316
private func commitStatement(for dbType: DatabaseType) -> String {
318317
switch dbType {
319318
case .mongodb, .redis:

TablePro/Views/Export/ExportDialog.swift

Lines changed: 24 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -447,62 +447,13 @@ struct ExportDialog: View {
447447
return item1.name < item2.name
448448
}
449449

450-
case .sqlite:
451-
// SQLite: only one database, fetch tables directly
452-
let tables = try await driver.fetchTables()
453-
let tableItems = tables.map { table in
454-
ExportTableItem(
455-
name: table.name,
456-
databaseName: "",
457-
type: table.type,
458-
isSelected: preselectedTables.contains(table.name)
459-
)
460-
}
461-
if !tableItems.isEmpty {
462-
items.append(ExportDatabaseItem(
463-
name: connection.database.isEmpty ? "main" : connection.database,
464-
tables: tableItems,
465-
isExpanded: true
466-
))
467-
}
468-
469-
case .mongodb:
470-
// MongoDB: similar to SQLite, fetch collections directly
471-
let tables = try await driver.fetchTables()
472-
let tableItems = tables.map { table in
473-
ExportTableItem(
474-
name: table.name,
475-
databaseName: "",
476-
type: table.type,
477-
isSelected: preselectedTables.contains(table.name)
478-
)
479-
}
480-
if !tableItems.isEmpty {
481-
items.append(ExportDatabaseItem(
482-
name: connection.database.isEmpty ? "main" : connection.database,
483-
tables: tableItems,
484-
isExpanded: true
485-
))
486-
}
487-
488-
case .redis:
489-
// Redis: fetch keys as table items
490-
let tables = try await driver.fetchTables()
491-
let tableItems = tables.map { table in
492-
ExportTableItem(
493-
name: table.name,
494-
databaseName: "",
495-
type: table.type,
496-
isSelected: preselectedTables.contains(table.name)
497-
)
498-
}
499-
if !tableItems.isEmpty {
500-
items.append(ExportDatabaseItem(
501-
name: connection.database.isEmpty ? "db0" : connection.database,
502-
tables: tableItems,
503-
isExpanded: true
504-
))
505-
}
450+
case .sqlite, .mongodb, .redis:
451+
let fallbackName = connection.type == .redis ? "db0" : "main"
452+
let dbItem = try await buildFlatDatabaseItem(
453+
driver: driver,
454+
name: connection.database.isEmpty ? fallbackName : connection.database
455+
)
456+
if let dbItem { items.append(dbItem) }
506457

507458
case .mssql:
508459
// MSSQL: fetch schemas within current database
@@ -612,6 +563,23 @@ struct ExportDialog: View {
612563
return result.rows.compactMap { $0[0] }
613564
}
614565

566+
private func buildFlatDatabaseItem(
567+
driver: DatabaseDriver,
568+
name: String
569+
) async throws -> ExportDatabaseItem? {
570+
let tables = try await driver.fetchTables()
571+
let tableItems = tables.map { table in
572+
ExportTableItem(
573+
name: table.name,
574+
databaseName: "",
575+
type: table.type,
576+
isSelected: preselectedTables.contains(table.name)
577+
)
578+
}
579+
guard !tableItems.isEmpty else { return nil }
580+
return ExportDatabaseItem(name: name, tables: tableItems, isExpanded: true)
581+
}
582+
615583
private func fetchTablesForSchema(_ schema: String, driver: DatabaseDriver) async throws -> [TableInfo] {
616584
// Oracle does not have information_schema — use ALL_TABLES/ALL_VIEWS
617585
if connection.type == .oracle {

TablePro/Views/Main/MainContentCoordinator.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1092,7 +1092,6 @@ final class MainContentCoordinator {
10921092
}
10931093
}
10941094
}
1095-
10961095
}
10971096

10981097
// MARK: - Query Execution Helpers

TablePro/Views/Results/DataGridView.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,6 @@ final class TableViewCoordinator: NSObject, NSTableViewDelegate, NSTableViewData
776776
func numberOfRows(in tableView: NSTableView) -> Int {
777777
cachedRowCount
778778
}
779-
780779
}
781780

782781
// MARK: - Preview

TablePro/Views/Settings/AISettingsView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ private struct AIProviderEditorSheet: View {
546546

547547
// MARK: - Connection Test
548548

549-
private func testProvider() {
549+
func testProvider() {
550550
let provider = AIProviderFactory.createProvider(for: draft, apiKey: editingAPIKey)
551551

552552
isTesting = true

0 commit comments

Comments
 (0)