Skip to content

Commit b793aba

Browse files
committed
Support WhenMatched::Delete in merge_insert
1 parent 28445c0 commit b793aba

File tree

11 files changed

+287
-21
lines changed

11 files changed

+287
-21
lines changed

docs/src/rest.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,13 @@ paths:
737737
required: true
738738
schema:
739739
type: string
740+
- name: "when_matched_delete"
741+
in: query
742+
description: Delete all rows in target table where a match exists in source table
743+
required: false
744+
schema:
745+
type: boolean
746+
default: false
740747
- name: "when_matched_update_all"
741748
in: query
742749
description: Update all columns when rows match
@@ -786,6 +793,7 @@ paths:
786793
It passes in the `MergeInsertIntoTableRequest` information in the following way:
787794
- `id`: pass through path parameter of the same name
788795
- `on`: pass through query parameter of the same name
796+
- `when_matched_delete`: pass through query parameter of the same name
789797
- `when_matched_update_all`: pass through query parameter of the same name
790798
- `when_matched_update_all_filt`: pass through query parameter of the same name
791799
- `when_not_matched_insert_all`: pass through query parameter of the same name
@@ -1938,6 +1946,10 @@ components:
19381946
"on":
19391947
description: Column name to use for matching rows (required)
19401948
type: string
1949+
when_matched_delete:
1950+
description: Delete all rows in target table where a match exists in source table
1951+
type: boolean
1952+
default: false
19411953
when_matched_update_all:
19421954
description: Update all columns when rows match
19431955
type: boolean

java/lance-jni/Cargo.lock

Lines changed: 10 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

java/lance-jni/src/merge_insert.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ fn extract_when_matched<'local>(env: &mut JNIEnv<'local>, jparam: &JObject) -> R
113113
Some(expr) => Ok(WhenMatched::UpdateIf(expr)),
114114
None => Err(Error::input_error("No matched updated expr".to_string())),
115115
},
116+
"Delete" => Ok(WhenMatched::Delete),
116117
_ => Err(Error::input_error(format!(
117118
"Illegal when_matched: {when_matched}",
118119
))),

java/src/main/java/com/lancedb/lance/merge/MergeInsertParams.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,19 @@ public MergeInsertParams withMatchedDoNothing() {
6666
return this;
6767
}
6868

69+
/**
70+
* Specify that when a row in the source table matches a row in the target table, the row in the
71+
* target table is deleted.
72+
*
73+
* <p>This can be used to achieve "when matched delete" behavior.
74+
*
75+
* @return This MergeInsertParams instance
76+
*/
77+
public MergeInsertParams withMatchedDelete() {
78+
this.whenMatched = WhenMatched.Delete;
79+
return this;
80+
}
81+
6982
/**
7083
* Specify that when a row in the source table matches a row in the target table and the
7184
* expression evaluates to true, the row in the target table is updated by the matched row from
@@ -284,6 +297,9 @@ public enum WhenMatched {
284297
* true.
285298
*/
286299
UpdateIf,
300+
301+
/** The row is deleted from the target table. */
302+
Delete
287303
}
288304

289305
public enum WhenNotMatched {

java/src/test/java/com/lancedb/lance/MergeInsertTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,24 @@ public void testWhenMatchedUpdateIf() throws Exception {
120120
}
121121
}
122122

123+
@Test
124+
public void testWhenMatchedDelete() throws Exception {
125+
// Test delete matched target rows if expression is true
126+
127+
try (VectorSchemaRoot source = buildSource(testDataset.getSchema(), allocator)) {
128+
try (ArrowArrayStream sourceStream = convertToStream(source, allocator)) {
129+
MergeInsertResult result =
130+
dataset.mergeInsert(
131+
new MergeInsertParams(Collections.singletonList("id"))
132+
.withMatchedDelete()
133+
.withNotMatched(MergeInsertParams.WhenNotMatched.DoNothing),
134+
sourceStream);
135+
136+
Assertions.assertEquals("{3=Person 3, 4=Person 4}", readAll(result.dataset()).toString());
137+
}
138+
}
139+
}
140+
123141
@Test
124142
public void testWhenNotMatchedBySourceDelete() throws Exception {
125143
// Test delete target rows which are not matched with source.

python/python/lance/dataset.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,16 @@ def when_matched_update_all(
159159
"""
160160
return super(MergeInsertBuilder, self).when_matched_update_all(condition)
161161

162+
def when_matched_delete(self) -> "MergeInsertBuilder":
163+
"""
164+
Configure the operation to delete matched rows in the target table.
165+
166+
After this method is called, when the merge insert operation executes,
167+
any rows that match both the source table and the target table will be
168+
deleted.
169+
"""
170+
return super(MergeInsertBuilder, self).when_matched_delete()
171+
162172
def when_not_matched_insert_all(self) -> "MergeInsertBuilder":
163173
"""
164174
Configure the operation to insert not matched rows

python/src/dataset.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,11 @@ impl MergeInsertBuilder {
177177
Ok(slf)
178178
}
179179

180+
pub fn when_matched_delete(mut slf: PyRefMut<Self>) -> PyResult<PyRefMut<Self>> {
181+
slf.builder.when_matched(WhenMatched::Delete);
182+
Ok(slf)
183+
}
184+
180185
pub fn when_not_matched_insert_all(mut slf: PyRefMut<Self>) -> PyResult<PyRefMut<Self>> {
181186
slf.builder.when_not_matched(WhenNotMatched::InsertAll);
182187
Ok(slf)

0 commit comments

Comments
 (0)