typecheck HQL function arguments

This commit is contained in:
Gavin King 2022-01-05 16:07:37 +01:00
parent a73068cc0f
commit cc91beb536
47 changed files with 888 additions and 232 deletions

View File

@ -49,6 +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;
/**
* Dialect for Intersystems Caché SQL 2007.1 and above.
@ -169,7 +171,8 @@ public class CacheDialect extends Dialect {
"locate",
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
"$find(?2,?1)",
"$find(?2,?1,?3)"
"$find(?2,?1,?3)",
STRING, STRING, INTEGER
).setArgumentListSignature("(pattern, string[, start])");
CommonFunctionFactory.bitLength_pattern( queryEngine, "($length(?1)*8)" );

View File

@ -74,6 +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.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;
@ -280,7 +282,8 @@ public class FirebirdDialect extends Dialect {
"locate",
integerType,
"position(?1 in ?2)",
"position(?1,?2,?3)"
"position(?1,?2,?3)",
STRING, STRING, INTEGER
).setArgumentListSignature( "(pattern, string[, start])" );
functionRegistry.namedDescriptorBuilder( "ascii_val" )
.setExactArgumentCount( 1 )

View File

@ -60,6 +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;
/**
* Dialect for Informix 7.31.UD3 with Informix
@ -184,7 +186,8 @@ public class InformixDialect extends Dialect {
"locate",
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
"instr(?2,?1)",
"instr(?2,?1,?3)"
"instr(?2,?1,?3)",
STRING, STRING, INTEGER
).setArgumentListSignature("(pattern, string[, start])");
//coalesce() and nullif() both supported since Informix 12

View File

@ -61,6 +61,9 @@ 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;
/**
* An SQL dialect for Ingres 9.2.
* <p/>
@ -283,7 +286,8 @@ public class IngresDialect extends Dialect {
"locate",
integerType,
"position(?1 in ?2)",
"(position(?1 in substring(?2 from ?3))+(?3)-1)"
"(position(?1 in substring(?2 from ?3))+(?3)-1)",
STRING, STRING, INTEGER
).setArgumentListSignature("(pattern, string[, start])");
queryEngine.getSqmFunctionRegistry().registerPattern( "extract", "date_part('?1',?2)", integerType );

View File

@ -38,6 +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;
/**
* A SQL dialect compatible with SAP MaxDB.
@ -164,7 +166,8 @@ public class MaxDBDialect extends Dialect {
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"locate",
integerType, "index(?2,?1)", "index(?2,?1,?3)"
integerType, "index(?2,?1)", "index(?2,?1,?3)",
STRING, STRING, INTEGER
).setArgumentListSignature("(pattern, string[, start])");
}

View File

@ -66,6 +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.type.descriptor.DateTimeUtils.appendAsDate;
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTime;
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithMicros;
@ -271,24 +275,28 @@ public class SQLiteDialect extends Dialect {
"locate",
integerType,
"instr(?2,?1)",
"instr(?2,?1,?3)"
"instr(?2,?1,?3)",
STRING, STRING, INTEGER
).setArgumentListSignature("(pattern, string[, start])");
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"lpad",
stringType,
"(substr(replace(hex(zeroblob(?2)),'00',' '),1,?2-length(?1))||?1)",
"(substr(replace(hex(zeroblob(?2)),'00',?3),1,?2-length(?1))||?1)"
"(substr(replace(hex(zeroblob(?2)),'00',?3),1,?2-length(?1))||?1)",
STRING, INTEGER, STRING
).setArgumentListSignature("(string, length[, padding])");
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"rpad",
stringType,
"(?1||substr(replace(hex(zeroblob(?2)),'00',' '),1,?2-length(?1)))",
"(?1||substr(replace(hex(zeroblob(?2)),'00',?3),1,?2-length(?1)))"
"(?1||substr(replace(hex(zeroblob(?2)),'00',?3),1,?2-length(?1)))",
STRING, INTEGER, STRING
).setArgumentListSignature("(string, length[, padding])");
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder("format", "strftime")
.setInvariantType( stringType )
.setExactArgumentCount( 2 )
.setParameterTypes(TEMPORAL, STRING)
.setArgumentListSignature("(datetime as pattern)")
.register();
@ -298,12 +306,14 @@ public class SQLiteDialect extends Dialect {
"(cast(?1 as int)-(?1<cast(?1 as int)))"
).setReturnTypeResolver( StandardFunctionReturnTypeResolvers.useArgType( 1 ) )
.setExactArgumentCount( 1 )
.setParameterTypes(NUMERIC)
.register();
queryEngine.getSqmFunctionRegistry().patternDescriptorBuilder(
"ceiling",
"(cast(?1 as int)+(?1>cast(?1 as int)))"
).setReturnTypeResolver( StandardFunctionReturnTypeResolvers.useArgType( 1 ) )
.setExactArgumentCount( 1 )
.setParameterTypes(NUMERIC)
.register();
}
}

View File

@ -46,6 +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;
/**
* A SQL dialect for TimesTen 5.1.
@ -169,7 +171,8 @@ public class TimesTenDialect extends Dialect {
"locate",
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
"instr(?2,?1)",
"instr(?2,?1,?3)"
"instr(?2,?1,?3)",
STRING, STRING, INTEGER
).setArgumentListSignature("(pattern, string[, start])");
}

View File

@ -78,6 +78,8 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jakarta.persistence.TemporalType;
import static org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType;
/**
* An abstract base class for SAP HANA dialects.
* <p>
@ -279,7 +281,8 @@ public abstract class AbstractHANADialect extends Dialect {
"locate",
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
"locate(?2,?1)",
"locate(?2,?1,?3)"
"locate(?2,?1,?3)",
ParameterType.STRING, ParameterType.STRING, ParameterType.INTEGER
).setArgumentListSignature("(pattern, string[, start])");
CommonFunctionFactory.ceiling_ceil( queryEngine );

View File

@ -8,7 +8,6 @@ package org.hibernate.dialect;
import org.hibernate.LockOptions;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.function.DB2FormatEmulation;
import org.hibernate.dialect.identity.DB2IdentityColumnSupport;
@ -35,6 +34,8 @@ 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.service.ServiceRegistry;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator;
@ -196,6 +197,7 @@ 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]])" )
.register();
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "substring" )
@ -203,6 +205,7 @@ 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{ from|,} start[{ for|,} length[, units]])" )
.register();
CommonFunctionFactory.translate( queryEngine );
@ -238,13 +241,15 @@ public class DB2Dialect extends Dialect {
CommonFunctionFactory.dateTrunc( queryEngine );
CommonFunctionFactory.bitLength_pattern( queryEngine, "length(?1)*8" );
queryEngine.getSqmFunctionRegistry().register( "format", new DB2FormatEmulation( queryEngine.getTypeConfiguration() ) );
queryEngine.getSqmFunctionRegistry().register( "format",
new DB2FormatEmulation( queryEngine.getTypeConfiguration() ) );
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "posstr" )
.setInvariantType(
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER )
)
.setExactArgumentCount( 2 )
.setParameterTypes(ParameterType.STRING, ParameterType.STRING)
.setArgumentListSignature("(string, pattern)")
.register();
}

View File

@ -574,80 +574,6 @@ public abstract class Dialect implements ConversionContext {
: size;
}
/**
* Does the given JDBC type code represent some sort of
* numeric type?
* @param sqlType a JDBC type code from {@link Types}
*/
private static boolean isNumericType(int sqlType) {
switch (sqlType) {
case Types.BIT:
case Types.SMALLINT:
case Types.TINYINT:
case Types.INTEGER:
case Types.BIGINT:
case Types.DOUBLE:
case Types.REAL:
case Types.FLOAT:
case Types.NUMERIC:
case Types.DECIMAL:
return true;
default:
return false;
}
}
/**
* Does the given JDBC type code represent some sort of
* character string type?
* @param sqlType a JDBC type code from {@link Types}
*/
private static boolean isCharacterType(int sqlType) {
switch (sqlType) {
case Types.CHAR:
case Types.VARCHAR:
case Types.LONGVARCHAR:
case Types.NCHAR:
case Types.NVARCHAR:
case Types.LONGNVARCHAR:
return true;
default:
return false;
}
}
/**
* Does the given JDBC type code represent some sort of
* variable-length character string type?
* @param sqlType a JDBC type code from {@link Types}
*/
private static boolean isVarcharType(int sqlType) {
switch (sqlType) {
case Types.VARCHAR:
case Types.LONGVARCHAR:
case Types.NVARCHAR:
case Types.LONGNVARCHAR:
return true;
default:
return false;
}
}
/**
* Does the given JDBC type code represent some sort of
* variable-length binary string type?
* @param sqlType a JDBC type code from {@link Types}
*/
private static boolean isVarbinaryType(int sqlType) {
switch (sqlType) {
case Types.VARBINARY:
case Types.LONGVARBINARY:
return true;
default:
return false;
}
}
/**
* Render a SQL check condition for a column that represents a boolean value.
*/
@ -1305,24 +1231,6 @@ public abstract class Dialect implements ConversionContext {
|| isVarbinaryType(typeCode1) && isVarbinaryType(typeCode2);
}
private static boolean isNumericOrDecimal(int typeCode) {
return typeCode == Types.NUMERIC
|| typeCode == Types.DECIMAL;
}
private static boolean isFloatOrRealOrDouble(int typeCode) {
return typeCode == Types.FLOAT
|| typeCode == Types.REAL
|| typeCode == Types.DOUBLE;
}
private static boolean isIntegral(int typeCode) {
return typeCode == Types.INTEGER
|| typeCode == Types.BIGINT
|| typeCode == Types.SMALLINT
|| typeCode == Types.TINYINT;
}
/**
* Retrieve a set of default Hibernate properties for this database.
*

View File

@ -20,6 +20,8 @@ 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;
/**
* An SQL dialect for the SAP HANA column store.
* <p>
@ -112,7 +114,8 @@ public class HANAColumnStoreDialect extends AbstractHANADialect {
"contains",
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.BOOLEAN ),
"contains(?1,?2)",
"contains(?1,?2,?3)"
"contains(?1,?2,?3)",
ANY, ANY, ANY
);
}

View File

@ -87,6 +87,7 @@ 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 static org.hibernate.type.SqlTypes.*;
/**
@ -180,7 +181,8 @@ public class OracleDialect extends Dialect {
"locate",
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
"instr(?2,?1)",
"instr(?2,?1,?3)"
"instr(?2,?1,?3)",
ParameterType.STRING, ParameterType.STRING, ParameterType.INTEGER
).setArgumentListSignature("(pattern, string[, start])");
}

View File

@ -84,6 +84,7 @@ 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 static org.hibernate.type.SqlTypes.*;
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsDate;
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTime;
@ -451,7 +452,8 @@ public class PostgreSQLDialect extends Dialect {
"locate",
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
"position(?1 in ?2)",
"(position(?1 in substring(?2 from ?3))+(?3)-1)"
"(position(?1 in substring(?2 from ?3))+(?3)-1)",
ParameterType.STRING, ParameterType.STRING, ParameterType.INTEGER
).setArgumentListSignature("(pattern, string[, start])");
if ( getVersion().isSameOrAfter( 9, 4 ) ) {

View File

@ -68,6 +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.type.SqlTypes.*;
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsDate;
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTime;
@ -236,26 +237,32 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "datefromparts" )
.setInvariantType( dateType )
.setExactArgumentCount( 3 )
.setParameterTypes(INTEGER)
.register();
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "timefromparts" )
.setInvariantType( timeType )
.setExactArgumentCount( 5 )
.setParameterTypes(INTEGER)
.register();
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "smalldatetimefromparts" )
.setInvariantType( timestampType )
.setExactArgumentCount( 5 )
.setParameterTypes(INTEGER)
.register();
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "datetimefromparts" )
.setInvariantType( timestampType )
.setExactArgumentCount( 7 )
.setParameterTypes(INTEGER)
.register();
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "datetime2fromparts" )
.setInvariantType( timestampType )
.setExactArgumentCount( 8 )
.setParameterTypes(INTEGER)
.register();
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "datetimeoffsetfromparts" )
.setInvariantType( timestampType )
.setExactArgumentCount( 10 )
.setParameterTypes(INTEGER)
.register();
}
}

View File

@ -14,6 +14,7 @@ import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.CastType;
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.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
@ -27,6 +28,8 @@ 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;
/**
* @author Christian Beikov
*/
@ -45,7 +48,7 @@ public class AvgFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
super(
FUNCTION_NAME,
FunctionKind.AGGREGATE,
StandardArgumentsValidators.exactly( 1 ),
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 1 ), NUMERIC ),
StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.DOUBLE )
)

