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

Rename TypedRequest to FetchRequest, drop Request #311

Merged
merged 7 commits into from
Feb 27, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,104 @@
Release Notes
=============

## Next Version

### Breaking Changes

- `Request` and `TypedRequest` protocols have been merged into `FetchRequest`.

### API diff

FetchRequest

```diff
+protocol FetchRequest {
+ associatedtype RowDecoder
+ func prepare(_ db: Database) throws -> (SelectStatement, RowAdapter?)
+ func fetchCount(_ db: Database) throws -> Int
+ func fetchedRegion(_ db: Database) throws -> DatabaseRegion
+}
+extension FetchRequest {
+ func fetchCount(_ db: Database) throws -> Int
+ func fetchedRegion(_ db: Database) throws -> DatabaseRegion
+ func asRequest<T>(of type: T.Type) -> AnyFetchRequest<T>
+ func adapted(_ adapter: @escaping (Database) throws -> RowAdapter) -> AdaptedFetchRequest<Self>
+}
+struct AdaptedFetchRequest<Base: FetchRequest> : FetchRequest {
+ typealias RowDecoder = Base.RowDecoder
+}
+struct AnyFetchRequest<T> : FetchRequest {
+ typealias RowDecoder = T
+ init<Request: FetchRequest>(_ request: Request)
+ init(_ prepare: @escaping (Database) throws -> (SelectStatement, RowAdapter?))
+}
+struct SQLRequest<T> : FetchRequest {
+ typealias RowDecoder = T
+ let sql: String
+ let arguments: StatementArguments?
+ let adapter: RowAdapter?
+ init(_ sql: String, arguments: StatementArguments? = nil, adapter: RowAdapter? = nil, cached: Bool = false)
+ init<Request: FetchRequest>(_ db: Database, request: Request, cached: Bool = false) throws where Request.RowDecoder == RowDecoder
+}

+extension FetchRequest where RowDecoder: DatabaseValueConvertible {
+ func fetchCursor(_ db: Database) throws -> DatabaseValueCursor<RowDecoder>
+ func fetchAll(_ db: Database) throws -> [RowDecoder]
+ func fetchOne(_ db: Database) throws -> RowDecoder?
+
}
+extension FetchRequest where RowDecoder: _OptionalProtocol, RowDecoder._Wrapped: DatabaseValueConvertible
+ func fetchCursor(_ db: Database) throws -> NullableDatabaseValueCursor<RowDecoder._Wrapped>
+ func fetchAll(_ db: Database) throws -> [RowDecoder._Wrapped?]
+}

+extension FetchRequest where RowDecoder: Row {
+ func fetchCursor(_ db: Database) throws -> RowCursor
+ func fetchAll(_ db: Database) throws -> [Row]
+ func fetchOne(_ db: Database) throws -> Row?
+}

+extension FetchRequest where RowDecoder: RowConvertible {
+ func fetchCursor(_ db: Database) throws -> RecordCursor<RowDecoder>
+ func fetchAll(_ db: Database) throws -> [RowDecoder]
+ func fetchOne(_ db: Database) throws -> RowDecoder?
+}

-protocol Request { }
-struct AdaptedRequest : Request { }
-struct AnyRequest : Request { }
-struct SQLRequest : Request { }
-protocol TypedRequest : Request { }
-struct AdaptedTypedRequest<Base: TypedRequest> : TypedRequest { }
-struct AnyTypedRequest<T> : TypedRequest { }

-extension DatabaseValueConvertible {
- static func fetchCursor(_ db: Database, _ request: Request) throws -> DatabaseValueCursor<Self>
- static func fetchAll(_ db: Database, _ request: Request) throws -> [Self]
- static func fetchOne(_ db: Database, _ request: Request) throws -> Self?
-}

-extension Optional where Wrapped: DatabaseValueConvertible {
- static func fetchCursor(_ db: Database, _ request: Request) throws -> NullableDatabaseValueCursor<Wrapped>
- static func fetchAll(_ db: Database, _ request: Request) throws -> [Wrapped?]
-}

-extension Row {
- static func fetchCursor(_ db: Database, _ request: Request) throws -> RowCursor
- static func fetchAll(_ db: Database, _ request: Request) throws -> [Row]
- static func fetchOne(_ db: Database, _ request: Request) throws -> Row?
-}

-extension RowConvertible {
- static func fetchCursor(_ db: Database, _ request: Request) throws -> RecordCursor<Self>
- static func fetchAll(_ db: Database, _ request: Request) throws -> [Self]
- static func fetchOne(_ db: Database, _ request: Request) throws -> Self?
-}

-extension QueryInterfaceRequest : TypedRequest { }
+extension QueryInterfaceRequest : FetchRequest { }
```

