vertx-sql-client icon indicating copy to clipboard operation
vertx-sql-client copied to clipboard

Introduce SPI Row/Tuple converter

Open zero88 opened this issue 4 years ago • 8 comments

Describe the feature

Add new convention method for Row to accept converter. Introduce 2 converter interfaces, it should be 2-way converter: JDBC/Reactive SQL <=> User data type.

  • DataTypeConverter for converting by data type
  • ColumnConverter for converting by data type and column name

Something like that

interface Row {
default <T> T get(String column, ColumnConverter<T> converter) {
    return converter.convert(getValue(column));
}
}

Then extract every get<Type> to Converter, then add them to SPI as Vertx convention. On each database driver/business model, developer can easy enhance or override default converter and make seamlessly UDT from database to java type

The concept will be similar on what I have done in jooqx such as: https://github.com/zero88/jooqx/blob/fcc473908cdbcc7b61544ccfbc97b4f7a8797b13/core/src/main/java/io/zero88/jooqx/datatype/JooqxConverter.java#L19 and https://github.com/zero88/jooqx/blob/fcc473908cdbcc7b61544ccfbc97b4f7a8797b13/core/src/main/java/io/zero88/jooqx/datatype/DataTypeMapperRegistry.java#L23

Contribute

I might take it if you want to minimum API change in my lib also.

zero88 avatar Jul 23 '21 11:07 zero88

why does this need to be on the Row interface instead of being a static method in any codebase ?

vietj avatar Jul 26 '21 07:07 vietj

For auto mapping data type, might be conjunction with sql-client-template (not yet checked details).

Actually, this mapper could be in between Database and Vertx converter rather than in Row that is a result between Vertx and developer. in Row, you have: <T> T get(Class<T> type, String column), it is explicit cast data type. Then I introduce a lenient way like convert this data type to another data type, and it can be global configuration or on demand depend on table. It can be one of use-cases.

just in idea concept, need to go more deep. Yes, of course, it can be in another lib if you consider it makes API is not slim

zero88 avatar Jul 26 '21 08:07 zero88

can you show some practical use case with code so we understand better ?

On Mon, Jul 26, 2021 at 10:10 AM zero88 @.***> wrote:

For auto mapping data type, might be conjunction with sql-client-template (not yet checked details).

Actually, this mapper could be in between Database and Vertx converter rather than in Row that is a storage between Vertx and developer. in Row, you have: <T> T get(Class<T> type, String column), it is explicit cast data type. Then I introduce a lenient way like convert this data type to another data type, and it can be global configuration or on demand depend on table. It can be one of use-cases.

just in idea concept, need to go more deep. Yes, of course, it can be in another lib if you consider it makes API is not slim

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/eclipse-vertx/vertx-sql-client/issues/1013#issuecomment-886477043, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABXDCUQEJFG7JKM5TGEQXTTZUJ6VANCNFSM5A32UTDA .

vietj avatar Jul 26 '21 11:07 vietj

sure, I will keep an update in this week.

zero88 avatar Jul 26 '21 12:07 zero88

@vietj it is similar that I did in JDBC client. https://github.com/vert-x3/vertx-jdbc-client/pull/235#issuecomment-886412088

I hope Vertx can provide SPI entrypoint then developer can provide a hook to convert data directly from SQL before it will be stored in Row, and in reverse direction also. Some use cases (with PostgreSQL context):

  • Database use INTERVAL data type, Vertx convert to io.vertx.pgclient.data.Interval but application use java.time.Duration
  • Database use VARCHAR data type for column field_duration (for legacy system), Vertx convert to String and application use java.time.Duration

zero88 avatar Aug 04 '21 04:08 zero88

how about doing that directly on the Query`` with the map method ? you would provide a Function<Row, Row> that performs the desired mapping instead

vietj avatar Aug 05 '21 07:08 vietj

as for Interval we should I think add a method to convert to Duration

vietj avatar Aug 05 '21 07:08 vietj

how about doing that directly on the Query`` with the map method ? you would provide a Function<Row, Row> that performs the desired mapping instead

Ya, I think it can be good to add it as ad-hoc query. However, Row is "lenient immutable" that unable to set value at index in public API, and no public constructor (I think should not coz duplicate memory when copy).

Interval is one of example. I have more consider about UDT, something like I have Address UDT in database, then I want to map it as Pojo class directly to Address.java

I thought a inject converter can start from here (PostgreSQL example but similar to others):

https://github.com/eclipse-vertx/vertx-sql-client/blob/35188239370f3ad3d19b18a0b1b43e54d160d2a7/vertx-pg-client/src/main/java/io/vertx/pgclient/impl/codec/RowResultDecoder.java#L43-L48

  • DataType can be interface instead of Enum
  • DataTypeCodec is able to override instead of static

zero88 avatar Aug 05 '21 08:08 zero88