mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-17 00:24:57 +00:00
Introduce FunctionExpression in SQL AST and remove shallowness handling in sqm to sql converter
This commit is contained in:
parent
7934625688
commit
682678fbe5
@ -90,6 +90,7 @@ public SelfRenderingFunctionSqlAstExpression expression(
|
||||
SqlAstNode... sqlAstArguments) {
|
||||
Expression to = (Expression) sqlAstArguments[2];
|
||||
return new SelfRenderingFunctionSqlAstExpression(
|
||||
getName(),
|
||||
this::render,
|
||||
asList( sqlAstArguments ),
|
||||
impliedResultType,
|
||||
|
@ -95,6 +95,7 @@ public SelfRenderingFunctionSqlAstExpression expression(
|
||||
SqlAstNode... sqlAstArguments) {
|
||||
DurationUnit field = (DurationUnit) sqlAstArguments[0];
|
||||
return new SelfRenderingFunctionSqlAstExpression(
|
||||
getName(),
|
||||
this::render,
|
||||
asList( sqlAstArguments ),
|
||||
impliedResultType,
|
||||
|
@ -22,6 +22,7 @@
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
import org.hibernate.sql.ast.tree.expression.FunctionExpression;
|
||||
import org.hibernate.sql.ast.tree.expression.SelfRenderingExpression;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
@ -40,17 +41,20 @@
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SelfRenderingFunctionSqlAstExpression
|
||||
implements SelfRenderingExpression, Selectable, SqlExpressable, DomainResultProducer {
|
||||
implements SelfRenderingExpression, Selectable, SqlExpressable, DomainResultProducer, FunctionExpression {
|
||||
private final String functionName;
|
||||
private final FunctionRenderingSupport renderer;
|
||||
private final List<SqlAstNode> sqlAstArguments;
|
||||
private final AllowableFunctionReturnType<?> type;
|
||||
private final MappingModelExpressable<?> expressable;
|
||||
|
||||
public SelfRenderingFunctionSqlAstExpression(
|
||||
String functionName,
|
||||
FunctionRenderingSupport renderer,
|
||||
List<SqlAstNode> sqlAstArguments,
|
||||
AllowableFunctionReturnType<?> type,
|
||||
MappingModelExpressable<?> expressable) {
|
||||
this.functionName = functionName;
|
||||
this.renderer = renderer;
|
||||
this.sqlAstArguments = sqlAstArguments;
|
||||
this.type = type;
|
||||
@ -58,6 +62,16 @@ public SelfRenderingFunctionSqlAstExpression(
|
||||
this.expressable = expressable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFunctionName() {
|
||||
return functionName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SqlAstNode> getArguments() {
|
||||
return sqlAstArguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingModelExpressable getExpressionType() {
|
||||
return expressable;
|
||||
|
@ -31,9 +31,7 @@
|
||||
public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
|
||||
private final AllowableFunctionReturnType<T> impliedResultType;
|
||||
private final FunctionReturnTypeResolver returnTypeResolver;
|
||||
private final String name;
|
||||
private final FunctionRenderingSupport renderingSupport;
|
||||
private final List<SqmTypedNode<?>> arguments;
|
||||
private AllowableFunctionReturnType<?> resultType;
|
||||
|
||||
public SelfRenderingSqmFunction(
|
||||
@ -44,41 +42,38 @@ public SelfRenderingSqmFunction(
|
||||
FunctionReturnTypeResolver returnTypeResolver,
|
||||
NodeBuilder nodeBuilder,
|
||||
String name) {
|
||||
super( name, descriptor, impliedResultType, nodeBuilder );
|
||||
super( name, descriptor, impliedResultType, arguments, nodeBuilder );
|
||||
this.renderingSupport = renderingSupport;
|
||||
this.arguments = arguments;
|
||||
this.impliedResultType = impliedResultType;
|
||||
this.returnTypeResolver = returnTypeResolver;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<SqmTypedNode<?>> getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
public FunctionRenderingSupport getRenderingSupport() {
|
||||
return renderingSupport;
|
||||
}
|
||||
|
||||
private static List<SqlAstNode> resolveSqlAstArguments(List<SqmTypedNode<?>> sqmArguments, SqmToSqlAstConverter walker) {
|
||||
protected static List<SqlAstNode> resolveSqlAstArguments(List<SqmTypedNode<?>> sqmArguments, SqmToSqlAstConverter walker) {
|
||||
if ( sqmArguments == null || sqmArguments.isEmpty() ) {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
final ArrayList<SqlAstNode> sqlAstArguments = new ArrayList<>();
|
||||
final ArrayList<SqlAstNode> sqlAstArguments = new ArrayList<>( sqmArguments.size() );
|
||||
for ( SqmTypedNode<?> sqmArgument : sqmArguments ) {
|
||||
sqlAstArguments.add((SqlAstNode) ((SqmVisitableNode) sqmArgument).accept(walker));
|
||||
sqlAstArguments.add( (SqlAstNode) ( (SqmVisitableNode) sqmArgument ).accept( walker ) );
|
||||
}
|
||||
return sqlAstArguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SelfRenderingFunctionSqlAstExpression convertToSqlAst(SqmToSqlAstConverter walker) {
|
||||
resolveResultType( walker.getCreationContext().getDomainModel().getTypeConfiguration() );
|
||||
final AllowableFunctionReturnType<?> resultType = resolveResultType(
|
||||
walker.getCreationContext().getDomainModel().getTypeConfiguration()
|
||||
);
|
||||
|
||||
return new SelfRenderingFunctionSqlAstExpression(
|
||||
getFunctionName(),
|
||||
getRenderingSupport(),
|
||||
resolveSqlAstArguments( getArguments(), walker),
|
||||
resolveSqlAstArguments( getArguments(), walker ),
|
||||
resultType,
|
||||
getMappingModelExpressable( walker, resultType )
|
||||
);
|
||||
@ -93,7 +88,7 @@ public SqmExpressable<T> getNodeType() {
|
||||
return nodeType;
|
||||
}
|
||||
|
||||
private void resolveResultType(TypeConfiguration typeConfiguration) {
|
||||
protected AllowableFunctionReturnType<?> resolveResultType(TypeConfiguration typeConfiguration) {
|
||||
if ( resultType == null ) {
|
||||
resultType = returnTypeResolver.resolveFunctionReturnType(
|
||||
impliedResultType,
|
||||
@ -102,9 +97,10 @@ private void resolveResultType(TypeConfiguration typeConfiguration) {
|
||||
);
|
||||
setExpressableType( resultType );
|
||||
}
|
||||
return resultType;
|
||||
}
|
||||
|
||||
private MappingModelExpressable<?> getMappingModelExpressable(
|
||||
protected MappingModelExpressable<?> getMappingModelExpressable(
|
||||
SqmToSqlAstConverter walker,
|
||||
AllowableFunctionReturnType<?> resultType) {
|
||||
MappingModelExpressable<?> mapping;
|
||||
@ -131,17 +127,12 @@ private MappingModelExpressable<?> getMappingModelExpressable(
|
||||
return null; // this works at least approximately
|
||||
}
|
||||
},
|
||||
resolveSqlAstArguments( arguments, walker )
|
||||
resolveSqlAstArguments( getArguments(), walker )
|
||||
);
|
||||
}
|
||||
return mapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFunctionName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySqlSelections(DomainResultCreationState creationState) {
|
||||
//implemented on SelfRenderingFunctionSqlAstExpression
|
||||
|
@ -293,13 +293,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||
|
||||
private static final Logger log = Logger.getLogger( BaseSqmToSqlAstConverter.class );
|
||||
|
||||
protected enum Shallowness {
|
||||
NONE,
|
||||
CTOR,
|
||||
FUNCTION,
|
||||
SUBQUERY
|
||||
}
|
||||
|
||||
private final SqlAstCreationContext creationContext;
|
||||
private final SqmStatement<?> statement;
|
||||
|
||||
@ -326,7 +319,6 @@ protected enum Shallowness {
|
||||
private FromClauseIndex lastPoppedFromClauseIndex;
|
||||
|
||||
private final Stack<Clause> currentClauseStack = new StandardStack<>();
|
||||
private final Stack<Shallowness> shallownessStack = new StandardStack<>( Shallowness.NONE );
|
||||
|
||||
private SqmByUnit appliedByUnit;
|
||||
private Expression adjustedTimestamp;
|
||||
@ -1331,7 +1323,6 @@ protected void applyCollectionFilterPredicates(QuerySpec sqlQuerySpec) {
|
||||
@Override
|
||||
public SelectClause visitSelectClause(SqmSelectClause selectClause) {
|
||||
currentClauseStack.push( Clause.SELECT );
|
||||
shallownessStack.push( Shallowness.SUBQUERY );
|
||||
try {
|
||||
super.visitSelectClause( selectClause );
|
||||
|
||||
@ -1340,7 +1331,6 @@ public SelectClause visitSelectClause(SqmSelectClause selectClause) {
|
||||
return sqlSelectClause;
|
||||
}
|
||||
finally {
|
||||
shallownessStack.pop();
|
||||
currentClauseStack.pop();
|
||||
}
|
||||
}
|
||||
@ -2297,12 +2287,10 @@ public Object visitCollate(SqmCollate<?> sqmCollate) {
|
||||
@Override
|
||||
public Expression visitFunction(SqmFunction sqmFunction) {
|
||||
inferableTypeAccessStack.push( () -> null );
|
||||
shallownessStack.push( Shallowness.FUNCTION );
|
||||
try {
|
||||
return sqmFunction.convertToSqlAst( this );
|
||||
}
|
||||
finally {
|
||||
shallownessStack.pop();
|
||||
inferableTypeAccessStack.pop();
|
||||
}
|
||||
}
|
||||
@ -2319,19 +2307,11 @@ public Object visitDistinct(SqmDistinct sqmDistinct) {
|
||||
|
||||
@Override
|
||||
public Object visitTrimSpecification(SqmTrimSpecification specification) {
|
||||
shallownessStack.push( Shallowness.FUNCTION );
|
||||
try {
|
||||
return new TrimSpecification( specification.getSpecification() );
|
||||
}
|
||||
finally {
|
||||
shallownessStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitCastTarget(SqmCastTarget target) {
|
||||
shallownessStack.push( Shallowness.FUNCTION );
|
||||
try {
|
||||
BasicValuedMapping targetType = (BasicValuedMapping) target.getType();
|
||||
if ( targetType instanceof BasicType<?> ) {
|
||||
targetType = InferredBasicValueResolver.resolveSqlTypeIndicators( this, (BasicType<?>) targetType );
|
||||
@ -2343,38 +2323,22 @@ public Object visitCastTarget(SqmCastTarget target) {
|
||||
target.getScale()
|
||||
);
|
||||
}
|
||||
finally {
|
||||
shallownessStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitExtractUnit(SqmExtractUnit unit) {
|
||||
shallownessStack.push( Shallowness.FUNCTION );
|
||||
try {
|
||||
return new ExtractUnit(
|
||||
unit.getUnit(),
|
||||
(BasicValuedMapping) unit.getType()
|
||||
);
|
||||
}
|
||||
finally {
|
||||
shallownessStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitDurationUnit(SqmDurationUnit unit) {
|
||||
shallownessStack.push( Shallowness.FUNCTION );
|
||||
try {
|
||||
return new DurationUnit(
|
||||
unit.getUnit(),
|
||||
(BasicValuedMapping) unit.getType()
|
||||
);
|
||||
}
|
||||
finally {
|
||||
shallownessStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitFormat(SqmFormat sqmFormat) {
|
||||
@ -2764,19 +2728,12 @@ public Object visitFormat(SqmFormat sqmFormat) {
|
||||
|
||||
@Override
|
||||
public Object visitUnaryOperationExpression(SqmUnaryOperation expression) {
|
||||
shallownessStack.push( Shallowness.NONE );
|
||||
|
||||
try {
|
||||
return new UnaryOperation(
|
||||
interpret( expression.getOperation() ),
|
||||
toSqlExpression( expression.getOperand().accept( this ) ),
|
||||
(BasicValuedMapping) determineValueMapping( expression.getOperand() )
|
||||
);
|
||||
}
|
||||
finally {
|
||||
shallownessStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
private UnaryArithmeticOperator interpret(UnaryArithmeticOperator operator) {
|
||||
return operator;
|
||||
@ -2784,9 +2741,6 @@ private UnaryArithmeticOperator interpret(UnaryArithmeticOperator operator) {
|
||||
|
||||
@Override
|
||||
public Object visitBinaryArithmeticExpression(SqmBinaryArithmetic expression) {
|
||||
shallownessStack.push( Shallowness.NONE );
|
||||
|
||||
try {
|
||||
SqmExpression leftOperand = expression.getLeftHandOperand();
|
||||
SqmExpression rightOperand = expression.getRightHandOperand();
|
||||
|
||||
@ -2828,10 +2782,6 @@ else if ( durationToRight && appliedByUnit != null ) {
|
||||
);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
shallownessStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
private BasicValuedMapping getExpressionType(SqmBinaryArithmetic expression) {
|
||||
SqmExpressable leftHandOperandType = expression.getLeftHandOperand().getNodeType();
|
||||
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.sql.ast.tree.expression;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
|
||||
/**
|
||||
* Models a function expression at the SQL AST level.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public interface FunctionExpression extends Expression {
|
||||
|
||||
String getFunctionName();
|
||||
|
||||
List<SqlAstNode> getArguments();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user