Skip to content

Commit c68878e

Browse files
Add big endian support
Signed-off-by: Dmitry Nikolaev <dnikolaev@rocketsoftware.com>
1 parent 69062a3 commit c68878e

5 files changed

Lines changed: 38 additions & 40 deletions

File tree

src/jni/refs.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ jmethodID J_DuckStruct_init;
7878
jclass J_ByteBuffer;
7979
jmethodID J_ByteBuffer_order;
8080
jclass J_ByteOrder;
81-
jobject J_ByteOrder_LITTLE_ENDIAN;
81+
jobject J_ByteOrder_NATIVE;
8282

8383
jclass J_DuckMap;
8484
jmethodID J_DuckMap_getSQLTypeName;
@@ -156,6 +156,19 @@ static jfieldID get_field_id(JNIEnv *env, jclass clazz, const std::string &name,
156156
return field_id;
157157
}
158158

159+
static jobject make_static_method_call_ref(JNIEnv *env, jclass clazz, const std::string &name,
160+
const std::string &sig) {
161+
jmethodID method_id = get_static_method_id(env, clazz, name, sig);
162+
jobject local_ref = env->CallStaticObjectMethod(clazz, method_id);
163+
check_not_null(local_ref, "Static method returned null, name: [" + name + "], signature: [" + sig + "]");
164+
jobject global_ref = env->NewGlobalRef(local_ref);
165+
check_not_null(global_ref,
166+
"Cannot create global ref for static method result, name: [" + name + "], signature: [" + sig + "]");
167+
env->DeleteLocalRef(local_ref);
168+
global_refs.emplace_back(global_ref);
169+
return global_ref;
170+
}
171+
159172
static jobject make_static_object_field_ref(JNIEnv *env, jclass clazz, const std::string &name,
160173
const std::string &sig) {
161174
jfieldID field_id = env->GetStaticFieldID(clazz, name.c_str(), sig.c_str());
@@ -278,7 +291,7 @@ void create_refs(JNIEnv *env) {
278291
J_ByteBuffer = make_class_ref(env, "java/nio/ByteBuffer");
279292
J_ByteBuffer_order = get_method_id(env, J_ByteBuffer, "order", "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;");
280293
J_ByteOrder = make_class_ref(env, "java/nio/ByteOrder");
281-
J_ByteOrder_LITTLE_ENDIAN = make_static_object_field_ref(env, J_ByteOrder, "LITTLE_ENDIAN", "Ljava/nio/ByteOrder;");
294+
J_ByteOrder_NATIVE = make_static_method_call_ref(env, J_ByteOrder, "nativeOrder", "()Ljava/nio/ByteOrder;");
282295

283296
J_ProfilerPrintFormat = make_class_ref(env, "org/duckdb/ProfilerPrintFormat");
284297
J_ProfilerPrintFormat_QUERY_TREE =

src/jni/refs.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ extern jmethodID J_DuckStruct_init;
7575
extern jclass J_ByteBuffer;
7676
extern jmethodID J_ByteBuffer_order;
7777
extern jclass J_ByteOrder;
78-
extern jobject J_ByteOrder_LITTLE_ENDIAN;
78+
extern jobject J_ByteOrder_NATIVE;
7979

8080
extern jclass J_DuckMap;
8181
extern jmethodID J_DuckMap_getSQLTypeName;

src/jni/util.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ jobject make_ptr_buf(JNIEnv *env, void *ptr) {
144144
jobject make_data_buf(JNIEnv *env, void *data, idx_t len) {
145145
if (data != nullptr) {
146146
jobject buf = env->NewDirectByteBuffer(data, uint64_to_jlong(len));
147-
env->CallObjectMethod(buf, J_ByteBuffer_order, J_ByteOrder_LITTLE_ENDIAN);
147+
env->CallObjectMethod(buf, J_ByteBuffer_order, J_ByteOrder_NATIVE);
148148
return buf;
149149
}
150150

src/main/java/org/duckdb/DuckDBResultSet.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ public int read(byte[] bytes, int off, int len) throws IOException {
465465

466466
public DuckDBBlobResult(ByteBuffer buffer_p) {
467467
buffer_p.position(0);
468-
buffer_p.order(ByteOrder.LITTLE_ENDIAN);
468+
buffer_p.order(ByteOrder.nativeOrder());
469469
this.buffer = buffer_p;
470470
}
471471

src/main/java/org/duckdb/DuckDBVector.java

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ Boolean getBoolean(int idx) throws SQLException {
457457

458458
protected ByteBuffer getbuf(int idx, int typeWidth) {
459459
ByteBuffer buf = constlen_data;
460-
buf.order(ByteOrder.LITTLE_ENDIAN);
460+
buf.order(ByteOrder.nativeOrder());
461461
buf.position(idx * typeWidth);
462462
return buf;
463463
}
@@ -505,9 +505,7 @@ short getUint8(int idx) throws SQLException {
505505
return 0;
506506
}
507507
if (isType(DuckDBColumnType.UTINYINT)) {
508-
ByteBuffer buf = ByteBuffer.allocate(2);
509-
getbuf(idx, 1).get(buf.array(), 1, 1);
510-
return buf.getShort();
508+
return (short) Byte.toUnsignedInt(getbuf(idx, 1).get());
511509
}
512510
throw new SQLFeatureNotSupportedException("getUint8");
513511
}
@@ -517,10 +515,7 @@ long getUint32(int idx) throws SQLException {
517515
return 0;
518516
}
519517
if (isType(DuckDBColumnType.UINTEGER)) {
520-
ByteBuffer buf = ByteBuffer.allocate(8);
521-
buf.order(ByteOrder.LITTLE_ENDIAN);
522-
getbuf(idx, 4).get(buf.array(), 0, 4);
523-
return buf.getLong();
518+
return Integer.toUnsignedLong(getbuf(idx, 4).getInt());
524519
}
525520
throw new SQLFeatureNotSupportedException("getUint32");
526521
}
@@ -530,10 +525,7 @@ int getUint16(int idx) throws SQLException {
530525
return 0;
531526
}
532527
if (isType(DuckDBColumnType.USMALLINT)) {
533-
ByteBuffer buf = ByteBuffer.allocate(4);
534-
buf.order(ByteOrder.LITTLE_ENDIAN);
535-
getbuf(idx, 2).get(buf.array(), 0, 2);
536-
return buf.getInt();
528+
return Short.toUnsignedInt(getbuf(idx, 2).getShort());
537529
}
538530
throw new SQLFeatureNotSupportedException("getUint16");
539531
}
@@ -543,13 +535,10 @@ BigInteger getUint64(int idx) throws SQLException {
543535
return BigInteger.ZERO;
544536
}
545537
if (isType(DuckDBColumnType.UBIGINT)) {
546-
byte[] buf_res = new byte[16];
547-
byte[] buf = new byte[8];
548-
getbuf(idx, 8).get(buf);
549-
for (int i = 0; i < 8; i++) {
550-
buf_res[i + 8] = buf[7 - i];
551-
}
552-
return new BigInteger(buf_res);
538+
byte[] buf_res = new byte[8];
539+
long value = getbuf(idx, 8).getLong();
540+
ByteBuffer.wrap(buf_res).putLong(value);
541+
return new BigInteger(1, buf_res);
553542
}
554543
throw new SQLFeatureNotSupportedException("getUint64");
555544
}
@@ -601,14 +590,12 @@ BigInteger getHugeint(int idx) throws SQLException {
601590
return BigInteger.ZERO;
602591
}
603592
if (isType(DuckDBColumnType.HUGEINT)) {
604-
byte[] buf = new byte[16];
605-
getbuf(idx, 16).get(buf);
606-
for (int i = 0; i < 8; i++) {
607-
byte keep = buf[i];
608-
buf[i] = buf[15 - i];
609-
buf[15 - i] = keep;
610-
}
611-
return new BigInteger(buf);
593+
byte[] buf_res = new byte[16];
594+
ByteBuffer buf = getbuf(idx, 16);
595+
long lower = buf.getLong();
596+
long upper = buf.getLong();
597+
ByteBuffer.wrap(buf_res).putLong(upper).putLong(lower);
598+
return new BigInteger(buf_res);
612599
}
613600
Object o = getObject(idx);
614601
return new BigInteger(o.toString());
@@ -619,14 +606,12 @@ BigInteger getUhugeint(int idx) throws SQLException {
619606
return BigInteger.ZERO;
620607
}
621608
if (isType(DuckDBColumnType.UHUGEINT)) {
622-
byte[] buf = new byte[16];
623-
getbuf(idx, 16).get(buf);
624-
for (int i = 0; i < 8; i++) {
625-
byte keep = buf[i];
626-
buf[i] = buf[15 - i];
627-
buf[15 - i] = keep;
628-
}
629-
return new BigInteger(1, buf);
609+
byte[] buf_res = new byte[16];
610+
ByteBuffer buf = getbuf(idx, 16);
611+
long lower = buf.getLong();
612+
long upper = buf.getLong();
613+
ByteBuffer.wrap(buf_res).putLong(upper).putLong(lower);
614+
return new BigInteger(1, buf_res);
630615
}
631616
Object o = getObject(idx);
632617
return new BigInteger(o.toString());

0 commit comments

Comments
 (0)