@@ -212,24 +212,54 @@ jobject _duckdb_jdbc_prepare(JNIEnv *env, jclass, jobject conn_ref_buf, jbyteArr
212212 }
213213 }
214214
215- auto stmt_ref = new StatementHolder ();
215+ auto stmt_ref = make_uniq< StatementHolder> ();
216216 stmt_ref->stmt = conn_ref->Prepare (std::move (statements.back ()));
217217 if (stmt_ref->stmt ->HasError ()) {
218218 string error_msg = string (stmt_ref->stmt ->GetError ());
219219 stmt_ref->stmt = nullptr ;
220-
221- // No success, so it must be deleted
222- delete stmt_ref;
223220 ThrowJNI (env, error_msg.c_str ());
221+ return nullptr ;
222+ }
223+ return env->NewDirectByteBuffer (stmt_ref.release (), 0 );
224+ }
224225
225- // Just return control flow back to JVM, as an Exception is pending anyway
226+ jobject _duckdb_jdbc_pending_query (JNIEnv *env, jclass, jobject conn_ref_buf, jbyteArray query_j) {
227+ auto conn_ref = get_connection (env, conn_ref_buf);
228+ if (!conn_ref) {
226229 return nullptr ;
227230 }
228- return env->NewDirectByteBuffer (stmt_ref, 0 );
231+
232+ auto query = jbyteArray_to_string (env, query_j);
233+
234+ auto statements = conn_ref->ExtractStatements (query.c_str ());
235+ if (statements.empty ()) {
236+ throw InvalidInputException (" No statements to execute." );
237+ }
238+
239+ // if there are multiple statements, we directly execute the statements besides the last one
240+ // we only return the result of the last statement to the user, unless one of the previous statements fails
241+ for (idx_t i = 0 ; i + 1 < statements.size (); i++) {
242+ auto res = conn_ref->Query (std::move (statements[i]));
243+ if (res->HasError ()) {
244+ res->ThrowError ();
245+ }
246+ }
247+
248+ Value result;
249+ bool stream_results =
250+ conn_ref->context ->TryGetCurrentSetting (" jdbc_stream_results" , result) ? result.GetValue <bool >() : false ;
251+ QueryParameters query_parameters;
252+ query_parameters.output_type =
253+ stream_results ? QueryResultOutputType::ALLOW_STREAMING : QueryResultOutputType::FORCE_MATERIALIZED;
254+
255+ auto pending_ref = make_uniq<PendingHolder>();
256+ pending_ref->pending = conn_ref->PendingQuery (std::move (statements.back ()), query_parameters);
257+
258+ return env->NewDirectByteBuffer (pending_ref.release (), 0 );
229259}
230260
231261jobject _duckdb_jdbc_execute (JNIEnv *env, jclass, jobject stmt_ref_buf, jobjectArray params) {
232- auto stmt_ref = ( StatementHolder *) env->GetDirectBufferAddress (stmt_ref_buf);
262+ auto stmt_ref = reinterpret_cast < StatementHolder *>( env->GetDirectBufferAddress (stmt_ref_buf) );
233263 if (!stmt_ref) {
234264 throw InvalidInputException (" Invalid statement" );
235265 }
@@ -269,21 +299,50 @@ jobject _duckdb_jdbc_execute(JNIEnv *env, jclass, jobject stmt_ref_buf, jobjectA
269299 return env->NewDirectByteBuffer (res_ref.release (), 0 );
270300}
271301
302+ jobject _duckdb_jdbc_execute_pending (JNIEnv *env, jclass, jobject pending_ref_buf) {
303+ auto pending_ref = reinterpret_cast <PendingHolder *>(env->GetDirectBufferAddress (pending_ref_buf));
304+ if (!pending_ref) {
305+ throw InvalidInputException (" Invalid pending query" );
306+ }
307+
308+ auto res_ref = make_uniq<ResultHolder>();
309+ res_ref->res = pending_ref->pending ->Execute ();
310+ if (res_ref->res ->HasError ()) {
311+ std::string error_msg = std::string (res_ref->res ->GetError ());
312+ duckdb::ExceptionType error_type = res_ref->res ->GetErrorType ();
313+ res_ref->res = nullptr ;
314+ jclass exc_type = duckdb::ExceptionType::INTERRUPT == error_type ? J_SQLTimeoutException : J_SQLException;
315+ env->ThrowNew (exc_type, error_msg.c_str ());
316+ return nullptr ;
317+ }
318+ return env->NewDirectByteBuffer (res_ref.release (), 0 );
319+ }
320+
272321void _duckdb_jdbc_release (JNIEnv *env, jclass, jobject stmt_ref_buf) {
273322 if (nullptr == stmt_ref_buf) {
274323 return ;
275324 }
276- auto stmt_ref = ( StatementHolder *) env->GetDirectBufferAddress (stmt_ref_buf);
325+ auto stmt_ref = reinterpret_cast < StatementHolder *>( env->GetDirectBufferAddress (stmt_ref_buf) );
277326 if (stmt_ref) {
278327 delete stmt_ref;
279328 }
280329}
281330
331+ void _duckdb_jdbc_release_pending (JNIEnv *env, jclass, jobject pending_ref_buf) {
332+ if (nullptr == pending_ref_buf) {
333+ return ;
334+ }
335+ auto pending_ref = reinterpret_cast <PendingHolder *>(env->GetDirectBufferAddress (pending_ref_buf));
336+ if (pending_ref) {
337+ delete pending_ref;
338+ }
339+ }
340+
282341void _duckdb_jdbc_free_result (JNIEnv *env, jclass, jobject res_ref_buf) {
283342 if (nullptr == res_ref_buf) {
284343 return ;
285344 }
286- auto res_ref = ( ResultHolder *) env->GetDirectBufferAddress (res_ref_buf);
345+ auto res_ref = reinterpret_cast < ResultHolder *>( env->GetDirectBufferAddress (res_ref_buf) );
287346 if (res_ref) {
288347 delete res_ref;
289348 }
0 commit comments