Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixing join mapping - take 1 #410

Merged
merged 7 commits into from Mar 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 }
}