diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift index 597f6f910..51f79fd93 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLCapabilities.swift @@ -24,4 +24,5 @@ struct PostgreSQLCapabilities: Sendable, Equatable { var hasDatabaseICULocale: Bool { serverVersion >= 150_000 } var hasDatabaseLocale: Bool { serverVersion >= 170_000 } + var hasModernICUSyntax: Bool { serverVersion >= 160_000 } } diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift index c0aef3054..f1d4360f6 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver+Columns.swift @@ -10,7 +10,7 @@ extension PostgreSQLPluginDriver { func fetchColumns(table: String, schema: String?) async throws -> [PluginColumnInfo] { let safeSchema = escapeLiteralForColumns(currentSchema ?? "public") let safeTable = escapeLiteralForColumns(table) - let caps = capabilities + let caps = versionedCapabilities let identityProjection = caps.hasIdentityColumns ? "a.attidentity" : "NULL::text" let generatedProjection = caps.hasGeneratedColumns ? "a.attgenerated" : "NULL::text" let attributeJoin = (caps.hasIdentityColumns || caps.hasGeneratedColumns) ? """ @@ -60,7 +60,7 @@ extension PostgreSQLPluginDriver { func fetchAllColumns(schema: String?) async throws -> [String: [PluginColumnInfo]] { let safeSchema = escapeLiteralForColumns(currentSchema ?? "public") - let caps = capabilities + let caps = versionedCapabilities let identityProjection = caps.hasIdentityColumns ? "a.attidentity" : "NULL::text" let generatedProjection = caps.hasGeneratedColumns ? "a.attgenerated" : "NULL::text" let attributeJoin = (caps.hasIdentityColumns || caps.hasGeneratedColumns) ? """ diff --git a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift index 7f97515b2..7c9a85a21 100644 --- a/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift +++ b/Plugins/PostgreSQLDriverPlugin/PostgreSQLPluginDriver.swift @@ -22,7 +22,7 @@ final class PostgreSQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { var supportsTransactions: Bool { true } var serverVersion: String? { libpqConnection?.serverVersion() } var serverVersionNumber: Int32 { libpqConnection?.serverVersionNumber() ?? 0 } - var capabilities: PostgreSQLCapabilities { + var versionedCapabilities: PostgreSQLCapabilities { PostgreSQLCapabilities(serverVersion: serverVersionNumber) } var parameterStyle: ParameterStyle { .dollar } @@ -234,7 +234,7 @@ final class PostgreSQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { func fetchTables(schema: String?) async throws -> [PluginTableInfo] { let schemaLiteral = escapeLiteral(schema ?? _currentSchema) - let caps = capabilities + let caps = versionedCapabilities var unions: [String] = [ """ @@ -284,7 +284,7 @@ final class PostgreSQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { func fetchIndexes(table: String, schema: String?) async throws -> [PluginIndexInfo] { - let columnOrdering = capabilities.hasArrayPosition + let columnOrdering = versionedCapabilities.hasArrayPosition ? "ORDER BY array_position(ix.indkey, a.attnum)" : "ORDER BY a.attnum" let query = """ @@ -433,7 +433,7 @@ final class PostgreSQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { func fetchTableDDL(table: String, schema: String?) async throws -> String { let safeTable = escapeLiteral(table) let quotedTable = "\"\(table.replacingOccurrences(of: "\"", with: "\"\""))\"" - let caps = capabilities + let caps = versionedCapabilities let identityClause: String = caps.hasIdentityColumns ? """ CASE @@ -672,7 +672,7 @@ final class PostgreSQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { } func fetchDependentSequences(table: String, schema: String?) async throws -> [(name: String, ddl: String)] { - guard capabilities.hasSequencesCatalog else { return [] } + guard versionedCapabilities.hasSequencesCatalog else { return [] } let safeTable = escapeLiteral(table) let query = """ SELECT s.sequencename, @@ -720,7 +720,7 @@ final class PostgreSQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { ] func createDatabaseFormSpec() async throws -> PluginCreateDatabaseFormSpec? { - let supportsProvider = capabilities.hasDatabaseICULocale + let supportsProvider = versionedCapabilities.hasDatabaseICULocale async let templateDefaultsTask = fetchTemplate1Defaults() async let collationsTask = fetchCollations() @@ -813,7 +813,7 @@ final class PostgreSQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { var sql = "CREATE DATABASE \"\(quotedName)\" ENCODING '\(encoding)'" - let supportsProvider = capabilities.hasDatabaseICULocale + let supportsProvider = versionedCapabilities.hasDatabaseICULocale let provider = supportsProvider ? (request.values["provider"] ?? "libc") : "libc" switch provider { @@ -873,7 +873,7 @@ final class PostgreSQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { ) } let escapedIcu = escapeLiteral(icuLocale) - if let major = majorVersion, major >= 16 { + if versionedCapabilities.hasModernICUSyntax { sql += " LOCALE_PROVIDER 'icu' LOCALE '\(escapedIcu)' TEMPLATE template0" } else { sql += " LOCALE_PROVIDER 'icu' ICU_LOCALE '\(escapedIcu)' LC_COLLATE 'C' LC_CTYPE 'C' TEMPLATE template0" @@ -903,7 +903,7 @@ final class PostgreSQLPluginDriver: PluginDatabaseDriver, @unchecked Sendable { } private func fetchTemplate1Defaults() async -> Template1Defaults? { - let caps = capabilities + let caps = versionedCapabilities let selectColumns: String if caps.hasDatabaseLocale { selectColumns = "datcollate, datctype, datlocprovider, datlocale"