HHH-17314 - Add a configuration option to ignore jdbc parameters in native queries
Signed-off-by: Jan Schatteman <jschatte@redhat.com>
This commit is contained in:
parent
ffee08d853
commit
763a70f633
|
@ -248,6 +248,7 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
||||||
private TimeZone jdbcTimeZone;
|
private TimeZone jdbcTimeZone;
|
||||||
private final ValueHandlingMode criteriaValueHandlingMode;
|
private final ValueHandlingMode criteriaValueHandlingMode;
|
||||||
private final boolean criteriaCopyTreeEnabled;
|
private final boolean criteriaCopyTreeEnabled;
|
||||||
|
private final boolean nativeJdbcParametersIgnored;
|
||||||
private final ImmutableEntityUpdateQueryHandlingMode immutableEntityUpdateQueryHandlingMode;
|
private final ImmutableEntityUpdateQueryHandlingMode immutableEntityUpdateQueryHandlingMode;
|
||||||
// These two settings cannot be modified from the builder,
|
// These two settings cannot be modified from the builder,
|
||||||
// in order to maintain consistency.
|
// in order to maintain consistency.
|
||||||
|
@ -551,6 +552,12 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
||||||
jpaBootstrap
|
jpaBootstrap
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.nativeJdbcParametersIgnored = getBoolean(
|
||||||
|
AvailableSettings.NATIVE_IGNORE_JDBC_PARAMETERS,
|
||||||
|
configurationSettings,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
// added the boolean parameter in case we want to define some form of "all" as discussed
|
// added the boolean parameter in case we want to define some form of "all" as discussed
|
||||||
this.jpaCompliance = context.getJpaCompliance();
|
this.jpaCompliance = context.getJpaCompliance();
|
||||||
|
|
||||||
|
@ -1145,6 +1152,11 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
||||||
return criteriaCopyTreeEnabled;
|
return criteriaCopyTreeEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getNativeJdbcParametersIgnored() {
|
||||||
|
return nativeJdbcParametersIgnored;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImmutableEntityUpdateQueryHandlingMode getImmutableEntityUpdateQueryHandlingMode() {
|
public ImmutableEntityUpdateQueryHandlingMode getImmutableEntityUpdateQueryHandlingMode() {
|
||||||
return immutableEntityUpdateQueryHandlingMode;
|
return immutableEntityUpdateQueryHandlingMode;
|
||||||
|
|
|
@ -382,6 +382,10 @@ public class AbstractDelegatingSessionFactoryOptions implements SessionFactoryOp
|
||||||
return delegate.isCriteriaCopyTreeEnabled();
|
return delegate.isCriteriaCopyTreeEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getNativeJdbcParametersIgnored() {
|
||||||
|
return delegate.getNativeJdbcParametersIgnored();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JpaCompliance getJpaCompliance() {
|
public JpaCompliance getJpaCompliance() {
|
||||||
return delegate.getJpaCompliance();
|
return delegate.getJpaCompliance();
|
||||||
|
|
|
@ -231,6 +231,13 @@ public interface SessionFactoryOptions extends QueryEngineOptions {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.hibernate.cfg.AvailableSettings#NATIVE_IGNORE_JDBC_PARAMETERS
|
||||||
|
*/
|
||||||
|
default boolean getNativeJdbcParametersIgnored() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
JpaCompliance getJpaCompliance();
|
JpaCompliance getJpaCompliance();
|
||||||
|
|
||||||
boolean isFailOnPaginationOverCollectionFetchEnabled();
|
boolean isFailOnPaginationOverCollectionFetchEnabled();
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.cfg;
|
package org.hibernate.cfg;
|
||||||
|
|
||||||
|
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||||
import org.hibernate.query.NullPrecedence;
|
import org.hibernate.query.NullPrecedence;
|
||||||
import org.hibernate.query.spi.QueryPlan;
|
import org.hibernate.query.spi.QueryPlan;
|
||||||
|
|
||||||
|
@ -124,6 +125,16 @@ public interface QuerySettings {
|
||||||
*/
|
*/
|
||||||
String CRITERIA_COPY_TREE = "hibernate.criteria.copy_tree";
|
String CRITERIA_COPY_TREE = "hibernate.criteria.copy_tree";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When set to true, indicates that ordinal parameters (represented by the '?' placeholder) in native queries will be ignored.
|
||||||
|
* <p>
|
||||||
|
* By default, this is set to false, i.e. native queries will be checked for ordinal placeholders.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* @see SessionFactoryOptions#getIgnoreNativeJdbcParameters()
|
||||||
|
*/
|
||||||
|
String NATIVE_IGNORE_JDBC_PARAMETERS = "hibernate.query.native.ignore_jdbc_parameters";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When {@linkplain org.hibernate.query.Query#setMaxResults(int) pagination} is used
|
* When {@linkplain org.hibernate.query.Query#setMaxResults(int) pagination} is used
|
||||||
* in combination with a {@code fetch join} applied to a collection or many-valued
|
* in combination with a {@code fetch join} applied to a collection or many-valued
|
||||||
|
|
|
@ -21,11 +21,17 @@ public class NativeQueryInterpreterStandardImpl implements NativeQueryInterprete
|
||||||
/**
|
/**
|
||||||
* Singleton access
|
* Singleton access
|
||||||
*/
|
*/
|
||||||
public static final NativeQueryInterpreterStandardImpl NATIVE_QUERY_INTERPRETER = new NativeQueryInterpreterStandardImpl();
|
public static final NativeQueryInterpreterStandardImpl NATIVE_QUERY_INTERPRETER = new NativeQueryInterpreterStandardImpl( false );
|
||||||
|
|
||||||
|
private boolean nativeJdbcParametersIgnored;
|
||||||
|
|
||||||
|
public NativeQueryInterpreterStandardImpl(boolean nativeJdbcParametersIgnored) {
|
||||||
|
this.nativeJdbcParametersIgnored = nativeJdbcParametersIgnored;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void recognizeParameters(String nativeQuery, ParameterRecognizer recognizer) {
|
public void recognizeParameters(String nativeQuery, ParameterRecognizer recognizer) {
|
||||||
ParameterParser.parse( nativeQuery, recognizer );
|
ParameterParser.parse( nativeQuery, recognizer, nativeJdbcParametersIgnored );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -21,7 +21,7 @@ public class NativeQueryInterpreterInitiator implements SessionFactoryServiceIni
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NativeQueryInterpreter initiateService(SessionFactoryServiceInitiatorContext context) {
|
public NativeQueryInterpreter initiateService(SessionFactoryServiceInitiatorContext context) {
|
||||||
return new NativeQueryInterpreterStandardImpl();
|
return new NativeQueryInterpreterStandardImpl( context.getSessionFactoryOptions().getNativeJdbcParametersIgnored() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -240,6 +240,16 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
|
||||||
return delegate.isCriteriaCopyTreeEnabled();
|
return delegate.isCriteriaCopyTreeEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getNativeJdbcParametersIgnored() {
|
||||||
|
return delegate.getNativeJdbcParametersIgnored();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNativeJdbcParametersIgnored(boolean nativeJdbcParametersIgnored) {
|
||||||
|
delegate.setNativeJdbcParametersIgnored( nativeJdbcParametersIgnored );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isOpen() {
|
public boolean isOpen() {
|
||||||
return delegate.isOpen();
|
return delegate.isOpen();
|
||||||
|
|
|
@ -381,6 +381,10 @@ public interface SharedSessionContractImplementor
|
||||||
|
|
||||||
boolean isCriteriaCopyTreeEnabled();
|
boolean isCriteriaCopyTreeEnabled();
|
||||||
|
|
||||||
|
boolean getNativeJdbcParametersIgnored();
|
||||||
|
|
||||||
|
void setNativeJdbcParametersIgnored(boolean nativeJdbcParametersIgnored);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current {@link FlushModeType} for this session.
|
* Get the current {@link FlushModeType} for this session.
|
||||||
* <p>
|
* <p>
|
||||||
|
|
|
@ -474,6 +474,16 @@ public class SharedSessionDelegatorBaseImpl implements SharedSessionContractImpl
|
||||||
return delegate.isCriteriaCopyTreeEnabled();
|
return delegate.isCriteriaCopyTreeEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getNativeJdbcParametersIgnored() {
|
||||||
|
return delegate.getNativeJdbcParametersIgnored();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNativeJdbcParametersIgnored(boolean nativeJdbcParametersIgnored) {
|
||||||
|
delegate.setNativeJdbcParametersIgnored( nativeJdbcParametersIgnored );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FlushModeType getFlushMode() {
|
public FlushModeType getFlushMode() {
|
||||||
return delegate.getFlushMode();
|
return delegate.getFlushMode();
|
||||||
|
|
|
@ -162,6 +162,8 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
||||||
|
|
||||||
private boolean criteriaCopyTreeEnabled;
|
private boolean criteriaCopyTreeEnabled;
|
||||||
|
|
||||||
|
private boolean nativeJdbcParametersIgnored;
|
||||||
|
|
||||||
protected boolean closed;
|
protected boolean closed;
|
||||||
protected boolean waitingForAutoClose;
|
protected boolean waitingForAutoClose;
|
||||||
|
|
||||||
|
@ -183,6 +185,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
||||||
sessionEventsManager = createSessionEventsManager(options);
|
sessionEventsManager = createSessionEventsManager(options);
|
||||||
entityNameResolver = new CoordinatingEntityNameResolver( factory, interceptor );
|
entityNameResolver = new CoordinatingEntityNameResolver( factory, interceptor );
|
||||||
setCriteriaCopyTreeEnabled( factory.getSessionFactoryOptions().isCriteriaCopyTreeEnabled() );
|
setCriteriaCopyTreeEnabled( factory.getSessionFactoryOptions().isCriteriaCopyTreeEnabled() );
|
||||||
|
setNativeJdbcParametersIgnored( factory.getSessionFactoryOptions().getNativeJdbcParametersIgnored() );
|
||||||
|
|
||||||
final StatementInspector statementInspector = interpret( options.getStatementInspector() );
|
final StatementInspector statementInspector = interpret( options.getStatementInspector() );
|
||||||
|
|
||||||
|
@ -701,6 +704,16 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
||||||
return criteriaCopyTreeEnabled;
|
return criteriaCopyTreeEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getNativeJdbcParametersIgnored() {
|
||||||
|
return nativeJdbcParametersIgnored;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNativeJdbcParametersIgnored(boolean nativeJdbcParametersIgnored) {
|
||||||
|
this.nativeJdbcParametersIgnored = nativeJdbcParametersIgnored;
|
||||||
|
}
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// dynamic HQL handling
|
// dynamic HQL handling
|
||||||
|
|
||||||
|
|
|
@ -173,55 +173,6 @@ public class NativeQueryImpl<R>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
private interface ResultSetMappingHandler {
|
|
||||||
boolean resolveResultSetMapping(
|
|
||||||
ResultSetMapping resultSetMapping,
|
|
||||||
Consumer<String> querySpaceConsumer,
|
|
||||||
ResultSetMappingResolutionContext context);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ResultSetMapping buildResultSetMapping(
|
|
||||||
String registeredName,
|
|
||||||
boolean isDynamic,
|
|
||||||
SharedSessionContractImplementor session) {
|
|
||||||
return ResultSetMapping.resolveResultSetMapping( registeredName, isDynamic, session.getFactory() );
|
|
||||||
}
|
|
||||||
|
|
||||||
public NativeQueryImpl(
|
|
||||||
NamedNativeQueryMemento memento,
|
|
||||||
Supplier<ResultSetMapping> resultSetMappingCreator,
|
|
||||||
ResultSetMappingHandler resultSetMappingHandler,
|
|
||||||
SharedSessionContractImplementor session) {
|
|
||||||
super( session );
|
|
||||||
|
|
||||||
this.originalSqlString = memento.getOriginalSqlString();
|
|
||||||
|
|
||||||
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation(
|
|
||||||
originalSqlString,
|
|
||||||
session
|
|
||||||
);
|
|
||||||
|
|
||||||
this.sqlString = parameterInterpretation.getAdjustedSqlString();
|
|
||||||
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
|
|
||||||
this.parameterOccurrences = parameterInterpretation.getOrderedParameterOccurrences();
|
|
||||||
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
|
|
||||||
this.querySpaces = new HashSet<>();
|
|
||||||
|
|
||||||
this.resultSetMapping = resultSetMappingCreator.get();
|
|
||||||
|
|
||||||
//noinspection UnnecessaryLocalVariable
|
|
||||||
final boolean appliedAnyResults = resultSetMappingHandler.resolveResultSetMapping(
|
|
||||||
resultSetMapping,
|
|
||||||
querySpaces::add,
|
|
||||||
this
|
|
||||||
);
|
|
||||||
|
|
||||||
this.resultMappingSuppliedToCtor = appliedAnyResults;
|
|
||||||
|
|
||||||
applyOptions( memento );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a NativeQueryImpl given a sql query defined in the mappings.
|
* Constructs a NativeQueryImpl given a sql query defined in the mappings.
|
||||||
*/
|
*/
|
||||||
|
@ -306,6 +257,40 @@ public class NativeQueryImpl<R>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NativeQueryImpl(
|
||||||
|
NamedNativeQueryMemento memento,
|
||||||
|
Supplier<ResultSetMapping> resultSetMappingCreator,
|
||||||
|
ResultSetMappingHandler resultSetMappingHandler,
|
||||||
|
SharedSessionContractImplementor session) {
|
||||||
|
super( session );
|
||||||
|
|
||||||
|
this.originalSqlString = memento.getOriginalSqlString();
|
||||||
|
|
||||||
|
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation(
|
||||||
|
originalSqlString,
|
||||||
|
session
|
||||||
|
);
|
||||||
|
|
||||||
|
this.sqlString = parameterInterpretation.getAdjustedSqlString();
|
||||||
|
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
|
||||||
|
this.parameterOccurrences = parameterInterpretation.getOrderedParameterOccurrences();
|
||||||
|
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
|
||||||
|
this.querySpaces = new HashSet<>();
|
||||||
|
|
||||||
|
this.resultSetMapping = resultSetMappingCreator.get();
|
||||||
|
|
||||||
|
//noinspection UnnecessaryLocalVariable
|
||||||
|
final boolean appliedAnyResults = resultSetMappingHandler.resolveResultSetMapping(
|
||||||
|
resultSetMapping,
|
||||||
|
querySpaces::add,
|
||||||
|
this
|
||||||
|
);
|
||||||
|
|
||||||
|
this.resultMappingSuppliedToCtor = appliedAnyResults;
|
||||||
|
|
||||||
|
applyOptions( memento );
|
||||||
|
}
|
||||||
|
|
||||||
public NativeQueryImpl(
|
public NativeQueryImpl(
|
||||||
String sqlString,
|
String sqlString,
|
||||||
NamedResultSetMappingMemento resultSetMappingMemento,
|
NamedResultSetMappingMemento resultSetMappingMemento,
|
||||||
|
@ -331,6 +316,37 @@ public class NativeQueryImpl<R>
|
||||||
this.resultMappingSuppliedToCtor = true;
|
this.resultMappingSuppliedToCtor = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NativeQueryImpl(String sqlString, SharedSessionContractImplementor session) {
|
||||||
|
super( session );
|
||||||
|
|
||||||
|
this.querySpaces = new HashSet<>();
|
||||||
|
|
||||||
|
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( sqlString, session );
|
||||||
|
this.originalSqlString = sqlString;
|
||||||
|
this.sqlString = parameterInterpretation.getAdjustedSqlString();
|
||||||
|
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
|
||||||
|
this.parameterOccurrences = parameterInterpretation.getOrderedParameterOccurrences();
|
||||||
|
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
|
||||||
|
|
||||||
|
this.resultSetMapping = ResultSetMapping.resolveResultSetMapping( sqlString, true, session.getFactory() );
|
||||||
|
this.resultMappingSuppliedToCtor = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
private interface ResultSetMappingHandler {
|
||||||
|
boolean resolveResultSetMapping(
|
||||||
|
ResultSetMapping resultSetMapping,
|
||||||
|
Consumer<String> querySpaceConsumer,
|
||||||
|
ResultSetMappingResolutionContext context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ResultSetMapping buildResultSetMapping(
|
||||||
|
String registeredName,
|
||||||
|
boolean isDynamic,
|
||||||
|
SharedSessionContractImplementor session) {
|
||||||
|
return ResultSetMapping.resolveResultSetMapping( registeredName, isDynamic, session.getFactory() );
|
||||||
|
}
|
||||||
|
|
||||||
public List<ParameterOccurrence> getParameterOccurrences() {
|
public List<ParameterOccurrence> getParameterOccurrences() {
|
||||||
return parameterOccurrences;
|
return parameterOccurrences;
|
||||||
}
|
}
|
||||||
|
@ -374,22 +390,6 @@ public class NativeQueryImpl<R>
|
||||||
// todo (6.0) : query returns
|
// todo (6.0) : query returns
|
||||||
}
|
}
|
||||||
|
|
||||||
public NativeQueryImpl(String sqlString, SharedSessionContractImplementor session) {
|
|
||||||
super( session );
|
|
||||||
|
|
||||||
this.querySpaces = new HashSet<>();
|
|
||||||
|
|
||||||
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( sqlString, session );
|
|
||||||
this.originalSqlString = sqlString;
|
|
||||||
this.sqlString = parameterInterpretation.getAdjustedSqlString();
|
|
||||||
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
|
|
||||||
this.parameterOccurrences = parameterInterpretation.getOrderedParameterOccurrences();
|
|
||||||
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
|
|
||||||
|
|
||||||
this.resultSetMapping = ResultSetMapping.resolveResultSetMapping( sqlString, true, session.getFactory() );
|
|
||||||
this.resultMappingSuppliedToCtor = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IllegalArgumentException buildIncompatibleException(Class<?> resultClass, Class<?> actualResultClass) {
|
private IllegalArgumentException buildIncompatibleException(Class<?> resultClass, Class<?> actualResultClass) {
|
||||||
final String resultClassName = resultClass.getName();
|
final String resultClassName = resultClass.getName();
|
||||||
final String actualResultClassName = actualResultClass.getName();
|
final String actualResultClassName = actualResultClass.getName();
|
||||||
|
|
|
@ -47,9 +47,10 @@ public class ParameterParser {
|
||||||
*
|
*
|
||||||
* @param sqlString The string to be parsed/tokenized.
|
* @param sqlString The string to be parsed/tokenized.
|
||||||
* @param recognizer The thing which handles recognition events.
|
* @param recognizer The thing which handles recognition events.
|
||||||
|
* @param nativeJdbcParametersIgnored Whether to ignore ordinal parameters in native queries or not.
|
||||||
* @throws QueryException Indicates unexpected parameter conditions.
|
* @throws QueryException Indicates unexpected parameter conditions.
|
||||||
*/
|
*/
|
||||||
public static void parse(String sqlString, ParameterRecognizer recognizer) throws QueryException {
|
public static void parse(String sqlString, ParameterRecognizer recognizer, boolean nativeJdbcParametersIgnored) throws QueryException {
|
||||||
checkIsNotAFunctionCall( sqlString );
|
checkIsNotAFunctionCall( sqlString );
|
||||||
final int stringLength = sqlString.length();
|
final int stringLength = sqlString.length();
|
||||||
|
|
||||||
|
@ -163,9 +164,11 @@ public class ParameterParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if ( !nativeJdbcParametersIgnored ) {
|
||||||
recognizer.ordinalParameter( indx );
|
recognizer.ordinalParameter( indx );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
recognizer.other( c );
|
recognizer.other( c );
|
||||||
}
|
}
|
||||||
|
@ -175,6 +178,10 @@ public class ParameterParser {
|
||||||
recognizer.complete();
|
recognizer.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void parse(String sqlString, ParameterRecognizer recognizer) throws QueryException {
|
||||||
|
parse( sqlString, recognizer, false );
|
||||||
|
}
|
||||||
|
|
||||||
private static void checkIsNotAFunctionCall(String sqlString) {
|
private static void checkIsNotAFunctionCall(String sqlString) {
|
||||||
final String trimmed = sqlString.trim();
|
final String trimmed = sqlString.trim();
|
||||||
if ( !( trimmed.startsWith( "{" ) && trimmed.endsWith( "}" ) ) ) {
|
if ( !( trimmed.startsWith( "{" ) && trimmed.endsWith( "}" ) ) ) {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
package org.hibernate.query.sql.spi;
|
package org.hibernate.query.sql.spi;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the "callback" the process of recognizing native query parameters.
|
* Defines the "callback" process of recognizing native query parameters.
|
||||||
*
|
*
|
||||||
* @see org.hibernate.engine.query.spi.NativeQueryInterpreter#recognizeParameters
|
* @see org.hibernate.engine.query.spi.NativeQueryInterpreter#recognizeParameters
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -9,12 +9,15 @@ package org.hibernate.orm.test.query.sql;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
import org.hibernate.type.StandardBasicTypes;
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
|
|
||||||
import org.hibernate.testing.orm.domain.StandardDomainModel;
|
import org.hibernate.testing.orm.domain.StandardDomainModel;
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.hibernate.testing.orm.junit.Setting;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,6 +37,24 @@ public class NativeQueryParameterTests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DomainModel( standardModels = StandardDomainModel.HELPDESK )
|
||||||
|
@SessionFactory
|
||||||
|
@ServiceRegistry(
|
||||||
|
settings = {
|
||||||
|
@Setting(name = AvailableSettings.NATIVE_IGNORE_JDBC_PARAMETERS, value = "true")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@Test
|
||||||
|
public void testJdbcParameterScanningDisabled(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
// Nonsensical query just to test that the '?' is ignored
|
||||||
|
session.createNativeQuery( "select t.id, t.ticket_key, t.subject ? from Ticket t where t.ticket_key = :key" )
|
||||||
|
.setParameter( "key", "ABC-123" );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testJpaStylePositionalParametersInNativeSql(SessionFactoryScope scope) {
|
public void testJpaStylePositionalParametersInNativeSql(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.query.sql;
|
package org.hibernate.orm.test.query.sql;
|
||||||
|
|
||||||
|
import org.hibernate.engine.query.ParameterRecognitionException;
|
||||||
|
import org.hibernate.engine.query.internal.NativeQueryInterpreterStandardImpl;
|
||||||
import org.hibernate.engine.query.spi.ParamLocationRecognizer;
|
import org.hibernate.engine.query.spi.ParamLocationRecognizer;
|
||||||
import org.hibernate.query.sql.internal.ParameterParser;
|
import org.hibernate.query.sql.internal.ParameterParser;
|
||||||
import org.hibernate.query.sql.spi.ParameterRecognizer;
|
import org.hibernate.query.sql.spi.ParameterRecognizer;
|
||||||
|
@ -15,6 +17,7 @@ import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.hibernate.engine.query.internal.NativeQueryInterpreterStandardImpl.NATIVE_QUERY_INTERPRETER;
|
import static org.hibernate.engine.query.internal.NativeQueryInterpreterStandardImpl.NATIVE_QUERY_INTERPRETER;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
@ -197,4 +200,44 @@ public class ParameterParserTest {
|
||||||
assertEquals( 2, recognizer.getOrdinalParameterDescriptionMap().size() );
|
assertEquals( 2, recognizer.getOrdinalParameterDescriptionMap().size() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJdbcParameterScanningEnabled() {
|
||||||
|
ParamLocationRecognizer recognizer = createRecognizer();
|
||||||
|
|
||||||
|
assertThrows(
|
||||||
|
ParameterRecognitionException.class,
|
||||||
|
() -> {
|
||||||
|
NATIVE_QUERY_INTERPRETER.recognizeParameters(
|
||||||
|
"SELECT column FROM Table WHERE column.id = :param and column.name = ?1",
|
||||||
|
recognizer
|
||||||
|
);
|
||||||
|
recognizer.validate();
|
||||||
|
},
|
||||||
|
"Mixed parameter strategies - use just one of named, positional or JPA-ordinal strategy"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJdbcParameterScanningDisabled() {
|
||||||
|
ParamLocationRecognizer recognizer = createRecognizer();
|
||||||
|
|
||||||
|
// Should recognize the jpa style ordinal parameters
|
||||||
|
new NativeQueryInterpreterStandardImpl( true ).recognizeParameters(
|
||||||
|
"SELECT column FROM Table WHERE column.id = ?1 and column.name = ?2",
|
||||||
|
recognizer
|
||||||
|
);
|
||||||
|
recognizer.validate();
|
||||||
|
assertEquals( 2, recognizer.getOrdinalParameterDescriptionMap().size() );
|
||||||
|
|
||||||
|
recognizer = createRecognizer();
|
||||||
|
// Should ignore the '?'
|
||||||
|
new NativeQueryInterpreterStandardImpl( true ).recognizeParameters(
|
||||||
|
"SELECT column ? FROM Table WHERE column.id = :id",
|
||||||
|
recognizer
|
||||||
|
);
|
||||||
|
recognizer.validate();
|
||||||
|
assertTrue(recognizer.getNamedParameterDescriptionMap().containsKey("id"));
|
||||||
|
assertEquals( 0, recognizer.getOrdinalParameterDescriptionMap().size() );
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -427,7 +427,7 @@ public abstract class MockSessionFactory
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NativeQueryInterpreter getNativeQueryInterpreter() {
|
public NativeQueryInterpreter getNativeQueryInterpreter() {
|
||||||
return new NativeQueryInterpreterStandardImpl();
|
return new NativeQueryInterpreterStandardImpl( this.getNativeJdbcParametersIgnored() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue