https://kotlinlang.org logo
#komapper
Title
# komapper
d

dave08

10/29/2023, 12:48 PM
On production I'm getting a cryptic stack trace (with no indication to where this is happening in my code) with an
Copy code
io.r2dbc.spi.R2dbcBadGrammarException
it would have been great to have been great if Komapper could try catching such errors and include some info like the sql that was run, etc...
t

Toshihiro Nakamura

10/29/2023, 1:05 PM
Ideally, I think the R2DBC driver should include enough information in the R2dbcBadGrammarException. However, if you could provide a stack trace, I would like to consider what can be done with Komapper.
d

dave08

10/29/2023, 1:14 PM
Copy code
io.r2dbc.spi.R2dbcBadGrammarException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '....' at line 1	at com.github.jasync.r2dbc.mysql.JasyncStatement.mapException(JasyncStatement.kt:184)	at com.github.jasync.r2dbc.mysql.JasyncStatement.access$mapException(JasyncStatement.kt:30)	at com.github.jasync.r2dbc.mysql.JasyncStatement$execute$4.invoke(JasyncStatement.kt:122)	at com.github.jasync.r2dbc.mysql.JasyncStatement$execute$4.invoke(JasyncStatement.kt:120)	at reactor.kotlin.core.publisher.FluxExtensionsKt.onErrorMap$lambda-1(FluxExtensions.kt:172)	at reactor.core.publisher.Flux.lambda$onErrorMap$28(Flux.java:7236)	at reactor.core.publisher.Flux.lambda$onErrorResume$29(Flux.java:7289)	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:94)	at reactor.core.publisher.FluxMap$MapSubscriber.onError(FluxMap.java:134)	at reactor.core.publisher.FluxConcatMapNoPrefetch$FluxConcatMapNoPrefetchSubscriber.maybeOnError(FluxConcatMapNoPrefetch.java:326)	at reactor.core.publisher.FluxConcatMapNoPrefetch$FluxConcatMapNoPrefetchSubscriber.innerError(FluxConcatMapNoPrefetch.java:297)	at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onError(FluxConcatMap.java:875)	at reactor.core.publisher.MonoCompletionStage$MonoCompletionStageSubscription.apply(MonoCompletionStage.java:122)	at reactor.core.publisher.MonoCompletionStage$MonoCompletionStageSubscription.apply(MonoCompletionStage.java:71)	at java.base/java.util.concurrent.CompletableFuture.uniHandle(Unknown Source)	at java.base/java.util.concurrent.CompletableFuture$UniHandle.tryFire(Unknown Source)	at java.base/java.util.concurrent.CompletableFuture.postComplete(Unknown Source)	at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(Unknown Source)	at com.github.jasync.sql.db.util.FutureUtilsKt.failed(FutureUtils.kt:18)	at com.github.jasync.sql.db.mysql.MySQLConnection$failQueryPromise$1.invoke(MySQLConnection.kt:418)	at com.github.jasync.sql.db.mysql.MySQLConnection$failQueryPromise$1.invoke(MySQLConnection.kt:417)	at com.github.jasync.sql.db.mysql.MySQLConnection.failQueryPromise$lambda$13(MySQLConnection.kt:417)	at java.base/java.util.Optional.ifPresent(Unknown Source)	at com.github.jasync.sql.db.mysql.MySQLConnection.failQueryPromise(MySQLConnection.kt:417)	at com.github.jasync.sql.db.mysql.MySQLConnection.setException(MySQLConnection.kt:218)	at com.github.jasync.sql.db.mysql.MySQLConnection.onError(MySQLConnection.kt:212)	at com.github.jasync.sql.db.mysql.codec.MySQLConnectionHandler.channelRead0(MySQLConnectionHandler.kt:128)	at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
t

Toshihiro Nakamura

10/29/2023, 1:22 PM
Thank you for sharing the stack trace of R2dbcBadGrammarException in the DM. There was a hint in the stack trace. Are you using MySQL 5 and trying to issue a DELETE statement? The DELETE statement in MySQL 5 does not support the AS clause.
Komapper supports MySQL version 8 and above.
d

dave08

10/29/2023, 1:23 PM
Yes, exactly!... So I guess I'll need to override that too (I already have one for upsert...)
Where did you see the hint?
It doesn't show anything about delete..
If it doesn't support that AS then the override would be a complete rewrite to avoid the alias... a bit more complicated than the upsert...
Ooh... it seems like this is not in the mysql dialect at all @Toshihiro Nakamura, is there really any way I can override this?
Before I wrote that override for upsert, I was using
executeScript
and it broke all my unit tests (that are mostly running under H2...), so overriding the upsert was VERY helpful, now if
delete
isn't overridable, I'm really stuck.
t

Toshihiro Nakamura

10/29/2023, 1:36 PM
You can override the
getEntityDeleteStatementBuilder
and
getRelationDeleteStatementBuilder
functions in
MySqlR2dbcDialect
. Inside the Builder returned from the functions, please use
TableNameType.NAME_ONLY
instead of
TableNameType.NAME_AND_ALIAS
.
d

dave08

10/29/2023, 1:54 PM
In both there's
Copy code
private val aliasManager =
    if (dialect.supportsAliasForDeleteStatement()) {
        DefaultAliasManager(context)
    } else {
        EmptyAliasManager
    }
maybe it's enough just to override
supportsAliasForDeleteStatement()
@Toshihiro Nakamura?
👍 1
Or maybe I'm not sure what you mean by:
Inside the Builder returned from the functions, please use
TableNameType.NAME_ONLY
instead of
TableNameType.NAME_AND_ALIAS
.
So far, I'd have this in my dialect:
Copy code
override fun <ENTITY : Any, ID : Any, META : EntityMetamodel<ENTITY, ID, META>> getEntityDeleteStatementBuilder(
        dialect: BuilderDialect,
        context: EntityDeleteContext<ENTITY, ID, META>,
        entity: ENTITY
    ): EntityDeleteStatementBuilder<ENTITY, ID, META> {
        return DefaultEntityDeleteStatementBuilder(dialect, context, entity)
    }

    override fun <ENTITY : Any, ID : Any, META : EntityMetamodel<ENTITY, ID, META>> getRelationDeleteStatementBuilder(
        dialect: BuilderDialect,
        context: RelationDeleteContext<ENTITY, ID, META>,
    ): RelationDeleteStatementBuilder<ENTITY, ID, META> {
        return RelationDeleteStatementBuilder(dialect, context)
    }
t

Toshihiro Nakamura

10/29/2023, 1:57 PM
That’s right, there is the
supportsAliasForDeleteStatement
function. Overriding that function should be sufficient.
d

dave08

10/29/2023, 1:58 PM
So basically just adding this to my dialect:
override fun supportsAliasForDeleteStatement(): Boolean = false
👍 1
Do you know of any other differences with 5.7? It might avoid me a bunch of surprises... Btw, so far, the way you built Komapper in such a flexible way is really nice 👌🏼!
Just tested that change in production, and it works! Thanks for the help!
Just a little thought, I don't think it would be too hard to have the existing Mysql dialect take a parameter in it's constructor
supportFor57
or something... these changes aren't too big (if they really are the only difference...) and they might be helpful for others... and it's not like providing a whole new dialect for those that still have that obsolete version of mysql... it could maybe even be flagged with some kind of experimental or deprecated annotation, to indicate that it won't really be supported.
Or maybe at least in a FAQ section in the docs, to copy and paste for those that need support for 5.7
Also, perhaps in the dialects page or other places, you should write the minimum versions of the dbs supported, so that others won't have this surprise...
t

Toshihiro Nakamura

11/03/2023, 4:17 AM
We will support MySQL 5.7 in the next release. https://github.com/komapper/komapper/pull/1108
👍🏼 1
d

dave08

11/15/2023, 12:16 PM
Any due date for this release? I'd really like to use it instead of my implementation... there's probably a bunch of things I missed.
t

Toshihiro Nakamura

11/15/2023, 12:43 PM
We plan to release by November 26. There is a need to write documentation.
d

dave08

11/15/2023, 12:45 PM
Oh... that's quite a bit of time... we need to release this to production in the next few days. I guess I'll have to hope for the best that my implementation will do the trick, thanks anyways for all this effort!
3 Views