Skip to content

Commit

Permalink
postgres data encoder refactor (#161)
Browse files Browse the repository at this point in the history
* postgres data encoder refactor

* wrap calls to json encoder

* add fluent kit driver test

* test

* test

* _value

* retest w/ latest postgres-nio

* encoder + decoder fixes; sql-kit updates

* sql row updates
  • Loading branch information
tanner0101 authored Dec 13, 2019
1 parent 0943b3e commit 8d3a5d3
Show file tree
Hide file tree
Showing 5 changed files with 222 additions and 114 deletions.
22 changes: 22 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,25 @@ jobs:
steps:
- uses: actions/checkout@v1
- run: swift test --enable-test-discovery --sanitize=thread
fluent:
container:
image: vapor/swift:5.1
services:
psql:
image: postgres
ports:
- 5432:5432
env:
POSTGRES_USER: vapor_username
POSTGRES_DB: vapor_database
POSTGRES_PASSWORD: vapor_password
runs-on: ubuntu-latest
steps:
- run: git clone -b master https://github.com/vapor/fluent-postgres-driver.git
working-directory: ./
- run: swift package edit postgres-kit --revision ${{ github.sha }}
working-directory: ./fluent-postgres-driver
- run: swift test --enable-test-discovery --sanitize=thread
working-directory: ./fluent-postgres-driver
env:
POSTGRES_HOSTNAME: psql
101 changes: 78 additions & 23 deletions Sources/PostgresKit/PostgresDataDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,14 @@ public final class PostgresDataDecoder {
}
}

private final class _Decoder: Decoder {
enum _Error: Error {
case keyedElement
case unkeyedArray
case arrayElementJSON
case nesting
}

final class _Decoder: Decoder {
var codingPath: [CodingKey] {
return []
}
Expand All @@ -42,50 +49,98 @@ public final class PostgresDataDecoder {
}

func unkeyedContainer() throws -> UnkeyedDecodingContainer {
try self.jsonDecoder().unkeyedContainer()
print(self.data.type)
guard let data = self.data.array else {
throw _Error.unkeyedArray
}
return _UnkeyedDecoder(data: data, json: self.json)
}

func container<Key>(
keyedBy type: Key.Type
) throws -> KeyedDecodingContainer<Key> where Key : CodingKey {
try self.jsonDecoder().container(keyedBy: Key.self)
}

func jsonDecoder() throws -> Decoder {
guard let buffer = self.data.value else {
throw DecodingError.valueNotFound(Any.self, .init(
codingPath: self.codingPath,
debugDescription: "Cannot decode JSON from nil value"
))
guard self.data.type == .jsonb else {
throw _Error.arrayElementJSON
}
guard let json = self.data.jsonb else {
throw _Error.arrayElementJSON
}
let unwrapper = try self.json
.decode(DecoderUnwrapper.self, from: Data(buffer.readableBytesView))
return unwrapper.decoder
return try self.json
.decode(DecoderUnwrapper.self, from: json)
.decoder.container(keyedBy: Key.self)
}

func singleValueContainer() throws -> SingleValueDecodingContainer {
return _SingleValueDecoder(self)
_ValueDecoder(data: self.data, json: self.json)
}
}

private struct _SingleValueDecoder: SingleValueDecodingContainer {
struct _UnkeyedDecoder: UnkeyedDecodingContainer {
var count: Int? {
self.data.count
}

var isAtEnd: Bool {
self.currentIndex == self.data.count
}
var currentIndex: Int = 0

let data: [PostgresData]
let json: JSONDecoder
var codingPath: [CodingKey] {
return self.decoder.codingPath
[]
}

mutating func decodeNil() throws -> Bool {
defer { self.currentIndex += 1 }
return self.data[self.currentIndex].value == nil
}

mutating func decode<T>(_ type: T.Type) throws -> T where T : Decodable {
defer { self.currentIndex += 1 }
let data = self.data[self.currentIndex]
guard data.type == .jsonb else {
throw _Error.arrayElementJSON
}
guard let json = data.jsonb else {
throw _Error.arrayElementJSON
}
return try self.json.decode(T.self, from: json)
}

mutating func nestedContainer<NestedKey>(
keyedBy type: NestedKey.Type
) throws -> KeyedDecodingContainer<NestedKey>
where NestedKey : CodingKey
{
throw _Error.nesting
}

mutating func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
throw _Error.nesting
}
let decoder: _Decoder
init(_ decoder: _Decoder) {
self.decoder = decoder

mutating func superDecoder() throws -> Decoder {
throw _Error.nesting
}
}

struct _ValueDecoder: SingleValueDecodingContainer {
let data: PostgresData
let json: JSONDecoder
var codingPath: [CodingKey] {
[]
}

func decodeNil() -> Bool {
return self.decoder.data.value == nil
return self.data.value == nil
}

func decode<T>(_ type: T.Type) throws -> T where T : Decodable {
if let convertible = T.self as? PostgresDataConvertible.Type {
return convertible.init(postgresData: self.decoder.data)! as! T
return convertible.init(postgresData: self.data)! as! T
} else {
return try T.init(from: self.decoder)
return try T.init(from: _Decoder(data: self.data, json: self.json))
}
}
}
Expand Down
Loading

0 comments on commit 8d3a5d3

Please sign in to comment.