diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 796c99e..08bdb03 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -36,4 +36,5 @@ requires transitive r2dbc.spi; exports oracle.r2dbc; + exports oracle.r2dbc.impl; } diff --git a/src/main/java/oracle/r2dbc/impl/OracleReadableImpl.java b/src/main/java/oracle/r2dbc/impl/OracleReadableImpl.java index d00dbef..a8519c0 100755 --- a/src/main/java/oracle/r2dbc/impl/OracleReadableImpl.java +++ b/src/main/java/oracle/r2dbc/impl/OracleReadableImpl.java @@ -212,7 +212,8 @@ else if (Object.class.equals(type)) { // Use the default type mapping if Object.class has been specified. // This method is invoked recursively with the default mapping, so long // as Object.class is not also the default mapping. - Class defaultType = readablesMetadata.get(index).getJavaType(); + Class defaultType = readablesMetadata.get(index).getType().getJavaType(); + value = Object.class.equals(defaultType) ? jdbcReadable.getObject(index, Object.class) : convert(index, defaultType); diff --git a/src/main/java/oracle/r2dbc/impl/OracleStatementImpl.java b/src/main/java/oracle/r2dbc/impl/OracleStatementImpl.java index ac92262..0e07054 100755 --- a/src/main/java/oracle/r2dbc/impl/OracleStatementImpl.java +++ b/src/main/java/oracle/r2dbc/impl/OracleStatementImpl.java @@ -694,7 +694,7 @@ private void bindObject(int index, Object object) { if (object == null){ bindValues[index] = NULL_BIND; } - else if (object instanceof Parameter) { + else if (object instanceof Parameter || object instanceof UserDefinedType) { bindParameter(index, (Parameter)object); } else if (object instanceof Parameter.In @@ -716,7 +716,7 @@ else if (object instanceof Parameter.In * @throws IllegalArgumentException If the Java or SQL type of the * {@code parameter} is not supported. */ - private void bindParameter(int index, Parameter parameter) { + private void bindParameter(int index, Object parameter) { if (parameter instanceof Parameter.Out) { if (! batch.isEmpty()) @@ -725,21 +725,35 @@ private void bindParameter(int index, Parameter parameter) { throw outParameterWithGeneratedValues(); } + Type parameterType; + Object parameterValue; + if(parameter instanceof Parameter){ + parameterType= ((Parameter) parameter).getType(); + parameterValue= ((Parameter) parameter).getValue(); + } else { + throw new IllegalArgumentException("Invalid parameter type: "+parameter); + } + // TODO: This method should check if Java type can be converted to the // specified SQL type. If the conversion is unsupported, then JDBC // setObject(...) will throw when this statement is executed. The correct // behavior is to throw IllegalArgumentException here, and not from // execute() - Type r2dbcType = - requireNonNull(parameter.getType(), "Parameter type is null"); - SQLType jdbcType = toJdbcType(r2dbcType); + Type r2dbcType= requireNonNull(parameterType, "Parameter type is null"); + + SQLType jdbcType; + if(r2dbcType instanceof UserDefinedType){ + jdbcType = toJdbcType(r2dbcType.getJavaType()); + } else { + jdbcType = toJdbcType(r2dbcType); + } if (jdbcType == null) { throw new IllegalArgumentException( "Unsupported SQL type: " + r2dbcType); } - requireSupportedJavaType(parameter.getValue()); + requireSupportedJavaType(parameterValue); bindValues[index] = parameter; } @@ -983,7 +997,7 @@ protected final Publisher bind(Object[] binds) { List> bindPublishers = null; for (int i = 0; i < binds.length; i++) { - if (binds[i] instanceof Parameter.Out + if ((((binds[i] instanceof Parameter.Out) || (binds[i] instanceof UserDefinedType))) && !(binds[i] instanceof Parameter.In)) continue; @@ -1339,7 +1353,7 @@ private JdbcCall( super(callableStatement, bindValues); outBindIndexes = IntStream.range(0, bindValues.length) - .filter(i -> bindValues[i] instanceof Parameter.Out) + .filter(i -> bindValues[i] instanceof Parameter.Out || bindValues[i] instanceof UserDefinedType) .toArray(); OutParameterMetadata[] metadataArray = @@ -1351,8 +1365,10 @@ private JdbcCall( // Use the parameter name, or the index if the parameter is unnamed String name = requireNonNullElse( parameterNames.get(bindIndex), String.valueOf(i)); - metadataArray[i] = createParameterMetadata( - name, ((Parameter)bindValues[bindIndex]).getType()); + if(bindValues[bindIndex] instanceof Parameter){ + metadataArray[i] = createParameterMetadata( + name, ((Parameter)bindValues[bindIndex]).getType()); + } } this.metadata = createOutParametersMetadata(metadataArray); @@ -1377,8 +1393,15 @@ private Publisher registerOutParameters() { for (int i : outBindIndexes) { Type type = ((Parameter) binds[i]).getType(); - SQLType jdbcType = toJdbcType(type); - callableStatement.registerOutParameter(i + 1, jdbcType); + SQLType jdbcType; + + if(type instanceof UserDefinedType){ + jdbcType = toJdbcType(type.getJavaType()); + callableStatement.registerOutParameter(i+1,jdbcType,type.getName()); + } else { + jdbcType = toJdbcType(type); + callableStatement.registerOutParameter(i+1, jdbcType); + } } }); } diff --git a/src/main/java/oracle/r2dbc/impl/SqlTypeMap.java b/src/main/java/oracle/r2dbc/impl/SqlTypeMap.java index 231c1fd..e2b77a4 100644 --- a/src/main/java/oracle/r2dbc/impl/SqlTypeMap.java +++ b/src/main/java/oracle/r2dbc/impl/SqlTypeMap.java @@ -215,6 +215,9 @@ static Type toR2dbcType(int jdbcTypeNumber) { * @return A JDBC SQL type */ static SQLType toJdbcType(Type r2dbcType) { + if(r2dbcType instanceof UserDefinedType){ + return JAVA_TO_SQL_TYPE_MAP.get(r2dbcType.getClass()); + } return r2dbcType instanceof Type.InferredType ? toJdbcType(r2dbcType.getJavaType()) : R2DBC_TO_JDBC_TYPE_MAP.get(r2dbcType); diff --git a/src/main/java/oracle/r2dbc/impl/UserDefinedType.java b/src/main/java/oracle/r2dbc/impl/UserDefinedType.java new file mode 100644 index 0000000..83d34e3 --- /dev/null +++ b/src/main/java/oracle/r2dbc/impl/UserDefinedType.java @@ -0,0 +1,23 @@ +package oracle.r2dbc.impl; + +import io.r2dbc.spi.Type; + +public final class UserDefinedType implements Type { + private final Class sqlClassType; + private final String typeName; + + public UserDefinedType(Class sqlClassType, String typeName) { + this.sqlClassType = sqlClassType; + this.typeName = typeName; + } + + @Override + public Class getJavaType() { + return sqlClassType; + } + + @Override + public String getName() { + return typeName; + } +} \ No newline at end of file