View File

@ -14,6 +14,8 @@ 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;
@ -26,6 +28,8 @@ 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;
public class CastingConcatFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
private final Dialect dialect;
@ -40,7 +44,7 @@ public class CastingConcatFunction extends AbstractSqmSelfRenderingFunctionDescr
TypeConfiguration typeConfiguration) {
super(
"concat",
StandardArgumentsValidators.min( 1 ),
new ArgumentTypesValidator( StandardArgumentsValidators.min( 1 ), STRING ),
StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
)

View File

@ -24,7 +24,7 @@ public class CurrentFunction
private final String sql;
public CurrentFunction(String name, String sql, BasicType type) {
public CurrentFunction(String name, String sql, BasicType<?> type) {
super(
name,
StandardArgumentsValidators.NO_ARGS,

View File

@ -7,8 +7,9 @@
package org.hibernate.dialect.function;
import org.hibernate.dialect.OracleDialect;
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.SqlAstTranslator;
@ -22,6 +23,9 @@ 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;
/**
* DB2's varchar_format() can't handle quoted literal strings in
* the format pattern. So just split the pattern into bits, call
@ -36,7 +40,7 @@ public class DB2FormatEmulation
public DB2FormatEmulation(TypeConfiguration typeConfiguration) {
super(
"format",
StandardArgumentsValidators.exactly( 2 ),
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), TEMPORAL, STRING ),
StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
)

View File

@ -10,6 +10,8 @@ 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;
@ -19,6 +21,9 @@ 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;
/**
* A derby implementation for lpad.
*
@ -30,7 +35,7 @@ public class DerbyLpadEmulation
public DerbyLpadEmulation(TypeConfiguration typeConfiguration) {
super(
"lpad",
StandardArgumentsValidators.exactly( 2 ),
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, INTEGER ),
StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
)

View File

@ -10,6 +10,7 @@ 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;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
@ -19,6 +20,9 @@ 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;
/**
* A derby implementation for rpad.
*
@ -30,7 +34,7 @@ public class DerbyRpadEmulation
public DerbyRpadEmulation(TypeConfiguration typeConfiguration) {
super(
"rpad",
StandardArgumentsValidators.exactly( 2 ),
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, INTEGER ),
StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
)

View File

@ -8,16 +8,11 @@ package org.hibernate.dialect.function;
import java.util.List;
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
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.tree.SqmTypedNode;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
@ -25,6 +20,8 @@ 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;
/**
* @author Jan Schatteman
*/
@ -36,7 +33,7 @@ public class EveryAnyEmulation extends AbstractSqmSelfRenderingFunctionDescripto
super(
every ? "every" : "any",
FunctionKind.AGGREGATE,
StandardArgumentsValidators.exactly( 1 ),
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 1 ), BOOLEAN ),
StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.BOOLEAN )
)

View File

@ -14,6 +14,8 @@ import org.hibernate.query.spi.QueryEngine;
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;
@ -27,6 +29,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.StandardFunctionReturnTypeResolvers.useArgType;
/**
@ -40,7 +44,10 @@ public class ExtractFunction
public ExtractFunction(Dialect dialect) {
super(
"extract",
StandardArgumentsValidators.exactly( 2 ),
new ArgumentTypesValidator(
StandardArgumentsValidators.exactly( 2 ),
ANY, TEMPORAL
),
StandardFunctionReturnTypeResolvers.useArgType( 1 )
);
this.dialect = dialect;

View File

@ -10,10 +10,10 @@ import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
import org.hibernate.query.BinaryArithmeticOperator;
import org.hibernate.query.ComparisonOperator;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.SqmExpressable;
import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
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.tree.SqmTypedNode;
@ -31,6 +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;
/**
* @author Gavin King
@ -43,7 +45,10 @@ public class InsertSubstringOverlayEmulation
public InsertSubstringOverlayEmulation(TypeConfiguration typeConfiguration, boolean strictSubstring) {
super(
"overlay",
StandardArgumentsValidators.between( 3, 4 ),
new ArgumentTypesValidator(
StandardArgumentsValidators.between( 3, 4 ),
STRING, INTEGER, INTEGER, STRING
),
StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
)

View File

@ -11,6 +11,7 @@ import org.hibernate.query.TrimSpec;
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.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.tree.SqmTypedNode;
@ -21,6 +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;
/**
* @author Gavin King
@ -31,7 +35,10 @@ public class LpadRpadPadEmulation
public LpadRpadPadEmulation(TypeConfiguration typeConfiguration) {
super(
"pad",
StandardArgumentsValidators.between( 3, 4 ),
new ArgumentTypesValidator(
StandardArgumentsValidators.between( 3, 4 ),
STRING, INTEGER, ANY, STRING
),
StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
)

View File

@ -10,6 +10,7 @@ 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.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.SqlAstTranslator;
@ -19,6 +20,8 @@ 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;
/**
* @author Jan Schatteman
*/
@ -30,7 +33,7 @@ public class SQLServerEveryAnyEmulation extends AbstractSqmSelfRenderingFunction
super(
every ? "every" : "any",
FunctionKind.AGGREGATE,
StandardArgumentsValidators.exactly( 1 ),
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 1 ), BOOLEAN ),
StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.BOOLEAN )
)

