Skip to content

Commit 4acbe76

Browse files
Merge pull request #67 from oracle/66-vsession-options
66 vsession options
2 parents 260a09a + 90f758b commit 4acbe76

File tree

4 files changed

+130
-8
lines changed

4 files changed

+130
-8
lines changed

.github/workflows/startup/01_createUser.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@
3434
-- tables, and to query some V$ views:
3535
-- v$open_cursor (to verify if cursors are being closed).
3636
-- v$transaction (to verify if TransactionDefinitions are applied).
37+
-- v$session (to verify if VSESSION_* Options are applied).
3738
ALTER SESSION SET CONTAINER=xepdb1;
3839
CREATE ROLE r2dbc_test_user;
3940
GRANT SELECT ON v_$open_cursor TO r2dbc_test_user;
4041
GRANT SELECT ON v_$transaction TO r2dbc_test_user;
42+
GRANT SELECT ON v_$session TO r2dbc_test_user;
4143

4244
CREATE USER test IDENTIFIED BY test;
4345
GRANT connect, resource, unlimited tablespace, r2dbc_test_user TO test;

src/main/java/oracle/r2dbc/OracleR2dbcOptions.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,4 +223,40 @@ private OracleR2dbcOptions() {}
223223
*/
224224
public static final Option<CharSequence> ENABLE_QUERY_RESULT_CACHE =
225225
Option.valueOf(OracleConnection.CONNECTION_PROPERTY_ENABLE_QUERY_RESULT_CACHE);
226+
227+
/**
228+
* Configures the Oracle JDBC Connection used by Oracle R2DBC as specified by:
229+
* {@link OracleConnection#CONNECTION_PROPERTY_THIN_VSESSION_TERMINAL}
230+
*/
231+
public static final Option<CharSequence> VSESSION_TERMINAL =
232+
Option.valueOf(OracleConnection.CONNECTION_PROPERTY_THIN_VSESSION_TERMINAL);
233+
234+
/**
235+
* Configures the Oracle JDBC Connection used by Oracle R2DBC as specified by:
236+
* {@link OracleConnection#CONNECTION_PROPERTY_THIN_VSESSION_MACHINE}
237+
*/
238+
public static final Option<CharSequence> VSESSION_MACHINE =
239+
Option.valueOf(OracleConnection.CONNECTION_PROPERTY_THIN_VSESSION_MACHINE);
240+
241+
/**
242+
* Configures the Oracle JDBC Connection used by Oracle R2DBC as specified by:
243+
* {@link OracleConnection#CONNECTION_PROPERTY_THIN_VSESSION_OSUSER}
244+
*/
245+
public static final Option<CharSequence> VSESSION_OSUSER =
246+
Option.valueOf(OracleConnection.CONNECTION_PROPERTY_THIN_VSESSION_OSUSER);
247+
248+
/**
249+
* Configures the Oracle JDBC Connection used by Oracle R2DBC as specified by:
250+
* {@link OracleConnection#CONNECTION_PROPERTY_THIN_VSESSION_PROGRAM}
251+
*/
252+
public static final Option<CharSequence> VSESSION_PROGRAM =
253+
Option.valueOf(OracleConnection.CONNECTION_PROPERTY_THIN_VSESSION_PROGRAM);
254+
255+
/**
256+
* Configures the Oracle JDBC Connection used by Oracle R2DBC as specified by:
257+
* {@link OracleConnection#CONNECTION_PROPERTY_THIN_VSESSION_PROCESS}
258+
*/
259+
public static final Option<CharSequence> VSESSION_PROCESS =
260+
Option.valueOf(OracleConnection.CONNECTION_PROPERTY_THIN_VSESSION_PROCESS);
261+
226262
}

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

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,17 +126,20 @@
126126
final class OracleReactiveJdbcAdapter implements ReactiveJdbcAdapter {
127127

128128
/**
129+
* <p>
129130
* The set of JDBC connection properties that this adapter supports. Each
130131
* property in this set is represented as an {@link Option} having the name
131132
* of the supported JDBC connection property. When a property is configured
132133
* with a sensitive value, such as a password, it is represented in this
133134
* set as a {@linkplain Option#sensitiveValueOf(String) sensitive Option}.
135+
* </p><p>
134136
* If a new Option is added to this set, then it <i>must</i> be documented
135137
* in the javadoc of {@link #createDataSource(ConnectionFactoryOptions)},
136138
* and in any other reference that lists which options the Oracle R2DBC Driver
137139
* supports. Undocumented options are useless; Other programmers won't be
138140
* able to use an option if they have no way to understand what the option
139141
* does or how it should be configured.
142+
* </p>
140143
*/
141144
private static final Set<Option<CharSequence>>
142145
JDBC_CONNECTION_PROPERTY_OPTIONS = Set.of(
@@ -198,7 +201,14 @@ final class OracleReactiveJdbcAdapter implements ReactiveJdbcAdapter {
198201
// Allow the client-side ResultSet cache to be disabled. It is
199202
// necessary to do so when using the serializable transaction isolation
200203
// level in order to prevent phantom reads.
201-
OracleR2dbcOptions.ENABLE_QUERY_RESULT_CACHE
204+
OracleR2dbcOptions.ENABLE_QUERY_RESULT_CACHE,
205+
206+
// Allow v$session attributes to be configured for tracing
207+
OracleR2dbcOptions.VSESSION_OSUSER,
208+
OracleR2dbcOptions.VSESSION_TERMINAL,
209+
OracleR2dbcOptions.VSESSION_PROCESS,
210+
OracleR2dbcOptions.VSESSION_PROGRAM,
211+
OracleR2dbcOptions.VSESSION_MACHINE
202212
);
203213

204214
/** Guards access to a JDBC {@code Connection} created by this adapter */
@@ -379,6 +389,21 @@ public AsyncLock getLock() {
379389
* </li><li>
380390
* {@linkplain OracleConnection#CONNECTION_PROPERTY_IMPLICIT_STATEMENT_CACHE_SIZE
381391
* oracle.jdbc.implicitStatementCacheSize}
392+
* </li><li>
393+
* {@linkplain OracleConnection#CONNECTION_PROPERTY_THIN_VSESSION_OSUSER
394+
* v$session.osuser}
395+
* </li><li>
396+
* {@linkplain OracleConnection#CONNECTION_PROPERTY_THIN_VSESSION_TERMINAL
397+
* v$session.terminal}
398+
* </li><li>
399+
* {@linkplain OracleConnection#CONNECTION_PROPERTY_THIN_VSESSION_PROCESS
400+
* v$session.process}
401+
* </li><li>
402+
* {@linkplain OracleConnection#CONNECTION_PROPERTY_THIN_VSESSION_PROGRAM
403+
* v$session.program}
404+
* </li><li>
405+
* {@linkplain OracleConnection#CONNECTION_PROPERTY_THIN_VSESSION_MACHINE
406+
* v$session.machine}
382407
* </li>
383408
* </ul>
384409
*

src/test/java/oracle/r2dbc/impl/OracleReactiveJdbcAdapterTest.java

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import oracle.jdbc.OracleConnection;
3131
import oracle.jdbc.datasource.OracleDataSource;
3232
import oracle.r2dbc.OracleR2dbcOptions;
33+
import oracle.r2dbc.test.DatabaseConfig;
3334
import org.junit.jupiter.api.Test;
3435
import reactor.core.publisher.Flux;
3536
import reactor.core.publisher.Mono;
@@ -63,6 +64,7 @@
6364
import static io.r2dbc.spi.ConnectionFactoryOptions.PORT;
6465
import static io.r2dbc.spi.ConnectionFactoryOptions.STATEMENT_TIMEOUT;
6566
import static io.r2dbc.spi.ConnectionFactoryOptions.USER;
67+
import static java.lang.String.format;
6668
import static oracle.r2dbc.test.DatabaseConfig.connectTimeout;
6769
import static oracle.r2dbc.test.DatabaseConfig.host;
6870
import static oracle.r2dbc.test.DatabaseConfig.password;
@@ -210,7 +212,7 @@ public void testCreateDataSource() throws SQLException {
210212
public void testTnsAdmin() throws IOException {
211213

212214
// Create an Oracle Net Descriptor
213-
String descriptor = String.format(
215+
String descriptor = format(
214216
"(DESCRIPTION=(ADDRESS=(HOST=%s)(PORT=%d)(PROTOCOL=tcp))" +
215217
"(CONNECT_DATA=(SERVICE_NAME=%s)))",
216218
host(), port(), serviceName());
@@ -227,13 +229,13 @@ public void testTnsAdmin() throws IOException {
227229
try {
228230
// Expect to connect with the descriptor in the R2DBC URL
229231
awaitNone(awaitOne(
230-
ConnectionFactories.get(String.format(
232+
ConnectionFactories.get(format(
231233
"r2dbc:oracle://%s:%s@?oracle.r2dbc.descriptor=%s",
232234
user(), password(), descriptor))
233235
.create())
234236
.close());
235237
awaitNone(awaitOne(
236-
ConnectionFactories.get(ConnectionFactoryOptions.parse(String.format(
238+
ConnectionFactories.get(ConnectionFactoryOptions.parse(format(
237239
"r2dbc:oracle://@?oracle.r2dbc.descriptor=%s", descriptor))
238240
.mutate()
239241
.option(USER, user())
@@ -245,14 +247,14 @@ public void testTnsAdmin() throws IOException {
245247
// Expect to connect with the tnsnames.ora file, when a URL specifies
246248
// the file path and an alias
247249
awaitNone(awaitOne(
248-
ConnectionFactories.get(String.format(
250+
ConnectionFactories.get(format(
249251
"r2dbc:oracle://%s:%s@?oracle.r2dbc.descriptor=%s&TNS_ADMIN=%s",
250252
user(), password(), "test_alias", userDir))
251253
.create())
252254
.close());
253255
awaitNone(awaitOne(
254256
ConnectionFactories.get(ConnectionFactoryOptions.parse(
255-
String.format(
257+
format(
256258
"r2dbc:oracle://@?oracle.r2dbc.descriptor=%s&TNS_ADMIN=%s",
257259
"test_alias", userDir))
258260
.mutate()
@@ -288,14 +290,14 @@ public void testTnsAdmin() throws IOException {
288290

289291
// Create an ojdbc.properties file containing the user name
290292
Files.writeString(Path.of("ojdbc.properties"),
291-
String.format("user=%s", user()),
293+
format("user=%s", user()),
292294
StandardOpenOption.CREATE_NEW);
293295
try {
294296
// Expect to connect with the tnsnames.ora and ojdbc.properties files,
295297
// when a URL specifies their path and an alias, the properties file
296298
// specifies a user, and a standard option specifies the password.
297299
awaitNone(awaitOne(
298-
ConnectionFactories.get(ConnectionFactoryOptions.parse(String.format(
300+
ConnectionFactories.get(ConnectionFactoryOptions.parse(format(
299301
"r2dbc:oracle://?oracle.r2dbc.descriptor=%s&TNS_ADMIN=%s",
300302
"test_alias", userDir))
301303
.mutate()
@@ -469,6 +471,63 @@ public void testExecutorOption() {
469471
}
470472
}
471473

474+
/**
475+
* Verifies the
476+
* {@link OracleR2dbcOptions#VSESSION_OSUSER},
477+
* {@link OracleR2dbcOptions#VSESSION_TERMINAL},
478+
* {@link OracleR2dbcOptions#VSESSION_PROCESS},
479+
* {@link OracleR2dbcOptions#VSESSION_PROGRAM}, and
480+
* {@link OracleR2dbcOptions#VSESSION_MACHINE} options.
481+
*/
482+
@Test
483+
public void testVSessionOptions() {
484+
String osuser = "test-osuser";
485+
String terminal = "test-terminal";
486+
String process = "test-process";
487+
String program = "test-program";
488+
String machine = "test-machine";
489+
490+
// Verify configuration with URL parameters
491+
Connection connection = awaitOne(ConnectionFactories.get(
492+
ConnectionFactoryOptions.parse(
493+
format("r2dbc:oracle://%s:%d/%s" +
494+
"?v$session.osuser=%s" +
495+
"&v$session.terminal=%s" +
496+
"&v$session.process=%s" +
497+
"&v$session.program=%s" +
498+
"&v$session.machine=%s",
499+
host(), port(), serviceName(),
500+
osuser, terminal, process, program, machine))
501+
.mutate()
502+
.option(USER, user())
503+
.option(PASSWORD, password())
504+
.build())
505+
.create());
506+
try {
507+
Result result = awaitOne(connection.createStatement(
508+
"SELECT count(*)" +
509+
" FROM v$session" +
510+
" WHERE osuser=?" +
511+
" AND terminal=?" +
512+
" AND process=?" +
513+
" AND program=?" +
514+
" AND machine=?")
515+
.bind(0, osuser)
516+
.bind(1, terminal)
517+
.bind(2, process)
518+
.bind(3, program)
519+
.bind(4, machine)
520+
.execute());
521+
522+
assertEquals(
523+
Integer.valueOf(1),
524+
awaitOne(result.map(row -> row.get(0, Integer.class))));
525+
}
526+
finally {
527+
tryAwaitNone(connection.close());
528+
}
529+
}
530+
472531
/**
473532
* Verifies that an attempt to connect with a {@code listeningChannel}
474533
* results in an {@link R2dbcTimeoutException}.

0 commit comments

Comments
 (0)