Skip to content

Commit 7182da7

Browse files
Merge pull request #157 from oracle/update-1.3.0
Updates for Release 1.3.0
2 parents bc7e1a6 + ad2d023 commit 7182da7

16 files changed

+514
-235
lines changed

README.md

+87-112
Large diffs are not rendered by default.

pom.xml

+3-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
<groupId>com.oracle.database.r2dbc</groupId>
2828
<artifactId>oracle-r2dbc</artifactId>
29-
<version>1.2.0</version>
29+
<version>1.3.0</version>
3030
<name>oracle-r2dbc</name>
3131
<description>
3232
Oracle R2DBC Driver implementing version 1.0.0 of the R2DBC SPI for Oracle Database.
@@ -65,9 +65,9 @@
6565

6666
<properties>
6767
<java.version>11</java.version>
68-
<ojdbc.version>23.4.0.24.05</ojdbc.version>
68+
<ojdbc.version>23.6.0.24.10</ojdbc.version>
6969
<r2dbc.version>1.0.0.RELEASE</r2dbc.version>
70-
<reactor.version>3.5.11</reactor.version>
70+
<reactor.version>3.6.11</reactor.version>
7171
<reactive-streams.version>1.0.3</reactive-streams.version>
7272
<junit.version>5.9.1</junit.version>
7373
<spring-jdbc.version>5.3.19</spring-jdbc.version>

src/main/java/oracle/r2dbc/impl/OracleBatchImpl.java

