@@ -26,6 +26,46 @@ public protocol TableProtocol {
26
26
///
27
27
var viewNameOverride : String ? { get }
28
28
var viewName : String { get }
29
+
30
+ /// Whether to add a hidden `_metadata` column that will ne abled for updates to
31
+ /// attach custom information about writes.
32
+ ///
33
+ /// When the `_metadata` column is written to for inserts or updates, its value will not be
34
+ /// part of ``CrudEntry/opData``. Instead, it is reported as ``CrudEntry/metadata``,
35
+ /// allowing ``PowerSyncBackendConnector``s to handle these updates specially.
36
+ var trackMetadata : Bool { get }
37
+
38
+ /// When set to a non-`nil` value, track old values of columns for ``CrudEntry/previousValues``.
39
+ ///
40
+ /// See ``TrackPreviousValuesOptions`` for details
41
+ var trackPreviousValues : TrackPreviousValuesOptions ? { get }
42
+
43
+ /// Whether an `UPDATE` statement that doesn't change any values should be ignored entirely when
44
+ /// creating CRUD entries.
45
+ ///
46
+ /// This is disabled by default, meaning that an `UPDATE` on a row that doesn't change values would
47
+ /// create a ``CrudEntry`` with an empty ``CrudEntry/opData`` and ``UpdateType/patch``.
48
+ var ignoreEmptyUpdates : Bool { get }
49
+ }
50
+
51
+ /// Options to include old values in ``CrudEntry/previousValues`` for update statements.
52
+ ///
53
+ /// These options are enabled by passing them to a non-local ``Table`` constructor.
54
+ public struct TrackPreviousValuesOptions {
55
+ /// A filter of column names for which updates should be tracked.
56
+ ///
57
+ /// When set to a non-`nil` value, columns not included in this list will not appear in
58
+ /// ``CrudEntry/previousValues``. By default, all columns are included.
59
+ public let columnFilter : [ String ] ? ;
60
+
61
+ /// Whether to only include old values when they were changed by an update, instead of always including
62
+ /// all old values.
63
+ public let onlyWhenChanged : Bool ;
64
+
65
+ public init ( columnFilter: [ String ] ? = nil , onlyWhenChanged: Bool = false ) {
66
+ self . columnFilter = columnFilter
67
+ self . onlyWhenChanged = onlyWhenChanged
68
+ }
29
69
}
30
70
31
71
private let MAX_AMOUNT_OF_COLUMNS = 63
@@ -40,6 +80,9 @@ public struct Table: TableProtocol {
40
80
public let localOnly : Bool
41
81
public let insertOnly : Bool
42
82
public let viewNameOverride : String ?
83
+ public let trackMetadata : Bool
84
+ public let trackPreviousValues : TrackPreviousValuesOptions ?
85
+ public let ignoreEmptyUpdates : Bool
43
86
44
87
public var viewName : String {
45
88
viewNameOverride ?? name
@@ -60,14 +103,20 @@ public struct Table: TableProtocol {
60
103
indexes: [ Index ] = [ ] ,
61
104
localOnly: Bool = false ,
62
105
insertOnly: Bool = false ,
63
- viewNameOverride: String ? = nil
106
+ viewNameOverride: String ? = nil ,
107
+ trackMetadata: Bool = false ,
108
+ trackPreviousValues: TrackPreviousValuesOptions ? = nil ,
109
+ ignoreEmptyUpdates: Bool = false
64
110
) {
65
111
self . name = name
66
112
self . columns = columns
67
113
self . indexes = indexes
68
114
self . localOnly = localOnly
69
115
self . insertOnly = insertOnly
70
116
self . viewNameOverride = viewNameOverride
117
+ self . trackMetadata = trackMetadata
118
+ self . trackPreviousValues = trackPreviousValues
119
+ self . ignoreEmptyUpdates = ignoreEmptyUpdates
71
120
}
72
121
73
122
private func hasInvalidSqliteCharacters( _ string: String ) -> Bool {
@@ -82,11 +131,20 @@ public struct Table: TableProtocol {
82
131
if columns. count > MAX_AMOUNT_OF_COLUMNS {
83
132
throw TableError . tooManyColumns ( tableName: name, count: columns. count)
84
133
}
85
-
134
+
86
135
if let viewNameOverride = viewNameOverride,
87
136
hasInvalidSqliteCharacters ( viewNameOverride) {
88
137
throw TableError . invalidViewName ( viewName: viewNameOverride)
89
138
}
139
+
140
+ if localOnly {
141
+ if trackPreviousValues != nil {
142
+ throw TableError . trackPreviousForLocalTable ( tableName: name)
143
+ }
144
+ if trackMetadata {
145
+ throw TableError . metadataForLocalTable ( tableName: name)
146
+ }
147
+ }
90
148
91
149
var columnNames = Set < String > ( [ " id " ] )
92
150
@@ -156,4 +214,8 @@ public enum TableError: Error {
156
214
case duplicateIndex( tableName: String , indexName: String )
157
215
case invalidIndexName( tableName: String , indexName: String )
158
216
case columnNotFound( tableName: String , columnName: String , indexName: String )
217
+ /// Local-only tables can't enable ``Table/trackMetadata`` because no updates are tracked for those tables at all.
218
+ case metadataForLocalTable( tableName: String )
219
+ /// Local-only tables can't enable ``Table/trackPreviousValues`` because no updates are tracked for those tables at all.
220
+ case trackPreviousForLocalTable( tableName: String )
159
221
}
0 commit comments