From 7bfa630a4f7dd06c439fa73568caa5491356a7bd Mon Sep 17 00:00:00 2001 From: Linus Bohle Date: Fri, 4 Feb 2022 11:20:58 +0100 Subject: [PATCH] final touches on iteration #1 of compatibility warnings for aggregation stages vs. connection MongoDB version --- Sources/MongoKitten/Aggregate.swift | 4 ++-- Sources/MongoKitten/AggregateStage.swift | 17 +---------------- .../QueryPrimitives/Projection.swift | 19 +++++++++++++++++++ 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/Sources/MongoKitten/Aggregate.swift b/Sources/MongoKitten/Aggregate.swift index c93b0b72..859adc3b 100644 --- a/Sources/MongoKitten/Aggregate.swift +++ b/Sources/MongoKitten/Aggregate.swift @@ -66,9 +66,9 @@ public struct AggregateBuilderPipeline: QueryCursor { #if DEBUG - let minimalVersionRequired = stages.compactMap { \.minimalVersionRequired }.max() + let minimalVersionRequired = stages.compactMap(\.minimalVersionRequired).max() - if let actualVersion = connection.wireVersion, let minimalVersion = minimalVersionRequired, actualVersion < minimalVersion { + if let actualVersion = await connection.wireVersion, let minimalVersion = minimalVersionRequired, actualVersion < minimalVersion { connection.logger.warning("Aggregation might fail since one or more aggregation stages require a higher MongoDB version than provided by the current connection.") } diff --git a/Sources/MongoKitten/AggregateStage.swift b/Sources/MongoKitten/AggregateStage.swift index 682cd40d..fad1bee1 100644 --- a/Sources/MongoKitten/AggregateStage.swift +++ b/Sources/MongoKitten/AggregateStage.swift @@ -39,24 +39,9 @@ public struct AggregateBuilderStage { } public static func project(_ projection: Projection) -> AggregateBuilderStage { - func valueUnwrapper(_ value: Primitive) -> WireVersion?{ - switch value { - case let value as Int32: - (value == 0) ? return .mongo3_4 : return nil // indicates excluded fields - case let value as String: - (value == "$$REMOVE") ? return .mongo3_6 : return nil // indicates conditionally excluded fields - case let value as Document: - return valueUnwrapper(value) - default: - return nil - } - } - - let minimalVersionRequired: WireVersion? = projection.document.values.compactMap{ valueUnwrapper($0) }.min() - return AggregateBuilderStage(document: [ "$project": projection.document - ], minimalVersion: minimalVersionRequired) + ], minimalVersion: projection.minimalVersion) } public static func project(_ fields: String...) -> AggregateBuilderStage { diff --git a/Sources/MongoKittenCore/QueryPrimitives/Projection.swift b/Sources/MongoKittenCore/QueryPrimitives/Projection.swift index ffd5be4a..8bf884b0 100644 --- a/Sources/MongoKittenCore/QueryPrimitives/Projection.swift +++ b/Sources/MongoKittenCore/QueryPrimitives/Projection.swift @@ -2,9 +2,28 @@ import BSON public struct Projection: Encodable, ExpressibleByDictionaryLiteral { public internal(set) var document: Document + public internal(set) var minimalVersion: WireVersion? { + func valueUnwrapper(_ value: Primitive) -> WireVersion?{ + switch value { + case let value as Int32: + return value == 0 ? .mongo3_4 : nil // indicates excluded fields + case let value as String: + return value == "$$REMOVE" ? .mongo3_6 : nil // indicates conditionally excluded fields + case let value as Document: + return value.values.compactMap(valueUnwrapper).max() + default: + return nil + } + } + + return self.document.values.compactMap(valueUnwrapper).max() + } /// An expression that can be specified to either include or exclude a field (or some custom value) public enum ProjectionExpression: ExpressibleByBooleanLiteral, ExpressibleByStringLiteral, ExpressibleByDictionaryLiteral, PrimitiveConvertible { + /// Conditional exclusion of a field from the projection + public static let remove = ProjectionExpression.custom("$$REMOVE") + /// Creates a BSON.Primitive of this ProjectionExpression for easy embedding in Documents public func makePrimitive() -> Primitive? { switch self {