improve doc for SqmFunctionDescriptor

This commit is contained in:
Gavin 2022-12-31 09:58:51 +01:00
parent 46dec087fc
commit 1d7ecf61c5
2 changed files with 62 additions and 32 deletions

View File

@ -19,7 +19,6 @@ import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator; import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.FunctionArgumentTypeResolver; import org.hibernate.query.sqm.produce.function.FunctionArgumentTypeResolver;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver; import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter; import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.tree.SqmCopyContext; import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;

View File

@ -21,12 +21,22 @@ import static java.util.Collections.singletonList;
/** /**
* A factory for SQM nodes representing invocations of a certain * A factory for SQM nodes representing invocations of a certain
* named function. When a function names and arguments are * named function.
* encountered in the HQL, a {@code SqmFunctionDescriptor} for * <p>
* the given name is obtained from a {@link SqmFunctionRegistry}, * When a function call is encountered in the text of an HQL query,
* and the {@link #generateSqmExpression} method is called with * a {@code SqmFunctionDescriptor} for the given name is obtained
* the given argument SQM nodes to produce a subtree of SQM nodes * from the {@link SqmFunctionRegistry}, and the
* representing the function invocation. * {@link #generateSqmExpression} method is called with SQM nodes
* representing the invocation arguments. It is the responsibility
* of the {@code SqmFunctionDescriptor} to produce a subtree of SQM
* nodes representing the function invocation.
* <p>
* The resulting subtree might be quite complex, since the
* {@code SqmFunctionDescriptor} is permitted to perform syntactic
* de-sugaring. On the other hand, {@link #generateSqmExpression}
* returns {@link SelfRenderingSqmFunction}, which is an object
* that is permitted to take over the logic of producing the
* SQL AST subtree, so de-sugaring may also be performed there.
* *
* @author David Channon * @author David Channon
* @author Steve Ebersole * @author Steve Ebersole
@ -49,8 +59,10 @@ public interface SqmFunctionDescriptor {
TypeConfiguration typeConfiguration); TypeConfiguration typeConfiguration);
/** /**
* Like {@link #generateSqmExpression(List, ReturnableType, QueryEngine, TypeConfiguration)} * Like {@link #generateSqmExpression(List, ReturnableType, QueryEngine, TypeConfiguration)},
* but also accepts a filter predicate. This method is intended for aggregate functions. * but also accepts a {@code filter} predicate.
* <p>
* This method is intended for aggregate functions.
*/ */
default <T> SelfRenderingSqmFunction<T> generateAggregateSqmExpression( default <T> SelfRenderingSqmFunction<T> generateAggregateSqmExpression(
List<? extends SqmTypedNode<?>> arguments, List<? extends SqmTypedNode<?>> arguments,
@ -62,8 +74,10 @@ public interface SqmFunctionDescriptor {
} }
/** /**
* Like {@link #generateSqmExpression(List, ReturnableType, QueryEngine, TypeConfiguration)} * Like {@link #generateSqmExpression(List, ReturnableType, QueryEngine, TypeConfiguration)},
* but also accepts a filter predicate. This method is intended for ordered set-aggregate functions. * but also accepts a {@code filter} predicate and an {@code order by} clause.
* <p>
* This method is intended for ordered set aggregate functions.
*/ */
default <T> SelfRenderingSqmFunction<T> generateOrderedSetAggregateSqmExpression( default <T> SelfRenderingSqmFunction<T> generateOrderedSetAggregateSqmExpression(
List<? extends SqmTypedNode<?>> arguments, List<? extends SqmTypedNode<?>> arguments,
@ -72,12 +86,14 @@ public interface SqmFunctionDescriptor {
ReturnableType<T> impliedResultType, ReturnableType<T> impliedResultType,
QueryEngine queryEngine, QueryEngine queryEngine,
TypeConfiguration typeConfiguration) { TypeConfiguration typeConfiguration) {
throw new UnsupportedOperationException( "Not an ordered set-aggregate function" ); throw new UnsupportedOperationException( "Not an ordered set aggregate function" );
} }
/** /**
* Like {@link #generateSqmExpression(List, ReturnableType, QueryEngine, TypeConfiguration)} * Like {@link #generateSqmExpression(List, ReturnableType, QueryEngine, TypeConfiguration)}
* but also accepts a filter predicate. This method is intended for aggregate functions. * but also accepts a {@code filter} predicate.
* <p>
* This method is intended for window functions.
*/ */
default <T> SelfRenderingSqmFunction<T> generateWindowSqmExpression( default <T> SelfRenderingSqmFunction<T> generateWindowSqmExpression(
List<? extends SqmTypedNode<?>> arguments, List<? extends SqmTypedNode<?>> arguments,
@ -87,11 +103,11 @@ public interface SqmFunctionDescriptor {
ReturnableType<T> impliedResultType, ReturnableType<T> impliedResultType,
QueryEngine queryEngine, QueryEngine queryEngine,
TypeConfiguration typeConfiguration) { TypeConfiguration typeConfiguration) {
throw new UnsupportedOperationException( "Not an aggregate function" ); throw new UnsupportedOperationException( "Not a window function" );
} }
/** /**
* Convenience for single argument * Convenience for a single argument.
*/ */
default <T> SelfRenderingSqmFunction<T> generateSqmExpression( default <T> SelfRenderingSqmFunction<T> generateSqmExpression(
SqmTypedNode<?> argument, SqmTypedNode<?> argument,
@ -107,7 +123,7 @@ public interface SqmFunctionDescriptor {
} }
/** /**
* Convenience for no arguments * Convenience for no arguments.
*/ */
default <T> SelfRenderingSqmFunction<T> generateSqmExpression( default <T> SelfRenderingSqmFunction<T> generateSqmExpression(
ReturnableType<T> impliedResultType, ReturnableType<T> impliedResultType,
@ -122,37 +138,52 @@ public interface SqmFunctionDescriptor {
} }
/** /**
* Will a call to the described function always include * Will a call to the described function always include parentheses?
* parentheses?
* <p> * <p>
* SqmFunctionTemplate is generally used for rendering of a function. * Instances of this interface are usually used for rendering of functions.
* However there are cases where Hibernate needs to consume a fragment * However, there are cases where Hibernate needs to consume a fragment
* and decide if a token represents a function name. In cases where * and decide if a token represents a function name. In cases where the
* the token is followed by an open-paren we can safely assume the * token is followed by an opening parenthesis, we can safely assume the
* token is a function name. However, if the next token is not an * token is a function name. Bur if the next token is not an opening
* open-paren, the token can still represent a function provided that * parenthesis, the token might still represent a function if the function
* the function has a "no paren" form in the case of no arguments. E.g. * has a "no paren" form in the case of no arguments.
* Many databases do not require parentheses on functions like
* `current_timestamp`, etc. This method helps account for those
* cases.
* <p> * <p>
* Note that the most common case, by far, is that a function will always * For example, many databases do not require parentheses for functions
* include the parentheses - therefore this return is defined as true by * like {@code current_timestamp} and friends. This method helps account
* default. * for those cases.
*
* @apiNote The most common case, by far, is that a function call requires
* the parentheses. So this method returns true by default.
* *
* see Template#isFunction * @return {@code true} by default
*/ */
default boolean alwaysIncludesParentheses() { default boolean alwaysIncludesParentheses() {
return true; return true;
} }
/**
* Used only for pretty-printing the function signature in the log.
*
* @param name the function name
* @return the signature of the function
*/
default String getSignature(String name) { default String getSignature(String name) {
return name; return name;
} }
/**
* What sort of function is this?
*
* @return {@link FunctionKind#NORMAL} by default
*/
default FunctionKind getFunctionKind() { default FunctionKind getFunctionKind() {
return FunctionKind.NORMAL; return FunctionKind.NORMAL;
} }
/**
* The object responsible for validating arguments of the function.
*
* @return an instance of {@link ArgumentsValidator}
*/
ArgumentsValidator getArgumentsValidator(); ArgumentsValidator getArgumentsValidator();
} }