Skip to content
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

Support NULL bind values of type UUID in R2DBC integration #15042

Closed
2 tasks done
lukaseder opened this issue May 8, 2023 · 1 comment
Closed
2 tasks done

Support NULL bind values of type UUID in R2DBC integration #15042

lukaseder opened this issue May 8, 2023 · 1 comment

Comments

@lukaseder
Copy link
Member

lukaseder commented May 8, 2023

When adding R2DBC tests for the YEAR type (#15035), I've noticed that the UUID type also isn't always supported by dialects, e.g. MariaDB:

org.jooq.exception.DataAccessException: SQL [null]; Error while writing value at R2DBC bind index: 1
	at org.jooq.impl.Tools.translate(Tools.java:3522)
	at org.jooq.impl.Tools.translate(Tools.java:3510)
	at org.jooq.impl.AbstractBindContext.bindValue(AbstractBindContext.java:77)
	at org.jooq.impl.Val.accept(Val.java:216)
	at org.jooq.impl.AbstractBindContext.bindInternal(AbstractBindContext.java:258)
	at org.jooq.impl.AbstractBindContext.visit0(AbstractBindContext.java:68)
	at org.jooq.impl.AbstractContext.visit(AbstractContext.java:354)
	at org.jooq.impl.QueryPartCollectionView.acceptElement(QueryPartCollectionView.java:256)
	at org.jooq.impl.QueryPartCollectionView.accept(QueryPartCollectionView.java:226)
	at org.jooq.impl.AbstractBindContext.bindInternal(AbstractBindContext.java:258)
	at org.jooq.impl.AbstractBindContext.visit0(AbstractBindContext.java:68)
	at org.jooq.impl.AbstractContext.visit(AbstractContext.java:354)
	at org.jooq.impl.R2DBC$QueryExecutionSubscriber.onNext0(R2DBC.java:430)
	at org.jooq.impl.R2DBC$ConnectionSubscriber.onNext(R2DBC.java:392)
	at org.jooq.impl.R2DBC$AbstractNonBlockingSubscription.lambda$1(R2DBC.java:583)
	at org.jooq.impl.Internal$1.onNext(Internal.java:486)
	at org.jooq.test.setup.DatabaseSetup$1.lambda$2(DatabaseSetup.java:398)
	at org.jooq.impl.Internal$1.onNext(Internal.java:486)
	at reactor.core.publisher.StrictSubscriber.onNext(StrictSubscriber.java:89)
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:129)
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondComplete(MonoFlatMap.java:245)
	at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:305)
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79)
	at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2545)
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:2341)
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onSubscribe(FluxOnErrorResume.java:74)
	at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:55)
	at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:165)
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79)
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondComplete(MonoFlatMap.java:245)
	at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:305)
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.complete(MonoIgnoreThen.java:292)
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onNext(MonoIgnoreThen.java:187)
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:236)
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:203)
	at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:89)
	at reactor.core.publisher.Operators$BaseFluxToMonoOperator.completePossiblyEmpty(Operators.java:2072)
	at reactor.core.publisher.MonoTakeLastOne$TakeLastOneSubscriber.onComplete(MonoTakeLastOne.java:162)
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onComplete(FluxMapFuseable.java:152)
	at reactor.core.publisher.FluxWindowPredicate$WindowPredicateMain.checkTerminated(FluxWindowPredicate.java:540)
	at reactor.core.publisher.FluxWindowPredicate$WindowPredicateMain.drainLoop(FluxWindowPredicate.java:488)
	at reactor.core.publisher.FluxWindowPredicate$WindowPredicateMain.drain(FluxWindowPredicate.java:432)
	at reactor.core.publisher.FluxWindowPredicate$WindowPredicateMain.onComplete(FluxWindowPredicate.java:312)
	at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onComplete(FluxContextWrite.java:126)
	at reactor.core.publisher.FluxCreate$BaseSink.complete(FluxCreate.java:460)
	at reactor.core.publisher.FluxCreate$BufferAsyncSink.drain(FluxCreate.java:805)
	at reactor.core.publisher.FluxCreate$BufferAsyncSink.complete(FluxCreate.java:753)
	at reactor.core.publisher.FluxCreate$SerializedFluxSink.drainLoop(FluxCreate.java:247)
	at reactor.core.publisher.FluxCreate$SerializedFluxSink.drain(FluxCreate.java:213)
	at reactor.core.publisher.FluxCreate$SerializedFluxSink.complete(FluxCreate.java:204)
	at org.mariadb.r2dbc.client.Exchange.emit(Exchange.java:69)
	at org.mariadb.r2dbc.client.SimpleClient$ServerMessageSubscriber.onNext(SimpleClient.java:646)
	at org.mariadb.r2dbc.client.SimpleClient$ServerMessageSubscriber.onNext(SimpleClient.java:589)
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79)
	at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:122)
	at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:292)
	at reactor.netty.channel.FluxReceive.onInboundNext(FluxReceive.java:401)
	at reactor.netty.channel.ChannelOperations.onInboundNext(ChannelOperations.java:411)
	at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:113)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:336)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:308)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:833)
	Suppressed: java.lang.Exception: #block terminated with an error
		at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:99)
		at reactor.core.publisher.Mono.block(Mono.java:1710)
		at org.jooq.test.all.testcases.R2DBCTests.lambda$15(R2DBCTests.java:418)
		at org.jooq.test.jOOQAbstractTest.withDSLContext(jOOQAbstractTest.java:2341)
		at org.jooq.test.jOOQAbstractTest.bindAndInlineWithDSLContexts(jOOQAbstractTest.java:2334)
		at org.jooq.test.BaseTest.bindAndInlineWithDSLContexts(BaseTest.java:2043)
		at org.jooq.test.all.testcases.R2DBCTests.testR2DBCFetchTypesUUID(R2DBCTests.java:412)
		at org.jooq.test.jOOQAbstractTest.testR2DBCFetchTypesUUID(jOOQAbstractTest.java:2973)
		at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
		at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
		at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
		at java.base/java.lang.reflect.Method.invoke(Method.java:568)
		at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
		at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
		at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
		at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
		at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
		at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
		at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:61)
		at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:61)
		at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
		at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
		at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
		at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
		at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
		at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
		at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
		at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
		at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
		at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
		at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
		at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
		at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
		at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
		at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:93)
		at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
		at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
		at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756)
		at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
		at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Caused by: java.sql.SQLException: Error while writing value at R2DBC bind index: 1
	at org.jooq.impl.DefaultBindContext.bindValue0(DefaultBindContext.java:77)
	at org.jooq.impl.AbstractBindContext.bindValue(AbstractBindContext.java:74)
	... 78 more