View File

@ -46,7 +46,12 @@ public class TransactSQLStrFunction extends CastStrEmulation implements Function
QueryEngine queryEngine,
TypeConfiguration typeConfiguration) {
if ( arguments.size() == 1 ) {
return super.generateSqmFunctionExpression( arguments, impliedResultType, queryEngine, typeConfiguration );
return super.generateSqmFunctionExpression(
arguments,
impliedResultType,
queryEngine,
typeConfiguration
);
}
return new SelfRenderingSqmFunction<>(
@ -54,6 +59,7 @@ public class TransactSQLStrFunction extends CastStrEmulation implements Function
this,
arguments,
impliedResultType,
getArgumentsValidator(),
getReturnTypeResolver(),
queryEngine.getCriteriaBuilder(),
getName()

View File

@ -8,8 +8,8 @@ package org.hibernate.dialect.function;
import org.hibernate.dialect.Dialect;
import org.hibernate.query.TrimSpec;
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;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
@ -25,6 +25,9 @@ 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;
/**
* @author Gavin King
*/
@ -35,7 +38,10 @@ public class TrimFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
public TrimFunction(Dialect dialect, TypeConfiguration typeConfiguration) {
super(
"trim",
StandardArgumentsValidators.exactly( 3 ),
new ArgumentTypesValidator(
StandardArgumentsValidators.exactly( 3 ),
ANY, STRING, STRING
),
StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
)

View File

@ -65,6 +65,11 @@ public abstract class AbstractSqmFunctionDescriptor implements SqmFunctionDescri
return getReturnSignature() + name + getArgumentListSignature();
}
@Override
public ArgumentsValidator getArgumentsValidator() {
return argumentsValidator;
}
public String getReturnSignature() {
String result = returnTypeResolver.getReturnType();
return result.isEmpty() ? "" : result + " ";
@ -98,7 +103,7 @@ public abstract class AbstractSqmFunctionDescriptor implements SqmFunctionDescri
AllowableFunctionReturnType<T> impliedResultType,
QueryEngine queryEngine,
TypeConfiguration typeConfiguration) {
argumentsValidator.validate( arguments );
argumentsValidator.validate( arguments, getName() );
return generateSqmFunctionExpression(
arguments,
@ -115,7 +120,7 @@ public abstract class AbstractSqmFunctionDescriptor implements SqmFunctionDescri
AllowableFunctionReturnType<T> impliedResultType,
QueryEngine queryEngine,
TypeConfiguration typeConfiguration) {
argumentsValidator.validate( arguments );
argumentsValidator.validate( arguments, getName() );
return generateSqmAggregateFunctionExpression(
arguments,
@ -130,8 +135,7 @@ public abstract class AbstractSqmFunctionDescriptor implements SqmFunctionDescri
* Return an SQM node or subtree representing an invocation of this function
* with the given arguments. This method may be overridden in the case of
* function descriptors that wish to customize creation of the node.
*
* @param arguments the arguments of the function invocation
* @param arguments the arguments of the function invocation
* @param impliedResultType the function return type as inferred from its usage
*/
protected abstract <T> SelfRenderingSqmFunction<T> generateSqmFunctionExpression(

View File

@ -64,6 +64,7 @@ public abstract class AbstractSqmSelfRenderingFunctionDescriptor
this::render,
arguments,
impliedResultType,
getArgumentsValidator(),
getReturnTypeResolver(),
queryEngine.getCriteriaBuilder(),
getName()
@ -86,6 +87,7 @@ public abstract class AbstractSqmSelfRenderingFunctionDescriptor
arguments,
filter,
impliedResultType,
getArgumentsValidator(),
getReturnTypeResolver(),
queryEngine.getCriteriaBuilder(),
getName()

View File

@ -55,6 +55,7 @@ public class JdbcEscapeFunctionDescriptor
},
arguments,
impliedResultType,
getArgumentsValidator(),
getReturnTypeResolver(),
queryEngine.getCriteriaBuilder(),
getName());

View File

@ -8,9 +8,12 @@ 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.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator.ParameterType;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.type.BasicType;
import org.hibernate.type.spi.TypeConfiguration;
import java.util.List;
@ -48,21 +51,25 @@ public class MultipatternSqmFunctionDescriptor extends AbstractSqmFunctionDescri
* template. The array must be padded with leading nulls
* where there is no overloaded form corresponding to
* lower arities.
*
* @param name
* @param name
* @param functions the function templates to delegate to,
* where array position corresponds to
* @param type
*/
public MultipatternSqmFunctionDescriptor(
String name, SqmFunctionDescriptor[] functions,
FunctionReturnTypeResolver type) {
String name,
SqmFunctionDescriptor[] functions,
BasicType<?> type,
ParameterType... parameterTypes) {
super(
name,
StandardArgumentsValidators.between(
first(functions),
last(functions)
new ArgumentTypesValidator(
StandardArgumentsValidators.between(
first(functions),
last(functions)
),
parameterTypes
),
type
StandardFunctionReturnTypeResolvers.invariant( type )
);
this.functions = functions;
}

View File

@ -21,6 +21,7 @@ import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
@ -188,8 +189,7 @@ public class SelfRenderingFunctionSqlAstExpression
}
@Override
public int forEachJdbcType(
int offset, IndexedConsumer<JdbcMapping> action) {
public int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action) {
throw new NotYetImplementedFor6Exception( getClass() );
}
}

View File

@ -10,6 +10,7 @@ import java.util.List;
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;
@ -34,10 +35,11 @@ public class SelfRenderingSqmAggregateFunction<T> extends SelfRenderingSqmFuncti
List<? extends SqmTypedNode<?>> arguments,
SqmPredicate filter,
AllowableFunctionReturnType<T> impliedResultType,
ArgumentsValidator argumentsValidator,
FunctionReturnTypeResolver returnTypeResolver,
NodeBuilder nodeBuilder,
String name) {
super( descriptor, renderingSupport, arguments, impliedResultType, returnTypeResolver, nodeBuilder, name );
super( descriptor, renderingSupport, arguments, impliedResultType, argumentsValidator, returnTypeResolver, nodeBuilder, name );
this.filter = filter;
}

View File

@ -11,16 +11,19 @@ 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;
import org.hibernate.query.sqm.SqmExpressable;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
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;
@ -30,6 +33,7 @@ import static java.util.Collections.emptyList;
*/
public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
private final AllowableFunctionReturnType<T> impliedResultType;
private final ArgumentsValidator argumentsValidator;
private final FunctionReturnTypeResolver returnTypeResolver;
private final FunctionRenderingSupport renderingSupport;
private AllowableFunctionReturnType<?> resultType;
@ -39,12 +43,14 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
FunctionRenderingSupport renderingSupport,
List<? extends SqmTypedNode<?>> arguments,
AllowableFunctionReturnType<T> impliedResultType,
ArgumentsValidator argumentsValidator,
FunctionReturnTypeResolver returnTypeResolver,
NodeBuilder nodeBuilder,
String name) {
super( name, descriptor, impliedResultType, arguments, nodeBuilder );
this.renderingSupport = renderingSupport;
this.impliedResultType = impliedResultType;
this.argumentsValidator = argumentsValidator;
this.returnTypeResolver = returnTypeResolver;
}
@ -70,10 +76,14 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
walker.getCreationContext().getDomainModel().getTypeConfiguration()
);
List<SqlAstNode> arguments = resolveSqlAstArguments( getArguments(), walker );
if ( argumentsValidator != null ) {
argumentsValidator.validateSqlTypes( arguments, getFunctionName() );
}
return new SelfRenderingFunctionSqlAstExpression(
getFunctionName(),
getRenderingSupport(),
resolveSqlAstArguments( getArguments(), walker ),
arguments,
resultType,
resultType == null ? null : getMappingModelExpressable( walker, resultType )
);

