Skip to content

UDP Implementation #86

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed

Conversation

nirmalhk7
Copy link

Fixes #83. As explained and discussed in the issue, neither Oracle's R2DBC driver nor R2DBC itself support user defined datatypes within itself. I'm not aware about other databases, but my project used several UDTs within it, and the lack of support is causing me some issues to migrate my project to a reactive stack. Hence, my PR for the same.

I've created a custom class UserDefinedType (Implementing Type class) that records the SQL type to map to (the Java class corresponding it) and the type name (string).

.bind(1, Parameters.Out(new UserDefinedType(java.sql.Array.class, "typeName"))

After this, its relatively straightforward: every time we operate on the Type object, we check if its an instance of UserDefinedType or not and tweak it accordingly.

Signed-off-by: Nirmal Khedkar <[email protected]>
Copy link
Member

@Michael-A-McMahon Michael-A-McMahon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really appreciate you taking this on. Please review my comments and let me know your thoughts/questions.

@@ -36,4 +36,5 @@
requires transitive r2dbc.spi;

exports oracle.r2dbc;
exports oracle.r2dbc.impl;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The impl package is not part of the public API. We can not export it.

@@ -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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The R2DBC SPI uses instances of Parameter.Out to represent out binds. It should be possible to do so with UserDefinedType, as in:

statement.bind(Parameters.out(new UserDefinedType(...)))

There should be no need to support mapping UserDefinedType objects directly.

@@ -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();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain why we need this change? I feel like I'm missing something :)

@@ -0,0 +1,23 @@
package oracle.r2dbc.impl;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the need for exporting the impl package came from here.
On the Issue thread, I had suggested a factory method on OracleR2dbcTypes. We can make UserDefinedType an inner class of OracleR2dbcTypes, also private and static. We can then have the factory method return an instance of this class. This would eliminate the need to export the impl package.
A factory method will also allow us to return an instance of the Type interface, rather than a specific concrete class. By returning an interface, we will have more freedom to change the code later without breaking existing code that calls the method.


import io.r2dbc.spi.Type;

public final class UserDefinedType implements Type {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We must write a JavaDoc before merging any code. The doc should capture the rationale which was present in the mind of the programmer who wrote the code: What problem was the code intended to solve, and how did the programmer intend for their code to be used?

import io.r2dbc.spi.Type;

public final class UserDefinedType implements Type {
private final Class sqlClassType;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had been thinking to add new Type constants in OracleR2dbcTypes:
STRUCT, ARRAY, and REF.

And these SQL types can map to Java classes of the java.sql package: Struct, Array, and Ref

All this is to say that UserDefinedType can retain an io.r2dbc.spi.Type field, rather than a Class field. The Type field would be one of STRUCT, ARRAY, REF. We can then implement getJavaType to return the java type mapping for this Type field.

Does this make sense?

@Michael-A-McMahon
Copy link
Member

Hi @nirmalhk7. Were you planning to return to this? If not, I think I'll have a go at it on my own.

@nirmalhk7
Copy link
Author

nirmalhk7 commented Oct 14, 2022

Hey Michael,
Apologies, I was trying to craft a better way to take this issue.

You can take up this issue, but can you give an estimate when can this be released at the earliest? I think UDPs are a big part of Oracle SQL, so this does warrant a fast release

@Michael-A-McMahon
Copy link
Member

Thanks for the update. I think I can have a run at this today and, if all goes well, I can get a PR ready for merging.

We are closing in on a 1.1.0 release for Oracle R2DBC. If can get the PR done today, then we can include this in the next release.

I don't want to guess when the release will happen, as I'd probably end up being wrong. However, I can say for sure that we've begun a review and approval process that is required before releasing a new version. It's too hard to say when this will be done at the moment, as most of us at Oracle are busy preparing for the Cloud World and JavaOne conferences happening next week.

@Michael-A-McMahon
Copy link
Member

Changes in this branch are superseded by #104 .
@nirmalhk7: I very much appreciate the effort you put in here, and your initial issue which got me thinking about this problem. If you have any feedback for the changes in #104, I'd be very interested to hear it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for sending type name with Out Parameters.
2 participants