HHH-10885 - Fix JPA Native Queries with ordinal parameter is zero based
This commit is contained in:
parent
e99270c332
commit
92f5032cc0
|
@ -824,23 +824,9 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NativeQueryImplementor createNativeQuery(String sqlString) {
|
public NativeQueryImplementor createNativeQuery(String sqlString) {
|
||||||
checkOpen();
|
final NativeQueryImpl query = (NativeQueryImpl) createSQLQuery( sqlString );
|
||||||
checkTransactionSynchStatus();
|
query.setZeroBasedParametersIndex( false );
|
||||||
delayedAfterCompletion();
|
return query;
|
||||||
|
|
||||||
try {
|
|
||||||
NativeQueryImpl query = new NativeQueryImpl(
|
|
||||||
sqlString,
|
|
||||||
false,
|
|
||||||
this,
|
|
||||||
getFactory().getQueryPlanCache().getSQLParameterMetadata( sqlString )
|
|
||||||
);
|
|
||||||
query.setComment( "dynamic native SQL query" );
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
catch ( RuntimeException he ) {
|
|
||||||
throw exceptionConverter.convert( he );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -891,12 +877,31 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NativeQueryImplementor createSQLQuery(String queryString) {
|
public NativeQueryImplementor createSQLQuery(String queryString) {
|
||||||
return createNativeQuery( queryString );
|
checkOpen();
|
||||||
|
checkTransactionSynchStatus();
|
||||||
|
delayedAfterCompletion();
|
||||||
|
|
||||||
|
try {
|
||||||
|
NativeQueryImpl query = new NativeQueryImpl(
|
||||||
|
queryString,
|
||||||
|
false,
|
||||||
|
this,
|
||||||
|
getFactory().getQueryPlanCache().getSQLParameterMetadata( queryString )
|
||||||
|
);
|
||||||
|
query.setComment( "dynamic native SQL query" );
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
catch ( RuntimeException he ) {
|
||||||
|
throw exceptionConverter.convert( he );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NativeQueryImplementor getNamedSQLQuery(String name) {
|
public NativeQueryImplementor getNamedSQLQuery(String name) {
|
||||||
return getNamedNativeQuery( name );
|
final NativeQueryImpl nativeQuery = (NativeQueryImpl) getNamedNativeQuery( name );
|
||||||
|
nativeQuery.setZeroBasedParametersIndex( true );
|
||||||
|
return nativeQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,6 +15,7 @@ import javax.persistence.Parameter;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface ParameterMetadata {
|
public interface ParameterMetadata {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does this parameter set contain any named parameters?
|
* Does this parameter set contain any named parameters?
|
||||||
*
|
*
|
||||||
|
@ -52,4 +53,11 @@ public interface ParameterMetadata {
|
||||||
<T> QueryParameter<T> getQueryParameter(Integer position);
|
<T> QueryParameter<T> getQueryParameter(Integer position);
|
||||||
|
|
||||||
<T> QueryParameter<T> resolve(Parameter<T> param);
|
<T> QueryParameter<T> resolve(Parameter<T> param);
|
||||||
|
|
||||||
|
default boolean isOrdinalParametersZeroBased() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
default void setOrdinalParametersZeroBased(boolean isZeroBased) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,6 +121,10 @@ public class NativeQueryImpl<T> extends AbstractProducedQuery<T> implements Nati
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setZeroBasedParametersIndex(boolean zeroBasedParametersIndex) {
|
||||||
|
getParameterMetadata().setOrdinalParametersZeroBased( zeroBasedParametersIndex );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getQueryString() {
|
public String getQueryString() {
|
||||||
return sqlString;
|
return sqlString;
|
||||||
|
|
|
@ -31,6 +31,7 @@ public class ParameterMetadataImpl implements ParameterMetadata {
|
||||||
|
|
||||||
private final OrdinalParameterDescriptor[] ordinalDescriptors;
|
private final OrdinalParameterDescriptor[] ordinalDescriptors;
|
||||||
private final Map<String,NamedParameterDescriptor> namedDescriptorMap;
|
private final Map<String,NamedParameterDescriptor> namedDescriptorMap;
|
||||||
|
private boolean isOrdinalParametersZeroBased = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a ParameterMetadata container.
|
* Instantiates a ParameterMetadata container.
|
||||||
|
@ -116,6 +117,9 @@ public class ParameterMetadataImpl implements ParameterMetadata {
|
||||||
* @throws QueryParameterException If the position is out of range
|
* @throws QueryParameterException If the position is out of range
|
||||||
*/
|
*/
|
||||||
public OrdinalParameterDescriptor getOrdinalParameterDescriptor(int position) {
|
public OrdinalParameterDescriptor getOrdinalParameterDescriptor(int position) {
|
||||||
|
if ( !isOrdinalParametersZeroBased ) {
|
||||||
|
position--;
|
||||||
|
}
|
||||||
if ( position < 0 || position >= ordinalDescriptors.length ) {
|
if ( position < 0 || position >= ordinalDescriptors.length ) {
|
||||||
throw new QueryParameterException(
|
throw new QueryParameterException(
|
||||||
"Position beyond number of declared ordinal parameters. " +
|
"Position beyond number of declared ordinal parameters. " +
|
||||||
|
@ -239,4 +243,13 @@ public class ParameterMetadataImpl implements ParameterMetadata {
|
||||||
return getNamedParameterDescriptor( name ).getSourceLocations();
|
return getNamedParameterDescriptor( name ).getSourceLocations();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOrdinalParametersZeroBased() {
|
||||||
|
return isOrdinalParametersZeroBased;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOrdinalParametersZeroBased(boolean isZeroBased) {
|
||||||
|
this.isOrdinalParametersZeroBased = isZeroBased;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,31 +197,35 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryParameterBinding getBinding(int position) {
|
public QueryParameterBinding getBinding(int position) {
|
||||||
|
int positionAdjustment = 0;
|
||||||
|
if ( !parameterMetadata.isOrdinalParametersZeroBased() ) {
|
||||||
|
positionAdjustment = -1;
|
||||||
|
}
|
||||||
QueryParameterBinding binding = null;
|
QueryParameterBinding binding = null;
|
||||||
if ( parameterMetadata != null ) {
|
if ( parameterMetadata != null ) {
|
||||||
if ( ! parameterMetadata.hasPositionalParameters() ) {
|
if ( !parameterMetadata.hasPositionalParameters() ) {
|
||||||
// no positional parameters, assume jpa named.
|
// no positional parameters, assume jpa named.
|
||||||
binding = locateBinding( Integer.toString( position ) );
|
binding = locateBinding( Integer.toString( position ) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
if ( position < positionalParameterBindings.size() ) {
|
if ( position + positionAdjustment < positionalParameterBindings.size() ) {
|
||||||
binding = positionalParameterBindings.get( position );
|
binding = positionalParameterBindings.get( position + positionAdjustment );
|
||||||
if ( binding == null ) {
|
if ( binding == null ) {
|
||||||
binding = makeBinding( parameterMetadata.getQueryParameter( position ) );
|
binding = makeBinding( parameterMetadata.getQueryParameter( position ) );
|
||||||
positionalParameterBindings.set( position, binding );
|
positionalParameterBindings.set( position + positionAdjustment, binding );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for ( int i = 0; i < position - positionalParameterBindings.size(); i++ ) {
|
for ( int i = 0; i < position + positionAdjustment - positionalParameterBindings.size(); i++ ) {
|
||||||
positionalParameterBindings.add( null );
|
positionalParameterBindings.add( null );
|
||||||
}
|
}
|
||||||
QueryParameter queryParameter = parameterMetadata.getQueryParameter( position );
|
QueryParameter queryParameter = parameterMetadata.getQueryParameter( position );
|
||||||
binding = makeBinding( queryParameter );
|
binding = makeBinding( queryParameter );
|
||||||
positionalParameterBindings.add( binding );
|
positionalParameterBindings.add( binding );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch ( QueryParameterException e ) {
|
catch (QueryParameterException e) {
|
||||||
// treat this as null binding
|
// treat this as null binding
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -247,8 +251,18 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// verify position parameters bound
|
// verify position parameters bound
|
||||||
for ( int i = 0; i < positionalParameterBindings.size(); i++ ) {
|
int startIndex = 0;
|
||||||
final QueryParameterBinding binding = positionalParameterBindings.get( i );
|
if ( !parameterMetadata.isOrdinalParametersZeroBased() ) {
|
||||||
|
startIndex = 1;
|
||||||
|
}
|
||||||
|
for ( int i = startIndex; i < positionalParameterBindings.size(); i++ ) {
|
||||||
|
QueryParameterBinding binding = null;
|
||||||
|
if ( parameterMetadata.isOrdinalParametersZeroBased() ) {
|
||||||
|
binding = positionalParameterBindings.get( i );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
binding = positionalParameterBindings.get( i - 1 );
|
||||||
|
}
|
||||||
if ( binding == null || !binding.isBound() ) {
|
if ( binding == null || !binding.isBound() ) {
|
||||||
throw new QueryException( "Positional parameter [" + i + "] not set" );
|
throw new QueryException( "Positional parameter [" + i + "] not set" );
|
||||||
}
|
}
|
||||||
|
@ -282,7 +296,6 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
|
||||||
if ( bindType == null ) {
|
if ( bindType == null ) {
|
||||||
bindType = SerializableType.INSTANCE;
|
bindType = SerializableType.INSTANCE;
|
||||||
}
|
}
|
||||||
Object object = binding.getBindValue();
|
|
||||||
positionalValueSpan += bindType.getColumnSpan( sessionFactory );
|
positionalValueSpan += bindType.getColumnSpan( sessionFactory );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue