diff --git a/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java b/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java index 67352020a0..d1826ceb31 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java @@ -824,23 +824,9 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont @Override public NativeQueryImplementor createNativeQuery(String sqlString) { - checkOpen(); - checkTransactionSynchStatus(); - delayedAfterCompletion(); - - 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 ); - } + final NativeQueryImpl query = (NativeQueryImpl) createSQLQuery( sqlString ); + query.setZeroBasedParametersIndex( false ); + return query; } @Override @@ -891,12 +877,31 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont @Override 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 public NativeQueryImplementor getNamedSQLQuery(String name) { - return getNamedNativeQuery( name ); + final NativeQueryImpl nativeQuery = (NativeQueryImpl) getNamedNativeQuery( name ); + nativeQuery.setZeroBasedParametersIndex( true ); + return nativeQuery; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/ParameterMetadata.java b/hibernate-core/src/main/java/org/hibernate/query/ParameterMetadata.java index 987e75f5d3..cd3a2ded15 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/ParameterMetadata.java +++ b/hibernate-core/src/main/java/org/hibernate/query/ParameterMetadata.java @@ -15,6 +15,7 @@ import javax.persistence.Parameter; * @author Steve Ebersole */ public interface ParameterMetadata { + /** * Does this parameter set contain any named parameters? * @@ -52,4 +53,11 @@ public interface ParameterMetadata { QueryParameter getQueryParameter(Integer position); QueryParameter resolve(Parameter param); + + default boolean isOrdinalParametersZeroBased() { + return true; + } + + default void setOrdinalParametersZeroBased(boolean isZeroBased) { + } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/NativeQueryImpl.java b/hibernate-core/src/main/java/org/hibernate/query/internal/NativeQueryImpl.java index b08c3c393f..6980a26e04 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/NativeQueryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/NativeQueryImpl.java @@ -121,6 +121,10 @@ public class NativeQueryImpl extends AbstractProducedQuery implements Nati return this; } + public void setZeroBasedParametersIndex(boolean zeroBasedParametersIndex) { + getParameterMetadata().setOrdinalParametersZeroBased( zeroBasedParametersIndex ); + } + @Override public String getQueryString() { return sqlString; diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/ParameterMetadataImpl.java b/hibernate-core/src/main/java/org/hibernate/query/internal/ParameterMetadataImpl.java index 1a17b914a3..f560ec2e82 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/ParameterMetadataImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/ParameterMetadataImpl.java @@ -31,6 +31,7 @@ public class ParameterMetadataImpl implements ParameterMetadata { private final OrdinalParameterDescriptor[] ordinalDescriptors; private final Map namedDescriptorMap; + private boolean isOrdinalParametersZeroBased = true; /** * Instantiates a ParameterMetadata container. @@ -116,6 +117,9 @@ public class ParameterMetadataImpl implements ParameterMetadata { * @throws QueryParameterException If the position is out of range */ public OrdinalParameterDescriptor getOrdinalParameterDescriptor(int position) { + if ( !isOrdinalParametersZeroBased ) { + position--; + } if ( position < 0 || position >= ordinalDescriptors.length ) { throw new QueryParameterException( "Position beyond number of declared ordinal parameters. " + @@ -239,4 +243,13 @@ public class ParameterMetadataImpl implements ParameterMetadata { return getNamedParameterDescriptor( name ).getSourceLocations(); } + @Override + public boolean isOrdinalParametersZeroBased() { + return isOrdinalParametersZeroBased; + } + + @Override + public void setOrdinalParametersZeroBased(boolean isZeroBased) { + this.isOrdinalParametersZeroBased = isZeroBased; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingsImpl.java b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingsImpl.java index 4a4533efbd..fa4e51fc33 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingsImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingsImpl.java @@ -197,31 +197,35 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings { } public QueryParameterBinding getBinding(int position) { + int positionAdjustment = 0; + if ( !parameterMetadata.isOrdinalParametersZeroBased() ) { + positionAdjustment = -1; + } QueryParameterBinding binding = null; if ( parameterMetadata != null ) { - if ( ! parameterMetadata.hasPositionalParameters() ) { + if ( !parameterMetadata.hasPositionalParameters() ) { // no positional parameters, assume jpa named. binding = locateBinding( Integer.toString( position ) ); } else { try { - if ( position < positionalParameterBindings.size() ) { - binding = positionalParameterBindings.get( position ); + if ( position + positionAdjustment < positionalParameterBindings.size() ) { + binding = positionalParameterBindings.get( position + positionAdjustment ); if ( binding == null ) { - binding = makeBinding( parameterMetadata.getQueryParameter( position ) ); - positionalParameterBindings.set( position, binding ); + binding = makeBinding( parameterMetadata.getQueryParameter( position ) ); + positionalParameterBindings.set( position + positionAdjustment, binding ); } } else { - for ( int i = 0; i < position - positionalParameterBindings.size(); i++ ) { + for ( int i = 0; i < position + positionAdjustment - positionalParameterBindings.size(); i++ ) { positionalParameterBindings.add( null ); } - QueryParameter queryParameter = parameterMetadata.getQueryParameter( position ); + QueryParameter queryParameter = parameterMetadata.getQueryParameter( position ); binding = makeBinding( queryParameter ); positionalParameterBindings.add( binding ); } } - catch ( QueryParameterException e ) { + catch (QueryParameterException e) { // treat this as null binding } } @@ -247,8 +251,18 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings { } } // verify position parameters bound - for ( int i = 0; i < positionalParameterBindings.size(); i++ ) { - final QueryParameterBinding binding = positionalParameterBindings.get( i ); + int startIndex = 0; + 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() ) { throw new QueryException( "Positional parameter [" + i + "] not set" ); } @@ -282,7 +296,6 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings { if ( bindType == null ) { bindType = SerializableType.INSTANCE; } - Object object = binding.getBindValue(); positionalValueSpan += bindType.getColumnSpan( sessionFactory ); } }