Skip to content

Commit 6b135ac

Browse files
authored
fix: FFI/Java bindings improvements (#2644)
Implement some small fixes for Java - Handle dropping field DTypes when creating Struct DType, less error-prone than relying on user to call free - Expose nullability + null_count over FFI and in Java bindings
1 parent 58c8fa6 commit 6b135ac

File tree

10 files changed

+47
-81
lines changed

10 files changed

+47
-81
lines changed

java/vortex-jni/src/main/java/dev/vortex/api/Array.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ public interface Array extends AutoCloseable {
2626

2727
boolean getNull(int index);
2828

29+
int getNullCount();
30+
2931
byte getByte(int index);
3032

3133
short getShort(int index);
@@ -43,4 +45,7 @@ public interface Array extends AutoCloseable {
4345
String getUTF8(int index);
4446

4547
byte[] getBinary(int index);
48+
49+
@Override
50+
void close();
4651
}

java/vortex-jni/src/main/java/dev/vortex/api/ArrayStream.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,7 @@ public interface ArrayStream extends AutoCloseable {
2626
* It is an error to call this method if a previous invocation returned false.
2727
*/
2828
boolean next();
29+
30+
@Override
31+
void close();
2932
}

java/vortex-jni/src/main/java/dev/vortex/impl/NativeArray.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,14 @@ public Array slice(int start, int stop) {
8484

8585
@Override
8686
public boolean getNull(int index) {
87-
// check validity of the array
88-
return false;
87+
checkNotNull(inner, "inner");
88+
return FFI.FFIArray_is_null(inner, index);
89+
}
90+
91+
@Override
92+
public int getNullCount() {
93+
checkNotNull(inner, "inner");
94+
return FFI.FFIArray_null_count(inner);
8995
}
9096

9197
@Override

java/vortex-jni/src/main/java/dev/vortex/jni/FFI.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ public final class FFI {
3737

3838
public static native FFIArray FFIArray_slice(FFIArray array, int start, int stop);
3939

40+
public static native boolean FFIArray_is_null(FFIArray array, int index);
41+
42+
public static native int FFIArray_null_count(FFIArray array);
43+
4044
public static native FFIArray FFIArray_get_field(FFIArray array, int index);
4145

4246
public static native byte FFIArray_get_u8(FFIArray array, int index);

java/vortex-jni/src/test/java/dev/vortex/jni/FFITest.java

Lines changed: 0 additions & 72 deletions
This file was deleted.

java/vortex-spark/src/main/java/dev/vortex/spark/read/VortexColumnVector.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
import dev.vortex.api.Array;
1919
import dev.vortex.spark.SparkTypes;
20-
import java.io.IOException;
2120
import org.apache.spark.sql.types.Decimal;
2221
import org.apache.spark.sql.vectorized.ColumnVector;
2322
import org.apache.spark.sql.vectorized.ColumnarArray;
@@ -36,7 +35,7 @@ public VortexColumnVector(Array array) {
3635
public void close() {
3736
try {
3837
array.close();
39-
} catch (IOException e) {
38+
} catch (Exception e) {
4039
throw new RuntimeException("Failed to close Vortex Array", e);
4140
}
4241
}

java/vortex-spark/src/main/java/dev/vortex/spark/read/VortexPartitionReader.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import dev.vortex.api.ScanOptions;
2525
import dev.vortex.impl.NativeFile;
2626
import dev.vortex.spark.VortexFilePartition;
27-
import java.io.IOException;
2827
import java.util.Objects;
2928
import org.apache.spark.sql.connector.read.PartitionReader;
3029
import org.apache.spark.sql.vectorized.ColumnarBatch;
@@ -72,7 +71,7 @@ void initNativeResources() {
7271
}
7372

7473
@Override
75-
public void close() throws IOException {
74+
public void close() {
7675
checkState(Objects.nonNull(file), "File was closed");
7776
checkState(Objects.nonNull(arrayStream), "ArrayStream was closed");
7877

java/vortex-spark/src/test/java/dev/vortex/spark/VortexScanTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
import java.nio.file.Path;
2020
import java.nio.file.Paths;
2121
import org.apache.spark.sql.SparkSession;
22+
import org.junit.jupiter.api.Disabled;
2223
import org.junit.jupiter.api.Test;
2324

25+
@Disabled
2426
final class VortexScanTest {
2527
private static final Path TPCH_ROOT = Paths.get("/Volumes/Code/vortex/bench-vortex/data/tpch/1/vortex_compressed");
2628

vortex-ffi/src/array.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,27 @@ pub unsafe extern "C" fn FFIArray_slice(
8282
Box::into_raw(Box::new(FFIArray { inner: sliced }))
8383
}
8484

85+
#[unsafe(no_mangle)]
86+
pub unsafe extern "C" fn FFIArray_is_null(array: *const FFIArray, index: u32) -> bool {
87+
let array = &*array;
88+
array
89+
.inner
90+
.is_invalid(index as usize)
91+
.vortex_expect("FFIArray_is_null: is_invalid")
92+
}
93+
94+
#[unsafe(no_mangle)]
95+
pub unsafe extern "C" fn FFIArray_null_count(array: *const FFIArray) -> u32 {
96+
let array = &*array;
97+
array
98+
.inner
99+
.as_ref()
100+
.invalid_count()
101+
.vortex_expect("FFIArray_null_count: invalid count")
102+
.try_into()
103+
.vortex_expect("FFIArray_null_count: invalid count to u32")
104+
}
105+
85106
macro_rules! ffiarray_get_ptype {
86107
($ptype:ident) => {
87108
paste::paste! {

vortex-ffi/src/dtype.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ pub unsafe extern "C" fn DType_new_struct(
6868
for i in 0..len {
6969
let name_ptr = *names.add(i as usize);
7070
let name: Arc<str> = CStr::from_ptr(name_ptr).to_string_lossy().into();
71-
let dtype = (**dtypes.add(i as usize)).clone();
71+
let dtype = Box::from_raw(*dtypes.add(i as usize));
72+
let dtype = *dtype;
7273

7374
rust_names.push(name);
7475
field_dtypes.push(dtype);
@@ -301,8 +302,6 @@ mod tests {
301302
let dtypes = [name, age];
302303

303304
let person = DType_new_struct(names.as_ptr(), dtypes.as_ptr(), 2, false);
304-
DType_free(name);
305-
DType_free(age);
306305

307306
assert_eq!(DType_get(person), DTYPE_STRUCT);
308307
assert_eq!(DType_field_count(person), 2);

0 commit comments

Comments
 (0)