Skip to content

Commit c50cfd9

Browse files
committed
DocC: DatabaseQueue and DatabasePool
1 parent 3d7170f commit c50cfd9

File tree

7 files changed

+32
-156
lines changed

7 files changed

+32
-156
lines changed

Documentation/Combine.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ let cancellable = hallOfFamePublisher.sink(
398398
[`writePublisher(receiveOn:updates:thenRead:)`]: #databasewriterwritepublisherreceiveonupdatesthenread
399399
[`migratePublisher(_:receiveOn:)`]: https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasemigrator/migratepublisher(_:receiveon:)
400400
[configured]: ../README.md#databasepool-configuration
401-
[database pool]: ../README.md#database-pools
402-
[database queue]: ../README.md#database-queues
401+
[database pool]: https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasepool
402+
[database queue]: https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasequeue
403403
[database snapshot]: https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasesnapshot
404404
[scheduler]: https://developer.apple.com/documentation/combine/scheduler

Documentation/CustomSQLiteBuilds.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ GRDB builds SQLite with [swiftlyfalling/SQLiteLib](https://github.com/swiftlyfal
2121

2222
2. Choose your [extra compilation options](https://www.sqlite.org/compile.html). For example, `SQLITE_ENABLE_FTS5`, `SQLITE_ENABLE_PREUPDATE_HOOK`.
2323

24-
It is recommended that you enable the `SQLITE_ENABLE_SNAPSHOT` option. It allows GRDB to optimize [ValueObservation](https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/valueobservation) when you use a [Database Pool](../README.md#database-pools).
24+
It is recommended that you enable the `SQLITE_ENABLE_SNAPSHOT` option. It allows GRDB to optimize [ValueObservation](https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/valueobservation) when you use a [Database Pool](https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasepool).
2525

2626
3. Create a folder named `GRDBCustomSQLite` somewhere in your project directory.
2727

Documentation/WhyAdoptGRDB.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,11 +154,11 @@ See [Database Observation](https://swiftpackageindex.com/groue/grdb.swift/docume
154154

155155
### Non-blocking database reads
156156

157-
GRDB ships with two ways to access databases, [database queues](../README.md#database-queues) and [pools](../README.md#database-pools).
157+
GRDB ships with two ways to access databases, [database queues](https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasequeue) and [pools](https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasepool).
158158

159159
Database queues look a lot like FMDB's [FMDatabaseQueue](https://github.com/ccgus/fmdb#using-fmdatabasequeue-and-thread-safety): they serialize database accesses in a serial dispatch queue. There is never more than one thread that is accessing the database. This means that a long running database transaction that happens in a background thread, such as the synchronization of your local database from a remote server, can block your UI. As long as the queue is busy, the main thread can't fetch the values it wants to display on screen.
160160

161-
[Database pools](../README.md#database-pools) can lift these unwanted locks. With database pools, reads are generally non-blocking, unless the maximum number of concurrent reads has been reached (and this maximum number can be configured).
161+
[Database pools](https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasepool) can lift these unwanted locks. With database pools, reads are generally non-blocking, unless the maximum number of concurrent reads has been reached (and this maximum number can be configured).
162162

163163

164164
### Strong and clear multi-threading guarantees
@@ -287,7 +287,7 @@ Happy GRDB! :gift:
287287

288288
[Concurrency Guide]: https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/concurrency
289289
[Core Data]: https://developer.apple.com/documentation/coredata
290-
[DatabasePool]: ../README.md#database-pools
290+
[DatabasePool]: https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasepool
291291
[Diesel]: http://diesel.rs
292292
[FCModel]: https://github.com/marcoarment/FCModel
293293
[ValueObservation]: https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/valueobservation

GRDB/Documentation.docc/DatabaseConnections.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,11 @@ let dbPool = try DatabasePool(path: "/path/to/database.sqlite")
1717
The differences are:
1818

1919
- `DatabasePool` allows concurrent database accesses (this can improve the performance of multithreaded applications).
20-
- `DatabasePool` opens your SQLite database in the [WAL mode](https://www.sqlite.org/wal.html) (unless ``Configuration/readonly``).
20+
- `DatabasePool` opens your SQLite database in the [WAL mode](https://www.sqlite.org/wal.html).
2121
- `DatabaseQueue` supports <doc:DatabaseQueue#In-Memory-Databases>.
2222

2323
**If you are not sure, choose `DatabaseQueue`.** You will always be able to switch to `DatabasePool` later.
2424

25-
Once connected, you can define the database schema, and access the database with raw SQL or high-level Swift apis:
26-
27-
- <doc:DatabaseSchema>
28-
- <doc:SQLSupport>
29-
- <doc:QueryInterface>
30-
3125
## Topics
3226

3327
### Configuring database connections

GRDB/Documentation.docc/Extension/DatabasePool.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ A database connection that allows concurrent accesses to an SQLite database.
44

55
## Usage
66

7-
**Open a `DatabasePool`** with the path to a database file:
7+
Open a `DatabasePool` with the path to a database file:
88

99
```swift
1010
import GRDB

GRDB/Documentation.docc/Extension/DatabaseQueue.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ A database connection that serializes accesses to an SQLite database.
44

55
## Usage
66

7-
**Open a `DatabaseQueue`** with the path to a database file:
7+
Open a `DatabaseQueue` with the path to a database file:
88

99
```swift
1010
import GRDB

README.md

Lines changed: 23 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ Programming tools for both database beginners and SQLite experts:
7070
- [Records](#records): Fetching and persistence methods for your custom structs and class hierarchies.
7171
- [Query Interface](#the-query-interface): A swift way to avoid the SQL language.
7272
- [Associations]: Relations and joins between record types.
73-
- [WAL Mode Support](#database-pools): Extra performance for multi-threaded applications.
73+
- [WAL Mode Support](https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasepool): Extra performance for multi-threaded applications.
7474
- [Migrations]: Transform your database as your application evolves.
7575
- [Database Observation]: Observe database changes and transactions.
7676
- [Full-Text Search]
@@ -428,7 +428,7 @@ GRDB offers two libraries, `GRDB` and `GRDB-dynamic`. Pick only one. When in dou
428428
Database Connections
429429
====================
430430

431-
GRDB provides two classes for accessing SQLite databases: `DatabaseQueue` and `DatabasePool`:
431+
GRDB provides two classes for accessing SQLite databases: [`DatabaseQueue`] and [`DatabasePool`]:
432432

433433
```swift
434434
import GRDB
@@ -444,137 +444,7 @@ The differences are:
444444
- Database pools open your SQLite database in the [WAL mode](https://www.sqlite.org/wal.html) (unless read-only).
445445
- Database queues support [in-memory databases](https://www.sqlite.org/inmemorydb.html).
446446

447-
**If you are not sure, choose DatabaseQueue.** You will always be able to switch to DatabasePool later.
448-
449-
- [Database Queues](#database-queues)
450-
- [Database Pools](#database-pools)
451-
452-
453-
## Database Queues
454-
455-
**Open a database queue** with the path to a database file:
456-
457-
```swift
458-
import GRDB
459-
460-
let dbQueue = try DatabaseQueue(path: "/path/to/database.sqlite")
461-
let inMemoryDBQueue = try DatabaseQueue()
462-
```
463-
464-
SQLite creates the database file if it does not already exist. The connection is closed when the database queue gets deinitialized.
465-
466-
**A database queue can be used from any thread.** The `write` and `read` methods are synchronous, and block the current thread until your database statements are executed in a protected dispatch queue:
467-
468-
```swift
469-
// Modify the database:
470-
try dbQueue.write { db in
471-
try db.create(table: "place") { ... }
472-
try Place(...).insert(db)
473-
}
474-
475-
// Read values:
476-
try dbQueue.read { db in
477-
let places = try Place.fetchAll(db)
478-
let placeCount = try Place.fetchCount(db)
479-
}
480-
```
481-
482-
Database access methods can return values:
483-
484-
```swift
485-
let placeCount = try dbQueue.read { db in
486-
try Place.fetchCount(db)
487-
}
488-
489-
let newPlaceCount = try dbQueue.write { db -> Int in
490-
try Place(...).insert(db)
491-
return try Place.fetchCount(db)
492-
}
493-
```
494-
495-
See the [Concurrency] guide for asynchronous database accesses.
496-
497-
**A database queue serializes accesses to the database**, which means that there is never more than one thread that uses the database.
498-
499-
- When you don't need to modify the database, prefer the `read` method. It prevents any modification to the database.
500-
501-
- The `write` method wraps your database statements in a transaction that commits if and only if no error occurs. On the first unhandled error, all changes are reverted, the whole transaction is rollbacked, and the error is rethrown.
502-
503-
When precise transaction handling is required, see [Transactions and Savepoints].
504-
505-
**A database queue needs your application to follow rules in order to deliver its safety guarantees.** Please refer to the [Concurrency] guide.
506-
507-
See [Database Configuration] for DatabaseQueue options.
508-
509-
> :bulb: **Tip**: see the [Demo Applications] for sample code.
510-
511-
512-
## Database Pools
513-
514-
**A database pool allows concurrent database accesses.**
515-
516-
```swift
517-
import GRDB
518-
let dbPool = try DatabasePool(path: "/path/to/database.sqlite")
519-
```
520-
521-
SQLite creates the database file if it does not already exist. The connection is closed when the database pool gets deinitialized.
522-
523-
> **Note**: unless read-only, a database pool opens your database in the SQLite "WAL mode". The WAL mode does not fit all situations. Please have a look at https://www.sqlite.org/wal.html.
524-
525-
**A database pool can be used from any thread.** The `write` and `read` methods are synchronous, and block the current thread until your database statements are executed in a protected dispatch queue:
526-
527-
```swift
528-
// Modify the database:
529-
try dbPool.write { db in
530-
try db.create(table: "place") { ... }
531-
try Place(...).insert(db)
532-
}
533-
534-
// Read values:
535-
try dbPool.read { db in
536-
let places = try Place.fetchAll(db)
537-
let placeCount = try Place.fetchCount(db)
538-
}
539-
```
540-
541-
Database access methods can return values:
542-
543-
```swift
544-
let placeCount = try dbPool.read { db in
545-
try Place.fetchCount(db)
546-
}
547-
548-
let newPlaceCount = try dbPool.write { db -> Int in
549-
try Place(...).insert(db)
550-
return try Place.fetchCount(db)
551-
}
552-
```
553-
554-
See the [Concurrency] guide for asynchronous database accesses.
555-
556-
**Database pools allow several threads to access the database at the same time:**
557-
558-
- When you don't need to modify the database, prefer the `read` method, because several threads can perform reads in parallel.
559-
560-
Reads are generally non-blocking, unless the maximum number of concurrent reads has been reached. In this case, a read has to wait for another read to complete. That maximum number can be [configured](https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/configuration).
561-
562-
- Reads are guaranteed an immutable view of the last committed state of the database, regardless of concurrent writes. This kind of isolation is called [snapshot isolation](https://sqlite.org/isolation.html).
563-
564-
- Unlike reads, writes are serialized. There is never more than a single thread that is writing into the database.
565-
566-
- The `write` method wraps your database statements in a transaction that commits if and only if no error occurs. On the first unhandled error, all changes are reverted, the whole transaction is rollbacked, and the error is rethrown.
567-
568-
When precise transaction handling is required, see [Transactions and Savepoints].
569-
570-
- Database pools can take [snapshots](https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasesnapshot) of the database.
571-
572-
**A database pool needs your application to follow rules in order to deliver its safety guarantees.** See the [Concurrency] guide for more details about database pools, how they differ from database queues, and advanced use cases.
573-
574-
See [Database Configuration] for DatabasePool options.
575-
576-
> :bulb: **Tip**: see the [Demo Applications] for sample code.
577-
447+
**If you are not sure, choose `DatabaseQueue`.** You will always be able to switch to `DatabasePool` later.
578448

579449

580450
SQLite API
@@ -1729,7 +1599,7 @@ When the same query will be used several times in the lifetime of your applicati
17291599

17301600
**Don't cache statements yourself.**
17311601

1732-
> **Note**: This is because you don't have the necessary tools. Statements are tied to specific SQLite connections and dispatch queues which you don't manage yourself, especially when you use [database pools](#database-pools). A change in the database schema [may, or may not](https://www.sqlite.org/compile.html#max_schema_retry) invalidate a statement.
1602+
> **Note**: This is because you don't have the necessary tools. Statements are tied to specific SQLite connections and dispatch queues which you don't manage yourself, especially when you use [database pools]. A change in the database schema [may, or may not](https://www.sqlite.org/compile.html#max_schema_retry) invalidate a statement.
17331603

17341604
Instead, use the `cachedStatement` method. GRDB does all the hard caching and [memory management](#memory-management) stuff for you:
17351605

@@ -5709,15 +5579,15 @@ See [SQLCipher 4.0.0 Release](https://www.zetetic.net/blog/2018/11/30/sqlcipher-
57095579

57105580
**You can change the passphrase** of an already encrypted database.
57115581

5712-
When you use a [database queue](#database-queues), open the database with the old passphrase, and then apply the new passphrase:
5582+
When you use a [database queue](https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasequeue), open the database with the old passphrase, and then apply the new passphrase:
57135583

57145584
```swift
57155585
try dbQueue.write { db in
57165586
try db.changePassphrase("newSecret")
57175587
}
57185588
```
57195589

5720-
When you use a [database pool](#database-pools), make sure that no concurrent read can happen by changing the passphrase within the `barrierWriteWithoutTransaction` block. You must also ensure all future reads open a new database connection by calling the `invalidateReadOnlyConnections` method:
5590+
When you use a [database pool](https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasepool), make sure that no concurrent read can happen by changing the passphrase within the `barrierWriteWithoutTransaction` block. You must also ensure all future reads open a new database connection by calling the `invalidateReadOnlyConnections` method:
57215591

57225592
```swift
57235593
try dbPool.barrierWriteWithoutTransaction { db in
@@ -5865,7 +5735,7 @@ config.prepareDatabase { db in
58655735
let dbQueue = try DatabaseQueue(path: dbPath, configuration: config)
58665736
```
58675737

5868-
For the same reason, [database pools](#database-pools), which open SQLite connections on demand, may fail at any time as soon as the passphrase becomes unavailable:
5738+
For the same reason, [database pools], which open SQLite connections on demand, may fail at any time as soon as the passphrase becomes unavailable:
58695739

58705740
```swift
58715741
// Success if and only if the passphrase is available
@@ -5899,7 +5769,7 @@ try source.backup(to: destination)
58995769

59005770
The `backup` method blocks the current thread until the destination database contains the same contents as the source database.
59015771

5902-
When the source is a [database pool](#database-pools), concurrent writes can happen during the backup. Those writes may, or may not, be reflected in the backup, but they won't trigger any error.
5772+
When the source is a [database pool](https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasepool), concurrent writes can happen during the backup. Those writes may, or may not, be reflected in the backup, but they won't trigger any error.
59035773

59045774
`Database` has an analogous `backup` method.
59055775

@@ -6412,7 +6282,7 @@ dbPool.releaseMemoryEventually()
64126282

64136283
**The iOS operating system likes applications that do not consume much memory.**
64146284

6415-
[Database queues](#database-queues) and [pools](#database-pools) automatically free non-essential memory when the application receives a memory warning, and when the application enters background.
6285+
[Database queues] and [pools](https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasepool) automatically free non-essential memory when the application receives a memory warning, and when the application enters background.
64166286

64176287
You can opt out of this automatic memory management:
64186288

@@ -6429,7 +6299,7 @@ let dbQueue = try DatabaseQueue(path: dbPath, configuration: config) // or Datab
64296299

64306300
Data protection can be enabled [globally](https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/AddingCapabilities/AddingCapabilities.html#//apple_ref/doc/uid/TP40012582-CH26-SW30) for all files created by an application.
64316301

6432-
You can also explicitly protect a database, by configuring its enclosing *directory*. This will not only protect the database file, but also all [temporary files](https://www.sqlite.org/tempfiles.html) created by SQLite (including the persistent `.shm` and `.wal` files created by [database pools](#database-pools)).
6302+
You can also explicitly protect a database, by configuring its enclosing *directory*. This will not only protect the database file, but also all [temporary files](https://www.sqlite.org/tempfiles.html) created by SQLite (including the persistent `.shm` and `.wal` files created by [database pools]).
64336303

64346304
For example, to explicitly use [complete](https://developer.apple.com/reference/foundation/fileprotectiontype/1616200-complete) protection:
64356305

@@ -7046,6 +6916,14 @@ This chapter has [moved](https://swiftpackageindex.com/groue/grdb.swift/document
70466916

70476917
This chapter has [moved](https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/configuration).
70486918

6919+
#### Database Queues
6920+
6921+
This chapter has [moved](https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasequeue).
6922+
6923+
#### Database Pools
6924+
6925+
This chapter has [moved](https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasepool).
6926+
70496927
#### Database Snapshots
70506928

70516929
This chapter has [moved](https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/concurrency).
@@ -7173,4 +7051,8 @@ This chapter has been superseded by [ValueObservation] and [DatabaseRegionObserv
71737051
[Persistence Methods]: #persistence-methods
71747052
[persistence methods]: #persistence-methods
71757053
[RecordError]: #recorderror
7176-
[Transactions and Savepoints]: https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/transactions
7054+
[Transactions and Savepoints]: https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/transactions
7055+
[`DatabaseQueue`]: https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasequeue
7056+
[Database queues]: https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasequeue
7057+
[`DatabasePool`]: https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasepool
7058+
[database pools]: https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databasepool

0 commit comments

Comments
 (0)