diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SelfRenderingSqmFunction.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SelfRenderingSqmFunction.java index 006bad5e35..f266101da9 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SelfRenderingSqmFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SelfRenderingSqmFunction.java @@ -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; diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SqmFunctionDescriptor.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SqmFunctionDescriptor.java index 9c8023ffcd..75517bd1b7 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SqmFunctionDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SqmFunctionDescriptor.java @@ -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. + *

+ * 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. + *

+ * 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. + *

+ * This method is intended for aggregate functions. */ default SelfRenderingSqmFunction generateAggregateSqmExpression( List> 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. + *

+ * This method is intended for ordered set aggregate functions. */ default SelfRenderingSqmFunction generateOrderedSetAggregateSqmExpression( List> arguments, @@ -72,12 +86,14 @@ public interface SqmFunctionDescriptor { ReturnableType 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. + *

+ * This method is intended for window functions. */ default SelfRenderingSqmFunction generateWindowSqmExpression( List> arguments, @@ -87,11 +103,11 @@ public interface SqmFunctionDescriptor { ReturnableType 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 SelfRenderingSqmFunction generateSqmExpression( SqmTypedNode argument, @@ -107,7 +123,7 @@ public interface SqmFunctionDescriptor { } /** - * Convenience for no arguments + * Convenience for no arguments. */ default SelfRenderingSqmFunction generateSqmExpression( ReturnableType 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? *

- * 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. *

- * 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. + * + * @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() { 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(); }