Skip to content

Commit 0943b3e

Browse files
Custom JSON Coders for Postgres Data Coders (vapor#159)
* Changed dependencies to Skelpo forks * Conformed PostgresDataDecoder to PostrgesDecoder and PostgresDataEncoder to PostgresEncoder * Added JSON encoder/decoder configurations to PostgresConfiguration initializer * Added .encoder and .decoder properties to _ConnectionPoolPostgresDatabase extension * Pass configuration.encoder and .decoder into PostgresConnection.connect call in PostgresConnectionSource.makeConnection method * Use PostgresRow.decoder to decode data in PostgresRow.decode(column:as:) method * Added .encoder and .decoder properties to _PostgresSQLDatabase * Use .encoder to encode query binds in _PostgresSQLDatabase.execute(sql:onRow:) method * Use .source instead of .sourceInfo propety in _ConnectionPoolPostgresDatabase.encoder and .decoder properties * Use skeplo/master for PostgresNIO until forks are merged * Replaced PostgresRow:SQLRow conformance with .sqlRow(using:) method This results in an erased private _PostgreSQLRow struct instance that handles all the confrmance * Replaced uses of Postgres<Coder> protocols with PostgresData<Coder> types * Use original PostgresNIO library instead of Skelpo fork * Fixed calls to PostgresConnection.sql(encoder:decoder:) in PostgresKitTests * Deleted Xcode workspace * Keep PostgresRow.sqlRow(using:) method internal * Removed PostgresConnection.sql() extension method * Pass in PostgresData coders instead of JSON coders to PostgresConfiguration init * Removed leftover PostgresData coder declarations in PostgresConnection.test(on:) method * Revert "Keep PostgresRow.sqlRow(using:) method internal" This reverts commit 0fa2d80. * Use registered JSONEncoder to handle DoJSON case in PostgresDataEncoder * Added default value to PostgresDataEncoder.init(json:) and PostgresDataDecoder.init(json:) initializers * Renamed PostgresRow.sqlRow(using:) method to .sql(using:) * Replace uses of PostgresRow.sqlRow with .sql * Revert all changes made for custom JSON * Add default value to PostgresRow.sql method Co-Authored-By: Tanner <me@tanner.xyz> * Fix PostgresDataDecoder paramater name for .sql call
1 parent a8538f3 commit 0943b3e

6 files changed

+55
-22
lines changed

Diff for: Sources/PostgresKit/ConnectionPool+Postgres.swift

+1-3
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ private struct _ConnectionPoolPostgresDatabase {
1010
}
1111

1212
extension _ConnectionPoolPostgresDatabase: PostgresDatabase {
13-
var eventLoop: EventLoop {
14-
self.pool.eventLoop
15-
}
13+
var eventLoop: EventLoop { self.pool.eventLoop }
1614

1715
func send(_ request: PostgresRequest, logger: Logger) -> EventLoopFuture<Void> {
1816
self.pool.withConnection(logger: logger) {

Diff for: Sources/PostgresKit/PostgresClient+SQL.swift

+11-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
1+
import PostgresNIO
2+
import Foundation
13
import SQLKit
24

35
extension PostgresDatabase {
4-
public func sql() -> SQLDatabase {
5-
_PostgresSQLDatabase(database: self)
6+
public func sql(
7+
encoder: PostgresDataEncoder = PostgresDataEncoder(),
8+
decoder: PostgresDataDecoder = PostgresDataDecoder()
9+
) -> SQLDatabase {
10+
_PostgresSQLDatabase(database: self, encoder: encoder, decoder: decoder)
611
}
712
}
813

914
private struct _PostgresSQLDatabase {
1015
let database: PostgresDatabase
16+
let encoder: PostgresDataEncoder
17+
let decoder: PostgresDataDecoder
1118
}
1219

1320
extension _PostgresSQLDatabase: SQLDatabase {
@@ -27,9 +34,9 @@ extension _PostgresSQLDatabase: SQLDatabase {
2734
let (sql, binds) = self.serialize(query)
2835
do {
2936
return try self.database.query(sql, binds.map { encodable in
30-
return try PostgresDataEncoder().encode(encodable)
37+
return try self.encoder.encode(encodable)
3138
}) { row in
32-
onRow(row)
39+
onRow(row.sql(decoder: self.decoder))
3340
}
3441
} catch {
3542
return self.eventLoop.makeFailedFuture(error)

Diff for: Sources/PostgresKit/PostgresConfiguration.swift

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1-
@_exported import struct Foundation.URL
1+
@_exported import Foundation
22

33
public struct PostgresConfiguration {
44
public let address: () throws -> SocketAddress
55
public let username: String
66
public let password: String
77
public let database: String?
88
public let tlsConfiguration: TLSConfiguration?
9-
9+
10+
public let encoder: PostgresDataEncoder
11+
public let decoder: PostgresDataDecoder
12+
1013
internal var _hostname: String?
1114

1215
public init?(url: URL) {
@@ -49,7 +52,9 @@ public struct PostgresConfiguration {
4952
username: String,
5053
password: String,
5154
database: String? = nil,
52-
tlsConfiguration: TLSConfiguration? = nil
55+
tlsConfiguration: TLSConfiguration? = nil,
56+
encoder: PostgresDataEncoder = PostgresDataEncoder(),
57+
decoder: PostgresDataDecoder = PostgresDataDecoder()
5358
) {
5459
self.address = {
5560
return try SocketAddress.makeAddressResolvingHost(hostname, port: port)
@@ -59,5 +64,7 @@ public struct PostgresConfiguration {
5964
self.password = password
6065
self.tlsConfiguration = tlsConfiguration
6166
self._hostname = hostname
67+
self.encoder = encoder
68+
self.decoder = decoder
6269
}
6370
}

Diff for: Sources/PostgresKit/PostgresDataDecoder.swift

+12-5
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,20 @@ struct DecoderUnwrapper: Decodable {
77
}
88
}
99

10-
public struct PostgresDataDecoder {
11-
public init() {}
10+
public final class PostgresDataDecoder {
11+
public let jsonDecoder: JSONDecoder
12+
13+
public init(json: JSONDecoder = JSONDecoder()) {
14+
self.jsonDecoder = json
15+
}
1216

1317
public func decode<T>(_ type: T.Type, from data: PostgresData) throws -> T
1418
where T: Decodable
1519
{
1620
if let convertible = T.self as? PostgresDataConvertible.Type {
1721
return convertible.init(postgresData: data)! as! T
1822
} else {
19-
return try T.init(from: _Decoder(data: data))
23+
return try T.init(from: _Decoder(data: data, json: self.jsonDecoder))
2024
}
2125
}
2226

@@ -30,8 +34,11 @@ public struct PostgresDataDecoder {
3034
}
3135

3236
let data: PostgresData
33-
init(data: PostgresData) {
37+
let json: JSONDecoder
38+
39+
init(data: PostgresData, json: JSONDecoder) {
3440
self.data = data
41+
self.json = json
3542
}
3643

3744
func unkeyedContainer() throws -> UnkeyedDecodingContainer {
@@ -51,7 +58,7 @@ public struct PostgresDataDecoder {
5158
debugDescription: "Cannot decode JSON from nil value"
5259
))
5360
}
54-
let unwrapper = try JSONDecoder()
61+
let unwrapper = try self.json
5562
.decode(DecoderUnwrapper.self, from: Data(buffer.readableBytesView))
5663
return unwrapper.decoder
5764
}

Diff for: Sources/PostgresKit/PostgresDataEncoder.swift

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import Foundation
22

3-
public struct PostgresDataEncoder {
4-
public init() { }
3+
public final class PostgresDataEncoder {
4+
public let jsonEncoder: JSONEncoder
5+
6+
public init(json: JSONEncoder = JSONEncoder()) {
7+
self.jsonEncoder = json
8+
}
59

610
public func encode(_ value: Encodable) throws -> PostgresData {
711
if let custom = value as? PostgresDataConvertible {
@@ -12,7 +16,8 @@ public struct PostgresDataEncoder {
1216
try value.encode(to: encoder)
1317
return encoder.data
1418
} catch is DoJSON {
15-
return try PostgresData(jsonb: Wrapper(value))
19+
let data = try self.jsonEncoder.encode(Wrapper(value))
20+
return PostgresData(jsonb: data)
1621
}
1722
}
1823
}

Diff for: Sources/PostgresKit/PostgresRow+SQL.swift

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
1-
extension PostgresRow: SQLRow {
2-
public func decode<D>(column: String, as type: D.Type) throws -> D where D : Decodable {
3-
guard let data = self.column(column) else {
1+
extension PostgresRow {
2+
public func sql(decoder: PostgresDataDecoder = .init()) -> SQLRow {
3+
return _PostgreSQLRow(row: self, decoder: decoder)
4+
}
5+
}
6+
7+
private struct _PostgreSQLRow: SQLRow {
8+
let row: PostgresRow
9+
let decoder: PostgresDataDecoder
10+
11+
func decode<D>(column: String, as type: D.Type) throws -> D where D : Decodable {
12+
guard let data = self.row.column(column) else {
413
fatalError()
514
}
6-
return try PostgresDataDecoder().decode(D.self, from: data)
15+
return try self.decoder.decode(D.self, from: data)
716
}
817
}

0 commit comments

Comments
 (0)