Skip to content

Commit 26766e9

Browse files
authored
fix(create-database): server-driven dialog (#927) (#953)
* refactor(create-database): server-driven dialog (fixes #927) * fix(mysql): expose logger to extension file * fix(create-database): show button in PG and remove duplicate parens * fix(create-database): default provider from template1 and fall back when picker default missing * fix(postgresql): preselect ICU locale from template1 and parallelize fetches
1 parent 8569671 commit 26766e9

47 files changed

Lines changed: 983 additions & 295 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

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

1010
### Added
1111

12+
- PostgreSQL ICU collation provider in Create Database (PG 15+). Provider picker is added when the server reports PG 15 or newer. ICU locale list comes from `pg_collation`. SQL emission is version-aware: PG 16+ uses unified `LOCALE`, PG 15 uses `ICU_LOCALE` with `LC_COLLATE 'C' LC_CTYPE 'C'`.
1213
- Connection URL parsing: SSH `user:password@host` split, `safeModeLevel` from TablePlus URLs, case-insensitive query params
1314
- Connection URL export: SSH password, Redis database index, MongoDB auth params (`authSource`, `authMechanism`, `replicaSet`), and multi-host
1415
- SSH Private Key auth resolves keys from `~/.ssh/config` and default locations (`id_ed25519`, `id_rsa`, `id_ecdsa`) when no explicit key path is set
@@ -24,6 +25,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2425

2526
### Changed
2627

28+
- Create Database dialog is now driver-driven. Each driver discovers its own valid options (PostgreSQL queries `pg_collation` and `pg_database`, MySQL/MariaDB query `information_schema.character_sets`/`collations`). The hardcoded macOS-flavored locale list is gone. Engines that don't support creation hide the Create button instead of failing on click.
29+
- Introduced TableRows, Row, and Delta value types in TablePro/Models/Query/ as the foundation for the data grid row model rewrite. No callers migrated yet (Phase C.1 of the DataGrid refactor).
2730
- DataGrid columns and cells refactored to use a persistent column pool and typed cell view hierarchy. CPU usage on table switch reduced significantly through proper NSTableView reuse pool retention.
2831
- Data grid column identifiers are now the column name (with positional fallback for duplicate names), so saved widths follow the column across schema changes that shift its position. Identifier resolution moved from static `DataGridView` helpers to a `ColumnIdentitySchema` value type owned by the coordinator.
2932
- `ColumnLayoutStorage` singleton replaced by a `ColumnLayoutPersisting` protocol with an injectable `FileColumnLayoutPersister` default. The coordinator depends on the protocol, not the concrete class, so tests can substitute a fake.
@@ -67,7 +70,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6770
- Connection form: `usePrivateKey=true` from URL no longer disables Test/Create buttons
6871
- Transient connections from URL clean up keychain entries on connection failure
6972
- Native Search Field focus regression when clearing text
70-
- Using the template0 database to resolve database creation failures in PostgreSQL
73+
- PostgreSQL Create Database failed with `new collation incompatible with template database` on glibc-initialized servers (#927). Encodings, collations, and the `template1` defaults are now read from the server. `LC_CTYPE` mirrors `LC_COLLATE`, and `TEMPLATE template0` is added automatically when the chosen collation differs from `template1.datcollate`.
74+
- Redshift Create Database emitted PostgreSQL `LC_COLLATE` syntax which is invalid Redshift grammar. Now emits `COLLATE { CASE_SENSITIVE | CASE_INSENSITIVE }`.
7175

7276
## [0.36.0] - 2026-04-27
7377

Plugins/BigQueryDriverPlugin/BigQueryPluginDriver.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -805,9 +805,13 @@ internal final class BigQueryPluginDriver: PluginDatabaseDriver, @unchecked Send
805805
"CREATE OR REPLACE VIEW \(quoteIdentifier(viewName)) AS\nSELECT * FROM table_name;"
806806
}
807807

808-
func createDatabase(name: String, charset: String, collation: String?) async throws {
808+
func createDatabaseFormSpec() async throws -> PluginCreateDatabaseFormSpec? {
809+
PluginCreateDatabaseFormSpec(fields: [], footnote: nil)
810+
}
811+
812+
func createDatabase(_ request: PluginCreateDatabaseRequest) async throws {
809813
guard let conn = connection else { throw BigQueryError.notConnected }
810-
let escaped = name.replacingOccurrences(of: "`", with: "\\`")
814+
let escaped = request.name.replacingOccurrences(of: "`", with: "\\`")
811815
_ = try await conn.executeQuery("CREATE SCHEMA `\(escaped)`")
812816
}
813817

Plugins/BigQueryDriverPlugin/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
<plist version="1.0">
44
<dict>
55
<key>TableProPluginKitVersion</key>
6-
<integer>7</integer>
6+
<integer>8</integer>
77
</dict>
88
</plist>

Plugins/CSVExportPlugin/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
<plist version="1.0">
44
<dict>
55
<key>TableProPluginKitVersion</key>
6-
<integer>7</integer>
6+
<integer>8</integer>
77
</dict>
88
</plist>

Plugins/CassandraDriverPlugin/CassandraPlugin.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,8 +1237,12 @@ internal final class CassandraPluginDriver: PluginDatabaseDriver, @unchecked Sen
12371237
return databases.map { PluginDatabaseMetadata(name: $0) }
12381238
}
12391239

1240-
func createDatabase(name: String, charset: String, collation: String?) async throws {
1241-
let safeKs = escapeIdentifier(name)
1240+
func createDatabaseFormSpec() async throws -> PluginCreateDatabaseFormSpec? {
1241+
PluginCreateDatabaseFormSpec(fields: [], footnote: nil)
1242+
}
1243+
1244+
func createDatabase(_ request: PluginCreateDatabaseRequest) async throws {
1245+
let safeKs = escapeIdentifier(request.name)
12421246
let query = """
12431247
CREATE KEYSPACE "\(safeKs)"
12441248
WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 3}

Plugins/CassandraDriverPlugin/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<key>CFBundleVersion</key>
2020
<string>$(CURRENT_PROJECT_VERSION)</string>
2121
<key>TableProPluginKitVersion</key>
22-
<integer>7</integer>
22+
<integer>8</integer>
2323
<key>NSPrincipalClass</key>
2424
<string>$(PRODUCT_MODULE_NAME).CassandraPlugin</string>
2525
</dict>

Plugins/ClickHouseDriverPlugin/ClickHousePlugin.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -579,8 +579,12 @@ final class ClickHousePluginDriver: PluginDatabaseDriver, @unchecked Sendable {
579579
}
580580
}
581581

582-
func createDatabase(name: String, charset: String, collation: String?) async throws {
583-
let escapedName = name.replacingOccurrences(of: "`", with: "``")
582+
func createDatabaseFormSpec() async throws -> PluginCreateDatabaseFormSpec? {
583+
PluginCreateDatabaseFormSpec(fields: [], footnote: nil)
584+
}
585+
586+
func createDatabase(_ request: PluginCreateDatabaseRequest) async throws {
587+
let escapedName = request.name.replacingOccurrences(of: "`", with: "``")
584588
_ = try await execute(query: "CREATE DATABASE `\(escapedName)`")
585589
}
586590

Plugins/ClickHouseDriverPlugin/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
<plist version="1.0">
44
<dict>
55
<key>TableProPluginKitVersion</key>
6-
<integer>7</integer>
6+
<integer>8</integer>
77
</dict>
88
</plist>

Plugins/CloudflareD1DriverPlugin/CloudflareD1PluginDriver.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,12 +500,16 @@ final class CloudflareD1PluginDriver: PluginDatabaseDriver, @unchecked Sendable
500500
PluginDatabaseMetadata(name: database)
501501
}
502502

503-
func createDatabase(name: String, charset: String, collation: String?) async throws {
503+
func createDatabaseFormSpec() async throws -> PluginCreateDatabaseFormSpec? {
504+
PluginCreateDatabaseFormSpec(fields: [], footnote: nil)
505+
}
506+
507+
func createDatabase(_ request: PluginCreateDatabaseRequest) async throws {
504508
guard let client = getClient() else {
505509
throw CloudflareD1Error.notConnected
506510
}
507511

508-
let newDb = try await client.createDatabase(name: name)
512+
let newDb = try await client.createDatabase(name: request.name)
509513

510514
lock.lock()
511515
databaseNameToUuid[newDb.name] = newDb.uuid

Plugins/CloudflareD1DriverPlugin/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
<plist version="1.0">
44
<dict>
55
<key>TableProPluginKitVersion</key>
6-
<integer>7</integer>
6+
<integer>8</integer>
77
</dict>
88
</plist>

0 commit comments

Comments
 (0)