Skip to content

Commit

Permalink
Merge pull request #571 from rausnitz/safe-sum
Browse files Browse the repository at this point in the history
Safe sum
  • Loading branch information
tanner0101 authored Oct 17, 2018
2 parents 291aaec + 7f98167 commit 25eeedf
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 4 deletions.
13 changes: 10 additions & 3 deletions Sources/Fluent/QueryBuilder/QueryBuilder+Aggregate.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
extension QueryBuilder {
// MARK: Aggregate

/// Returns the sum of all entries for the supplied field.
/// Returns the sum of all entries for the supplied field, falling back to the default value if the Future containing the sum resolves to an Error.
///
/// let totalLikes = try Post.query(on: conn).sum(\.likes)
/// let totalViralPostLikes = try Post.query(on: conn).filter(\.likes >= 10_000_000).sum(\.likes, default: 0)
///
/// - parameters:
/// - field: Field to sum.
/// - default: Optional default to use.
/// - returns: A `Future` containing the sum.
public func sum<T>(_ field: KeyPath<Result, T>) -> Future<T> where T: Decodable {
return aggregate(Database.queryAggregateSum, field: field)
public func sum<T>(_ field: KeyPath<Result, T>, default: T? = nil) -> Future<T> where T: Decodable {
return aggregate(Database.queryAggregateSum, field: field).catchMap { error in
guard let d = `default` else {
throw error
}
return d
}
}

/// Returns the average of all entries for the supplied field.
Expand Down
33 changes: 32 additions & 1 deletion Sources/FluentBenchmark/Benchmarks/BenchmarkAggregate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,33 @@ extension Benchmarker where Database: QuerySupporting {
if all.count != count {
fail("wrong count: \(all.count) != \(count)")
}

let firstSummer = User<Database>(name: "Summer", age: 30)
let secondSummer = User<Database>(name: "Summer", age: 31)
_ = try test(firstSummer.create(on: conn))
_ = try test(secondSummer.create(on: conn))
let summersSum = try User<Database>.query(on: conn).filter(\.name == "Summer").sum(\.age).wait()
if summersSum != 61 {
fail("sum should be 61")
}

let autumn = User<Database>(name: "Autumn", age: 40)
do {
_ = try User<Database>.query(on: conn).filter(\.name == "Autumn").sum(\.age).wait()
fail("should not have produced a sum")
} catch {
let defaultSum = try User<Database>.query(on: conn).filter(\.name == "Autumn").sum(\.age, default: 0).wait()
if defaultSum != 0 {
fail("should have defaulted to 0")
}
}

_ = try test(autumn.create(on: conn))
let autumnsSum = try User<Database>.query(on: conn).filter(\.name == "Autumn").sum(\.age).wait()
let alsoAutumnsSum = try User<Database>.query(on: conn).filter(\.name == "Autumn").sum(\.age, default: 0).wait()
if autumnsSum != 40 || alsoAutumnsSum != 40 {
fail("sum should be 40, whether or not a default is provided")
}
}

public func benchmarkAggregate() throws {
Expand All @@ -26,8 +53,12 @@ extension Benchmarker where Database: QuerySupporting {
extension Benchmarker where Database: QuerySupporting & SchemaSupporting & MigrationSupporting {
public func benchmarkAggregate_withSchema() throws {
let conn = try test(pool.requestConnection())
defer { try? test(Galaxy<Database>.revert(on: conn)) }
defer {
try? test(Galaxy<Database>.revert(on: conn))
try? test(UserMigration<Database>.revert(on: conn))
}
try test(Galaxy<Database>.prepare(on: conn))
try test(UserMigration<Database>.prepare(on: conn))
try self._benchmark(on: conn)
pool.releaseConnection(conn)
}
Expand Down

0 comments on commit 25eeedf

Please sign in to comment.