Skip to content

Commit d9306d7

Browse files
Add and improve JavaDocs
1 parent c16319b commit d9306d7

File tree

3 files changed

+82
-78
lines changed

3 files changed

+82
-78
lines changed

src/main/java/oracle/r2dbc/OracleR2dbcTypes.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ private OracleR2dbcTypes() {}
106106
* {@code CREATE TYPE} command that created the type used an "enquoted" type
107107
* name.
108108
* </p><p>
109-
* The {@code ArrayType} object returned by this method may be used to a
110-
* {@link Parameter} that binds an array value to a {@link Statement}.
109+
* The {@code ArrayType} object returned by this method may be used to create
110+
* a {@link Parameter} that binds an array value to a {@link Statement}.
111111
* </p><pre>{@code
112112
* Publisher<Result> arrayBindExample(Connection connection) {
113113
* Statement statement =

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

Lines changed: 66 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
import oracle.r2dbc.impl.ReactiveJdbcAdapter.JdbcReadable;
3737
import oracle.r2dbc.impl.ReadablesMetadata.OutParametersMetadataImpl;
3838
import oracle.r2dbc.impl.ReadablesMetadata.RowMetadataImpl;
39-
import oracle.sql.DatumWithConnection;
4039

4140
import java.math.BigDecimal;
4241
import java.nio.ByteBuffer;
@@ -388,6 +387,15 @@ private Object getJavaArray(int index, Class<?> javaType) {
388387
: convertOracleArray(oracleArray, javaType);
389388
}
390389

390+
/**
391+
* Converts an {@code OracleArray} from Oracle JDBC into the Java array
392+
* variant of the specified {@code javaType}. If the {@code javaType} is
393+
* {@code Object.class}, this method converts to the R2DBC standard mapping
394+
* for the SQL type of the ARRAY elements.
395+
* @param oracleArray Array from Oracle JDBC. Not null.
396+
* @param javaType Type to convert to. Not null.
397+
* @return The converted array.
398+
*/
391399
private Object convertOracleArray(
392400
OracleArray oracleArray, Class<?> javaType) {
393401
try {
@@ -399,7 +407,7 @@ private Object convertOracleArray(
399407
// In this case, the default mapping is declared as Object[] in
400408
// SqlTypeMap, and this method gets called with Object.class. A default
401409
// mapping is used in this case.
402-
Class<?> convertedType = getJavaArrayType(oracleArray, javaType);
410+
Class<?> convertedType = getArrayTypeMapping(oracleArray, javaType);
403411

404412
// Attempt to have Oracle JDBC convert to the desired type
405413
Object[] javaArray =
@@ -420,51 +428,55 @@ private Object convertOracleArray(
420428
}
421429

422430
/**
423-
* Returns the Java array type that an ARRAY will be mapped to. If the
424-
* {@code javaType} argument is {@code Object.class}, then this method returns
425-
* a default mapping based on the element type of the ARRAY. Otherwise, this
426-
* method just returns the {@code javaType}.
431+
* Returns the Java array type that an ARRAY will be mapped to. This method
432+
* is used to determine a default type mapping when {@link #get(int)} or
433+
* {@link #get(String)} are called. In this case, the {@code javaType}
434+
* argument is expected to be {@code Object.class} and this method returns
435+
* a default mapping based on the element type of the ARRAY. Otherwise, if
436+
* the {@code javaType} is something more specific, this method just returns
437+
* it.
427438
*/
428-
private Class<?> getJavaArrayType(
439+
private Class<?> getArrayTypeMapping(
429440
OracleArray oracleArray, Class<?> javaType) {
430441

431442
if (!Object.class.equals(javaType))
432443
return javaType;
433444

434-
// Determine a default Java type mapping for the element type of the ARRAY.
435-
// If the element type is DATE, handle it as if it were TIMESTAMP.
436-
// This is consistent with how DATE columns are usually handled, and
437-
// reflects the fact that Oracle DATE values have a time component.
438445
int jdbcType = fromJdbc(oracleArray::getBaseType);
446+
447+
// Check if the array is multi-dimensional
439448
if (jdbcType == Types.ARRAY) {
440449

441450
Object[] oracleArrays = (Object[]) fromJdbc(oracleArray::getArray);
442451

443-
// TODO: It should be possible to determine the type of next ARRAY
444-
// dimension by calling
445-
// OracleConnection.createArray(
446-
// oracleArray.getSQLTypeName(), new Object[0]).getBaseType())
452+
// An instance of OracleArray representing base type is needed in order to
453+
// know the base type of the next dimension.
447454
final OracleArray oracleArrayElement;
448455
if (oracleArrays.length > 0) {
449456
oracleArrayElement = (OracleArray) oracleArrays[0];
450457
}
451458
else {
452-
// Need to create an instance of the OracleArray base type in order to
453-
// know its own base type. The information for the base type ARRAY
454-
// should already be cached by Oracle JDBC, as the type info was
455-
// retrieved when value was returned from the database. If the
456-
// information is cached, then createOracleArray should not perform a
457-
// blocking call.
459+
// The array is empty, so an OracleArray will need to be created. The
460+
// type information for the ARRAY should be cached by Oracle JDBC, and
461+
// so createOracleArray should not perform a blocking call.
458462
oracleArrayElement = (OracleArray) fromJdbc(() ->
459463
jdbcConnection.unwrap(OracleConnection.class)
460464
.createOracleArray(oracleArray.getBaseTypeName(), new Object[0]));
461465
}
462466

467+
// Recursively call getJavaArrayType, creating a Java array at each level
468+
// of recursion until a non-array SQL type is found. Returning back up the
469+
// stack, the top level of recursion will then create an array with
470+
// the right number of dimensions, and the class of this multi-dimensional
471+
// array is returned.
463472
return java.lang.reflect.Array.newInstance(
464-
getJavaArrayType(oracleArrayElement, Object.class), 0)
473+
getArrayTypeMapping(oracleArrayElement, Object.class), 0)
465474
.getClass();
466475
}
467476

477+
// If the element type is DATE, handle it as if it were TIMESTAMP.
478+
// This is consistent with how DATE columns are usually handled, and
479+
// reflects the fact that Oracle DATE values have a time component.
468480
Type r2dbcType = SqlTypeMap.toR2dbcType(
469481
jdbcType == Types.DATE ? Types.TIMESTAMP : jdbcType);
470482

@@ -476,6 +488,12 @@ private Class<?> getJavaArrayType(
476488
: javaType;
477489
}
478490

491+
/**
492+
* Converts an array from Oracle JDBC into a Java array of a primitive type,
493+
* such as int[], boolean[], etc. This method is handles the case where user
494+
* code explicitly requests a primitive array by passing the class type
495+
* to {@link #get(int, Class)} or {@link #get(String, Class)}.
496+
*/
479497
private Object convertPrimitiveArray(
480498
OracleArray oracleArray, Class<?> primitiveType) {
481499
try {
@@ -531,11 +549,11 @@ else if (double.class.equals(primitiveType)) {
531549
}
532550

533551
/**
534-
* Converts a given {@code array} to an array of a specified
535-
* {@code desiredType}. This method handles arrays returned by
536-
* {@link Array#getArray(Map)}, which may contain objects that are the default
537-
* desiredType mapping for a JDBC driver. This method converts the default JDBC
538-
* desiredType mappings to the default R2DBC desiredType mappings.
552+
* Converts a given {@code array} to an array of a {@code desiredType}. This
553+
* method handles arrays returned by {@link Array#getArray(Map)}, which may
554+
* contain objects that are the default desiredType mapping for a JDBC driver.
555+
* This method converts the default JDBC desiredType mappings to the default
556+
* R2DBC desiredType mappings.
539557
*/
540558
@SuppressWarnings("unchecked")
541559
private <T> T[] convertArray(Object[] array, Class<T> desiredType) {
@@ -685,6 +703,7 @@ else if (oracle.sql.INTERVALDS.class.isAssignableFrom(elementType)
685703
}
686704
else if (oracle.jdbc.OracleArray.class.isAssignableFrom(elementType)
687705
&& desiredType.isArray()) {
706+
// Recursively convert a multi-dimensional array.
688707
return (T[]) mapArray(
689708
array,
690709
length ->
@@ -699,13 +718,32 @@ else if (oracle.jdbc.OracleArray.class.isAssignableFrom(elementType)
699718
throw unsupportedArrayConversion(elementType, desiredType);
700719
}
701720

721+
/**
722+
* Returns an exception indicating a type of elements in a Java array can
723+
* not be converted to a different type.
724+
*/
702725
private static IllegalArgumentException unsupportedArrayConversion(
703726
Class<?> fromType, Class<?> toType) {
704727
return new IllegalArgumentException(format(
705728
"Conversion from array of %s to array of %s is not supported",
706729
fromType.getName(), toType.getName()));
707730
}
708731

732+
/**
733+
* <p>
734+
* Maps the elements of a given {@code array} using a {@code mappingFunction},
735+
* and returns an array generated by an {@code arrayAllocator} that stores the
736+
* mapped elements.
737+
* </p><p>
738+
* The {@code array} may contain {@code null} elements. A {@code null} element
739+
* is automatically converted to {@code null}, and not supplied as input to
740+
* the {@code mappingFunction}.
741+
* </p>
742+
* @param array Array of elements to convert. Not null.
743+
* @param arrayAllocator Allocates an array of an input length. Not null.
744+
* @param mappingFunction Maps elements from the {@code array}. Not null.
745+
* @return Array of mapped elements.
746+
*/
709747
private static <T,U> U[] mapArray(
710748
T[] array, IntFunction<U[]> arrayAllocator,
711749
Function<T, U> mappingFunction) {
@@ -722,49 +760,6 @@ private static <T,U> U[] mapArray(
722760
return result;
723761
}
724762

725-
/**
726-
* Converts an array of {@code BigDecimal} values to objects of a given
727-
* type. This method handles the case where Oracle JDBC does not perform
728-
* conversions specified by the {@code Map} argument to
729-
* {@link Array#getArray(Map)}
730-
*/
731-
private <T> T[] convertBigDecimalArray(
732-
BigDecimal[] bigDecimals, Class<T> type) {
733-
734-
final Function<BigDecimal, T> mapFunction;
735-
736-
if (type.equals(Byte.class)) {
737-
mapFunction = bigDecimal -> type.cast(bigDecimal.byteValue());
738-
}
739-
else if (type.equals(Short.class)) {
740-
mapFunction = bigDecimal -> type.cast(bigDecimal.shortValue());
741-
}
742-
else if (type.equals(Integer.class)) {
743-
mapFunction = bigDecimal -> type.cast(bigDecimal.intValue());
744-
}
745-
else if (type.equals(Long.class)) {
746-
mapFunction = bigDecimal -> type.cast(bigDecimal.longValue());
747-
}
748-
else if (type.equals(Float.class)) {
749-
mapFunction = bigDecimal -> type.cast(bigDecimal.floatValue());
750-
}
751-
else if (type.equals(Double.class)) {
752-
mapFunction = bigDecimal -> type.cast(bigDecimal.doubleValue());
753-
}
754-
else {
755-
throw new IllegalArgumentException(
756-
"Can not convert BigDecimal to " + type);
757-
}
758-
759-
return Arrays.stream(bigDecimals)
760-
.map(mapFunction)
761-
.toArray(length -> {
762-
@SuppressWarnings("unchecked")
763-
T[] array = (T[])java.lang.reflect.Array.newInstance(type, length);
764-
return array;
765-
});
766-
}
767-
768763
/**
769764
* Checks if the specified zero-based {@code index} is a valid column index
770765
* for this row. This method is used to verify index value parameters
@@ -801,7 +796,7 @@ private static final class RowImpl
801796
* determine the default type mapping of column values.
802797
* </p>
803798
* @param jdbcConnection JDBC connection that created the
804-
* {@code jdbcReadable}. Not null.*
799+
* {@code jdbcReadable}. Not null.
805800
* @param jdbcReadable Row data from the Oracle JDBC Driver. Not null.
806801
* @param metadata Meta-data for the specified row. Not null.
807802
* @param adapter Adapts JDBC calls into reactive streams. Not null.

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

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -976,7 +976,20 @@ final Publisher<OracleResultImpl> execute() {
976976

977977
/**
978978
* <p>
979-
* Sets {@link #binds} on the {@link #preparedStatement}. The
979+
* Sets {@link #binds} on the {@link #preparedStatement}, as specified by
980+
* {@link #bind(Object[])}. This method is called when this statement is
981+
* executed. Subclasess override this method to perform additional actions.
982+
* </p>
983+
* @return A {@code Publisher} that emits {@code onComplete} when all
984+
* {@code binds} have been set.
985+
*/
986+
protected Publisher<Void> bind() {
987+
return bind(binds);
988+
}
989+
990+
/**
991+
* <p>
992+
* Sets the given {@code binds} on the {@link #preparedStatement}. The
980993
* returned {@code Publisher} completes after all bind values have
981994
* materialized and been set on the {@code preparedStatement}.
982995
* </p><p>
@@ -988,10 +1001,6 @@ final Publisher<OracleResultImpl> execute() {
9881001
* @return A {@code Publisher} that emits {@code onComplete} when all
9891002
* {@code binds} have been set.
9901003
*/
991-
protected Publisher<Void> bind() {
992-
return bind(binds);
993-
}
994-
9951004
protected final Publisher<Void> bind(Object[] binds) {
9961005
return adapter.getLock().flatMap(() -> {
9971006

0 commit comments

Comments
 (0)