typecheck HQL function arguments
This commit is contained in:
parent
a73068cc0f
commit
cc91beb536
|
@ -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)" );
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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])");
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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])");
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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])");
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ) ) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 )
|
||||
)
|
||||
|
|
|
@ -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 )
|
||||
)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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,
|
||||
|
|
|
@ -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 )
|
||||
)
|
||||
|
|
|
@ -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 )
|
||||
)
|
||||
|
|
|
@ -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 )
|
||||
)
|
||||
|
|
|
@ -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 )
|
||||
)
|
||||
|
|
|
@ -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",
|
||||
new ArgumentTypesValidator(
|
||||
StandardArgumentsValidators.exactly( 2 ),
|
||||
ANY, TEMPORAL
|
||||
),
|
||||
StandardFunctionReturnTypeResolvers.useArgType( 1 )
|
||||
);
|
||||
this.dialect = dialect;
|
||||
|
|
|
@ -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",
|
||||
new ArgumentTypesValidator(
|
||||
StandardArgumentsValidators.between( 3, 4 ),
|
||||
STRING, INTEGER, INTEGER, STRING
|
||||
),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
|
||||
)
|
||||
|
|
|
@ -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",
|
||||
new ArgumentTypesValidator(
|
||||
StandardArgumentsValidators.between( 3, 4 ),
|
||||
STRING, INTEGER, ANY, STRING
|
||||
),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
|
||||
)
|
||||
|
|
|
@ -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 )
|
||||
)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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",
|
||||
new ArgumentTypesValidator(
|
||||
StandardArgumentsValidators.exactly( 3 ),
|
||||
ANY, STRING, STRING
|
||||
),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
|
||||
)
|
||||
|
|
|
@ -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,7 +135,6 @@ 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 impliedResultType the function return type as inferred from its usage
|
||||
*/
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -55,6 +55,7 @@ public class JdbcEscapeFunctionDescriptor
|
|||
},
|
||||
arguments,
|
||||
impliedResultType,
|
||||
getArgumentsValidator(),
|
||||
getReturnTypeResolver(),
|
||||
queryEngine.getCriteriaBuilder(),
|
||||
getName());
|
||||
|
|
|
@ -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 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,
|
||||
new ArgumentTypesValidator(
|
||||
StandardArgumentsValidators.between(
|
||||
first(functions),
|
||||
last(functions)
|
||||
),
|
||||
type
|
||||
parameterTypes
|
||||
),
|
||||
StandardFunctionReturnTypeResolvers.invariant( type )
|
||||
);
|
||||
this.functions = functions;
|
||||
}
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 )
|
||||
);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 ) );
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
||||
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";
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -61,6 +61,7 @@ public class OrderByFragmentFunction extends AbstractSqmFunctionDescriptor {
|
|||
null,
|
||||
arguments,
|
||||
impliedResultType,
|
||||
getArgumentsValidator(),
|
||||
getReturnTypeResolver(),
|
||||
queryEngine.getCriteriaBuilder(),
|
||||
getName()
|
||||
|
|
|
@ -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)
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue