-
-
Notifications
You must be signed in to change notification settings - Fork 138
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
initial r2dbc mysql support #99
Conversation
Codecov Report
@@ Coverage Diff @@
## master #99 +/- ##
=========================================
Coverage 78.94% 78.94%
Complexity 1011 1011
=========================================
Files 258 258
Lines 3661 3661
Branches 487 487
=========================================
Hits 2890 2890
Misses 531 531
Partials 240 240 Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work and really excited to see this change happen. I wonder whether it would rather make sense to use Project Reactor as Reactor provides Mono.fromFuture(CompletableFuture)
adapters and aligns, in general, better with Java 8 code.
As soon as there's support for parametrized statements, we should extend our r2dbc-client
examples to include a MySQL example as well.
# Conflicts: # build.gradle
@mp911de I added prepared statement support. you're welcome to review it and if it looks ok I will merge it and release a version, so it can be tested externally. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A great start, I left some comments on the PR.
import java.util.function.Supplier | ||
import com.github.jasync.sql.db.Connection as JasyncConnection | ||
|
||
class JasyncClientConnection(private val jasyncConnection: JasyncConnection) : Connection, Supplier<JasyncConnection> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have support for MySQL's PING? Adding this functionality here would be a preparation for r2dbc/r2dbc-spi#54.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the connection itself don't have ping, but there is a connection factory that knows how to test the connection:
jasync-sql/db-async-common/src/main/java/com/github/jasync/sql/db/pool/ConnectionFactory.kt
Line 79 in dde3f6a
override fun test(item: T): CompletableFuture<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea behind is to check for e.g. pooling implementations whether the connection works without actually executing SQL.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, there is no ping support, but there is a 'validate' check that don't do any network action:
jasync-sql/db-async-common/src/main/java/com/github/jasync/sql/db/pool/ConnectionFactory.kt
Line 49 in dde3f6a
override fun validate(item: T): Try<T> { |
override fun <T> get(identifier: Any, requestedType: Class<T>): T? { | ||
|
||
|
||
if (identifier is String) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initially dropping the requested type (Class<T>
) is okay, but make sure to consider the requested type at some point in time as this is part of the SPI contract, otherwise, the calling side will run into ClassCastException
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand the spi. should the returned value be of type requestedType
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly. Each database type maps to a specific Java type (e.g. TINYINT
to Byte
, SMALLINT
to Short
). You should be able to retrieve a TINYINT
as Integer.class
or as Long.class
. The caller requests the type Integer.class
and expects the get(Any, Class<T>)
method to return that specific type.
This conversion makes only sense for convertible types (Numbers
, Dates (LocalDateTime
to LocalTime
or LocalDate
) and converting values to String
).
For a start, if you don't want to implement an advanced Codec mechanism, it would make sense to consider the mentioned three conversions and if the value is not null
, to requestedType.cast(…)
the value.
In contrast, get(Any)
returns the native type (i.e. what happens right now, that the driver determines the most appropriate type).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as you mentioned the driver has "builtin" types right now depending on the db type. I am not what you mean to do for a start? just a cast? didn't understand the different cases you mentioned.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method should do at least a cast.
I would also suggest adding the following conversion rules:
- If a value is a
Number
and the requested type is a number, too, then convert the value toT
usingNumber.intValue()
,Number.longValue()
methods. - If the requested type is
String
, then calltoString()
on the value. - If a value is
LocalDate
,LocalDateTime
, orLocalTime
and the requested type is one of these date types, then convert the value into the requested value using the provided methods onLocalDate
etc (e.g.LocalDateTime.atStartOfDay()
).
Does this make sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, I added it, please review again to see we are aligned. Note that for DateTime the lib is using joda so I had to do an extra conversion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty decent now. I wasn't aware that you build on top of Joda. For R2DBC we want to stay within the Java 8 type realm for primitives. The native get(Any)
method should ideally return Java 8 types for dates. Retrieving a Joda type would be still possible via get(Any, Class<T>)
when requesting the Joda LocalDateTime
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will change that. we have joda as a legacy from the original driver.
r2dbc-mysql/build.gradle
Outdated
compile project(':mysql-async') | ||
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" | ||
compile "io.r2dbc:r2dbc-spi:1.0.0.BUILD-SNAPSHOT" | ||
implementation "io.reactivex.rxjava2:rxjava:2.2.7" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it compatible or something else? Otherwise using reactor-core
may be a better choice because of more powerful and concise API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have a strong opinion about it, just followed what @mp911de did in this gist: https://gist.github.com/mp911de/9ea13939e8fd9a6b4ef138419f085715
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used RxJava 2 in the vert.x example as vert.x had no dependency on Project Reactor.
My choice for a Java 8 project would be Project Reactor, because it properly supports CompletableFuture
(Java 8 types) and it has a Context
that can be used to bind a connection to, if someone wants to properly manage a transaction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed it.
Did a first integration test pass with Spring Data R2DBC and things look quite for simple queries using MySQL 5.6.43. The latest MySQL version fails to connect with
For the |
caching_sha2_password is default auth since 8.0.4, but it can be changed on the db server: https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_default_authentication_plugin Regarding configuration, let's not change it now but think of a consistent api later. So I will merge this PR and let you know what it's initial released version. |
No description provided.