Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder Maven / Gradle / Ivy
/*
* 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.query.sqm.internal;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.Tuple;
import javax.persistence.criteria.CollectionJoin;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.ListJoin;
import javax.persistence.criteria.MapJoin;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Selection;
import javax.persistence.criteria.SetJoin;
import javax.persistence.criteria.Subquery;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.NullPrecedence;
import org.hibernate.QueryException;
import org.hibernate.SortOrder;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.metamodel.model.domain.BasicDomainType;
import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.metamodel.model.domain.JpaMetamodel;
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
import org.hibernate.query.BinaryArithmeticOperator;
import org.hibernate.query.ComparisonOperator;
import org.hibernate.query.TrimSpec;
import org.hibernate.query.UnaryArithmeticOperator;
import org.hibernate.query.criteria.JpaCoalesce;
import org.hibernate.query.criteria.JpaCompoundSelection;
import org.hibernate.query.criteria.JpaExpression;
import org.hibernate.query.criteria.JpaSelection;
import org.hibernate.query.internal.QueryHelper;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.SqmQuerySource;
import org.hibernate.query.sqm.produce.function.SqmFunctionTemplate;
import org.hibernate.query.sqm.function.SqmCastTarget;
import org.hibernate.query.sqm.function.SqmDistinct;
import org.hibernate.query.sqm.function.SqmTrimSpecification;
import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
import org.hibernate.query.sqm.tree.domain.SqmBagJoin;
import org.hibernate.query.sqm.tree.domain.SqmListJoin;
import org.hibernate.query.sqm.tree.domain.SqmMapJoin;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.domain.SqmSetJoin;
import org.hibernate.query.sqm.tree.domain.SqmSingularJoin;
import org.hibernate.query.sqm.tree.expression.SqmBinaryArithmetic;
import org.hibernate.query.sqm.tree.expression.SqmCaseSearched;
import org.hibernate.query.sqm.tree.expression.SqmCaseSimple;
import org.hibernate.query.sqm.tree.expression.SqmCollectionSize;
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
import org.hibernate.query.sqm.tree.expression.SqmLiteralNull;
import org.hibernate.query.sqm.tree.expression.SqmRestrictedSubQueryExpression;
import org.hibernate.query.sqm.tree.expression.SqmTuple;
import org.hibernate.query.sqm.tree.expression.SqmUnaryOperation;
import org.hibernate.query.sqm.function.SqmCoalesce;
import org.hibernate.query.sqm.tree.from.SqmRoot;
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmBooleanExpressionPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmInListPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmInPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmInSubQueryPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmLikePredicate;
import org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmOrPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiationArgument;
import org.hibernate.query.sqm.tree.select.SqmJpaCompoundSelection;
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
import org.hibernate.query.sqm.tree.select.SqmSortSpecification;
import org.hibernate.query.sqm.tree.select.SqmSubQuery;
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.query.sqm.function.SqmFunction;
import org.hibernate.type.StandardBasicTypes;
import static java.util.Arrays.asList;
import static org.hibernate.query.internal.QueryHelper.highestPrecedenceType;
/**
* Acts as a JPA {@link javax.persistence.criteria.CriteriaBuilder} by
* using SQM nodes as the JPA Criteria nodes
*
* @author Steve Ebersole
*/
public class SqmCriteriaNodeBuilder implements NodeBuilder {
public static SqmCriteriaNodeBuilder create(SessionFactoryImplementor sf) {
return new SqmCriteriaNodeBuilder(
sf.getQueryEngine(),
sf.getMetamodel().getJpaMetamodel(),
sf.getServiceRegistry()
);
}
private final QueryEngine queryEngine;
private final JpaMetamodel domainModel;
private final ServiceRegistry serviceRegistry;
public SqmCriteriaNodeBuilder(
QueryEngine queryEngine,
JpaMetamodel domainModel,
ServiceRegistry serviceRegistry) {
this.queryEngine = queryEngine;
this.domainModel = domainModel;
this.serviceRegistry = serviceRegistry;
}
@Override
public JpaMetamodel getDomainModel() {
return domainModel;
}
@Override
public ServiceRegistry getServiceRegistry() {
return serviceRegistry;
}
@Override
public QueryEngine getQueryEngine() {
return queryEngine;
}
public void close() {
// for potential future use
}
@Override
public SqmSelectStatement createQuery() {
return new SqmSelectStatement<>( Object.class, this );
}
@Override
public SqmSelectStatement createQuery(Class resultClass) {
return new SqmSelectStatement<>( resultClass, this );
}
@Override
public SqmSelectStatement createTupleQuery() {
return new SqmSelectStatement<>( Tuple.class, this );
}
@Override
public SqmUpdateStatement createCriteriaUpdate(Class targetEntity) {
return new SqmUpdateStatement<>( targetEntity, this );
}
@Override
public SqmDeleteStatement createCriteriaDelete(Class targetEntity) {
return new SqmDeleteStatement<>( targetEntity, SqmQuerySource.CRITERIA, this );
}
@Override
public SqmInsertSelectStatement createCriteriaInsertSelect(Class targetEntity) {
return new SqmInsertSelectStatement<>( targetEntity, this );
}
@Override
public SqmExpression cast(JpaExpression expression, Class castTargetJavaType) {
//noinspection unchecked
BasicDomainType type = getTypeConfiguration().standardBasicTypeForJavaType( castTargetJavaType );
//noinspection unchecked
return getFunctionTemplate("cast").makeSqmFunctionExpression(
asList( (SqmTypedNode) expression, new SqmCastTarget<>( type, this ) ),
type,
queryEngine
);
}
@Override
public SqmPredicate wrap(Expression expression) {
if ( expression instanceof SqmPredicate ) {
return (SqmPredicate) expression;
}
return new SqmBooleanExpressionPredicate( (SqmExpression) expression, this );
}
// todo (6.0) : wrapping a non-`SqmPredicate` `Expression` expression should be as easy as an impl
@Override
public SqmPredicate wrap(Expression... expressions) {
SqmPredicate lhs = (SqmPredicate) expressions[0];
SqmPredicate rhs = (SqmPredicate) expressions[0];
SqmPredicate predicate = new SqmAndPredicate( lhs, rhs, this );
if ( expressions.length > 2 ) {
for ( Expression expression : expressions ) {
final SqmPredicate newRhs;
if ( expression instanceof SqmPredicate ) {
newRhs = (SqmPredicate) expression;
}
else {
//noinspection unchecked
return new SqmBooleanExpressionPredicate( (SqmExpression) expression, this );
}
predicate = new SqmAndPredicate( predicate, newRhs, this );
}
}
return predicate;
}
@Override
public SqmPath treat(Path path, Class type) {
//noinspection unchecked
return ( (SqmPath) path ).treatAs( type );
}
@Override
public SqmRoot treat(Root root, Class type) {
//noinspection unchecked
return ( (SqmRoot) root ).treatAs( type );
}
@Override
public SqmSingularJoin treat(Join join, Class type) {
//noinspection unchecked
return ( (SqmSingularJoin) join ).treatAs( type );
}
@Override
public SqmBagJoin treat(CollectionJoin join, Class type) {
//noinspection unchecked
return ( (SqmBagJoin) join ).treatAs( type );
}
@Override
public SqmSetJoin treat(SetJoin join, Class type) {
//noinspection unchecked
return ( (SqmSetJoin) join ).treatAs( type );
}
@Override
public SqmListJoin treat(ListJoin join, Class type) {
//noinspection unchecked
return ( (SqmListJoin) join ).treatAs( type );
}
@Override
public SqmMapJoin treat(MapJoin join, Class type) {
//noinspection unchecked
return ( (SqmMapJoin) join ).treatAs( type );
}
@Override
public JpaCompoundSelection construct(Class resultClass, Selection[] arguments) {
final SqmDynamicInstantiation instantiation;
if ( List.class.equals( resultClass ) ) {
instantiation = SqmDynamicInstantiation.forListInstantiation( this );
}
else if ( Map.class.equals( resultClass ) ) {
instantiation = SqmDynamicInstantiation.forMapInstantiation( this );
}
else {
instantiation = SqmDynamicInstantiation.forClassInstantiation( resultClass, this );
}
for ( Selection argument : arguments ) {
//noinspection unchecked
instantiation.addArgument(
new SqmDynamicInstantiationArgument(
(SqmSelectableNode) argument,
argument.getAlias(),
this
)
);
}
//noinspection unchecked
return instantiation;
}
@Override
public JpaCompoundSelection construct(Class resultClass, List> arguments) {
final SqmDynamicInstantiation instantiation;
if ( List.class.equals( resultClass ) ) {
instantiation = SqmDynamicInstantiation.forListInstantiation( this );
}
else if ( Map.class.equals( resultClass ) ) {
instantiation = SqmDynamicInstantiation.forMapInstantiation( this );
}
else {
instantiation = SqmDynamicInstantiation.forClassInstantiation( resultClass, this );
}
for ( Selection argument : arguments ) {
//noinspection unchecked
instantiation.addArgument(
new SqmDynamicInstantiationArgument(
(SqmSelectableNode) argument,
argument.getAlias(),
this
)
);
}
//noinspection unchecked
return instantiation;
}
@Override
public SqmSortSpecification sort(JpaExpression sortExpression, SortOrder sortOrder, NullPrecedence nullPrecedence) {
return new SqmSortSpecification( (SqmExpression) sortExpression, sortOrder, nullPrecedence );
}
@Override
public SqmSortSpecification sort(JpaExpression sortExpression, SortOrder sortOrder) {
return new SqmSortSpecification( (SqmExpression) sortExpression, sortOrder );
}
@Override
public SqmSortSpecification sort(JpaExpression sortExpression) {
return new SqmSortSpecification( (SqmExpression) sortExpression );
}
@Override
public SqmSortSpecification asc(Expression x) {
return new SqmSortSpecification( (SqmExpression) x, SortOrder.ASCENDING );
}
@Override
public SqmSortSpecification desc(Expression x) {
return new SqmSortSpecification( (SqmExpression) x, SortOrder.DESCENDING );
}
@Override
public JpaCompoundSelection tuple(Selection[] selections) {
//noinspection unchecked
return new SqmJpaCompoundSelection(
ArrayHelper.toList( selections ),
getTypeConfiguration().getJavaTypeDescriptorRegistry().getDescriptor( Tuple.class ),
this
);
}
@Override
public JpaCompoundSelection tuple(List> selections) {
//noinspection unchecked
return new SqmJpaCompoundSelection(
selections,
getTypeConfiguration().getJavaTypeDescriptorRegistry().getDescriptor( Tuple.class ),
this
);
}
@Override
public SqmTuple tuple(Class tupleType, JpaExpression... expressions) {
//noinspection unchecked
return new SqmTuple(
(List) asList( expressions ),
// getTypeConfiguration().standardExpressableTypeForJavaType( tupleType ),
this
);
}
@Override
public SqmTuple tuple(Class tupleType, List> expressions) {
//noinspection unchecked
return new SqmTuple(
(List) expressions,
// getTypeConfiguration().standardExpressableTypeForJavaType( tupleType ),
this
);
}
@Override
public SqmTuple tuple(DomainType tupleType, JpaExpression... expressions) {
//noinspection unchecked
return new SqmTuple(
(List) asList( expressions ),
tupleType,
this
);
}
@Override
public SqmTuple tuple(
DomainType tupleType, List> expressions) {
//noinspection unchecked
return new SqmTuple(
new ArrayList<>((List) expressions),
tupleType,
this
);
}
@Override
public JpaCompoundSelection array(Selection[] selections) {
//noinspection unchecked
return new SqmJpaCompoundSelection(
ArrayHelper.toList( selections ),
getTypeConfiguration().getJavaTypeDescriptorRegistry().getDescriptor( Object[].class ),
this
);
}
@Override
public JpaCompoundSelection array(List> selections) {
//noinspection unchecked
return new SqmJpaCompoundSelection(
selections,
getTypeConfiguration().getJavaTypeDescriptorRegistry().getDescriptor( Object[].class ),
this
);
}
@Override
public SqmExpression avg(Expression argument) {
//noinspection unchecked
return getFunctionTemplate("avg").makeSqmFunctionExpression(
(SqmTypedNode) argument,
StandardBasicTypes.DOUBLE,
queryEngine
);
}
@Override
public SqmExpression sum(Expression argument) {
return getFunctionTemplate("sum").makeSqmFunctionExpression(
(SqmTypedNode) argument,
(AllowableFunctionReturnType) ((SqmExpression) argument).getNodeType(),
queryEngine
);
}
@Override
public SqmExpression sumAsLong(Expression argument) {
return cast( sum( argument ), Long.class );
}
@Override
public SqmExpression sumAsDouble(Expression argument) {
return cast( sum( argument ), Double.class );
}
@Override
public SqmExpression max(Expression argument) {
return getFunctionTemplate("max").makeSqmFunctionExpression(
(SqmTypedNode) argument,
(AllowableFunctionReturnType) ((SqmExpression) argument).getNodeType(),
queryEngine
);
}
@Override
public SqmExpression min(Expression argument) {
return getFunctionTemplate("min").makeSqmFunctionExpression(
(SqmTypedNode) argument,
(AllowableFunctionReturnType) ((SqmExpression) argument).getNodeType(),
queryEngine
);
}
@Override
public > SqmExpression greatest(Expression argument) {
throw new NotYetImplementedFor6Exception();
}
@Override
public > SqmExpression least(Expression argument) {
throw new NotYetImplementedFor6Exception();
}
@Override
public SqmExpression count(Expression argument) {
//noinspection unchecked
return getFunctionTemplate("count").makeSqmFunctionExpression(
(SqmTypedNode) argument,
StandardBasicTypes.LONG,
queryEngine
);
}
@Override
public SqmExpression countDistinct(Expression argument) {
//noinspection unchecked
return getFunctionTemplate("count").makeSqmFunctionExpression(
new SqmDistinct<>( (SqmExpression) argument, getQueryEngine().getCriteriaBuilder() ),
StandardBasicTypes.LONG,
queryEngine
);
}
@Override
public SqmExpression neg(Expression x) {
final SqmExpression sqmExpression = (SqmExpression) x;
return new SqmUnaryOperation<>(
UnaryArithmeticOperator.UNARY_MINUS,
sqmExpression
);
}
@Override
public SqmExpression abs(Expression x) {
return getFunctionTemplate("abs").makeSqmFunctionExpression(
(SqmTypedNode) x,
(AllowableFunctionReturnType) ((SqmExpression) x).getNodeType(),
queryEngine
);
}
@Override
public SqmExpression sum(Expression x, Expression y) {
return createSqmArithmeticNode( BinaryArithmeticOperator.ADD, (SqmExpression) x, (SqmExpression) y );
}
private SqmExpression createSqmArithmeticNode(
BinaryArithmeticOperator operator,
SqmExpression leftHandExpression,
SqmExpression rightHandExpression) {
//noinspection unchecked
return new SqmBinaryArithmetic(
operator,
leftHandExpression,
rightHandExpression,
getDomainModel().getTypeConfiguration().resolveArithmeticType(
leftHandExpression.getNodeType(),
rightHandExpression.getNodeType(),
operator
),
this
);
}
@Override
public SqmExpression sum(Expression x, N y) {
return createSqmArithmeticNode( BinaryArithmeticOperator.ADD, (SqmExpression) x, literal( y ) );
}
@Override
public SqmExpression sum(N x, Expression y) {
return createSqmArithmeticNode( BinaryArithmeticOperator.ADD, literal( x ), (SqmExpression) y );
}
@Override
public SqmExpression prod(Expression x, Expression y) {
return createSqmArithmeticNode( BinaryArithmeticOperator.ADD, literal( x ), (SqmExpression) y );
}
@Override
public SqmExpression prod(Expression x, N y) {
return sum( x, y );
}
@Override
public SqmExpression prod(N x, Expression y) {
return sum( x, y );
}
@Override
public SqmExpression diff(Expression x, Expression y) {
return createSqmArithmeticNode(
BinaryArithmeticOperator.SUBTRACT,
(SqmExpression) x,
(SqmExpression) y
);
}
@Override
public SqmExpression diff(Expression x, N y) {
return createSqmArithmeticNode(
BinaryArithmeticOperator.SUBTRACT,
(SqmExpression) x,
literal( y )
);
}
@Override
public SqmExpression diff(N x, Expression y) {
return createSqmArithmeticNode(
BinaryArithmeticOperator.SUBTRACT,
literal( x ),
(SqmExpression) y
);
}
@Override
public SqmExpression quot(Expression x, Expression y) {
return createSqmArithmeticNode(
BinaryArithmeticOperator.QUOT,
(SqmExpression) x,
(SqmExpression) y
);
}
@Override
public SqmExpression quot(Expression x, Number y) {
return createSqmArithmeticNode(
BinaryArithmeticOperator.QUOT,
(SqmExpression) x,
literal( y )
);
}
@Override
public SqmExpression quot(Number x, Expression y) {
return createSqmArithmeticNode(
BinaryArithmeticOperator.QUOT,
literal( x ),
(SqmExpression) y
);
}
@Override
public SqmExpression mod(Expression x, Expression y) {
return createSqmArithmeticNode(
BinaryArithmeticOperator.MODULO,
(SqmExpression) x,
(SqmExpression) y
);
}
@Override
public SqmExpression mod(Expression x, Integer y) {
return createSqmArithmeticNode(
BinaryArithmeticOperator.MODULO,
(SqmExpression) x,
literal( y )
);
}
@Override
public SqmExpression mod(Integer x, Expression y) {
return createSqmArithmeticNode(
BinaryArithmeticOperator.MODULO,
literal( x ),
(SqmExpression) y
);
}
@Override
public SqmExpression sqrt(Expression x) {
//noinspection unchecked
return getFunctionTemplate("sqrt").makeSqmFunctionExpression(
(SqmTypedNode) x,
(AllowableFunctionReturnType) QueryHelper.highestPrecedenceType2(
((SqmExpression) x).getNodeType(),
StandardBasicTypes.DOUBLE
),
queryEngine
);
}
@Override
@SuppressWarnings("unchecked")
public SqmExpression toLong(Expression number) {
return ( (SqmExpression) number ).asLong();
}
@Override
@SuppressWarnings("unchecked")
public SqmExpression toInteger(Expression number) {
return ( (SqmExpression) number ).asInteger();
}
@Override
@SuppressWarnings("unchecked")
public SqmExpression toFloat(Expression number) {
return ( (SqmExpression) number ).asFloat();
}
@Override
@SuppressWarnings("unchecked")
public SqmExpression toDouble(Expression number) {
return ( (SqmExpression) number ).asDouble();
}
@Override
@SuppressWarnings("unchecked")
public SqmExpression toBigDecimal(Expression number) {
return ( (SqmExpression) number ).asBigDecimal();
}
@Override
@SuppressWarnings("unchecked")
public SqmExpression toBigInteger(Expression number) {
return ( (SqmExpression) number ).asBigInteger();
}
@Override
@SuppressWarnings("unchecked")
public SqmExpression toString(Expression character) {
return ( (SqmExpression) character ).asString();
}
@Override
@SuppressWarnings("unchecked")
public SqmLiteral literal(T value) {
if ( value == null ) {
return (SqmLiteral) new SqmLiteralNull( this );
}
return new SqmLiteral(
value,
getTypeConfiguration().standardBasicTypeForJavaType( value.getClass() ),
this
);
}
@Override
public List> literals(T[] values) {
if ( values == null || values.length == 0 ) {
return Collections.emptyList();
}
final List> literals = new ArrayList<>();
for ( T value : values ) {
literals.add( literal( value ) );
}
return literals;
}
@Override
public List> literals(List values) {
if ( values == null || values.isEmpty() ) {
return Collections.emptyList();
}
final List> literals = new ArrayList<>();
for ( T value : values ) {
literals.add( literal( value ) );
}
return literals;
}
@Override
public SqmExpression nullLiteral(Class resultClass) {
//noinspection unchecked
return new SqmLiteralNull( getTypeConfiguration().standardBasicTypeForJavaType( resultClass ), this );
}
@Override
public JpaCriteriaParameter parameter(Class paramClass) {
//noinspection unchecked
return new JpaCriteriaParameter<>(
getTypeConfiguration().standardBasicTypeForJavaType( paramClass ),
false,
this
);
}
@Override
public JpaCriteriaParameter parameter(Class paramClass, String name) {
//noinspection unchecked
return new JpaCriteriaParameter<>(
name,
getTypeConfiguration().standardBasicTypeForJavaType( paramClass ),
false,
this
);
}
@Override
public SqmExpression concat(Expression x, Expression y) {
final SqmExpression xSqmExpression = (SqmExpression) x;
final SqmExpression ySqmExpression = (SqmExpression) y;
//noinspection unchecked
return getFunctionTemplate( "concat" ).makeSqmFunctionExpression(
asList( xSqmExpression, ySqmExpression ),
(AllowableFunctionReturnType) highestPrecedenceType(
xSqmExpression.getNodeType(),
ySqmExpression.getNodeType(),
StandardBasicTypes.STRING
),
getQueryEngine()
);
}
@Override
public SqmExpression concat(Expression x, String y) {
final SqmExpression xSqmExpression = (SqmExpression) x;
final SqmExpression ySqmExpression = literal( y );
//noinspection unchecked
return getFunctionTemplate( "concat" ).makeSqmFunctionExpression(
asList( xSqmExpression, ySqmExpression ),
(AllowableFunctionReturnType) highestPrecedenceType(
xSqmExpression.getNodeType(),
ySqmExpression.getNodeType(),
StandardBasicTypes.STRING
),
getQueryEngine()
);
}
@Override
public SqmExpression concat(String x, Expression y) {
final SqmExpression xSqmExpression = literal( x );
final SqmExpression ySqmExpression = (SqmExpression) y;
//noinspection unchecked
return getFunctionTemplate( "concat" ).makeSqmFunctionExpression(
asList( xSqmExpression, ySqmExpression ),
(AllowableFunctionReturnType) highestPrecedenceType(
xSqmExpression.getNodeType(),
ySqmExpression.getNodeType(),
StandardBasicTypes.STRING
),
getQueryEngine()
);
}
@Override
public SqmExpression concat(String x, String y) {
final SqmExpression xSqmExpression = literal( x );
final SqmExpression ySqmExpression = literal( y );
//noinspection unchecked
return getFunctionTemplate( "concat" ).makeSqmFunctionExpression(
asList( xSqmExpression, ySqmExpression ),
(AllowableFunctionReturnType) highestPrecedenceType(
xSqmExpression.getNodeType(),
ySqmExpression.getNodeType(),
StandardBasicTypes.STRING
),
getQueryEngine()
);
}
@Override
public SqmFunction substring(Expression source, Expression from) {
return createSubstringNode(
(SqmExpression) source,
(SqmExpression) from,
null
);
}
private SqmFunction createSubstringNode(SqmExpression source, SqmExpression from, SqmExpression len) {
final AllowableFunctionReturnType resultType = (AllowableFunctionReturnType) QueryHelper.highestPrecedenceType2(
source.getNodeType(),
StandardBasicTypes.STRING
);
//noinspection unchecked
return getFunctionTemplate( "substring" ).makeSqmFunctionExpression(
len==null ? asList( source, from ) : asList( source, from, len ),
resultType,
getQueryEngine()
);
}
@Override
public SqmFunction substring(Expression source, int from) {
return createSubstringNode(
(SqmExpression) source,
literal( from ),
null
);
}
@Override
public SqmFunction substring(Expression source, Expression from, Expression len) {
return createSubstringNode(
(SqmExpression) source,
(SqmExpression) from,
(SqmExpression) len
);
}
@Override
public SqmFunction substring(Expression source, int from, int len) {
return createSubstringNode(
(SqmExpression) source,
literal( from ),
literal( len )
);
}
@Override
public SqmFunction trim(Expression source) {
return createTrimNode( null, null, (SqmExpression) source );
}
private SqmFunction createTrimNode(TrimSpec trimSpecification, SqmExpression trimCharacter, SqmExpression source) {
final ArrayList> arguments = new ArrayList<>();
if ( trimSpecification != null ) {
arguments.add(
new SqmTrimSpecification( trimSpecification, this )
);
}
if ( trimCharacter != null ) {
arguments.add( trimCharacter );
}
arguments.add( source );
//noinspection unchecked
return getFunctionTemplate( "trim" ).makeSqmFunctionExpression(
arguments,
(AllowableFunctionReturnType) QueryHelper.highestPrecedenceType2( source.getNodeType(), StandardBasicTypes.STRING ),
getQueryEngine()
);
}
@Override
public SqmFunction trim(Trimspec ts, Expression source) {
return createTrimNode( convertTrimSpec( ts ), null, (SqmExpression) source );
}
private static TrimSpec convertTrimSpec(Trimspec jpaTs) {
if ( jpaTs == null ) {
return null;
}
switch ( jpaTs ) {
case BOTH: {
return TrimSpec.BOTH;
}
case LEADING: {
return TrimSpec.LEADING;
}
case TRAILING: {
return TrimSpec.TRAILING;
}
}
throw new QueryException( "Could not resolve JPA TrimSpec : " + jpaTs );
}
@Override
public SqmFunction trim(Expression trimChar, Expression source) {
return createTrimNode( null, (SqmExpression) trimChar, (SqmExpression) source );
}
@Override
public SqmFunction trim(Trimspec ts, Expression trimChar, Expression source) {
return createTrimNode( convertTrimSpec( ts ), (SqmExpression) trimChar, (SqmExpression) source );
}
@Override
public SqmFunction trim(char trimChar, Expression source) {
return createTrimNode( null, literal( trimChar ), (SqmExpression) source );
}
@Override
public SqmFunction trim(Trimspec ts, char trimChar, Expression source) {
return createTrimNode( convertTrimSpec( ts ), literal( trimChar ), (SqmExpression) source );
}
@Override
public SqmFunction lower(Expression x) {
final AllowableFunctionReturnType type = (AllowableFunctionReturnType) highestPrecedenceType(
((SqmExpression) x).getNodeType(),
StandardBasicTypes.STRING
);
//noinspection unchecked
return getFunctionTemplate( "lower" ).makeSqmFunctionExpression(
(SqmExpression) x,
type,
getQueryEngine()
);
}
@Override
public SqmFunction upper(Expression x) {
final AllowableFunctionReturnType type = (AllowableFunctionReturnType) highestPrecedenceType(
((SqmExpression) x).getNodeType(),
StandardBasicTypes.STRING
);
//noinspection unchecked
return getFunctionTemplate( "upper" ).makeSqmFunctionExpression(
(SqmExpression) x,
type,
getQueryEngine()
);
}
@Override
public SqmFunction length(Expression argument) {
//noinspection unchecked
return getFunctionTemplate( "length" ).makeSqmFunctionExpression(
(SqmExpression) argument,
(AllowableFunctionReturnType) highestPrecedenceType(
((SqmExpression) argument).getNodeType(),
StandardBasicTypes.INTEGER
),
getQueryEngine()
);
}
@Override
public SqmFunction locate(Expression source, Expression pattern) {
return createLocateFunctionNode(
(SqmExpression) source,
(SqmExpression) pattern,
null
);
}
private SqmFunction createLocateFunctionNode(
SqmExpression source,
SqmExpression pattern,
SqmExpression startPosition) {
final AllowableFunctionReturnType type = (AllowableFunctionReturnType) highestPrecedenceType(
source.getNodeType(),
StandardBasicTypes.INTEGER
);
final List> arguments;
if ( startPosition == null ) {
arguments = asList(
source,
pattern
);
}
else {
arguments = asList(
source,
pattern
);
}
//noinspection unchecked
return getFunctionTemplate("locate").makeSqmFunctionExpression(
arguments,
type,
getQueryEngine()
);
}
@Override
public SqmFunction locate(Expression source, String pattern) {
return createLocateFunctionNode(
(SqmExpression) source,
literal( pattern ),
null
);
}
@Override
public SqmFunction locate(Expression source, Expression pattern, Expression startPosition) {
return createLocateFunctionNode(
(SqmExpression) source,
(SqmExpression) pattern,
(SqmExpression) startPosition
);
}
@Override
public SqmFunction locate(Expression source, String pattern, int startPosition) {
return createLocateFunctionNode(
(SqmExpression) source,
literal( pattern ),
literal( startPosition )
);
}
@Override
public SqmFunction currentDate() {
//noinspection unchecked
// return getFunctionTemplate("current_date").makeSqmFunctionExpression(
// StandardBasicTypes.DATE,
// queryEngine
// );
throw new NotYetImplementedFor6Exception( getClass() );
}
@Override
public SqmFunction currentTimestamp() {
//noinspection unchecked
// return getFunctionTemplate("current_timestamp").makeSqmFunctionExpression(
// StandardBasicTypes.TIMESTAMP,
// queryEngine
// );
throw new NotYetImplementedFor6Exception( getClass() );
}
@Override
public SqmFunction currentTime() {
//noinspection unchecked
// return getFunctionTemplate("current_time").makeSqmFunctionExpression(
// StandardBasicTypes.TIME,
// queryEngine
// );
throw new NotYetImplementedFor6Exception( getClass() );
}
@Override
public SqmFunction currentInstant() {
//noinspection unchecked
return getFunctionTemplate("current_timestamp").makeSqmFunctionExpression(
StandardBasicTypes.INSTANT,
queryEngine
);
}
@Override
public SqmFunction function(String name, Class type, Expression[] args) {
final SqmFunctionTemplate functionTemplate = getFunctionTemplate(name);
if ( functionTemplate == null ) {
throw new SemanticException( "Could not resolve function named `" + name + "`" );
}
//noinspection unchecked
return functionTemplate.makeSqmFunctionExpression(
(List) expressionList( args ),
getTypeConfiguration().standardBasicTypeForJavaType( type ),
getQueryEngine()
);
}
private static List> expressionList(Expression[] jpaExpressions) {
if ( jpaExpressions == null || jpaExpressions.length == 0 ) {
return Collections.emptyList();
}
final ArrayList> sqmExpressions = new ArrayList<>();
for ( Expression jpaExpression : jpaExpressions ) {
sqmExpressions.add( (SqmExpression) jpaExpression );
}
return sqmExpressions;
}
@Override
public SqmRestrictedSubQueryExpression all(Subquery