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
This commit is contained in:
Gavin King 2022-01-06 12:08:40 +01:00
parent 7178caea8d
commit aef951f279
47 changed files with 480 additions and 295 deletions

View File

@ -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;

View File

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

View File

@ -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;

View File

@ -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

View File

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

View File

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

View File

@ -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() ) {

View File

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

View File

@ -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 );

View File

@ -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();
}

View File

@ -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();
}

View File

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

View File

@ -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])");
}

View File

@ -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 ) ) {

View File

@ -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;

View File

@ -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();
}

View File

@ -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)";
}
}

View File

@ -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[, ...]])";
}
}

View File

@ -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 )
)

View File

@ -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 {

View File

@ -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();
}

View File

@ -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)";
}
}

View File

@ -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)";
}
}

View File

@ -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)";
}
}

View File

@ -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

View File

@ -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)";
}
}

View File

@ -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])";
}
}

View File

@ -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)";
}
}

View File

@ -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])";
}
}

View File

@ -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[, ...]])";
}
}

View File

@ -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

View File

@ -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)";
}
}

View File

@ -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",
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)";
}
}

View File

@ -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",
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)";
}
}

View File

@ -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)";
}
}

View File

@ -103,7 +103,7 @@ public abstract class AbstractSqmFunctionDescriptor implements SqmFunctionDescri
AllowableFunctionReturnType<T> 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<T> impliedResultType,
QueryEngine queryEngine,
TypeConfiguration typeConfiguration) {
argumentsValidator.validate( arguments, getName() );
argumentsValidator.validate( arguments, getName(), queryEngine );
return generateSqmAggregateFunctionExpression(
arguments,

View File

@ -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(

View File

@ -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<T> extends SelfRenderingSqmFuncti
walker.getCreationContext().getDomainModel().getTypeConfiguration()
);
List<SqlAstNode> arguments = resolveSqlAstArguments( getArguments(), walker );
ArgumentsValidator argumentsValidator = getArgumentsValidator();
if ( argumentsValidator != null ) {
argumentsValidator.validateSqlTypes( arguments, getFunctionName() );
}
return new SelfRenderingAggregateFunctionSqlAstExpression(
getFunctionName(),
getRenderingSupport(),

View File

@ -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<T> extends SqmFunction<T> {
return renderingSupport;
}
protected ArgumentsValidator getArgumentsValidator() {
return argumentsValidator;
}
protected static List<SqlAstNode> resolveSqlAstArguments(List<? extends SqmTypedNode<?>> sqmArguments, SqmToSqlAstConverter walker) {
if ( sqmArguments == null || sqmArguments.isEmpty() ) {
return emptyList();

View File

@ -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];

View File

@ -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<? extends SqmTypedNode<?>> arguments, String functionName) {
delegate.validate(arguments, functionName);
public void validate(List<? extends SqmTypedNode<?>> 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<? extends SqlAstNode> 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<JdbcMapping> 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<types.length; i++) {
String argName = types.length == 1 ? "arg" : "arg" + i;
sig = sig.replace(argName, types[i] + " " + argName);
}
return sig;
}
}

View File

@ -6,21 +6,30 @@
*/
package org.hibernate.query.sqm.produce.function;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.sql.ast.tree.SqlAstNode;
import java.util.List;
/**
* Validates the arguments provided to a HQL function invocation.
*
* @author Steve Ebersole
*
* @see StandardArgumentsValidators
* @see ArgumentTypesValidator
*/
public interface ArgumentsValidator {
/**
* Perform validation that may be done using the {@link SqmTypedNode}
* tree and assigned Java types.
*/
void validate(List<? extends SqmTypedNode<?>> arguments, String functionName);
void validate(List<? extends SqmTypedNode<?>> 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<? extends SqlAstNode> arguments, String functionName) {}
/**
* A mini-"type system" for HQL function parameters.
* <p>
* 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
}
}

View File

@ -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.
* <p>
* 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
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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<? extends SqmTypedNode<?>> arguments, String functionName) {}
public void validate(List<? extends SqmTypedNode<?>> 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<? extends SqmTypedNode<?>> arguments, String functionName) {
public void validate(List<? extends SqmTypedNode<?>> 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<? extends SqmTypedNode<?>> arguments, String functionName) {
public void validate(List<? extends SqmTypedNode<?>> 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<? extends SqmTypedNode<?>> arguments, String functionName) {
public void validate(List<? extends SqmTypedNode<?>> 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<? extends SqmTypedNode<?>> arguments, String functionName) {
public void validate(List<? extends SqmTypedNode<?>> 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<? extends SqmTypedNode<?>> arguments, String functionName) {
public void validate(List<? extends SqmTypedNode<?>> 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<ArgumentsValidator> validators) {
return (arguments, functionName) -> validators.forEach(
individualValidator -> individualValidator.validate( arguments, functionName)
return (arguments, functionName, queryEngine) -> validators.forEach(
individualValidator -> individualValidator.validate( arguments, functionName, queryEngine)
);
}
}

View File

@ -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 -> {