4141import java .util .Queue ;
4242import java .util .concurrent .atomic .AtomicBoolean ;
4343import java .util .function .BiFunction ;
44+ import java .util .function .Function ;
4445
4546import static oracle .r2dbc .impl .OracleR2dbcExceptions .getOrHandleSQLException ;
4647import static oracle .r2dbc .impl .OracleR2dbcExceptions .requireNonNull ;
@@ -546,8 +547,8 @@ private Publisher<Result> createResultPublisher(
546547
547548 /**
548549 * <p>
549- * Executes a JDBC statement with a single, non-batched, set of parameters.
550- * If the execution returns a {@link java.sql.ResultSet} then the
550+ * Executes a JDBC statement with a single, non-batched, set of {@code
551+ * bindValues}. If the execution results in a {@link java.sql.ResultSet} then the
551552 * {@code jdbcStatement} is closed after the {@code ResultSet} is fully
552553 * consumed by {@link Result#map(BiFunction)}. Otherwise, if the execution
553554 * only produces an update count, then the {@code jdbcStatement} is closed
@@ -569,7 +570,6 @@ private Publisher<Result> executeSingle(
569570 return Mono .from (adapter .publishSQLExecution (jdbcStatement ))
570571 .map (isResultSet -> {
571572 if (isResultSet ) {
572- runOrHandleSQLException (jdbcStatement ::closeOnCompletion );
573573 return OracleResultImpl .createQueryResult (
574574 adapter , getOrHandleSQLException (jdbcStatement ::getResultSet ));
575575 }
@@ -614,22 +614,27 @@ private Publisher<Result> executeBatch(
614614
615615 // Execute the batch. The execution won't return a ResultSet, so the JDBC
616616 // statement is closed immediately after the execution completes.
617- runOrHandleSQLException (jdbcStatement ::closeOnCompletion );
618617 return Flux .from (adapter .publishBatchUpdate (jdbcStatement ))
619618 .map (updateCount ->
620- OracleResultImpl .createUpdateCountResult (Math .toIntExact (updateCount )));
619+ OracleResultImpl .createUpdateCountResult (Math .toIntExact (updateCount )))
620+ .doFinally (signalType -> runOrHandleSQLException (jdbcStatement ::close ));
621621 }
622622
623623 /**
624624 * <p>
625- * Executes a key generating {@code jdbcStatement} for each set
626- * of bind values in a {@code batch}. The {@code jdbcStatement} is closed
627- * after all executions have completed. If any execution results in an
628- * error, subsequent executions are skipped.
625+ * Executes a JDBC statement with a single, non-batched, set of {@code
626+ * bindValues}. If the execution results in a {@link java.sql.ResultSet} then
627+ * the {@code jdbcStatement} is closed after the {@code ResultSet} is fully
628+ * consumed by {@link Result#map(BiFunction)}. If the execution results in
629+ * an update count and/or values generated by DML, then the {@code
630+ * jdbcStatement} is closed after the returned {@code Publisher} emits a
631+ * {@code Result} with all generated values cached, such that
632+ * {@link Result#map(BiFunction)} may be called after the database connection
633+ * has been closed.
629634 * </p><p>
630- * The returned {@code Publisher} emits a {@code Result} with an update
631- * count and generated values for each execution of the {@code
632- * jdbcStatement} .
635+ * The returned publisher initiates SQL execution <i>the first time</i> a
636+ * subscriber subscribes, before the subscriber emits a {@code request}
637+ * signal .
633638 * </p>
634639 *
635640 * @implNote The 21c Oracle JDBC Driver does not support batch DML when
@@ -638,25 +643,23 @@ private Publisher<Result> executeBatch(
638643 *
639644 * @param jdbcStatement A JDBC statement
640645 * @param bindValues A set of bind values
641- * @return A publisher that emits the {@code Results } of executing the
642- * JDBC statement for each set of bind values in the {@code batch}
646+ * @return A publisher that emits the {@code Result } of executing the
647+ * JDBC statement.
643648 */
644649 private Publisher <Result > executeGeneratingValues (
645650 PreparedStatement jdbcStatement , Object [] bindValues ) {
646651
647652 setJdbcBindValues (bindValues , jdbcStatement );
648653 return Mono .from (adapter .publishSQLExecution (jdbcStatement ))
649- .flatMap (isResultSet -> {
650- runOrHandleSQLException (jdbcStatement ::closeOnCompletion );
651- return isResultSet
654+ .flatMap (isResultSet ->
655+ isResultSet
652656 ? Mono .just (OracleResultImpl .createQueryResult (
653657 adapter ,
654658 getOrHandleSQLException (jdbcStatement ::getResultSet )))
655659 : Mono .from (OracleResultImpl .createGeneratedValuesResult (
656660 adapter ,
657661 getOrHandleSQLException (jdbcStatement ::getUpdateCount ),
658- getOrHandleSQLException (jdbcStatement ::getGeneratedKeys )));
659- });
662+ getOrHandleSQLException (jdbcStatement ::getGeneratedKeys ))));
660663 }
661664
662665 /**
0 commit comments