View File

@ -8,6 +8,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.ArgumentsValidator;
import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
import org.hibernate.type.spi.TypeConfiguration;
@ -122,4 +123,6 @@ public interface SqmFunctionDescriptor {
default FunctionKind getFunctionKind() {
return FunctionKind.NORMAL;
}
ArgumentsValidator getArgumentsValidator();
}

View File

@ -11,9 +11,9 @@ 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.NamedFunctionDescriptorBuilder;
import org.hibernate.query.sqm.produce.function.PatternFunctionDescriptorBuilder;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.type.BasicType;
import org.jboss.logging.Logger;
@ -254,8 +254,9 @@ public class SqmFunctionRegistry {
String name,
BasicType type,
String pattern0,
String pattern1) {
return registerPatterns( name, type, pattern0, pattern1 );
String pattern1,
ParameterType parameterType) {
return registerPatterns( name, type, new ParameterType[]{parameterType}, pattern0, pattern1 );
}
/**
@ -265,10 +266,14 @@ public class SqmFunctionRegistry {
*/
public MultipatternSqmFunctionDescriptor registerUnaryBinaryPattern(
String name,
BasicType type,
BasicType<?> type,
String pattern1,
String pattern2) {
return registerPatterns( name, type, null, pattern1, pattern2 );
String pattern2,
ParameterType parameterType1,
ParameterType parameterType2) {
return registerPatterns( name, type,
new ParameterType[]{parameterType1,parameterType2},
null, pattern1, pattern2 );
}
/**
@ -278,10 +283,15 @@ public class SqmFunctionRegistry {
*/
public MultipatternSqmFunctionDescriptor registerBinaryTernaryPattern(
String name,
BasicType type,
BasicType<?> type,
String pattern2,
String pattern3) {
return registerPatterns( name, type, null, null, pattern2, pattern3 );
String pattern3,
ParameterType parameterType1,
ParameterType parameterType2,
ParameterType parameterType3) {
return registerPatterns( name, type,
new ParameterType[]{parameterType1,parameterType2,parameterType3},
null, null, pattern2, pattern3 );
}
/**
@ -291,15 +301,22 @@ public class SqmFunctionRegistry {
*/
public MultipatternSqmFunctionDescriptor registerTernaryQuaternaryPattern(
String name,
BasicType type,
BasicType<?> type,
String pattern3,
String pattern4) {
return registerPatterns( name, type, null, null, null, pattern3, pattern4 );
String pattern4,
ParameterType parameterType1,
ParameterType parameterType2,
ParameterType parameterType3,
ParameterType parameterType4) {
return registerPatterns( name, type,
new ParameterType[]{parameterType1,parameterType2,parameterType3, parameterType4},
null, null, null, pattern3, pattern4 );
}
private MultipatternSqmFunctionDescriptor registerPatterns(
String name,
BasicType type,
BasicType<?> type,
ParameterType[] parameterTypes,
String... patterns) {
SqmFunctionDescriptor[] descriptors =
new SqmFunctionDescriptor[patterns.length];
@ -309,15 +326,14 @@ public class SqmFunctionRegistry {
descriptors[i] =
patternDescriptorBuilder( name, pattern )
.setExactArgumentCount( i )
.setParameterTypes( parameterTypes )
.setInvariantType( type )
.descriptor();
}
}
MultipatternSqmFunctionDescriptor function = new MultipatternSqmFunctionDescriptor(
name, descriptors,
StandardFunctionReturnTypeResolvers.invariant( type )
);
MultipatternSqmFunctionDescriptor function =
new MultipatternSqmFunctionDescriptor( name, descriptors, type, parameterTypes );
register( name, function );
return function;
}

