Skip to content

Commit cbfbe2c

Browse files
committed
Appender UNION support (1.4)
This is a backport of the PR #372 to `v1.4-andium` stable branch. This PR adds support for appending data to `UNION` columns. The tag (field name) of the union must be specified in `beginUnion()` call before appending the actual value. Nested unions (or structs inside unions) are not supported. Example: ```sql CREATE TABLE tab1 (col1 INTEGER, col2 UNION(u1 INTEGER, u2 VARCHAR)) ``` ```java DuckDBAppender appender = conn.createAppender("tab1"); // append row with INTEGER value in UNION appender .beginRow() .append(1) .beginUnion("u1") .append(42) .endUnion() .endRow(); // append row with VARCHAR value in UNION appender .beginRow() .append(2) .beginUnion("u2") .append("foo") .endUnion() .endRow(); ``` Testing: existing test is extended to cover `UNION`s.
1 parent fb4a4a1 commit cbfbe2c

File tree

10 files changed

+362
-40
lines changed

10 files changed

+362
-40
lines changed

duckdb_java.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ Java_org_duckdb_DuckDBBindings_duckdb_1create_1list_1type
5858
Java_org_duckdb_DuckDBBindings_duckdb_1create_1array_1type
5959
Java_org_duckdb_DuckDBBindings_duckdb_1create_1struct_1type
6060
Java_org_duckdb_DuckDBBindings_duckdb_1struct_1type_1child_1count
61+
Java_org_duckdb_DuckDBBindings_duckdb_1struct_1type_1child_1name
6162
Java_org_duckdb_DuckDBBindings_duckdb_1array_1type_1array_1size
6263
Java_org_duckdb_DuckDBBindings_duckdb_1destroy_1logical_1type
6364
Java_org_duckdb_DuckDBBindings_duckdb_1create_1vector

duckdb_java.exp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ _Java_org_duckdb_DuckDBBindings_duckdb_1create_1list_1type
5555
_Java_org_duckdb_DuckDBBindings_duckdb_1create_1array_1type
5656
_Java_org_duckdb_DuckDBBindings_duckdb_1create_1struct_1type
5757
_Java_org_duckdb_DuckDBBindings_duckdb_1struct_1type_1child_1count
58+
_Java_org_duckdb_DuckDBBindings_duckdb_1struct_1type_1child_1name
5859
_Java_org_duckdb_DuckDBBindings_duckdb_1array_1type_1array_1size
5960
_Java_org_duckdb_DuckDBBindings_duckdb_1destroy_1logical_1type
6061
_Java_org_duckdb_DuckDBBindings_duckdb_1create_1vector

duckdb_java.map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ DUCKDB_JAVA {
5757
Java_org_duckdb_DuckDBBindings_duckdb_1create_1array_1type;
5858
Java_org_duckdb_DuckDBBindings_duckdb_1create_1struct_1type;
5959
Java_org_duckdb_DuckDBBindings_duckdb_1struct_1type_1child_1count;
60+
Java_org_duckdb_DuckDBBindings_duckdb_1struct_1type_1child_1name;
6061
Java_org_duckdb_DuckDBBindings_duckdb_1array_1type_1array_1size;
6162
Java_org_duckdb_DuckDBBindings_duckdb_1destroy_1logical_1type;
6263
Java_org_duckdb_DuckDBBindings_duckdb_1create_1vector;

src/jni/bindings_logical_type.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "refs.hpp"
33
#include "util.hpp"
44

5+
#include <cstring>
56
#include <vector>
67

78
duckdb_logical_type logical_type_buf_to_logical_type(JNIEnv *env, jobject logical_type_buf) {
@@ -209,8 +210,9 @@ JNIEXPORT jobject JNICALL Java_org_duckdb_DuckDBBindings_duckdb_1create_1struct_
209210
if (env->ExceptionCheck()) {
210211
return nullptr;
211212
}
212-
names_cstr_vec.emplace_back(str.c_str());
213213
names_vec.emplace_back(std::move(str));
214+
std::string &str_ref = names_vec.back();
215+
names_cstr_vec.emplace_back(str_ref.c_str());
214216
}
215217

216218
duckdb_logical_type struct_type =
@@ -237,6 +239,40 @@ JNIEXPORT jlong JNICALL Java_org_duckdb_DuckDBBindings_duckdb_1struct_1type_1chi
237239
return static_cast<jlong>(count);
238240
}
239241

242+
/*
243+
* Class: org_duckdb_DuckDBBindings
244+
* Method: duckdb_struct_type_child_name
245+
* Signature: (Ljava/nio/ByteBuffer;J)[B
246+
*/
247+
JNIEXPORT jbyteArray JNICALL Java_org_duckdb_DuckDBBindings_duckdb_1struct_1type_1child_1name(JNIEnv *env, jclass,
248+
jobject logical_type,
249+
jlong index) {
250+
251+
duckdb_logical_type lt = logical_type_buf_to_logical_type(env, logical_type);
252+
if (env->ExceptionCheck()) {
253+
return nullptr;
254+
}
255+
idx_t index_idx = jlong_to_idx(env, index);
256+
if (env->ExceptionCheck()) {
257+
return nullptr;
258+
}
259+
260+
idx_t count = duckdb_struct_type_child_count(lt);
261+
if (index_idx >= count) {
262+
env->ThrowNew(J_SQLException, "Invalid struct field index specified");
263+
return nullptr;
264+
}
265+
266+
auto name_ptr = varchar_ptr(duckdb_struct_type_child_name(lt, index_idx), varchar_deleter);
267+
if (name_ptr.get() == nullptr) {
268+
return nullptr;
269+
}
270+
271+
idx_t len = static_cast<idx_t>(std::strlen(name_ptr.get()));
272+
273+
return make_jbyteArray(env, name_ptr.get(), len);
274+
}
275+
240276
/*
241277
* Class: org_duckdb_DuckDBBindings
242278
* Method: duckdb_array_type_array_size

src/jni/util.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,14 @@ extern "C" {
99
#include <memory>
1010
#include <string>
1111

12-
using jstring_ptr = std::unique_ptr<const char, std::function<void(const char *)>>;
13-
1412
using jbyteArray_ptr = std::unique_ptr<char, std::function<void(char *)>>;
1513

14+
using varchar_ptr = std::unique_ptr<char, void (*)(char *)>;
15+
16+
inline void varchar_deleter(char *val) {
17+
duckdb_free(val);
18+
}
19+
1620
void check_java_exception_and_rethrow(JNIEnv *env);
1721

1822
std::string jbyteArray_to_string(JNIEnv *env, jbyteArray ba_j);

0 commit comments

Comments
 (0)