## 2.9.0

Released February 25, 2018 &bull; [diff](https://github.com/groue/GRDB.swift/compare/v2.8.0...v2.9.0)
Expand Down
45 changes: 20 additions & 25 deletions Documentation/WhyAdoptGRDB.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ For further information about GRDB concurrency, check its detailed [Concurrency

SQL is a weird language. Born in the 70s, easy to [misuse](https://xkcd.com/327/), feared by some developers, despised by others, and yet wonderfully concise and powerful.

GRDB provides high-level record methods that generate SQL for you:
GRDB records can generate SQL for you:

```swift
// SELECT * FROM players ORDER BY score DESC LIMIT 10
Expand All @@ -196,7 +196,7 @@ let exAequoCount: Int = try Player
.fetchCount(db)
```

But you can *always* switch to SQL when you want to:
But you can always switch to SQL when you want to:

```swift
let bestPlayers: [Player] = try Player.fetchAll(db, """
Expand All @@ -212,42 +212,37 @@ let exAequoCount: Int? = try Int.fetchOne(db, """
""", arguments: [maximumScore])
```

SQL is also welcome in high-level database observation tools like [FetchedRecordsController] and [RxGRDB]:
In performance-critical sections, you may want to deal with raw database rows, and fetch [lazy cursors](https://github.com/groue/GRDB.swift/blob/master/README.md#cursors) instead of arrays:

```swift
SQLRequest("SELECT * FROM players ORDER BY score DESC LIMIT 10")
.asRequest(of: Player.self)
.rx
.fetchAll(in: dbQueue)
.subscribe(onNext: { players: [Player] in
print("Best 10 players have changed")
})
```

You can of course deal with raw database rows, and fetch [lazy cursors](https://github.com/groue/GRDB.swift/blob/master/README.md#cursors) instead of arrays:

```swift
let rows = try Row.fetchCursor(db, "SELECT * FROM players")
let rows = try Row.fetchCursor(db, "SELECT id, name, score FROM players")
while let row = try rows.next() {
let id: Int64 = row["id"]
let name: String = row["name"]
let score: Int = row["score"]
let id: Int64 = row[0]
let name: String = row[1]
let score: Int = row[2]
}
```

When you feel like your code clarity would be enhanced by hiding your custom SQL in a dedicated method, you can build [custom requests](https://github.com/groue/GRDB.swift/blob/master/README.md#custom-requests):

```swift
extension Player {
static func customRequest(...) -> AnyTypedRequest<Player> {
return SQLRequest("""
SELECT ...
""", arguments: ...)
.asRequestOf(Player.self)
static func customRequest(...) -> SQLRequest<Player> {
return SQLRequest<Player>("SELECT ...", arguments: ...)
}
}

let players = Player.customRequest(...).fetchAll(db)
let players = try Player.customRequest(...).fetchAll(db)
```

Those custom requests are welcome in database observation tools like [FetchedRecordsController] and [RxGRDB]:

```swift
Player.customRequest(...)
.rx.fetchAll(in: dbQueue)
.subscribe(onNext: { players: [Player] in
print("Players have changed")
})
```

---
Expand Down
Loading