View File

@ -0,0 +1,134 @@
/*
* 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;
import org.hibernate.QueryException;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.query.sqm.tree.SqmTypedNode;
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 java.lang.reflect.Type;
import java.util.List;
import static org.hibernate.type.SqlTypes.*;
/**
* Typechecks the arguments of HQL functions based on the assigned JDBC types.
*/
public class ArgumentTypesValidator implements ArgumentsValidator {
final ArgumentsValidator delegate;
private final ParameterType[] types;
public ArgumentTypesValidator(ArgumentsValidator delegate, ParameterType... types) {
this.types = types;
if (types.length==0) {
System.out.println();
}
if (delegate == null ) {
delegate = StandardArgumentsValidators.exactly(types.length);
}
this.delegate = delegate;
}
@Override
public void validate(List<? extends SqmTypedNode<?>> arguments, String functionName) {
delegate.validate(arguments, functionName);
}
@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);
if (argument instanceof Expression) {
JdbcMappingContainer expressionType = ((Expression) argument).getExpressionType();
if ( expressionType != null ) {
ParameterDetector detector = new ParameterDetector();
argument.accept(detector);
if ( detector.detected ) {
count += expressionType.getJdbcTypeCount();
}
else {
count = validateArgument(count, expressionType, functionName);
}
}
}
}
}
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];
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;
}
}
}
return count;
}
private void throwError(ParameterType 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",
count,
functionName,
type,
javaType.getTypeName()
)
);
}
private static class ParameterDetector extends AbstractSqlAstWalker {
private boolean detected;
@Override
public void visitParameter(JdbcParameter jdbcParameter) {
detected = true;
}
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.query.sqm.produce.function;
import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.sql.ast.tree.SqlAstNode;
import java.util.List;
@ -15,12 +16,62 @@ import java.util.List;
*/
public interface ArgumentsValidator {
/**
* The main (functional) operation defining validation
* Perform validation that may be done using the {@link SqmTypedNode}
* tree and assigned Java types.
*/
void validate(List<? extends SqmTypedNode<?>> arguments);
void validate(List<? extends SqmTypedNode<?>> arguments, String functionName);
default String getSignature() {
return "( ... )";
}
/**
* Perform validation that requires the {@link SqlAstNode} tree and
* assigned JDBC types.
*/
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

@ -64,11 +64,16 @@ public class NamedFunctionDescriptorBuilder {
return this;
}
public NamedFunctionDescriptorBuilder setInvariantType(BasicType invariantType) {
public NamedFunctionDescriptorBuilder setInvariantType(BasicType<?> invariantType) {
setReturnTypeResolver( StandardFunctionReturnTypeResolvers.invariant( invariantType ) );
return this;
}
public NamedFunctionDescriptorBuilder setParameterTypes(ArgumentsValidator.ParameterType... types) {
setArgumentsValidator( new ArgumentTypesValidator(argumentsValidator, types) );
return this;
}
public NamedFunctionDescriptorBuilder setUseParenthesesWhenNoArgs(boolean useParenthesesWhenNoArgs) {
this.useParenthesesWhenNoArgs = useParenthesesWhenNoArgs;
return this;
@ -100,4 +105,5 @@ public class NamedFunctionDescriptorBuilder {
argumentRenderingMode
);
}
}

View File

@ -44,6 +44,15 @@ public class PatternFunctionDescriptorBuilder {
return this;
}
public PatternFunctionDescriptorBuilder setParameterTypes(ArgumentsValidator.ParameterType... types) {
setArgumentsValidator( new ArgumentTypesValidator(argumentsValidator, types) );
return this;
}
public PatternFunctionDescriptorBuilder setMinArgumentCount(int min) {
return setArgumentsValidator( StandardArgumentsValidators.min( min ) );
}
public PatternFunctionDescriptorBuilder setExactArgumentCount(int exactArgumentCount) {
return setArgumentsValidator( StandardArgumentsValidators.exactly( exactArgumentCount ) );
}

View File

@ -28,7 +28,7 @@ public final class StandardArgumentsValidators {
*/
public static final ArgumentsValidator NONE = new ArgumentsValidator() {
@Override
public void validate(List<? extends SqmTypedNode<?>> arguments) {}
public void validate(List<? extends SqmTypedNode<?>> arguments, String functionName) {}
@Override
public String getSignature() {
@ -41,9 +41,16 @@ public final class StandardArgumentsValidators {
*/
public static final ArgumentsValidator NO_ARGS = new ArgumentsValidator() {
@Override
public void validate(List<? extends SqmTypedNode<?>> arguments) {
public void validate(List<? extends SqmTypedNode<?>> arguments, String functionName) {
if (!arguments.isEmpty()) {
throw new QueryException("Expecting no arguments, but found " + arguments.size());
throw new QueryException(
String.format(
Locale.ROOT,
"Function %s has no parameters, but %d arguments given",
functionName,
arguments.size()
)
);
}
}
@ -59,12 +66,13 @@ public final class StandardArgumentsValidators {
}
return new ArgumentsValidator() {
@Override
public void validate(List<? extends SqmTypedNode<?>> arguments) {
public void validate(List<? extends SqmTypedNode<?>> arguments, String functionName) {
if (arguments.size() < minNumOfArgs) {
throw new QueryException(
String.format(
Locale.ROOT,
"Function requires %d or more arguments, but only %d found",
"Function %s() requires at least %d arguments, but only %d arguments given",
functionName,
minNumOfArgs,
arguments.size()
)
@ -92,12 +100,13 @@ public final class StandardArgumentsValidators {
public static ArgumentsValidator exactly(int number) {
return new ArgumentsValidator() {
@Override
public void validate(List<? extends SqmTypedNode<?>> arguments) {
public void validate(List<? extends SqmTypedNode<?>> arguments, String functionName) {
if (arguments.size() != number) {
throw new QueryException(
String.format(
Locale.ROOT,
"Function requires %d arguments, but %d found",
"Function %s() has %d parameters, but %d arguments given",
functionName,
number,
arguments.size()
)
@ -127,12 +136,13 @@ public final class StandardArgumentsValidators {
public static ArgumentsValidator max(int maxNumOfArgs) {
return new ArgumentsValidator() {
@Override
public void validate(List<? extends SqmTypedNode<?>> arguments) {
public void validate(List<? extends SqmTypedNode<?>> arguments, String functionName) {
if (arguments.size() > maxNumOfArgs) {
throw new QueryException(
String.format(
Locale.ROOT,
"Function requires %d or fewer arguments, but %d found",
"Function %s() allows at most %d arguments, but %d arguments given",
functionName,
maxNumOfArgs,
arguments.size()
)
@ -158,12 +168,13 @@ public final class StandardArgumentsValidators {
public static ArgumentsValidator between(int minNumOfArgs, int maxNumOfArgs) {
return new ArgumentsValidator() {
@Override
public void validate(List<? extends SqmTypedNode<?>> arguments) {
public void validate(List<? extends SqmTypedNode<?>> arguments, String functionName) {
if (arguments.size() < minNumOfArgs || arguments.size() > maxNumOfArgs) {
throw new QueryException(
String.format(
Locale.ROOT,
"Function requires between %d and %d arguments, but %d found",
"Function %s() requires between %d and %d arguments, but %d arguments given",
functionName,
minNumOfArgs,
maxNumOfArgs,
arguments.size()
@ -191,14 +202,15 @@ public final class StandardArgumentsValidators {
}
public static ArgumentsValidator of(Class<?> javaType) {
return arguments -> arguments.forEach(
return (arguments, functionName) -> arguments.forEach(
arg -> {
Class<?> argType = arg.getNodeJavaTypeDescriptor().getJavaTypeClass();
if ( !javaType.isAssignableFrom( argType ) ) {
throw new QueryException(
String.format(
Locale.ROOT,
"Function expects arguments to be of type %s, but %s found",
"Function %s() has parameters of type %s, but argument of type %s given",
functionName,
javaType.getName(),
argType.getName()
)
@ -213,8 +225,8 @@ public final class StandardArgumentsValidators {
}
public static ArgumentsValidator composite(List<ArgumentsValidator> validators) {
return arguments -> validators.forEach(
individualValidator -> individualValidator.validate( arguments )
return (arguments, functionName) -> validators.forEach(
individualValidator -> individualValidator.validate( arguments, functionName)
);
}
}

View File

@ -452,4 +452,139 @@ public class SqlTypes {
private SqlTypes() {
}
/**
* Does the given JDBC type code represent some sort of
* numeric type?
* @param sqlType a JDBC type code from {@link Types}
*/
public static boolean isNumericType(int sqlType) {
switch (sqlType) {
case Types.BIT:
case Types.SMALLINT:
case Types.TINYINT:
case Types.INTEGER:
case Types.BIGINT:
case Types.DOUBLE:
case Types.REAL:
case Types.FLOAT:
case Types.NUMERIC:
case Types.DECIMAL:
return true;
default:
return false;
}
}
/**
* Does the given JDBC type code represent some sort of
* character string type?
* @param sqlType a JDBC type code from {@link Types}
*/
public static boolean isCharacterType(int sqlType) {
switch (sqlType) {
case Types.CHAR:
case Types.VARCHAR:
case Types.LONGVARCHAR:
case Types.NCHAR:
case Types.NVARCHAR:
case Types.LONGNVARCHAR:
return true;
default:
return false;
}
}
/**
* Does the given JDBC type code represent some sort of
* variable-length character string type?
* @param sqlType a JDBC type code from {@link Types}
*/
public static boolean isVarcharType(int sqlType) {
switch (sqlType) {
case Types.VARCHAR:
case Types.LONGVARCHAR:
case Types.NVARCHAR:
case Types.LONGNVARCHAR:
return true;
default:
return false;
}
}
/**
* Does the given JDBC type code represent some sort of
* variable-length binary string type?
* @param sqlType a JDBC type code from {@link Types}
*/
public static boolean isVarbinaryType(int sqlType) {
switch (sqlType) {
case Types.VARBINARY:
case Types.LONGVARBINARY:
return true;
default:
return false;
}
}
/**
* Does the given typecode represent one of the two SQL decimal types?
* @param typeCode a JDBC type code from {@link Types}
*/
public static boolean isNumericOrDecimal(int typeCode) {
return typeCode == NUMERIC
|| typeCode == DECIMAL;
}
/**
* Does the given typecode represent a SQL floating point type?
* @param typeCode a JDBC type code from {@link Types}
*/
public static boolean isFloatOrRealOrDouble(int typeCode) {
return typeCode == FLOAT
|| typeCode == REAL
|| typeCode == DOUBLE;
}
/**
* Does the given typecode represent a SQL integer type?
* @param typeCode a JDBC type code from {@link Types}
*/
public static boolean isIntegral(int typeCode) {
return typeCode == INTEGER
|| typeCode == BIGINT
|| typeCode == SMALLINT
|| typeCode == TINYINT;
}
/**
* Does the given typecode represent a SQL date, time, or timestamp type?
* @param typeCode a JDBC type code from {@link Types}
*/
public static boolean isTemporalType(int typeCode) {
return typeCode == DATE
|| typeCode == TIME
|| typeCode == TIMESTAMP
|| typeCode == TIMESTAMP_WITH_TIMEZONE;
}
/**
* Does the given typecode represent a SQL date or timestamp type?
* @param typeCode a JDBC type code from {@link Types}
*/
public static boolean hasDatePart(int typeCode) {
return typeCode == DATE
|| typeCode == TIMESTAMP
|| typeCode == TIMESTAMP_WITH_TIMEZONE;
}
/**
* Does the given typecode represent a SQL time or timestamp type?
* @param typeCode a JDBC type code from {@link Types}
*/
public static boolean hasTimePart(int typeCode) {
return typeCode == TIME
|| typeCode == TIMESTAMP
|| typeCode == TIMESTAMP_WITH_TIMEZONE;
}
}

View File

@ -35,10 +35,7 @@ import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.loader.MultipleBagFetchException;
@ -300,8 +297,8 @@ public class ASTParserLoadingTest extends BaseCoreFunctionalTestCase {
inTransaction(
(session) -> {
final String qry = "select new Constructor( c.id, c.id is not null, c.id = c.id, c.id + 1, concat( c.id, 'foo' ) ) from Constructor c where c.id = :id";
final Constructor result = (Constructor) session.createQuery(qry ).setParameter( "id", created.getId() ).uniqueResult();
final String qry = "select new Constructor( c.id, c.id is not null, c.id = c.id, c.id + 1, concat( str(c.id), 'foo' ) ) from Constructor c where c.id = :id";
final Constructor result = session.createQuery(qry, Constructor.class).setParameter( "id", created.getId() ).uniqueResult();
assertEquals( 1, Constructor.getConstructorExecutionCount() );
Constructor expected = new Constructor(
created.getId(),
@ -3697,29 +3694,11 @@ public class ASTParserLoadingTest extends BaseCoreFunctionalTestCase {
hql = "from Animal a where mod(16, 4) = 4";
session.createQuery(hql).list();
/**
* PostgreSQL >= 8.3.7 typecasts are no longer automatically allowed
* <link>http://www.postgresql.org/docs/current/static/release-8-3.html</link>
*/
if ( getDialect() instanceof PostgreSQLDialect
|| getDialect() instanceof HSQLDialect
|| getDialect() instanceof CockroachDialect ) {
hql = "from Animal a where bit_length(str(a.bodyWeight)) = 24";
}
else {
hql = "from Animal a where bit_length(a.bodyWeight) = 24";
}
hql = "from Animal a where bit_length(str(a.bodyWeight)) = 24";
session.createQuery(hql).list();
if ( getDialect() instanceof PostgreSQLDialect
|| getDialect() instanceof HSQLDialect
|| getDialect() instanceof CockroachDialect ) {
hql = "select bit_length(str(a.bodyWeight)) from Animal a";
}
else {
hql = "select bit_length(a.bodyWeight) from Animal a";
}
hql = "select bit_length(str(a.bodyWeight)) from Animal a";
session.createQuery(hql).list();
/*hql = "select object(a) from Animal a where CURRENT_DATE = :p1 or CURRENT_TIME = :p2 or CURRENT_TIMESTAMP = :p3";

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.orm.test.query.hql;
import org.hibernate.QueryException;
import org.hibernate.dialect.DerbyDialect;
import org.hibernate.testing.orm.domain.StandardDomainModel;
@ -29,12 +30,9 @@ import java.time.LocalTime;
import org.hamcrest.Matchers;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.CoreMatchers.startsWith;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.fail;
/**
* @author Gavin King
@ -206,6 +204,19 @@ public class FunctionTests {
assertThat( session.createQuery("select upper('hello')").getSingleResult(), is("HELLO") );
}
);
try {
scope.inTransaction(
session -> {
session.createQuery("select upper(3)")
.list();
}
);
fail();
}
catch (IllegalArgumentException e) {
assertThat( e.getCause(), is(instanceOf(QueryException.class)) );
}
}
@Test
@ -217,6 +228,19 @@ public class FunctionTests {
assertThat( session.createQuery("select length('hello')").getSingleResult(), is(5) );
}
);
try {
scope.inTransaction(
session -> {
session.createQuery("select length(3)")
.list();
}
);
fail();
}
catch (IllegalArgumentException e) {
assertThat( e.getCause(), is(instanceOf(QueryException.class)) );
}
}
@Test
@ -234,6 +258,19 @@ public class FunctionTests {
assertThat( session.createQuery("select substring('hello world',4, 5)").getSingleResult(), is("lo wo") );
}
);
try {
scope.inTransaction(
session -> {
session.createQuery("select substring('hello world', 'world', 5)")
.list();
}
);
fail();
}
catch (IllegalArgumentException e) {
assertThat( e.getCause(), is(instanceOf(QueryException.class)) );
}
}
@Test
@ -324,6 +361,19 @@ public class FunctionTests {
assertThat( session.createQuery("select replace('hello world', 'o', 'ooo')").getSingleResult(), is("hellooo wooorld") );
}
);
try {
scope.inTransaction(
session -> {
session.createQuery("select replace(e.theString, 1, 'goodbye') from EntityOfBasics e")
.list();
}
);
fail();
}
catch (IllegalArgumentException e) {
assertThat( e.getCause(), is(instanceOf(QueryException.class)) );
}
}
@Test
@ -342,6 +392,19 @@ public class FunctionTests {
assertThat( session.createQuery("select trim(both '-' from '---hello---')").getSingleResult(), is("hello") );
}
);
try {
scope.inTransaction(
session -> {
session.createQuery("select trim(leading ' ' from 3)")
.list();
}
);
fail();
}
catch (IllegalArgumentException e) {
assertThat( e.getCause(), is(instanceOf(QueryException.class)) );
}
}
@Test
@ -359,6 +422,31 @@ public class FunctionTests {
is("hello....."));
}
);
try {
scope.inTransaction(
session -> {
session.createQuery("select pad('hello' with ' ' leading)")
.list();
}
);
fail();
}
catch (IllegalArgumentException e) {
assertThat( e.getCause(), is(instanceOf(QueryException.class)) );
}
try {
scope.inTransaction(
session -> {
session.createQuery("select pad(3 with 4 leading)")
.list();
}
);
fail();
}
catch (IllegalArgumentException e) {
assertThat( e.getCause(), is(instanceOf(QueryException.class)) );
}
}
@Test

View File

@ -61,6 +61,7 @@ public class OrderByFragmentFunction extends AbstractSqmFunctionDescriptor {
null,
arguments,
impliedResultType,
getArgumentsValidator(),
getReturnTypeResolver(),
queryEngine.getCriteriaBuilder(),
getName()

View File

@ -16,6 +16,7 @@ import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
import org.hibernate.type.BasicTypeReference;
@ -53,6 +54,11 @@ class SDOObjectProperty implements SqmFunctionDescriptor {
return true;
}
@Override
public ArgumentsValidator getArgumentsValidator() {
return null;
}
/*
* (non-Javadoc)
*