@@ -174,7 +174,9 @@ pub struct TxData {
174
174
/// The inserted rows per table.
175
175
inserts : BTreeMap < TableId , Arc < [ ProductValue ] > > ,
176
176
/// The deleted rows per table.
177
- deletes : BTreeMap < TableId , Arc < [ ProductValue ] > > ,
177
+ ///
178
+ /// Also stores per table whether it has been truncated.
179
+ deletes : BTreeMap < TableId , TxDeleteEntry > ,
178
180
/// Map of all `TableId`s in both `inserts` and `deletes` to their
179
181
/// corresponding table name.
180
182
tables : IntMap < TableId , String > ,
@@ -186,6 +188,24 @@ pub struct TxData {
186
188
// TODO: Store an `Arc<String>` or equivalent instead.
187
189
}
188
190
191
+ /// A record of a list of deletes for and potential truncation of a table,
192
+ /// within a transaction.
193
+ pub struct TxDeleteEntry {
194
+ /// Were all rows previously in the table deleted within this transaction?
195
+ truncated : TxTableTruncated ,
196
+ /// The deleted rows of the table.
197
+ rows : Arc < [ ProductValue ] > ,
198
+ }
199
+
200
+ /// Whether a table was truncated in a transaction.
201
+ #[ derive( Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Debug ) ]
202
+ pub enum TxTableTruncated {
203
+ /// It was truncated.
204
+ Yes ,
205
+ /// It was not truncated.
206
+ No ,
207
+ }
208
+
189
209
impl TxData {
190
210
/// Set `tx_offset` as the expected on-disk transaction offset of this transaction.
191
211
pub fn set_tx_offset ( & mut self , tx_offset : u64 ) {
@@ -208,8 +228,22 @@ impl TxData {
208
228
}
209
229
210
230
/// Set `rows` as the deleted rows for `(table_id, table_name)`.
211
- pub fn set_deletes_for_table ( & mut self , table_id : TableId , table_name : & str , rows : Arc < [ ProductValue ] > ) {
212
- self . deletes . insert ( table_id, rows) ;
231
+ ///
232
+ /// When `truncated` is set, the table has been emptied in this transaction.
233
+ pub fn set_deletes_for_table (
234
+ & mut self ,
235
+ table_id : TableId ,
236
+ table_name : & str ,
237
+ rows : Arc < [ ProductValue ] > ,
238
+ truncated : bool ,
239
+ ) {
240
+ let truncated = if truncated {
241
+ TxTableTruncated :: Yes
242
+ } else {
243
+ TxTableTruncated :: No
244
+ } ;
245
+ let entry = TxDeleteEntry { truncated, rows } ;
246
+ self . deletes . insert ( table_id, entry) ;
213
247
self . tables . entry ( table_id) . or_insert_with ( || table_name. to_owned ( ) ) ;
214
248
}
215
249
@@ -238,26 +272,28 @@ impl TxData {
238
272
}
239
273
240
274
/// Obtain an iterator over the deleted rows per table.
241
- pub fn deletes ( & self ) -> impl Iterator < Item = ( & TableId , & Arc < [ ProductValue ] > ) > + ' _ {
242
- self . deletes . iter ( )
275
+ pub fn deletes ( & self ) -> impl Iterator < Item = ( & TableId , TxTableTruncated , & Arc < [ ProductValue ] > ) > + ' _ {
276
+ self . deletes
277
+ . iter ( )
278
+ . map ( |( table_id, entry) | ( table_id, entry. truncated , & entry. rows ) )
243
279
}
244
280
245
281
/// Get the `i`th deleted row for `table_id` if it exists
246
282
pub fn get_ith_delete ( & self , table_id : TableId , i : usize ) -> Option < & ProductValue > {
247
- self . deletes . get ( & table_id) . and_then ( |rows| rows. get ( i) )
283
+ self . deletes . get ( & table_id) . and_then ( |entry| entry . rows . get ( i) )
248
284
}
249
285
250
286
/// Obtain an iterator over the inserted rows per table.
251
287
///
252
288
/// If you don't need access to the table name, [`Self::deletes`] is
253
289
/// slightly more efficient.
254
290
pub fn deletes_with_table_name ( & self ) -> impl Iterator < Item = ( & TableId , & str , & Arc < [ ProductValue ] > ) > + ' _ {
255
- self . deletes . iter ( ) . map ( |( table_id, rows ) | {
291
+ self . deletes . iter ( ) . map ( |( table_id, entry ) | {
256
292
let table_name = self
257
293
. tables
258
294
. get ( table_id)
259
295
. expect ( "invalid `TxData`: partial table name mapping" ) ;
260
- ( table_id, table_name. as_str ( ) , rows)
296
+ ( table_id, table_name. as_str ( ) , & entry . rows )
261
297
} )
262
298
}
263
299
@@ -266,7 +302,7 @@ impl TxData {
266
302
/// This is used to determine if a transaction should be written to disk.
267
303
pub fn has_rows_or_connect_disconnect ( & self , reducer_context : Option < & ReducerContext > ) -> bool {
268
304
self . inserts ( ) . any ( |( _, inserted_rows) | !inserted_rows. is_empty ( ) )
269
- || self . deletes ( ) . any ( |( _ , deleted_rows) | !deleted_rows. is_empty ( ) )
305
+ || self . deletes ( ) . any ( |( .. , deleted_rows) | !deleted_rows. is_empty ( ) )
270
306
|| matches ! (
271
307
reducer_context. map( |rcx| rcx. name. strip_prefix( "__identity_" ) ) ,
272
308
Some ( Some ( "connected__" | "disconnected__" ) )
0 commit comments