HHH-13785 : HQL/Criteria function support
- preliminary work on updated tree handling. See SqmFunctionDescriptor, SqmFunctionRegistry and SqmFunction
This commit is contained in:
parent
6925fe5ab4
commit
3e89772bb8
|
@ -60,7 +60,7 @@ import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
|
|||
import org.hibernate.query.criteria.LiteralHandlingMode;
|
||||
import org.hibernate.query.hql.HqlTranslator;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.query.sqm.produce.function.SqmFunctionRegistry;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
||||
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
||||
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
|
||||
import org.hibernate.resource.jdbc.spi.StatementInspector;
|
||||
|
|
|
@ -32,7 +32,7 @@ import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
|
|||
import org.hibernate.query.criteria.LiteralHandlingMode;
|
||||
import org.hibernate.query.hql.HqlTranslator;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.query.sqm.produce.function.SqmFunctionRegistry;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
||||
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
||||
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
|
||||
import org.hibernate.resource.jdbc.spi.StatementInspector;
|
||||
|
|
|
@ -35,7 +35,7 @@ import org.hibernate.query.QueryLiteralRendering;
|
|||
import org.hibernate.query.criteria.LiteralHandlingMode;
|
||||
import org.hibernate.query.hql.HqlTranslator;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.query.sqm.produce.function.SqmFunctionRegistry;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
||||
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
||||
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
|
||||
import org.hibernate.resource.jdbc.spi.StatementInspector;
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.List;
|
|||
import org.hibernate.QueryException;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
|
@ -24,7 +25,7 @@ import org.hibernate.type.Type;
|
|||
* @author David Channon
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @deprecated Replaced by {@link org.hibernate.query.sqm.function.SqmFunction}
|
||||
* @deprecated Replaced by {@link SqmFunction}
|
||||
*/
|
||||
@Deprecated
|
||||
public interface SQLFunction {
|
||||
|
|
|
@ -10,13 +10,14 @@ import java.util.Map;
|
|||
import java.util.TreeMap;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||
|
||||
/**
|
||||
* Defines a registry for SQLFunction instances
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @deprecated Replaced by {@link org.hibernate.query.sqm.function.SqmFunction}
|
||||
* @deprecated Replaced by {@link SqmFunction}
|
||||
*/
|
||||
@Deprecated
|
||||
public class SQLFunctionRegistry {
|
||||
|
|
|
@ -18,7 +18,6 @@ import org.hibernate.query.hql.spi.SqmCreationOptions;
|
|||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
import org.hibernate.query.hql.spi.SqmPathRegistry;
|
||||
import org.hibernate.query.sqm.function.SqmFunction;
|
||||
import org.hibernate.query.sqm.spi.BaseSemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.spi.SqmCreationContext;
|
||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||
|
@ -590,14 +589,6 @@ public class QuerySplitter {
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmFunction visitFunction(SqmFunction functionProducer) {
|
||||
// todo (6.0) : likely this needs a copy too
|
||||
// how to model that?
|
||||
// for now, return the same reference
|
||||
return functionProducer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmLiteral visitLiteral(SqmLiteral literal) {
|
||||
return new SqmLiteral(
|
||||
|
|
|
@ -11,8 +11,8 @@ 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.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
@ -56,16 +56,11 @@ import org.hibernate.query.sqm.SqmQuerySource;
|
|||
import org.hibernate.query.sqm.SqmTreeCreationLogger;
|
||||
import org.hibernate.query.sqm.StrictJpaComplianceViolation;
|
||||
import org.hibernate.query.sqm.UnknownEntityException;
|
||||
import org.hibernate.query.sqm.function.SqmCastTarget;
|
||||
import org.hibernate.query.sqm.function.SqmDistinct;
|
||||
import org.hibernate.query.sqm.function.SqmExtractUnit;
|
||||
import org.hibernate.query.sqm.function.SqmStar;
|
||||
import org.hibernate.query.sqm.function.SqmTrimSpecification;
|
||||
import org.hibernate.query.sqm.function.NamedSqmFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.internal.ParameterCollector;
|
||||
import org.hibernate.query.sqm.internal.SqmDmlCreationProcessingState;
|
||||
import org.hibernate.query.sqm.internal.SqmQuerySpecCreationProcessingStateStandardImpl;
|
||||
import org.hibernate.query.sqm.produce.function.SqmFunctionTemplate;
|
||||
import org.hibernate.query.sqm.produce.function.spi.NamedSqmFunctionTemplate;
|
||||
import org.hibernate.query.sqm.spi.ParameterDeclarationContext;
|
||||
import org.hibernate.query.sqm.spi.SqmCreationContext;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
|
@ -85,8 +80,13 @@ import org.hibernate.query.sqm.tree.expression.LiteralHelper;
|
|||
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.SqmCastTarget;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmCoalesce;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmCollectionSize;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmDistinct;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralNull;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
|
||||
|
@ -94,6 +94,8 @@ import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
|||
import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmPathEntityType;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmStar;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmTrimSpecification;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmUnaryOperation;
|
||||
import org.hibernate.query.sqm.tree.from.DowncastLocation;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
|
@ -131,6 +133,7 @@ import org.hibernate.query.sqm.tree.select.SqmSelection;
|
|||
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.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
@ -1305,13 +1308,15 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
}
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate( "concat" ).makeSqmFunctionExpression(
|
||||
(List) asList(
|
||||
return new SqmFunction(
|
||||
"concat",
|
||||
getFunctionDescriptor( "concat" ),
|
||||
StandardBasicTypes.STRING,
|
||||
asList(
|
||||
ctx.expression( 0 ).accept( this ),
|
||||
ctx.expression( 1 ).accept( this )
|
||||
),
|
||||
resolveExpressableTypeBasic( String.class ),
|
||||
creationContext.getQueryEngine()
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1386,10 +1391,12 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
SqmExpression<?> divisor = (SqmExpression) ctx.expression( 1 ).accept( this );
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("mod").makeSqmFunctionExpression(
|
||||
asList( dividend, divisor ),
|
||||
return new SqmFunction(
|
||||
"mod",
|
||||
getFunctionDescriptor( "mod" ),
|
||||
(AllowableFunctionReturnType) dividend.getNodeType(),
|
||||
creationContext.getQueryEngine()
|
||||
asList( dividend, divisor ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1455,38 +1462,46 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
|
||||
@Override
|
||||
public SqmExpression visitCurrentDateFunction(HqlParser.CurrentDateFunctionContext ctx) {
|
||||
return getFunctionTemplate("current_date")
|
||||
.makeSqmFunctionExpression(
|
||||
resolveExpressableTypeBasic( Date.class ),
|
||||
creationContext.getQueryEngine()
|
||||
);
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"current_date",
|
||||
getFunctionDescriptor( "current_date" ),
|
||||
StandardBasicTypes.DATE,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression visitCurrentTimeFunction(HqlParser.CurrentTimeFunctionContext ctx) {
|
||||
return getFunctionTemplate("current_time")
|
||||
.makeSqmFunctionExpression(
|
||||
resolveExpressableTypeBasic( Time.class ),
|
||||
creationContext.getQueryEngine()
|
||||
);
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"current_time",
|
||||
getFunctionDescriptor( "current_time" ),
|
||||
StandardBasicTypes.TIME,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression visitCurrentTimestampFunction(HqlParser.CurrentTimestampFunctionContext ctx) {
|
||||
return getFunctionTemplate("current_timestamp")
|
||||
.makeSqmFunctionExpression(
|
||||
resolveExpressableTypeBasic( Timestamp.class ),
|
||||
creationContext.getQueryEngine()
|
||||
);
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"current_timestamp",
|
||||
getFunctionDescriptor( "current_timestamp" ),
|
||||
StandardBasicTypes.TIMESTAMP,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression visitCurrentInstantFunction(HqlParser.CurrentInstantFunctionContext ctx) {
|
||||
return getFunctionTemplate("current_timestamp")
|
||||
.makeSqmFunctionExpression(
|
||||
resolveExpressableTypeBasic( Instant.class ),
|
||||
creationContext.getQueryEngine()
|
||||
);
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"current_instant",
|
||||
getFunctionDescriptor( "current_instant" ),
|
||||
StandardBasicTypes.INSTANT,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1502,12 +1517,14 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
type = arg.getNodeType();
|
||||
}
|
||||
|
||||
return getFunctionTemplate("least")
|
||||
.makeSqmFunctionExpression(
|
||||
arguments,
|
||||
(AllowableFunctionReturnType<?>) type,
|
||||
creationContext.getQueryEngine()
|
||||
);
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"least",
|
||||
getFunctionDescriptor( "least" ),
|
||||
(AllowableFunctionReturnType<?>) type,
|
||||
arguments,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1523,12 +1540,14 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
type = arg.getNodeType();
|
||||
}
|
||||
|
||||
return getFunctionTemplate("greatest")
|
||||
.makeSqmFunctionExpression(
|
||||
arguments,
|
||||
(AllowableFunctionReturnType<?>) type,
|
||||
creationContext.getQueryEngine()
|
||||
);
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"greatest",
|
||||
getFunctionDescriptor( "greatest" ),
|
||||
type,
|
||||
arguments,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1544,12 +1563,14 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
type = arg.getNodeType();
|
||||
}
|
||||
|
||||
return getFunctionTemplate("coalesce")
|
||||
.makeSqmFunctionExpression(
|
||||
arguments,
|
||||
(AllowableFunctionReturnType<?>) type,
|
||||
creationContext.getQueryEngine()
|
||||
);
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"coalesce",
|
||||
getFunctionDescriptor( "coalesce" ),
|
||||
type,
|
||||
arguments,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1558,10 +1579,12 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
final SqmExpression arg2 = (SqmExpression) ctx.nullIf().expression( 1 ).accept( this );
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("nullif").makeSqmFunctionExpression(
|
||||
return new SqmFunction(
|
||||
"nullif",
|
||||
getFunctionDescriptor( "nullif" ),
|
||||
arg1.getNodeType(),
|
||||
asList( arg1, arg2 ),
|
||||
(AllowableFunctionReturnType) arg1.getNodeType(),
|
||||
creationContext.getQueryEngine()
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1819,14 +1842,18 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
final String functionName = ctx.jpaNonStandardFunctionName().STRING_LITERAL().getText().toLowerCase();
|
||||
final List<SqmTypedNode<?>> functionArguments = visitNonStandardFunctionArguments( ctx.nonStandardFunctionArguments() );
|
||||
|
||||
SqmFunctionTemplate functionTemplate = getFunctionTemplate( functionName );
|
||||
if (functionTemplate == null) {
|
||||
functionTemplate = new NamedSqmFunctionTemplate( functionName, true, null, null );
|
||||
SqmFunctionDescriptor functionDescriptor = getFunctionDescriptor( functionName );
|
||||
if (functionDescriptor == null) {
|
||||
functionDescriptor = new NamedSqmFunctionDescriptor( functionName, functionName, true, null );
|
||||
}
|
||||
return functionTemplate.makeSqmFunctionExpression(
|
||||
functionArguments,
|
||||
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
functionName,
|
||||
functionDescriptor,
|
||||
null,
|
||||
creationContext.getQueryEngine()
|
||||
functionArguments,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1843,14 +1870,18 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
final String functionName = ctx.nonStandardFunctionName().getText().toLowerCase();
|
||||
final List<SqmTypedNode<?>> functionArguments = visitNonStandardFunctionArguments( ctx.nonStandardFunctionArguments() );
|
||||
|
||||
SqmFunctionTemplate functionTemplate = getFunctionTemplate( functionName);
|
||||
if (functionTemplate == null) {
|
||||
functionTemplate = new NamedSqmFunctionTemplate( functionName, true, null, null );
|
||||
SqmFunctionDescriptor functionDescriptor = getFunctionDescriptor( functionName);
|
||||
if ( functionDescriptor == null ) {
|
||||
functionDescriptor = new NamedSqmFunctionDescriptor( functionName, functionName, true, null );
|
||||
}
|
||||
return functionTemplate.makeSqmFunctionExpression(
|
||||
functionArguments,
|
||||
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
functionName,
|
||||
functionDescriptor,
|
||||
null,
|
||||
creationContext.getQueryEngine()
|
||||
functionArguments,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1888,10 +1919,12 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
final SqmExpression arg = (SqmExpression) ctx.expression().accept( this );
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("ceiling").makeSqmFunctionExpression(
|
||||
arg,
|
||||
(AllowableFunctionReturnType) resolveExpressableTypeBasic( Long.class ),
|
||||
creationContext.getQueryEngine()
|
||||
return new SqmFunction(
|
||||
"ceiling",
|
||||
getFunctionDescriptor( "ceiling" ),
|
||||
StandardBasicTypes.LONG,
|
||||
Collections.singletonList( arg ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1900,15 +1933,17 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
final SqmExpression arg = (SqmExpression) ctx.expression().accept( this );
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("floor").makeSqmFunctionExpression(
|
||||
arg,
|
||||
(AllowableFunctionReturnType) resolveExpressableTypeBasic( Long.class ),
|
||||
creationContext.getQueryEngine()
|
||||
return new SqmFunction(
|
||||
"floor",
|
||||
getFunctionDescriptor( "floor" ),
|
||||
StandardBasicTypes.LONG,
|
||||
Collections.singletonList( arg ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
private SqmFunctionTemplate getFunctionTemplate(String name) {
|
||||
return creationContext.getQueryEngine().getSqmFunctionRegistry().findFunctionTemplate( name );
|
||||
private SqmFunctionDescriptor getFunctionDescriptor(String name) {
|
||||
return creationContext.getQueryEngine().getSqmFunctionRegistry().findFunctionDescriptor( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1916,10 +1951,12 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
final SqmExpression arg = (SqmExpression) ctx.expression().accept( this );
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("abs").makeSqmFunctionExpression(
|
||||
arg,
|
||||
(AllowableFunctionReturnType) arg.getNodeType(),
|
||||
creationContext.getQueryEngine()
|
||||
return new SqmFunction(
|
||||
"abs",
|
||||
getFunctionDescriptor( "abs" ),
|
||||
arg.getNodeType(),
|
||||
Collections.singletonList( arg ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1928,10 +1965,12 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
final SqmExpression arg = (SqmExpression) ctx.expression().accept( this );
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("sign").makeSqmFunctionExpression(
|
||||
arg,
|
||||
(AllowableFunctionReturnType) resolveExpressableTypeBasic( Integer.class ),
|
||||
creationContext.getQueryEngine()
|
||||
return new SqmFunction(
|
||||
"sign",
|
||||
getFunctionDescriptor( "sign" ),
|
||||
StandardBasicTypes.INTEGER,
|
||||
Collections.singletonList( arg ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1941,10 +1980,12 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
final SqmExpression divisor = (SqmExpression) ctx.modDivisorArgument().accept( this );
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("mod").makeSqmFunctionExpression(
|
||||
return new SqmFunction(
|
||||
"mod",
|
||||
getFunctionDescriptor( "mod" ),
|
||||
dividend.getNodeType(),
|
||||
asList( dividend, divisor ),
|
||||
(AllowableFunctionReturnType) dividend.getNodeType(),
|
||||
creationContext.getQueryEngine()
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1954,21 +1995,28 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
final SqmExpression power = (SqmExpression) ctx.powerPowerArgument().accept( this );
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("power").makeSqmFunctionExpression(
|
||||
return new SqmFunction(
|
||||
"power",
|
||||
getFunctionDescriptor( "power" ),
|
||||
base.getNodeType(),
|
||||
asList( base, power ),
|
||||
(AllowableFunctionReturnType) base.getNodeType(),
|
||||
creationContext.getQueryEngine()
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression visitTrigFunction(HqlParser.TrigFunctionContext ctx) {
|
||||
final String functionName = ctx.trigFunctionName().getText();
|
||||
final SqmExpression arg = (SqmExpression) ctx.expression().accept( this );
|
||||
|
||||
return getFunctionTemplate( ctx.trigFunctionName().getText() ).makeSqmFunctionExpression(
|
||||
arg,
|
||||
resolveExpressableTypeBasic( Double.class ),
|
||||
creationContext.getQueryEngine()
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
functionName,
|
||||
getFunctionDescriptor( functionName ),
|
||||
StandardBasicTypes.DOUBLE,
|
||||
Collections.singletonList( arg ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1977,10 +2025,12 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
final SqmExpression arg = (SqmExpression) ctx.expression().accept( this );
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("sqrt").makeSqmFunctionExpression(
|
||||
arg,
|
||||
(AllowableFunctionReturnType) arg.getNodeType(),
|
||||
creationContext.getQueryEngine()
|
||||
return new SqmFunction(
|
||||
"sqrt",
|
||||
getFunctionDescriptor( "sqrt" ),
|
||||
arg.getNodeType(),
|
||||
Collections.singletonList( arg ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1990,10 +2040,12 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
final SqmExpression precision = (SqmExpression) ctx.roundFunctionPrecision().expression().accept( this );
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("round").makeSqmFunctionExpression(
|
||||
asList(arg, precision),
|
||||
(AllowableFunctionReturnType) arg.getNodeType(),
|
||||
creationContext.getQueryEngine()
|
||||
return new SqmFunction(
|
||||
"round",
|
||||
getFunctionDescriptor( "round" ),
|
||||
arg.getNodeType(),
|
||||
asList( arg, precision ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2003,10 +2055,12 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
final SqmExpression cos = (SqmExpression) ctx.expression().get( 1).accept( this );
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("atan2").makeSqmFunctionExpression(
|
||||
return new SqmFunction(
|
||||
"atan2",
|
||||
getFunctionDescriptor( "atan2" ),
|
||||
sin.getNodeType(),
|
||||
asList(sin, cos),
|
||||
(AllowableFunctionReturnType) sin.getNodeType(),
|
||||
creationContext.getQueryEngine()
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2015,12 +2069,13 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
final SqmExpression arg = (SqmExpression) ctx.expression().accept( this );
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("ln").makeSqmFunctionExpression(
|
||||
arg,
|
||||
(AllowableFunctionReturnType) arg.getNodeType(),
|
||||
creationContext.getQueryEngine()
|
||||
return new SqmFunction(
|
||||
"ln",
|
||||
getFunctionDescriptor( "ln" ),
|
||||
arg.getNodeType(),
|
||||
Collections.singletonList( arg ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2028,10 +2083,12 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
final SqmExpression arg = (SqmExpression) ctx.expression().accept( this );
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("exp").makeSqmFunctionExpression(
|
||||
arg,
|
||||
(AllowableFunctionReturnType) arg.getNodeType(),
|
||||
creationContext.getQueryEngine()
|
||||
return new SqmFunction(
|
||||
"exp",
|
||||
getFunctionDescriptor( "exp" ),
|
||||
arg.getNodeType(),
|
||||
Collections.singletonList( arg ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2156,29 +2213,27 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
}
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("extract").makeSqmFunctionExpression(
|
||||
return new SqmFunction(
|
||||
"extract",
|
||||
getFunctionDescriptor( "extract" ),
|
||||
extractFieldExpression.getNodeType(),
|
||||
asList( extractFieldExpression, expressionToExtract ),
|
||||
extractFieldExpression.getType(),
|
||||
creationContext.getQueryEngine()
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression visitCastFunction(HqlParser.CastFunctionContext ctx) {
|
||||
|
||||
final SqmExpression<?> expressionToCast = (SqmExpression) ctx.expression().accept( this );
|
||||
final SqmCastTarget<?> castTargetExpression = interpretCastTarget( ctx.castTarget() );
|
||||
|
||||
//getSessionFactory().getTypeConfiguration().resolveCastTargetType( ctx.dataType().IDENTIFIER().getText() )
|
||||
|
||||
// if ( !AllowableFunctionReturnType.class.isInstance( castTargetExpression ) ) {
|
||||
// throw new SqmProductionException( "Found cast target expression [%s] which is not allowed as a function return" );
|
||||
// }
|
||||
|
||||
return getFunctionTemplate("cast").makeSqmFunctionExpression(
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"cast",
|
||||
getFunctionDescriptor( "cast" ),
|
||||
castTargetExpression.getNodeType(),
|
||||
asList( expressionToCast, castTargetExpression ),
|
||||
castTargetExpression.getType(),
|
||||
creationContext.getQueryEngine()
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2252,23 +2307,25 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
public SqmExpression visitUpperFunction(HqlParser.UpperFunctionContext ctx) {
|
||||
final SqmExpression expression = (SqmExpression) ctx.expression().accept( this );
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("upper").makeSqmFunctionExpression(
|
||||
expression,
|
||||
(AllowableFunctionReturnType) expression.getNodeType(),
|
||||
creationContext.getQueryEngine()
|
||||
return new SqmFunction(
|
||||
"upper",
|
||||
getFunctionDescriptor( "upper" ),
|
||||
expression.getNodeType(),
|
||||
Collections.singletonList( expression ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression visitLowerFunction(HqlParser.LowerFunctionContext ctx) {
|
||||
// todo (6.0) : why pass both the expression and its expression-type?
|
||||
// can't we just pass the expression?
|
||||
final SqmExpression expression = (SqmExpression) ctx.expression().accept( this );
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("lower").makeSqmFunctionExpression(
|
||||
expression,
|
||||
(AllowableFunctionReturnType) expression.getNodeType(),
|
||||
creationContext.getQueryEngine()
|
||||
return new SqmFunction(
|
||||
"lower",
|
||||
getFunctionDescriptor( "lower" ),
|
||||
expression.getNodeType(),
|
||||
Collections.singletonList( expression ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2279,10 +2336,13 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
arguments.add( (SqmTypedNode<?>) argument.accept( this ) );
|
||||
}
|
||||
|
||||
return getFunctionTemplate("concat").makeSqmFunctionExpression(
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"concat",
|
||||
getFunctionDescriptor( "concat" ),
|
||||
StandardBasicTypes.STRING,
|
||||
arguments,
|
||||
resolveExpressableTypeBasic( String.class ),
|
||||
creationContext.getQueryEngine()
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2290,10 +2350,13 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
public Object visitLengthFunction(HqlParser.LengthFunctionContext ctx) {
|
||||
final SqmExpression arg = (SqmExpression) ctx.expression().accept( this );
|
||||
|
||||
return getFunctionTemplate("character_length").makeSqmFunctionExpression(
|
||||
arg,
|
||||
resolveExpressableTypeBasic( Integer.class ),
|
||||
creationContext.getQueryEngine()
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"character_length",
|
||||
getFunctionDescriptor( "character_length" ),
|
||||
StandardBasicTypes.INTEGER,
|
||||
Collections.singletonList( arg ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2302,10 +2365,13 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
final SqmExpression<?> string = (SqmExpression) ctx.positionFunctionStringArgument().accept( this );
|
||||
final SqmExpression<?> pattern = (SqmExpression) ctx.positionFunctionPatternArgument().accept( this );
|
||||
|
||||
return getFunctionTemplate("locate").makeSqmFunctionExpression(
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"locate",
|
||||
getFunctionDescriptor( "locate" ),
|
||||
StandardBasicTypes.INTEGER,
|
||||
asList( pattern, string ),
|
||||
resolveExpressableTypeBasic( Integer.class ),
|
||||
creationContext.getQueryEngine()
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2317,12 +2383,15 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
? null
|
||||
: (SqmExpression) ctx.locateFunctionStartArgument().accept( this );
|
||||
|
||||
return getFunctionTemplate("locate").makeSqmFunctionExpression(
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"locate",
|
||||
getFunctionDescriptor( "locate" ),
|
||||
StandardBasicTypes.INTEGER,
|
||||
start == null
|
||||
? asList( pattern, string )
|
||||
: asList( pattern, string, start ),
|
||||
resolveExpressableTypeBasic( Integer.class ),
|
||||
creationContext.getQueryEngine()
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2333,84 +2402,110 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
final SqmExpression<?> pattern = (SqmExpression) ctx.replaceFunctionPatternArgument().accept( this );
|
||||
final SqmExpression<?> replacement = (SqmExpression) ctx.replaceFunctionReplacementArgument().accept( this );
|
||||
|
||||
return getFunctionTemplate("replace").makeSqmFunctionExpression(
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"replace",
|
||||
getFunctionDescriptor( "replace" ),
|
||||
StandardBasicTypes.INTEGER,
|
||||
asList( string, pattern, replacement ),
|
||||
resolveExpressableTypeBasic( String.class ),
|
||||
creationContext.getQueryEngine()
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitStrFunction(HqlParser.StrFunctionContext ctx) {
|
||||
final SqmExpression<?> arg = (SqmExpression) ctx.expression().accept( this );
|
||||
AllowableFunctionReturnType<String> type = resolveExpressableTypeBasic( String.class );
|
||||
return getFunctionTemplate("cast").makeSqmFunctionExpression(
|
||||
asList( arg, new SqmCastTarget<>( type, creationContext.getNodeBuilder() ) ),
|
||||
final AllowableFunctionReturnType<String> type = resolveExpressableTypeBasic( String.class );
|
||||
final SqmCastTarget<String> castTarget = new SqmCastTarget<>( type, creationContext.getNodeBuilder() );
|
||||
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"cast",
|
||||
getFunctionDescriptor( "cast" ),
|
||||
type,
|
||||
creationContext.getQueryEngine()
|
||||
asList( arg, castTarget ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression visitMaxFunction(HqlParser.MaxFunctionContext ctx) {
|
||||
final SqmExpression<?> arg = (SqmExpression) ctx.expression().accept( this );
|
||||
//ignore DISTINCT
|
||||
return getFunctionTemplate("max").makeSqmFunctionExpression(
|
||||
arg,
|
||||
(AllowableFunctionReturnType<?>) arg.getNodeType(),
|
||||
creationContext.getQueryEngine()
|
||||
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"max",
|
||||
getFunctionDescriptor( "max" ),
|
||||
arg.getNodeType(),
|
||||
Collections.singletonList( arg ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression visitMinFunction(HqlParser.MinFunctionContext ctx) {
|
||||
final SqmExpression<?> arg = (SqmExpression) ctx.expression().accept( this );
|
||||
//ignore DISTINCT
|
||||
return getFunctionTemplate("min").makeSqmFunctionExpression(
|
||||
arg,
|
||||
(AllowableFunctionReturnType<?>) arg.getNodeType(),
|
||||
creationContext.getQueryEngine()
|
||||
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"min",
|
||||
getFunctionDescriptor( "min" ),
|
||||
arg.getNodeType(),
|
||||
Collections.singletonList( arg ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression visitSumFunction(HqlParser.SumFunctionContext ctx) {
|
||||
|
||||
final SqmExpression<?> arg = (SqmExpression) ctx.expression().accept( this );
|
||||
SqmTypedNode<?> argument = ctx.DISTINCT() != null ? new SqmDistinct<>( arg, getCreationContext().getNodeBuilder()) : arg;
|
||||
final SqmTypedNode<?> argument = ctx.DISTINCT() != null
|
||||
? new SqmDistinct<>( arg, getCreationContext().getNodeBuilder() )
|
||||
: arg;
|
||||
|
||||
return getFunctionTemplate("sum").makeSqmFunctionExpression(
|
||||
argument,
|
||||
(AllowableFunctionReturnType<?>) arg.getNodeType(),
|
||||
creationContext.getQueryEngine()
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"sum",
|
||||
getFunctionDescriptor( "sum" ),
|
||||
arg.getNodeType(),
|
||||
Collections.singletonList( argument ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression visitAvgFunction(HqlParser.AvgFunctionContext ctx) {
|
||||
|
||||
final SqmExpression<?> arg = (SqmExpression) ctx.expression().accept( this );
|
||||
SqmTypedNode<?> argument = ctx.DISTINCT() != null ? new SqmDistinct<>( arg, getCreationContext().getNodeBuilder()) : arg;
|
||||
final SqmTypedNode<?> argument = ctx.DISTINCT() != null
|
||||
? new SqmDistinct<>( arg, getCreationContext().getNodeBuilder() )
|
||||
: arg;
|
||||
|
||||
return getFunctionTemplate("avg").makeSqmFunctionExpression(
|
||||
argument,
|
||||
resolveExpressableTypeBasic( Double.class ),
|
||||
creationContext.getQueryEngine()
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"avg",
|
||||
getFunctionDescriptor( "avg" ),
|
||||
arg.getNodeType(),
|
||||
Collections.singletonList( argument ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression visitCountFunction(HqlParser.CountFunctionContext ctx) {
|
||||
|
||||
final SqmExpression<?> arg = ctx.ASTERISK() != null
|
||||
? new SqmStar( getCreationContext().getNodeBuilder() )
|
||||
: (SqmExpression) ctx.expression().accept( this );
|
||||
SqmTypedNode<?> argument = ctx.DISTINCT() != null ? new SqmDistinct<>( arg, getCreationContext().getNodeBuilder() ) : arg;
|
||||
final SqmTypedNode<?> argument = ctx.DISTINCT() != null
|
||||
? new SqmDistinct<>( arg, getCreationContext().getNodeBuilder() )
|
||||
: arg;
|
||||
|
||||
return getFunctionTemplate("count").makeSqmFunctionExpression(
|
||||
argument,
|
||||
resolveExpressableTypeBasic( Long.class ),
|
||||
creationContext.getQueryEngine()
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"count",
|
||||
getFunctionDescriptor( "count" ),
|
||||
StandardBasicTypes.LONG,
|
||||
Collections.singletonList( argument ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2423,12 +2518,13 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
: (SqmExpression) ctx.substringFunctionLengthArgument().accept( this );
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("substring").makeSqmFunctionExpression(
|
||||
length==null ? asList( source, start ) : asList( source, start, length ),
|
||||
resolveExpressableTypeBasic( String.class ),
|
||||
creationContext.getQueryEngine()
|
||||
return new SqmFunction(
|
||||
"substring",
|
||||
getFunctionDescriptor( "substring" ),
|
||||
StandardBasicTypes.STRING,
|
||||
length == null ? asList( source, start ) : asList( source, start, length ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2436,14 +2532,16 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
final SqmExpression source = (SqmExpression) ctx.expression().accept( this );
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("trim").makeSqmFunctionExpression(
|
||||
return new SqmFunction(
|
||||
"trim",
|
||||
getFunctionDescriptor( "trim" ),
|
||||
StandardBasicTypes.STRING,
|
||||
asList(
|
||||
interpretTrimSpecification( ctx.trimSpecification() ),
|
||||
visitTrimCharacter( ctx.trimCharacter() ),
|
||||
source
|
||||
),
|
||||
resolveExpressableTypeBasic( String.class ),
|
||||
creationContext.getQueryEngine()
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ import org.hibernate.query.named.NamedQueryRepository;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.internal.SqmCreationOptionsStandard;
|
||||
import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder;
|
||||
import org.hibernate.query.sqm.produce.function.SqmFunctionRegistry;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
||||
import org.hibernate.query.sqm.spi.SqmCreationContext;
|
||||
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
||||
import org.hibernate.query.sqm.sql.StandardSqmTranslatorFactory;
|
||||
|
|
|
@ -50,7 +50,6 @@ 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.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmRestrictedSubQueryExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmTuple;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
|
@ -62,7 +61,7 @@ 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.query.sqm.tree.expression.SqmFunction;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,8 +25,11 @@ import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
|
|||
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.SqmCastTarget;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmCoalesce;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmCollectionSize;
|
||||
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
|
@ -39,12 +42,10 @@ import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter;
|
|||
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.SqmCastTarget;
|
||||
import org.hibernate.query.sqm.function.SqmDistinct;
|
||||
import org.hibernate.query.sqm.function.SqmExtractUnit;
|
||||
import org.hibernate.query.sqm.function.SqmFunction;
|
||||
import org.hibernate.query.sqm.function.SqmStar;
|
||||
import org.hibernate.query.sqm.function.SqmTrimSpecification;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmDistinct;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmStar;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmTrimSpecification;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmCrossJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
|
||||
|
@ -196,15 +197,21 @@ public interface SemanticQueryWalker<T> {
|
|||
|
||||
T visitUnaryOperationExpression(SqmUnaryOperation<?> expression);
|
||||
|
||||
T visitFunction(SqmFunction tSqmFunction);
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// expressions - non-standard functions
|
||||
T visitExtractUnit(SqmExtractUnit extractUnit);
|
||||
|
||||
T visitFunction(SqmFunction<?> sqmFunction);
|
||||
T visitCastTarget(SqmCastTarget sqmCastTarget);
|
||||
|
||||
T visitTrimSpecification(SqmTrimSpecification trimSpecification);
|
||||
|
||||
T visitDistinct(SqmDistinct distinct);
|
||||
|
||||
T visitStar(SqmStar sqmStar);
|
||||
|
||||
T visitCoalesce(SqmCoalesce sqmCoalesce);
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// expressions - standard functions
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// predicates
|
||||
|
@ -262,14 +269,4 @@ public interface SemanticQueryWalker<T> {
|
|||
T visitMapEntryFunction(SqmMapEntryReference function);
|
||||
|
||||
T visitFullyQualifiedClass(Class<?> namedClass);
|
||||
|
||||
T visitExtractUnit(SqmExtractUnit extractUnit);
|
||||
|
||||
T visitCastTarget(SqmCastTarget sqmCastTarget);
|
||||
|
||||
T visitTrimSpecification(SqmTrimSpecification trimSpecification);
|
||||
|
||||
T visitDistinct(SqmDistinct distinct);
|
||||
|
||||
T visitStar(SqmStar sqmStar);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* 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.function;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||
import org.hibernate.sql.ast.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.SelfRenderingExpression;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractSelfRenderingFunctionTemplate extends AbstractSqmFunctionDescriptor {
|
||||
private final ArgumentsValidator argumentsValidator;
|
||||
|
||||
public AbstractSelfRenderingFunctionTemplate(ArgumentsValidator argumentsValidator) {
|
||||
super();
|
||||
|
||||
this.argumentsValidator = argumentsValidator == null
|
||||
? StandardArgumentsValidators.NONE
|
||||
: argumentsValidator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression generateSqlExpression(
|
||||
String functionName,
|
||||
List<? extends SqmVisitableNode> sqmArguments,
|
||||
Supplier<MappingModelExpressable> inferableTypeAccess,
|
||||
SqmToSqlAstConverter converter,
|
||||
SqlAstCreationState creationState) {
|
||||
argumentsValidator.validate( sqmArguments );
|
||||
|
||||
// todo (6.0) : work out the specifics of the type resolution
|
||||
|
||||
final List<SqlAstNode> sqlAstArgs;
|
||||
if ( sqmArguments == null || sqmArguments.isEmpty() ) {
|
||||
sqlAstArgs = Collections.emptyList();
|
||||
}
|
||||
else if ( sqmArguments.size() == 1 ) {
|
||||
sqlAstArgs = Collections.singletonList(
|
||||
(SqlAstNode) sqmArguments.get( 0 ).accept( converter )
|
||||
);
|
||||
}
|
||||
else {
|
||||
sqlAstArgs = new ArrayList<>( sqmArguments.size() );
|
||||
for ( int i = 0; i < sqmArguments.size(); i++ ) {
|
||||
final SqmVisitableNode sqmVisitableNode = sqmArguments.get( i );
|
||||
sqlAstArgs.add( (SqlAstNode) sqmVisitableNode.accept( converter ) );
|
||||
}
|
||||
}
|
||||
|
||||
return new SelfRenderingSqlFunctionExpression(
|
||||
functionName,
|
||||
inferableTypeAccess.get(),
|
||||
sqlAstArgs,
|
||||
getRenderingSupport()
|
||||
);
|
||||
}
|
||||
|
||||
protected abstract FunctionRenderingSupport getRenderingSupport();
|
||||
|
||||
|
||||
private static class SelfRenderingSqlFunctionExpression implements SelfRenderingExpression {
|
||||
private final String name;
|
||||
private final MappingModelExpressable type;
|
||||
private final List<SqlAstNode> arguments;
|
||||
|
||||
private final FunctionRenderingSupport renderingSupport;
|
||||
|
||||
public SelfRenderingSqlFunctionExpression(
|
||||
String name,
|
||||
MappingModelExpressable type,
|
||||
List<SqlAstNode> arguments,
|
||||
FunctionRenderingSupport renderingSupport) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.arguments = arguments;
|
||||
this.renderingSupport = renderingSupport;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderToSql(
|
||||
SqlAppender sqlAppender,
|
||||
SqlAstWalker walker,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
renderingSupport.render( sqlAppender, name, arguments, walker, sessionFactory );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingModelExpressable getExpressionType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* 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.function;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||
import org.hibernate.sql.ast.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.SelfRenderingExpression;
|
||||
|
||||
/**
|
||||
* Support for SQM function descriptors which ultimately render themselves
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractSqmFunctionDescriptor implements SqmFunctionDescriptor {
|
||||
private final ArgumentsValidator argumentsValidator;
|
||||
|
||||
public AbstractSqmFunctionDescriptor() {
|
||||
this( null );
|
||||
}
|
||||
|
||||
public AbstractSqmFunctionDescriptor(ArgumentsValidator argumentsValidator) {
|
||||
this.argumentsValidator = argumentsValidator == null
|
||||
? StandardArgumentsValidators.NONE
|
||||
: argumentsValidator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression generateSqlExpression(
|
||||
String functionName,
|
||||
List<? extends SqmVisitableNode> sqmArguments,
|
||||
Supplier<MappingModelExpressable> inferableTypeAccess,
|
||||
SqmToSqlAstConverter converter,
|
||||
SqlAstCreationState creationState) {
|
||||
argumentsValidator.validate( sqmArguments );
|
||||
|
||||
// todo (6.0) : work out the specifics of the type resolution
|
||||
|
||||
final List<SqlAstNode> sqlAstArgs;
|
||||
if ( sqmArguments == null || sqmArguments.isEmpty() ) {
|
||||
sqlAstArgs = Collections.emptyList();
|
||||
}
|
||||
else if ( sqmArguments.size() == 1 ) {
|
||||
sqlAstArgs = Collections.singletonList(
|
||||
(SqlAstNode) sqmArguments.get( 0 ).accept( converter )
|
||||
);
|
||||
}
|
||||
else {
|
||||
sqlAstArgs = new ArrayList<>( sqmArguments.size() );
|
||||
for ( int i = 0; i < sqmArguments.size(); i++ ) {
|
||||
final SqmVisitableNode sqmVisitableNode = sqmArguments.get( i );
|
||||
sqlAstArgs.add( (SqlAstNode) sqmVisitableNode.accept( converter ) );
|
||||
}
|
||||
}
|
||||
|
||||
return new SelfRenderingSqlFunctionExpression(
|
||||
functionName,
|
||||
inferableTypeAccess.get(),
|
||||
sqlAstArgs,
|
||||
getRenderingSupport()
|
||||
);
|
||||
}
|
||||
|
||||
protected abstract FunctionRenderingSupport getRenderingSupport();
|
||||
|
||||
|
||||
private static class SelfRenderingSqlFunctionExpression implements SelfRenderingExpression {
|
||||
private final String name;
|
||||
private final MappingModelExpressable type;
|
||||
private final List<SqlAstNode> arguments;
|
||||
|
||||
private final FunctionRenderingSupport renderingSupport;
|
||||
|
||||
public SelfRenderingSqlFunctionExpression(
|
||||
String name,
|
||||
MappingModelExpressable type,
|
||||
List<SqlAstNode> arguments,
|
||||
FunctionRenderingSupport renderingSupport) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.arguments = arguments;
|
||||
this.renderingSupport = renderingSupport;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderToSql(
|
||||
SqlAppender sqlAppender,
|
||||
SqlAstWalker walker,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
renderingSupport.render( sqlAppender, name, arguments, walker, sessionFactory );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingModelExpressable getExpressionType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,18 +4,14 @@
|
|||
* 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.produce.function.spi;
|
||||
package org.hibernate.query.sqm.function;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
|
||||
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
@ -24,8 +20,8 @@ import org.jboss.logging.Logger;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class FunctionAsExpressionTemplate
|
||||
extends AbstractSelfRenderingFunctionTemplate
|
||||
implements SelfRenderingFunctionSupport {
|
||||
extends AbstractSqmFunctionDescriptor
|
||||
implements FunctionRenderingSupport {
|
||||
|
||||
private static final Logger log = Logger.getLogger( FunctionAsExpressionTemplate.class );
|
||||
|
||||
|
@ -37,28 +33,22 @@ public class FunctionAsExpressionTemplate
|
|||
String expressionStart,
|
||||
String argumentSeparator,
|
||||
String expressionEnd,
|
||||
FunctionReturnTypeResolver returnTypeResolver,
|
||||
ArgumentsValidator argumentsValidator,
|
||||
String name) {
|
||||
super( name, returnTypeResolver, argumentsValidator );
|
||||
ArgumentsValidator argumentsValidator) {
|
||||
super( argumentsValidator );
|
||||
this.expressionStart = expressionStart;
|
||||
this.argumentSeparator = argumentSeparator;
|
||||
this.expressionEnd = expressionEnd;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SelfRenderingFunctionSupport getRenderingFunctionSupport(
|
||||
List<SqmTypedNode<?>> arguments,
|
||||
AllowableFunctionReturnType<?> resolvedReturnType,
|
||||
QueryEngine queryEngine) {
|
||||
protected FunctionRenderingSupport getRenderingSupport() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void render(
|
||||
SqlAppender sqlAppender,
|
||||
List<SqlAstNode> sqlAstArguments,
|
||||
String functionName, List<SqlAstNode> sqlAstArguments,
|
||||
SqlAstWalker walker,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
sqlAppender.appendSql( expressionStart );
|
||||
|
@ -68,31 +58,15 @@ public class FunctionAsExpressionTemplate
|
|||
}
|
||||
else {
|
||||
// render the first argument..
|
||||
renderArgument( sqlAppender, sqlAstArguments.get( 0 ), walker, sessionFactory );
|
||||
sqlAstArguments.get( 0 ).accept( walker );
|
||||
|
||||
// render the rest of the arguments, preceded by the separator
|
||||
for ( int i = 1; i < sqlAstArguments.size(); i++ ) {
|
||||
sqlAppender.appendSql( argumentSeparator );
|
||||
renderArgument( sqlAppender, sqlAstArguments.get( i ), walker, sessionFactory );
|
||||
sqlAstArguments.get( i ).accept( walker );
|
||||
}
|
||||
}
|
||||
|
||||
sqlAppender.appendSql( expressionEnd );
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from {@link #render} to render an argument.
|
||||
*
|
||||
* @param sqlAppender The sql appender to append the rendered argument.
|
||||
* @param sqlAstArgument The argument being processed.
|
||||
* @param walker The walker to use for rendering {@link SqlAstNode} expressions
|
||||
* @param sessionFactory The session factory
|
||||
*/
|
||||
protected void renderArgument(
|
||||
SqlAppender sqlAppender,
|
||||
SqlAstNode sqlAstArgument,
|
||||
SqlAstWalker walker,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
sqlAstArgument.accept( walker );
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
* 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.produce.function.spi;
|
||||
package org.hibernate.query.sqm.function;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
|
@ -14,14 +14,14 @@ import org.hibernate.sql.ast.tree.SqlAstNode;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Support for SqmFunctionTemplates that ultimately want to
|
||||
* perform SQL rendering themselves
|
||||
* Support for SqmFunctionDescriptors that ultimately want to perform SQL rendering themselves
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SelfRenderingFunctionSupport {
|
||||
public interface FunctionRenderingSupport {
|
||||
void render(
|
||||
SqlAppender sqlAppender,
|
||||
String functionName,
|
||||
List<SqlAstNode> sqlAstArguments,
|
||||
SqlAstWalker walker,
|
||||
SessionFactoryImplementor sessionFactory);
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* 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.function;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||
import org.hibernate.sql.ast.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.SelfRenderingExpression;
|
||||
|
||||
/**
|
||||
* Acts as a wrapper to another SqmFunctionTemplate - upon rendering uses the
|
||||
* standard JDBC escape sequence (i.e. `{fn blah}`) when rendering the SQL.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class JdbcEscapeFunctionDescriptor implements SqmFunctionDescriptor {
|
||||
private final SqmFunctionDescriptor wrapped;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public JdbcEscapeFunctionDescriptor(SqmFunctionDescriptor wrapped) {
|
||||
this.wrapped = wrapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression generateSqlExpression(
|
||||
String functionName,
|
||||
List<? extends SqmVisitableNode> sqmArguments,
|
||||
Supplier<MappingModelExpressable> inferableTypeAccess,
|
||||
SqmToSqlAstConverter converter,
|
||||
SqlAstCreationState creationState) {
|
||||
final Expression wrappedExpression = wrapped.generateSqlExpression(
|
||||
functionName,
|
||||
sqmArguments,
|
||||
inferableTypeAccess,
|
||||
converter,
|
||||
creationState
|
||||
);
|
||||
|
||||
return new EscapeExpression( wrappedExpression );
|
||||
}
|
||||
|
||||
private static class EscapeExpression implements SelfRenderingExpression {
|
||||
private final Expression wrappedExpression;
|
||||
|
||||
EscapeExpression(Expression wrappedExpression) {
|
||||
this.wrappedExpression = wrappedExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderToSql(
|
||||
SqlAppender sqlAppender,
|
||||
SqlAstWalker walker,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
sqlAppender.appendSql( "{fn " );
|
||||
wrappedExpression.accept( walker );
|
||||
sqlAppender.appendSql( "}" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingModelExpressable getExpressionType() {
|
||||
return wrappedExpression.getExpressionType();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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.function;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
|
||||
/**
|
||||
* Provides a standard implementation that supports the majority of the HQL
|
||||
* functions that are translated to SQL. The Dialect and its sub-classes use
|
||||
* this class to provide details required for processing of the associated
|
||||
* function.
|
||||
*
|
||||
* @author David Channon
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NamedSqmFunctionDescriptor extends AbstractSqmFunctionDescriptor {
|
||||
private final String functionKey;
|
||||
private final String functionName;
|
||||
private final boolean useParenthesesWhenNoArgs;
|
||||
|
||||
public NamedSqmFunctionDescriptor(
|
||||
String functionKey,
|
||||
String functionName,
|
||||
boolean useParenthesesWhenNoArgs,
|
||||
ArgumentsValidator argumentsValidator) {
|
||||
super( argumentsValidator );
|
||||
this.functionKey = functionKey;
|
||||
|
||||
this.functionName = functionName;
|
||||
this.useParenthesesWhenNoArgs = useParenthesesWhenNoArgs;
|
||||
}
|
||||
|
||||
public String getFunctionKey() {
|
||||
return functionKey;
|
||||
}
|
||||
|
||||
public String getFunctionName() {
|
||||
return functionName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FunctionRenderingSupport getRenderingSupport() {
|
||||
return (sqlAppender, functionName1, sqlAstArguments, walker, sessionFactory) -> {
|
||||
final boolean useParens = useParenthesesWhenNoArgs || !sqlAstArguments.isEmpty();
|
||||
|
||||
sqlAppender.appendSql( functionName );
|
||||
if ( useParens ) {
|
||||
sqlAppender.appendSql( "(" );
|
||||
}
|
||||
|
||||
boolean firstPass = true;
|
||||
for ( SqlAstNode sqlAstArgument : sqlAstArguments ) {
|
||||
if ( !firstPass ) {
|
||||
sqlAppender.appendSql( ", " );
|
||||
}
|
||||
sqlAstArgument.accept( walker );
|
||||
firstPass = false;
|
||||
}
|
||||
|
||||
if ( useParens ) {
|
||||
sqlAppender.appendSql( ")" );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
Locale.ROOT,
|
||||
"NamedSqmFunctionTemplate(%s)",
|
||||
functionName
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -4,22 +4,19 @@
|
|||
* 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.produce.function.spi;
|
||||
package org.hibernate.query.sqm.function;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
|
||||
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents HQL functions that can have different representations in different SQL dialects where that
|
||||
* difference can be handled via a template/pattern.
|
||||
|
@ -33,8 +30,8 @@ import java.util.List;
|
|||
* @author <a href="mailto:alex@jboss.org">Alexey Loubyansky</a>
|
||||
*/
|
||||
public class PatternBasedSqmFunctionTemplate
|
||||
extends AbstractSelfRenderingFunctionTemplate
|
||||
implements SelfRenderingFunctionSupport {
|
||||
extends AbstractSqmFunctionDescriptor
|
||||
implements FunctionRenderingSupport {
|
||||
private final PatternRenderer renderer;
|
||||
|
||||
/**
|
||||
|
@ -43,11 +40,8 @@ public class PatternBasedSqmFunctionTemplate
|
|||
public PatternBasedSqmFunctionTemplate(
|
||||
PatternRenderer renderer,
|
||||
ArgumentsValidator argumentsValidator,
|
||||
FunctionReturnTypeResolver returnTypeResolver,
|
||||
String name) {
|
||||
FunctionReturnTypeResolver returnTypeResolver) {
|
||||
super(
|
||||
name,
|
||||
returnTypeResolver,
|
||||
argumentsValidator != null
|
||||
? argumentsValidator
|
||||
// If no validator is given, it's still better to validate against the parameter count as given
|
||||
|
@ -58,16 +52,14 @@ public class PatternBasedSqmFunctionTemplate
|
|||
}
|
||||
|
||||
@Override
|
||||
protected SelfRenderingFunctionSupport getRenderingFunctionSupport(
|
||||
List<SqmTypedNode<?>> arguments,
|
||||
AllowableFunctionReturnType<?> impliedResultType,
|
||||
QueryEngine queryEngine) {
|
||||
protected FunctionRenderingSupport getRenderingSupport() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(
|
||||
SqlAppender sqlAppender,
|
||||
String functionName,
|
||||
List<SqlAstNode> sqlAstArguments,
|
||||
SqlAstWalker walker,
|
||||
SessionFactoryImplementor sessionFactory) {
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* 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.function;
|
||||
|
||||
import org.hibernate.query.criteria.JpaFunction;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
|
||||
/**
|
||||
* Contract for functions impls that would like to control the
|
||||
* translation of the SQM expression into the SQL AST function
|
||||
* <p/>
|
||||
* {@link #convertToSqlAst} is the main contract here. It will
|
||||
* be called as we walk the SQM tree to generate SQL AST and
|
||||
* asked to produce the equivalent SQL AST expression
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmFunction<T> extends SqmExpression<T>, JpaFunction<T>, DomainResultProducer<T> {
|
||||
// /**
|
||||
// * Generate the SQL AST form of the function as an expression.
|
||||
// *
|
||||
// * To be able to use this in the select-clause, the returned
|
||||
// * expression must also implement the
|
||||
// * {@link DomainResultProducer}
|
||||
// * contract
|
||||
// */
|
||||
// Expression convertToSqlAst(SqmToSqlAstConverter walker);
|
||||
//
|
||||
@Override
|
||||
default <X> X accept(SemanticQueryWalker<X> walker) {
|
||||
return walker.visitFunction( this );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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.function;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
|
||||
/**
|
||||
* Extension for supplying support for non-standard (ANSI SQL) functions in HQL and Criteria queries.
|
||||
*
|
||||
* Ultimately acts as a factory for SQM function expressions.
|
||||
*
|
||||
* @author David Channon
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Incubating
|
||||
public interface SqmFunctionDescriptor {
|
||||
/**
|
||||
* Generate a representation of the described function as a SQL AST node
|
||||
*/
|
||||
Expression generateSqlExpression(
|
||||
String functionName,
|
||||
List<? extends SqmVisitableNode> arguments,
|
||||
Supplier<MappingModelExpressable> inferableTypeAccess,
|
||||
SqmToSqlAstConverter converter,
|
||||
SqlAstCreationState creationState);
|
||||
|
||||
}
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* 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.function;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.query.sqm.produce.function.NamedFunctionDescriptorBuilder;
|
||||
import org.hibernate.query.sqm.produce.function.PatternFunctionDescriptorBuilder;
|
||||
import org.hibernate.query.sqm.produce.function.VarArgsFunctionDescriptorBuilder;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import static java.lang.String.CASE_INSENSITIVE_ORDER;
|
||||
|
||||
/**
|
||||
* Defines a registry for SQLFunction instances
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Incubating
|
||||
public class SqmFunctionRegistry {
|
||||
private static final Logger log = Logger.getLogger( SqmFunctionRegistry.class );
|
||||
|
||||
private final Map<String, SqmFunctionDescriptor> functionMap = new TreeMap<>( CASE_INSENSITIVE_ORDER );
|
||||
private final Map<String,String> alternateKeyMap = new TreeMap<>( CASE_INSENSITIVE_ORDER );
|
||||
|
||||
public SqmFunctionRegistry() {
|
||||
log.tracef( "SqmFunctionRegistry created" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a SqmFunctionTemplate by name. Returns {@code null} if
|
||||
* no such function is found.
|
||||
*/
|
||||
public SqmFunctionDescriptor findFunctionDescriptor(String functionName) {
|
||||
SqmFunctionDescriptor found = null;
|
||||
|
||||
final String alternateKeyResolution = alternateKeyMap.get( functionName );
|
||||
if ( alternateKeyResolution != null ) {
|
||||
found = functionMap.get( alternateKeyResolution );
|
||||
}
|
||||
|
||||
if ( found == null ) {
|
||||
found = functionMap.get( functionName );
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a function descriptor by name
|
||||
*/
|
||||
public SqmFunctionDescriptor register(String registrationKey, SqmFunctionDescriptor function) {
|
||||
final SqmFunctionDescriptor priorRegistration = functionMap.put( registrationKey, function );
|
||||
log.debugf(
|
||||
"Registered SqmFunctionTemplate [%s] under %s; prior registration was %s",
|
||||
function,
|
||||
registrationKey,
|
||||
priorRegistration
|
||||
);
|
||||
|
||||
return function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a pattern-based descriptor by name. Shortcut for building the descriptor via
|
||||
* {@link #patternDescriptorBuilder} accepting its defaults.
|
||||
*/
|
||||
public SqmFunctionDescriptor registerPattern(String name, String pattern) {
|
||||
return patternDescriptorBuilder( name, pattern ).register();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a pattern-based descriptor by name and invariant return type. Shortcut for building the descriptor
|
||||
* via {@link #patternDescriptorBuilder} accepting its defaults.
|
||||
*/
|
||||
public SqmFunctionDescriptor registerPattern(String name, String pattern, AllowableFunctionReturnType returnType) {
|
||||
return patternDescriptorBuilder( name, pattern )
|
||||
.setInvariantType( returnType )
|
||||
.register();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a builder for creating and registering a pattern-based function descriptor.
|
||||
*
|
||||
* @param registrationKey The name under which the descriptor will get registered
|
||||
* @param pattern The pattern defining the the underlying function call
|
||||
*
|
||||
* @return The builder
|
||||
*/
|
||||
public PatternFunctionDescriptorBuilder patternDescriptorBuilder(String registrationKey, String pattern) {
|
||||
return new PatternFunctionDescriptorBuilder( this, registrationKey, pattern );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a descriptor by name. Shortcut for building a descriptor via {@link #namedDescriptorBuilder} using the
|
||||
* passed name as both the registration key and underlying SQL function name and accepting the builder's defaults.
|
||||
*
|
||||
* @param name The function name (and registration key)
|
||||
*/
|
||||
public SqmFunctionDescriptor registerNamed(String name) {
|
||||
return namedDescriptorBuilder( name ).register();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a named descriptor by name and invariant return type. Shortcut for building
|
||||
* a descriptor via {@link #namedDescriptorBuilder} using the passed name as both the
|
||||
* registration key and underlying SQL function name and accepting the builder's defaults.
|
||||
*
|
||||
* @param name The function name (and registration key)
|
||||
*/
|
||||
public SqmFunctionDescriptor registerNamed(String name, AllowableFunctionReturnType returnType) {
|
||||
return namedDescriptorBuilder( name ).setInvariantType( returnType ).register();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a builder for creating and registering a name-based function descriptor using the passed name as
|
||||
* both the registration key and underlying SQL function name
|
||||
*
|
||||
* @param name The function name (and registration key)
|
||||
*
|
||||
* @return The builder
|
||||
*/
|
||||
public NamedFunctionDescriptorBuilder namedDescriptorBuilder(String name) {
|
||||
return namedDescriptorBuilder( name, name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a builder for creating and registering a name-based function descriptor.
|
||||
*
|
||||
* @param registrationKey The name under which the descriptor will get registered
|
||||
* @param name The underlying SQL function name to use
|
||||
*
|
||||
* @return The builder
|
||||
*/
|
||||
public NamedFunctionDescriptorBuilder namedDescriptorBuilder(String registrationKey, String name) {
|
||||
return new NamedFunctionDescriptorBuilder( this, registrationKey, name );
|
||||
}
|
||||
|
||||
public NamedFunctionDescriptorBuilder noArgsBuilder(String name) {
|
||||
return noArgsBuilder( name, name );
|
||||
}
|
||||
|
||||
public NamedFunctionDescriptorBuilder noArgsBuilder(String registrationKey, String name) {
|
||||
return namedDescriptorBuilder( registrationKey, name )
|
||||
.setExactArgumentCount( 0 );
|
||||
}
|
||||
|
||||
public VarArgsFunctionDescriptorBuilder varArgsBuilder(String registrationKey, String begin, String sep, String end) {
|
||||
return new VarArgsFunctionDescriptorBuilder( this, registrationKey, begin, sep, end );
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialized registration method for registering a named template for functions
|
||||
* expecting zero arguments. Short-cut for building a named template via
|
||||
* {@link #namedDescriptorBuilder} specifying zero arguments and accepting the
|
||||
* rest of the builder's defaults.
|
||||
*
|
||||
* @param name The function name (and registration key)
|
||||
*/
|
||||
public SqmFunctionDescriptor registerNoArgs(String name) {
|
||||
return registerNoArgs( name, name );
|
||||
}
|
||||
|
||||
public SqmFunctionDescriptor registerNoArgs(String registrationKey, String name) {
|
||||
return noArgsBuilder( registrationKey, name ).register();
|
||||
}
|
||||
|
||||
public SqmFunctionDescriptor registerNoArgs(String name, AllowableFunctionReturnType returnType) {
|
||||
return registerNoArgs( name, name, returnType );
|
||||
}
|
||||
|
||||
public SqmFunctionDescriptor registerNoArgs(String registrationKey, String name, AllowableFunctionReturnType returnType) {
|
||||
return noArgsBuilder( registrationKey, name )
|
||||
.setInvariantType( returnType )
|
||||
.register();
|
||||
}
|
||||
|
||||
public SqmFunctionDescriptor registerVarArgs(String registrationKey, AllowableFunctionReturnType returnType, String begin, String sep, String end) {
|
||||
return varArgsBuilder( registrationKey, begin, sep, end )
|
||||
.setInvariantType( returnType )
|
||||
.register();
|
||||
}
|
||||
|
||||
public SqmFunctionDescriptor wrapInJdbcEscape(String registrationKey, SqmFunctionDescriptor wrapped) {
|
||||
final JdbcEscapeFunctionDescriptor wrapperTemplate = new JdbcEscapeFunctionDescriptor( wrapped );
|
||||
register( registrationKey, wrapperTemplate );
|
||||
return wrapperTemplate;
|
||||
}
|
||||
|
||||
public void registerAlternateKey(String alternateKey, String mappedKey) {
|
||||
log.debugf( "Registering alternate key : %s -> %s", alternateKey, mappedKey );
|
||||
alternateKeyMap.put( alternateKey, mappedKey );
|
||||
}
|
||||
|
||||
/**
|
||||
* Overlay the functions registered here on top of the
|
||||
* incoming registry, potentially overriding its registrations
|
||||
*/
|
||||
public void overlay(SqmFunctionRegistry registryToOverly) {
|
||||
// NOTE : done in this "direction" as it is easier to access the
|
||||
// functionMap directly in performing this operation
|
||||
functionMap.forEach( registryToOverly::register );
|
||||
alternateKeyMap.forEach( registryToOverly::registerAlternateKey );
|
||||
}
|
||||
|
||||
public void close() {
|
||||
functionMap.clear();
|
||||
alternateKeyMap.clear();
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* 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.function;
|
||||
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.produce.function.internal.SelfRenderingSqmFunction;
|
||||
|
||||
/**
|
||||
* Adds a JDBC function escape (i.e. `{fn <wrapped-function-call>}) around the wrapped function
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class SqmJdbcFunctionEscapeWrapper<T>
|
||||
extends SelfRenderingSqmFunction<T> {
|
||||
private final SelfRenderingSqmFunction<?> wrappedSqmFunction;
|
||||
|
||||
public SqmJdbcFunctionEscapeWrapper(
|
||||
SelfRenderingSqmFunction<T> wrappedSqmFunction,
|
||||
NodeBuilder nodeBuilder) {
|
||||
super(
|
||||
(sqlAppender,
|
||||
sqlAstArguments,
|
||||
walker,
|
||||
sessionFactory) -> {
|
||||
sqlAppender.appendSql( "{fn " );
|
||||
wrappedSqmFunction.getRenderingSupport().render(
|
||||
sqlAppender,
|
||||
sqlAstArguments,
|
||||
walker,
|
||||
sessionFactory
|
||||
);
|
||||
sqlAppender.appendSql( "}" );
|
||||
},
|
||||
wrappedSqmFunction.getArguments(),
|
||||
wrappedSqmFunction.getNodeType(),
|
||||
nodeBuilder,
|
||||
wrappedSqmFunction.getFunctionName()
|
||||
);
|
||||
this.wrappedSqmFunction = wrappedSqmFunction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asLoggableText() {
|
||||
return "wrapped-function[ " + wrappedSqmFunction.asLoggableText() + " ]";
|
||||
}
|
||||
|
||||
}
|
|
@ -47,6 +47,6 @@
|
|||
* * str - generally defined as `cast(?1 as CHAR )`
|
||||
* * non-standard functions
|
||||
* * using JPA's function('function_name', [args]*) syntax.
|
||||
* * directly leveraging Hibernate's {@link org.hibernate.query.sqm.produce.function.SqmFunctionRegistry}
|
||||
* * directly leveraging Hibernate's {@link org.hibernate.query.sqm.function.SqmFunctionRegistry}
|
||||
*/
|
||||
package org.hibernate.query.sqm.function;
|
||||
|
|
|
@ -37,12 +37,13 @@ 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.AllowableFunctionReturnType;
|
||||
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.SemanticException;
|
||||
import org.hibernate.query.TrimSpec;
|
||||
import org.hibernate.query.UnaryArithmeticOperator;
|
||||
import org.hibernate.query.criteria.JpaCoalesce;
|
||||
|
@ -52,12 +53,10 @@ 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.function.SqmFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.spi.SqmCreationContext;
|
||||
import org.hibernate.query.sqm.tree.SqmNode;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmBagJoin;
|
||||
|
@ -66,18 +65,22 @@ 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.JpaCriteriaParameter;
|
||||
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.SqmCastTarget;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmCoalesce;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmCollectionSize;
|
||||
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmDistinct;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||
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.SqmTrimSpecification;
|
||||
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;
|
||||
|
@ -100,7 +103,6 @@ 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;
|
||||
|
@ -112,7 +114,7 @@ import static org.hibernate.query.internal.QueryHelper.highestPrecedenceType;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
||||
public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
||||
/**
|
||||
* Simplified creation from a SessionFactory
|
||||
*/
|
||||
|
@ -152,6 +154,11 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
|||
return queryEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JpaMetamodel getJpaMetamodel() {
|
||||
return domainModel;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
// for potential future use
|
||||
}
|
||||
|
@ -188,13 +195,14 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
|||
|
||||
@Override
|
||||
public <X, T> SqmExpression<X> cast(JpaExpression<T> expression, Class<X> castTargetJavaType) {
|
||||
final BasicDomainType type = getTypeConfiguration().standardBasicTypeForJavaType( castTargetJavaType );
|
||||
//noinspection unchecked
|
||||
BasicDomainType<X> type = getTypeConfiguration().standardBasicTypeForJavaType( castTargetJavaType );
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("cast").makeSqmFunctionExpression(
|
||||
asList( (SqmTypedNode) expression, new SqmCastTarget<>( type, this ) ),
|
||||
return new SqmFunction(
|
||||
"cast",
|
||||
getFunctionDescriptor( "cast" ),
|
||||
type,
|
||||
queryEngine
|
||||
asList( (SqmTypedNode) expression, new SqmCastTarget<>( type, this ) ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -439,19 +447,24 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
|||
@Override
|
||||
public <N extends Number> SqmExpression<Double> avg(Expression<N> argument) {
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("avg").makeSqmFunctionExpression(
|
||||
(SqmTypedNode) argument,
|
||||
return new SqmFunction(
|
||||
"avg",
|
||||
getFunctionDescriptor( "avg" ),
|
||||
StandardBasicTypes.DOUBLE,
|
||||
queryEngine
|
||||
Collections.singletonList( (SqmTypedNode) argument ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <N extends Number> SqmExpression<N> sum(Expression<N> argument) {
|
||||
return getFunctionTemplate("sum").makeSqmFunctionExpression(
|
||||
(SqmTypedNode) argument,
|
||||
(AllowableFunctionReturnType<N>) ((SqmExpression<N>) argument).getNodeType(),
|
||||
queryEngine
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"sum",
|
||||
getFunctionDescriptor( "sum" ),
|
||||
( (SqmExpression<N>) argument ).getNodeType(),
|
||||
Collections.singletonList( (SqmTypedNode) argument ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -467,19 +480,25 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
|||
|
||||
@Override
|
||||
public <N extends Number> SqmExpression<N> max(Expression<N> argument) {
|
||||
return getFunctionTemplate("max").makeSqmFunctionExpression(
|
||||
(SqmTypedNode) argument,
|
||||
(AllowableFunctionReturnType<N>) ((SqmExpression<N>) argument).getNodeType(),
|
||||
queryEngine
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"max",
|
||||
getFunctionDescriptor( "max" ),
|
||||
( (SqmExpression<N>) argument ).getNodeType(),
|
||||
Collections.singletonList( (SqmTypedNode) argument ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <N extends Number> SqmExpression<N> min(Expression<N> argument) {
|
||||
return getFunctionTemplate("min").makeSqmFunctionExpression(
|
||||
(SqmTypedNode) argument,
|
||||
(AllowableFunctionReturnType<N>) ((SqmExpression<N>) argument).getNodeType(),
|
||||
queryEngine
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"min",
|
||||
getFunctionDescriptor( "min" ),
|
||||
( (SqmExpression<N>) argument ).getNodeType(),
|
||||
Collections.singletonList( (SqmTypedNode) argument ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -496,20 +515,24 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
|||
@Override
|
||||
public SqmExpression<Long> count(Expression<?> argument) {
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("count").makeSqmFunctionExpression(
|
||||
(SqmTypedNode) argument,
|
||||
return new SqmFunction(
|
||||
"count",
|
||||
getFunctionDescriptor( "count" ),
|
||||
StandardBasicTypes.LONG,
|
||||
queryEngine
|
||||
Collections.singletonList( (SqmExpression) argument ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<Long> countDistinct(Expression<?> argument) {
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("count").makeSqmFunctionExpression(
|
||||
new SqmDistinct<>( (SqmExpression<?>) argument, getQueryEngine().getCriteriaBuilder() ),
|
||||
return new SqmFunction(
|
||||
"count",
|
||||
getFunctionDescriptor( "count" ),
|
||||
StandardBasicTypes.LONG,
|
||||
queryEngine
|
||||
Collections.singletonList( new SqmDistinct( (SqmExpression) argument, this ) ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -524,10 +547,13 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
|||
|
||||
@Override
|
||||
public <N extends Number> SqmExpression<N> abs(Expression<N> x) {
|
||||
return getFunctionTemplate("abs").makeSqmFunctionExpression(
|
||||
(SqmTypedNode) x,
|
||||
(AllowableFunctionReturnType<N>) ((SqmExpression<N>) x).getNodeType(),
|
||||
queryEngine
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"abs",
|
||||
getFunctionDescriptor( "abs" ),
|
||||
( (SqmExpression<N>) x ).getNodeType(),
|
||||
Collections.singletonList( (SqmExpression) x ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -663,13 +689,15 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
|||
@Override
|
||||
public SqmExpression<Double> sqrt(Expression<? extends Number> x) {
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("sqrt").makeSqmFunctionExpression(
|
||||
(SqmTypedNode) x,
|
||||
(AllowableFunctionReturnType) QueryHelper.highestPrecedenceType2(
|
||||
((SqmExpression) x).getNodeType(),
|
||||
return new SqmFunction(
|
||||
"sqrt",
|
||||
getFunctionDescriptor( "sqrt" ),
|
||||
QueryHelper.highestPrecedenceType2(
|
||||
( (SqmExpression) x ).getNodeType(),
|
||||
StandardBasicTypes.DOUBLE
|
||||
),
|
||||
queryEngine
|
||||
Collections.singletonList( (SqmExpression) x ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -787,14 +815,16 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
|||
final SqmExpression xSqmExpression = (SqmExpression) x;
|
||||
final SqmExpression ySqmExpression = (SqmExpression) y;
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate( "concat" ).makeSqmFunctionExpression(
|
||||
asList( xSqmExpression, ySqmExpression ),
|
||||
(AllowableFunctionReturnType) highestPrecedenceType(
|
||||
return new SqmFunction(
|
||||
"concat",
|
||||
getFunctionDescriptor( "concat" ),
|
||||
highestPrecedenceType(
|
||||
xSqmExpression.getNodeType(),
|
||||
ySqmExpression.getNodeType(),
|
||||
StandardBasicTypes.STRING
|
||||
),
|
||||
getQueryEngine()
|
||||
asList( xSqmExpression, ySqmExpression ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -803,14 +833,16 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
|||
final SqmExpression xSqmExpression = (SqmExpression) x;
|
||||
final SqmExpression ySqmExpression = literal( y );
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate( "concat" ).makeSqmFunctionExpression(
|
||||
asList( xSqmExpression, ySqmExpression ),
|
||||
(AllowableFunctionReturnType) highestPrecedenceType(
|
||||
return new SqmFunction(
|
||||
"concat",
|
||||
getFunctionDescriptor( "concat" ),
|
||||
highestPrecedenceType(
|
||||
xSqmExpression.getNodeType(),
|
||||
ySqmExpression.getNodeType(),
|
||||
StandardBasicTypes.STRING
|
||||
),
|
||||
getQueryEngine()
|
||||
asList( xSqmExpression, ySqmExpression ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -819,14 +851,16 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
|||
final SqmExpression xSqmExpression = literal( x );
|
||||
final SqmExpression ySqmExpression = (SqmExpression) y;
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate( "concat" ).makeSqmFunctionExpression(
|
||||
asList( xSqmExpression, ySqmExpression ),
|
||||
(AllowableFunctionReturnType) highestPrecedenceType(
|
||||
return new SqmFunction(
|
||||
"concat",
|
||||
getFunctionDescriptor( "concat" ),
|
||||
highestPrecedenceType(
|
||||
xSqmExpression.getNodeType(),
|
||||
ySqmExpression.getNodeType(),
|
||||
StandardBasicTypes.STRING
|
||||
),
|
||||
getQueryEngine()
|
||||
asList( xSqmExpression, ySqmExpression ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -835,14 +869,16 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
|||
final SqmExpression xSqmExpression = literal( x );
|
||||
final SqmExpression ySqmExpression = literal( y );
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate( "concat" ).makeSqmFunctionExpression(
|
||||
asList( xSqmExpression, ySqmExpression ),
|
||||
(AllowableFunctionReturnType) highestPrecedenceType(
|
||||
return new SqmFunction(
|
||||
"concat",
|
||||
getFunctionDescriptor( "concat" ),
|
||||
highestPrecedenceType(
|
||||
xSqmExpression.getNodeType(),
|
||||
ySqmExpression.getNodeType(),
|
||||
StandardBasicTypes.STRING
|
||||
),
|
||||
getQueryEngine()
|
||||
asList( xSqmExpression, ySqmExpression ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -862,10 +898,12 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
|||
);
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate( "substring" ).makeSqmFunctionExpression(
|
||||
len==null ? asList( source, from ) : asList( source, from, len ),
|
||||
return new SqmFunction(
|
||||
"substring",
|
||||
getFunctionDescriptor( "substring" ),
|
||||
resultType,
|
||||
getQueryEngine()
|
||||
len==null ? asList( source, from ) : asList( source, from, len ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -903,25 +941,28 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
|||
|
||||
private SqmFunction<String> createTrimNode(TrimSpec trimSpecification, SqmExpression trimCharacter, SqmExpression source) {
|
||||
|
||||
final ArrayList<SqmTypedNode<?>> arguments = new ArrayList<>();
|
||||
if ( trimSpecification != null ) {
|
||||
arguments.add(
|
||||
new SqmTrimSpecification( trimSpecification, this )
|
||||
);
|
||||
}
|
||||
final ArrayList<SqmNode> arguments = new ArrayList<>();
|
||||
|
||||
if ( trimCharacter != null ) {
|
||||
arguments.add( trimCharacter );
|
||||
}
|
||||
|
||||
arguments.add( source );
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate( "trim" ).makeSqmFunctionExpression(
|
||||
arguments,
|
||||
(AllowableFunctionReturnType) QueryHelper.highestPrecedenceType2( source.getNodeType(), StandardBasicTypes.STRING ),
|
||||
getQueryEngine()
|
||||
if ( trimSpecification != null ) {
|
||||
arguments.add(
|
||||
new SqmTrimSpecification( trimSpecification, this )
|
||||
);
|
||||
}
|
||||
|
||||
if ( trimCharacter != null ) {
|
||||
arguments.add( trimCharacter );
|
||||
}
|
||||
|
||||
arguments.add( source );
|
||||
|
||||
//noinspection unchecked
|
||||
return new SqmFunction(
|
||||
"trim",
|
||||
getFunctionDescriptor( "trim" ),
|
||||
QueryHelper.highestPrecedenceType2( source.getNodeType(), StandardBasicTypes.STRING ),
|
||||
arguments,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -978,10 +1019,12 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
|||
);
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate( "lower" ).makeSqmFunctionExpression(
|
||||
(SqmExpression) x,
|
||||
return new SqmFunction(
|
||||
"lower",
|
||||
getFunctionDescriptor( "lower" ),
|
||||
type,
|
||||
getQueryEngine()
|
||||
Collections.singletonList( (SqmExpression) x ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -993,24 +1036,27 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
|||
);
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate( "upper" ).makeSqmFunctionExpression(
|
||||
(SqmExpression) x,
|
||||
return new SqmFunction(
|
||||
"upper",
|
||||
getFunctionDescriptor( "upper" ),
|
||||
type,
|
||||
getQueryEngine()
|
||||
Collections.singletonList( (SqmExpression) x ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmFunction<Integer> length(Expression<String> argument) {
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate( "length" ).makeSqmFunctionExpression(
|
||||
(SqmExpression) argument,
|
||||
return new SqmFunction(
|
||||
"length",
|
||||
getFunctionDescriptor( "length" ),
|
||||
(AllowableFunctionReturnType) highestPrecedenceType(
|
||||
((SqmExpression) argument).getNodeType(),
|
||||
StandardBasicTypes.INTEGER
|
||||
),
|
||||
getQueryEngine()
|
||||
Collections.singletonList( (SqmExpression) argument ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1047,12 +1093,13 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
|||
}
|
||||
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("locate").makeSqmFunctionExpression(
|
||||
arguments,
|
||||
return new SqmFunction(
|
||||
"locate",
|
||||
getFunctionDescriptor( "locate" ),
|
||||
type,
|
||||
getQueryEngine()
|
||||
arguments,
|
||||
this
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1085,55 +1132,65 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
|||
@Override
|
||||
public SqmFunction<Date> currentDate() {
|
||||
//noinspection unchecked
|
||||
// return getFunctionTemplate("current_date").makeSqmFunctionExpression(
|
||||
// StandardBasicTypes.DATE,
|
||||
// queryEngine
|
||||
// );
|
||||
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
return new SqmFunction(
|
||||
"current_date",
|
||||
getFunctionDescriptor( "current_date" ),
|
||||
StandardBasicTypes.DATE,
|
||||
Collections.emptyList(),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmFunction<Timestamp> currentTimestamp() {
|
||||
//noinspection unchecked
|
||||
// return getFunctionTemplate("current_timestamp").makeSqmFunctionExpression(
|
||||
// StandardBasicTypes.TIMESTAMP,
|
||||
// queryEngine
|
||||
// );
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
return new SqmFunction(
|
||||
"current_timestamp",
|
||||
getFunctionDescriptor( "current_timestamp" ),
|
||||
StandardBasicTypes.TIMESTAMP,
|
||||
Collections.emptyList(),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmFunction<Time> currentTime() {
|
||||
//noinspection unchecked
|
||||
// return getFunctionTemplate("current_time").makeSqmFunctionExpression(
|
||||
// StandardBasicTypes.TIME,
|
||||
// queryEngine
|
||||
// );
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
return new SqmFunction(
|
||||
"current_time",
|
||||
getFunctionDescriptor( "current_time" ),
|
||||
StandardBasicTypes.TIME,
|
||||
Collections.emptyList(),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmFunction<Instant> currentInstant() {
|
||||
//noinspection unchecked
|
||||
return getFunctionTemplate("current_timestamp").makeSqmFunctionExpression(
|
||||
return new SqmFunction(
|
||||
"current_instant",
|
||||
getFunctionDescriptor( "current_instant" ),
|
||||
StandardBasicTypes.INSTANT,
|
||||
queryEngine
|
||||
Collections.emptyList(),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> SqmFunction<T> function(String name, Class<T> type, Expression<?>[] args) {
|
||||
final SqmFunctionTemplate functionTemplate = getFunctionTemplate(name);
|
||||
final SqmFunctionDescriptor functionTemplate = getFunctionDescriptor( name);
|
||||
if ( functionTemplate == null ) {
|
||||
throw new SemanticException( "Could not resolve function named `" + name + "`" );
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
return functionTemplate.makeSqmFunctionExpression(
|
||||
(List) expressionList( args ),
|
||||
return new SqmFunction<>(
|
||||
name,
|
||||
getFunctionDescriptor( name ),
|
||||
getTypeConfiguration().standardBasicTypeForJavaType( type ),
|
||||
getQueryEngine()
|
||||
(List) expressionList( args ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1254,16 +1311,17 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
|||
second.getNodeType()
|
||||
);
|
||||
|
||||
return getFunctionTemplate("nullif").makeSqmFunctionExpression(
|
||||
asList( first, second ),
|
||||
return new SqmFunction<>(
|
||||
"nullif",
|
||||
getFunctionDescriptor( "nullif" ),
|
||||
type,
|
||||
getQueryEngine()
|
||||
asList( first, second ),
|
||||
this
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
private SqmFunctionTemplate getFunctionTemplate(String name) {
|
||||
return queryEngine.getSqmFunctionRegistry().findFunctionTemplate(name);
|
||||
private SqmFunctionDescriptor getFunctionDescriptor(String name) {
|
||||
return queryEngine.getSqmFunctionRegistry().findFunctionDescriptor( name);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -27,29 +27,30 @@ import org.hibernate.query.sqm.tree.domain.SqmMinElementPath;
|
|||
import org.hibernate.query.sqm.tree.domain.SqmMinIndexPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
|
||||
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
|
||||
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.SqmCastTarget;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmCoalesce;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmCollectionSize;
|
||||
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmDistinct;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmPathEntityType;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmRestrictedSubQueryExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmStar;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmTrimSpecification;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmTuple;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmUnaryOperation;
|
||||
import org.hibernate.query.sqm.function.SqmCastTarget;
|
||||
import org.hibernate.query.sqm.function.SqmDistinct;
|
||||
import org.hibernate.query.sqm.function.SqmExtractUnit;
|
||||
import org.hibernate.query.sqm.function.SqmFunction;
|
||||
import org.hibernate.query.sqm.function.SqmStar;
|
||||
import org.hibernate.query.sqm.function.SqmTrimSpecification;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmCrossJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
|
||||
|
@ -605,7 +606,12 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object visitFunction(SqmFunction sqmFunction) {
|
||||
public Object visitFunction(SqmFunction tSqmFunction) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitCoalesce(SqmCoalesce sqmCoalesce) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,16 +8,16 @@ package org.hibernate.query.sqm.produce.function;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ArgumentsValidator {
|
||||
/**
|
||||
* The main (functional) operation defining validation
|
||||
* Validate the arguments
|
||||
*/
|
||||
void validate(List<SqmTypedNode<?>> arguments);
|
||||
void validate(List<? extends SqmVisitableNode> arguments);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* 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.produce.function;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.sqm.produce.function.internal.SelfRenderingSqmFunction;
|
||||
import org.hibernate.query.sqm.produce.function.spi.AbstractSqmFunctionTemplate;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.function.SqmJdbcFunctionEscapeWrapper;
|
||||
|
||||
/**
|
||||
* Acts as a wrapper to another SqmFunctionTemplate - upon rendering uses the
|
||||
* standard JDBC escape sequence (i.e. `{fn blah}`) when rendering the SQL.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class JdbcFunctionEscapeWrapperTemplate
|
||||
extends AbstractSqmFunctionTemplate {
|
||||
private final SqmFunctionTemplate wrapped;
|
||||
|
||||
public JdbcFunctionEscapeWrapperTemplate(SqmFunctionTemplate wrapped) {
|
||||
this.wrapped = wrapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> SelfRenderingSqmFunction<T> generateSqmFunctionExpression(
|
||||
List<SqmTypedNode<?>> arguments,
|
||||
AllowableFunctionReturnType<T> impliedResultType,
|
||||
QueryEngine queryEngine) {
|
||||
return new SqmJdbcFunctionEscapeWrapper<>(
|
||||
wrapped.makeSqmFunctionExpression(
|
||||
arguments,
|
||||
impliedResultType,
|
||||
queryEngine
|
||||
),
|
||||
queryEngine.getCriteriaBuilder()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -7,15 +7,17 @@
|
|||
package org.hibernate.query.sqm.produce.function;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.query.sqm.produce.function.spi.NamedSqmFunctionTemplate;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.function.NamedSqmFunctionDescriptor;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NamedFunctionTemplateBuilder {
|
||||
private static final Logger log = Logger.getLogger( NamedFunctionTemplateBuilder.class );
|
||||
public class NamedFunctionDescriptorBuilder {
|
||||
private static final Logger log = Logger.getLogger( NamedFunctionDescriptorBuilder.class );
|
||||
|
||||
private final SqmFunctionRegistry registry;
|
||||
private final String registrationKey;
|
||||
|
@ -27,54 +29,53 @@ public class NamedFunctionTemplateBuilder {
|
|||
|
||||
private boolean useParenthesesWhenNoArgs;
|
||||
|
||||
public NamedFunctionTemplateBuilder(SqmFunctionRegistry registry, String registrationKey, String functionName) {
|
||||
public NamedFunctionDescriptorBuilder(SqmFunctionRegistry registry, String registrationKey, String functionName) {
|
||||
this.registry = registry;
|
||||
this.registrationKey = registrationKey;
|
||||
this.functionName = functionName;
|
||||
}
|
||||
|
||||
public NamedFunctionTemplateBuilder setArgumentsValidator(ArgumentsValidator argumentsValidator) {
|
||||
public NamedFunctionDescriptorBuilder setArgumentsValidator(ArgumentsValidator argumentsValidator) {
|
||||
this.argumentsValidator = argumentsValidator;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedFunctionTemplateBuilder setArgumentCountBetween(int min, int max) {
|
||||
public NamedFunctionDescriptorBuilder setArgumentCountBetween(int min, int max) {
|
||||
return setArgumentsValidator( StandardArgumentsValidators.between( min, max ) );
|
||||
}
|
||||
|
||||
public NamedFunctionTemplateBuilder setExactArgumentCount(int exactArgumentCount) {
|
||||
public NamedFunctionDescriptorBuilder setExactArgumentCount(int exactArgumentCount) {
|
||||
return setArgumentsValidator( StandardArgumentsValidators.exactly( exactArgumentCount ) );
|
||||
}
|
||||
|
||||
public NamedFunctionTemplateBuilder setReturnTypeResolver(FunctionReturnTypeResolver returnTypeResolver) {
|
||||
public NamedFunctionDescriptorBuilder setReturnTypeResolver(FunctionReturnTypeResolver returnTypeResolver) {
|
||||
this.returnTypeResolver = returnTypeResolver;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedFunctionTemplateBuilder setInvariantType(AllowableFunctionReturnType invariantType) {
|
||||
public NamedFunctionDescriptorBuilder setInvariantType(AllowableFunctionReturnType invariantType) {
|
||||
setReturnTypeResolver( StandardFunctionReturnTypeResolvers.invariant( invariantType ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedFunctionTemplateBuilder setUseParenthesesWhenNoArgs(boolean useParenthesesWhenNoArgs) {
|
||||
public NamedFunctionDescriptorBuilder setUseParenthesesWhenNoArgs(boolean useParenthesesWhenNoArgs) {
|
||||
this.useParenthesesWhenNoArgs = useParenthesesWhenNoArgs;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SqmFunctionTemplate register() {
|
||||
public SqmFunctionDescriptor register() {
|
||||
return registry.register(
|
||||
registrationKey,
|
||||
template()
|
||||
build()
|
||||
);
|
||||
}
|
||||
|
||||
public SqmFunctionTemplate template() {
|
||||
return new NamedSqmFunctionTemplate(
|
||||
public SqmFunctionDescriptor build() {
|
||||
return new NamedSqmFunctionDescriptor(
|
||||
registrationKey,
|
||||
functionName,
|
||||
useParenthesesWhenNoArgs,
|
||||
argumentsValidator,
|
||||
returnTypeResolver,
|
||||
registrationKey
|
||||
argumentsValidator
|
||||
);
|
||||
}
|
||||
}
|
|
@ -7,13 +7,15 @@
|
|||
package org.hibernate.query.sqm.produce.function;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
|
||||
import org.hibernate.query.sqm.produce.function.spi.PatternBasedSqmFunctionTemplate;
|
||||
import org.hibernate.query.sqm.function.PatternBasedSqmFunctionTemplate;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class PatternFunctionTemplateBuilder {
|
||||
public class PatternFunctionDescriptorBuilder {
|
||||
private final SqmFunctionRegistry registry;
|
||||
private final String registrationKey;
|
||||
private final String pattern;
|
||||
|
@ -23,50 +25,49 @@ public class PatternFunctionTemplateBuilder {
|
|||
|
||||
private boolean useParenthesesWhenNoArgs;
|
||||
|
||||
public PatternFunctionTemplateBuilder(SqmFunctionRegistry registry, String registrationKey, String pattern) {
|
||||
public PatternFunctionDescriptorBuilder(SqmFunctionRegistry registry, String registrationKey, String pattern) {
|
||||
this.registry = registry;
|
||||
this.registrationKey = registrationKey;
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
public PatternFunctionTemplateBuilder setArgumentsValidator(ArgumentsValidator argumentsValidator) {
|
||||
public PatternFunctionDescriptorBuilder setArgumentsValidator(ArgumentsValidator argumentsValidator) {
|
||||
this.argumentsValidator = argumentsValidator;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PatternFunctionTemplateBuilder setExactArgumentCount(int exactArgumentCount) {
|
||||
public PatternFunctionDescriptorBuilder setExactArgumentCount(int exactArgumentCount) {
|
||||
return setArgumentsValidator( StandardArgumentsValidators.exactly( exactArgumentCount ) );
|
||||
}
|
||||
|
||||
public PatternFunctionTemplateBuilder setArgumentCountBetween(int min, int max) {
|
||||
public PatternFunctionDescriptorBuilder setArgumentCountBetween(int min, int max) {
|
||||
return setArgumentsValidator( StandardArgumentsValidators.between( min, max ) );
|
||||
}
|
||||
|
||||
public PatternFunctionTemplateBuilder setReturnTypeResolver(FunctionReturnTypeResolver returnTypeResolver) {
|
||||
public PatternFunctionDescriptorBuilder setReturnTypeResolver(FunctionReturnTypeResolver returnTypeResolver) {
|
||||
this.returnTypeResolver = returnTypeResolver;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PatternFunctionTemplateBuilder setInvariantType(AllowableFunctionReturnType invariantType) {
|
||||
public PatternFunctionDescriptorBuilder setInvariantType(AllowableFunctionReturnType invariantType) {
|
||||
setReturnTypeResolver( StandardFunctionReturnTypeResolvers.invariant( invariantType ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
public PatternFunctionTemplateBuilder setUseParenthesesWhenNoArgs(boolean useParenthesesWhenNoArgs) {
|
||||
public PatternFunctionDescriptorBuilder setUseParenthesesWhenNoArgs(boolean useParenthesesWhenNoArgs) {
|
||||
this.useParenthesesWhenNoArgs = useParenthesesWhenNoArgs;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SqmFunctionTemplate register() {
|
||||
public SqmFunctionDescriptor register() {
|
||||
return registry.register( registrationKey, template() );
|
||||
}
|
||||
|
||||
public SqmFunctionTemplate template() {
|
||||
public SqmFunctionDescriptor template() {
|
||||
return new PatternBasedSqmFunctionTemplate(
|
||||
new PatternRenderer( pattern, useParenthesesWhenNoArgs ),
|
||||
argumentsValidator,
|
||||
returnTypeResolver,
|
||||
registrationKey
|
||||
returnTypeResolver
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,215 +0,0 @@
|
|||
/*
|
||||
* 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.produce.function;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import static java.lang.String.CASE_INSENSITIVE_ORDER;
|
||||
|
||||
/**
|
||||
* Defines a registry for SQLFunction instances
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmFunctionRegistry {
|
||||
private static final Logger log = Logger.getLogger( SqmFunctionRegistry.class );
|
||||
|
||||
private final Map<String,SqmFunctionTemplate> functionMap = new TreeMap<>( CASE_INSENSITIVE_ORDER );
|
||||
private final Map<String,String> alternateKeyMap = new TreeMap<>( CASE_INSENSITIVE_ORDER );
|
||||
|
||||
public SqmFunctionRegistry() {
|
||||
log.tracef( "SqmFunctionRegistry created" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a SqmFunctionTemplate by name. Returns {@code null} if
|
||||
* no such function is found.
|
||||
*/
|
||||
public SqmFunctionTemplate findFunctionTemplate(String functionName) {
|
||||
SqmFunctionTemplate found = null;
|
||||
|
||||
final String alternateKeyResolution = alternateKeyMap.get( functionName );
|
||||
if ( alternateKeyResolution != null ) {
|
||||
found = functionMap.get( alternateKeyResolution );
|
||||
}
|
||||
|
||||
if ( found == null ) {
|
||||
found = functionMap.get( functionName );
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a function template by name
|
||||
*/
|
||||
public SqmFunctionTemplate register(String registrationKey, SqmFunctionTemplate function) {
|
||||
final SqmFunctionTemplate priorRegistration = functionMap.put( registrationKey, function );
|
||||
log.debugf(
|
||||
"Registered SqmFunctionTemplate [%s] under %s; prior registration was %s",
|
||||
function,
|
||||
registrationKey,
|
||||
priorRegistration
|
||||
);
|
||||
|
||||
return function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a pattern-based template by name. Shortcut for building the template
|
||||
* via {@link #patternTemplateBuilder} accepting its defaults.
|
||||
*/
|
||||
public SqmFunctionTemplate registerPattern(String name, String pattern) {
|
||||
return patternTemplateBuilder( name, pattern ).register();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a pattern-based template by name and invariant return type. Shortcut for building the template
|
||||
* via {@link #patternTemplateBuilder} accepting its defaults.
|
||||
*/
|
||||
public SqmFunctionTemplate registerPattern(String name, String pattern, AllowableFunctionReturnType returnType) {
|
||||
return patternTemplateBuilder( name, pattern )
|
||||
.setInvariantType( returnType )
|
||||
.register();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a builder for creating and registering a pattern-based function template.
|
||||
*
|
||||
* @param registrationKey The name under which the template will get registered
|
||||
* @param pattern The pattern defining the the underlying function call
|
||||
*
|
||||
* @return The builder
|
||||
*/
|
||||
public PatternFunctionTemplateBuilder patternTemplateBuilder(String registrationKey, String pattern) {
|
||||
return new PatternFunctionTemplateBuilder( this, registrationKey, pattern );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a named template by name. Shortcut for building a template via
|
||||
* {@link #namedTemplateBuilder} using the passed name as both the registration
|
||||
* key and underlying SQL function name and accepting the builder's defaults.
|
||||
*
|
||||
* @param name The function name (and registration key)
|
||||
*/
|
||||
public SqmFunctionTemplate registerNamed(String name) {
|
||||
return namedTemplateBuilder( name ).register();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a named template by name and invariant return type. Shortcut for building
|
||||
* a template via {@link #namedTemplateBuilder} using the passed name as both the
|
||||
* registration key and underlying SQL function name and accepting the builder's defaults.
|
||||
*
|
||||
* @param name The function name (and registration key)
|
||||
*/
|
||||
public SqmFunctionTemplate registerNamed(String name, AllowableFunctionReturnType returnType) {
|
||||
return namedTemplateBuilder( name ).setInvariantType( returnType ).register();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a builder for creating and registering a name-based function template
|
||||
* using the passed name as both the registration key and underlying SQL
|
||||
* function name
|
||||
*
|
||||
* @param name The function name (and registration key)
|
||||
*
|
||||
* @return The builder
|
||||
*/
|
||||
public NamedFunctionTemplateBuilder namedTemplateBuilder(String name) {
|
||||
return namedTemplateBuilder( name, name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a builder for creating and registering a name-based function template.
|
||||
*
|
||||
* @param registrationKey The name under which the template will get registered
|
||||
* @param name The underlying SQL function name to use
|
||||
*
|
||||
* @return The builder
|
||||
*/
|
||||
public NamedFunctionTemplateBuilder namedTemplateBuilder(String registrationKey, String name) {
|
||||
return new NamedFunctionTemplateBuilder( this, registrationKey, name );
|
||||
}
|
||||
|
||||
public NamedFunctionTemplateBuilder noArgsBuilder(String name) {
|
||||
return noArgsBuilder( name, name );
|
||||
}
|
||||
|
||||
public NamedFunctionTemplateBuilder noArgsBuilder(String registrationKey, String name) {
|
||||
return namedTemplateBuilder( registrationKey, name )
|
||||
.setExactArgumentCount( 0 );
|
||||
}
|
||||
|
||||
public VarArgsFunctionTemplateBuilder varArgsBuilder(String registrationKey, String begin, String sep, String end) {
|
||||
return new VarArgsFunctionTemplateBuilder( this, registrationKey, begin, sep, end );
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialized registration method for registering a named template for functions
|
||||
* expecting zero arguments. Short-cut for building a named template via
|
||||
* {@link #namedTemplateBuilder} specifying zero arguments and accepting the
|
||||
* rest of the builder's defaults.
|
||||
*
|
||||
* @param name The function name (and registration key)
|
||||
*/
|
||||
public SqmFunctionTemplate registerNoArgs(String name) {
|
||||
return registerNoArgs( name, name );
|
||||
}
|
||||
|
||||
public SqmFunctionTemplate registerNoArgs(String registrationKey, String name) {
|
||||
return noArgsBuilder( registrationKey, name ).register();
|
||||
}
|
||||
|
||||
public SqmFunctionTemplate registerNoArgs(String name, AllowableFunctionReturnType returnType) {
|
||||
return registerNoArgs( name, name, returnType );
|
||||
}
|
||||
|
||||
public SqmFunctionTemplate registerNoArgs(String registrationKey, String name, AllowableFunctionReturnType returnType) {
|
||||
return noArgsBuilder( registrationKey, name )
|
||||
.setInvariantType( returnType )
|
||||
.register();
|
||||
}
|
||||
|
||||
public SqmFunctionTemplate registerVarArgs(String registrationKey, AllowableFunctionReturnType returnType, String begin, String sep, String end) {
|
||||
return varArgsBuilder( registrationKey, begin, sep, end )
|
||||
.setInvariantType( returnType )
|
||||
.register();
|
||||
}
|
||||
|
||||
public SqmFunctionTemplate wrapInJdbcEscape(String registrationKey, SqmFunctionTemplate wrapped) {
|
||||
final JdbcFunctionEscapeWrapperTemplate wrapperTemplate = new JdbcFunctionEscapeWrapperTemplate( wrapped );
|
||||
register( registrationKey, wrapperTemplate );
|
||||
return wrapperTemplate;
|
||||
}
|
||||
|
||||
public void registerAlternateKey(String alternateKey, String mappedKey) {
|
||||
log.debugf( "Registering alternate key : %s -> %s", alternateKey, mappedKey );
|
||||
alternateKeyMap.put( alternateKey, mappedKey );
|
||||
}
|
||||
|
||||
/**
|
||||
* Overlay the functions registered here on top of the
|
||||
* incoming registry, potentially overriding its registrations
|
||||
*/
|
||||
public void overlay(SqmFunctionRegistry registryToOverly) {
|
||||
// NOTE : done in this "direction" as it is easier to access the
|
||||
// functionMap directly in performing this operation
|
||||
functionMap.forEach( registryToOverly::register );
|
||||
alternateKeyMap.forEach( registryToOverly::registerAlternateKey );
|
||||
}
|
||||
|
||||
public void close() {
|
||||
functionMap.clear();
|
||||
alternateKeyMap.clear();
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
* 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.produce.function;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.sqm.produce.function.internal.SelfRenderingSqmFunction;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
/**
|
||||
* Extension for supplying support for non-standard (ANSI SQL) functions
|
||||
* in HQL and Criteria queries.
|
||||
* <p/>
|
||||
* Ultimately acts as a factory for SQM function expressions.
|
||||
*
|
||||
* @author David Channon
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmFunctionTemplate {
|
||||
/**
|
||||
* Generate an SqmExpression instance from this template.
|
||||
* <p/>
|
||||
* Note that this returns SqmExpression rather than the more
|
||||
* restrictive SqmFunctionExpression to allow implementors
|
||||
* to transform the source function expression into any
|
||||
* "expressable form".
|
||||
*/
|
||||
<T> SelfRenderingSqmFunction<T> makeSqmFunctionExpression(
|
||||
List<SqmTypedNode<?>> arguments,
|
||||
AllowableFunctionReturnType<T> impliedResultType,
|
||||
QueryEngine queryEngine);
|
||||
|
||||
default <T> SelfRenderingSqmFunction<T> makeSqmFunctionExpression(
|
||||
SqmTypedNode<?> argument,
|
||||
AllowableFunctionReturnType<T> impliedResultType,
|
||||
QueryEngine queryEngine) {
|
||||
return makeSqmFunctionExpression(
|
||||
singletonList(argument),
|
||||
impliedResultType,
|
||||
queryEngine
|
||||
);
|
||||
}
|
||||
|
||||
default <T> SelfRenderingSqmFunction<T> makeSqmFunctionExpression(
|
||||
AllowableFunctionReturnType<T> impliedResultType,
|
||||
QueryEngine queryEngine) {
|
||||
return makeSqmFunctionExpression(
|
||||
emptyList(),
|
||||
impliedResultType,
|
||||
queryEngine
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Will a call to the described function always include
|
||||
* parentheses?
|
||||
* <p>
|
||||
* SqmFunctionTemplate is generally used for rendering of a function.
|
||||
* However there are cases where Hibernate needs to consume a fragment
|
||||
* and decide if a token represents a function name. In cases where
|
||||
* the token is followed by an open-paren we can safely assume the
|
||||
* token is a function name. However, if the next token is not an
|
||||
* open-paren, the token can still represent a function provided that
|
||||
* the function has a "no paren" form in the case of no arguments. E.g.
|
||||
* Many databases do not require parentheses on functions like
|
||||
* `current_timestamp`, etc. This method helps account for those
|
||||
* cases.
|
||||
* <p>
|
||||
* Note that the most common case, by far, is that a function will always
|
||||
* include the parentheses - therefore this return is defined as true by
|
||||
* default.
|
||||
*/
|
||||
default boolean alwaysIncludesParentheses() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -100,16 +101,21 @@ public final class StandardArgumentsValidators {
|
|||
public static ArgumentsValidator of(Class<?> javaType) {
|
||||
return arguments -> arguments.forEach(
|
||||
arg -> {
|
||||
Class<?> argType = arg.getNodeType().getExpressableJavaTypeDescriptor().getJavaType();
|
||||
if ( !javaType.isAssignableFrom(argType) ) {
|
||||
throw new QueryException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Function expects arguments to be of type %s, but %s found",
|
||||
javaType.getName(),
|
||||
argType.getName()
|
||||
)
|
||||
);
|
||||
if ( arg instanceof SqmTypedNode ) {
|
||||
Class<?> argType = ( (SqmTypedNode) arg ).getNodeType().getExpressableJavaTypeDescriptor().getJavaType();
|
||||
if ( !javaType.isAssignableFrom(argType) ) {
|
||||
throw new QueryException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Function expects arguments to be of type %s, but %s found",
|
||||
javaType.getName(),
|
||||
argType.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new QueryException( "Found un-typed arguments with typed argument validator" );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
@ -7,15 +7,17 @@
|
|||
package org.hibernate.query.sqm.produce.function;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.query.sqm.produce.function.spi.FunctionAsExpressionTemplate;
|
||||
import org.hibernate.query.sqm.function.FunctionAsExpressionTemplate;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class VarArgsFunctionTemplateBuilder {
|
||||
private static final Logger log = Logger.getLogger( VarArgsFunctionTemplateBuilder.class );
|
||||
public class VarArgsFunctionDescriptorBuilder {
|
||||
private static final Logger log = Logger.getLogger( VarArgsFunctionDescriptorBuilder.class );
|
||||
|
||||
private final SqmFunctionRegistry registry;
|
||||
private final String registrationKey;
|
||||
|
@ -25,9 +27,8 @@ public class VarArgsFunctionTemplateBuilder {
|
|||
private final String end;
|
||||
|
||||
private ArgumentsValidator argumentsValidator;
|
||||
private FunctionReturnTypeResolver returnTypeResolver;
|
||||
|
||||
public VarArgsFunctionTemplateBuilder(SqmFunctionRegistry registry, String registrationKey, String begin, String sep, String end) {
|
||||
public VarArgsFunctionDescriptorBuilder(SqmFunctionRegistry registry, String registrationKey, String begin, String sep, String end) {
|
||||
this.registry = registry;
|
||||
this.registrationKey = registrationKey;
|
||||
this.begin = begin;
|
||||
|
@ -35,43 +36,41 @@ public class VarArgsFunctionTemplateBuilder {
|
|||
this.end = end;
|
||||
}
|
||||
|
||||
public VarArgsFunctionTemplateBuilder setArgumentsValidator(ArgumentsValidator argumentsValidator) {
|
||||
public VarArgsFunctionDescriptorBuilder setArgumentsValidator(ArgumentsValidator argumentsValidator) {
|
||||
this.argumentsValidator = argumentsValidator;
|
||||
return this;
|
||||
}
|
||||
|
||||
public VarArgsFunctionTemplateBuilder setArgumentCountBetween(int min, int max) {
|
||||
public VarArgsFunctionDescriptorBuilder setArgumentCountBetween(int min, int max) {
|
||||
return setArgumentsValidator( StandardArgumentsValidators.between( min, max ) );
|
||||
}
|
||||
|
||||
public VarArgsFunctionTemplateBuilder setMinArgumentCount(int min) {
|
||||
public VarArgsFunctionDescriptorBuilder setMinArgumentCount(int min) {
|
||||
return setArgumentsValidator( StandardArgumentsValidators.min( min ) );
|
||||
}
|
||||
|
||||
public VarArgsFunctionTemplateBuilder setExactArgumentCount(int exactArgumentCount) {
|
||||
public VarArgsFunctionDescriptorBuilder setExactArgumentCount(int exactArgumentCount) {
|
||||
return setArgumentsValidator( StandardArgumentsValidators.exactly( exactArgumentCount ) );
|
||||
}
|
||||
|
||||
public VarArgsFunctionTemplateBuilder setReturnTypeResolver(FunctionReturnTypeResolver returnTypeResolver) {
|
||||
this.returnTypeResolver = returnTypeResolver;
|
||||
public VarArgsFunctionDescriptorBuilder setReturnTypeResolver(FunctionReturnTypeResolver returnTypeResolver) {
|
||||
// this.returnTypeResolver = returnTypeResolver;
|
||||
return this;
|
||||
}
|
||||
|
||||
public VarArgsFunctionTemplateBuilder setInvariantType(AllowableFunctionReturnType invariantType) {
|
||||
public VarArgsFunctionDescriptorBuilder setInvariantType(AllowableFunctionReturnType invariantType) {
|
||||
setReturnTypeResolver( StandardFunctionReturnTypeResolvers.invariant( invariantType ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
public SqmFunctionTemplate register() {
|
||||
public SqmFunctionDescriptor register() {
|
||||
return registry.register(
|
||||
registrationKey,
|
||||
new FunctionAsExpressionTemplate(
|
||||
begin,
|
||||
sep,
|
||||
end,
|
||||
returnTypeResolver,
|
||||
argumentsValidator,
|
||||
registrationKey
|
||||
argumentsValidator
|
||||
)
|
||||
);
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* 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.produce.function.internal;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.function.SqmFunction;
|
||||
import org.hibernate.query.sqm.produce.function.spi.SelfRenderingFunctionSupport;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.expression.AbstractSqmExpression;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SelfRenderingSqmFunction<T>
|
||||
extends AbstractSqmExpression<T>
|
||||
implements SqmFunction<T> {
|
||||
private final String name;
|
||||
private final SelfRenderingFunctionSupport renderingSupport;
|
||||
private final List<SqmTypedNode<?>> arguments;
|
||||
|
||||
public SelfRenderingSqmFunction(
|
||||
SelfRenderingFunctionSupport renderingSupport,
|
||||
List<SqmTypedNode<?>> arguments,
|
||||
AllowableFunctionReturnType<T> impliedResultType,
|
||||
NodeBuilder nodeBuilder,
|
||||
String name) {
|
||||
super( impliedResultType, nodeBuilder );
|
||||
this.renderingSupport = renderingSupport;
|
||||
this.arguments = arguments;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<SqmTypedNode<?>> getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AllowableFunctionReturnType<T> getNodeType() {
|
||||
return (AllowableFunctionReturnType<T>) super.getNodeType();
|
||||
}
|
||||
|
||||
public SelfRenderingFunctionSupport getRenderingSupport() {
|
||||
return renderingSupport;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFunctionName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Package defining support for {@link org.hibernate.query.sqm.produce.function.SqmFunctionTemplate} handling.
|
||||
* Package defining support for {@link org.hibernate.query.sqm.function.SqmFunctionDescriptor} handling.
|
||||
* <p/>
|
||||
* Between {@link org.hibernate.query.sqm.produce.function.ArgumentsValidator} and
|
||||
* {@link org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver} creating
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* 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.produce.function.spi;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
|
||||
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
|
||||
import org.hibernate.query.sqm.produce.function.internal.SelfRenderingSqmFunction;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractSelfRenderingFunctionTemplate extends AbstractSqmFunctionTemplate {
|
||||
private final String name;
|
||||
|
||||
public AbstractSelfRenderingFunctionTemplate(
|
||||
String name,
|
||||
FunctionReturnTypeResolver returnTypeResolver,
|
||||
ArgumentsValidator argumentsValidator) {
|
||||
super( argumentsValidator, returnTypeResolver );
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> SelfRenderingSqmFunction<T> generateSqmFunctionExpression(
|
||||
List<SqmTypedNode<?>> arguments,
|
||||
AllowableFunctionReturnType<T> resolvedReturnType,
|
||||
QueryEngine queryEngine) {
|
||||
//noinspection unchecked
|
||||
return new SelfRenderingSqmFunction(
|
||||
getRenderingFunctionSupport( arguments, resolvedReturnType, queryEngine ),
|
||||
arguments,
|
||||
resolvedReturnType,
|
||||
queryEngine.getCriteriaBuilder(),
|
||||
name
|
||||
);
|
||||
}
|
||||
|
||||
protected abstract SelfRenderingFunctionSupport getRenderingFunctionSupport(
|
||||
List<SqmTypedNode<?>> arguments,
|
||||
AllowableFunctionReturnType<?> resolvedReturnType,
|
||||
QueryEngine queryEngine);
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* 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.produce.function.spi;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
|
||||
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
|
||||
import org.hibernate.query.sqm.produce.function.SqmFunctionTemplate;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.internal.SelfRenderingSqmFunction;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractSqmFunctionTemplate implements SqmFunctionTemplate {
|
||||
private final ArgumentsValidator argumentsValidator;
|
||||
private final FunctionReturnTypeResolver returnTypeResolver;
|
||||
|
||||
public AbstractSqmFunctionTemplate() {
|
||||
this( null, null );
|
||||
}
|
||||
|
||||
public AbstractSqmFunctionTemplate(ArgumentsValidator argumentsValidator) {
|
||||
this( argumentsValidator, null );
|
||||
}
|
||||
|
||||
public AbstractSqmFunctionTemplate(
|
||||
ArgumentsValidator argumentsValidator,
|
||||
FunctionReturnTypeResolver returnTypeResolver) {
|
||||
this.argumentsValidator = argumentsValidator == null
|
||||
? StandardArgumentsValidators.NONE
|
||||
: argumentsValidator;
|
||||
this.returnTypeResolver = returnTypeResolver == null
|
||||
? StandardFunctionReturnTypeResolvers.useFirstNonNull()
|
||||
: returnTypeResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public final <T> SelfRenderingSqmFunction<T> makeSqmFunctionExpression(
|
||||
List<SqmTypedNode<?>> arguments,
|
||||
AllowableFunctionReturnType<T> impliedResultType,
|
||||
QueryEngine queryEngine) {
|
||||
argumentsValidator.validate( arguments );
|
||||
|
||||
return generateSqmFunctionExpression(
|
||||
arguments,
|
||||
(AllowableFunctionReturnType<T>) //this cast is not truly correct
|
||||
returnTypeResolver.resolveFunctionReturnType( impliedResultType, arguments ),
|
||||
queryEngine
|
||||
);
|
||||
}
|
||||
|
||||
protected abstract <T> SelfRenderingSqmFunction<T> generateSqmFunctionExpression(
|
||||
List<SqmTypedNode<?>> arguments,
|
||||
AllowableFunctionReturnType<T> impliedResultType,
|
||||
QueryEngine queryEngine);
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
/*
|
||||
* 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.produce.function.spi;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
|
||||
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Provides a standard implementation that supports the majority of the HQL
|
||||
* functions that are translated to SQL. The Dialect and its sub-classes use
|
||||
* this class to provide details required for processing of the associated
|
||||
* function.
|
||||
*
|
||||
* @author David Channon
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NamedSqmFunctionTemplate
|
||||
extends AbstractSelfRenderingFunctionTemplate
|
||||
implements SelfRenderingFunctionSupport {
|
||||
private final String functionName;
|
||||
private final boolean useParenthesesWhenNoArgs;
|
||||
|
||||
public NamedSqmFunctionTemplate(
|
||||
String functionName,
|
||||
boolean useParenthesesWhenNoArgs,
|
||||
ArgumentsValidator argumentsValidator,
|
||||
FunctionReturnTypeResolver returnTypeResolver) {
|
||||
this( functionName, useParenthesesWhenNoArgs, argumentsValidator, returnTypeResolver, functionName );
|
||||
}
|
||||
|
||||
public NamedSqmFunctionTemplate(
|
||||
String functionName,
|
||||
boolean useParenthesesWhenNoArgs,
|
||||
ArgumentsValidator argumentsValidator,
|
||||
FunctionReturnTypeResolver returnTypeResolver,
|
||||
String name) {
|
||||
super( name, returnTypeResolver, argumentsValidator );
|
||||
|
||||
this.functionName = functionName;
|
||||
this.useParenthesesWhenNoArgs = useParenthesesWhenNoArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function name accessor
|
||||
*
|
||||
* @return The function name.
|
||||
*/
|
||||
public String getName() {
|
||||
return functionName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SelfRenderingFunctionSupport getRenderingFunctionSupport(
|
||||
List<SqmTypedNode<?>> arguments,
|
||||
AllowableFunctionReturnType<?> impliedResultType,
|
||||
QueryEngine queryEngine) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(
|
||||
SqlAppender sqlAppender,
|
||||
List<SqlAstNode> sqlAstArguments,
|
||||
SqlAstWalker walker,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final boolean useParens = useParenthesesWhenNoArgs || !sqlAstArguments.isEmpty();
|
||||
|
||||
sqlAppender.appendSql( functionName );
|
||||
if ( useParens ) {
|
||||
sqlAppender.appendSql( "(" );
|
||||
}
|
||||
|
||||
boolean firstPass = true;
|
||||
for ( SqlAstNode sqlAstArgument : sqlAstArguments ) {
|
||||
if ( !firstPass ) {
|
||||
sqlAppender.appendSql( ", " );
|
||||
}
|
||||
renderArgument( sqlAppender, sqlAstArgument, walker, sessionFactory );
|
||||
firstPass = false;
|
||||
}
|
||||
|
||||
if ( useParens ) {
|
||||
sqlAppender.appendSql( ")" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from {@link #render} to render an argument.
|
||||
*
|
||||
* @param sqlAppender The sql appender to append the rendered argument.
|
||||
* @param sqlAstArgument The argument being processed.
|
||||
* @param walker The walker to use for rendering {@link SqlAstNode} expressions
|
||||
* @param sessionFactory The session factory
|
||||
*/
|
||||
protected void renderArgument(
|
||||
SqlAppender sqlAppender,
|
||||
SqlAstNode sqlAstArgument,
|
||||
SqlAstWalker walker,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
sqlAstArgument.accept( walker );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
Locale.ROOT,
|
||||
"NamedSqmFunctionTemplate(%s)",
|
||||
functionName
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* 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.produce.function.spi;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.sqm.produce.function.SqmFunctionTemplate;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.internal.SelfRenderingSqmFunction;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class PairedFunctionTemplate extends AbstractSqmFunctionTemplate {
|
||||
|
||||
private SqmFunctionTemplate binaryFunction;
|
||||
private SqmFunctionTemplate ternaryFunction;
|
||||
|
||||
public PairedFunctionTemplate(
|
||||
SqmFunctionTemplate binaryFunction,
|
||||
SqmFunctionTemplate ternaryFunction) {
|
||||
super( StandardArgumentsValidators.between( 2, 3 ) );
|
||||
this.binaryFunction = binaryFunction;
|
||||
this.ternaryFunction = ternaryFunction;
|
||||
}
|
||||
|
||||
public static void register(
|
||||
QueryEngine queryEngine,
|
||||
String name,
|
||||
AllowableFunctionReturnType type,
|
||||
String pattern2,
|
||||
String pattern3) {
|
||||
queryEngine.getSqmFunctionRegistry().register(
|
||||
name,
|
||||
new PairedFunctionTemplate(
|
||||
queryEngine.getSqmFunctionRegistry()
|
||||
.patternTemplateBuilder( name, pattern2 )
|
||||
.setExactArgumentCount( 2 )
|
||||
.setInvariantType( type)
|
||||
.template(),
|
||||
queryEngine.getSqmFunctionRegistry()
|
||||
.patternTemplateBuilder( name, pattern3 )
|
||||
.setExactArgumentCount( 3 )
|
||||
.setInvariantType( type )
|
||||
.template()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected <T> SelfRenderingSqmFunction<T> generateSqmFunctionExpression(
|
||||
List<SqmTypedNode<?>> arguments,
|
||||
AllowableFunctionReturnType<T> impliedResultType,
|
||||
QueryEngine queryEngine) {
|
||||
return ( arguments.size()<3 ? binaryFunction : ternaryFunction )
|
||||
.makeSqmFunctionExpression( arguments, impliedResultType, queryEngine );
|
||||
}
|
||||
}
|
|
@ -8,12 +8,6 @@ package org.hibernate.query.sqm.spi;
|
|||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.function.SqmCastTarget;
|
||||
import org.hibernate.query.sqm.function.SqmDistinct;
|
||||
import org.hibernate.query.sqm.function.SqmExtractUnit;
|
||||
import org.hibernate.query.sqm.function.SqmFunction;
|
||||
import org.hibernate.query.sqm.function.SqmStar;
|
||||
import org.hibernate.query.sqm.function.SqmTrimSpecification;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteConsumer;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
|
||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||
|
@ -34,19 +28,26 @@ import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
|
|||
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.SqmCastTarget;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmCoalesce;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmCollectionSize;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmPathEntityType;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter;
|
||||
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.tree.expression.SqmDistinct;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmStar;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmTrimSpecification;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmCrossJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
|
||||
|
@ -81,7 +82,6 @@ import org.hibernate.query.sqm.tree.update.SqmAssignment;
|
|||
import org.hibernate.query.sqm.tree.update.SqmSetClause;
|
||||
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
|
||||
/**
|
||||
* Base support for an SQM walker
|
||||
|
@ -494,6 +494,11 @@ public class BaseSemanticQueryWalker implements SemanticQueryWalker<Object> {
|
|||
return castTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitCoalesce(SqmCoalesce sqmCoalesce) {
|
||||
return sqmCoalesce;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitTrimSpecification(SqmTrimSpecification trimSpecification) {
|
||||
return trimSpecification;
|
||||
|
|
|
@ -37,7 +37,7 @@ import org.hibernate.query.spi.QueryParameterImplementor;
|
|||
import org.hibernate.query.sqm.InterpretationException;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.function.SqmFunction;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||
import org.hibernate.query.sqm.internal.SqmMappingModelHelper;
|
||||
import org.hibernate.query.sqm.spi.BaseSemanticQueryWalker;
|
||||
|
@ -66,6 +66,7 @@ import org.hibernate.query.sqm.tree.expression.SqmCaseSimple;
|
|||
import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
|
||||
|
@ -924,43 +925,28 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// non-standard functions
|
||||
|
||||
|
||||
@Override
|
||||
public Object visitFunction(SqmFunction sqmFunction) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
// shallownessStack.push( Shallowness.FUNCTION );
|
||||
// try {
|
||||
// return new NonStandardFunction(
|
||||
// sqmFunction.getFunctionName(),
|
||||
// determineValueMapping( sqmFunction ),
|
||||
// visitArguments( sqmFunction.getArguments() )
|
||||
// );
|
||||
// }
|
||||
// finally {
|
||||
// shallownessStack.pop();
|
||||
// }
|
||||
public Expression visitFunction(SqmFunction sqmFunction) {
|
||||
final SqmFunctionDescriptor functionDescriptor = creationContext.getSessionFactory()
|
||||
.getQueryEngine()
|
||||
.getSqmFunctionRegistry()
|
||||
.findFunctionDescriptor( sqmFunction.getFunctionName() );
|
||||
|
||||
shallownessStack.push( Shallowness.FUNCTION );
|
||||
try {
|
||||
return functionDescriptor.generateSqlExpression(
|
||||
sqmFunction.getFunctionName(),
|
||||
sqmFunction.getArguments(),
|
||||
inferableTypeAccessStack.getCurrent(),
|
||||
this,
|
||||
this
|
||||
);
|
||||
}
|
||||
finally {
|
||||
shallownessStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
// private List<Expression> visitArguments(List<SqmExpression> sqmArguments) {
|
||||
// if ( sqmArguments == null || sqmArguments.isEmpty() ) {
|
||||
// return Collections.emptyList();
|
||||
// }
|
||||
//
|
||||
// final ArrayList<Expression> sqlAstArguments = new ArrayList<>();
|
||||
// for ( SqmExpression sqmArgument : sqmArguments ) {
|
||||
// sqlAstArguments.add( (Expression) sqmArgument.accept( this ) );
|
||||
// }
|
||||
//
|
||||
// return sqlAstArguments;
|
||||
// }
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// standard functions
|
||||
|
||||
|
||||
// @Override
|
||||
// public Object visitAbsFunction(SqmAbsFunction function) {
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
* 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.function;
|
||||
package org.hibernate.query.sqm.tree.expression;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.tree.AbstractSqmNode;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||
|
@ -25,17 +25,13 @@ public class SqmCastTarget<T> extends AbstractSqmNode implements SqmTypedNode<T>
|
|||
this.type = type;
|
||||
}
|
||||
|
||||
public AllowableFunctionReturnType<T> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(SemanticQueryWalker<T> walker) {
|
||||
return walker.visitCastTarget(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpressable<T> getNodeType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||
return walker.visitCastTarget( this );
|
||||
}
|
||||
}
|
|
@ -4,11 +4,10 @@
|
|||
* 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.function;
|
||||
package org.hibernate.query.sqm.tree.expression;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.criteria.Expression;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
|
@ -16,38 +15,39 @@ import org.hibernate.query.criteria.JpaCoalesce;
|
|||
import org.hibernate.query.criteria.JpaExpression;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.produce.function.SqmFunctionTemplate;
|
||||
import org.hibernate.query.sqm.tree.expression.AbstractSqmExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
|
||||
|
||||
/**
|
||||
* Specialized CASE statement for resolving the first non-null value in a list of values
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class SqmCoalesce<T> extends AbstractSqmExpression<T> implements JpaCoalesce<T>, DomainResultProducer<T> {
|
||||
|
||||
private List<SqmExpression<? extends T>> arguments = new ArrayList<>();
|
||||
private SqmFunctionTemplate coalesceFunction;
|
||||
public class SqmCoalesce<T> extends AbstractSqmExpression<T> implements JpaCoalesce<T> {
|
||||
private final SqmFunctionDescriptor functionDescriptor;
|
||||
private final List<SqmExpression<? extends T>> arguments;
|
||||
|
||||
public SqmCoalesce(NodeBuilder nodeBuilder) {
|
||||
this( null, nodeBuilder );
|
||||
}
|
||||
|
||||
public SqmCoalesce(AllowableFunctionReturnType<T> type, NodeBuilder nodeBuilder) {
|
||||
public SqmCoalesce(SqmExpressable<T> type, NodeBuilder nodeBuilder) {
|
||||
super( type, nodeBuilder );
|
||||
coalesceFunction = nodeBuilder.getQueryEngine().getSqmFunctionRegistry().findFunctionTemplate("coalesce");
|
||||
functionDescriptor = nodeBuilder.getQueryEngine().getSqmFunctionRegistry().findFunctionDescriptor( "coalesce" );
|
||||
this.arguments = new ArrayList<>();
|
||||
}
|
||||
|
||||
public SqmCoalesce(SqmExpressable<T> type, int numberOfArguments, NodeBuilder nodeBuilder) {
|
||||
super( type, nodeBuilder );
|
||||
functionDescriptor = nodeBuilder.getQueryEngine().getSqmFunctionRegistry().findFunctionDescriptor( "coalesce" );
|
||||
this.arguments = new ArrayList<>( numberOfArguments );
|
||||
}
|
||||
|
||||
public SqmFunctionDescriptor getFunctionDescriptor() {
|
||||
return functionDescriptor;
|
||||
}
|
||||
|
||||
public void value(SqmExpression<? extends T> expression) {
|
||||
arguments.add( expression );
|
||||
|
||||
//TODO: improve this
|
||||
// if ( getNodeType() == null ) {
|
||||
setExpressableType( expression.getNodeType() );
|
||||
// }
|
||||
}
|
||||
|
||||
public List<SqmExpression<? extends T>> getArguments() {
|
||||
|
@ -56,13 +56,7 @@ public class SqmCoalesce<T> extends AbstractSqmExpression<T> implements JpaCoale
|
|||
|
||||
@Override
|
||||
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||
return walker.visitFunction(
|
||||
coalesceFunction.makeSqmFunctionExpression(
|
||||
new ArrayList<>(arguments),
|
||||
(AllowableFunctionReturnType<?>) getNodeType(),
|
||||
nodeBuilder().getQueryEngine()
|
||||
)
|
||||
);
|
||||
return walker.visitCoalesce( this );
|
||||
}
|
||||
|
||||
@Override
|
|
@ -4,7 +4,7 @@
|
|||
* 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.function;
|
||||
package org.hibernate.query.sqm.tree.expression;
|
||||
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
|
@ -13,7 +13,6 @@ import java.util.function.Consumer;
|
|||
import javax.persistence.criteria.Expression;
|
||||
|
||||
import org.hibernate.annotations.Remove;
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.metamodel.model.domain.DomainType;
|
||||
import org.hibernate.query.criteria.JpaExpression;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
|
@ -100,11 +99,14 @@ public interface SqmExpression<T> extends SqmSelectableNode<T>, JpaExpression<T>
|
|||
SqmPredicate in(Expression<Collection<?>> values);
|
||||
|
||||
default <X> SqmExpression<X> castAs(DomainType<X> type) {
|
||||
return nodeBuilder().getQueryEngine()
|
||||
.getSqmFunctionRegistry()
|
||||
.findFunctionTemplate( "cast" )
|
||||
.makeSqmFunctionExpression( this, ( AllowableFunctionReturnType<X>) type, nodeBuilder().getQueryEngine() );
|
||||
return new SqmFunction<>(
|
||||
"cast",
|
||||
nodeBuilder().getQueryEngine()
|
||||
.getSqmFunctionRegistry()
|
||||
.findFunctionDescriptor( "cast" ),
|
||||
type,
|
||||
nodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* 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.function;
|
||||
package org.hibernate.query.sqm.tree.expression;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* 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.tree.expression;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.query.criteria.JpaFunction;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
import org.hibernate.query.sqm.tree.SqmNode;
|
||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||
|
||||
/**
|
||||
* An SQM function
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmFunction<T> extends AbstractSqmExpression<T> implements JpaFunction<T>, DomainResultProducer<T> {
|
||||
// this function-name is the one used to resolve the descriptor from the function registry (which may or may not be a db function name)
|
||||
private final String functionName;
|
||||
private final SqmFunctionDescriptor functionDescriptor;
|
||||
|
||||
private List<SqmVisitableNode> arguments;
|
||||
|
||||
public SqmFunction(
|
||||
String functionName,
|
||||
SqmFunctionDescriptor functionDescriptor,
|
||||
SqmExpressable<T> type,
|
||||
NodeBuilder criteriaBuilder) {
|
||||
super( type, criteriaBuilder );
|
||||
this.functionName = functionName;
|
||||
this.functionDescriptor = functionDescriptor;
|
||||
}
|
||||
|
||||
public SqmFunction(
|
||||
String functionName,
|
||||
SqmFunctionDescriptor functionDescriptor,
|
||||
SqmExpressable<T> type,
|
||||
List<SqmVisitableNode> arguments,
|
||||
NodeBuilder criteriaBuilder) {
|
||||
super( type, criteriaBuilder );
|
||||
this.functionName = functionName;
|
||||
this.functionDescriptor = functionDescriptor;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFunctionName() {
|
||||
return functionName;
|
||||
}
|
||||
|
||||
public List<SqmVisitableNode> getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
public void addArgument(SqmVisitableNode argument) {
|
||||
assert argument != null;
|
||||
|
||||
if ( arguments == null ) {
|
||||
arguments = new ArrayList<>();
|
||||
}
|
||||
arguments.add( argument );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||
return walker.visitFunction( this );
|
||||
}
|
||||
}
|
|
@ -4,11 +4,10 @@
|
|||
* 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.function;
|
||||
package org.hibernate.query.sqm.tree.expression;
|
||||
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.expression.AbstractSqmExpression;
|
||||
|
||||
/**
|
||||
* @author Gavin King
|
|
@ -4,7 +4,7 @@
|
|||
* 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.function;
|
||||
package org.hibernate.query.sqm.tree.expression;
|
||||
|
||||
import org.hibernate.query.TrimSpec;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
|
@ -8,16 +8,15 @@ package org.hibernate.orm.test.query.hql;
|
|||
|
||||
import org.hibernate.orm.test.query.sqm.BaseSqmUnitTest;
|
||||
import org.hibernate.orm.test.query.sqm.domain.Person;
|
||||
import org.hibernate.query.sqm.function.SqmCoalesce;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmCaseSearched;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmCaseSimple;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
|
||||
|
||||
import org.hibernate.testing.orm.junit.FailureExpected;
|
||||
import org.hibernate.testing.orm.junit.TestingUtil;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -87,7 +86,6 @@ public class CaseExpressionsTest extends BaseSqmUnitTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected( reason = "Support for functions not yet defined" )
|
||||
public void testBasicCoalesceExpression() {
|
||||
SqmSelectStatement select = interpretSelect(
|
||||
"select coalesce(p.nickName, p.mate.nickName) from Person p"
|
||||
|
@ -95,9 +93,9 @@ public class CaseExpressionsTest extends BaseSqmUnitTest {
|
|||
|
||||
assertThat( select.getQuerySpec().getSelectClause().getSelections(), hasSize( 1 ) );
|
||||
|
||||
final SqmCoalesce<?> coalesce = TestingUtil.cast(
|
||||
final SqmFunction<?> coalesce = TestingUtil.cast(
|
||||
select.getQuerySpec().getSelectClause().getSelections().get( 0 ).getSelectableNode(),
|
||||
SqmCoalesce.class
|
||||
SqmFunction.class
|
||||
);
|
||||
|
||||
assertThat( coalesce.getArguments(), hasSize( 2 ) );
|
||||
|
@ -105,7 +103,6 @@ public class CaseExpressionsTest extends BaseSqmUnitTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected( reason = "Support for functions not yet defined" )
|
||||
public void testBasicNullifExpression() {
|
||||
SqmSelectStatement select = interpretSelect(
|
||||
"select nullif(p.nickName, p.mate.nickName) from Person p"
|
||||
|
|
Loading…
Reference in New Issue