diff --git a/docs/src/js/interfaces/MergeResult.md b/docs/src/js/interfaces/MergeResult.md index 9874fd5d..d59049cb 100644 --- a/docs/src/js/interfaces/MergeResult.md +++ b/docs/src/js/interfaces/MergeResult.md @@ -8,6 +8,14 @@ ## Properties +### numAttempts + +```ts +numAttempts: number; +``` + +*** + ### numDeletedRows ```ts diff --git a/nodejs/src/table.rs b/nodejs/src/table.rs index 56517e76..aa2bc51e 100644 --- a/nodejs/src/table.rs +++ b/nodejs/src/table.rs @@ -740,6 +740,7 @@ pub struct MergeResult { pub num_inserted_rows: i64, pub num_updated_rows: i64, pub num_deleted_rows: i64, + pub num_attempts: i64, } impl From for MergeResult { @@ -749,6 +750,7 @@ impl From for MergeResult { num_inserted_rows: value.num_inserted_rows as i64, num_updated_rows: value.num_updated_rows as i64, num_deleted_rows: value.num_deleted_rows as i64, + num_attempts: value.num_attempts as i64, } } } diff --git a/python/python/lancedb/_lancedb.pyi b/python/python/lancedb/_lancedb.pyi index d5b39c9b..77791c59 100644 --- a/python/python/lancedb/_lancedb.pyi +++ b/python/python/lancedb/_lancedb.pyi @@ -306,6 +306,7 @@ class MergeResult: num_updated_rows: int num_inserted_rows: int num_deleted_rows: int + num_attempts: int class AddColumnsResult: version: int diff --git a/python/src/table.rs b/python/src/table.rs index 2097909a..eaa55633 100644 --- a/python/src/table.rs +++ b/python/src/table.rs @@ -134,17 +134,19 @@ pub struct MergeResult { pub num_updated_rows: u64, pub num_inserted_rows: u64, pub num_deleted_rows: u64, + pub num_attempts: u32, } #[pymethods] impl MergeResult { pub fn __repr__(&self) -> String { format!( - "MergeResult(version={}, num_updated_rows={}, num_inserted_rows={}, num_deleted_rows={})", + "MergeResult(version={}, num_updated_rows={}, num_inserted_rows={}, num_deleted_rows={}, num_attempts={})", self.version, self.num_updated_rows, self.num_inserted_rows, - self.num_deleted_rows + self.num_deleted_rows, + self.num_attempts ) } } @@ -156,6 +158,7 @@ impl From for MergeResult { num_updated_rows: result.num_updated_rows, num_inserted_rows: result.num_inserted_rows, num_deleted_rows: result.num_deleted_rows, + num_attempts: result.num_attempts, } } } diff --git a/rust/lancedb/src/remote/table.rs b/rust/lancedb/src/remote/table.rs index 0da9586d..f28770da 100644 --- a/rust/lancedb/src/remote/table.rs +++ b/rust/lancedb/src/remote/table.rs @@ -1183,6 +1183,7 @@ impl BaseTable for RemoteTable { num_deleted_rows: 0, num_inserted_rows: 0, num_updated_rows: 0, + num_attempts: 0, }); } diff --git a/rust/lancedb/src/table.rs b/rust/lancedb/src/table.rs index 5aae72f7..79c1be35 100644 --- a/rust/lancedb/src/table.rs +++ b/rust/lancedb/src/table.rs @@ -467,6 +467,11 @@ pub struct MergeResult { /// However those rows are not shared with the user. #[serde(default)] pub num_deleted_rows: u64, + /// Number of attempts performed during the merge operation. + /// This includes the initial attempt plus any retries due to transaction conflicts. + /// A value of 1 means the operation succeeded on the first try. + #[serde(default)] + pub num_attempts: u32, } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)] @@ -2531,6 +2536,7 @@ impl BaseTable for NativeTable { num_updated_rows: stats.num_updated_rows, num_inserted_rows: stats.num_inserted_rows, num_deleted_rows: stats.num_deleted_rows, + num_attempts: stats.num_attempts, }) } @@ -2990,9 +2996,13 @@ mod tests { // Perform a "insert if not exists" let mut merge_insert_builder = table.merge_insert(&["i"]); merge_insert_builder.when_not_matched_insert_all(); - merge_insert_builder.execute(new_batches).await.unwrap(); + let result = merge_insert_builder.execute(new_batches).await.unwrap(); // Only 5 rows should actually be inserted assert_eq!(table.count_rows(None).await.unwrap(), 15); + assert_eq!(result.num_inserted_rows, 5); + assert_eq!(result.num_updated_rows, 0); + assert_eq!(result.num_deleted_rows, 0); + assert_eq!(result.num_attempts, 1); // Create new data with i=15..25 (no id matches) let new_batches = Box::new(merge_insert_test_batches(15, 2));