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.FunctionArgumentTypeResolver;
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.tree.SqmCopyContext;
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
* named function. When a function names and arguments are
* encountered in the HQL, a {@code SqmFunctionDescriptor} for
* the given name is obtained from a {@link SqmFunctionRegistry},
* and the {@link #generateSqmExpression} method is called with
* the given argument SQM nodes to produce a subtree of SQM nodes
* representing the function invocation.
* named function.
* <p>
* When a function call is encountered in the text of an HQL query,
* a {@code SqmFunctionDescriptor} for the given name is obtained
* from the {@link SqmFunctionRegistry}, and the
* {@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 Steve Ebersole
@ -49,8 +59,10 @@ public interface SqmFunctionDescriptor {
TypeConfiguration typeConfiguration);
/**
* Like {@link #generateSqmExpression(List, ReturnableType, QueryEngine, TypeConfiguration)}
* but also accepts a filter predicate. This method is intended for aggregate functions.
* Like {@link #generateSqmExpression(List, ReturnableType, QueryEngine, TypeConfiguration)},
* but also accepts a {@code filter} predicate.
* <p>
* This method is intended for aggregate functions.
*/
default <T> SelfRenderingSqmFunction<T> generateAggregateSqmExpression(
List<? extends SqmTypedNode<?>> arguments,
@ -62,8 +74,10 @@ public interface SqmFunctionDescriptor {
}
/**
* Like {@link #generateSqmExpression(List, ReturnableType, QueryEngine, TypeConfiguration)}
* but also accepts a filter predicate. This method is intended for ordered set-aggregate functions.
* Like {@link #generateSqmExpression(List, ReturnableType, QueryEngine, TypeConfiguration)},
* 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(
List<? extends SqmTypedNode<?>> arguments,
@ -72,12 +86,14 @@ public interface SqmFunctionDescriptor {
ReturnableType<T> impliedResultType,
QueryEngine queryEngine,
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)}
* 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(
List<? extends SqmTypedNode<?>> arguments,
@ -87,11 +103,11 @@ public interface SqmFunctionDescriptor {
ReturnableType<T> impliedResultType,
QueryEngine queryEngine,
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(
SqmTypedNode<?> argument,
@ -107,7 +123,7 @@ public interface SqmFunctionDescriptor {
}
/**
* Convenience for no arguments
* Convenience for no arguments.
*/
default <T> SelfRenderingSqmFunction<T> generateSqmExpression(
ReturnableType<T> impliedResultType,
@ -122,37 +138,52 @@ public interface SqmFunctionDescriptor {
}
/**
* Will a call to the described function always include
* parentheses?
* 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.
* Instances of this interface are usually used for rendering of functions.
* 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 opening parenthesis, we can safely assume the
* token is a function name. Bur if the next token is not an opening
* parenthesis, the token might still represent a function if the function
* has a "no paren" form in the case of no arguments.
* <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.
* For example, many databases do not require parentheses for functions
* like {@code current_timestamp} and friends. This method helps account
* for those cases.
*
* see Template#isFunction
* @apiNote The most common case, by far, is that a function call requires
* the parentheses. So this method returns true by default.
*
* @return {@code true} by default
*/
default boolean alwaysIncludesParentheses() {
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) {
return name;
}
/**
* What sort of function is this?
*
* @return {@link FunctionKind#NORMAL} by default
*/
default FunctionKind getFunctionKind() {
return FunctionKind.NORMAL;
}
/**
* The object responsible for validating arguments of the function.
*
* @return an instance of {@link ArgumentsValidator}
*/
ArgumentsValidator getArgumentsValidator();
}