From 9f4cad41345a8b6f470ba663c7ce85177c0e7c11 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 3 Apr 2019 15:13:37 -0400 Subject: [PATCH 1/6] Make DatabaseRegion initializer public to enable observation of tables. --- GRDB/Core/DatabaseRegion.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GRDB/Core/DatabaseRegion.swift b/GRDB/Core/DatabaseRegion.swift index 04c499538a..6614310e21 100644 --- a/GRDB/Core/DatabaseRegion.swift +++ b/GRDB/Core/DatabaseRegion.swift @@ -64,7 +64,7 @@ public struct DatabaseRegion: CustomStringConvertible, Equatable { } /// A full table: (all columns in the table) × (all rows) - init(table: String) { + public init(table: String) { self.init(tableRegions: [table: TableRegion(columns: nil, rowIds: nil)]) } From 9f41277bd4269605daf12131deaebde695e9f772 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Thu, 4 Apr 2019 17:30:29 -0400 Subject: [PATCH 2/6] Make more DatabaseRegion initializers public; elaborate docs. --- GRDB/Core/DatabaseRegion.swift | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/GRDB/Core/DatabaseRegion.swift b/GRDB/Core/DatabaseRegion.swift index 6614310e21..77bcbe87a2 100644 --- a/GRDB/Core/DatabaseRegion.swift +++ b/GRDB/Core/DatabaseRegion.swift @@ -63,21 +63,26 @@ public struct DatabaseRegion: CustomStringConvertible, Equatable { self.init(tableRegions: [:]) } - /// A full table: (all columns in the table) × (all rows) + /// This initializer can be used to observe (all rows) & (all columns) in a single table. public init(table: String) { self.init(tableRegions: [table: TableRegion(columns: nil, rowIds: nil)]) } - /// Full columns in a table: (some columns in a table) × (all rows) - init(table: String, columns: Set) { + /// This initializer can be used to observe (all rows) & (a subset of columns) in a single table. + public init(table: String, columns: Set) { self.init(tableRegions: [table: TableRegion(columns: columns, rowIds: nil)]) } - /// Full rows in a table: (all columns in a table) × (some rows) - init(table: String, rowIds: Set) { + /// This initializer can be used to observe (a subset of rows) & (all columns) in a single table. + public init(table: String, rowIds: Set) { self.init(tableRegions: [table: TableRegion(columns: nil, rowIds: rowIds)]) } + /// This initializer can be used to observe (a subset of rows) & (a subset of columns) in a single table. + public init(table: String, columns: Set, rowIds: Set) { + self.init(tableRegions: [table: TableRegion(columns: columns, rowIds: rowIds)]) + } + /// Returns the intersection of this region and the given one. /// /// This method is not public because there is no known public use case for From 0561b7de5de340e6e2eb141a987bd9249629d342 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Fri, 5 Apr 2019 09:50:07 -0400 Subject: [PATCH 3/6] Respond to CR. --- GRDB/Core/DatabaseRegion.swift | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/GRDB/Core/DatabaseRegion.swift b/GRDB/Core/DatabaseRegion.swift index 77bcbe87a2..ec4ab342d2 100644 --- a/GRDB/Core/DatabaseRegion.swift +++ b/GRDB/Core/DatabaseRegion.swift @@ -63,26 +63,23 @@ public struct DatabaseRegion: CustomStringConvertible, Equatable { self.init(tableRegions: [:]) } - /// This initializer can be used to observe (all rows) & (all columns) in a single table. + /// Creates a region that spans all rows and columns of a database table. + /// + /// - parameter table: A table name. public init(table: String) { self.init(tableRegions: [table: TableRegion(columns: nil, rowIds: nil)]) } - /// This initializer can be used to observe (all rows) & (a subset of columns) in a single table. - public init(table: String, columns: Set) { + /// Full columns in a table: (some columns in a table) × (all rows) + init(table: String, columns: Set) { self.init(tableRegions: [table: TableRegion(columns: columns, rowIds: nil)]) } - /// This initializer can be used to observe (a subset of rows) & (all columns) in a single table. - public init(table: String, rowIds: Set) { + /// Full rows in a table: (all columns in a table) × (some rows) + init(table: String, rowIds: Set) { self.init(tableRegions: [table: TableRegion(columns: nil, rowIds: rowIds)]) } - /// This initializer can be used to observe (a subset of rows) & (a subset of columns) in a single table. - public init(table: String, columns: Set, rowIds: Set) { - self.init(tableRegions: [table: TableRegion(columns: columns, rowIds: rowIds)]) - } - /// Returns the intersection of this region and the given one. /// /// This method is not public because there is no known public use case for From 6f20d8b4063a1af8e58bf48cf12a7e686a6140da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gwendal=20Roue=CC=81?= Date: Tue, 9 Apr 2019 19:17:24 +0200 Subject: [PATCH 4/6] CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21b5e0c00a..3d14d1fd66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,7 @@ GRDB adheres to [Semantic Versioning](https://semver.org/), with one expection: - [#499](https://github.com/groue/GRDB.swift/pull/499): Extract EncodableRecord from MutablePersistableRecord - [#502](https://github.com/groue/GRDB.swift/pull/502): Rename Future to DatabaseFuture - [#503](https://github.com/groue/GRDB.swift/pull/503): IFNULL support for association aggregates +- [#510](https://github.com/groue/GRDB.swift/pull/510) by [@charlesmchen-signal](https://github.com/charlesmchen-signal): Expose DatabaseRegion(table:) initializer ### Fixed From 212290bbf96c36470f689bffd5e5d055430dd858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gwendal=20Roue=CC=81?= Date: Tue, 9 Apr 2019 19:23:50 +0200 Subject: [PATCH 5/6] Make DatabaseRegion documentation less detailed --- GRDB/Core/DatabaseRegion.swift | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/GRDB/Core/DatabaseRegion.swift b/GRDB/Core/DatabaseRegion.swift index ec4ab342d2..7df10aa59f 100644 --- a/GRDB/Core/DatabaseRegion.swift +++ b/GRDB/Core/DatabaseRegion.swift @@ -3,8 +3,7 @@ /// `observes(eventsOfKind:)` and `databaseDidChange(with:)` methods. /// /// A database region is the union of any number of "table regions", which can -/// cover a full table, or the combination of columns and rows (identified by -/// their rowids): +/// cover a full table, or the combination of columns and rows: /// /// |Table1 | |Table2 | |Table3 | |Table4 | |Table5 | /// |-------| |-------| |-------| |-------| |-------| @@ -13,32 +12,23 @@ /// |x|x|x|x| |x| | | | | | | | | |x|x| |x| | | | | | /// |x|x|x|x| |x| | | | | | | | | | | | | | | | | | | /// -/// You don't create a database region directly. Instead, you use one of -/// those methods: +/// To create a database region, you use one of those methods: /// -/// - `SelectStatement.databaseRegion`: +/// - `DatabaseRegion.fullDatabase`: the region that covers all database tables. /// -/// let statement = db.makeSelectStatement(sql: "SELECT name, score FROM player") -/// print(statement.databaseRegion) -/// // prints "player(name,score)" +/// - `DatabaseRegion()`: the empty region. /// -/// - `FetchRequest.databaseRegion(_:)` +/// - `DatabaseRegion(table:)`: the region that covers one database table. /// -/// let request = Player.filter(key: 1) -/// try print(request.databaseRegion(db)) -/// // prints "player(*)[1]" +/// - `SelectStatement.databaseRegion`: /// -/// Database regions returned by requests can be more precise than regions -/// returned by select statements. Especially, regions returned by statements -/// don't know about rowids: +/// let statement = try db.makeSelectStatement(sql: "SELECT name, score FROM player") +/// let region = statement.databaseRegion /// -/// // A plain statement -/// let statement = db.makeSelectStatement(sql: "SELECT * FROM player WHERE id = 1") -/// statement.databaseRegion // "player(*)" +/// - `FetchRequest.databaseRegion(_:)` /// -/// // A query interface request that executes the same statement: -/// let request = Player.filter(key: 1) -/// try request.databaseRegion(db) // "player(*)[1]" +/// let request = Player.filter(key: 1) +/// let region = try request.databaseRegion(db) public struct DatabaseRegion: CustomStringConvertible, Equatable { private let tableRegions: [String: TableRegion]? private init(tableRegions: [String: TableRegion]?) { @@ -58,7 +48,7 @@ public struct DatabaseRegion: CustomStringConvertible, Equatable { /// from all tables. public static let fullDatabase = DatabaseRegion(tableRegions: nil) - /// The empty database region + /// Creates an empty database region. public init() { self.init(tableRegions: [:]) } From 7a42bb42f52c1feb9bdabd6599b0bf28532883ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gwendal=20Roue=CC=81?= Date: Tue, 9 Apr 2019 19:29:38 +0200 Subject: [PATCH 6/6] README: make DatabaseRegion documentation less detailed --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 97a2513f9c..de92945512 100644 --- a/README.md +++ b/README.md @@ -7271,8 +7271,6 @@ DatabaseRegion fuels, for example, [ValueObservation and DatabaseRegionObservati For example, if you observe the region of `Player.select(max(Column("score")))`, then you'll get be notified of all changes performed on the `score` column of the `player` table (updates, insertions and deletions), even if they do not modify the value of the maximum score. However, you will not get any notification for changes performed on other database tables, or updates to other columns of the player table. -Similarly, observing the region of `Country.filter(key: "FR")` will notify all changes that happen to the whole `country` table. That is because SQLite only notifies the numerical [rowid](https://www.sqlite.org/rowidtable.html) of changed rows, and we can't check if it is the row "FR" that has been changed, or another. This limitation does not apply to tables whose primary key is the rowid: `Player.filter(key: 42)` will only notify of changes performed on the row with id 42. - For more details, see the [reference](http://groue.github.io/GRDB.swift/docs/3.7/Structs/DatabaseRegion.html#/s:4GRDB14DatabaseRegionV10isModified2bySbAA0B5EventV_tF).