+8-6
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@
5656
*/
5757
final class OracleBatchImpl implements Batch {
5858

59+
/** The OracleConnectionImpl that created this Batch */
60+
private final OracleConnectionImpl r2dbcConnection;
61+
5962
/** Adapts Oracle JDBC Driver APIs into Reactive Streams APIs */
6063
private final ReactiveJdbcAdapter adapter;
6164

@@ -83,12 +86,11 @@ final class OracleBatchImpl implements Batch {
8386
* @param jdbcConnection JDBC connection to an Oracle Database. Not null.
8487
* @param adapter Adapts JDBC calls into reactive streams. Not null.
8588
*/
86-
OracleBatchImpl(
87-
Duration timeout, Connection jdbcConnection, ReactiveJdbcAdapter adapter) {
89+
OracleBatchImpl(Duration timeout, OracleConnectionImpl r2dbcConnection) {
8890
this.timeout = timeout;
89-
this.jdbcConnection =
90-
requireNonNull(jdbcConnection, "jdbcConnection is null");
91-
this.adapter = requireNonNull(adapter, "adapter is null");
91+
this.r2dbcConnection = r2dbcConnection;
92+
this.jdbcConnection = r2dbcConnection.jdbcConnection();
93+
this.adapter = r2dbcConnection.adapter();
9294
}
9395

9496
/**
@@ -103,7 +105,7 @@ public Batch add(String sql) {
103105
requireOpenConnection(jdbcConnection);
104106
requireNonNull(sql, "sql is null");
105107
statements.add(
106-
new OracleStatementImpl(sql, timeout, jdbcConnection, adapter));
108+
new OracleStatementImpl(sql, timeout, r2dbcConnection));
107109
return this;
108110
}
109111

src/main/java/oracle/r2dbc/impl/OracleConnectionImpl.java

+77-5
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,17 @@
3838
import java.sql.SQLException;
3939
import java.sql.Savepoint;
4040
import java.time.Duration;
41+
import java.util.Set;
42+
import java.util.concurrent.ConcurrentHashMap;
4143

4244
import static io.r2dbc.spi.IsolationLevel.READ_COMMITTED;
4345
import static io.r2dbc.spi.IsolationLevel.SERIALIZABLE;
4446
import static io.r2dbc.spi.TransactionDefinition.ISOLATION_LEVEL;
4547
import static io.r2dbc.spi.TransactionDefinition.LOCK_WAIT_TIMEOUT;
4648
import static io.r2dbc.spi.TransactionDefinition.NAME;
4749
import static io.r2dbc.spi.TransactionDefinition.READ_ONLY;
48-
import static oracle.r2dbc.impl.OracleR2dbcExceptions.requireNonNull;
4950
import static oracle.r2dbc.impl.OracleR2dbcExceptions.fromJdbc;
51+
import static oracle.r2dbc.impl.OracleR2dbcExceptions.requireNonNull;
5052
import static oracle.r2dbc.impl.OracleR2dbcExceptions.requireOpenConnection;
5153
import static oracle.r2dbc.impl.OracleR2dbcExceptions.runJdbc;
5254
import static oracle.r2dbc.impl.OracleR2dbcExceptions.toR2dbcException;
@@ -126,6 +128,12 @@ final class OracleConnectionImpl implements Connection, Lifecycle {
126128
*/
127129
private TransactionDefinition currentTransaction = null;
128130

131+
/**
132+
* A set of tasks that must complete before the {@link #jdbcConnection} is
133+
* closed. The tasks are executed by subscribing to a Publisher.
134+
*/
135+
private final Set<Publisher<?>> closeTasks = ConcurrentHashMap.newKeySet();
136+
129137
/**
130138
* Constructs a new connection that uses the specified {@code adapter} to
131139
* perform database operations with the specified {@code jdbcConnection}.
@@ -369,7 +377,52 @@ else if (isReadOnly == null && name == null) {
369377
*/
370378
@Override
371379
public Publisher<Void> close() {
372-
return adapter.publishClose(jdbcConnection);
380+
381+
Publisher<Void> closeTasksPublisher = Mono.defer(() -> {
382+
Publisher<?>[] closeTasksArray = closeTasks.toArray(Publisher<?>[]::new);
383+
closeTasks.clear();
384+
385+
return Flux.concatDelayError(closeTasksArray).then();
386+
});
387+
388+
return Flux.concatDelayError(
389+
closeTasksPublisher,
390+
adapter.publishClose(jdbcConnection));
391+
}
392+
393+
/**
394+
* <p>
395+
* Adds a publisher that must be subscribed to and must terminate before
396+
* closing the JDBC connection. This method can be used to ensure that certain
397+
* tasks are completed before the {@link #jdbcConnection()} is closed and
398+
* becomes unusable.
399+
* </p><p>
400+
* The publisher returned by this method emits the same result as the
401+
* publisher passed into this method. However, when the returned publisher
402+
* terminates, it will also remove any reference to the publisher that was
403+
* passed into this method. <i>If the returned publisher is never subscribed
404+
* to, then the reference will not be cleared until the connection is
405+
* closed!</i> So, this method should only be used in cases where the user is
406+
* responsible for subscribing to the returned publisher, in the same way they
407+
* would be responsible for calling close() on an AutoCloseable. If the user
408+
* is not responsible for subscribing, then there is no reasonable way for
409+
* them to reduce the number object references that this method will create;
410+
* They would either need to close this connection, or subscribe to a
411+
* publisher when there is no obligation to do so.
412+
* </p>
413+
*
414+
* @param publisher Publisher that must be subscribed to before closing the
415+
* JDBC connection. Not null.
416+
*
417+
* @return A publisher that emits the same result as the publisher passed into
418+
* this method, and clears any reference to it when terminated. Not null.
419+
*/
420+
<T> Publisher<T> addCloseTask(Publisher<T> publisher) {
421+
closeTasks.add(publisher);
422+
423+
return Publishers.concatTerminal(
424+
publisher,
425+
Mono.fromRunnable(() -> closeTasks.remove(publisher)));
373426
}
374427

375428
/**
@@ -417,7 +470,7 @@ public Publisher<Void> commitTransaction() {
417470
@Override
418471
public Batch createBatch() {
419472
requireOpenConnection(jdbcConnection);
420-
return new OracleBatchImpl(statementTimeout, jdbcConnection, adapter);
473+
return new OracleBatchImpl(statementTimeout, this);
421474
}
422475

423476
/**
@@ -441,8 +494,7 @@ public Batch createBatch() {
441494
public Statement createStatement(String sql) {
442495
requireNonNull(sql, "sql is null");
443496
requireOpenConnection(jdbcConnection);
444-
return new OracleStatementImpl(
445-
sql, statementTimeout, jdbcConnection, adapter);
497+
return new OracleStatementImpl(sql, statementTimeout, this);
446498
}
447499

448500
/**
@@ -826,4 +878,24 @@ public Publisher<Void> preRelease() {
826878
});
827879
}
828880

881+
/**
882+
* Returns the JDBC connection that this R2DBC connection executes database
883+
* calls with.
884+
*
885+
* @return The JDBC connection which backs this R2DBC connection. Not null.
886+
*/
887+
java.sql.Connection jdbcConnection() {
888+
return jdbcConnection;
889+
}
890+
891+
/**
892+
* Returns the adapter that adapts the asynchronous API of the
893+
* {@link #jdbcConnection()} that backs this R2DBC connection.
894+
*
895+
* @return The JDBC connection that backs this R2DBC connection. Not null.
896+
*/
897+
ReactiveJdbcAdapter adapter() {
898+
return adapter;
899+
}
900+
829901
}

src/main/java/oracle/r2dbc/impl/OracleReadableImpl.java

+50-44
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import oracle.sql.INTERVALYM;
4747
import oracle.sql.TIMESTAMPLTZ;
4848
import oracle.sql.TIMESTAMPTZ;
49+
import org.reactivestreams.Publisher;
4950

5051
import java.math.BigDecimal;
5152
import java.nio.ByteBuffer;
@@ -93,6 +94,9 @@
9394
class OracleReadableImpl implements io.r2dbc.spi.Readable {
9495

9596

97+
/** The R2DBC connection that created this readable */
98+
private final OracleConnectionImpl r2dbcConnection;
99+
96100
/** The JDBC connection that created this readable */
97101
private final java.sql.Connection jdbcConnection;
98102

@@ -117,21 +121,21 @@ class OracleReadableImpl implements io.r2dbc.spi.Readable {
117121
* {@code jdbcReadable} and obtains metadata of the values from
118122
* {@code resultMetadata}.
119123
* </p>
120-
* @param jdbcConnection JDBC connection that created the
124+
* @param r2dbcConnection R2DBC connection that created the
121125
* {@code jdbcReadable}. Not null.
122126
* @param jdbcReadable Readable values from a JDBC Driver. Not null.
123127
* @param readablesMetadata Metadata of each value. Not null.
124128
* @param adapter Adapts JDBC calls into reactive streams. Not null.
125129
*/
126130
private OracleReadableImpl(
127-
java.sql.Connection jdbcConnection, DependentCounter dependentCounter,
128-
JdbcReadable jdbcReadable, ReadablesMetadata<?> readablesMetadata,
129-
ReactiveJdbcAdapter adapter) {
130-
this.jdbcConnection = jdbcConnection;
131+
OracleConnectionImpl r2dbcConnection, DependentCounter dependentCounter,
132+
JdbcReadable jdbcReadable, ReadablesMetadata<?> readablesMetadata) {
133+
this.r2dbcConnection = r2dbcConnection;
134+
this.jdbcConnection = r2dbcConnection.jdbcConnection();
131135
this.dependentCounter = dependentCounter;
132136
this.jdbcReadable = jdbcReadable;
133137
this.readablesMetadata = readablesMetadata;
134-
this.adapter = adapter;
138+
this.adapter = r2dbcConnection.adapter();
135139
}
136140

137141
/**
@@ -151,11 +155,10 @@ private OracleReadableImpl(
151155
* {@code metadata}. Not null.
152156
*/
153157
static Row createRow(
154-
java.sql.Connection jdbcConnection, DependentCounter dependentCounter,
155-
JdbcReadable jdbcReadable, RowMetadataImpl metadata,
156-
ReactiveJdbcAdapter adapter) {
158+
OracleConnectionImpl r2dbcConnection, DependentCounter dependentCounter,
159+
JdbcReadable jdbcReadable, RowMetadataImpl metadata) {
157160
return new RowImpl(
158-
jdbcConnection, dependentCounter, jdbcReadable, metadata, adapter);
161+
r2dbcConnection, dependentCounter, jdbcReadable, metadata);
159162
}
160163

161164
/**
@@ -164,7 +167,7 @@ static Row createRow(
164167
* the provided {@code jdbcReadable} and {@code rowMetadata}. The metadata
165168
* object is used to determine the default type mapping of column values.
166169
* </p>
167-
* @param jdbcConnection JDBC connection that created the
170+
* @param r2dbcConnection R2DBC connection that created the
168171
* {@code jdbcReadable}. Not null.
169172
* @param dependentCounter Counter that is increased for each dependent
170173
* {@code Result} created by the returned {@code OutParameters}
@@ -175,11 +178,10 @@ static Row createRow(
175178
* {@code metadata}. Not null.
176179
*/
177180
static OutParameters createOutParameters(
178-
java.sql.Connection jdbcConnection, DependentCounter dependentCounter,
179-
JdbcReadable jdbcReadable, OutParametersMetadataImpl metadata,
180-
ReactiveJdbcAdapter adapter) {
181+
OracleConnectionImpl r2dbcConnection, DependentCounter dependentCounter,
182+
JdbcReadable jdbcReadable, OutParametersMetadataImpl metadata) {
181183
return new OutParametersImpl(
182-
jdbcConnection, dependentCounter, jdbcReadable, metadata, adapter);
184+
r2dbcConnection, dependentCounter, jdbcReadable, metadata);
183185
}
184186

185187
/**
@@ -335,11 +337,16 @@ private ByteBuffer getByteBuffer(int index) {
335337
*/
336338
private Blob getBlob(int index) {
337339
java.sql.Blob jdbcBlob = jdbcReadable.getObject(index, java.sql.Blob.class);
338-
return jdbcBlob == null
339-
? null
340-
: OracleLargeObjects.createBlob(
341-
adapter.publishBlobRead(jdbcBlob),
342-
adapter.publishBlobFree(jdbcBlob));
340+
341+
if (jdbcBlob == null)
342+
return null;
343+
344+
Publisher<Void> freePublisher =
345+
r2dbcConnection.addCloseTask(adapter.publishBlobFree(jdbcBlob));
346+
347+
return OracleLargeObjects.createBlob(
348+
adapter.publishBlobRead(jdbcBlob),
349+
freePublisher);
343350
}
344351

345352
/**
@@ -367,11 +374,15 @@ private Clob getClob(int index) {
367374
jdbcClob = jdbcReadable.getObject(index, java.sql.Clob.class);
368375
}
369376

370-
return jdbcClob == null
371-
? null
372-
: OracleLargeObjects.createClob(
373-
adapter.publishClobRead(jdbcClob),
374-
adapter.publishClobFree(jdbcClob));
377+
if (jdbcClob == null)
378+
return null;
379+
380+
Publisher<Void> freePublisher =
381+
r2dbcConnection.addCloseTask(adapter.publishClobFree(jdbcClob));
382+
383+
return OracleLargeObjects.createClob(
384+
adapter.publishClobRead(jdbcClob),
385+
freePublisher);
375386
}
376387

377388
/**
@@ -685,11 +696,10 @@ private OracleR2dbcObjectImpl getOracleR2dbcObject(int index) {
685696
return null;
686697

687698
return new OracleR2dbcObjectImpl(
688-
jdbcConnection,
699+
r2dbcConnection,
689700
dependentCounter,
690701
new StructJdbcReadable(oracleStruct),
691-
ReadablesMetadata.createAttributeMetadata(oracleStruct),
692-
adapter);
702+
ReadablesMetadata.createAttributeMetadata(oracleStruct));
693703
}
694704

695705
/**
@@ -956,7 +966,7 @@ private Result getResult(int index) {
956966

957967
dependentCounter.increment();
958968
return OracleResultImpl.createQueryResult(
959-
dependentCounter, resultSet, adapter);
969+
r2dbcConnection, dependentCounter, resultSet);
960970
}
961971

962972
/**
@@ -994,17 +1004,16 @@ private static final class RowImpl
9941004
* {@code jdbcReadable}, and uses the specified {@code rowMetadata} to
9951005
* determine the default type mapping of column values.
9961006
* </p>
997-
* @param jdbcConnection JDBC connection that created the
1007+
* @param r2dbcConnection R2DBC connection that created the
9981008
* {@code jdbcReadable}. Not null.
9991009
* @param jdbcReadable Row data from the Oracle JDBC Driver. Not null.
10001010
* @param metadata Meta-data for the specified row. Not null.
10011011
* @param adapter Adapts JDBC calls into reactive streams. Not null.
10021012
*/
10031013
private RowImpl(
1004-
java.sql.Connection jdbcConnection, DependentCounter dependentCounter,
1005-
JdbcReadable jdbcReadable, RowMetadataImpl metadata,
1006-
ReactiveJdbcAdapter adapter) {
1007-
super(jdbcConnection, dependentCounter, jdbcReadable, metadata, adapter);
1014+
OracleConnectionImpl r2dbcConnection, DependentCounter dependentCounter,
1015+
JdbcReadable jdbcReadable, RowMetadataImpl metadata) {
1016+
super(r2dbcConnection, dependentCounter, jdbcReadable, metadata);
10081017
this.metadata = metadata;
10091018
}
10101019

@@ -1044,10 +1053,9 @@ private static final class OutParametersImpl
10441053
* @param adapter Adapts JDBC calls into reactive streams. Not null.
10451054
*/
10461055
private OutParametersImpl(
1047-
java.sql.Connection jdbcConnection, DependentCounter dependentCounter,
1048-
JdbcReadable jdbcReadable, OutParametersMetadataImpl metadata,
1049-
ReactiveJdbcAdapter adapter) {
1050-
super(jdbcConnection, dependentCounter, jdbcReadable, metadata, adapter);
1056+
OracleConnectionImpl r2dbcConnection, DependentCounter dependentCounter,
1057+
JdbcReadable jdbcReadable, OutParametersMetadataImpl metadata) {
1058+
super(r2dbcConnection, dependentCounter, jdbcReadable, metadata);
10511059
this.metadata = metadata;
10521060
}
10531061

@@ -1068,20 +1076,18 @@ private final class OracleR2dbcObjectImpl
10681076
* {@code jdbcReadable} and obtains metadata of the values from
10691077
* {@code outParametersMetaData}.
10701078
* </p>
1071-
* @param jdbcConnection JDBC connection that created the
1079+
* @param r2dbcConnection R2DBC connection that created the
10721080
* {@code jdbcReadable}. Not null.
10731081
* @param structJdbcReadable Readable values from a JDBC Driver. Not null.
10741082
* @param metadata Metadata of each value. Not null.
10751083
* @param adapter Adapts JDBC calls into reactive streams. Not null.
10761084
*/
10771085
private OracleR2dbcObjectImpl(
1078-
java.sql.Connection jdbcConnection,
1086+
OracleConnectionImpl r2dbcConnection,
10791087
DependentCounter dependentCounter,
10801088
StructJdbcReadable structJdbcReadable,
1081-
OracleR2dbcObjectMetadataImpl metadata,
1082-
ReactiveJdbcAdapter adapter) {
1083-
super(
1084-
jdbcConnection, dependentCounter, structJdbcReadable, metadata, adapter);
1089+
OracleR2dbcObjectMetadataImpl metadata) {
1090+
super(r2dbcConnection, dependentCounter, structJdbcReadable, metadata);
10851091
this.metadata = metadata;
10861092
}
10871093

0 commit comments

Comments
 (0)