cleanups related to function registry

This commit is contained in:
Gavin King 2024-09-10 20:56:02 +02:00
parent d269637f77
commit f2f802645c
16 changed files with 255 additions and 335 deletions

View File

@ -32,7 +32,7 @@ class SessionFactoryObserverForNamedQueryValidation implements SessionFactoryObs
@Override
public void sessionFactoryCreated(SessionFactory factory) {
SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) factory;
final SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) factory;
final QueryEngine queryEngine = sessionFactory.getQueryEngine();
queryEngine.getNamedObjectRepository().prepare( sessionFactory, metadata );
if ( sessionFactory.getSessionFactoryOptions().isNamedQueryStartupCheckingEnabled() ) {

View File

@ -15,8 +15,8 @@ import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.CastType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionRenderer;
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
@ -54,13 +54,10 @@ public class CastFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
}
private CastType getBooleanCastType(int preferredSqlTypeCodeForBoolean) {
switch ( preferredSqlTypeCodeForBoolean ) {
case Types.BIT:
case Types.SMALLINT:
case Types.TINYINT:
return CastType.INTEGER_BOOLEAN;
}
return CastType.BOOLEAN;
return switch (preferredSqlTypeCodeForBoolean) {
case Types.BIT, Types.SMALLINT, Types.TINYINT -> CastType.INTEGER_BOOLEAN;
default -> CastType.BOOLEAN;
};
}
@Override
@ -94,12 +91,12 @@ public class CastFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
Dialect dialect,
SqlAstTranslator<?> walker) {
final SessionFactoryImplementor sessionFactory = walker.getSessionFactory();
final BasicType<?> stringType = sessionFactory.getTypeConfiguration()
.getBasicTypeForJavaType( String.class );
final SqmFunctionRegistry functionRegistry = sessionFactory.getQueryEngine()
.getSqmFunctionRegistry();
final SqmFunctionDescriptor concatDescriptor = functionRegistry.findFunctionDescriptor( "concat" );
final SqmFunctionDescriptor arrayToStringDescriptor = functionRegistry.findFunctionDescriptor( "array_to_string" );
final BasicType<?> stringType = sessionFactory.getTypeConfiguration().getBasicTypeForJavaType( String.class );
final SqmFunctionRegistry functionRegistry = sessionFactory.getQueryEngine().getSqmFunctionRegistry();
final FunctionRenderer concatDescriptor =
(FunctionRenderer) functionRegistry.findFunctionDescriptor( "concat" );
final FunctionRenderer arrayToStringDescriptor =
(FunctionRenderer) functionRegistry.findFunctionDescriptor( "array_to_string" );
final boolean caseWhen = dialect.isEmptyStringTreatedAsNull();
if ( caseWhen ) {
sqlAppender.append( "case when " );
@ -107,13 +104,13 @@ public class CastFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
sqlAppender.append( " is null then null else " );
}
( (AbstractSqmSelfRenderingFunctionDescriptor) concatDescriptor ).render(
concatDescriptor.render(
sqlAppender,
List.of(
new QueryLiteral<>( "[", stringType ),
new SelfRenderingFunctionSqlAstExpression(
"array_to_string",
( (AbstractSqmSelfRenderingFunctionDescriptor) arrayToStringDescriptor ),
arrayToStringDescriptor,
List.of(
arrayArgument,
new QueryLiteral<>( ",", stringType ),

View File

@ -17,6 +17,7 @@ import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.CastType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.function.FunctionRenderer;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
@ -182,16 +183,15 @@ public class CountFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
// '' -> \0 + argumentNumber
// In the end, the expression looks like the following:
// count(distinct coalesce(nullif(coalesce(col1 || '', '\0'), ''), '\01') || '\0' || coalesce(nullif(coalesce(col2 || '', '\0'), ''), '\02'))
final AbstractSqmSelfRenderingFunctionDescriptor chr =
(AbstractSqmSelfRenderingFunctionDescriptor) translator.getSessionFactory()
.getQueryEngine()
.getSqmFunctionRegistry()
.findFunctionDescriptor( "chr" );
final FunctionRenderer chrFunction =
(FunctionRenderer)
translator.getSessionFactory().getQueryEngine()
.getSqmFunctionRegistry()
.findFunctionDescriptor( "chr" );
final List<Expression> chrArguments = List.of(
new QueryLiteral<>(
0,
translator.getSessionFactory()
.getTypeConfiguration()
translator.getSessionFactory().getTypeConfiguration()
.getBasicTypeForJavaType( Integer.class )
)
);
@ -215,15 +215,15 @@ public class CountFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
sqlAppender.appendSql( "''" );
}
sqlAppender.appendSql( SqlAppender.COMMA_SEPARATOR_CHAR );
chr.render( sqlAppender, chrArguments, returnType, translator );
chrFunction.render( sqlAppender, chrArguments, returnType, translator );
sqlAppender.appendSql( "),'')," );
chr.render( sqlAppender, chrArguments, returnType, translator );
chrFunction.render( sqlAppender, chrArguments, returnType, translator );
sqlAppender.appendSql( concatOperator );
sqlAppender.appendSql( "'" );
sqlAppender.appendSql( argumentNumber );
sqlAppender.appendSql( "')" );
sqlAppender.appendSql( concatOperator );
chr.render( sqlAppender, chrArguments, returnType, translator );
chrFunction.render( sqlAppender, chrArguments, returnType, translator );
sqlAppender.appendSql( concatOperator );
sqlAppender.appendSql( "coalesce(nullif(coalesce(" );
needsConcat = renderCastedArgument( sqlAppender, translator, expressions.get( i ) );
@ -234,9 +234,9 @@ public class CountFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
sqlAppender.appendSql( "''" );
}
sqlAppender.appendSql( SqlAppender.COMMA_SEPARATOR_CHAR );
chr.render( sqlAppender, chrArguments, returnType, translator );
chrFunction.render( sqlAppender, chrArguments, returnType, translator );
sqlAppender.appendSql( "),'')," );
chr.render( sqlAppender, chrArguments, returnType, translator );
chrFunction.render( sqlAppender, chrArguments, returnType, translator );
sqlAppender.appendSql( concatOperator );
sqlAppender.appendSql( "'" );
sqlAppender.appendSql( argumentNumber );
@ -424,8 +424,7 @@ public class CountFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
private boolean canReplaceWithStar(SqlAstNode arg, SqlAstTranslator<?> translator) {
// To determine if we can replace the argument with a star, we must know if the argument is nullable
if ( arg instanceof AbstractSqmPathInterpretation<?> ) {
final AbstractSqmPathInterpretation<?> pathInterpretation = (AbstractSqmPathInterpretation<?>) arg;
if ( arg instanceof AbstractSqmPathInterpretation<?> pathInterpretation ) {
final TableGroup tableGroup = pathInterpretation.getTableGroup();
final Expression sqlExpression = pathInterpretation.getSqlExpression();
final JdbcMappingContainer expressionType = sqlExpression.getExpressionType();

View File

@ -10,7 +10,6 @@ import java.util.ArrayList;
import java.util.List;
import org.hibernate.dialect.Dialect;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.metamodel.mapping.MappingModelExpressible;
import org.hibernate.query.ReturnableType;
@ -47,6 +46,7 @@ import org.hibernate.type.SqlTypes;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.spi.TypeConfiguration;
import static org.hibernate.internal.util.StringHelper.splitFull;
import static org.hibernate.query.sqm.BinaryArithmeticOperator.DIVIDE_PORTABLE;
import static org.hibernate.query.sqm.BinaryArithmeticOperator.MODULO;
import static org.hibernate.query.sqm.ComparisonOperator.GREATER_THAN_OR_EQUAL;
@ -200,21 +200,17 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
public Expression convertToSqlAst(SqmToSqlAstConverter walker) {
final List<SqlAstNode> arguments = resolveSqlAstArguments( getArguments(), walker );
final ReturnableType<?> resultType = resolveResultType( walker );
final MappingModelExpressible<?> mappingModelExpressible = resultType == null ? null : getMappingModelExpressible(
walker,
resultType,
arguments
);
final MappingModelExpressible<?> mappingModelExpressible =
resultType == null
? null
: getMappingModelExpressible( walker, resultType, arguments );
final SqlAstNode expression = arguments.get( 0 );
if ( expression instanceof SqlTupleContainer ) {
// SqlTupleContainer means this is a composite temporal type i.e. uses `@TimeZoneStorage(COLUMN)`
// The support for this kind of type requires that we inject the offset from the second column
// as literal into the pattern, and apply the formatting on the date time part
final SqlTuple sqlTuple = ( (SqlTupleContainer) expression ).getSqlTuple();
final AbstractSqmSelfRenderingFunctionDescriptor timestampaddFunction = getFunction(
walker,
"timestampadd"
);
final FunctionRenderer timestampaddFunction = getFunction( walker, "timestampadd" );
final BasicType<Integer> integerType = typeConfiguration.getBasicTypeRegistry()
.resolve( StandardBasicTypes.INTEGER );
arguments.set( 0, getOffsetAdjusted( sqlTuple, timestampaddFunction, integerType ) );
@ -224,21 +220,13 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
final Format format = (Format) arguments.get( 1 );
// If the format contains a time zone or offset, we must replace that with the offset column
if ( format.getFormat().contains( "x" ) || !supportsPatternLiterals ) {
final AbstractSqmSelfRenderingFunctionDescriptor concatFunction = getFunction(
walker,
"concat"
);
final AbstractSqmSelfRenderingFunctionDescriptor substringFunction = getFunction(
walker,
"substring",
3
);
final FunctionRenderer concatFunction = getFunction( walker, "concat" );
final FunctionRenderer substringFunction = getFunction( walker, "substring", 3 );
final BasicType<String> stringType = typeConfiguration.getBasicTypeRegistry()
.resolve( StandardBasicTypes.STRING );
final Dialect dialect = walker.getCreationContext()
.getSessionFactory()
.getJdbcServices()
.getDialect();
final Dialect dialect =
walker.getCreationContext().getSessionFactory().getJdbcServices()
.getDialect();
Expression formatExpression = null;
final StringBuilder sb = new StringBuilder();
final StringBuilderSqlAppender sqlAppender = new StringBuilderSqlAppender( sb );
@ -250,7 +238,7 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
else {
delimiter = "";
}
final String[] chunks = StringHelper.splitFull( "'", format.getFormat() );
final String[] chunks = splitFull( "'", format.getFormat() );
final Expression offsetExpression = sqlTuple.getExpressions().get( 1 );
// Splitting by `'` will put actual format pattern parts to even indices and literal pattern parts
// to uneven indices. We will only replace the time zone and offset pattern in the format pattern parts
@ -260,17 +248,17 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
// xxx stands for the full offset i.e. `+01:00`
// xx stands for the medium offset i.e. `+0100`
// x stands for the small offset i.e. `+01`
final String[] fullParts = StringHelper.splitFull( "xxx", chunks[i] );
final String[] fullParts = splitFull( "xxx", chunks[i] );
for ( int j = 0; j < fullParts.length; j++ ) {
if ( fullParts[j].isEmpty() ) {
continue;
}
final String[] mediumParts = StringHelper.splitFull( "xx", fullParts[j] );
final String[] mediumParts = splitFull( "xx", fullParts[j] );
for ( int k = 0; k < mediumParts.length; k++ ) {
if ( mediumParts[k].isEmpty() ) {
continue;
}
final String[] smallParts = StringHelper.splitFull( "x", mediumParts[k] );
final String[] smallParts = splitFull( "x", mediumParts[k] );
for ( int l = 0; l < smallParts.length; l++ ) {
if ( smallParts[l].isEmpty() ) {
continue;
@ -394,15 +382,12 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
}
if ( !supportsPatternLiterals ) {
final AbstractSqmSelfRenderingFunctionDescriptor concatFunction = getFunction(
walker,
"concat"
);
final FunctionRenderer concatFunction = getFunction( walker, "concat" );
final BasicType<String> stringType = typeConfiguration.getBasicTypeRegistry()
.resolve( StandardBasicTypes.STRING );
Expression formatExpression = null;
final Format format = (Format) arguments.get( 1 );
final String[] chunks = StringHelper.splitFull( "'", format.getFormat() );
final String[] chunks = splitFull( "'", format.getFormat() );
// Splitting by `'` will put actual format pattern parts to even indices and literal pattern parts
// to uneven indices. We need to apply the format parts and then concatenate because the pattern
// doesn't support literals
@ -441,31 +426,27 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
);
}
private AbstractSqmSelfRenderingFunctionDescriptor getFunction(SqmToSqlAstConverter walker, String name) {
return (AbstractSqmSelfRenderingFunctionDescriptor) walker.getCreationContext()
.getSessionFactory()
.getQueryEngine()
.getSqmFunctionRegistry()
.findFunctionDescriptor( name );
private FunctionRenderer getFunction(SqmToSqlAstConverter walker, String name) {
return (FunctionRenderer)
walker.getCreationContext().getSessionFactory().getQueryEngine()
.getSqmFunctionRegistry().findFunctionDescriptor( name );
}
private AbstractSqmSelfRenderingFunctionDescriptor getFunction(SqmToSqlAstConverter walker, String name, int argumentCount) {
final SqmFunctionDescriptor functionDescriptor = walker.getCreationContext()
.getSessionFactory()
.getQueryEngine()
.getSqmFunctionRegistry()
.findFunctionDescriptor( name );
if ( functionDescriptor instanceof MultipatternSqmFunctionDescriptor ) {
return (AbstractSqmSelfRenderingFunctionDescriptor)
( (MultipatternSqmFunctionDescriptor) functionDescriptor )
.getFunction( argumentCount );
private FunctionRenderer getFunction(SqmToSqlAstConverter walker, String name, int argumentCount) {
final SqmFunctionDescriptor functionDescriptor =
walker.getCreationContext().getSessionFactory().getQueryEngine().getSqmFunctionRegistry()
.findFunctionDescriptor( name );
if ( functionDescriptor instanceof MultipatternSqmFunctionDescriptor multipatternSqmFunctionDescriptor ) {
return (FunctionRenderer) multipatternSqmFunctionDescriptor.getFunction( argumentCount );
}
else {
return (FunctionRenderer) functionDescriptor;
}
return (AbstractSqmSelfRenderingFunctionDescriptor) functionDescriptor;
}
private SqlAstNode getOffsetAdjusted(
SqlTuple sqlTuple,
AbstractSqmSelfRenderingFunctionDescriptor timestampaddFunction,
FunctionRenderer timestampaddFunction,
BasicType<Integer> integerType) {
final Expression instantExpression = sqlTuple.getExpressions().get( 0 );
final Expression offsetExpression = sqlTuple.getExpressions().get( 1 );
@ -484,7 +465,7 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
}
private Expression createFullOffset(
AbstractSqmSelfRenderingFunctionDescriptor concatFunction,
FunctionRenderer concatFunction,
BasicType<String> stringType,
BasicType<Integer> integerType,
Expression offsetExpression) {
@ -527,8 +508,8 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
}
private Expression createMediumOffset(
AbstractSqmSelfRenderingFunctionDescriptor concatFunction,
AbstractSqmSelfRenderingFunctionDescriptor substringFunction,
FunctionRenderer concatFunction,
FunctionRenderer substringFunction,
BasicType<String> stringType,
BasicType<Integer> integerType,
Expression offsetExpression) {
@ -593,8 +574,8 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
}
private Expression createSmallOffset(
AbstractSqmSelfRenderingFunctionDescriptor concatFunction,
AbstractSqmSelfRenderingFunctionDescriptor substringFunction,
FunctionRenderer concatFunction,
FunctionRenderer substringFunction,
BasicType<String> stringType,
BasicType<Integer> integerType,
Expression offsetExpression) {
@ -621,7 +602,7 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
}
private Expression concatAsLiteral(
AbstractSqmSelfRenderingFunctionDescriptor concatFunction,
FunctionRenderer concatFunction,
BasicType<String> stringType,
String delimiter,
Expression expression,
@ -645,23 +626,24 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
}
private Expression concat(
AbstractSqmSelfRenderingFunctionDescriptor concatFunction,
FunctionRenderer concatFunction,
BasicType<String> stringType,
Expression expression,
Expression expression2) {
if ( expression == null ) {
return expression2;
}
else if ( expression instanceof SelfRenderingFunctionSqlAstExpression
&& "concat".equals( ( (SelfRenderingFunctionSqlAstExpression) expression ).getFunctionName() ) ) {
List<SqlAstNode> list = (List<SqlAstNode>) ( (SelfRenderingFunctionSqlAstExpression) expression ).getArguments();
else if ( expression instanceof SelfRenderingFunctionSqlAstExpression selfRenderingFunction
&& "concat".equals( selfRenderingFunction.getFunctionName() ) ) {
final List<SqlAstNode> list = (List<SqlAstNode>) selfRenderingFunction.getArguments();
final SqlAstNode lastOperand = list.get( list.size() - 1 );
if ( expression2 instanceof QueryLiteral<?> && lastOperand instanceof QueryLiteral<?> ) {
if ( expression2 instanceof QueryLiteral<?> literal2
&& lastOperand instanceof QueryLiteral<?> literalOperand ) {
list.set(
list.size() - 1,
new QueryLiteral<>(
( (QueryLiteral<?>) lastOperand ).getLiteralValue().toString() +
( (QueryLiteral<?>) expression2 ).getLiteralValue().toString(),
literalOperand.getLiteralValue().toString()
+ literal2.getLiteralValue().toString(),
stringType
)
);
@ -671,17 +653,17 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
}
return expression;
}
else if ( expression2 instanceof SelfRenderingFunctionSqlAstExpression
&& "concat".equals( ( (SelfRenderingFunctionSqlAstExpression) expression2 ).getFunctionName() ) ) {
final List<SqlAstNode> list = (List<SqlAstNode>)
( (SelfRenderingFunctionSqlAstExpression) expression2 ).getArguments();
else if ( expression2 instanceof SelfRenderingFunctionSqlAstExpression selfRenderingFunction
&& "concat".equals( selfRenderingFunction.getFunctionName() ) ) {
final List<SqlAstNode> list = (List<SqlAstNode>) selfRenderingFunction.getArguments();
final SqlAstNode firstOperand = list.get( 0 );
if ( expression instanceof QueryLiteral<?> && firstOperand instanceof QueryLiteral<?> ) {
if ( expression instanceof QueryLiteral<?> literal
&& firstOperand instanceof QueryLiteral<?> literalOperand ) {
list.set(
list.size() - 1,
new QueryLiteral<>(
( (QueryLiteral<?>) expression ).getLiteralValue().toString() +
( (QueryLiteral<?>) firstOperand ).getLiteralValue().toString(),
literal.getLiteralValue().toString() +
literalOperand.getLiteralValue().toString(),
stringType
)
);
@ -691,10 +673,11 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
}
return expression2;
}
else if ( expression instanceof QueryLiteral<?> && expression2 instanceof QueryLiteral<?> ) {
else if ( expression instanceof QueryLiteral<?> literal
&& expression2 instanceof QueryLiteral<?> literal2 ) {
return new QueryLiteral<>(
( (QueryLiteral<?>) expression ).getLiteralValue().toString() +
( (QueryLiteral<?>) expression2 ).getLiteralValue().toString(),
literal.getLiteralValue().toString() +
literal2.getLiteralValue().toString(),
stringType
);
}

View File

@ -8,7 +8,6 @@ package org.hibernate.dialect.function;
import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;

View File

@ -12,7 +12,6 @@ import java.util.function.Supplier;
import org.hibernate.dialect.Dialect;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.metamodel.mapping.MappingModelExpressible;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.TemporalUnit;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;

View File

@ -70,12 +70,11 @@ public class OracleArrayAggEmulation extends AbstractSqmSelfRenderingFunctionDes
List<SortSpecification> withinGroup,
ReturnableType<?> returnType,
SqlAstTranslator<?> translator) {
if ( !( returnType instanceof BasicPluralType<?, ?> ) ) {
if ( !( returnType instanceof BasicPluralType<?, ?> pluralType ) ) {
throw new SemanticException(
"Oracle array_agg emulation requires a basic plural return type, but resolved return type was: " + returnType
);
}
final BasicPluralType<?, ?> pluralType = (BasicPluralType<?, ?>) returnType;
final boolean returnJson = pluralType.getJdbcType().getDefaultSqlTypeCode() == SqlTypes.JSON;
if ( returnJson ) {
sqlAppender.append( "json_arrayagg(" );

View File

@ -9,19 +9,12 @@ package org.hibernate.dialect.function.array;
import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.spi.TypeConfiguration;
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.ANY;
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER;
/**
* Oracle array_to_string function.
*/

View File

@ -831,8 +831,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
}
protected <R> HqlInterpretation<R> interpretHql(String hql, Class<R> resultType) {
final QueryEngine queryEngine = getFactory().getQueryEngine();
return queryEngine.interpretHql( hql, resultType );
return getFactory().getQueryEngine().interpretHql( hql, resultType );
}
protected static void checkSelectionQuery(String hql, HqlInterpretation<?> hqlInterpretation) {
@ -944,8 +943,9 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
}
protected NamedResultSetMappingMemento getResultSetMappingMemento(String resultSetMappingName) {
final NamedResultSetMappingMemento resultSetMappingMemento = getFactory().getQueryEngine()
.getNamedObjectRepository().getResultSetMappingMemento( resultSetMappingName );
final NamedResultSetMappingMemento resultSetMappingMemento =
getFactory().getQueryEngine().getNamedObjectRepository()
.getResultSetMappingMemento( resultSetMappingName );
if ( resultSetMappingMemento == null ) {
throw new HibernateException( "Could not resolve specified result-set mapping name: "
+ resultSetMappingName );
@ -1053,14 +1053,12 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
}
private NamedSqmQueryMemento getSqmQueryMemento(String queryName) {
return getFactory().getQueryEngine()
.getNamedObjectRepository()
return getFactory().getQueryEngine().getNamedObjectRepository()
.getSqmQueryMemento( queryName );
}
private NamedNativeQueryMemento getNativeQueryMemento(String queryName) {
return getFactory().getQueryEngine()
.getNamedObjectRepository()
return getFactory().getQueryEngine().getNamedObjectRepository()
.getNativeQueryMemento( queryName );
}
@ -1327,17 +1325,18 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
}
@Override
@SuppressWarnings("UnnecessaryLocalVariable")
public ProcedureCall getNamedProcedureCall(String name) {
checkOpen();
final NamedCallableQueryMemento memento = factory.getQueryEngine()
.getNamedObjectRepository().getCallableQueryMemento( name );
final NamedCallableQueryMemento memento =
factory.getQueryEngine().getNamedObjectRepository()
.getCallableQueryMemento( name );
if ( memento == null ) {
throw new IllegalArgumentException(
"Could not find named stored procedure call with that registration name : " + name
);
}
@SuppressWarnings("UnnecessaryLocalVariable")
final ProcedureCall procedureCall = memento.makeProcedureCall( this );
// procedureCall.setComment( "Named stored procedure call [" + name + "]" );
return procedureCall;

View File

@ -51,25 +51,22 @@ public interface OrderingExpression extends Node {
sortExpression = expression;
}
else {
final QueryEngine queryEngine = creationState.getCreationContext()
.getSessionFactory()
.getQueryEngine();
final SqmToSqlAstConverter converter;
if ( creationState instanceof SqmToSqlAstConverter ) {
converter = (SqmToSqlAstConverter) creationState;
}
else {
converter = new FakeSqmToSqlAstConverter( creationState );
}
sortExpression = queryEngine
.getSqmFunctionRegistry()
.findFunctionDescriptor( "collate" )
.generateSqmExpression(
new SqmSelfRenderingExpression<>( walker -> expression, null, null ),
null,
queryEngine
)
.convertToSqlAst( converter );
final QueryEngine queryEngine =
creationState.getCreationContext().getSessionFactory()
.getQueryEngine();
final SqmToSqlAstConverter converter =
creationState instanceof SqmToSqlAstConverter sqmToSqlAstConverter
? sqmToSqlAstConverter
: new FakeSqmToSqlAstConverter(creationState);
sortExpression =
queryEngine.getSqmFunctionRegistry()
.findFunctionDescriptor( "collate" )
.generateSqmExpression(
new SqmSelfRenderingExpression<>( walker -> expression, null, null ),
null,
queryEngine
)
.convertToSqlAst( converter );
}
return sortExpression;
}

View File

@ -10,8 +10,6 @@ import java.util.Collection;
import jakarta.persistence.metamodel.EntityType;
import org.hibernate.query.sqm.SqmPathSource;
/**
* Extension to the JPA {@link EntityType} contract.
*

View File

@ -25,12 +25,10 @@ import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.ScrollMode;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.graph.GraphSemantic;
import org.hibernate.graph.RootGraph;
import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.persister.entity.EntityPersister;
@ -96,6 +94,9 @@ import jakarta.persistence.PersistenceException;
import jakarta.persistence.TemporalType;
import jakarta.persistence.TransactionRequiredException;
import static java.lang.Boolean.parseBoolean;
import static java.util.Collections.emptyList;
import static org.hibernate.internal.util.StringHelper.join;
import static org.hibernate.jpa.HibernateHints.HINT_CALLABLE_FUNCTION;
import static org.hibernate.procedure.internal.NamedCallableQueryMementoImpl.ParameterMementoImpl.fromRegistration;
import static org.hibernate.query.results.ResultSetMapping.resolveResultSetMapping;
@ -163,9 +164,9 @@ public class ProcedureCallImpl<R>
this.synchronizedQuerySpaces = new HashSet<>();
final String mappingId = procedureName + ":" + StringHelper.join( ",", resultClasses );
final String mappingId = procedureName + ":" + join( ",", resultClasses );
this.resultSetMapping = ResultSetMapping.resolveResultSetMapping( mappingId, session.getSessionFactory() );
this.resultSetMapping = resolveResultSetMapping( mappingId, session.getSessionFactory() );
Util.resolveResultSetMappingClasses(
resultClasses,
@ -197,8 +198,8 @@ public class ProcedureCallImpl<R>
this.synchronizedQuerySpaces = new HashSet<>();
final String mappingId = procedureName + ":" + StringHelper.join( ",", resultSetMappingNames );
this.resultSetMapping = ResultSetMapping.resolveResultSetMapping( mappingId, session.getSessionFactory() );
final String mappingId = procedureName + ":" + join( ",", resultSetMappingNames );
this.resultSetMapping = resolveResultSetMapping( mappingId, session.getSessionFactory() );
Util.resolveResultSetMappingNames(
resultSetMappingNames,
@ -224,7 +225,7 @@ public class ProcedureCallImpl<R>
this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() );
this.resultSetMapping = ResultSetMapping.resolveResultSetMapping( memento.getRegistrationName(), session.getSessionFactory() );
this.resultSetMapping = resolveResultSetMapping( memento.getRegistrationName(), session.getSessionFactory() );
Util.resolveResultSetMappings(
memento.getResultSetMappingNames(),
@ -256,15 +257,15 @@ public class ProcedureCallImpl<R>
this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() );
final String mappingId = procedureName + ":" + StringHelper.join( ",", resultTypes );
this.resultSetMapping = ResultSetMapping.resolveResultSetMapping( mappingId, session.getSessionFactory() );
final String mappingId = procedureName + ":" + join( ",", resultTypes );
this.resultSetMapping = resolveResultSetMapping( mappingId, session.getSessionFactory() );
Util.resolveResultSetMappings(
null,
resultTypes,
resultSetMapping,
synchronizedQuerySpaces::add,
() -> getSession().getFactory()
getSession()::getFactory
);
applyOptions( memento );
@ -283,8 +284,8 @@ public class ProcedureCallImpl<R>
this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() );
final String mappingId = procedureName + ":" + StringHelper.join( ",", resultSetMappingNames );
this.resultSetMapping = ResultSetMapping.resolveResultSetMapping( mappingId, session.getSessionFactory() );
final String mappingId = procedureName + ":" + join( ",", resultSetMappingNames );
this.resultSetMapping = resolveResultSetMapping( mappingId, session.getSessionFactory() );
Util.resolveResultSetMappings(
resultSetMappingNames,
@ -302,7 +303,7 @@ public class ProcedureCallImpl<R>
if ( memento.getHints() != null ) {
final Object callableFunction = memento.getHints().get( HINT_CALLABLE_FUNCTION );
if ( callableFunction != null && Boolean.parseBoolean( callableFunction.toString() ) ) {
if ( callableFunction != null && parseBoolean( callableFunction.toString() ) ) {
applyCallableFunctionHint();
}
}
@ -313,13 +314,19 @@ public class ProcedureCallImpl<R>
resultSetMapping.visitResultBuilders(
(index, resultBuilder) -> resultTypes.add( resultBuilder.getJavaType() )
);
final TypeConfiguration typeConfiguration = getSessionFactory().getTypeConfiguration();
final BasicType<?> type;
if ( resultTypes.size() != 1 || ( type = typeConfiguration.getBasicTypeForJavaType( resultTypes.get( 0 ) ) ) == null ) {
markAsFunctionCall( Types.REF_CURSOR );
if ( resultTypes.size() == 1 ) {
final BasicType<?> type =
getSessionFactory().getTypeConfiguration()
.getBasicTypeForJavaType( resultTypes.get(0) );
if ( type != null ) {
markAsFunctionCall( type );
}
else {
markAsFunctionCallRefRefCursor();
}
}
else {
markAsFunctionCall( type );
markAsFunctionCallRefRefCursor();
}
}
@ -363,6 +370,10 @@ public class ProcedureCallImpl<R>
return this;
}
private void markAsFunctionCallRefRefCursor() {
functionReturn = new FunctionReturnImpl<>( this, Types.REF_CURSOR );
}
@Override
public ProcedureCallImpl<R> markAsFunctionCall(Class<?> resultType) {
final TypeConfiguration typeConfiguration = getSessionFactory().getTypeConfiguration();
@ -370,7 +381,8 @@ public class ProcedureCallImpl<R>
if ( basicType == null ) {
throw new IllegalArgumentException( "Could not resolve a BasicType for the java type: " + resultType.getName() );
}
return markAsFunctionCall( basicType );
markAsFunctionCall( basicType );
return this;
}
@Override
@ -381,10 +393,11 @@ public class ProcedureCallImpl<R>
if ( basicType == null ) {
throw new IllegalArgumentException( "Could not resolve a BasicType for the java type: " + typeReference.getName() );
}
return markAsFunctionCall( basicType );
markAsFunctionCall( basicType );
return this;
}
private ProcedureCallImpl<R> markAsFunctionCall(BasicType<?> basicType) {
private void markAsFunctionCall(BasicType<?> basicType) {
if ( resultSetMapping.getNumberOfResultBuilders() == 0 ) {
// Function returns might not be represented as callable parameters,
// but we still want to convert the result to the requested java type if possible
@ -394,7 +407,6 @@ public class ProcedureCallImpl<R>
}
//noinspection unchecked
functionReturn = new FunctionReturnImpl<>( this, (OutputableType<R>) basicType );
return this;
}
@Override
@ -402,10 +414,6 @@ public class ProcedureCallImpl<R>
return paramBindings;
}
public SessionFactoryImplementor getSessionFactory() {
return getSession().getFactory();
}
@Override
public Query<R> setOrder(List<Order<? super R>> orderList) {
throw new UnsupportedOperationException("Ordering not supported for stored procedure calls");
@ -814,7 +822,7 @@ public class ProcedureCallImpl<R>
ProcedureParameterMetadataImpl parameterMetadata) {
if ( parameterMetadata.getParameterStrategy() == ParameterStrategy.UNKNOWN ) {
// none...
return Collections.emptyList();
return emptyList();
}
final List<NamedCallableQueryMemento.ParameterMemento> mementos = new ArrayList<>();
@ -922,8 +930,8 @@ public class ProcedureCallImpl<R>
if ( rtn == null ) {
return -1;
}
else if ( rtn instanceof UpdateCountOutput ) {
return ( (UpdateCountOutput) rtn ).getUpdateCount();
else if ( rtn instanceof UpdateCountOutput updateCount ) {
return updateCount.getUpdateCount();
}
else {
return -1;
@ -944,7 +952,7 @@ public class ProcedureCallImpl<R>
@Override
protected List<R> doList() {
if ( getMaxResults() == 0 ) {
return Collections.emptyList();
return emptyList();
}
try {
final Output rtn = outputs().getCurrent();
@ -1127,7 +1135,7 @@ public class ProcedureCallImpl<R>
@Override
public ProcedureCallImplementor<R> setHint(String hintName, Object value) {
if ( HINT_CALLABLE_FUNCTION.equals( hintName ) ) {
if ( value != null && Boolean.parseBoolean( value.toString() ) ) {
if ( value != null && parseBoolean( value.toString() ) ) {
applyCallableFunctionHint();
}
}
@ -1249,7 +1257,7 @@ public class ProcedureCallImpl<R>
}
@Override
public Stream stream() {
public Stream<R> stream() {
return getResultStream();
}

View File

@ -54,10 +54,11 @@ public class Util {
ResultSetMapping resultSetMapping,
Consumer<String> querySpaceConsumer,
ResultSetMappingResolutionContext context) {
final NamedObjectRepository namedObjectRepository = context.getSessionFactory().getQueryEngine().getNamedObjectRepository();
final NamedObjectRepository namedObjectRepository =
context.getSessionFactory().getQueryEngine().getNamedObjectRepository();
for ( String resultSetMappingName : resultSetMappingNames ) {
final NamedResultSetMappingMemento memento = namedObjectRepository.getResultSetMappingMemento( resultSetMappingName );
final NamedResultSetMappingMemento memento =
namedObjectRepository.getResultSetMappingMemento( resultSetMappingName );
if ( memento == null ) {
throw new UnknownSqlResultSetMappingException( "Unknown SqlResultSetMapping [" + resultSetMappingName + "]" );
}

View File

@ -98,9 +98,9 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
}
private <T> Class<T> treatTarget(String typeName) {
final ManagedDomainType<T> managedType = creationState.getCreationContext()
.getJpaMetamodel()
.managedType( typeName );
final ManagedDomainType<T> managedType =
creationState.getCreationContext().getJpaMetamodel()
.managedType( typeName );
return managedType.getJavaType();
}
@ -132,35 +132,23 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
if ( isBase ) {
isBase = false;
final SqmPathRegistry sqmPathRegistry = creationState.getProcessingStateStack()
.getCurrent()
.getPathRegistry();
final SqmPathRegistry sqmPathRegistry =
creationState.getProcessingStateStack().getCurrent()
.getPathRegistry();
final SqmFrom<?,?> pathRootByAlias = sqmPathRegistry.findFromByAlias( identifier, true );
if ( pathRootByAlias != null ) {
// identifier is an alias (identification variable)
validateAsRoot( pathRootByAlias );
if ( isTerminal ) {
return pathRootByAlias;
}
else {
return new DomainPathPart( pathRootByAlias );
}
return isTerminal ? pathRootByAlias : new DomainPathPart( pathRootByAlias );
}
final SqmFrom<?, ?> pathRootByExposedNavigable = sqmPathRegistry.findFromExposing( identifier );
if ( pathRootByExposedNavigable != null ) {
// identifier is an "unqualified attribute reference"
validateAsRoot( pathRootByExposedNavigable );
final SqmPath<?> sqmPath = pathRootByExposedNavigable.get( identifier );
if ( isTerminal ) {
return sqmPath;
}
else {
return new DomainPathPart( sqmPath );
}
return isTerminal ? sqmPath : new DomainPathPart( sqmPath );
}
}
@ -176,14 +164,14 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
//
// todo (6.0) : finish this logic. and see above note in `! isTerminal` block
final SqmCreationContext creationContext = creationState.getCreationContext();
if ( ! isTerminal ) {
return this;
}
final String path = pathSoFar.toString();
final SqmCreationContext creationContext = creationState.getCreationContext();
final JpaMetamodel jpaMetamodel = creationContext.getJpaMetamodel();
final String path = pathSoFar.toString();
final String importableName = jpaMetamodel.qualifyImportableName( path );
final NodeBuilder nodeBuilder = creationContext.getNodeBuilder();
if ( importableName != null ) {
@ -197,14 +185,10 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
}
final SqmFunctionDescriptor functionDescriptor =
creationContext.getQueryEngine()
.getSqmFunctionRegistry()
creationContext.getQueryEngine().getSqmFunctionRegistry()
.findFunctionDescriptor( path );
if ( functionDescriptor != null ) {
return functionDescriptor.generateSqmExpression(
null,
creationContext.getQueryEngine()
);
return functionDescriptor.generateSqmExpression( null, creationContext.getQueryEngine() );
}
// see if it is a named field/enum reference
@ -212,7 +196,6 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
if ( splitPosition > 0 ) {
final String prefix = path.substring( 0, splitPosition );
final String terminal = path.substring( splitPosition + 1 );
try {
final EnumJavaType<?> enumType = jpaMetamodel.getEnumType( prefix );
if ( enumType != null ) {

View File

@ -19,7 +19,6 @@ import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.TreatException;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.produce.function.FunctionArgumentException;
import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmFunction;

View File

@ -73,7 +73,7 @@ import org.hibernate.query.sqm.FrameKind;
import org.hibernate.query.sqm.FrameMode;
import org.hibernate.query.sqm.SetOperator;
import org.hibernate.query.sqm.UnaryArithmeticOperator;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionRenderer;
import org.hibernate.query.sqm.function.MultipatternSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.SelfRenderingAggregateFunctionSqlAstExpression;
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
@ -325,7 +325,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
// This field holds the index of where the "recursive" keyword should appear in the sqlBuffer.
// See #visitCteContainer for details about the usage.
private int withClauseRecursiveIndex = -1;
private transient AbstractSqmSelfRenderingFunctionDescriptor castFunction;
private transient FunctionRenderer castFunction;
private transient LazySessionWrapperOptions lazySessionWrapperOptions;
private transient BasicType<Integer> integerType;
private transient BasicType<String> stringType;
@ -361,7 +361,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
return sessionFactory;
}
protected AbstractSqmSelfRenderingFunctionDescriptor castFunction() {
protected FunctionRenderer castFunction() {
if ( castFunction == null ) {
castFunction = findSelfRenderingFunction( "cast", 2 );
}
@ -685,11 +685,10 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
expression.accept( this );
return;
}
else if ( expression instanceof JdbcParameter ) {
else if ( expression instanceof JdbcParameter parameter ) {
if ( jdbcParameterBindings == null ) {
throw new IllegalArgumentException( "Can't interpret expression because no parameter bindings are available" );
}
final JdbcParameter parameter = (JdbcParameter) expression;
renderAsLiteral( parameter, getParameterBindValue( parameter ) );
return;
}
@ -732,13 +731,10 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
}
private static Boolean matchOverOrWithinGroupClauses(final Clause clause) {
switch ( clause ) {
case OVER:
case WITHIN_GROUP:
return Boolean.TRUE;
default:
return null;
}
return switch (clause) {
case OVER, WITHIN_GROUP -> Boolean.TRUE;
default -> null;
};
}
protected Stack<Clause> getClauseStack() {
@ -772,16 +768,14 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
}
private static CteStatement matchCteStatement(final Statement stmt, final String cteName) {
if ( stmt instanceof CteContainer ) {
final CteContainer cteContainer = (CteContainer) stmt;
if ( stmt instanceof CteContainer cteContainer ) {
return cteContainer.getCteStatement( cteName );
}
return null;
}
private static CteContainer matchCteContainerByStatement(final Statement stmt, final String cteName) {
if ( stmt instanceof CteContainer ) {
final CteContainer cteContainer = (CteContainer) stmt;
if ( stmt instanceof CteContainer cteContainer ) {
if ( cteContainer.getCteStatement( cteName ) != null ) {
return cteContainer;
}
@ -2835,8 +2829,8 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
* The mappings are implemented in {@link #wrapRowComponentAsOrderPreservingConcatArgument(Expression)}.
*/
private void emulateSearchClauseOrderWithString(SelectClause selectClause) {
final AbstractSqmSelfRenderingFunctionDescriptor concat = findSelfRenderingFunction( "concat", 2 );
final AbstractSqmSelfRenderingFunctionDescriptor coalesce = findSelfRenderingFunction( "coalesce", 2 );
final FunctionRenderer concat = findSelfRenderingFunction( "concat", 2 );
final FunctionRenderer coalesce = findSelfRenderingFunction( "coalesce", 2 );
final BasicType<String> stringType = getStringType();
final BasicType<Integer> integerType = getIntegerType();
// Shift by 1 bit instead of multiplying by 2
@ -3148,7 +3142,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
}
private Expression createNullSeparator() {
final AbstractSqmSelfRenderingFunctionDescriptor chr = findSelfRenderingFunction( "chr", 1 );
final FunctionRenderer chr = findSelfRenderingFunction( "chr", 1 );
final BasicType<String> stringType = getStringType();
return new SelfRenderingFunctionSqlAstExpression(
"chr",
@ -3170,8 +3164,8 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
* The mappings are implemented in {@link #wrapRowComponentAsEqualityPreservingConcatArgument(Expression)}.
*/
private void emulateCycleClauseWithString(SelectClause selectClause) {
final AbstractSqmSelfRenderingFunctionDescriptor concat = findSelfRenderingFunction( "concat", 2 );
final AbstractSqmSelfRenderingFunctionDescriptor coalesce = findSelfRenderingFunction( "coalesce", 2 );
final FunctionRenderer concat = findSelfRenderingFunction( "concat", 2 );
final FunctionRenderer coalesce = findSelfRenderingFunction( "coalesce", 2 );
final BasicType<String> stringType = getStringType();
// Shift by 2 bit instead of multiplying by 4
final List<SqlAstNode> arguments = new ArrayList<>( currentCteStatement.getCycleColumns().size() << 2 );
@ -3284,7 +3278,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
}
protected void renderStringContainsExactlyPredicate(Expression haystack, Expression needle) {
final AbstractSqmSelfRenderingFunctionDescriptor position = findSelfRenderingFunction( "position", 2 );
final FunctionRenderer position = findSelfRenderingFunction( "position", 2 );
new SelfRenderingFunctionSqlAstExpression(
"position",
position,
@ -3348,8 +3342,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
final JdbcMapping jdbcMapping = expression.getExpressionType().getSingleJdbcMapping();
switch ( jdbcMapping.getCastType() ) {
case STRING:
if ( expression.getExpressionType() instanceof SqlTypedMapping ) {
final SqlTypedMapping sqlTypedMapping = (SqlTypedMapping) expression.getExpressionType();
if ( expression.getExpressionType() instanceof SqlTypedMapping sqlTypedMapping ) {
if ( sqlTypedMapping.getLength() != null ) {
return sqlTypedMapping.getLength().intValue();
}
@ -3364,8 +3357,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
case LONG:
return 20;
case FIXED:
if ( expression.getExpressionType() instanceof SqlTypedMapping ) {
final SqlTypedMapping sqlTypedMapping = (SqlTypedMapping) expression.getExpressionType();
if ( expression.getExpressionType() instanceof SqlTypedMapping sqlTypedMapping ) {
if ( sqlTypedMapping.getPrecision() != null && sqlTypedMapping.getScale() != null ) {
return sqlTypedMapping.getPrecision() + sqlTypedMapping.getScale() + 2;
}
@ -3409,7 +3401,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
}
// Should we maybe always cast instead? Not sure what is faster/better...
final BasicType<String> stringType = getStringType();
final AbstractSqmSelfRenderingFunctionDescriptor concat = findSelfRenderingFunction( "concat", 2 );
final FunctionRenderer concat = findSelfRenderingFunction( "concat", 2 );
return new SelfRenderingFunctionSqlAstExpression(
"concat",
concat,
@ -3434,8 +3426,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
final JdbcMapping jdbcMapping = expression.getExpressionType().getSingleJdbcMapping();
switch ( jdbcMapping.getCastType() ) {
case STRING:
if ( expression.getExpressionType() instanceof SqlTypedMapping ) {
final SqlTypedMapping sqlTypedMapping = (SqlTypedMapping) expression.getExpressionType();
if ( expression.getExpressionType() instanceof SqlTypedMapping sqlTypedMapping ) {
if ( sqlTypedMapping.getLength() != null ) {
return sqlTypedMapping.getLength().intValue();
}
@ -3450,8 +3441,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
case LONG:
return 20;
case FIXED:
if ( expression.getExpressionType() instanceof SqlTypedMapping ) {
final SqlTypedMapping sqlTypedMapping = (SqlTypedMapping) expression.getExpressionType();
if ( expression.getExpressionType() instanceof SqlTypedMapping sqlTypedMapping ) {
if ( sqlTypedMapping.getPrecision() != null && sqlTypedMapping.getScale() != null ) {
return sqlTypedMapping.getPrecision() + sqlTypedMapping.getScale() + 2;
}
@ -3470,10 +3460,9 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
}
private Expression abs(Expression expression) {
final AbstractSqmSelfRenderingFunctionDescriptor abs = findSelfRenderingFunction( "abs", 2 );
return new SelfRenderingFunctionSqlAstExpression(
"abs",
abs,
findSelfRenderingFunction( "abs", 2 ),
List.of( expression ),
(ReturnableType<?>) expression.getExpressionType(),
expression.getExpressionType()
@ -3482,29 +3471,26 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
private Expression lpad(Expression expression, int stringLength, String padString) {
final BasicType<String> stringType = getStringType();
final AbstractSqmSelfRenderingFunctionDescriptor lpad = findSelfRenderingFunction( "lpad", 3 );
final FunctionRenderer lpad = findSelfRenderingFunction( "lpad", 3 );
return new SelfRenderingFunctionSqlAstExpression(
"lpad",
lpad,
List.of(
expression,
List.of( expression,
new QueryLiteral<>( stringLength, getIntegerType() ),
new QueryLiteral<>( padString, stringType )
),
new QueryLiteral<>( padString, stringType ) ),
stringType,
stringType
);
}
private AbstractSqmSelfRenderingFunctionDescriptor findSelfRenderingFunction(String functionName, int argumentCount) {
final SqmFunctionDescriptor functionDescriptor = sessionFactory.getQueryEngine()
.getSqmFunctionRegistry()
.findFunctionDescriptor( functionName );
if ( functionDescriptor instanceof MultipatternSqmFunctionDescriptor ) {
final MultipatternSqmFunctionDescriptor multiPatternFunction = (MultipatternSqmFunctionDescriptor) functionDescriptor;
return (AbstractSqmSelfRenderingFunctionDescriptor) multiPatternFunction.getFunction( argumentCount );
private FunctionRenderer findSelfRenderingFunction(String functionName, int argumentCount) {
final SqmFunctionDescriptor functionDescriptor =
sessionFactory.getQueryEngine().getSqmFunctionRegistry()
.findFunctionDescriptor( functionName );
if ( functionDescriptor instanceof MultipatternSqmFunctionDescriptor multiPatternFunction ) {
return (FunctionRenderer) multiPatternFunction.getFunction( argumentCount );
}
return (AbstractSqmSelfRenderingFunctionDescriptor) functionDescriptor;
return (FunctionRenderer) functionDescriptor;
}
/**
@ -3512,7 +3498,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
*/
protected Expression castNumberToString(Expression expression, int precision, int scale) {
final BasicType<String> stringType = getStringType();
final AbstractSqmSelfRenderingFunctionDescriptor concat = findSelfRenderingFunction( "concat", 2 );
final FunctionRenderer concat = findSelfRenderingFunction( "concat", 2 );
final CaseSearchedExpression signExpression = new CaseSearchedExpression( stringType );
signExpression.when(
@ -3809,19 +3795,19 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
}
protected Expression resolveAliasedExpression(List<SqlSelection> sqlSelections, Expression expression) {
if ( expression instanceof Literal ) {
Object literalValue = ( (Literal) expression ).getLiteralValue();
if ( literalValue instanceof Integer ) {
return sqlSelections.get( (Integer) literalValue ).getExpression();
if ( expression instanceof Literal literal ) {
final Object literalValue = literal.getLiteralValue();
if ( literalValue instanceof Integer integer ) {
return sqlSelections.get( integer ).getExpression();
}
}
else if ( expression instanceof SqlSelectionExpression ) {
return ( (SqlSelectionExpression) expression ).getSelection().getExpression();
else if ( expression instanceof SqlSelectionExpression selectionExpression ) {
return selectionExpression.getSelection().getExpression();
}
else if ( expression instanceof SqmPathInterpretation<?> ) {
final Expression sqlExpression = ( (SqmPathInterpretation<?>) expression ).getSqlExpression();
if ( sqlExpression instanceof SqlSelectionExpression ) {
return ( (SqlSelectionExpression) sqlExpression ).getSelection().getExpression();
else if ( expression instanceof SqmPathInterpretation<?> pathInterpretation ) {
final Expression sqlExpression = pathInterpretation.getSqlExpression();
if ( sqlExpression instanceof SqlSelectionExpression selectionExpression ) {
return selectionExpression.getSelection().getExpression();
}
}
return expression;
@ -3829,13 +3815,13 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
protected Expression resolveExpressionToAlias(Expression expression) {
int index = -1;
if ( expression instanceof SqlSelectionExpression ) {
index = ( (SqlSelectionExpression) expression ).getSelection().getValuesArrayPosition();
if ( expression instanceof SqlSelectionExpression selectionExpression ) {
index = selectionExpression.getSelection().getValuesArrayPosition();
}
else if ( expression instanceof SqmPathInterpretation<?> ) {
final Expression sqlExpression = ( (SqmPathInterpretation<?>) expression ).getSqlExpression();
if ( sqlExpression instanceof SqlSelectionExpression ) {
index = ( (SqlSelectionExpression) sqlExpression ).getSelection().getValuesArrayPosition();
else if ( expression instanceof SqmPathInterpretation<?> pathInterpretation ) {
final Expression sqlExpression = pathInterpretation.getSqlExpression();
if ( sqlExpression instanceof SqlSelectionExpression selectionExpression ) {
index = selectionExpression.getSelection().getValuesArrayPosition();
}
}
if ( index == -1 ) {
@ -5496,8 +5482,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
final Expression overExpression = over.getExpression();
overExpression.accept( this );
final boolean orderedSetAggregate;
if ( overExpression instanceof OrderedSetAggregateFunctionExpression ) {
final OrderedSetAggregateFunctionExpression expression = (OrderedSetAggregateFunctionExpression) overExpression;
if ( overExpression instanceof OrderedSetAggregateFunctionExpression expression ) {
orderedSetAggregate = expression.getWithinGroup() != null && !expression.getWithinGroup().isEmpty();
}
else {
@ -5766,8 +5751,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
protected void renderSelectExpressionWithCastedOrInlinedPlainParameters(Expression expression) {
// Null literals have to be casted in the select clause
if ( expression instanceof Literal ) {
final Literal literal = (Literal) expression;
if ( expression instanceof Literal literal ) {
if ( literal.getLiteralValue() == null ) {
renderCasted( literal );
}
@ -5802,8 +5786,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
final List<SqlAstNode> arguments = new ArrayList<>( 2 );
arguments.add( expression );
final CastTarget castTarget;
if ( expression instanceof SqlTypedMappingJdbcParameter ) {
final SqlTypedMappingJdbcParameter parameter = (SqlTypedMappingJdbcParameter) expression;
if ( expression instanceof SqlTypedMappingJdbcParameter parameter ) {
final SqlTypedMapping sqlTypedMapping = parameter.getSqlTypedMapping();
castTarget = new CastTarget(
parameter.getJdbcMapping(),
@ -6017,8 +6000,8 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
processTableGroupJoins( tableGroup );
}
ModelPartContainer modelPart = tableGroup.getModelPart();
if ( modelPart instanceof EntityPersister ) {
String[] querySpaces = (String[]) ( (EntityPersister) modelPart ).getQuerySpaces();
if ( modelPart instanceof EntityPersister persister ) {
String[] querySpaces = (String[]) persister.getQuerySpaces();
for ( int i = 0; i < querySpaces.length; i++ ) {
registerAffectedTable( querySpaces[i] );
}
@ -6151,8 +6134,8 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
}
ModelPartContainer modelPart = tableGroup.getModelPart();
if ( modelPart instanceof EntityPersister ) {
String[] querySpaces = (String[]) ( (EntityPersister) modelPart ).getQuerySpaces();
if ( modelPart instanceof EntityPersister persister ) {
String[] querySpaces = (String[]) persister.getQuerySpaces();
for ( int i = 0; i < querySpaces.length; i++ ) {
registerAffectedTable( querySpaces[i] );
}
@ -6212,17 +6195,15 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
if ( dialect.supportsLateral() ) {
appendSql( "lateral " );
}
else if ( tableReference instanceof QueryPartTableReference ) {
final QueryPartTableReference queryPartTableReference = (QueryPartTableReference) tableReference;
else if ( tableReference instanceof QueryPartTableReference queryPartTableReference ) {
final SelectStatement emulationStatement = stripToSelectClause( queryPartTableReference.getStatement() );
final QueryPart queryPart = queryPartTableReference.getStatement().getQueryPart();
final QueryPart emulationQueryPart = emulationStatement.getQueryPart();
final List<String> columnNames;
if ( queryPart instanceof QuerySpec && needsLateralSortExpressionVirtualSelections( (QuerySpec) queryPart ) ) {
if ( queryPart instanceof QuerySpec querySpec && needsLateralSortExpressionVirtualSelections( querySpec ) ) {
// One of our lateral emulations requires that sort expressions are present in the select clause
// when the query spec use limit/offset. So we add selections for these, if necessary
columnNames = new ArrayList<>( queryPartTableReference.getColumnNames() );
final QuerySpec querySpec = (QuerySpec) queryPart;
final QuerySpec emulationQuerySpec = (QuerySpec) emulationQueryPart;
final List<SqlSelection> sqlSelections = emulationQuerySpec.getSelectClause().getSqlSelections();
final List<SortSpecification> sortSpecifications = queryPart.getSortSpecifications();
@ -6519,8 +6500,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
}
protected Predicate determineLateralEmulationPredicate(TableGroup tableGroup) {
if ( tableGroup.getPrimaryTableReference() instanceof QueryPartTableReference ) {
final QueryPartTableReference tableReference = (QueryPartTableReference) tableGroup.getPrimaryTableReference();
if ( tableGroup.getPrimaryTableReference() instanceof QueryPartTableReference tableReference ) {
final List<String> columnNames = tableReference.getColumnNames();
final List<ColumnReference> columnReferences = new ArrayList<>( columnNames.size() );
final SelectStatement statement = tableReference.getStatement();
@ -6810,33 +6790,26 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
private boolean isNullsFirst(SortSpecification sortSpecification) {
Nulls nullPrecedence = sortSpecification.getNullPrecedence();
if ( nullPrecedence == null || nullPrecedence == Nulls.NONE ) {
switch ( dialect.getNullOrdering() ) {
case FIRST:
nullPrecedence = Nulls.FIRST;
break;
case LAST:
nullPrecedence = Nulls.LAST;
break;
case SMALLEST:
nullPrecedence = sortSpecification.getSortOrder() == SortDirection.ASCENDING
? Nulls.FIRST
: Nulls.LAST;
break;
case GREATEST:
nullPrecedence = sortSpecification.getSortOrder() == SortDirection.DESCENDING
? Nulls.FIRST
: Nulls.LAST;
break;
}
nullPrecedence = switch ( dialect.getNullOrdering() ) {
case FIRST -> Nulls.FIRST;
case LAST -> Nulls.LAST;
case SMALLEST ->
sortSpecification.getSortOrder() == SortDirection.ASCENDING
? Nulls.FIRST
: Nulls.LAST;
case GREATEST ->
sortSpecification.getSortOrder() == SortDirection.DESCENDING
? Nulls.FIRST
: Nulls.LAST;
};
}
return nullPrecedence == Nulls.FIRST;
}
private int getSortSelectionIndex(QuerySpec querySpec, SortSpecification sortSpecification) {
final Expression sortExpression = sortSpecification.getSortExpression();
if ( sortExpression instanceof SqlSelectionExpression ) {
final SqlSelection selection = ( (SqlSelectionExpression) sortExpression ).getSelection();
return selection.getValuesArrayPosition();
if ( sortExpression instanceof SqlSelectionExpression selectionExpression ) {
return selectionExpression.getSelection().getValuesArrayPosition();
}
else {
final List<SqlSelection> sqlSelections = querySpec.getSelectClause().getSqlSelections();
@ -7149,8 +7122,6 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
/**
* Renders a parameter marker for the given position
* @param jdbcParameter
* @param position
*/
protected void renderParameterAsParameter(int position, JdbcParameter jdbcParameter) {
final JdbcType jdbcType = jdbcParameter.getExpressionType().getJdbcMapping( 0 ).getJdbcType();
@ -8089,8 +8060,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
}
private void visitJunctionPredicate(Junction.Nature nature, Predicate p) {
if ( p instanceof Junction ) {
final Junction junction = (Junction) p;
if ( p instanceof Junction junction ) {
// If we have the same nature, or if this is a disjunction and the operand is a conjunction,
// then we don't need parenthesis, because the AND operator binds stronger
if ( nature == junction.getNature() || nature == Junction.Nature.DISJUNCTION ) {
@ -8169,8 +8139,8 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
// Check if escapeCharacter was explicitly set and do nothing in that case
// Note: this does not cover cases where it's set via parameter binding
boolean isExplicitEscape = false;
if ( escapeCharacter instanceof Literal ) {
Object literalValue = ( (Literal) escapeCharacter ).getLiteralValue();
if ( escapeCharacter instanceof Literal literal ) {
Object literalValue = literal.getLiteralValue();
isExplicitEscape = literalValue != null && !literalValue.toString().equals( "" );
}
if ( isExplicitEscape ) {
@ -8467,17 +8437,13 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
if ( !supportsRowValueConstructorSyntax() ) {
return true;
}
switch ( operator ) {
case LESS_THAN:
case LESS_THAN_OR_EQUAL:
case GREATER_THAN:
case GREATER_THAN_OR_EQUAL:
return !supportsRowValueConstructorGtLtSyntax();
case DISTINCT_FROM:
case NOT_DISTINCT_FROM:
return !supportsRowValueConstructorDistinctFromSyntax();
}
return false;
return switch (operator) {
case LESS_THAN, LESS_THAN_OR_EQUAL, GREATER_THAN, GREATER_THAN_OR_EQUAL ->
!supportsRowValueConstructorGtLtSyntax();
case DISTINCT_FROM, NOT_DISTINCT_FROM ->
!supportsRowValueConstructorDistinctFromSyntax();
default -> false;
};
}
/**
@ -8684,14 +8650,14 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
}
private String[] determineKeyColumnNames(ModelPart modelPart) {
if ( modelPart instanceof EntityPersister) {
return ( (EntityPersister) modelPart ).getIdentifierColumnNames();
if ( modelPart instanceof EntityPersister entityPersister ) {
return entityPersister.getIdentifierColumnNames();
}
else if ( modelPart instanceof PluralAttributeMapping ) {
return ((PluralAttributeMapping) modelPart).getCollectionDescriptor().getKeyColumnAliases( null );
else if ( modelPart instanceof PluralAttributeMapping pluralAttributeMapping ) {
return pluralAttributeMapping.getCollectionDescriptor().getKeyColumnAliases( null );
}
else if ( modelPart instanceof EntityAssociationMapping ) {
return determineKeyColumnNames( ( (EntityAssociationMapping) modelPart ).getAssociatedEntityMappingType() );
else if ( modelPart instanceof EntityAssociationMapping entityAssociationMapping ) {
return determineKeyColumnNames( entityAssociationMapping.getAssociatedEntityMappingType() );
}
return null;
}