Skip to content

Commit a30edb6

Browse files
committed
Expose query progress on statement
This change exposes the `duckdb_query_progress` native call as `getQueryProgress()` method on the statement. Similar to the `Stament#cancel()` this new method also expected to be called when `execute()` is running and also works on the connection (not on the statement itself). Note, the local option `SET enable_progress_bar = true` needs to be set to be able to fetch actual progress data. Testing: new test is added that checks that `getQueryProgress()` returns valid values.
1 parent f647a9f commit a30edb6

15 files changed

+178
-0
lines changed

duckdb_java.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1interrupt
3838
Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1prepare
3939
Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1prepared_1statement_1meta
4040
Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1query_1result_1meta
41+
Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1query_1progress
4142
Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1release
4243
Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1set_1auto_1commit
4344
Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1set_1catalog

duckdb_java.exp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ _Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1interrupt
3535
_Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1prepare
3636
_Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1prepared_1statement_1meta
3737
_Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1query_1result_1meta
38+
_Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1query_1progress
3839
_Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1release
3940
_Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1set_1auto_1commit
4041
_Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1set_1catalog

duckdb_java.map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ DUCKDB_JAVA {
3737
Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1prepare;
3838
Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1prepared_1statement_1meta;
3939
Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1query_1result_1meta;
40+
Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1query_1progress;
4041
Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1release;
4142
Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1set_1auto_1commit;
4243
Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1set_1catalog;

src/jni/duckdb_java.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
extern "C" {
2+
#include "duckdb.h"
3+
}
14
#include "config.hpp"
25
#include "duckdb.hpp"
36
#include "duckdb/catalog/catalog_search_path.hpp"
@@ -149,6 +152,16 @@ void _duckdb_jdbc_interrupt(JNIEnv *env, jclass, jobject conn_ref_buf) {
149152
conn_ref->Interrupt();
150153
}
151154

155+
jobject _duckdb_jdbc_query_progress(JNIEnv *env, jclass, jobject conn_ref_buf) {
156+
auto conn_ref = get_connection(env, conn_ref_buf);
157+
if (!conn_ref) {
158+
return nullptr;
159+
}
160+
duckdb_query_progress_type qpc = duckdb_query_progress(reinterpret_cast<duckdb_connection>(conn_ref));
161+
return env->NewObject(J_QueryProgress, J_QueryProgress_init, static_cast<jdouble>(qpc.percentage),
162+
uint64_to_jlong(qpc.rows_processed), uint64_to_jlong(qpc.total_rows_to_process));
163+
}
164+
152165
void _duckdb_jdbc_disconnect(JNIEnv *env, jclass, jobject conn_ref_buf) {
153166
auto conn_ref = (ConnectionHolder *)env->GetDirectBufferAddress(conn_ref_buf);
154167
if (conn_ref) {

src/jni/functions.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,16 @@ JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1interrupt(JNIE
257257
}
258258
}
259259

260+
JNIEXPORT jobject JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1query_1progress(JNIEnv * env, jclass param0, jobject param1) {
261+
try {
262+
return _duckdb_jdbc_query_progress(env, param0, param1);
263+
} catch (const std::exception &e) {
264+
duckdb::ErrorData error(e);
265+
ThrowJNI(env, error.Message().c_str());
266+
return nullptr;
267+
}
268+
}
269+
260270
JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1close(JNIEnv * env, jclass param0, jobject param1) {
261271
try {
262272
return _duckdb_jdbc_appender_close(env, param0, param1);

src/jni/functions.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ void _duckdb_jdbc_interrupt(JNIEnv * env, jclass param0, jobject param1);
105105

106106
JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1interrupt(JNIEnv * env, jclass param0, jobject param1);
107107

108+
jobject _duckdb_jdbc_query_progress(JNIEnv * env, jclass param0, jobject param1);
109+
110+
JNIEXPORT jobject JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1query_1progress(JNIEnv * env, jclass param0, jobject param1);
111+
108112
void _duckdb_jdbc_appender_close(JNIEnv * env, jclass param0, jobject param1);
109113

110114
JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1close(JNIEnv * env, jclass param0, jobject param1);

src/jni/refs.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ jobject J_ProfilerPrintFormat_NO_OUTPUT;
111111
jobject J_ProfilerPrintFormat_HTML;
112112
jobject J_ProfilerPrintFormat_GRAPHVIZ;
113113

114+
jclass J_QueryProgress;
115+
jmethodID J_QueryProgress_init;
116+
114117
static std::vector<jobject> global_refs;
115118

116119
template <typename T>
@@ -280,6 +283,9 @@ void create_refs(JNIEnv *env) {
280283
make_static_object_field_ref(env, J_ProfilerPrintFormat, "HTML", "Lorg/duckdb/ProfilerPrintFormat;");
281284
J_ProfilerPrintFormat_GRAPHVIZ =
282285
make_static_object_field_ref(env, J_ProfilerPrintFormat, "GRAPHVIZ", "Lorg/duckdb/ProfilerPrintFormat;");
286+
287+
J_QueryProgress = make_class_ref(env, "org/duckdb/QueryProgress");
288+
J_QueryProgress_init = get_method_id(env, J_QueryProgress, "<init>", "(DJJ)V");
283289
}
284290

285291
void delete_global_refs(JNIEnv *env) noexcept {

src/jni/refs.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ extern jobject J_ProfilerPrintFormat_NO_OUTPUT;
108108
extern jobject J_ProfilerPrintFormat_HTML;
109109
extern jobject J_ProfilerPrintFormat_GRAPHVIZ;
110110

111+
extern jclass J_QueryProgress;
112+
extern jmethodID J_QueryProgress_init;
113+
111114
void create_refs(JNIEnv *env);
112115

113116
void delete_global_refs(JNIEnv *env) noexcept;

src/jni/util.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
#include "refs.hpp"
44

5+
#include <cstdint>
6+
#include <limits>
7+
58
void check_java_exception_and_rethrow(JNIEnv *env) {
69
if (env->ExceptionCheck()) {
710
jthrowable exc = env->ExceptionOccurred();
@@ -42,3 +45,10 @@ jobject decode_charbuffer_to_jstring(JNIEnv *env, const char *d_str, idx_t d_str
4245
auto j_str = env->CallObjectMethod(j_cb, J_CharBuffer_toString);
4346
return j_str;
4447
}
48+
49+
jlong uint64_to_jlong(uint64_t value) {
50+
if (value <= std::numeric_limits<int64_t>::max()) {
51+
return static_cast<jlong>(value);
52+
}
53+
return static_cast<jlong>(std::numeric_limits<int64_t>::max());
54+
}

src/jni/util.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ std::string byte_array_to_string(JNIEnv *env, jbyteArray ba_j);
1212
std::string jstring_to_string(JNIEnv *env, jstring string_j);
1313

1414
jobject decode_charbuffer_to_jstring(JNIEnv *env, const char *d_str, idx_t d_str_len);
15+
16+
jlong uint64_to_jlong(uint64_t value);

0 commit comments

Comments
 (0)