Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/jni/duckdb_java.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,9 @@ jobjectArray _duckdb_jdbc_cast_result_to_strings(JNIEnv *env, jclass, jobject re
}

jobject ProcessVector(JNIEnv *env, Connection *conn_ref, Vector &vec, idx_t row_count) {
if (vec.GetVectorType() != VectorType::FLAT_VECTOR) {
vec.Flatten(row_count);
}
auto type_str = env->NewStringUTF(type_to_jduckdb_type(vec.GetType()).c_str());
// construct nullmask
auto null_array = env->NewBooleanArray(row_count);
Expand Down Expand Up @@ -723,7 +726,6 @@ jobject ProcessVector(JNIEnv *env, Connection *conn_ref, Vector &vec, idx_t row_
continue;
}
Vector variant_vec(variant_val);
variant_vec.Flatten(1);
jobject variant_j_vec = ProcessVector(env, conn_ref, variant_vec, 1);
env->CallVoidMethod(variant_j_vec, J_DuckVector_retainConstlenData);
env->SetObjectArrayElement(varlen_data, row_idx, variant_j_vec);
Expand All @@ -734,6 +736,9 @@ jobject ProcessVector(JNIEnv *env, Connection *conn_ref, Vector &vec, idx_t row_
Vector string_vec(LogicalType::VARCHAR);
VectorOperations::Cast(*conn_ref->context, vec, string_vec, row_count);
vec.ReferenceAndSetType(string_vec);
if (vec.GetVectorType() != VectorType::FLAT_VECTOR) {
vec.Flatten(row_count);
}
// fall through on purpose
}
case LogicalTypeId::VARCHAR:
Expand Down
42 changes: 42 additions & 0 deletions src/test/java/org/duckdb/TestVariant.java
Original file line number Diff line number Diff line change
Expand Up @@ -268,4 +268,46 @@ public static void test_variant_struct_with_variant() throws Exception {
}
}
}

public static void test_variant_nested_struct_json() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement stmt = conn.createStatement()) {
stmt.execute("CREATE TABLE IF NOT EXISTS events (\n"
+ " globalSequence BIGINT,\n"
+ " data VARIANT\n"
+ " )");

String testData = "{\n"
+ " \"id\": \"72869b95-ab13-4405-9371-546b6dcc443e\",\n"
+ " \"isSimulation\": false,\n"
+ " \"workOrderSchedules\": [\n"
+ " {\n"
+ " \"workOrderId\": \"e10c064f-6280-41f7-be75-b0075234754b\",\n"
+ " \"scheduledStart\": \"2026-06-02T22:56:00\",\n"
+ " \"scheduledEnd\": \"2026-06-03T05:01:00\",\n"
+ " \"scheduledResourceIds\": [\n"
+ " \"a49f8503-f2db-43aa-9d7c-711fc78d8dc9\"\n"
+ " ],\n"
+ " \"batchId\": null,\n"
+ " \"batchSequence\": null\n"
+ " }\n"
+ " ],\n"
+ " \"simulationResultType\": null\n"
+ " }";

try (PreparedStatement preparedStatement =
conn.prepareStatement("INSERT INTO events (globalSequence, data) VALUES (?, json(?)::VARIANT)")) {
preparedStatement.setLong(1, 100);
preparedStatement.setString(2, testData);
preparedStatement.execute();
}
try (ResultSet rs = stmt.executeQuery("SELECT globalSequence, data FROM events")) {
assertTrue(rs.next());
assertEquals(rs.getLong(1), 100L);
assertEquals(
rs.getString(2),
"{id=72869b95-ab13-4405-9371-546b6dcc443e, isSimulation=false, workOrderSchedules=[{workOrderId=e10c064f-6280-41f7-be75-b0075234754b, scheduledStart=2026-06-02T22:56:00, scheduledEnd=2026-06-03T05:01:00, scheduledResourceIds=[a49f8503-f2db-43aa-9d7c-711fc78d8dc9], batchId=null, batchSequence=null}], simulationResultType=null}");
assertFalse(rs.next());
}
}
}
}
Loading