Caused by: org.jooq.impl.R2DBC$R2DBCGenericException
	at org.jooq.impl.R2DBC.wrapExceptions(R2DBC.java:869)
	at org.jooq.impl.R2DBC$R2DBCPreparedStatement.bindNull(R2DBC.java:917)
	at org.jooq.impl.R2DBC$R2DBCPreparedStatement.setNull(R2DBC.java:1000)
	at org.jooq.impl.DefaultBinding$InternalBinding.setNull0(DefaultBinding.java:1144)
	at org.jooq.impl.DefaultBinding$DefaultUUIDBinding.setNull0(DefaultBinding.java:4866)
	at org.jooq.impl.DefaultBinding$InternalBinding.set(DefaultBinding.java:1088)
	at org.jooq.impl.DefaultBindContext.bindValue0(DefaultBindContext.java:65)
	... 79 more
Caused by: java.lang.IllegalArgumentException: No encoder for class java.util.UUID (parameter at index 1) 
	at org.mariadb.r2dbc.codec.Codecs.codecByClass(Codecs.java:184)
	at org.mariadb.r2dbc.codec.Codecs.codecFromClass(Codecs.java:88)
	at org.mariadb.r2dbc.codec.Codecs.encodeNull(Codecs.java:58)
	at org.mariadb.r2dbc.MariadbCommonStatement.bindNull(MariadbCommonStatement.java:83)
	at org.mariadb.r2dbc.MariadbCommonStatement.bindNull(MariadbCommonStatement.java:23)
	at org.jooq.tools.r2dbc.LoggingStatement.bindNull(LoggingStatement.java:93)
	at org.jooq.impl.R2DBC$R2DBCPreparedStatement.lambda$2(R2DBC.java:927)
	at org.jooq.impl.R2DBC.wrapExceptions(R2DBC.java:861)
	... 85 more

Affected dialects include:

  • MariaDB
  • MySQL (the older R2DBC driver that is still being used with the 5.7 integration test)

Dialects with native support (or who simply ignore the class passed to bindNull()) include:

  • H2
  • Oracle
  • PostgreSQL
  • SQL Server
@lukaseder
Copy link
Member Author

Fixed in jOOQ 3.19.0, 3.18.4 (#15043), 3.17.13 (#15044), and 3.16.19 (#15045)

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

No branches or pull requests

1 participant