Skip to content

Commit

Permalink
Merge pull request #410 from rafiki270/fixing-join-mapping
Browse files Browse the repository at this point in the history
fixing join mapping - take 1
  • Loading branch information
tanner0101 committed Mar 20, 2018
2 parents 580a953 + 8a5109b commit 666352d
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 10 deletions.
7 changes: 4 additions & 3 deletions Sources/Fluent/Query/Builder/QueryBuilder.swift
Expand Up @@ -97,7 +97,7 @@ public final class QueryBuilder<Model, Result> where Model: Fluent.Model, Model.

/// Sets the query to decode type `D` when run.
public func decode<D>(_ type: D.Type, entity: String = Model.entity) -> QueryBuilder<Model, D> where D: Decodable {
let decoder = QueryDataDecoder(Model.Database.self)
let decoder = QueryDataDecoder(Model.Database.self, entity: entity)
return changeResult { row, conn in
let row = row.onlyValues(forEntity: entity)
return Future.map(on: conn) {
Expand All @@ -109,7 +109,7 @@ public final class QueryBuilder<Model, Result> where Model: Fluent.Model, Model.
/// Adds an additional type `D` to be decoded when run.
/// The new result for this query will be a tuple containing the previous result and this new result.
public func alsoDecode<D>(_ type: D.Type, entity: String) -> QueryBuilder<Model, (Result, D)> where D: Decodable {
let decoder = QueryDataDecoder(Model.Database.self)
let decoder = QueryDataDecoder(Model.Database.self, entity: entity)
return transformResult { row, conn, result in
let row = row.onlyValues(forEntity: entity)
return Future.map(on: conn) {
Expand All @@ -131,7 +131,7 @@ extension Model where Database: QuerySupporting {
static func query<D>(decoding type: D.Type, on connection: Future<Self.Database.Connection>) -> QueryBuilder<Self, D> where D: Decodable {
return QueryBuilder<Self, D>.make(on: connection) { row, conn in
return Future.map(on: conn) {
let decoder = QueryDataDecoder(Self.Database.self)
let decoder = QueryDataDecoder(Self.Database.self, entity: Self.entity)
return try decoder.decode(D.self, from: row)
}
}
Expand All @@ -146,3 +146,4 @@ extension Model where Database: QuerySupporting {
}
}
}

30 changes: 23 additions & 7 deletions Sources/Fluent/Query/Codable/QueryDataDecoder.swift
@@ -1,7 +1,10 @@
final class QueryDataDecoder<Database> where Database: QuerySupporting {
init(_ database: Database.Type) { }
var entity: String?
init(_ database: Database.Type, entity: String? = nil) {
self.entity = entity
}
func decode<D>(_ type: D.Type, from data: [QueryField: Database.QueryData]) throws -> D where D: Decodable {
let decoder = _QueryDataDecoder<Database>(data: data)
let decoder = _QueryDataDecoder<Database>(data: data, entity: entity)
return try D.init(from: decoder)
}
}
Expand All @@ -12,12 +15,14 @@ fileprivate final class _QueryDataDecoder<Database>: Decoder where Database: Que
var codingPath: [CodingKey] { return [] }
var userInfo: [CodingUserInfoKey: Any] { return [:] }
var data: [QueryField: Database.QueryData]
init(data: [QueryField: Database.QueryData]) {
var entity: String?
init(data: [QueryField: Database.QueryData], entity: String?) {
self.data = data
self.entity = entity
}

func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key : CodingKey {
return KeyedDecodingContainer(_QueryDataKeyedDecoder<Key, Database>(decoder: self))
return KeyedDecodingContainer(_QueryDataKeyedDecoder<Key, Database>(decoder: self, entity: entity))
}

func unkeyedContainer() throws -> UnkeyedDecodingContainer { throw unsupported() }
Expand All @@ -44,20 +49,30 @@ fileprivate struct _QueryDataKeyedDecoder<K, Database>: KeyedDecodingContainerPr
}
var codingPath: [CodingKey] { return [] }
let decoder: _QueryDataDecoder<Database>
init(decoder: _QueryDataDecoder<Database>) {
var entity: String?
init(decoder: _QueryDataDecoder<Database>, entity: String?) {
self.decoder = decoder
self.entity = entity
}

func _value(forEntity entity: String?, atField field: String) -> Database.QueryData? {
print("Entity is: \(entity ?? "unknown")")
guard let entity = entity else {
return decoder.data.firstValue(forField: field)
}
return decoder.data.value(forEntity: entity, atField: field) ?? decoder.data.firstValue(forField: field)
}

func _parse<T>(_ type: T.Type, forKey key: K) throws -> T? {
guard let data = decoder.data.firstValue(forField: key.stringValue) else {
guard let data = _value(forEntity: entity, atField: key.stringValue) else {
return nil
}

return try Database.queryDataParse(T.self, from: data)
}

func contains(_ key: K) -> Bool { return decoder.data.keys.contains { $0.name == key.stringValue } }
func decodeNil(forKey key: K) throws -> Bool { return decoder.data.firstValue(forField: key.stringValue) == nil }
func decodeNil(forKey key: K) throws -> Bool { return _value(forEntity: entity, atField: key.stringValue) == nil }
func decodeIfPresent(_ type: Int.Type, forKey key: K) throws -> Int? { return try _parse(Int.self, forKey: key) }
func decodeIfPresent(_ type: Int8.Type, forKey key: K) throws -> Int8? { return try _parse(Int8.self, forKey: key) }
func decodeIfPresent(_ type: Int16.Type, forKey key: K) throws -> Int16? { return try _parse(Int16.self, forKey: key) }
Expand Down Expand Up @@ -86,3 +101,4 @@ fileprivate struct _QueryDataKeyedDecoder<K, Database>: KeyedDecodingContainerPr
func superDecoder() throws -> Decoder { return decoder }
func superDecoder(forKey key: K) throws -> Decoder { return decoder }
}

0 comments on commit 666352d

Please sign in to comment.