Wrong NativeQueryImpl.setZeroBasedParametersIndex when Session#createSQLQuery is executed after EM#createNativeQuery

Description

Calling EntityManager.createNativeQuery calls NativeQueryImpl.setZeroBasedParametersIndex, which in turn calls ParameterMetadataImpl.setOrdinalParametersZeroBased(false). ParameterMetadataImpl is shared between threads for all sessions, and so one thread is getting the 'true' version of isZeroBasedParametersIndex(). It probably happens the first time 2 EntityManager objects on different threads try to run the query at the same time.

EntityManager is being used on a single thread. I can't easily reproduce this, except in a specific integration test while playing with setOrdinalParametersZeroBased. It happened in Confluence while deleting a space for a user one time after running in production for all instances in Confluence Cloud for 9 hours.

Positional parameter [0] not set
at org.hibernate.query.internal.QueryParameterBindingsImpl.verifyParametersBound(QueryParameterBindingsImpl.java:255)
at org.hibernate.query.internal.AbstractProducedQuery.beforeQuery(AbstractProducedQuery.java:1307)
at org.hibernate.query.internal.NativeQueryImpl.beforeQuery(NativeQueryImpl.java:222)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1396)

Environment

Linux, multi-core processor

Activity

Show:
Clinton Volzke
September 22, 2016, 10:33 PM
Edited

@Andrea No. That's a related, but different bug (and fixing it may fix this one anyway..). This bug is a race condition - it happens when two threads call createNativeQuery with the same query, but no threads call createSQLQuery.

Andrea Boriero
September 23, 2016, 7:18 AM
Edited

Hi ,

I think the problem is not specific to a race condition but it's related to the fact that The ParameterMetadataImpl is cached by QueryPlanCache with isZeroBasedParametersIndex value to false and then the same query it's executed but this time it needs isZeroBasedParametersIndex to true.

Clinton Volzke
September 23, 2016, 7:36 AM

It's not limited to a race condition, but it was caused by a race condition in our case. Below is the query, which uses EM.createNativeQuery (only) and so needs isZeroBasedParametersIndex=false (only). Despite being run 1000s of times in a large cloud application, the error only happened once.

Looking at AbstractSharedSessionContract.createNativeQuery(), the race condition could manifest on the 1st and 2nd query (same query run on different threads), or the two queries run after a query plan is evicted from QueryPlanCache.queryPlanCache which is a BoundedConcurrentHashMap.

Andrea Boriero
September 23, 2016, 7:55 AM

what is strange is that if entityManager.createNativeQuery is executed and the isZeroBasedParametersIndex is true instead of false the error message is
java.lang.IllegalArgumentException: Unknown parameter position: 1

Andrea Boriero
September 23, 2016, 9:46 AM

i noticed this also can cause an error

I changed the PR, now the QueryPlanChache#getSQLParameterMetadata(final String query) returns a copy of the ParameterMetadata;

Assignee

Andrea Boriero

Reporter

ClintonV

Fix versions

Labels

None

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

Pull Request

None

backportDecision

None

Affects versions

Priority

Major
Configure