Skip to content

Commit

Permalink
Redesign the request protocol hierarchy:
Browse files Browse the repository at this point in the history
DatabaseRequest -> SelectStatementRequest -> FetchRequest

This commit has two goals:

- introduce a protocol without any associated type which can feed RxGRDB multiple-requests observation methods without user pain (RxSwiftCommunity/RxGRDB#27 (comment))
- introduce a protocol that can feed RxGRDB observers and is able to execute multiple SQL queries (the eventual future "fetch all authors with all their books" request).
  • Loading branch information
groue committed Mar 13, 2018
1 parent 91e88fb commit 2750230
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 20 deletions.
62 changes: 42 additions & 20 deletions GRDB/Core/FetchRequest.swift
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
/// The protocol for all types that define a way to fetch database content.
///
/// struct Player: FetchableRecord { ... }
/// let request: ... // Some FetchRequest that fetches Player
/// try request.fetchCursor(db) // Cursor of Player
/// try request.fetchAll(db) // [Player]
/// try request.fetchOne(db) // Player?
public protocol FetchRequest {
/// The type that can convert raw database rows to fetched values
associatedtype RowDecoder

// MARK: - DatabaseRequest

/// The protocol for all types that request database values.
public protocol DatabaseRequest {
/// The database region that the request looks into.
///
/// - parameter db: A database connection.
func fetchedRegion(_ db: Database) throws -> DatabaseRegion
}

// MARK: - SelectStatementRequest

/// The protocol for all requests that run from a single select statement.
public protocol SelectStatementRequest: DatabaseRequest {
/// A tuple that contains a prepared statement that is ready to be
/// executed, and an eventual row adapter.
///
/// - parameter db: A database connection.
/// - returns: A prepared statement and an eventual row adapter.
func prepare(_ db: Database) throws -> (SelectStatement, RowAdapter?)

/// The number of rows fetched by the request.
///
/// Default implementation builds a naive SQL query based on the statement
/// returned by the `prepare` method: `SELECT COUNT(*) FROM (...)`.
///
/// Adopting types can refine this countRequest method and return more
/// Adopting types can refine this method in order to use more
/// efficient SQL.
///
/// - parameter db: A database connection.
func fetchCount(_ db: Database) throws -> Int

/// The database region that the request looks into.
///
/// This method has a default implementation.
///
/// - parameter db: A database connection.
func fetchedRegion(_ db: Database) throws -> DatabaseRegion
}

extension FetchRequest {
extension SelectStatementRequest {
// Default implementation
/// The number of rows fetched by the request.
///
/// This default implementation builds a naive SQL query based on the
Expand All @@ -45,6 +45,7 @@ extension FetchRequest {
return try Int.fetchOne(db, sql, arguments: statement.arguments)!
}

// Default implementation
/// The database region that the request looks into.
///
/// - parameter db: A database connection.
Expand All @@ -54,6 +55,21 @@ extension FetchRequest {
}
}

// MARK: - FetchRequest

/// The protocol for all requests that run from a single select statement, and
/// tell how fetched rows should be interpreted.
///
/// struct Player: FetchableRecord { ... }
/// let request: ... // Some FetchRequest that fetches Player
/// try request.fetchCursor(db) // Cursor of Player
/// try request.fetchAll(db) // [Player]
/// try request.fetchOne(db) // Player?
public protocol FetchRequest: SelectStatementRequest {
/// The type that tells how fetched database rows should be interpreted.
associatedtype RowDecoder
}

extension FetchRequest {
/// Returns a request bound to type T.
///
Expand All @@ -78,6 +94,8 @@ extension FetchRequest {
}
}

// MARK: - AdaptedFetchRequest

/// An adapted request.
public struct AdaptedFetchRequest<Base: FetchRequest> : FetchRequest {
public typealias RowDecoder = Base.RowDecoder
Expand Down Expand Up @@ -113,6 +131,8 @@ public struct AdaptedFetchRequest<Base: FetchRequest> : FetchRequest {
}
}

// MARK: - AnyFetchRequest

/// A type-erased FetchRequest.
///
/// An AnyFetchRequest forwards its operations to an underlying request,
Expand Down Expand Up @@ -166,6 +186,8 @@ public struct AnyFetchRequest<T> : FetchRequest {
}
}

// MARK: - SQLRequest

/// A Request built from raw SQL.
public struct SQLRequest<T> : FetchRequest {
public typealias RowDecoder = T
Expand Down
9 changes: 9 additions & 0 deletions GRDB/QueryInterface/RequestProtocols.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// MARK: - SelectionRequest

/// The protocol for all requests that can refine their selection.
public protocol SelectionRequest {
/// Creates a request with a new net of selected columns.
Expand Down Expand Up @@ -59,6 +61,8 @@ extension SelectionRequest {
}
}

// MARK: - FilteredRequest

/// The protocol for all requests that can be filtered.
public protocol FilteredRequest {
/// Creates a request with the provided *predicate* added to the
Expand Down Expand Up @@ -89,6 +93,8 @@ extension FilteredRequest {
}
}

// MARK: - AggregatingRequest

/// The protocol for all requests that can aggregate.
public protocol AggregatingRequest {
/// Creates a request grouped according to *expressions*.
Expand Down Expand Up @@ -127,6 +133,8 @@ extension AggregatingRequest {
}
}

// MARK: - OrderedRequest

/// The protocol for all requests that be ordered.
public protocol OrderedRequest {
/// Creates a request with the provided *orderings*.
Expand Down Expand Up @@ -201,3 +209,4 @@ extension OrderedRequest {
return order([expression])
}
}

0 comments on commit 2750230

Please sign in to comment.