@@ -174,7 +174,9 @@ pub struct TxData {
174174 /// The inserted rows per table.
175175 inserts : BTreeMap < TableId , Arc < [ ProductValue ] > > ,
176176 /// 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 > ,
178180 /// Map of all `TableId`s in both `inserts` and `deletes` to their
179181 /// corresponding table name.
180182 tables : IntMap < TableId , String > ,
@@ -186,6 +188,24 @@ pub struct TxData {
186188 // TODO: Store an `Arc<String>` or equivalent instead.
187189}
188190
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+
189209impl TxData {
190210 /// Set `tx_offset` as the expected on-disk transaction offset of this transaction.
191211 pub fn set_tx_offset ( & mut self , tx_offset : u64 ) {
@@ -208,8 +228,22 @@ impl TxData {
208228 }
209229
210230 /// 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) ;
213247 self . tables . entry ( table_id) . or_insert_with ( || table_name. to_owned ( ) ) ;
214248 }
215249
@@ -238,26 +272,28 @@ impl TxData {
238272 }
239273
240274 /// 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 ) )
243279 }
244280
245281 /// Get the `i`th deleted row for `table_id` if it exists
246282 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) )
248284 }
249285
250286 /// Obtain an iterator over the inserted rows per table.
251287 ///
252288 /// If you don't need access to the table name, [`Self::deletes`] is
253289 /// slightly more efficient.
254290 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 ) | {
256292 let table_name = self
257293 . tables
258294 . get ( table_id)
259295 . expect ( "invalid `TxData`: partial table name mapping" ) ;
260- ( table_id, table_name. as_str ( ) , rows)
296+ ( table_id, table_name. as_str ( ) , & entry . rows )
261297 } )
262298 }
263299
@@ -266,7 +302,7 @@ impl TxData {
266302 /// This is used to determine if a transaction should be written to disk.
267303 pub fn has_rows_or_connect_disconnect ( & self , reducer_context : Option < & ReducerContext > ) -> bool {
268304 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 ( ) )
270306 || matches ! (
271307 reducer_context. map( |rcx| rcx. name. strip_prefix( "__identity_" ) ) ,
272308 Some ( Some ( "connected__" | "disconnected__" ) )
0 commit comments