Skip to content

Commit 9ecc170

Browse files
Merge branch 'main' of https://github.com/oracle/oracle-r2dbc into 1-1-0-dep-update
2 parents dca2ece + 9d37887 commit 9ecc170

20 files changed

+4422
-184
lines changed

.github/workflows/test.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,6 @@ echo "HOST=localhost" >> src/test/resources/config.properties
8181
echo "PORT=1521" >> src/test/resources/config.properties
8282
echo "USER=test" >> src/test/resources/config.properties
8383
echo "PASSWORD=test" >> src/test/resources/config.properties
84-
echo "CONNECT_TIMEOUT=120" >> src/test/resources/config.properties
85-
echo "SQL_TIMEOUT=120" >> src/test/resources/config.properties
84+
echo "CONNECT_TIMEOUT=240" >> src/test/resources/config.properties
85+
echo "SQL_TIMEOUT=240" >> src/test/resources/config.properties
8686
mvn clean compile test

README.md

Lines changed: 163 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,169 @@ prefetched entirely, a smaller prefetch size can be configured using the
570570
option, and the LOB can be consumed as a stream. By mapping LOB columns to
571571
`Blob` or `Clob` objects, the content can be consumed as a reactive stream.
572572

573-
### REF Cursors
573+
### ARRAY
574+
Oracle Database supports `ARRAY` as a user defined type only. A `CREATE TYPE`
575+
command is used to define an `ARRAY` type:
576+
```sql
577+
CREATE TYPE MY_ARRAY AS ARRAY(8) OF NUMBER
578+
```
579+
Oracle R2DBC defines `oracle.r2dbc.OracleR2dbcType.ArrayType` as a `Type` for
580+
representing user defined `ARRAY` types. A `Parameter` with a type of
581+
`ArrayType` must be used when binding array values to a `Statement`.
582+
```java
583+
Publisher<Result> arrayBindExample(Connection connection) {
584+
Statement statement =
585+
connection.createStatement("INSERT INTO example VALUES (:array_bind)");
586+
587+
// Use the name defined for an ARRAY type:
588+
// CREATE TYPE MY_ARRAY AS ARRAY(8) OF NUMBER
589+
ArrayType arrayType = OracleR2dbcTypes.arrayType("MY_ARRAY");
590+
Integer[] arrayValues = {1, 2, 3};
591+
statement.bind("arrayBind", Parameters.in(arrayType, arrayValues));
592+
593+
return statement.execute();
594+
}
595+
```
596+
A `Parameter` with a type of `ArrayType` must also be used when binding OUT
597+
parameters of a PL/SQL call.
598+
```java
599+
Publisher<Result> arrayOutBindExample(Connection connection) {
600+
Statement statement =
601+
connection.createStatement("BEGIN; exampleCall(:array_bind); END;");
602+
603+
// Use the name defined for an ARRAY type:
604+
// CREATE TYPE MY_ARRAY AS ARRAY(8) OF NUMBER
605+
ArrayType arrayType = OracleR2dbcTypes.arrayType("MY_ARRAY");
606+
statement.bind("arrayBind", Parameters.out(arrayType));
607+
608+
return statement.execute();
609+
}
610+
```
611+
`ARRAY` values may be consumed from a `Row` or `OutParameter` as a Java array.
612+
The element type of the Java array may be any Java type that is supported as
613+
a mapping for the SQL type of the `ARRAY`. For instance, if the `ARRAY` type is
614+
`NUMBER`, then a `Integer[]` mapping is supported:
615+
```java
616+
Publisher<Integer[]> arrayMapExample(Result result) {
617+
return result.map(readable -> readable.get("arrayValue", Integer[].class));
618+
}
619+
```
620+
621+
### OBJECT
622+
Oracle Database supports `OBJECT` as a user defined type. A `CREATE TYPE`
623+
command is used to define an `OBJECT` type:
624+
```sql
625+
CREATE TYPE PET AS OBJECT(
626+
name VARCHAR(128),
627+
species VARCHAR(128),
628+
weight NUMBER,
629+
birthday DATE)
630+
```
631+
Oracle R2DBC defines `oracle.r2dbc.OracleR2dbcType.ObjectType` as a `Type` for
632+
representing user defined `OBJECT` types. A `Parameter` with a type of
633+
`ObjectType` may be used to bind `OBJECT` values to a `Statement`.
634+
635+
Use an `Object[]` to bind the attribute values of an `OBJECT` by index:
636+
```java
637+
Publisher<Result> objectArrayBindExample(Connection connection) {
638+
Statement statement =
639+
connection.createStatement("INSERT INTO petTable VALUES (:petObject)");
640+
641+
// Bind the attributes of the PET OBJECT defined above
642+
ObjectType objectType = OracleR2dbcTypes.objectType("PET");
643+
Object[] attributeValues = {
644+
"Derby",
645+
"Dog",
646+
22.8,
647+
LocalDate.of(2015, 11, 07)
648+
};
649+
statement.bind("petObject", Parameters.in(objectType, attributeValues));
650+
651+
return statement.execute();
652+
}
653+
```
654+
655+
Use a `Map<String,Object>` to bind the attribute values of an `OBJECT` by name:
656+
```java
657+
Publisher<Result> objectMapBindExample(Connection connection) {
658+
Statement statement =
659+
connection.createStatement("INSERT INTO petTable VALUES (:petObject)");
660+
661+
// Bind the attributes of the PET OBJECT defined above
662+
ObjectType objectType = OracleR2dbcTypes.objectType("PET");
663+
Map<String,Object> attributeValues = Map.of(
664+
"name", "Derby",
665+
"species", "Dog",
666+
"weight", 22.8,
667+
"birthday", LocalDate.of(2015, 11, 07));
668+
statement.bind("petObject", Parameters.in(objectType, attributeValues));
669+
670+
return statement.execute();
671+
}
672+
```
673+
A `Parameter` with a type of `ObjectType` must be used when binding OUT
674+
parameters of `OBJECT` types for a PL/SQL call:
675+
```java
676+
Publisher<Result> objectOutBindExample(Connection connection) {
677+
Statement statement =
678+
connection.createStatement("BEGIN; getPet(:petObject); END;");
679+
680+
ObjectType objectType = OracleR2dbcTypes.objectType("PET");
681+
statement.bind("petObject", Parameters.out(objectType));
682+
683+
return statement.execute();
684+
}
685+
```
686+
`OBJECT` values may be consumed from a `Row` or `OutParameter` as an
687+
`oracle.r2dbc.OracleR2dbcObject`. The `OracleR2dbcObject` interface is a subtype
688+
of `io.r2dbc.spi.Readable`. Attribute values may be accessed using the standard
689+
`get` methods of `Readable`. The `get` methods of `OracleR2dbcObject` support
690+
alll SQL to Java type mappings defined by the
691+
[R2DBC Specification](https://r2dbc.io/spec/1.0.0.RELEASE/spec/html/#datatypes.mapping):
692+
```java
693+
Publisher<Pet> objectMapExample(Result result) {
694+
return result.map(row -> {
695+
OracleR2dbcObject oracleObject = row.get(0, OracleR2dbcObject.class);
696+
return new Pet(
697+
oracleObject.get("name", String.class),
698+
oracleObject.get("species", String.class),
699+
oracleObject.get("weight", Float.class),
700+
oracleObject.get("birthday", LocalDate.class));
701+
});
702+
}
703+
```
704+
705+
Instances of `OracleR2dbcObject` may be passed directly to `Statement` bind
706+
methods:
707+
```java
708+
Publisher<Result> objectBindExample(
709+
OracleR2dbcObject oracleObject, Connection connection) {
710+
Statement statement =
711+
connection.createStatement("INSERT INTO petTable VALUES (:petObject)");
712+
713+
statement.bind("petObject", oracleObject);
714+
715+
return statement.execute();
716+
}
717+
```
718+
Attribute metadata is exposed by the `getMetadata` method of
719+
`OracleR2dbcObject`:
720+
```java
721+
void printObjectMetadata(OracleR2dbcObject oracleObject) {
722+
OracleR2dbcObjectMetadata metadata = oracleObject.getMetadata();
723+
OracleR2dbcTypes.ObjectType objectType = metadata.getObjectType();
724+
725+
System.out.println("Object Type: " + objectType);
726+
metadata.getAttributeMetadatas()
727+
.stream()
728+
.forEach(attributeMetadata -> {
729+
System.out.println("\tAttribute Name: " + attributeMetadata.getName()));
730+
System.out.println("\tAttribute Type: " + attributeMetadata.getType()));
731+
});
732+
}
733+
```
734+
735+
### REF Cursor
574736
Use the `oracle.r2dbc.OracleR2dbcTypes.REF_CURSOR` type to bind `SYS_REFCURSOR` out
575737
parameters:
576738
```java
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package oracle.r2dbc;
2+
3+
public interface OracleR2dbcObject extends io.r2dbc.spi.Readable {
4+
5+
OracleR2dbcObjectMetadata getMetadata();
6+
7+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package oracle.r2dbc;
2+
3+
import io.r2dbc.spi.ReadableMetadata;
4+
5+
import java.util.List;
6+
import java.util.NoSuchElementException;
7+
8+
/**
9+
* Represents the metadata for attributes of an OBJECT. Metadata for attributes
10+
* can either be retrieved by index or by name. Attribute indexes are
11+
* {@code 0}-based. Retrieval by attribute name is case-insensitive.
12+
*/
13+
public interface OracleR2dbcObjectMetadata {
14+
15+
/**
16+
* Returns the type of the OBJECT which metadata is provided for.
17+
* @return The type of the OBJECT. Not null.
18+
*/
19+
OracleR2dbcTypes.ObjectType getObjectType();
20+
21+
/**
22+
* Returns the {@link ReadableMetadata} for one attribute.
23+
*
24+
* @param index the attribute index starting at 0
25+
* @return the {@link ReadableMetadata} for one attribute. Not null.
26+
* @throws IndexOutOfBoundsException if {@code index} is out of range
27+
* (negative or equals/exceeds {@code getParameterMetadatas().size()})
28+
*/
29+
ReadableMetadata getAttributeMetadata(int index);
30+
31+
/**
32+
* Returns the {@link ReadableMetadata} for one attribute.
33+
*
34+
* @param name the name of the attribute. Not null. Parameter names are
35+
* case-insensitive.
36+
* @return the {@link ReadableMetadata} for one attribute. Not null.
37+
* @throws IllegalArgumentException if {@code name} is {@code null}
38+
* @throws NoSuchElementException if there is no attribute with the
39+
* {@code name}
40+
*/
41+
ReadableMetadata getAttributeMetadata(String name);
42+
43+
/**
44+
* Returns the {@link ReadableMetadata} for all attributes.
45+
*
46+
* @return the {@link ReadableMetadata} for all attributes. Not null.
47+
*/
48+
List<? extends ReadableMetadata> getAttributeMetadatas();
49+
}

0 commit comments

Comments
 (0)