From aef951f279980d6b413b5bf5d74cd645b4f1f6b8 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Thu, 6 Jan 2022 12:08:40 +0100 Subject: [PATCH] move some function arg typechecking up to the SQM phase this is where it needs to be for checking of named queries at startup and for any checks that happen in an IDE or at build time --- .../org/hibernate/userguide/hql/HQLTest.java | 1 - .../community/dialect/CacheDialect.java | 4 +- .../community/dialect/FirebirdDialect.java | 4 +- .../community/dialect/InformixDialect.java | 4 +- .../community/dialect/IngresDialect.java | 4 +- .../community/dialect/MaxDBDialect.java | 4 +- .../community/dialect/SQLiteDialect.java | 10 +- .../community/dialect/TimesTenDialect.java | 4 +- .../dialect/AbstractHANADialect.java | 4 +- .../hibernate/dialect/CockroachDialect.java | 2 +- .../org/hibernate/dialect/DB2Dialect.java | 15 +- .../dialect/HANAColumnStoreDialect.java | 2 +- .../org/hibernate/dialect/OracleDialect.java | 5 +- .../hibernate/dialect/PostgreSQLDialect.java | 5 +- .../hibernate/dialect/SQLServerDialect.java | 2 +- .../org/hibernate/dialect/SpannerDialect.java | 2 +- .../dialect/function/AvgFunction.java | 4 +- .../function/CaseLeastGreatestEmulation.java | 8 +- .../function/CaseWhenEveryAnyEmulation.java | 4 +- .../function/CastingConcatFunction.java | 4 +- .../function/CommonFunctionFactory.java | 171 ++++++++-------- .../dialect/function/DB2FormatEmulation.java | 7 +- .../dialect/function/DerbyLpadEmulation.java | 8 +- .../dialect/function/DerbyRpadEmulation.java | 7 +- .../dialect/function/EveryAnyEmulation.java | 2 +- .../dialect/function/ExtractFunction.java | 9 +- .../InsertSubstringOverlayEmulation.java | 8 +- .../function/LocatePositionEmulation.java | 8 +- .../function/LpadRpadPadEmulation.java | 10 +- .../QuantifiedLeastGreatestEmulation.java | 7 +- .../function/SQLServerEveryAnyEmulation.java | 2 +- .../function/SQLServerFormatEmulation.java | 9 +- .../function/TimestampaddFunction.java | 11 +- .../function/TimestampdiffFunction.java | 11 +- .../dialect/function/TrimFunction.java | 8 +- .../AbstractSqmFunctionDescriptor.java | 4 +- .../MultipatternSqmFunctionDescriptor.java | 4 +- .../SelfRenderingSqmAggregateFunction.java | 7 +- .../function/SelfRenderingSqmFunction.java | 6 +- .../sqm/function/SqmFunctionRegistry.java | 32 +-- .../function/ArgumentTypesValidator.java | 193 +++++++++++++----- .../produce/function/ArgumentsValidator.java | 54 +---- .../function/FunctionParameterType.java | 80 ++++++++ .../NamedFunctionDescriptorBuilder.java | 2 +- .../PatternFunctionDescriptorBuilder.java | 2 +- .../function/StandardArgumentsValidators.java | 19 +- .../orm/test/query/hql/FunctionTests.java | 2 +- 47 files changed, 480 insertions(+), 295 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/FunctionParameterType.java diff --git a/documentation/src/test/java/org/hibernate/userguide/hql/HQLTest.java b/documentation/src/test/java/org/hibernate/userguide/hql/HQLTest.java index ffe2ecb997..9cfb2ca30f 100644 --- a/documentation/src/test/java/org/hibernate/userguide/hql/HQLTest.java +++ b/documentation/src/test/java/org/hibernate/userguide/hql/HQLTest.java @@ -31,7 +31,6 @@ import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.OracleDialect; import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.SQLServerDialect; -import org.hibernate.dialect.SybaseDialect; import org.hibernate.dialect.TiDBDialect; import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase; import org.hibernate.query.QueryProducer; diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CacheDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CacheDialect.java index 01861a3927..9c0b3246bd 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CacheDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CacheDialect.java @@ -49,8 +49,8 @@ import java.sql.Types; import jakarta.persistence.TemporalType; import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.INTEGER; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.STRING; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; /** * Dialect for Intersystems Caché SQL 2007.1 and above. diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java index e3851e60a7..e3f73fa8e5 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java @@ -74,8 +74,8 @@ import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; import jakarta.persistence.TemporalType; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.INTEGER; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.STRING; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_END; import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_START_DATE; import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_START_TIME; diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java index 35c8446184..42d406ce46 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java @@ -60,8 +60,8 @@ import org.hibernate.type.StandardBasicTypes; import java.sql.Types; import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.INTEGER; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.STRING; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; /** * Dialect for Informix 7.31.UD3 with Informix diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java index f104441b4e..3606d7ab52 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java @@ -61,8 +61,8 @@ import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; import jakarta.persistence.TemporalType; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.INTEGER; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.STRING; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; /** * An SQL dialect for Ingres 9.2. diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java index cbd8de48f4..39abe5b666 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java @@ -38,8 +38,8 @@ import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; import static org.hibernate.dialect.SimpleDatabaseVersion.ZERO_VERSION; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.INTEGER; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.STRING; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; /** * A SQL dialect compatible with SAP MaxDB. diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteDialect.java index 322d4aed39..cea98c8205 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteDialect.java @@ -66,10 +66,10 @@ import static org.hibernate.query.TemporalUnit.EPOCH; import static org.hibernate.query.TemporalUnit.MONTH; import static org.hibernate.query.TemporalUnit.QUARTER; import static org.hibernate.query.TemporalUnit.YEAR; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.INTEGER; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.NUMERIC; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.STRING; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.TEMPORAL; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.NUMERIC; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL; import static org.hibernate.type.descriptor.DateTimeUtils.appendAsDate; import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTime; import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithMicros; @@ -297,7 +297,7 @@ public class SQLiteDialect extends Dialect { .setInvariantType( stringType ) .setExactArgumentCount( 2 ) .setParameterTypes(TEMPORAL, STRING) - .setArgumentListSignature("(datetime as pattern)") + .setArgumentListSignature("(TEMPORAL datetime as STRING pattern)") .register(); if (!supportsMathFunctions() ) { diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TimesTenDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TimesTenDialect.java index 493414bda3..5c23e4580f 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TimesTenDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TimesTenDialect.java @@ -46,8 +46,8 @@ import java.sql.Types; import jakarta.persistence.TemporalType; import static org.hibernate.dialect.SimpleDatabaseVersion.ZERO_VERSION; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.INTEGER; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.STRING; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; /** * A SQL dialect for TimesTen 5.1. diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java index b898d218ca..5ef435002a 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java @@ -77,7 +77,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import jakarta.persistence.TemporalType; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType; +import org.hibernate.query.sqm.produce.function.FunctionParameterType; /** * An abstract base class for SAP HANA dialects. @@ -279,7 +279,7 @@ public abstract class AbstractHANADialect extends Dialect { queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ), "locate(?2,?1)", "locate(?2,?1,?3)", - ParameterType.STRING, ParameterType.STRING, ParameterType.INTEGER + FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER ).setArgumentListSignature("(pattern, string[, start])"); CommonFunctionFactory.ceiling_ceil( queryEngine ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java index b4cd951cb8..b660ade85c 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java @@ -232,7 +232,7 @@ public class CockroachDialect extends Dialect { queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder("format", "experimental_strftime") .setInvariantType( stringType ) .setExactArgumentCount( 2 ) - .setArgumentListSignature("(datetime as pattern)") + .setArgumentListSignature("(TEMPORAL datetime as STRING pattern)") .register(); } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java index 62c1af4ba6..3e8a0c7c5f 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java @@ -34,8 +34,7 @@ import org.hibernate.query.sqm.mutation.internal.cte.CteInsertStrategy; import org.hibernate.query.sqm.mutation.internal.cte.CteMutationStrategy; import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy; import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; -import org.hibernate.query.sqm.produce.function.ArgumentsValidator; -import org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType; +import org.hibernate.query.sqm.produce.function.FunctionParameterType; import org.hibernate.service.ServiceRegistry; import org.hibernate.sql.ast.SqlAstNodeRenderingMode; import org.hibernate.sql.ast.SqlAstTranslator; @@ -197,16 +196,16 @@ public class DB2Dialect extends Dialect { queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) ) .setArgumentCountBetween( 2, 4 ) - .setParameterTypes(ParameterType.STRING, ParameterType.INTEGER, ParameterType.INTEGER, ParameterType.ANY) - .setArgumentListSignature( "(string, start[, length[, units]])" ) + .setParameterTypes(FunctionParameterType.STRING, FunctionParameterType.INTEGER, FunctionParameterType.INTEGER, FunctionParameterType.ANY) + .setArgumentListSignature( "(STRING string, INTEGER start[, INTEGER length[, units]])" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "substring" ) .setInvariantType( queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) ) .setArgumentCountBetween( 2, 4 ) - .setParameterTypes(ParameterType.STRING, ParameterType.INTEGER, ParameterType.INTEGER, ParameterType.ANY) - .setArgumentListSignature( "(string{ from|,} start[{ for|,} length[, units]])" ) + .setParameterTypes(FunctionParameterType.STRING, FunctionParameterType.INTEGER, FunctionParameterType.INTEGER, FunctionParameterType.ANY) + .setArgumentListSignature( "(STRING string{ INTEGER from|,} start[{ INTEGER for|,} length[, units]])" ) .register(); CommonFunctionFactory.translate( queryEngine ); CommonFunctionFactory.bitand( queryEngine ); @@ -249,8 +248,8 @@ public class DB2Dialect extends Dialect { queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ) ) .setExactArgumentCount( 2 ) - .setParameterTypes(ParameterType.STRING, ParameterType.STRING) - .setArgumentListSignature("(string, pattern)") + .setParameterTypes(FunctionParameterType.STRING, FunctionParameterType.STRING) + .setArgumentListSignature("(STRING string, STRING pattern)") .register(); } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java index a358c4ea33..eee59435e6 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java @@ -20,7 +20,7 @@ import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy; import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; import org.hibernate.type.StandardBasicTypes; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.ANY; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.ANY; /** * An SQL dialect for the SAP HANA column store. diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java index 5c600398b5..5b3160964c 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java @@ -87,7 +87,8 @@ import static org.hibernate.query.TemporalUnit.MINUTE; import static org.hibernate.query.TemporalUnit.MONTH; import static org.hibernate.query.TemporalUnit.SECOND; import static org.hibernate.query.TemporalUnit.YEAR; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType; + +import org.hibernate.query.sqm.produce.function.FunctionParameterType; import static org.hibernate.type.SqlTypes.*; /** @@ -182,7 +183,7 @@ public class OracleDialect extends Dialect { queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ), "instr(?2,?1)", "instr(?2,?1,?3)", - ParameterType.STRING, ParameterType.STRING, ParameterType.INTEGER + FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER ).setArgumentListSignature("(pattern, string[, start])"); } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java index 8dafafaab0..089f9b9594 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java @@ -84,7 +84,8 @@ import static org.hibernate.query.TemporalUnit.EPOCH; import static org.hibernate.query.TemporalUnit.MONTH; import static org.hibernate.query.TemporalUnit.QUARTER; import static org.hibernate.query.TemporalUnit.YEAR; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType; + +import org.hibernate.query.sqm.produce.function.FunctionParameterType; import static org.hibernate.type.SqlTypes.*; import static org.hibernate.type.descriptor.DateTimeUtils.appendAsDate; import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTime; @@ -453,7 +454,7 @@ public class PostgreSQLDialect extends Dialect { queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ), "position(?1 in ?2)", "(position(?1 in substring(?2 from ?3))+(?3)-1)", - ParameterType.STRING, ParameterType.STRING, ParameterType.INTEGER + FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER ).setArgumentListSignature("(pattern, string[, start])"); if ( getVersion().isSameOrAfter( 9, 4 ) ) { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java index 81faaef495..ec14c519f1 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java @@ -68,7 +68,7 @@ import java.util.TimeZone; import jakarta.persistence.TemporalType; import static org.hibernate.query.TemporalUnit.NANOSECOND; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.INTEGER; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; import static org.hibernate.type.SqlTypes.*; import static org.hibernate.type.descriptor.DateTimeUtils.appendAsDate; import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTime; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SpannerDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SpannerDialect.java index 0f369c4e73..93516f4ac2 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SpannerDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SpannerDialect.java @@ -424,7 +424,7 @@ public class SpannerDialect extends Dialect { queryEngine.getSqmFunctionRegistry().patternDescriptorBuilder("format", "format_timestamp(?2,?1)") .setInvariantType( stringType ) .setExactArgumentCount( 2 ) - .setArgumentListSignature("(datetime as pattern)") + .setArgumentListSignature("(TIMESTAMP datetime as STRING pattern)") .register(); } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/AvgFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/AvgFunction.java index 6e3f30d18d..f79dca6aea 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/AvgFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/AvgFunction.java @@ -28,7 +28,7 @@ import org.hibernate.sql.ast.tree.predicate.Predicate; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.spi.TypeConfiguration; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.NUMERIC; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.NUMERIC; /** * @author Christian Beikov @@ -112,7 +112,7 @@ public class AvgFunction extends AbstractSqmSelfRenderingFunctionDescriptor { @Override public String getArgumentListSignature() { - return "(arg)"; + return "(NUMERIC arg)"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/CaseLeastGreatestEmulation.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/CaseLeastGreatestEmulation.java index 6f10f37884..1fd883e233 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/CaseLeastGreatestEmulation.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/CaseLeastGreatestEmulation.java @@ -9,12 +9,16 @@ package org.hibernate.dialect.function; import java.util.List; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; +import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; +import org.hibernate.query.sqm.produce.function.FunctionParameterType; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.tree.SqlAstNode; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.COMPARABLE; + /** * * @author Christian Beikov @@ -27,7 +31,7 @@ public class CaseLeastGreatestEmulation public CaseLeastGreatestEmulation(boolean least) { super( least ? "least" : "greatest", - StandardArgumentsValidators.min( 2 ), + new ArgumentTypesValidator( StandardArgumentsValidators.min( 2 ), COMPARABLE, COMPARABLE ), StandardFunctionReturnTypeResolvers.useFirstNonNull() ); this.operator = least ? "<=" : ">="; @@ -66,6 +70,6 @@ public class CaseLeastGreatestEmulation @Override public String getArgumentListSignature() { - return "(arg0[, arg1[, ...]])"; + return "(COMPARABLE arg0[, COMPARABLE arg1[, ...]])"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/CaseWhenEveryAnyEmulation.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/CaseWhenEveryAnyEmulation.java index 80f1232e1b..38b0b08192 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/CaseWhenEveryAnyEmulation.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/CaseWhenEveryAnyEmulation.java @@ -10,6 +10,8 @@ import java.util.List; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.FunctionKind; +import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; +import org.hibernate.query.sqm.produce.function.FunctionParameterType; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.sql.ast.SqlAstTranslator; @@ -30,7 +32,7 @@ public class CaseWhenEveryAnyEmulation extends AbstractSqmSelfRenderingFunctionD super( every ? "every" : "any", FunctionKind.AGGREGATE, - StandardArgumentsValidators.exactly( 1 ), + new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 1 ), FunctionParameterType.BOOLEAN ), StandardFunctionReturnTypeResolvers.invariant( typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.BOOLEAN ) ) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/CastingConcatFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/CastingConcatFunction.java index 21b01a920b..31573b9c0b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/CastingConcatFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/CastingConcatFunction.java @@ -12,10 +12,8 @@ import java.util.List; import org.hibernate.dialect.Dialect; import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.query.CastType; -import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; -import org.hibernate.query.sqm.produce.function.ArgumentsValidator; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.internal.PatternRenderer; @@ -28,7 +26,7 @@ import org.hibernate.type.SqlTypes; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.spi.TypeConfiguration; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.STRING; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; public class CastingConcatFunction extends AbstractSqmSelfRenderingFunctionDescriptor { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java index 70cabb9c12..e560f59812 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java @@ -31,7 +31,7 @@ import org.hibernate.type.SqlTypes; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.spi.TypeConfiguration; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.*; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.*; import static org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers.useArgType; /** @@ -188,7 +188,7 @@ public class CommonFunctionFactory { .setInvariantType( queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.DOUBLE ) ) - .setArgumentListSignature( "(number[, places])" ) + .setArgumentListSignature( "(NUMERIC number[, INTEGER places])" ) .register(); } @@ -199,7 +199,7 @@ public class CommonFunctionFactory { .setInvariantType( queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.DOUBLE ) ) - .setArgumentListSignature( "(number, places)" ) + .setArgumentListSignature( "(NUMERIC number, INTEGER places)" ) .register(); } @@ -213,7 +213,7 @@ public class CommonFunctionFactory { .setInvariantType( queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.DOUBLE ) ) - .setArgumentListSignature( "(number, places)" ) + .setArgumentListSignature( "(NUMERIC number, INTEGER places)" ) .register(); } @@ -228,7 +228,7 @@ public class CommonFunctionFactory { .setInvariantType( queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.DOUBLE ) ) - .setArgumentListSignature( "([seed])" ) + .setArgumentListSignature( "([INTEGER seed])" ) .register(); } @@ -450,13 +450,13 @@ public class CommonFunctionFactory { .setInvariantType( stringType ) .setArgumentCountBetween( 1, 2 ) .setParameterTypes(STRING, STRING) - .setArgumentListSignature( "(string[, characters])" ) + .setArgumentListSignature( "(STRING string[, STRING characters])" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "rtrim" ) .setInvariantType( stringType ) .setArgumentCountBetween( 1, 2 ) .setParameterTypes(STRING, STRING) - .setArgumentListSignature( "(string[, characters])" ) + .setArgumentListSignature( "(STRING string[, STRING characters])" ) .register(); } @@ -467,13 +467,13 @@ public class CommonFunctionFactory { .setInvariantType( stringType ) .setExactArgumentCount( 1 ) .setParameterTypes(STRING) - .setArgumentListSignature( "(string)" ) + .setArgumentListSignature( "(STRING string)" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "rtrim" ) .setInvariantType( stringType ) .setExactArgumentCount( 1 ) .setParameterTypes(STRING) - .setArgumentListSignature( "(string)" ) + .setArgumentListSignature( "(STRING string)" ) .register(); } @@ -484,13 +484,13 @@ public class CommonFunctionFactory { .setInvariantType( stringType ) .setArgumentCountBetween( 2, 3 ) .setParameterTypes(STRING, INTEGER, STRING) - .setArgumentListSignature( "(string, length[, padding])" ) + .setArgumentListSignature( "(STRING string, INTEGER length[, STRING padding])" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "rpad" ) .setInvariantType( stringType ) .setArgumentCountBetween( 2, 3 ) .setParameterTypes(STRING, INTEGER, STRING) - .setArgumentListSignature( "(string, length[, padding])" ) + .setArgumentListSignature( "(STRING string, INTEGER length[, STRING padding])" ) .register(); } @@ -606,7 +606,7 @@ public class CommonFunctionFactory { ) .setExactArgumentCount( 2 ) .setParameterTypes(STRING, INTEGER) - .setArgumentListSignature( "(string, times)" ) + .setArgumentListSignature( "(STRING string, INTEGER times)" ) .register(); } @@ -617,13 +617,13 @@ public class CommonFunctionFactory { .setInvariantType( stringType ) .setExactArgumentCount( 2 ) .setParameterTypes(STRING, INTEGER) - .setArgumentListSignature( "(string, length)" ) + .setArgumentListSignature( "(STRING string, INTEGER length)" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "right" ) .setInvariantType( stringType ) .setExactArgumentCount( 2 ) .setParameterTypes(STRING, INTEGER) - .setArgumentListSignature( "(string, length)" ) + .setArgumentListSignature( "(STRING string, INTEGER length)" ) .register(); } @@ -634,13 +634,13 @@ public class CommonFunctionFactory { .setInvariantType( stringType ) .setExactArgumentCount( 2 ) .setParameterTypes(STRING, INTEGER) - .setArgumentListSignature( "(string, length)" ) + .setArgumentListSignature( "(STRING string, INTEGER length)" ) .register(); queryEngine.getSqmFunctionRegistry().patternDescriptorBuilder( "right", "substr(?1,-?2)" ) .setInvariantType( stringType ) .setExactArgumentCount( 2 ) .setParameterTypes(STRING, INTEGER) - .setArgumentListSignature( "(string, length)" ) + .setArgumentListSignature( "(STRING string, INTEGER length)" ) .register(); } @@ -651,13 +651,13 @@ public class CommonFunctionFactory { .setInvariantType( stringType ) .setExactArgumentCount( 2 ) .setParameterTypes(STRING, INTEGER) - .setArgumentListSignature( "(string, length)" ) + .setArgumentListSignature( "(STRING string, INTEGER length)" ) .register(); queryEngine.getSqmFunctionRegistry().patternDescriptorBuilder( "right", "substr(?1,length(?1)-?2+1)" ) .setInvariantType( stringType ) .setExactArgumentCount( 2 ) .setParameterTypes(STRING, INTEGER) - .setArgumentListSignature( "(string, length)" ) + .setArgumentListSignature( "(STRING string, INTEGER length)" ) .register(); } @@ -668,7 +668,7 @@ public class CommonFunctionFactory { ) .setExactArgumentCount( 2 ) .setParameterTypes(STRING, INTEGER) - .setArgumentListSignature( "(string, times)" ) + .setArgumentListSignature( "(STRING string, INTEGER times)" ) .register(); queryEngine.getSqmFunctionRegistry().registerAlternateKey( "repeat", "replicate" ); } @@ -698,7 +698,7 @@ public class CommonFunctionFactory { ) .setArgumentCountBetween( 2, 4 ) .setParameterTypes(STRING, STRING, INTEGER, INTEGER) - .setArgumentListSignature( "(string, pattern[, start[, occurrence]])" ) + .setArgumentListSignature( "(STRING string, STRING pattern[, INTEGER start[, INTEGER occurrence]])" ) .register(); } @@ -708,8 +708,8 @@ public class CommonFunctionFactory { queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) ) .setArgumentCountBetween( 2, 3 ) - .setParameterTypes(STRING, STRING, INTEGER) - .setArgumentListSignature( "(string, start[, length])" ) + .setParameterTypes(STRING, INTEGER, INTEGER) + .setArgumentListSignature( "(STRING string, INTEGER start[, INTEGER length])" ) .register(); } @@ -847,14 +847,14 @@ public class CommonFunctionFactory { .setExactArgumentCount( 1 ) .setInvariantType( booleanType ) .setParameterTypes(BOOLEAN) - .setArgumentListSignature( "(predicate)" ) + .setArgumentListSignature( "(BOOLEAN predicate)" ) .register(); queryEngine.getSqmFunctionRegistry().namedAggregateDescriptorBuilder( "any" ) .setExactArgumentCount( 1 ) .setInvariantType( booleanType ) .setParameterTypes(BOOLEAN) - .setArgumentListSignature( "(predicate)" ) + .setArgumentListSignature( "(BOOLEAN predicate)" ) .register(); } @@ -872,7 +872,7 @@ public class CommonFunctionFactory { .setExactArgumentCount( 1 ) .setParameterTypes(BOOLEAN) .setInvariantType( booleanType ) - .setArgumentListSignature( "(predicate)" ) + .setArgumentListSignature( "(BOOLEAN predicate)" ) .register(); queryEngine.getSqmFunctionRegistry().registerAlternateKey( "every", "bool_and" ); @@ -880,7 +880,7 @@ public class CommonFunctionFactory { .setExactArgumentCount( 1 ) .setParameterTypes(BOOLEAN) .setInvariantType( booleanType ) - .setArgumentListSignature( "(predicate)" ) + .setArgumentListSignature( "(BOOLEAN predicate)" ) .register(); queryEngine.getSqmFunctionRegistry().registerAlternateKey( "any", "bool_or" ); } @@ -1182,7 +1182,7 @@ public class CommonFunctionFactory { ) .setMinArgumentCount( 1 ) .setParameterTypes(STRING) - .setArgumentListSignature( "(string0[, string1[, ...]])" ) + .setArgumentListSignature( "(STRING string0[, STRING string1[, ...]])" ) .register(); } @@ -1196,7 +1196,7 @@ public class CommonFunctionFactory { ) .setMinArgumentCount( 1 ) .setParameterTypes(STRING) - .setArgumentListSignature( "(string0[, string1[, ...]])" ) + .setArgumentListSignature( "(STRING string0[, STRING string1[, ...]])" ) .register(); } @@ -1263,13 +1263,13 @@ public class CommonFunctionFactory { .setInvariantType( basicTypeRegistry.resolve( StandardBasicTypes.DATE ) ) .setExactArgumentCount( 2 ) .setParameterTypes(INTEGER, INTEGER) - .setArgumentListSignature( "(year, dayofyear)" ) + .setArgumentListSignature( "(INTEGER year, INTEGER dayofyear)" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "maketime" ) .setInvariantType( basicTypeRegistry.resolve( StandardBasicTypes.TIME )) .setExactArgumentCount( 3 ) .setParameterTypes(INTEGER, INTEGER, INTEGER) - .setArgumentListSignature( "(hour, min, sec)" ) + .setArgumentListSignature( "(INTEGER hour, INTEGER min, INTEGER sec)" ) .register(); } @@ -1541,7 +1541,7 @@ public class CommonFunctionFactory { ) .setExactArgumentCount( 2 ) .setParameterTypes(STRING, STRING) - .setArgumentListSignature( "(pattern in string)" ) + .setArgumentListSignature( "(STRING pattern in STRING string)" ) .register(); } @@ -1552,7 +1552,7 @@ public class CommonFunctionFactory { ) .setArgumentCountBetween( 2, 3 ) .setParameterTypes(STRING, STRING, INTEGER) - .setArgumentListSignature( "(pattern, string[, start])" ) + .setArgumentListSignature( "(STRING pattern, STRING string[, INTEGER start])" ) .register(); } @@ -1566,7 +1566,7 @@ public class CommonFunctionFactory { ) .setArgumentCountBetween( 2, 3 ) .setParameterTypes(STRING, STRING, INTEGER) - .setArgumentListSignature( "(pattern, string[, start])" ) + .setArgumentListSignature( "(STRING pattern, STRING string[, INTEGER start])" ) .register(); queryEngine.getSqmFunctionRegistry().registerAlternateKey( "locate", "charindex" ); } @@ -1581,7 +1581,7 @@ public class CommonFunctionFactory { "position(?1 in ?2)", "(position(?1 in substring(?2 from ?3))+?3)", STRING, STRING, INTEGER ) - .setArgumentListSignature( "(pattern, string[, start])" ); + .setArgumentListSignature( "(STRING pattern, STRING string[, INTEGER start])" ); } /** * ANSI-style substring @@ -1593,7 +1593,7 @@ public class CommonFunctionFactory { "substring(?1 from ?2)", "substring(?1 from ?2 for ?3)", STRING, INTEGER, INTEGER ) - .setArgumentListSignature( "(string{ from|,} start[{ for|,} length])" ); + .setArgumentListSignature( "(STRING string{ from|,} INTEGER start[{ for|,} INTEGER length])" ); } /** @@ -1606,7 +1606,7 @@ public class CommonFunctionFactory { ) .setArgumentCountBetween( 2, 3 ) .setParameterTypes(STRING, INTEGER, INTEGER) - .setArgumentListSignature( "(string{ from|,} start[{ for|,} length])" ) + .setArgumentListSignature( "(STRING string{ from|,} INTEGER start[{ for|,} INTEGER length])" ) .register(); } @@ -1622,7 +1622,7 @@ public class CommonFunctionFactory { "substring(?1,?2,?3)", STRING, INTEGER, INTEGER ) - .setArgumentListSignature( "(string{ from|,} start[{ for|,} length])" ); + .setArgumentListSignature( "(STRING string{ from|,} INTEGER start[{ for|,} INTEGER length])" ); } /** @@ -1630,7 +1630,7 @@ public class CommonFunctionFactory { */ public static void substring_substr(QueryEngine queryEngine) { queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "substring", "substr" ) - .setArgumentListSignature( "(string{ from|,} start[{ for|,} length])" ) + .setArgumentListSignature( "(STRING string{ from|,} INTEGER start[{ for|,} INTEGER length])" ) .setInvariantType( queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) ) @@ -1645,7 +1645,7 @@ public class CommonFunctionFactory { queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) ) .setParameterTypes(STRING, INTEGER, INTEGER, STRING) - .setArgumentListSignature( "(string, start, length, replacement)" ) + .setArgumentListSignature( "(STRING string, INTEGER start, INTEGER length, STRING replacement)" ) .register(); } @@ -1662,7 +1662,7 @@ public class CommonFunctionFactory { ) .setExactArgumentCount( 4 ) .setParameterTypes(STRING, INTEGER, INTEGER, STRING) - .setArgumentListSignature( "(string, start, length, replacement)" ) + .setArgumentListSignature( "(STRING string, INTEGER start, INTEGER length, STRING replacement)" ) .register(); } @@ -1703,7 +1703,7 @@ public class CommonFunctionFactory { ) .setExactArgumentCount( 3 ) .setParameterTypes(STRING, STRING, STRING) - .setArgumentListSignature( "(string, pattern, replacement)" ) + .setArgumentListSignature( "(STRING string, STRING pattern, STRING replacement)" ) .register(); } @@ -1717,7 +1717,7 @@ public class CommonFunctionFactory { ) .setExactArgumentCount( 3 ) .setParameterTypes(STRING, STRING, STRING) - .setArgumentListSignature( "(string, pattern, replacement)" ) + .setArgumentListSignature( "(STRING string, STRING pattern, STRING replacement)" ) .register(); queryEngine.getSqmFunctionRegistry().registerAlternateKey( "replace", "str_replace" ); } @@ -1729,7 +1729,7 @@ public class CommonFunctionFactory { ) .setMinArgumentCount( 1 ) .setParameterTypes(STRING) - .setArgumentListSignature( "(string0[, string1[, ...]])" ) + .setArgumentListSignature( "(STRING string0[, STRING string1[, ...]])" ) .register(); } @@ -1740,14 +1740,14 @@ public class CommonFunctionFactory { .setInvariantType( stringType ) .setExactArgumentCount( 1 ) .setParameterTypes(STRING) - .setArgumentListSignature( "(string)" ) + .setArgumentListSignature( "(STRING string)" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "upper" ) .setInvariantType( stringType ) .setExactArgumentCount( 1 ) .setParameterTypes(STRING) - .setArgumentListSignature( "(string)" ) + .setArgumentListSignature( "(STRING string)" ) .register(); } @@ -1775,6 +1775,7 @@ public class CommonFunctionFactory { public static void chr_char(QueryEngine queryEngine) { queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "char" ) .setExactArgumentCount( 1 ) + .setParameterTypes(INTEGER) .setInvariantType( queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.CHARACTER ) ) @@ -1790,16 +1791,16 @@ public class CommonFunctionFactory { // .setInvariantType( StandardBasicTypes.INTEGER ) .setReturnTypeResolver( useArgType( 1 ) ) .setExactArgumentCount( 2 ) - .setParameterTypes(ANY, TEMPORAL) - .setArgumentListSignature( "(field, arg)" ) + .setParameterTypes(TEMPORAL_UNIT, TEMPORAL) + .setArgumentListSignature( "(TEMPORAL_UNIT field, TEMPORAL arg)" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "datename" ) .setInvariantType( queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) ) .setExactArgumentCount( 2 ) - .setParameterTypes(ANY, TEMPORAL) - .setArgumentListSignature( "(field, arg)" ) + .setParameterTypes(TEMPORAL_UNIT, TEMPORAL) + .setArgumentListSignature( "(TEMPORAL_UNIT field, TEMPORAL arg)" ) .register(); } @@ -1827,27 +1828,33 @@ public class CommonFunctionFactory { public static void leastGreatest(QueryEngine queryEngine) { queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "least" ) .setMinArgumentCount( 2 ) + .setParameterTypes(COMPARABLE, COMPARABLE) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "greatest" ) .setMinArgumentCount( 2 ) + .setParameterTypes(COMPARABLE, COMPARABLE) .register(); } public static void leastGreatest_minMax(QueryEngine queryEngine) { queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "least", "min" ) .setMinArgumentCount( 2 ) + .setParameterTypes(COMPARABLE, COMPARABLE) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "greatest", "max" ) .setMinArgumentCount( 2 ) + .setParameterTypes(COMPARABLE, COMPARABLE) .register(); } public static void leastGreatest_minMaxValue(QueryEngine queryEngine) { queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "least", "minvalue" ) .setMinArgumentCount( 2 ) + .setParameterTypes(COMPARABLE, COMPARABLE) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "greatest", "maxvalue" ) .setMinArgumentCount( 2 ) + .setParameterTypes(COMPARABLE, COMPARABLE) .register(); } @@ -1860,11 +1867,13 @@ public class CommonFunctionFactory { queryEngine.getSqmFunctionRegistry().namedAggregateDescriptorBuilder( "max" ) .setArgumentRenderingMode( inferenceArgumentRenderingMode ) .setExactArgumentCount( 1 ) + .setParameterTypes(COMPARABLE) .register(); queryEngine.getSqmFunctionRegistry().namedAggregateDescriptorBuilder( "min" ) .setArgumentRenderingMode( inferenceArgumentRenderingMode ) .setExactArgumentCount( 1 ) + .setParameterTypes(COMPARABLE) .register(); final TypeConfiguration typeConfiguration = queryEngine.getTypeConfiguration(); @@ -2155,7 +2164,7 @@ public class CommonFunctionFactory { ) .setExactArgumentCount( 2 ) .setParameterTypes(DATE, DATE) - .setArgumentListSignature( "(end, start)" ) + .setArgumentListSignature( "(DATE end, DATE start)" ) .register(); } @@ -2167,32 +2176,32 @@ public class CommonFunctionFactory { .setReturnTypeResolver( useArgType( 1 ) ) .setExactArgumentCount( 2 ) .setParameterTypes(DATE, INTEGER) - .setArgumentListSignature( "(datetime, days)" ) + .setArgumentListSignature( "(DATE datetime, INTEGER days)" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "subdate" ) .setReturnTypeResolver( useArgType( 1 ) ) .setExactArgumentCount( 2 ) .setParameterTypes(DATE, INTEGER) - .setArgumentListSignature( "(datetime, days)" ) + .setArgumentListSignature( "(DATE datetime, INTEGER days)" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "addtime" ) .setReturnTypeResolver( useArgType( 1 ) ) .setExactArgumentCount( 2 ) - .setParameterTypes(TIME, INTEGER) - .setArgumentListSignature( "(datetime, time)" ) + .setParameterTypes(TIME, TIME) + .setArgumentListSignature( "(TIME datetime, TIME time)" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "subtime" ) .setReturnTypeResolver( useArgType( 1 ) ) .setExactArgumentCount( 2 ) - .setParameterTypes(TIME, INTEGER) - .setArgumentListSignature( "(datetime, time)" ) + .setParameterTypes(TIME, TIME) + .setArgumentListSignature( "(TIME datetime, TIME time)" ) .register(); } public static void addMonths(QueryEngine queryEngine) { queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "add_months" ) .setReturnTypeResolver( useArgType( 1 ) ) - .setArgumentListSignature( "(datetime, months)" ) + .setArgumentListSignature( "(DATE datetime, INTEGER months)" ) .setExactArgumentCount( 2 ) .setParameterTypes(DATE, INTEGER) .register(); @@ -2204,7 +2213,7 @@ public class CommonFunctionFactory { queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ) ) .setExactArgumentCount( 2 ) - .setArgumentListSignature( "(end, start)" ) + .setArgumentListSignature( "(DATE end, DATE start)" ) .setParameterTypes(DATE, DATE) .register(); } @@ -2216,7 +2225,7 @@ public class CommonFunctionFactory { ) .setExactArgumentCount( 2 ) .setParameterTypes(DATE, DATE) - .setArgumentListSignature( "(end, start)" ) + .setArgumentListSignature( "(DATE end, DATE start)" ) .register(); } @@ -2227,7 +2236,7 @@ public class CommonFunctionFactory { ) .setExactArgumentCount( 2 ) .setParameterTypes(TIME, TIME) - .setArgumentListSignature( "(end, start)" ) + .setArgumentListSignature( "(TIME end, TIME start)" ) .register(); } @@ -2239,37 +2248,37 @@ public class CommonFunctionFactory { .setInvariantType( integerType ) .setExactArgumentCount( 2 ) .setParameterTypes(DATE, DATE) - .setArgumentListSignature( "(end, start)" ) + .setArgumentListSignature( "(DATE end, DATE start)" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "months_between" ) .setInvariantType( integerType ) .setExactArgumentCount( 2 ) .setParameterTypes(DATE, DATE) - .setArgumentListSignature( "(end, start)" ) + .setArgumentListSignature( "(DATE end, DATE start)" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "days_between" ) .setInvariantType( integerType ) .setExactArgumentCount( 2 ) .setParameterTypes(DATE, DATE) - .setArgumentListSignature( "(end, start)" ) + .setArgumentListSignature( "(DATE end, DATE start)" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "hours_between" ) .setInvariantType( longType ) .setExactArgumentCount( 2 ) .setParameterTypes(TIME, TIME) - .setArgumentListSignature( "(end, start)" ) + .setArgumentListSignature( "(TIME end, TIME start)" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "minutes_between" ) .setInvariantType( longType ) .setExactArgumentCount( 2 ) .setParameterTypes(TIME, TIME) - .setArgumentListSignature( "(end, start)" ) + .setArgumentListSignature( "(TIME end, TIME start)" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "seconds_between" ) .setInvariantType( longType ) .setExactArgumentCount( 2 ) .setParameterTypes(TIME, TIME) - .setArgumentListSignature( "(end, start)" ) + .setArgumentListSignature( "(TIME end, TIME start)" ) .register(); } @@ -2278,37 +2287,37 @@ public class CommonFunctionFactory { .setReturnTypeResolver( useArgType( 1 ) ) .setExactArgumentCount( 2 ) .setParameterTypes(DATE, INTEGER) - .setArgumentListSignature( "(datetime, years)" ) + .setArgumentListSignature( "(DATE datetime, INTEGER years)" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "add_months" ) .setReturnTypeResolver( useArgType( 1 ) ) .setExactArgumentCount( 2 ) .setParameterTypes(DATE, INTEGER) - .setArgumentListSignature( "(datetime, months)" ) + .setArgumentListSignature( "(DATE datetime, INTEGER months)" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "add_days" ) .setReturnTypeResolver( useArgType( 1 ) ) .setExactArgumentCount( 2 ) .setParameterTypes(DATE, INTEGER) - .setArgumentListSignature( "(datetime, days)" ) + .setArgumentListSignature( "(DATE datetime, INTEGER days)" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "add_hours" ) .setReturnTypeResolver( useArgType( 1 ) ) .setExactArgumentCount( 2 ) .setParameterTypes(TIME, INTEGER) - .setArgumentListSignature( "(datetime, hours)" ) + .setArgumentListSignature( "(TIME datetime, INTEGER hours)" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "add_minutes" ) .setReturnTypeResolver( useArgType( 1 ) ) .setExactArgumentCount( 2 ) .setParameterTypes(TIME, INTEGER) - .setArgumentListSignature( "(datetime, minutes)" ) + .setArgumentListSignature( "(TIME datetime, INTEGER minutes)" ) .register(); queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "add_seconds" ) .setReturnTypeResolver( useArgType( 1 ) ) .setExactArgumentCount( 2 ) .setParameterTypes(TIME, INTEGER) - .setArgumentListSignature( "(datetime, seconds)" ) + .setArgumentListSignature( "(TIME datetime, INTEGER seconds)" ) .register(); } @@ -2322,7 +2331,7 @@ public class CommonFunctionFactory { ) .setExactArgumentCount( 2 ) .setParameterTypes(TEMPORAL, STRING) - .setArgumentListSignature( "(datetime as pattern)" ) + .setArgumentListSignature( "(TEMPORAL datetime as STRING pattern)" ) .register(); } @@ -2338,7 +2347,7 @@ public class CommonFunctionFactory { ) .setExactArgumentCount( 2 ) .setParameterTypes(TEMPORAL, STRING) - .setArgumentListSignature( "(datetime as pattern)" ) + .setArgumentListSignature( "(TEMPORAL datetime as STRING pattern)" ) .register(); } @@ -2354,7 +2363,7 @@ public class CommonFunctionFactory { ) .setExactArgumentCount( 2 ) .setParameterTypes(TEMPORAL, STRING) - .setArgumentListSignature( "(datetime as pattern)" ) + .setArgumentListSignature( "(TEMPORAL datetime as STRING pattern)" ) .register(); } @@ -2370,7 +2379,7 @@ public class CommonFunctionFactory { ) .setExactArgumentCount( 2 ) .setParameterTypes(TEMPORAL, STRING) - .setArgumentListSignature( "(datetime as pattern)" ) + .setArgumentListSignature( "(TEMPORAL datetime as STRING pattern)" ) .register(); } @@ -2383,8 +2392,8 @@ public class CommonFunctionFactory { queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) ) .setExactArgumentCount( 2 ) - .setParameterTypes(STRING, ANY) - .setArgumentListSignature("(string as collation)") + .setParameterTypes(STRING, COLLATION) + .setArgumentListSignature("(STRING string as COLLATION collation)") .register(); } @@ -2398,7 +2407,7 @@ public class CommonFunctionFactory { ) .setExactArgumentCount( 2 ) .setParameterTypes(STRING, ANY) - .setArgumentListSignature("(string as collation)") + .setArgumentListSignature("(STRING string as COLLATION collation)") .register(); } @@ -2410,8 +2419,8 @@ public class CommonFunctionFactory { .resolve( StandardBasicTypes.TIMESTAMP ) ) .setExactArgumentCount( 2 ) - .setParameterTypes(ANY, TEMPORAL) - .setArgumentListSignature( "(field, datetime)" ) + .setParameterTypes(TEMPORAL_UNIT, TEMPORAL) + .setArgumentListSignature( "(TEMPORAL_UNIT field, TEMPORAL datetime)" ) .register(); } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/DB2FormatEmulation.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/DB2FormatEmulation.java index 02f5a8791e..15ced544e6 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/DB2FormatEmulation.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/DB2FormatEmulation.java @@ -9,7 +9,6 @@ package org.hibernate.dialect.function; import org.hibernate.dialect.OracleDialect; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; -import org.hibernate.query.sqm.produce.function.ArgumentsValidator; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.sql.ast.SqlAstTranslator; @@ -23,8 +22,8 @@ import org.hibernate.type.spi.TypeConfiguration; import java.util.List; import jakarta.persistence.TemporalType; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.STRING; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.TEMPORAL; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL; /** * DB2's varchar_format() can't handle quoted literal strings in @@ -98,6 +97,6 @@ public class DB2FormatEmulation @Override public String getArgumentListSignature() { - return "(datetime as pattern)"; + return "(TEMPORAL datetime as STRING pattern)"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/DerbyLpadEmulation.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/DerbyLpadEmulation.java index 6697e5c750..73d30e990f 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/DerbyLpadEmulation.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/DerbyLpadEmulation.java @@ -8,10 +8,8 @@ package org.hibernate.dialect.function; import java.util.List; -import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; -import org.hibernate.query.sqm.produce.function.ArgumentsValidator; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.sql.ast.SqlAstNodeRenderingMode; @@ -21,8 +19,8 @@ import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.spi.TypeConfiguration; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.INTEGER; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.STRING; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; /** * A derby implementation for lpad. @@ -67,6 +65,6 @@ public class DerbyLpadEmulation @Override public String getArgumentListSignature() { - return "(string, length)"; + return "(STRNG string, INTEGER length)"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/DerbyRpadEmulation.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/DerbyRpadEmulation.java index 0a4e96d1ee..5fd3a797f3 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/DerbyRpadEmulation.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/DerbyRpadEmulation.java @@ -8,7 +8,6 @@ package org.hibernate.dialect.function; import java.util.List; -import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; @@ -20,8 +19,8 @@ import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.spi.TypeConfiguration; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.INTEGER; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.STRING; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; /** * A derby implementation for rpad. @@ -66,6 +65,6 @@ public class DerbyRpadEmulation @Override public String getArgumentListSignature() { - return "(string, length)"; + return "(STRING string, INTEGER length)"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/EveryAnyEmulation.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/EveryAnyEmulation.java index 60918c71d7..3bd7604b1b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/EveryAnyEmulation.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/EveryAnyEmulation.java @@ -20,7 +20,7 @@ import org.hibernate.sql.ast.tree.predicate.Predicate; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.spi.TypeConfiguration; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.BOOLEAN; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.BOOLEAN; /** * @author Jan Schatteman diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/ExtractFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/ExtractFunction.java index 2e56a3c5ef..d9bd670bc2 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/ExtractFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/ExtractFunction.java @@ -15,7 +15,6 @@ import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor; import org.hibernate.query.sqm.function.SelfRenderingSqmFunction; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; -import org.hibernate.query.sqm.produce.function.ArgumentsValidator; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.tree.SqmTypedNode; @@ -29,8 +28,8 @@ import java.util.List; import static java.util.Arrays.asList; import static org.hibernate.query.BinaryArithmeticOperator.*; import static org.hibernate.query.TemporalUnit.*; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.ANY; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.TEMPORAL; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL_UNIT; import static org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers.useArgType; /** @@ -46,7 +45,7 @@ public class ExtractFunction "extract", new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), - ANY, TEMPORAL + TEMPORAL_UNIT, TEMPORAL ), StandardFunctionReturnTypeResolvers.useArgType( 1 ) ); @@ -277,7 +276,7 @@ public class ExtractFunction @Override public String getArgumentListSignature() { - return "(field from arg)"; + return "(TEMPORAL_UNIT field from TEMPORAL arg)"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/InsertSubstringOverlayEmulation.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/InsertSubstringOverlayEmulation.java index 44b8ec1617..e8e091b82f 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/InsertSubstringOverlayEmulation.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/InsertSubstringOverlayEmulation.java @@ -31,8 +31,8 @@ import java.util.List; import jakarta.persistence.criteria.Expression; import static java.util.Arrays.asList; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.INTEGER; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.STRING; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; /** * @author Gavin King @@ -47,7 +47,7 @@ public class InsertSubstringOverlayEmulation "overlay", new ArgumentTypesValidator( StandardArgumentsValidators.between( 3, 4 ), - STRING, INTEGER, INTEGER, STRING + STRING, STRING, INTEGER, INTEGER ), StandardFunctionReturnTypeResolvers.invariant( typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) @@ -144,6 +144,6 @@ public class InsertSubstringOverlayEmulation @Override public String getArgumentListSignature() { - return "(string placing replacement from start[ for length])"; + return "(STRING string placing STRING replacement from INTEGER start[ for INTEGER length])"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/LocatePositionEmulation.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/LocatePositionEmulation.java index 4f4190792d..a0b7546f30 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/LocatePositionEmulation.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/LocatePositionEmulation.java @@ -10,6 +10,8 @@ import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType; import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor; import org.hibernate.query.sqm.function.SelfRenderingSqmFunction; +import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; +import org.hibernate.query.sqm.produce.function.FunctionParameterType; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.tree.SqmTypedNode; @@ -18,6 +20,8 @@ import org.hibernate.type.spi.TypeConfiguration; import java.util.List; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; + /** * @author Gavin King */ @@ -26,7 +30,7 @@ public class LocatePositionEmulation extends AbstractSqmFunctionDescriptor { public LocatePositionEmulation(TypeConfiguration typeConfiguration) { super( "position", - StandardArgumentsValidators.exactly( 2 ), + new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, STRING ), StandardFunctionReturnTypeResolvers.invariant( typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ) ) @@ -45,6 +49,6 @@ public class LocatePositionEmulation extends AbstractSqmFunctionDescriptor { @Override public String getArgumentListSignature() { - return "(pattern in string)"; + return "(STRING pattern in STRING string)"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/LpadRpadPadEmulation.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/LpadRpadPadEmulation.java index f47ca1f1fa..fd3154e0f1 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/LpadRpadPadEmulation.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/LpadRpadPadEmulation.java @@ -22,9 +22,9 @@ import org.hibernate.type.spi.TypeConfiguration; import java.util.List; import static java.util.Arrays.asList; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.ANY; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.INTEGER; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.STRING; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TRIM_SPEC; /** * @author Gavin King @@ -37,7 +37,7 @@ public class LpadRpadPadEmulation "pad", new ArgumentTypesValidator( StandardArgumentsValidators.between( 3, 4 ), - STRING, INTEGER, ANY, STRING + STRING, INTEGER, TRIM_SPEC, STRING ), StandardFunctionReturnTypeResolvers.invariant( typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) @@ -73,6 +73,6 @@ public class LpadRpadPadEmulation @Override public String getArgumentListSignature() { - return "(string with length {leading|trailing}[ character])"; + return "(STRING string with INTEGER length {leading|trailing}[ STRING character])"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/QuantifiedLeastGreatestEmulation.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/QuantifiedLeastGreatestEmulation.java index a1ede382dc..6a1aa3069c 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/QuantifiedLeastGreatestEmulation.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/QuantifiedLeastGreatestEmulation.java @@ -9,12 +9,15 @@ package org.hibernate.dialect.function; import java.util.List; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; +import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.tree.SqlAstNode; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.COMPARABLE; + /** * * @author Christian Beikov @@ -27,7 +30,7 @@ public class QuantifiedLeastGreatestEmulation public QuantifiedLeastGreatestEmulation(boolean least) { super( least ? "least" : "greatest", - StandardArgumentsValidators.min( 2 ), + new ArgumentTypesValidator( StandardArgumentsValidators.min( 2 ), COMPARABLE, COMPARABLE ), StandardFunctionReturnTypeResolvers.useFirstNonNull() ); this.operator = least ? "<=" : ">="; @@ -67,6 +70,6 @@ public class QuantifiedLeastGreatestEmulation @Override public String getArgumentListSignature() { - return "(arg0[, arg1[, ...]])"; + return "(COMPARABLE arg0[, COMPARABLE arg1[, ...]])"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/SQLServerEveryAnyEmulation.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/SQLServerEveryAnyEmulation.java index d2bf908886..470eca5a7b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/SQLServerEveryAnyEmulation.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/SQLServerEveryAnyEmulation.java @@ -20,7 +20,7 @@ import org.hibernate.sql.ast.tree.predicate.Predicate; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.spi.TypeConfiguration; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.BOOLEAN; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.BOOLEAN; /** * @author Jan Schatteman diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/SQLServerFormatEmulation.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/SQLServerFormatEmulation.java index 06e616ad1b..81ea8c52eb 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/SQLServerFormatEmulation.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/SQLServerFormatEmulation.java @@ -12,6 +12,8 @@ import jakarta.persistence.TemporalType; import org.hibernate.dialect.SQLServerDialect; import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; +import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; +import org.hibernate.query.sqm.produce.function.FunctionParameterType; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.sql.ast.SqlAstTranslator; @@ -22,6 +24,9 @@ import org.hibernate.sql.ast.tree.expression.Format; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.spi.TypeConfiguration; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL; + /** * SQL Server behaves strangely when the first argument to format is of the type time, so we cast to datetime. * @@ -34,7 +39,7 @@ public class SQLServerFormatEmulation extends AbstractSqmSelfRenderingFunctionDe public SQLServerFormatEmulation(SQLServerDialect dialect, TypeConfiguration typeConfiguration) { super( "format", - StandardArgumentsValidators.exactly( 2 ), + new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), TEMPORAL, STRING ), StandardFunctionReturnTypeResolvers.invariant( typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) ) @@ -67,6 +72,6 @@ public class SQLServerFormatEmulation extends AbstractSqmSelfRenderingFunctionDe @Override public String getArgumentListSignature() { - return "(datetime as pattern)"; + return "(TEMPORAL datetime as STRING pattern)"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/TimestampaddFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/TimestampaddFunction.java index 49c61e788a..90d98e0796 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/TimestampaddFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/TimestampaddFunction.java @@ -14,6 +14,7 @@ import org.hibernate.query.BinaryArithmeticOperator; import org.hibernate.query.TemporalUnit; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression; +import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.internal.PatternRenderer; @@ -35,6 +36,9 @@ import java.util.ArrayList; import java.util.List; import static java.util.Arrays.asList; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL_UNIT; /** * @author Gavin King @@ -49,7 +53,10 @@ public class TimestampaddFunction public TimestampaddFunction(Dialect dialect, TypeConfiguration typeConfiguration) { super( "timestampadd", - StandardArgumentsValidators.exactly( 3 ), + new ArgumentTypesValidator( + StandardArgumentsValidators.exactly( 3 ), + TEMPORAL_UNIT, INTEGER, TEMPORAL + ), StandardFunctionReturnTypeResolvers.useArgType( 3 ) ); this.dialect = dialect; @@ -194,7 +201,7 @@ public class TimestampaddFunction @Override public String getArgumentListSignature() { - return "(field, magnitude, datetime)"; + return "(TEMPORAL_UNIT field, INTEGER magnitude, TEMPORAL datetime)"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/TimestampdiffFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/TimestampdiffFunction.java index d7078ebbfb..40067ef7ff 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/TimestampdiffFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/TimestampdiffFunction.java @@ -12,6 +12,8 @@ import org.hibernate.dialect.Dialect; import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression; +import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; +import org.hibernate.query.sqm.produce.function.FunctionParameterType; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.internal.PatternRenderer; @@ -24,6 +26,8 @@ import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.spi.TypeConfiguration; import static java.util.Arrays.asList; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL_UNIT; /** * @author Gavin King @@ -36,7 +40,10 @@ public class TimestampdiffFunction public TimestampdiffFunction(Dialect dialect, TypeConfiguration typeConfiguration) { super( "timestampdiff", - StandardArgumentsValidators.exactly( 3 ), + new ArgumentTypesValidator( + StandardArgumentsValidators.exactly( 3 ), + TEMPORAL_UNIT, TEMPORAL, TEMPORAL + ), StandardFunctionReturnTypeResolvers.invariant( typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.LONG ) ) @@ -108,7 +115,7 @@ public class TimestampdiffFunction @Override public String getArgumentListSignature() { - return "(field, start, end)"; + return "(TEMPORAL_UNIT field, TEMPORAL start, TEMPORAL end)"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/TrimFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/TrimFunction.java index e9aeaba1bb..9c962d9f83 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/TrimFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/TrimFunction.java @@ -25,8 +25,8 @@ import org.hibernate.type.spi.TypeConfiguration; import java.util.Collections; import java.util.List; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.ANY; -import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType.STRING; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TRIM_SPEC; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; /** * @author Gavin King @@ -40,7 +40,7 @@ public class TrimFunction extends AbstractSqmSelfRenderingFunctionDescriptor { "trim", new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 3 ), - ANY, STRING, STRING + TRIM_SPEC, STRING, STRING ), StandardFunctionReturnTypeResolvers.invariant( typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) @@ -87,6 +87,6 @@ public class TrimFunction extends AbstractSqmSelfRenderingFunctionDescriptor { @Override public String getArgumentListSignature() { - return "([[{leading|trailing|both} ][arg0 ]from] arg1)"; + return "([[{leading|trailing|both} ][STRING arg0 ]from] STRING arg1)"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/function/AbstractSqmFunctionDescriptor.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/function/AbstractSqmFunctionDescriptor.java index 62946704e2..651eb78b4f 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/function/AbstractSqmFunctionDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/function/AbstractSqmFunctionDescriptor.java @@ -103,7 +103,7 @@ public abstract class AbstractSqmFunctionDescriptor implements SqmFunctionDescri AllowableFunctionReturnType impliedResultType, QueryEngine queryEngine, TypeConfiguration typeConfiguration) { - argumentsValidator.validate( arguments, getName() ); + argumentsValidator.validate( arguments, getName(), queryEngine); return generateSqmFunctionExpression( arguments, @@ -120,7 +120,7 @@ public abstract class AbstractSqmFunctionDescriptor implements SqmFunctionDescri AllowableFunctionReturnType impliedResultType, QueryEngine queryEngine, TypeConfiguration typeConfiguration) { - argumentsValidator.validate( arguments, getName() ); + argumentsValidator.validate( arguments, getName(), queryEngine ); return generateSqmAggregateFunctionExpression( arguments, diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/function/MultipatternSqmFunctionDescriptor.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/function/MultipatternSqmFunctionDescriptor.java index fcf6a78b1f..e37af963ea 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/function/MultipatternSqmFunctionDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/function/MultipatternSqmFunctionDescriptor.java @@ -9,7 +9,7 @@ package org.hibernate.query.sqm.function; import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType; import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; -import org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType; +import org.hibernate.query.sqm.produce.function.FunctionParameterType; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.tree.SqmTypedNode; @@ -59,7 +59,7 @@ public class MultipatternSqmFunctionDescriptor extends AbstractSqmFunctionDescri String name, SqmFunctionDescriptor[] functions, BasicType type, - ParameterType... parameterTypes) { + FunctionParameterType... parameterTypes) { super( name, new ArgumentTypesValidator( diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SelfRenderingSqmAggregateFunction.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SelfRenderingSqmAggregateFunction.java index 2a8bca970d..7a87f89b99 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SelfRenderingSqmAggregateFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SelfRenderingSqmAggregateFunction.java @@ -12,13 +12,13 @@ import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType; import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.produce.function.ArgumentsValidator; import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver; -import org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter; import org.hibernate.query.sqm.sql.SqmToSqlAstConverter; import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.expression.SqmAggregateFunction; import org.hibernate.query.sqm.tree.expression.SqmDistinct; import org.hibernate.query.sqm.tree.predicate.SqmPredicate; import org.hibernate.query.sqm.tree.select.SqmSelectableNode; +import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.predicate.Predicate; /** @@ -49,6 +49,11 @@ public class SelfRenderingSqmAggregateFunction extends SelfRenderingSqmFuncti walker.getCreationContext().getDomainModel().getTypeConfiguration() ); + List arguments = resolveSqlAstArguments( getArguments(), walker ); + ArgumentsValidator argumentsValidator = getArgumentsValidator(); + if ( argumentsValidator != null ) { + argumentsValidator.validateSqlTypes( arguments, getFunctionName() ); + } return new SelfRenderingAggregateFunctionSqlAstExpression( getFunctionName(), getRenderingSupport(), 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 88b5deec40..1f18b4d002 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 @@ -11,7 +11,6 @@ import java.util.List; import org.hibernate.metamodel.MappingMetamodel; import org.hibernate.metamodel.mapping.BasicValuedMapping; -import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.MappingModelExpressable; import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType; import org.hibernate.query.sqm.NodeBuilder; @@ -23,7 +22,6 @@ import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmVisitableNode; import org.hibernate.query.sqm.tree.expression.SqmFunction; import org.hibernate.sql.ast.tree.SqlAstNode; -import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.type.spi.TypeConfiguration; import static java.util.Collections.emptyList; @@ -58,6 +56,10 @@ public class SelfRenderingSqmFunction extends SqmFunction { return renderingSupport; } + protected ArgumentsValidator getArgumentsValidator() { + return argumentsValidator; + } + protected static List resolveSqlAstArguments(List> sqmArguments, SqmToSqlAstConverter walker) { if ( sqmArguments == null || sqmArguments.isEmpty() ) { return emptyList(); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SqmFunctionRegistry.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SqmFunctionRegistry.java index 8b7f7cb51b..99135e43cd 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SqmFunctionRegistry.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SqmFunctionRegistry.java @@ -11,7 +11,7 @@ import java.util.Map; import java.util.TreeMap; import java.util.stream.Stream; -import org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType; +import org.hibernate.query.sqm.produce.function.FunctionParameterType; import org.hibernate.query.sqm.produce.function.NamedFunctionDescriptorBuilder; import org.hibernate.query.sqm.produce.function.PatternFunctionDescriptorBuilder; import org.hibernate.type.BasicType; @@ -255,8 +255,8 @@ public class SqmFunctionRegistry { BasicType type, String pattern0, String pattern1, - ParameterType parameterType) { - return registerPatterns( name, type, new ParameterType[]{parameterType}, pattern0, pattern1 ); + FunctionParameterType parameterType) { + return registerPatterns( name, type, new FunctionParameterType[]{parameterType}, pattern0, pattern1 ); } /** @@ -269,10 +269,10 @@ public class SqmFunctionRegistry { BasicType type, String pattern1, String pattern2, - ParameterType parameterType1, - ParameterType parameterType2) { + FunctionParameterType parameterType1, + FunctionParameterType parameterType2) { return registerPatterns( name, type, - new ParameterType[]{parameterType1,parameterType2}, + new FunctionParameterType[]{parameterType1,parameterType2}, null, pattern1, pattern2 ); } @@ -286,11 +286,11 @@ public class SqmFunctionRegistry { BasicType type, String pattern2, String pattern3, - ParameterType parameterType1, - ParameterType parameterType2, - ParameterType parameterType3) { + FunctionParameterType parameterType1, + FunctionParameterType parameterType2, + FunctionParameterType parameterType3) { return registerPatterns( name, type, - new ParameterType[]{parameterType1,parameterType2,parameterType3}, + new FunctionParameterType[]{parameterType1,parameterType2,parameterType3}, null, null, pattern2, pattern3 ); } @@ -304,19 +304,19 @@ public class SqmFunctionRegistry { BasicType type, String pattern3, String pattern4, - ParameterType parameterType1, - ParameterType parameterType2, - ParameterType parameterType3, - ParameterType parameterType4) { + FunctionParameterType parameterType1, + FunctionParameterType parameterType2, + FunctionParameterType parameterType3, + FunctionParameterType parameterType4) { return registerPatterns( name, type, - new ParameterType[]{parameterType1,parameterType2,parameterType3, parameterType4}, + new FunctionParameterType[]{parameterType1,parameterType2,parameterType3, parameterType4}, null, null, null, pattern3, pattern4 ); } private MultipatternSqmFunctionDescriptor registerPatterns( String name, BasicType type, - ParameterType[] parameterTypes, + FunctionParameterType[] parameterTypes, String... patterns) { SqmFunctionDescriptor[] descriptors = new SqmFunctionDescriptor[patterns.length]; diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/ArgumentTypesValidator.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/ArgumentTypesValidator.java index e90768accb..b52623d16d 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/ArgumentTypesValidator.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/ArgumentTypesValidator.java @@ -9,11 +9,21 @@ package org.hibernate.query.sqm.produce.function; import org.hibernate.QueryException; import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMappingContainer; +import org.hibernate.query.spi.QueryEngine; +import org.hibernate.query.sqm.SqmExpressable; import org.hibernate.query.sqm.tree.SqmTypedNode; +import org.hibernate.query.sqm.tree.expression.SqmCollation; +import org.hibernate.query.sqm.tree.expression.SqmDurationUnit; +import org.hibernate.query.sqm.tree.expression.SqmExtractUnit; +import org.hibernate.query.sqm.tree.expression.SqmTrimSpecification; import org.hibernate.sql.ast.spi.AbstractSqlAstWalker; import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.JdbcParameter; +import org.hibernate.type.descriptor.java.JavaType; +import org.hibernate.type.descriptor.java.spi.JdbcTypeRecommendationException; +import org.hibernate.type.descriptor.jdbc.JdbcType; +import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptorIndicators; import java.lang.reflect.Type; import java.util.List; @@ -22,12 +32,17 @@ import static org.hibernate.type.SqlTypes.*; /** * Typechecks the arguments of HQL functions based on the assigned JDBC types. + * The main purpose for doing this is that we want to be able to check named + * queries at startup or build time, and we want to be able to check all queries + * in the IDE. + * + * @author Gavin King */ public class ArgumentTypesValidator implements ArgumentsValidator { final ArgumentsValidator delegate; - private final ParameterType[] types; + private final FunctionParameterType[] types; - public ArgumentTypesValidator(ArgumentsValidator delegate, ParameterType... types) { + public ArgumentTypesValidator(ArgumentsValidator delegate, FunctionParameterType... types) { this.types = types; if (delegate == null ) { delegate = StandardArgumentsValidators.exactly(types.length); @@ -35,22 +50,82 @@ public class ArgumentTypesValidator implements ArgumentsValidator { this.delegate = delegate; } + /** + * We do an initial validation phase with just the SQM tree, even though we don't + * have all typing information available here (in particular, we don't have the + * final JDBC type codes for things with converters) because this is the phase + * that is run at startup for named queries, and can be done in an IDE. + */ @Override - public void validate(List> arguments, String functionName) { - delegate.validate(arguments, functionName); + public void validate(List> arguments, String functionName, QueryEngine queryEngine) { + delegate.validate(arguments, functionName, queryEngine); + int count = 0; + for (SqmTypedNode argument : arguments) { + JdbcTypeDescriptorIndicators indicators = queryEngine.getTypeConfiguration().getCurrentBaseSqlTypeIndicators(); + SqmExpressable nodeType = argument.getNodeType(); + FunctionParameterType type = count < types.length ? types[count++] : types[types.length - 1]; + if ( nodeType!=null ) { + JavaType javaType = nodeType.getExpressableJavaTypeDescriptor(); + if (javaType != null) { + try { + JdbcType jdbcType = javaType.getRecommendedJdbcType(indicators); + checkType( + count, functionName, type, + jdbcType.getJdbcTypeCode(), + javaType.getJavaTypeClass() + ); + } + catch (JdbcTypeRecommendationException e) { + // it's a converter or something like that, and we will check it later + } + } + switch (type) { + case TEMPORAL_UNIT: + if ( !(argument instanceof SqmExtractUnit) && !(argument instanceof SqmDurationUnit) ) { + throwError(type, Object.class, functionName, count); + } + break; + // the following are not really necessary for the functions we have today + // since collations and trim specifications have special parser rules, + // but at the very least this is an assertion that we don't get given + // something crazy by the parser + case TRIM_SPEC: + if ( !(argument instanceof SqmTrimSpecification) ) { + throwError(type, Object.class, functionName, count); + } + break; + case COLLATION: + if ( !(argument instanceof SqmCollation) ) { + throwError(type, Object.class, functionName, count); + } + break; + } + } + else { + //TODO: appropriate error? + } + } } + /** + * This is the final validation phase with the fully-typed SQL nodes. Note that these + * checks are much less useful, occurring "too late", right before we execute the + * query and get an error from the database. However, they help in the sense of (a) + * resulting in more consistent/understandable error messages, and (b) protecting the + * user from writing queries that depend on generally-unportable implicit type + * conversions happening at the database level. (Implicit type conversions between + * numeric types are portable, and are not prohibited here.) + */ @Override public void validateSqlTypes(List arguments, String functionName) { int count = 0; - for (int i = 0; i < arguments.size(); i++ ) { - SqlAstNode argument = arguments.get(i); + for (SqlAstNode argument : arguments) { if (argument instanceof Expression) { JdbcMappingContainer expressionType = ((Expression) argument).getExpressionType(); - if ( expressionType != null ) { + if (expressionType != null) { ParameterDetector detector = new ParameterDetector(); argument.accept(detector); - if ( detector.detected ) { + if (detector.detected) { count += expressionType.getJdbcTypeCount(); } else { @@ -64,52 +139,64 @@ public class ArgumentTypesValidator implements ArgumentsValidator { private int validateArgument(int count, JdbcMappingContainer expressionType, String functionName) { List mappings = expressionType.getJdbcMappings(); for (JdbcMapping mapping : mappings) { - ParameterType type = count < types.length ? types[count++] : types[types.length - 1]; + FunctionParameterType type = count < types.length ? types[count++] : types[types.length - 1]; if (type != null) { - int code = mapping.getJdbcTypeDescriptor().getJdbcTypeCode(); - Type javaType = mapping.getJavaTypeDescriptor().getJavaType(); - switch (type) { - case STRING: - if (!isCharacterType(code)) { - throwError(type, javaType, functionName, count); - } - break; - case NUMERIC: - if (!isNumericType(code)) { - throwError(type, javaType, functionName, count); - } - break; - case INTEGER: - if (!isIntegral(code)) { - throwError(type, javaType, functionName, count); - } - break; - case BOOLEAN: - if (code != BOOLEAN && code != BIT) { - throwError(type, javaType, functionName, count); - } - case TEMPORAL: - if (!isTemporalType(code)) { - throwError(type, javaType, functionName, count); - } - break; - case DATE: - if (!hasDatePart(code)) { - throwError(type, javaType, functionName, count); - } - break; - case TIME: - if (!hasTimePart(code)) { - throwError(type, javaType, functionName, count); - } - break; - } + checkType( + count, functionName, type, + mapping.getJdbcTypeDescriptor().getJdbcTypeCode(), + mapping.getJavaTypeDescriptor().getJavaType() + ); } } return count; } - private void throwError(ParameterType type, Type javaType, String functionName, int count) { + private void checkType(int count, String functionName, FunctionParameterType type, int code, Type javaType) { + switch (type) { + case COMPARABLE: + if ( !isCharacterType(code) && !isTemporalType(code) &&!isNumericType(code) ) { + throwError(type, javaType, functionName, count); + } + break; + case STRING: + if ( !isCharacterType(code) ) { + throwError(type, javaType, functionName, count); + } + break; + case NUMERIC: + if ( !isNumericType(code) ) { + throwError(type, javaType, functionName, count); + } + break; + case INTEGER: + if ( !isIntegral(code) ) { + throwError(type, javaType, functionName, count); + } + break; + case BOOLEAN: + if ( code != BOOLEAN && code != BIT ) { + throwError(type, javaType, functionName, count); + } + break; + case TEMPORAL: + if ( !isTemporalType(code) ) { + throwError(type, javaType, functionName, count); + } + break; + case DATE: + if ( !hasDatePart(code) ) { + throwError(type, javaType, functionName, count); + } + break; + case TIME: + if ( !hasTimePart(code) ) { + throwError(type, javaType, functionName, count); + } + break; + } + } + + private void throwError(FunctionParameterType type, Type javaType, String functionName, int count) { throw new QueryException( String.format( "Parameter %d of function %s() has type %s, but argument is of type %s", @@ -128,4 +215,14 @@ public class ArgumentTypesValidator implements ArgumentsValidator { detected = true; } } + + @Override + public String getSignature() { + String sig = this.delegate.getSignature(); + for (int i=0; i> arguments, String functionName); + void validate(List> arguments, String functionName, QueryEngine queryEngine); + /** + * Pretty-print the signature of the argument list. + */ default String getSignature() { return "( ... )"; } @@ -31,47 +40,4 @@ public interface ArgumentsValidator { */ default void validateSqlTypes(List arguments, String functionName) {} - /** - * A mini-"type system" for HQL function parameters. - *

- * Note that typical database type systems have relatively few types, - * and lots of implicit type conversion between them. So we can be - * pretty forgiving here. - */ - enum ParameterType { - /** - * @see org.hibernate.type.SqlTypes#isCharacterType(int) - */ - STRING, - /** - * @see org.hibernate.type.SqlTypes#isNumericType(int) - */ - NUMERIC, - /** - * @see org.hibernate.type.SqlTypes#isIntegral(int) - */ - INTEGER, - /** - * @see org.hibernate.type.SqlTypes#isTemporalType(int) - */ - TEMPORAL, - /** - * @see org.hibernate.type.SqlTypes#hasDatePart(int) - */ - DATE, - /** - * @see org.hibernate.type.SqlTypes#hasTimePart(int) - */ - TIME, - /** - * Indicates that the argument should be of type - * {@link org.hibernate.type.SqlTypes#BOOLEAN} or - * a logical expression (predicate) - */ - BOOLEAN, - /** - * Indicates a parameter that accepts any type - */ - ANY - } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/FunctionParameterType.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/FunctionParameterType.java new file mode 100644 index 0000000000..a135b2dd2e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/FunctionParameterType.java @@ -0,0 +1,80 @@ +/* + * 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; + +/** + * A mini-"type system" for HQL function parameters. + *

+ * Note that typical database type systems have relatively few types, + * and lots of implicit type conversion between them. So we can be + * pretty forgiving here. + * + * @author Gavin King + * + * @see ArgumentTypesValidator + */ +public enum FunctionParameterType { + /** + * @see org.hibernate.type.SqlTypes#isCharacterType(int) + */ + STRING, + /** + * @see org.hibernate.type.SqlTypes#isNumericType(int) + */ + NUMERIC, + /** + * @see org.hibernate.type.SqlTypes#isIntegral(int) + */ + INTEGER, + /** + * @see org.hibernate.type.SqlTypes#isTemporalType(int) + */ + TEMPORAL, + /** + * @see org.hibernate.type.SqlTypes#hasDatePart(int) + */ + DATE, + /** + * @see org.hibernate.type.SqlTypes#hasTimePart(int) + */ + TIME, + /** + * Indicates that the argument should be of type + * {@link org.hibernate.type.SqlTypes#BOOLEAN} or + * a logical expression (predicate) + */ + BOOLEAN, + /** + * Indicates a parameter that accepts any type + */ + ANY, + /** + * A temporal unit, used by the {@code extract()} function, and + * some native database functions + * + * @see org.hibernate.query.TemporalUnit + * @see org.hibernate.query.sqm.tree.expression.SqmExtractUnit + * @see org.hibernate.query.sqm.tree.expression.SqmDurationUnit + */ + TEMPORAL_UNIT, + /** + * A trim specification, for trimming and padding functions + * + * @see org.hibernate.query.sqm.tree.expression.SqmTrimSpecification + */ + TRIM_SPEC, + /** + * A collation, used by the {@code collate()} function + * + * @see org.hibernate.query.sqm.tree.expression.SqmCollation + */ + COLLATION, + /** + * Any type with an order (numeric, string, and temporal types) + */ + COMPARABLE +} diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/NamedFunctionDescriptorBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/NamedFunctionDescriptorBuilder.java index b3725cebd0..66840dd57e 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/NamedFunctionDescriptorBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/NamedFunctionDescriptorBuilder.java @@ -69,7 +69,7 @@ public class NamedFunctionDescriptorBuilder { return this; } - public NamedFunctionDescriptorBuilder setParameterTypes(ArgumentsValidator.ParameterType... types) { + public NamedFunctionDescriptorBuilder setParameterTypes(FunctionParameterType... types) { setArgumentsValidator( new ArgumentTypesValidator(argumentsValidator, types) ); return this; } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/PatternFunctionDescriptorBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/PatternFunctionDescriptorBuilder.java index 0133b251e8..a86ee52a77 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/PatternFunctionDescriptorBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/PatternFunctionDescriptorBuilder.java @@ -44,7 +44,7 @@ public class PatternFunctionDescriptorBuilder { return this; } - public PatternFunctionDescriptorBuilder setParameterTypes(ArgumentsValidator.ParameterType... types) { + public PatternFunctionDescriptorBuilder setParameterTypes(FunctionParameterType... types) { setArgumentsValidator( new ArgumentTypesValidator(argumentsValidator, types) ); return this; } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/StandardArgumentsValidators.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/StandardArgumentsValidators.java index 9a3e89cf24..09e8e6ba9d 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/StandardArgumentsValidators.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/StandardArgumentsValidators.java @@ -7,6 +7,7 @@ package org.hibernate.query.sqm.produce.function; import org.hibernate.QueryException; +import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.sqm.tree.SqmTypedNode; import java.util.Arrays; @@ -28,7 +29,7 @@ public final class StandardArgumentsValidators { */ public static final ArgumentsValidator NONE = new ArgumentsValidator() { @Override - public void validate(List> arguments, String functionName) {} + public void validate(List> arguments, String functionName, QueryEngine queryEngine) {} @Override public String getSignature() { @@ -41,7 +42,7 @@ public final class StandardArgumentsValidators { */ public static final ArgumentsValidator NO_ARGS = new ArgumentsValidator() { @Override - public void validate(List> arguments, String functionName) { + public void validate(List> arguments, String functionName, QueryEngine queryEngine) { if (!arguments.isEmpty()) { throw new QueryException( String.format( @@ -66,7 +67,7 @@ public final class StandardArgumentsValidators { } return new ArgumentsValidator() { @Override - public void validate(List> arguments, String functionName) { + public void validate(List> arguments, String functionName, QueryEngine queryEngine) { if (arguments.size() < minNumOfArgs) { throw new QueryException( String.format( @@ -100,7 +101,7 @@ public final class StandardArgumentsValidators { public static ArgumentsValidator exactly(int number) { return new ArgumentsValidator() { @Override - public void validate(List> arguments, String functionName) { + public void validate(List> arguments, String functionName, QueryEngine queryEngine) { if (arguments.size() != number) { throw new QueryException( String.format( @@ -136,7 +137,7 @@ public final class StandardArgumentsValidators { public static ArgumentsValidator max(int maxNumOfArgs) { return new ArgumentsValidator() { @Override - public void validate(List> arguments, String functionName) { + public void validate(List> arguments, String functionName, QueryEngine queryEngine) { if (arguments.size() > maxNumOfArgs) { throw new QueryException( String.format( @@ -168,7 +169,7 @@ public final class StandardArgumentsValidators { public static ArgumentsValidator between(int minNumOfArgs, int maxNumOfArgs) { return new ArgumentsValidator() { @Override - public void validate(List> arguments, String functionName) { + public void validate(List> arguments, String functionName, QueryEngine queryEngine) { if (arguments.size() < minNumOfArgs || arguments.size() > maxNumOfArgs) { throw new QueryException( String.format( @@ -202,7 +203,7 @@ public final class StandardArgumentsValidators { } public static ArgumentsValidator of(Class javaType) { - return (arguments, functionName) -> arguments.forEach( + return (arguments, functionName, queryEngine) -> arguments.forEach( arg -> { Class argType = arg.getNodeJavaTypeDescriptor().getJavaTypeClass(); if ( !javaType.isAssignableFrom( argType ) ) { @@ -225,8 +226,8 @@ public final class StandardArgumentsValidators { } public static ArgumentsValidator composite(List validators) { - return (arguments, functionName) -> validators.forEach( - individualValidator -> individualValidator.validate( arguments, functionName) + return (arguments, functionName, queryEngine) -> validators.forEach( + individualValidator -> individualValidator.validate( arguments, functionName, queryEngine) ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/FunctionTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/FunctionTests.java index 8f71c0da5e..77bd738374 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/FunctionTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/FunctionTests.java @@ -44,7 +44,7 @@ public class FunctionTests { public static final double ERROR = 0.00001d; - @BeforeAll + @BeforeAll @SuppressWarnings("deprecation") public void prepareData(SessionFactoryScope scope) { scope.inTransaction( em -> {