Skip to content

Expose reading errors #148

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

Merged
merged 80 commits into from
Nov 30, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
b9fea2e
Introduce DatabaseCursor (addresses #147)
groue Nov 25, 2016
fab64c6
Add DatabaseCursor to CHANGELOG, fix FTS5, and some TODO (addresses #…
groue Nov 25, 2016
d97360e
DatabaseCursor.enumerated, filter, forEach, map, reduce (addresses #147)
groue Nov 25, 2016
2eb190d
Base DatabaseSequence on DatabaseCursor (addresses #147)
groue Nov 25, 2016
20a7c55
DatabaseCursor.enumerated, filter, forEach, map, reduce are public. …
groue Nov 26, 2016
b0db219
#147: Rename DatabaseCursor.step() into next
groue Nov 26, 2016
b31356a
#147: Database.tableExists(_:) and Database.indexes(on:) can now thro…
groue Nov 26, 2016
ab62abe
#147: use cursor
groue Nov 26, 2016
8215791
cleanup
groue Nov 26, 2016
e5a9159
#147: tests for DatabaseValueConvertible.fetchCursor() methods
groue Nov 26, 2016
c80f0d3
#147: Array(cursor) initialiser; base all fetchAll and fetchOne metho…
groue Nov 26, 2016
a0e5f64
#147: tests for StatementColumnConvertible.fetchCursor() methods
groue Nov 26, 2016
af8fe35
#147: tests for RowConvertible.fetchCursor() methods
groue Nov 26, 2016
8411efc
#147: tests for RowConvertible.fetchCursor(_:keys:) methods
groue Nov 26, 2016
173a60e
bugfix
groue Nov 26, 2016
612c963
TODO
groue Nov 26, 2016
1aeb6d0
bugfix
groue Nov 26, 2016
a548212
#147: tests for QueryInterfaceRequest.fetchCursor(_:) and (RowConvert…
groue Nov 26, 2016
ae10101
#147: record.exists(_:) can now throw a database error
groue Nov 26, 2016
a196ac0
#147: tests for DatabaseCursor.filter, forEach, map, reduce; dropped …
groue Nov 26, 2016
66bedf4
#147: DatabaseCursor.enumerated()
groue Nov 26, 2016
81504bb
#147: DatabaseCursor.flatMap()
groue Nov 26, 2016
6f158e3
TODO.md
groue Nov 26, 2016
af6e31d
#147: The `fetch` method have been removed, along with `DatabaseSeque…
groue Nov 26, 2016
ac6c7f6
#147: fetchAll() and fetchOne() can now throw database errors.
groue Nov 26, 2016
e313815
Update performance tests
groue Nov 26, 2016
6121a9b
Remove dead code
groue Nov 26, 2016
ceb0fc4
TODO.md
groue Nov 26, 2016
195c201
#147: DatabasePool.read(_:) and DatabasePool.nonIsolatedRead(_:) can …
groue Nov 26, 2016
8d9d0dd
DatabasePool.nonIsolatedRead(_:) can now throw on macOS, too
groue Nov 27, 2016
268080c
#147: FetchedRecordsController.performFetch() can now throw database …
groue Nov 27, 2016
829eb7d
SelectStatement.SelectionInfo cleanup
groue Nov 27, 2016
b8c05e5
Cleanup
groue Nov 27, 2016
e99e9f3
Migration.runWithDisabledForeignKeys(): throw error from `PRAGMA fore…
groue Nov 27, 2016
09697f2
DAO.init() throws DatabaseError instead of crashing whenever table do…
groue Nov 27, 2016
87024f0
QueryInterfaceSelectQueryDefinition.makeDeleteStatement() throws
groue Nov 27, 2016
95eb9af
Cleanup
groue Nov 27, 2016
f8029a6
Remove a couple try!
groue Nov 27, 2016
b85a8b8
#147: DatabaseValueConvertible.fetchOne() can throw conversion errors
groue Nov 27, 2016
ebf9b0e
Simplify tests for RowConvertible fetch requests
groue Nov 27, 2016
59506a9
Cleanup
groue Nov 27, 2016
90e99aa
TODO.md
groue Nov 27, 2016
35414e0
Update GRDBProfiling app
groue Nov 27, 2016
bbe0bfa
#147: fetchCursor, fetchAll & fetchOne all throw sqlite3_prepare_v2 e…
groue Nov 27, 2016
cbf4ab7
TODO.md
groue Nov 28, 2016
ee99abc
Replace fetchCursor().next() with fetchOne()
groue Nov 28, 2016
5e2dc95
DatabaseValueConvertible.fetchOne(): avoid double DatabaseValue conve…
groue Nov 28, 2016
f3cc0a0
Update sample playgrounds
groue Nov 28, 2016
ec2017f
Cursor.enumerated, filter, flatMap, map now return cursors. Cursor.la…
groue Nov 28, 2016
0c4fb36
Add RowFetchTests
groue Nov 28, 2016
bb1f8aa
Drop Cursor.lazy
groue Nov 29, 2016
d85a745
DatabaseStore: expose initialization error (addresses https://github.…
groue Nov 29, 2016
5b0b674
DatabaseStore: *really* expose initialization error (addresses https:…
groue Nov 29, 2016
2e73199
Cleanup FlattenCursor
groue Nov 29, 2016
617f0c8
TODO: more Cursor methods so that it looks more like a sequence
groue Nov 29, 2016
de57dc9
TODO: think about supporting Cursor's underestimatedCount
groue Nov 29, 2016
a8e2663
Documentation
groue Nov 29, 2016
527aed0
Documentation
groue Nov 29, 2016
ccb5826
Documentation
groue Nov 29, 2016
3749631
Documentation
groue Nov 29, 2016
cec1ed8
IteratorCursor has public initializers. Add joined() method for curso…
groue Nov 29, 2016
972789d
Replace Array(Type.fetchCursor()) with Type.fetchAll()
groue Nov 29, 2016
6af47fa
CHANGELOG.md
groue Nov 29, 2016
f495edf
Improve Cursor test coverage
groue Nov 29, 2016
6075a92
Documentation
groue Nov 29, 2016
f9bb3de
Documentation
groue Nov 29, 2016
fc1fdab
Documentation
groue Nov 29, 2016
6bcab17
Classify all try! and fatalError into TODO, Programmer Error, or GRDB…
groue Nov 30, 2016
9523b88
CHANGELOG.md
groue Nov 30, 2016
2cec3f2
Statement.fetchCursor() no longer throws. TODO: Type.fetchCursor(stat…
groue Nov 30, 2016
095778c
Documentation
groue Nov 30, 2016
5c44f55
FetchedRecordsController: remove some crash opportunities by compilin…
groue Nov 30, 2016
baa9501
Fix-its for removed APIs. Update GRDBDemoiOS for FetchedRecordsContro…
groue Nov 30, 2016
59ff18b
Thanks @kdubb in the README
groue Nov 30, 2016
948d749
Expose fixit files into CocoaPods
groue Nov 30, 2016
18937bd
Fixit files belong to GRDB
groue Nov 30, 2016
263adb1
Update tests for SQLCipher
groue Nov 30, 2016
316bb91
Documentation
groue Nov 30, 2016
2e2f28d
Documentation
groue Nov 30, 2016
8118f78
v0.91.0
groue Nov 30, 2016
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
281 changes: 281 additions & 0 deletions CHANGELOG.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ class InterfaceController: WKInterfaceController {
override func awake(withContext context: Any?) {
super.awake(withContext: context)

let persons = dbQueue.inDatabase { db in
Person.order(Column("name")).fetchAll(db)
let persons = try! dbQueue.inDatabase { db in
try Person.order(Column("name")).fetchAll(db)
}

table.setNumberOfRows(persons.count, withRowType: "Person")
Expand Down
16 changes: 8 additions & 8 deletions DemoApps/GRDBDemoiOS/GRDBDemoiOS/PersonsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class PersonsViewController: UITableViewController {
]

let request = personsSortedByScore
personsController = FetchedRecordsController(dbQueue, request: request, compareRecordsByPrimaryKey: true)
personsController = try! FetchedRecordsController(dbQueue, request: request, compareRecordsByPrimaryKey: true)
personsController.trackChanges(
recordsWillChange: { [unowned self] _ in
self.tableView.beginUpdates()
Expand Down Expand Up @@ -47,7 +47,7 @@ class PersonsViewController: UITableViewController {
recordsDidChange: { [unowned self] _ in
self.tableView.endUpdates()
})
personsController.performFetch()
try! personsController.performFetch()

configureToolbar()
}
Expand Down Expand Up @@ -164,19 +164,19 @@ extension PersonsViewController {

@IBAction func sortByName() {
setEditing(false, animated: true)
personsController.setRequest(personsSortedByName)
try! personsController.setRequest(personsSortedByName)
}

@IBAction func sortByScore() {
setEditing(false, animated: true)
personsController.setRequest(personsSortedByScore)
try! personsController.setRequest(personsSortedByScore)
}

@IBAction func randomizeScores() {
setEditing(false, animated: true)

try! dbQueue.inTransaction { db in
for person in Person.fetch(db) {
for person in try Person.fetchAll(db) {
person.score = Person.randomScore()
try person.update(db)
}
Expand All @@ -190,7 +190,7 @@ extension PersonsViewController {
for _ in 0..<50 {
DispatchQueue.global().async {
try! dbQueue.inTransaction { db in
if Person.fetchCount(db) == 0 {
if try Person.fetchCount(db) == 0 {
// Insert persons
for _ in 0..<8 {
try Person(name: Person.randomName(), score: Person.randomScore()).insert(db)
Expand All @@ -203,12 +203,12 @@ extension PersonsViewController {
}
// Delete a person
if arc4random_uniform(2) == 0 {
if let person = Person.order(sql: "RANDOM()").fetchOne(db) {
if let person = try Person.order(sql: "RANDOM()").fetchOne(db) {
try person.delete(db)
}
}
// Update some persons
for person in Person.fetchAll(db) {
for person in try Person.fetchAll(db) {
if arc4random_uniform(2) == 0 {
person.score = Person.randomScore()
try person.update(db)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ class SimplePersonsViewController: UITableViewController {
}

private func loadPersons() {
persons = dbQueue.inDatabase { db in
Person.order(Column("score").desc, Column("name")).fetchAll(db)
persons = try! dbQueue.inDatabase { db in
try Person.order(Column("score").desc, Column("name")).fetchAll(db)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Documentation/CustomSQLiteBuilds.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ GRDB builds SQLite with [swiftlyfalling/SQLiteLib](https://github.com/swiftlyfal

```sh
cd [GRDB.swift directory]
git checkout v0.90.1
git checkout v0.91.0
git submodule update --init SQLiteCustom/src
````

Expand Down
27 changes: 15 additions & 12 deletions Documentation/ExtendingGRDB.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ This guide is a step-by-step tour of GRDB extensibility, around a few topics:
You'll learn how to turn UIColor into a value type that you can store, fetch, and use in your records:

```swift
for row in Row.fetch(db, "SELECT name, color FROM clothes") {
let rows = try Row.fetchCursor(db, "SELECT name, color FROM clothes")
while let row = try rows.next() {
let name: String = row.value(named: "name")
let color: UIColor = row.value(named: "color") // <-- New! UIColor as value
}
Expand All @@ -32,7 +33,8 @@ This guide is a step-by-step tour of GRDB extensibility, around a few topics:
```swift
let jsonString = Column("jsonString")
let request = Books.select(cast(jsonString, as: .blob)) // <-- New! cast function
for row in Row.fetch(db, request) {
let rows = try Row.fetchCursor(db, request)
while let row = try rows.next() {
let data = row.dataNoCopy(atIndex: 0)
}
```
Expand Down Expand Up @@ -68,9 +70,9 @@ protocol DatabaseValueConvertible {
}
```

The `databaseValue` property returns [DatabaseValue](../../../#databasevalue), a type that wraps the five values supported by SQLite: NULL, Int64, Double, String and Data. DatabaseValue has no public initializer: to create one, use `DatabaseValue.null`, or another type that already adopts the protocol: `1.databaseValue`, `"foo".databaseValue`, etc.
The `databaseValue` property returns [DatabaseValue](../../../#databasevalue), a type that wraps the five values supported by SQLite: NULL, Int64, Double, String and Data. Since DatabaseValue has no public initializer, use `DatabaseValue.null`, or another type that already adopts the protocol: `1.databaseValue`, `"foo".databaseValue`, etc. Conversion to DatabaseValue *must not* fail.

The `fromDatabaseValue()` factory method returns an instance of your custom type if the databaseValue contains a suitable value. If the databaseValue does not contain a suitable value, such as "foo" for Date, the method returns nil.
The `fromDatabaseValue()` factory method returns an instance of your custom type if the databaseValue contains a suitable value. If the databaseValue does not contain a suitable value, such as "foo" for Date, `fromDatabaseValue` *must* return nil (GRDB will interpret this nil result as a conversion error, and react accordingly).

**What does the DatabaseValueConvertible protocol bring to a type like UIColor?**

Expand All @@ -87,7 +89,8 @@ Well, you will be able to use UIColor like all other [value types](../../../#val
- UIColor can be [extracted from rows](../../../#column-values):

```swift
for row in Row.fetch(db, "SELECT * FROM clothes") {
let rows = try Row.fetchCursor(db, "SELECT * FROM clothes")
while let row = try rows.next() {
let name: String = row.value(named: "name")
let color: UIColor = row.value(named: "color")
}
Expand All @@ -96,7 +99,7 @@ Well, you will be able to use UIColor like all other [value types](../../../#val
- UIColor can be [directly fetched](../../../#value-queries):

```swift
let colors = UIColor.fetchAll(db, "SELECT DISTINCT color FROM clothes") // [UIColor]
let colors = try UIColor.fetchAll(db, "SELECT DISTINCT color FROM clothes") // [UIColor]
```

- Use UIColor in [Records](../../../#records):
Expand All @@ -121,7 +124,7 @@ Well, you will be able to use UIColor like all other [value types](../../../#val
- Use UIColor in the [query interface](../../../#the-query-interface):

```swift
let redClothes = ClothingItem.filter(colorColumn == UIColor.red).fetchAll(db)
let redClothes = try ClothingItem.filter(colorColumn == UIColor.red).fetchAll(db)
```

**Let's have UIColor adopt DatabaseValueConvertible**
Expand Down Expand Up @@ -468,7 +471,7 @@ Build a `value IN (...)` expression from any sequence of [values](../../../#valu
![1,2,3].contains(Column("id"))
```

The most general way to generate an `IN` operator is from any value that adopts the [SQLCollection](http://cocoadocs.org/docsets/GRDB.swift/0.90.1/Protocols/SQLCollection.html) protocol, like the [query interface requests](../../../#requests):
The most general way to generate an `IN` operator is from any value that adopts the [SQLCollection](http://cocoadocs.org/docsets/GRDB.swift/0.91.0/Protocols/SQLCollection.html) protocol, like the [query interface requests](../../../#requests):

```swift
let request = Person.select(Column("id"))
Expand All @@ -490,7 +493,7 @@ Build a `value BETWEEN min AND max` expression from Swift ranges:

#### The EXISTS Operator

Build a `EXISTS(...)` expression from any value that adopts the [SQLSelectQuery](http://cocoadocs.org/docsets/GRDB.swift/0.90.1/Protocols/SQLSelectQuery.html) protocol, like the [query interface requests](../../../#requests):
Build a `EXISTS(...)` expression from any value that adopts the [SQLSelectQuery](http://cocoadocs.org/docsets/GRDB.swift/0.91.0/Protocols/SQLSelectQuery.html) protocol, like the [query interface requests](../../../#requests):

```swift
let request = Person.all()
Expand All @@ -502,7 +505,7 @@ request.exists()

#### The COUNT Function

Build a `COUNT(...)` expression from the [count](http://cocoadocs.org/docsets/GRDB.swift/0.90.1/Functions.html) and [count(distinct:)](http://cocoadocs.org/docsets/GRDB.swift/0.90.1/Functions.html) functions:
Build a `COUNT(...)` expression from the [count](http://cocoadocs.org/docsets/GRDB.swift/0.91.0/Functions.html) and [count(distinct:)](http://cocoadocs.org/docsets/GRDB.swift/0.91.0/Functions.html) functions:

```swift
// SQLExpression: COUNT(email)
Expand Down Expand Up @@ -537,7 +540,7 @@ We'll add below a Swift `cast` function:

```swift
let request = Books.select(cast(Column("jsonString"), as: .blob))
let jsonDatas = Data.fetchAll(db, request) // [Data]
let jsonDatas = try Data.fetchAll(db, request) // [Data]
```

`cast` is a top-level Swift function because this is how GRDB usually imports SQLite features which do not have matching standard Swift counterpart. It helps the Swift code looking like SQL when it is relevant. But YMMV.
Expand Down Expand Up @@ -593,4 +596,4 @@ You may want to compare it to another protocol, SQLSpecificExpressible, which ha

> :point_up: **Note**: whenever you extend GRDB with a Swift function, method, or operator, you should generally make sure that its signature contains at least one GRDB-specific type. In the `cast` function, it is Database.ColumnType.

**If SQLExpressionLiteral reveals too limited for your purpose**, you may have to implement a new type that adopts the [SQLExpression](http://cocoadocs.org/docsets/GRDB.swift/0.90.1/Protocols/SQLExpression.html) protocol.
**If SQLExpressionLiteral reveals too limited for your purpose**, you may have to implement a new type that adopts the [SQLExpression](http://cocoadocs.org/docsets/GRDB.swift/0.91.0/Protocols/SQLExpression.html) protocol.
2 changes: 1 addition & 1 deletion Documentation/FTS5Tokenizers.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ try db.execute("INSERT INTO documents VALUES (?)", arguments: ["..."])
try Document(content: "...").insert(db)

let pattern = FTS5Pattern(matchingAnyTokenIn:"...")
let documents = Document.matching(pattern).fetchAll(db)
let documents = try Document.matching(pattern).fetchAll(db)
```


Expand Down
7 changes: 4 additions & 3 deletions Documentation/ReleaseProcess.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ To release a new GRDB version:

- Tests
- Run GRDBOX tests
- Run GRDBiOS tests
- Run GRDBCustomSQLiteOSX tests
- Run GRDBCustomSQLiteiOS tests
- Run GRDBCipherOSX tests
- Run GRDBCustomSQLiteOSX tests
- Run GRDBiOS tests
- Run GRDBCipheriOS tests
- Run GRDBCustomSQLiteiOS tests
- Build and run GRDBDemoiOS
- Build and run GRDBDemoWatchOS
- Check for performance regression with GRDBOSXPerformanceTests
- `rm -rf Carthage; carthage build --no-skip-current`
- `pod lib lint --allow-warnings`
- On https://github.com/groue/sqlcipher.git upgrade, update SQLCipher version in README.md
Expand Down
2 changes: 1 addition & 1 deletion GRDB.swift.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'GRDB.swift'
s.version = '0.90.1'
s.version = '0.91.0'

s.license = { :type => 'MIT', :file => 'LICENSE' }
s.summary = 'A Swift application toolkit for SQLite databases.'
Expand Down
Loading