Skip to content

Commit 52d05c0

Browse files
committed
Revert "Public method for fetching metadata."
This reverts commit 6519f17.
1 parent 6519f17 commit 52d05c0

File tree

2 files changed

+141
-153
lines changed

2 files changed

+141
-153
lines changed
Lines changed: 130 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -1,158 +1,149 @@
11
#if canImport(CloudKit)
2-
import CloudKit
3-
4-
/// A table that tracks metadata related to synchronized data.
5-
///
6-
/// Each row of this table represents a synchronized record across all tables synchronized with
7-
/// CloudKit. This means that the sum of the count of rows across all synchronized tables in your
8-
/// application is the number of rows this one single table holds. However, this table is held
9-
/// in a database separate from your app's database.
2+
import CloudKit
3+
4+
/// A table that tracks metadata related to synchronized data.
5+
///
6+
/// Each row of this table represents a synchronized record across all tables synchronized with
7+
/// CloudKit. This means that the sum of the count of rows across all synchronized tables in your
8+
/// application is the number of rows this one single table holds. However, this table is held
9+
/// in a database separate from your app's database.
10+
///
11+
///
12+
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
13+
// @Table("\(String.sqliteDataCloudKitSchemaName)_metadata")
14+
public struct SyncMetadata: Hashable, Sendable {
15+
/// The unique identifier of the record synchronized.
16+
public var recordPrimaryKey: String
17+
18+
/// The type of the record synchronized, _i.e._ its table name.
19+
public var recordType: String
20+
21+
/// The name of the record synchronized.
1022
///
23+
/// This field encodes both the table name and primary key of the record synchronized in
24+
/// the format "primaryKey:tableName", for example:
1125
///
12-
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
13-
// @Table("\(String.sqliteDataCloudKitSchemaName)_metadata")
14-
public struct SyncMetadata: Hashable, Sendable {
15-
/// The unique identifier of the record synchronized.
16-
public var recordPrimaryKey: String
17-
18-
/// The type of the record synchronized, _i.e._ its table name.
19-
public var recordType: String
20-
21-
/// The name of the record synchronized.
22-
///
23-
/// This field encodes both the table name and primary key of the record synchronized in
24-
/// the format "primaryKey:tableName", for example:
25-
///
26-
/// ```swift
27-
/// "8c4d1e4e-49b2-4f60-b6df-3c23881b87c6:reminders"
28-
/// ```
29-
// @Column(generated: .virtual)
30-
public let recordName: String
31-
32-
/// The unique identifier of this record's parent, if any.
33-
public var parentRecordPrimaryKey: String?
34-
35-
/// The type of this record's parent, _i.e._ its table name, if any.
36-
public var parentRecordType: String?
37-
38-
/// The name of this record's parent, if any.
39-
///
40-
/// This field encodes both the table name and primary key of the parent record in the format
41-
/// "primaryKey:tableName", for example:
42-
///
43-
/// ```swift
44-
/// "d35e1f81-46e4-45d1-904b-2b7df1661e3e:remindersLists"
45-
/// ```
46-
// @Column(generated: .virtual)
47-
public let parentRecordName: String?
48-
49-
/// The last known `CKRecord` received from the server.
50-
///
51-
/// This record holds only the fields that are archived when using `encodeSystemFields(with:)`.
52-
// @Column(as: CKRecord?.SystemFieldsRepresentation.self)
53-
public var lastKnownServerRecord: CKRecord?
26+
/// ```swift
27+
/// "8c4d1e4e-49b2-4f60-b6df-3c23881b87c6:reminders"
28+
/// ```
29+
// @Column(generated: .virtual)
30+
public let recordName: String
5431

55-
/// The last known `CKRecord` received from the server with all fields archived.
56-
// @Column(as: CKRecord?.SystemFieldsRepresentation.self)
57-
package var _lastKnownServerRecordAllFields: CKRecord?
58-
59-
/// The `CKShare` associated with this record, if it is shared.
60-
// @Column(as: CKShare?.SystemFieldsRepresentation.self)
61-
public var share: CKShare?
62-
63-
// @Column(generated: .virtual)
64-
public let isShared: Bool
65-
66-
/// The date the user last modified the record.
67-
public var userModificationDate: Date
68-
69-
package init(
70-
recordPrimaryKey: String,
71-
recordType: String,
72-
parentRecordPrimaryKey: String? = nil,
73-
parentRecordType: String? = nil,
74-
lastKnownServerRecord: CKRecord? = nil,
75-
_lastKnownServerRecordAllFields: CKRecord? = nil,
76-
share: CKShare? = nil,
77-
userModificationDate: Date
78-
) {
79-
self.recordPrimaryKey = recordPrimaryKey
80-
self.recordType = recordType
81-
self.recordName = "\(recordPrimaryKey):\(recordType)"
82-
self.parentRecordPrimaryKey = parentRecordPrimaryKey
83-
self.parentRecordType = parentRecordType
84-
if let parentRecordPrimaryKey, let parentRecordType {
85-
self.parentRecordName = "\(parentRecordPrimaryKey):\(parentRecordType)"
86-
} else {
87-
self.parentRecordName = nil
88-
}
89-
self.lastKnownServerRecord = lastKnownServerRecord
90-
self._lastKnownServerRecordAllFields = _lastKnownServerRecordAllFields
91-
self.share = share
92-
self.isShared = share != nil
93-
self.userModificationDate = userModificationDate
94-
}
32+
/// The unique identifier of this record's parent, if any.
33+
public var parentRecordPrimaryKey: String?
9534

96-
// @Selection @Table
97-
struct AncestorMetadata {
98-
let recordName: String
99-
let parentRecordName: String?
100-
// @Column(as: CKRecord?.SystemFieldsRepresentation.self)
101-
let lastKnownServerRecord: CKRecord?
102-
}
103-
}
35+
/// The type of this record's parent, _i.e._ its table name, if any.
36+
public var parentRecordType: String?
37+
38+
/// The name of this record's parent, if any.
39+
///
40+
/// This field encodes both the table name and primary key of the parent record in the format
41+
/// "primaryKey:tableName", for example:
42+
///
43+
/// ```swift
44+
/// "d35e1f81-46e4-45d1-904b-2b7df1661e3e:remindersLists"
45+
/// ```
46+
// @Column(generated: .virtual)
47+
public let parentRecordName: String?
10448

105-
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
106-
extension SyncMetadata {
107-
package static func find<T: PrimaryKeyedTable>(
108-
_ primaryKey: T.PrimaryKey.QueryOutput,
109-
table _: T.Type,
110-
)
111-
-> Where<Self>
112-
where T.PrimaryKey: IdentifierStringConvertible {
113-
T.metadata(for: primaryKey)
49+
/// The last known `CKRecord` received from the server.
50+
///
51+
/// This record holds only the fields that are archived when using `encodeSystemFields(with:)`.
52+
// @Column(as: CKRecord?.SystemFieldsRepresentation.self)
53+
public var lastKnownServerRecord: CKRecord?
54+
55+
/// The last known `CKRecord` received from the server with all fields archived.
56+
// @Column(as: CKRecord?.SystemFieldsRepresentation.self)
57+
package var _lastKnownServerRecordAllFields: CKRecord?
58+
59+
/// The `CKShare` associated with this record, if it is shared.
60+
// @Column(as: CKShare?.SystemFieldsRepresentation.self)
61+
public var share: CKShare?
62+
63+
// @Column(generated: .virtual)
64+
public let isShared: Bool
65+
66+
/// The date the user last modified the record.
67+
public var userModificationDate: Date
68+
69+
package init(
70+
recordPrimaryKey: String,
71+
recordType: String,
72+
parentRecordPrimaryKey: String? = nil,
73+
parentRecordType: String? = nil,
74+
lastKnownServerRecord: CKRecord? = nil,
75+
_lastKnownServerRecordAllFields: CKRecord? = nil,
76+
share: CKShare? = nil,
77+
userModificationDate: Date
78+
) {
79+
self.recordPrimaryKey = recordPrimaryKey
80+
self.recordType = recordType
81+
self.recordName = "\(recordPrimaryKey):\(recordType)"
82+
self.parentRecordPrimaryKey = parentRecordPrimaryKey
83+
self.parentRecordType = parentRecordType
84+
if let parentRecordPrimaryKey, let parentRecordType {
85+
self.parentRecordName = "\(parentRecordPrimaryKey):\(parentRecordType)"
86+
} else {
87+
self.parentRecordName = nil
11488
}
89+
self.lastKnownServerRecord = lastKnownServerRecord
90+
self._lastKnownServerRecordAllFields = _lastKnownServerRecordAllFields
91+
self.share = share
92+
self.isShared = share != nil
93+
self.userModificationDate = userModificationDate
11594
}
11695

117-
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
118-
extension PrimaryKeyedTable where PrimaryKey: IdentifierStringConvertible {
119-
public static func metadata(for primaryKey: PrimaryKey.QueryOutput) -> Where<SyncMetadata> {
120-
SyncMetadata.where {
121-
SQLQueryExpression(
122-
"""
123-
\($0.recordPrimaryKey) = \(PrimaryKey(queryOutput: primaryKey)) \
124-
AND \($0.recordType) = \(bind: tableName)
125-
"""
126-
)
127-
}
96+
// @Selection @Table
97+
struct AncestorMetadata {
98+
let recordName: String
99+
let parentRecordName: String?
100+
// @Column(as: CKRecord?.SystemFieldsRepresentation.self)
101+
let lastKnownServerRecord: CKRecord?
102+
}
103+
}
104+
105+
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
106+
extension SyncMetadata {
107+
package static func find<T: PrimaryKeyedTable>(
108+
_ primaryKey: T.PrimaryKey.QueryOutput,
109+
table _: T.Type,
110+
) -> Where<Self> {
111+
Self.where {
112+
SQLQueryExpression(
113+
"""
114+
\($0.recordPrimaryKey) = \(T.PrimaryKey(queryOutput: primaryKey)) \
115+
AND \($0.recordType) = \(bind: T.tableName)
116+
"""
117+
)
128118
}
129119
}
120+
}
130121

131-
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
132-
extension PrimaryKeyedTable where PrimaryKey.QueryOutput: IdentifierStringConvertible {
133-
/// Constructs a ``SyncMetadata/RecordName-swift.struct`` for a primary keyed table give an ID.
134-
///
135-
/// - Parameter id: The ID of the record.
136-
package static func recordName(for id: PrimaryKey.QueryOutput) -> String {
137-
"\(id.rawIdentifier):\(tableName)"
138-
}
122+
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
123+
extension PrimaryKeyedTable where PrimaryKey.QueryOutput: IdentifierStringConvertible {
124+
/// Constructs a ``SyncMetadata/RecordName-swift.struct`` for a primary keyed table give an ID.
125+
///
126+
/// - Parameter id: The ID of the record.
127+
package static func recordName(for id: PrimaryKey.QueryOutput) -> String {
128+
"\(id.rawIdentifier):\(tableName)"
129+
}
139130

140-
var recordName: String {
141-
Self.recordName(for: self[keyPath: Self.columns.primaryKey.keyPath])
142-
}
131+
var recordName: String {
132+
Self.recordName(for: self[keyPath: Self.columns.primaryKey.keyPath])
143133
}
134+
}
144135

145-
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
146-
extension PrimaryKeyedTableDefinition where PrimaryKey.QueryOutput: IdentifierStringConvertible {
147-
public var recordName: some QueryExpression<String> {
148-
_recordName
149-
}
136+
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
137+
extension PrimaryKeyedTableDefinition where PrimaryKey.QueryOutput: IdentifierStringConvertible {
138+
public var recordName: some QueryExpression<String> {
139+
_recordName
150140
}
141+
}
151142

152-
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
153-
extension PrimaryKeyedTableDefinition {
154-
var _recordName: some QueryExpression<String> {
155-
SQLQueryExpression("\(primaryKey) || ':' || \(quote: QueryValue.tableName, delimiter: .text)")
156-
}
143+
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
144+
extension PrimaryKeyedTableDefinition {
145+
var _recordName: some QueryExpression<String> {
146+
SQLQueryExpression("\(primaryKey) || ':' || \(quote: QueryValue.tableName, delimiter: .text)")
157147
}
148+
}
158149
#endif

Sources/SharingGRDBCore/Documentation.docc/Articles/CloudKit.md

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -500,25 +500,21 @@ exposed for you to query it in whichever way you want.
500500
to attach the metadatabase to your database connection. This can be done with the
501501
``GRDB/Database/attachMetadatabase(containerIdentifier:)`` method defined on `Database`.
502502

503-
With that done you can use the ``StructuredQueriesCore/PrimaryKeyedTable/metadata(for:)`` method
504-
to construct a SQL query for fetching the meta data associated with one of your records.
505-
506503
For example, if you want to retrieve the `CKRecord` that is associated with a particular row in
507504
one of your tables, say a reminder, then you can use ``SyncMetadata/lastKnownServerRecord`` to
508505
retreive the `CKRecord` and then invoke a CloudKit database function to retreive all of the details:
509506

510507
```swift
511-
let lastKnownServerRecord = try database.read { db in
512-
try RemindersList
513-
.metadata(for: remindersListID)
514-
.select(\.lastKnownServerRecord)
508+
let metadata = try database.read { db in
509+
try SyncMetadata
510+
.find(RemindersList.recordName(for: remindersListID))
515511
.fetchOne(db)
516512
}
517-
guard let lastKnownServerRecord
513+
guard let metadata
518514
else { return }
519515

520516
let ckRecord = try await container.privateCloudDatabase
521-
.record(for: lastKnownServerRecord.recordID)
517+
.record(for: metadata.lastKnownServerRecord.recordID)
522518
```
523519

524520
> Important: In the above snippet we are explicitly using `privateCloudDatabase`, but that is
@@ -534,13 +530,14 @@ It is also possible to fetch the `CKShare` associated with a record if it has be
534530
will give you access to the most current list of paricipants and permissions for the shared record:
535531

536532
```swift
537-
let share = try database.read { db in
538-
try RemindersList
539-
.metadata(for: remindersListID)
540-
.select(\.share)
533+
let metadata = try database.read { db in
534+
try SyncMetadata
535+
.find(RemindersList.recordName(for: remindersListID))
541536
.fetchOne(db)
542537
}
543-
guard let share
538+
guard
539+
let metadata,
540+
let share = metadata.share
544541
else { return }
545542

546543
let ckRecord = try await container.sharedCloudDatabase

0 commit comments

Comments
 (0)