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

Statement.returnGeneratedValues() leads to NullPointerException upon INSERT that does not generate keys #63

Closed
mp911de opened this issue Jan 26, 2022 · 3 comments

Comments

@mp911de
Copy link

mp911de commented Jan 26, 2022

With version 0.4.0, calling returnGeneratedValues() upon an insert leads to a NullPointerException. Omitting returnGeneratedValues() does not raise the exception.

DDL:

CREATE TABLE legoset (
    id          INTEGER PRIMARY KEY,
    version     INTEGER NULL,
    name        VARCHAR2(255) NOT NULL,
    manual      INTEGER NULL,
    cert        RAW(255) NULL
)

Statement:

INSERT INTO legoset (ID, NAME, MANUAL) VALUES (:P0_id, :P1_name, :P2_manual)

Code to reproduce:

ConnectionFactory connectionFactory = ConnectionFactories.get(options);

Connection connection = Mono.from(connectionFactory.create()).block();

Flux.from(connection.createStatement("DROP TABLE legoset").execute())
		.flatMap(Result::getRowsUpdated).onErrorResume(it -> Mono.empty()).blockLast();

String CREATE_TABLE_LEGOSET = "CREATE TABLE legoset (\n" //
	+ "    id          INTEGER PRIMARY KEY,\n" //
	+ "    version     INTEGER NULL,\n" //
	+ "    name        VARCHAR2(255) NOT NULL,\n" //
	+ "    manual      INTEGER NULL,\n" //
	+ "    cert        RAW(255) NULL\n" //
	+ ")";

Flux.from(connection.createStatement(CREATE_TABLE_LEGOSET).execute())
		.flatMap(Result::getRowsUpdated).blockLast();


Flux.from(connection.createStatement("INSERT INTO legoset (ID, NAME, MANUAL) VALUES (:P0_id, :P1_name, :P2_manual)")
				.bind("P0_id", 42055)
				.bind("P1_name", "SCHAUFELRADBAGGER")
				.bind("P2_manual", 12)
				.returnGeneratedValues()
				.execute()).flatMap(Result::getRowsUpdated)
		.blockLast();

Stack trace:

java.lang.NullPointerException
	at oracle.jdbc.driver.OracleStatement.getMoreResults(OracleStatement.java:5851)
	at oracle.jdbc.driver.OracleStatementWrapper.getMoreResults(OracleStatementWrapper.java:298)
	at oracle.r2dbc.impl.OracleStatementImpl$JdbcReturningGenerated.lambda$executeJdbc$0(OracleStatementImpl.java:1582)
	at oracle.r2dbc.impl.AsyncLock.lambda$get$2(AsyncLock.java:161)
	at oracle.r2dbc.impl.AsyncLock.unlock(AsyncLock.java:122)
	at oracle.r2dbc.impl.AsyncLock$UsingConnectionSubscriber.terminate(AsyncLock.java:510)
	at oracle.r2dbc.impl.AsyncLock$UsingConnectionSubscriber.onComplete(AsyncLock.java:496)
	at reactor.core.publisher.StrictSubscriber.onComplete(StrictSubscriber.java:123)
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onComplete(Operators.java:2058)
	at org.reactivestreams.FlowAdapters$FlowToReactiveSubscriber.onComplete(FlowAdapters.java:228)
	at oracle.jdbc.internal.CompletionStageUtil$IteratorSubscription.emitComplete(CompletionStageUtil.java:681)
	at oracle.jdbc.internal.CompletionStageUtil$IteratorSubscription.emitItems(CompletionStageUtil.java:628)
	at oracle.jdbc.driver.PhysicalConnection.lambda$createUserCodeExecutor$10(PhysicalConnection.java:11713)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at oracle.jdbc.driver.PhysicalConnection.lambda$createUserCodeExecutor$11(PhysicalConnection.java:11711)
	at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1426)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177)
	Suppressed: java.lang.Exception: #block terminated with an error
		at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:99)
		at reactor.core.publisher.Flux.blockLast(Flux.java:2645)
		at org.springframework.data.r2dbc.core.Repro.reproducer(Repro.java:86)
		at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
		at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
		at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
		at java.base/java.lang.reflect.Method.invoke(Method.java:566)
		at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
		at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
		at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
		at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
		at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
@Michael-A-McMahon
Copy link
Member

This looks like a bug that was present in Oracle JDBC 21.1, and was fixed for 21.3. Do you know which version is on your classpath? Our pom.xml should have it as 21.3.0.0

@mp911de
Copy link
Author

mp911de commented Jan 26, 2022

Thanks for the pointer, I think I'm using an outdated Oracle JDBC version. I'll retest tomorrow and likely I'm going to close the issue then.

@mp911de
Copy link
Author

mp911de commented Jan 27, 2022

Upgrading to 21.4.0.0.1 let the issue go away. Thanks for your guidance. Closing the ticket.

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

No branches or pull requests

2 participants