Skip to content

Commit b8673a9

Browse files
committed
feat(dataframe): add dropColumns method
1 parent 850beeb commit b8673a9

3 files changed

Lines changed: 81 additions & 0 deletions

File tree

native/src/lib.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,33 @@ pub extern "system" fn Java_org_apache_datafusion_DataFrame_distinctRows<'local>
281281
})
282282
}
283283

284+
#[no_mangle]
285+
pub extern "system" fn Java_org_apache_datafusion_DataFrame_dropColumns<'local>(
286+
mut env: JNIEnv<'local>,
287+
_class: JClass<'local>,
288+
handle: jlong,
289+
column_names: JObjectArray<'local>,
290+
) -> jlong {
291+
try_unwrap_or_throw(&mut env, 0, |env| -> JniResult<jlong> {
292+
if handle == 0 {
293+
return Err("DataFrame handle is null".into());
294+
}
295+
let df = unsafe { &*(handle as *const DataFrame) }.clone();
296+
297+
let len = env.get_array_length(&column_names)?;
298+
let mut owned: Vec<String> = Vec::with_capacity(len as usize);
299+
for i in 0..len {
300+
let elem = env.get_object_array_element(&column_names, i)?;
301+
let jstr: JString = elem.into();
302+
owned.push(env.get_string(&jstr)?.into());
303+
}
304+
let refs: Vec<&str> = owned.iter().map(String::as_str).collect();
305+
306+
let new_df = df.drop_columns(&refs)?;
307+
Ok(Box::into_raw(Box::new(new_df)) as jlong)
308+
})
309+
}
310+
284311
#[no_mangle]
285312
pub extern "system" fn Java_org_apache_datafusion_DataFrame_writeParquetWithOptions<'local>(
286313
mut env: JNIEnv<'local>,

src/main/java/org/apache/datafusion/DataFrame.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,17 @@ public DataFrame distinct() {
152152
return new DataFrame(distinctRows(nativeHandle));
153153
}
154154

155+
/**
156+
* Drop the named columns. The inverse of {@link #select(String...)}. The receiver remains usable
157+
* and must still be closed independently.
158+
*/
159+
public DataFrame dropColumns(String... columnNames) {
160+
if (nativeHandle == 0) {
161+
throw new IllegalStateException("DataFrame is closed or already collected");
162+
}
163+
return new DataFrame(dropColumns(nativeHandle, columnNames));
164+
}
165+
155166
/**
156167
* Materialize this DataFrame as Parquet at {@code path}. The path is treated as a directory
157168
* unless overridden via {@link ParquetWriteOptions#singleFileOutput(boolean)}. The receiver
@@ -208,6 +219,8 @@ public void close() {
208219

209220
private static native long distinctRows(long handle);
210221

222+
private static native long dropColumns(long handle, String[] columnNames);
223+
211224
private static native void writeParquetWithOptions(
212225
long handle,
213226
String path,

src/test/java/org/apache/datafusion/DataFrameTransformationsTest.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,4 +253,45 @@ void distinctIsNonDestructive() {
253253
assertEquals(3L, source.count());
254254
}
255255
}
256+
257+
@Test
258+
void dropColumnsRemovesNamedColumns() throws Exception {
259+
try (BufferAllocator allocator = new RootAllocator();
260+
SessionContext ctx = new SessionContext();
261+
DataFrame source = ctx.sql("SELECT 1 AS a, 2 AS b, 3 AS c");
262+
DataFrame dropped = source.dropColumns("b");
263+
ArrowReader reader = dropped.collect(allocator)) {
264+
assertTrue(reader.loadNextBatch());
265+
VectorSchemaRoot root = reader.getVectorSchemaRoot();
266+
assertArrayEquals(
267+
new String[] {"a", "c"},
268+
root.getSchema().getFields().stream().map(f -> f.getName()).toArray(String[]::new));
269+
}
270+
}
271+
272+
@Test
273+
void dropColumnsIsNonDestructive() {
274+
try (SessionContext ctx = new SessionContext();
275+
DataFrame source = ctx.sql("SELECT 1 AS a, 2 AS b")) {
276+
try (DataFrame dropped = source.dropColumns("a")) {
277+
assertEquals(1L, dropped.count());
278+
}
279+
assertEquals(1L, source.count());
280+
}
281+
}
282+
283+
@Test
284+
void dropColumnsSilentlyIgnoresUnknownNames() throws Exception {
285+
try (BufferAllocator allocator = new RootAllocator();
286+
SessionContext ctx = new SessionContext();
287+
DataFrame df = ctx.sql("SELECT 1 AS x");
288+
DataFrame dropped = df.dropColumns("not_a_column");
289+
ArrowReader reader = dropped.collect(allocator)) {
290+
assertTrue(reader.loadNextBatch());
291+
VectorSchemaRoot root = reader.getVectorSchemaRoot();
292+
assertArrayEquals(
293+
new String[] {"x"},
294+
root.getSchema().getFields().stream().map(f -> f.getName()).toArray(String[]::new));
295+
}
296+
}
256297
}

0 commit comments

Comments
 (0)