diff --git a/Package.resolved b/Package.resolved index e0da6c8..a22b9a1 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,13 +1,13 @@ { - "originHash" : "fa52841b94ca393999caeb6b5bae49eec5f6dc7f48c7920b5cbfe47915ddb293", + "originHash" : "7d26a26963ba38c459f6f07137975ce10b735b047b1cfc60429a6e34416f59f6", "pins" : [ { "identity" : "feather-database", "kind" : "remoteSourceControl", "location" : "https://github.com/feather-framework/feather-database", "state" : { - "revision" : "4ef69e67018c4bdf843858e8976c13b97c3afe4c", - "version" : "1.0.0-beta.3" + "revision" : "8bd475b24dcf18b9b03534c99c5ccf626a8d38b9", + "version" : "1.0.0-beta.4" } }, { diff --git a/Package.swift b/Package.swift index 80e44c6..029f8d3 100644 --- a/Package.swift +++ b/Package.swift @@ -37,7 +37,7 @@ let package = Package( dependencies: [ .package(url: "https://github.com/apple/swift-log", from: "1.6.0"), .package(url: "https://github.com/vapor/postgres-nio", from: "1.27.0"), - .package(url: "https://github.com/feather-framework/feather-database", exact: "1.0.0-beta.3"), + .package(url: "https://github.com/feather-framework/feather-database", exact: "1.0.0-beta.4"), // [docc-plugin-placeholder] ], targets: [ diff --git a/README.md b/README.md index bed4523..31f9d48 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,11 @@ Postgres driver implementation for the abstract [Feather Database](https://github.com/feather-framework/feather-database) Swift API package. -[![Release: 1.0.0-beta.2](https://img.shields.io/badge/Release-1%2E0%2E0--beta%2E2-F05138)](https://github.com/feather-framework/feather-postgres-database/releases/tag/1.0.0-beta.2) +[ + ![Release: 1.0.0-beta.3](https://img.shields.io/badge/Release-1%2E0%2E0--beta%2E3-F05138) +]( + https://github.com/feather-framework/feather-postgres-database/releases/tag/1.0.0-beta.3 +) ## Features @@ -33,7 +37,7 @@ Postgres driver implementation for the abstract [Feather Database](https://githu Add the dependency to your `Package.swift`: ```swift -.package(url: "https://github.com/feather-framework/feather-postgres-database", exact: "1.0.0-beta.2"), +.package(url: "https://github.com/feather-framework/feather-postgres-database", exact: "1.0.0-beta.3"), ``` Then add `FeatherPostgresDatabase` to your target dependencies: diff --git a/Sources/FeatherPostgresDatabase/PostgresDatabaseConnection.swift b/Sources/FeatherPostgresDatabase/PostgresDatabaseConnection.swift index b255861..6cd107c 100644 --- a/Sources/FeatherPostgresDatabase/PostgresDatabaseConnection.swift +++ b/Sources/FeatherPostgresDatabase/PostgresDatabaseConnection.swift @@ -8,9 +8,38 @@ import FeatherDatabase import PostgresNIO +extension DatabaseQuery { + + fileprivate func toPostgresQuery() -> PostgresQuery { + var postgresUnsafeSQL = sql + var postgresBindings: PostgresBindings = .init() + + for binding in bindings { + /// postgres binding index starts with 1 + let idx = binding.index + 1 + postgresUnsafeSQL = + postgresUnsafeSQL + .replacing("{{\(idx)}}", with: "$\(idx)") + + switch binding.binding { + case .int(let value): + postgresBindings.append(value) + case .double(let value): + postgresBindings.append(value) + case .string(let value): + postgresBindings.append(value) + } + } + + return .init( + unsafeSQL: postgresUnsafeSQL, + binds: postgresBindings + ) + } +} + public struct PostgresDatabaseConnection: DatabaseConnection { - public typealias Query = PostgresDatabaseQuery public typealias RowSequence = PostgresDatabaseRowSequence var connection: PostgresConnection @@ -26,15 +55,12 @@ public struct PostgresDatabaseConnection: DatabaseConnection { /// - Returns: A query result containing the returned rows. @discardableResult public func run( - query: Query, + query: DatabaseQuery, _ handler: (RowSequence) async throws -> T = { $0 } ) async throws(DatabaseError) -> T { do { let sequence = try await connection.query( - .init( - unsafeSQL: query.sql, - binds: query.bindings - ), + query.toPostgresQuery(), logger: logger ) diff --git a/Sources/FeatherPostgresDatabase/PostgresDatabaseQuery.swift b/Sources/FeatherPostgresDatabase/PostgresDatabaseQuery.swift deleted file mode 100644 index 04e6cff..0000000 --- a/Sources/FeatherPostgresDatabase/PostgresDatabaseQuery.swift +++ /dev/null @@ -1,159 +0,0 @@ -// -// PostgresDatabaseQuery.swift -// feather-postgres-database -// -// Created by Tibor Bödecs on 2026. 01. 10. -// - -import FeatherDatabase -import PostgresNIO - -public struct PostgresDatabaseQuery: DatabaseQuery { - /// The bindings type for Postgres queries. - /// - /// This type represents parameter bindings for PostgresNIO. - public typealias Bindings = PostgresBindings - - /// The SQL text to execute. - /// - /// This is the raw SQL string for the query. - public var sql: String { - query.sql - } - - /// The bound parameters for the SQL text. - /// - /// This exposes the underlying `binds` storage. - public var bindings: PostgresBindings { - query.binds - } - - var query: PostgresQuery - -} - -extension PostgresDatabaseQuery: ExpressibleByStringInterpolation { - - public init( - stringLiteral value: String - ) { - self.init(query: .init(stringLiteral: value)) - } - - public init( - stringInterpolation value: StringInterpolation - ) { - self.init( - query: .init( - unsafeSQL: value.sql, - binds: value.binds - ) - ) - } -} - -extension PostgresDatabaseQuery { - - // NOTE: source derived from postgres-nio - public struct StringInterpolation: StringInterpolationProtocol, Sendable { - public typealias StringLiteralType = String - - @usableFromInline - var sql: String - - @usableFromInline - var binds: PostgresBindings - - public init( - literalCapacity: Int, - interpolationCount: Int - ) { - self.sql = "" - self.binds = PostgresBindings(capacity: interpolationCount) - } - - public mutating func appendLiteral( - _ literal: String - ) { - self.sql.append(contentsOf: literal) - } - - @inlinable - public mutating func appendInterpolation< - Value: PostgresThrowingDynamicTypeEncodable - >( - _ value: Value - ) throws { - try self.binds.append(value, context: .default) - self.sql.append(contentsOf: "$\(self.binds.count)") - } - - @inlinable - public mutating func appendInterpolation< - Value: PostgresThrowingDynamicTypeEncodable - >( - _ value: Value? - ) throws { - switch value { - case .none: - self.binds.appendNull() - case .some(let value): - try self.binds.append(value, context: .default) - } - - self.sql.append(contentsOf: "$\(self.binds.count)") - } - - @inlinable - public mutating func appendInterpolation< - Value: PostgresDynamicTypeEncodable - >( - _ value: Value - ) { - self.binds.append(value, context: .default) - self.sql.append(contentsOf: "$\(self.binds.count)") - } - - @inlinable - public mutating func appendInterpolation< - Value: PostgresDynamicTypeEncodable - >( - _ value: Value? - ) { - switch value { - case .none: - self.binds.appendNull() - case .some(let value): - self.binds.append(value, context: .default) - } - - self.sql.append(contentsOf: "$\(self.binds.count)") - } - - @inlinable - public mutating func appendInterpolation< - Value: PostgresThrowingDynamicTypeEncodable, - JSONEncoder: PostgresJSONEncoder - >( - _ value: Value, - context: PostgresEncodingContext - ) throws { - try self.binds.append(value, context: context) - self.sql.append(contentsOf: "$\(self.binds.count)") - } - - @inlinable - public mutating func appendInterpolation( - unescaped interpolated: String - ) { - self.sql.append(contentsOf: interpolated) - } - - @inlinable - public mutating func appendInterpolation( - unescaped interpolated: Int - ) { - self.sql.append(contentsOf: String(interpolated)) - } - } -}