HHH-10463 Implement function argument type inference

This commit is contained in:
Christian Beikov 2022-02-10 13:25:17 +01:00
parent 260c738a5a
commit dc6ad33cfc
69 changed files with 820 additions and 213 deletions

View File

@ -173,7 +173,8 @@ public class CacheDialect extends Dialect {
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ), queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
"$find(?2,?1)", "$find(?2,?1)",
"$find(?2,?1,?3)", "$find(?2,?1,?3)",
STRING, STRING, INTEGER STRING, STRING, INTEGER,
queryEngine.getTypeConfiguration()
).setArgumentListSignature("(pattern, string[, start])"); ).setArgumentListSignature("(pattern, string[, start])");
functionFactory.bitLength_pattern( "($length(?1)*8)" ); functionFactory.bitLength_pattern( "($length(?1)*8)" );

View File

@ -284,7 +284,8 @@ public class FirebirdDialect extends Dialect {
integerType, integerType,
"position(?1 in ?2)", "position(?1 in ?2)",
"position(?1,?2,?3)", "position(?1,?2,?3)",
STRING, STRING, INTEGER STRING, STRING, INTEGER,
queryEngine.getTypeConfiguration()
).setArgumentListSignature( "(pattern, string[, start])" ); ).setArgumentListSignature( "(pattern, string[, start])" );
functionRegistry.namedDescriptorBuilder( "ascii_val" ) functionRegistry.namedDescriptorBuilder( "ascii_val" )
.setExactArgumentCount( 1 ) .setExactArgumentCount( 1 )

View File

@ -288,7 +288,8 @@ public class IngresDialect extends Dialect {
integerType, integerType,
"position(?1 in ?2)", "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 STRING, STRING, INTEGER,
queryEngine.getTypeConfiguration()
).setArgumentListSignature("(pattern, string[, start])"); ).setArgumentListSignature("(pattern, string[, start])");
queryEngine.getSqmFunctionRegistry().registerPattern( "extract", "date_part('?1',?2)", integerType ); queryEngine.getSqmFunctionRegistry().registerPattern( "extract", "date_part('?1',?2)", integerType );

View File

@ -168,7 +168,8 @@ public class MaxDBDialect extends Dialect {
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"locate", "locate",
integerType, "index(?2,?1)", "index(?2,?1,?3)", integerType, "index(?2,?1)", "index(?2,?1,?3)",
STRING, STRING, INTEGER STRING, STRING, INTEGER,
queryEngine.getTypeConfiguration()
).setArgumentListSignature("(pattern, string[, start])"); ).setArgumentListSignature("(pattern, string[, start])");
} }

View File

@ -277,21 +277,24 @@ public class SQLiteDialect extends Dialect {
integerType, integerType,
"instr(?2,?1)", "instr(?2,?1)",
"instr(?2,?1,?3)", "instr(?2,?1,?3)",
STRING, STRING, INTEGER STRING, STRING, INTEGER,
queryEngine.getTypeConfiguration()
).setArgumentListSignature("(pattern, string[, start])"); ).setArgumentListSignature("(pattern, string[, start])");
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"lpad", "lpad",
stringType, stringType,
"(substr(replace(hex(zeroblob(?2)),'00',' '),1,?2-length(?1))||?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))||?1)",
STRING, INTEGER, STRING STRING, INTEGER, STRING,
queryEngine.getTypeConfiguration()
).setArgumentListSignature("(string, length[, padding])"); ).setArgumentListSignature("(string, length[, padding])");
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"rpad", "rpad",
stringType, stringType,
"(?1||substr(replace(hex(zeroblob(?2)),'00',' '),1,?2-length(?1)))", "(?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 STRING, INTEGER, STRING,
queryEngine.getTypeConfiguration()
).setArgumentListSignature("(string, length[, padding])"); ).setArgumentListSignature("(string, length[, padding])");
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder("format", "strftime") queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder("format", "strftime")

View File

@ -168,7 +168,8 @@ public class TimesTenDialect extends Dialect {
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ), queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
"instr(?2,?1)", "instr(?2,?1)",
"instr(?2,?1,?3)", "instr(?2,?1,?3)",
STRING, STRING, INTEGER STRING, STRING, INTEGER,
queryEngine.getTypeConfiguration()
).setArgumentListSignature("(pattern, string[, start])"); ).setArgumentListSignature("(pattern, string[, start])");
} }

View File

@ -79,6 +79,7 @@ import java.util.regex.Pattern;
import jakarta.persistence.TemporalType; import jakarta.persistence.TemporalType;
import org.hibernate.query.sqm.produce.function.FunctionParameterType; import org.hibernate.query.sqm.produce.function.FunctionParameterType;
import org.hibernate.type.spi.TypeConfiguration;
/** /**
* An abstract base class for SAP HANA dialects. * An abstract base class for SAP HANA dialects.
@ -274,13 +275,15 @@ public abstract class AbstractHANADialect extends Dialect {
@Override @Override
public void initializeFunctionRegistry(QueryEngine queryEngine) { public void initializeFunctionRegistry(QueryEngine queryEngine) {
super.initializeFunctionRegistry( queryEngine ); super.initializeFunctionRegistry( queryEngine );
final TypeConfiguration typeConfiguration = queryEngine.getTypeConfiguration();
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"locate", "locate",
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ), typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
"locate(?2,?1)", "locate(?2,?1)",
"locate(?2,?1,?3)", "locate(?2,?1,?3)",
FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER,
typeConfiguration
).setArgumentListSignature("(pattern, string[, start])"); ).setArgumentListSignature("(pattern, string[, start])");
CommonFunctionFactory functionFactory = new CommonFunctionFactory(queryEngine); CommonFunctionFactory functionFactory = new CommonFunctionFactory(queryEngine);
@ -317,7 +320,7 @@ public abstract class AbstractHANADialect extends Dialect {
functionFactory.hypotheticalOrderedSetAggregates_windowEmulation(); functionFactory.hypotheticalOrderedSetAggregates_windowEmulation();
queryEngine.getSqmFunctionRegistry().register( "timestampadd", queryEngine.getSqmFunctionRegistry().register( "timestampadd",
new IntegralTimestampaddFunction( this, queryEngine.getTypeConfiguration() ) ); new IntegralTimestampaddFunction( this, typeConfiguration ) );
} }
@Override @Override

View File

@ -142,7 +142,6 @@ public abstract class AbstractTransactSQLDialect extends Dialect {
functionFactory.yearMonthDay(); functionFactory.yearMonthDay();
functionFactory.ascii(); functionFactory.ascii();
functionFactory.chr_char(); functionFactory.chr_char();
functionFactory.concat_plusOperator();
functionFactory.trim1(); functionFactory.trim1();
functionFactory.repeat_replicate(); functionFactory.repeat_replicate();
functionFactory.characterLength_len(); functionFactory.characterLength_len();

View File

@ -160,6 +160,7 @@ import org.hibernate.type.descriptor.jdbc.NCharJdbcType;
import org.hibernate.type.descriptor.jdbc.NClobJdbcType; import org.hibernate.type.descriptor.jdbc.NClobJdbcType;
import org.hibernate.type.descriptor.jdbc.NVarcharJdbcType; import org.hibernate.type.descriptor.jdbc.NVarcharJdbcType;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
import org.hibernate.type.spi.TypeConfiguration;
import jakarta.persistence.TemporalType; import jakarta.persistence.TemporalType;
@ -769,7 +770,8 @@ public abstract class Dialect implements ConversionContext {
* same names. * same names.
*/ */
public void initializeFunctionRegistry(QueryEngine queryEngine) { public void initializeFunctionRegistry(QueryEngine queryEngine) {
final BasicTypeRegistry basicTypeRegistry = queryEngine.getTypeConfiguration().getBasicTypeRegistry(); final TypeConfiguration typeConfiguration = queryEngine.getTypeConfiguration();
final BasicTypeRegistry basicTypeRegistry = typeConfiguration.getBasicTypeRegistry();
final BasicType<Date> timestampType = basicTypeRegistry.resolve( StandardBasicTypes.TIMESTAMP ); final BasicType<Date> timestampType = basicTypeRegistry.resolve( StandardBasicTypes.TIMESTAMP );
final BasicType<Date> dateType = basicTypeRegistry.resolve( StandardBasicTypes.DATE ); final BasicType<Date> dateType = basicTypeRegistry.resolve( StandardBasicTypes.DATE );
final BasicType<Date> timeType = basicTypeRegistry.resolve( StandardBasicTypes.TIME ); final BasicType<Date> timeType = basicTypeRegistry.resolve( StandardBasicTypes.TIME );
@ -842,20 +844,20 @@ public abstract class Dialect implements ConversionContext {
//define it here as an alias for locate() //define it here as an alias for locate()
queryEngine.getSqmFunctionRegistry().register( "position", queryEngine.getSqmFunctionRegistry().register( "position",
new LocatePositionEmulation( queryEngine.getTypeConfiguration() ) ); new LocatePositionEmulation( typeConfiguration ) );
//very few databases support ANSI-style overlay() function, so emulate //very few databases support ANSI-style overlay() function, so emulate
//it here in terms of either insert() or concat()/substring() //it here in terms of either insert() or concat()/substring()
queryEngine.getSqmFunctionRegistry().register( "overlay", queryEngine.getSqmFunctionRegistry().register( "overlay",
new InsertSubstringOverlayEmulation( queryEngine.getTypeConfiguration(), false ) ); new InsertSubstringOverlayEmulation( typeConfiguration, false ) );
//ANSI SQL trim() function is supported on almost all of the databases //ANSI SQL trim() function is supported on almost all of the databases
//we care about, but on some it must be emulated using ltrim(), rtrim(), //we care about, but on some it must be emulated using ltrim(), rtrim(),
//and replace() //and replace()
queryEngine.getSqmFunctionRegistry().register( "trim", queryEngine.getSqmFunctionRegistry().register( "trim",
new TrimFunction( this, queryEngine.getTypeConfiguration() ) ); new TrimFunction( this, typeConfiguration ) );
//ANSI SQL cast() function is supported on the databases we care most //ANSI SQL cast() function is supported on the databases we care most
//about but in certain cases it doesn't allow some useful typecasts, //about but in certain cases it doesn't allow some useful typecasts,
@ -883,7 +885,7 @@ public abstract class Dialect implements ConversionContext {
//a very dialect-specific way //a very dialect-specific way
queryEngine.getSqmFunctionRegistry().register( "extract", queryEngine.getSqmFunctionRegistry().register( "extract",
new ExtractFunction( this ) ); new ExtractFunction( this, typeConfiguration ) );
//comparison functions supported on most databases, emulated on others //comparison functions supported on most databases, emulated on others
//using a case expression //using a case expression
@ -905,13 +907,13 @@ public abstract class Dialect implements ConversionContext {
//pad() is a function we've designed to look like ANSI trim() //pad() is a function we've designed to look like ANSI trim()
queryEngine.getSqmFunctionRegistry().register( "pad", queryEngine.getSqmFunctionRegistry().register( "pad",
new LpadRpadPadEmulation( queryEngine.getTypeConfiguration() ) ); new LpadRpadPadEmulation( typeConfiguration ) );
//legacy Hibernate convenience function for casting to string, defined //legacy Hibernate convenience function for casting to string, defined
//here as an alias for cast(arg as String) //here as an alias for cast(arg as String)
queryEngine.getSqmFunctionRegistry().register( "str", queryEngine.getSqmFunctionRegistry().register( "str",
new CastStrEmulation( queryEngine.getTypeConfiguration() ) ); new CastStrEmulation( typeConfiguration ) );
//format() function for datetimes, emulated on many databases using the //format() function for datetimes, emulated on many databases using the
//Oracle-style to_char() function, and on others using their native //Oracle-style to_char() function, and on others using their native
@ -923,9 +925,9 @@ public abstract class Dialect implements ConversionContext {
//since there is a great variety of different ways to emulate them //since there is a great variety of different ways to emulate them
queryEngine.getSqmFunctionRegistry().register( "timestampadd", queryEngine.getSqmFunctionRegistry().register( "timestampadd",
new TimestampaddFunction( this ) ); new TimestampaddFunction( this, typeConfiguration ) );
queryEngine.getSqmFunctionRegistry().register( "timestampdiff", queryEngine.getSqmFunctionRegistry().register( "timestampdiff",
new TimestampdiffFunction( this, queryEngine.getTypeConfiguration() ) ); new TimestampdiffFunction( this, typeConfiguration ) );
queryEngine.getSqmFunctionRegistry().registerAlternateKey( "dateadd", "timestampadd" ); queryEngine.getSqmFunctionRegistry().registerAlternateKey( "dateadd", "timestampadd" );
queryEngine.getSqmFunctionRegistry().registerAlternateKey( "datediff", "timestampdiff" ); queryEngine.getSqmFunctionRegistry().registerAlternateKey( "datediff", "timestampdiff" );

View File

@ -19,6 +19,7 @@ import org.hibernate.dialect.temptable.TemporaryTableKind;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy; import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.spi.TypeConfiguration;
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.ANY; import static org.hibernate.query.sqm.produce.function.FunctionParameterType.ANY;
@ -102,20 +103,22 @@ public class HANAColumnStoreDialect extends AbstractHANADialect {
@Override @Override
public void initializeFunctionRegistry(QueryEngine queryEngine) { public void initializeFunctionRegistry(QueryEngine queryEngine) {
super.initializeFunctionRegistry( queryEngine ); super.initializeFunctionRegistry( queryEngine );
final TypeConfiguration typeConfiguration = queryEngine.getTypeConfiguration();
// full-text search functions // full-text search functions
queryEngine.getSqmFunctionRegistry().registerNamed( queryEngine.getSqmFunctionRegistry().registerNamed(
"score", "score",
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.DOUBLE ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.DOUBLE )
); );
queryEngine.getSqmFunctionRegistry().registerNamed( "snippets" ); queryEngine.getSqmFunctionRegistry().registerNamed( "snippets" );
queryEngine.getSqmFunctionRegistry().registerNamed( "highlighted" ); queryEngine.getSqmFunctionRegistry().registerNamed( "highlighted" );
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"contains", "contains",
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.BOOLEAN ), typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.BOOLEAN ),
"contains(?1,?2)", "contains(?1,?2)",
"contains(?1,?2,?3)", "contains(?1,?2,?3)",
ANY, ANY, ANY ANY, ANY, ANY,
typeConfiguration
); );
} }

View File

@ -93,6 +93,8 @@ import static org.hibernate.query.sqm.TemporalUnit.SECOND;
import static org.hibernate.query.sqm.TemporalUnit.YEAR; import static org.hibernate.query.sqm.TemporalUnit.YEAR;
import org.hibernate.query.sqm.produce.function.FunctionParameterType; import org.hibernate.query.sqm.produce.function.FunctionParameterType;
import org.hibernate.type.spi.TypeConfiguration;
import static org.hibernate.type.SqlTypes.*; import static org.hibernate.type.SqlTypes.*;
/** /**
@ -136,6 +138,7 @@ public class OracleDialect extends Dialect {
@Override @Override
public void initializeFunctionRegistry(QueryEngine queryEngine) { public void initializeFunctionRegistry(QueryEngine queryEngine) {
super.initializeFunctionRegistry( queryEngine ); super.initializeFunctionRegistry( queryEngine );
final TypeConfiguration typeConfiguration = queryEngine.getTypeConfiguration();
CommonFunctionFactory functionFactory = new CommonFunctionFactory(queryEngine); CommonFunctionFactory functionFactory = new CommonFunctionFactory(queryEngine);
functionFactory.cosh(); functionFactory.cosh();
@ -185,10 +188,11 @@ public class OracleDialect extends Dialect {
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern( queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
"locate", "locate",
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ), typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
"instr(?2,?1)", "instr(?2,?1)",
"instr(?2,?1,?3)", "instr(?2,?1,?3)",
FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER,
typeConfiguration
).setArgumentListSignature("(pattern, string[, start])"); ).setArgumentListSignature("(pattern, string[, start])");
// The within group clause became optional in 18 // The within group clause became optional in 18
if ( getVersion().isSameOrAfter( 18 ) ) { if ( getVersion().isSameOrAfter( 18 ) ) {
@ -203,7 +207,7 @@ public class OracleDialect extends Dialect {
// Oracle has a regular aggregate function named stats_mode // Oracle has a regular aggregate function named stats_mode
queryEngine.getSqmFunctionRegistry().register( queryEngine.getSqmFunctionRegistry().register(
"mode", "mode",
new ModeStatsModeEmulation( queryEngine.getTypeConfiguration() ) new ModeStatsModeEmulation( typeConfiguration )
); );
} }

View File

@ -15,7 +15,9 @@ import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescript
import org.hibernate.query.sqm.function.FunctionKind; import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode; import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
@ -49,7 +51,8 @@ public class AvgFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 1 ), NUMERIC ), new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 1 ), NUMERIC ),
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.DOUBLE ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.DOUBLE )
) ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, NUMERIC )
); );
this.defaultArgumentRenderingMode = defaultArgumentRenderingMode; this.defaultArgumentRenderingMode = defaultArgumentRenderingMode;
doubleType = typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.DOUBLE ); doubleType = typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.DOUBLE );
@ -80,8 +83,10 @@ public class AvgFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
arg = (Expression) sqlAstArguments.get( 0 ); arg = (Expression) sqlAstArguments.get( 0 );
} }
if ( caseWrapper ) { if ( caseWrapper ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
sqlAppender.appendSql( "case when " ); sqlAppender.appendSql( "case when " );
filter.accept( translator ); filter.accept( translator );
translator.getCurrentClauseStack().pop();
sqlAppender.appendSql( " then " ); sqlAppender.appendSql( " then " );
renderArgument( sqlAppender, translator, arg ); renderArgument( sqlAppender, translator, arg );
sqlAppender.appendSql( " else null end)" ); sqlAppender.appendSql( " else null end)" );
@ -90,9 +95,11 @@ public class AvgFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
renderArgument( sqlAppender, translator, arg ); renderArgument( sqlAppender, translator, arg );
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
if ( filter != null ) { if ( filter != null ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
sqlAppender.appendSql( " filter (where " ); sqlAppender.appendSql( " filter (where " );
filter.accept( translator ); filter.accept( translator );
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
translator.getCurrentClauseStack().pop();
} }
} }
} }

View File

@ -11,6 +11,7 @@ import java.util.List;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
@ -33,7 +34,8 @@ public class CaseLeastGreatestEmulation
super( super(
least ? "least" : "greatest", least ? "least" : "greatest",
new ArgumentTypesValidator( StandardArgumentsValidators.min( 2 ), COMPARABLE, COMPARABLE ), new ArgumentTypesValidator( StandardArgumentsValidators.min( 2 ), COMPARABLE, COMPARABLE ),
StandardFunctionReturnTypeResolvers.useFirstNonNull() StandardFunctionReturnTypeResolvers.useFirstNonNull(),
StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE
); );
this.operator = least ? "<=" : ">="; this.operator = least ? "<=" : ">=";
} }

View File

@ -14,6 +14,7 @@ import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.sqm.CastType; import org.hibernate.query.sqm.CastType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer; import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
@ -38,7 +39,8 @@ public class CastFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
super( super(
"cast", "cast",
StandardArgumentsValidators.exactly( 2 ), StandardArgumentsValidators.exactly( 2 ),
StandardFunctionReturnTypeResolvers.useArgType( 2 ) StandardFunctionReturnTypeResolvers.useArgType( 2 ),
StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE
); );
this.dialect = dialect; this.dialect = dialect;
this.booleanCastType = getBooleanCastType( preferredSqlTypeCodeForBoolean ); this.booleanCastType = getBooleanCastType( preferredSqlTypeCodeForBoolean );

View File

@ -37,7 +37,8 @@ public class CastStrEmulation
StandardArgumentsValidators.exactly( 1 ), StandardArgumentsValidators.exactly( 1 ),
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
) ),
null
); );
} }
@ -45,7 +46,7 @@ public class CastStrEmulation
String name, String name,
ArgumentsValidator argumentsValidator, ArgumentsValidator argumentsValidator,
FunctionReturnTypeResolver returnTypeResolver) { FunctionReturnTypeResolver returnTypeResolver) {
super( name, argumentsValidator, returnTypeResolver ); super( name, argumentsValidator, returnTypeResolver, null );
} }
@Override @Override

View File

@ -15,6 +15,7 @@ import org.hibernate.query.sqm.CastType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer; import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode; import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
@ -42,10 +43,11 @@ public class CastingConcatFunction extends AbstractSqmSelfRenderingFunctionDescr
TypeConfiguration typeConfiguration) { TypeConfiguration typeConfiguration) {
super( super(
"concat", "concat",
new ArgumentTypesValidator( StandardArgumentsValidators.min( 1 ), STRING ), StandardArgumentsValidators.min( 1 ),
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
) ),
StandardFunctionArgumentTypeResolvers.impliedOrInvariant( typeConfiguration, STRING )
); );
this.dialect = dialect; this.dialect = dialect;
this.concatOperator = concatOperator; this.concatOperator = concatOperator;

View File

@ -11,6 +11,7 @@ import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction; import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
@ -25,7 +26,8 @@ public class CoalesceIfnullEmulation
public CoalesceIfnullEmulation() { public CoalesceIfnullEmulation() {
super( super(
"ifnull", "ifnull",
StandardArgumentsValidators.exactly( 2 ) StandardArgumentsValidators.exactly( 2 ),
StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE
); );
} }

View File

@ -16,6 +16,7 @@ import org.hibernate.query.sqm.function.SqmFunctionRegistry;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator; import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode; import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.hibernate.type.BasicTypeRegistry; import org.hibernate.type.BasicTypeRegistry;
@ -454,14 +455,16 @@ public class CommonFunctionFactory {
stringType, stringType,
"lpad(?1,?2,' ')", "lpad(?1,?2,' ')",
"lpad(?1,?2,?3)", "lpad(?1,?2,?3)",
STRING, INTEGER, STRING STRING, INTEGER, STRING,
typeConfiguration
).setArgumentListSignature( "(string, length[, padding])" ); ).setArgumentListSignature( "(string, length[, padding])" );
functionRegistry.registerBinaryTernaryPattern( functionRegistry.registerBinaryTernaryPattern(
"rpad", "rpad",
stringType, stringType,
"rpad(?1,?2,' ')", "rpad(?1,?2,' ')",
"rpad(?1,?2,?3)", "rpad(?1,?2,?3)",
STRING, INTEGER, STRING STRING, INTEGER, STRING,
typeConfiguration
).setArgumentListSignature( "(string, length[, padding])" ); ).setArgumentListSignature( "(string, length[, padding])" );
} }
@ -474,14 +477,16 @@ public class CommonFunctionFactory {
stringType, stringType,
"(space(?2-len(?1))+?1)", "(space(?2-len(?1))+?1)",
"(replicate(?3,?2-len(?1))+?1)", "(replicate(?3,?2-len(?1))+?1)",
STRING, INTEGER, STRING STRING, INTEGER, STRING,
typeConfiguration
).setArgumentListSignature( "(string, length[, padding])" ); ).setArgumentListSignature( "(string, length[, padding])" );
functionRegistry.registerBinaryTernaryPattern( functionRegistry.registerBinaryTernaryPattern(
"rpad", "rpad",
stringType, stringType,
"(?1+space(?2-len(?1)))", "(?1+space(?2-len(?1)))",
"(?1+replicate(?3,?2-len(?1)))", "(?1+replicate(?3,?2-len(?1)))",
STRING, INTEGER, STRING STRING, INTEGER, STRING,
typeConfiguration
).setArgumentListSignature( "(string, length[, padding])" ); ).setArgumentListSignature( "(string, length[, padding])" );
} }
@ -491,14 +496,16 @@ public class CommonFunctionFactory {
stringType, stringType,
"(repeat(' ',?2-character_length(?1))||?1)", "(repeat(' ',?2-character_length(?1))||?1)",
"(repeat(?3,?2-character_length(?1))||?1)", "(repeat(?3,?2-character_length(?1))||?1)",
STRING, INTEGER, STRING STRING, INTEGER, STRING,
typeConfiguration
).setArgumentListSignature( "(string, length[, padding])" ); ).setArgumentListSignature( "(string, length[, padding])" );
functionRegistry.registerBinaryTernaryPattern( functionRegistry.registerBinaryTernaryPattern(
"rpad", "rpad",
stringType, stringType,
"(?1||repeat(' ',?2-character_length(?1)))", "(?1||repeat(' ',?2-character_length(?1)))",
"(?1||repeat(?3,?2-character_length(?1)))", "(?1||repeat(?3,?2-character_length(?1)))",
STRING, INTEGER, STRING STRING, INTEGER, STRING,
typeConfiguration
).setArgumentListSignature( "(string, length[, padding])" ); ).setArgumentListSignature( "(string, length[, padding])" );
} }
@ -511,14 +518,16 @@ public class CommonFunctionFactory {
stringType, stringType,
"lfill(?1,' ',?2)", "lfill(?1,' ',?2)",
"lfill(?1,?3,?2)", "lfill(?1,?3,?2)",
STRING, INTEGER, STRING STRING, INTEGER, STRING,
typeConfiguration
).setArgumentListSignature( "(string, length[, padding])" ); ).setArgumentListSignature( "(string, length[, padding])" );
functionRegistry.registerBinaryTernaryPattern( functionRegistry.registerBinaryTernaryPattern(
"rpad", "rpad",
stringType, stringType,
"rfill(?1,' ',?2)", "rfill(?1,' ',?2)",
"rfill(?1,?3,?2)", "rfill(?1,?3,?2)",
STRING, INTEGER, STRING STRING, INTEGER, STRING,
typeConfiguration
).setArgumentListSignature( "(string, length[, padding])" ); ).setArgumentListSignature( "(string, length[, padding])" );
} }
@ -606,6 +615,7 @@ public class CommonFunctionFactory {
functionRegistry.namedDescriptorBuilder( "md5" ) functionRegistry.namedDescriptorBuilder( "md5" )
.setInvariantType(stringType) .setInvariantType(stringType)
.setExactArgumentCount( 1 ) .setExactArgumentCount( 1 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
.register(); .register();
} }
@ -613,6 +623,7 @@ public class CommonFunctionFactory {
functionRegistry.namedDescriptorBuilder( "initcap" ) functionRegistry.namedDescriptorBuilder( "initcap" )
.setInvariantType(stringType) .setInvariantType(stringType)
.setExactArgumentCount( 1 ) .setExactArgumentCount( 1 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
.register(); .register();
} }
@ -638,30 +649,35 @@ public class CommonFunctionFactory {
functionRegistry.namedDescriptorBuilder( "translate" ) functionRegistry.namedDescriptorBuilder( "translate" )
.setInvariantType(stringType) .setInvariantType(stringType)
.setExactArgumentCount( 3 ) .setExactArgumentCount( 3 )
.setParameterTypes( STRING, STRING, STRING )
.register(); .register();
} }
public void bitand() { public void bitand() {
functionRegistry.namedDescriptorBuilder( "bitand" ) functionRegistry.namedDescriptorBuilder( "bitand" )
.setExactArgumentCount( 2 ) .setExactArgumentCount( 2 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
} }
public void bitor() { public void bitor() {
functionRegistry.namedDescriptorBuilder( "bitor" ) functionRegistry.namedDescriptorBuilder( "bitor" )
.setExactArgumentCount( 2 ) .setExactArgumentCount( 2 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
} }
public void bitxor() { public void bitxor() {
functionRegistry.namedDescriptorBuilder( "bitxor" ) functionRegistry.namedDescriptorBuilder( "bitxor" )
.setExactArgumentCount( 2 ) .setExactArgumentCount( 2 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
} }
public void bitnot() { public void bitnot() {
functionRegistry.namedDescriptorBuilder( "bitnot" ) functionRegistry.namedDescriptorBuilder( "bitnot" )
.setExactArgumentCount( 1 ) .setExactArgumentCount( 1 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
.register(); .register();
} }
@ -671,21 +687,25 @@ public class CommonFunctionFactory {
public void bitandorxornot_bitAndOrXorNot() { public void bitandorxornot_bitAndOrXorNot() {
functionRegistry.namedDescriptorBuilder( "bit_and" ) functionRegistry.namedDescriptorBuilder( "bit_and" )
.setExactArgumentCount( 2 ) .setExactArgumentCount( 2 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
functionRegistry.registerAlternateKey( "bitand", "bit_and" ); functionRegistry.registerAlternateKey( "bitand", "bit_and" );
functionRegistry.namedDescriptorBuilder( "bit_or" ) functionRegistry.namedDescriptorBuilder( "bit_or" )
.setExactArgumentCount( 2 ) .setExactArgumentCount( 2 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
functionRegistry.registerAlternateKey( "bitor", "bit_or" ); functionRegistry.registerAlternateKey( "bitor", "bit_or" );
functionRegistry.namedDescriptorBuilder( "bit_xor" ) functionRegistry.namedDescriptorBuilder( "bit_xor" )
.setExactArgumentCount( 2 ) .setExactArgumentCount( 2 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
functionRegistry.registerAlternateKey( "bitxor", "bit_xor" ); functionRegistry.registerAlternateKey( "bitxor", "bit_xor" );
functionRegistry.namedDescriptorBuilder( "bit_not" ) functionRegistry.namedDescriptorBuilder( "bit_not" )
.setExactArgumentCount( 1 ) .setExactArgumentCount( 1 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
.register(); .register();
functionRegistry.registerAlternateKey( "bitnot", "bit_not" ); functionRegistry.registerAlternateKey( "bitnot", "bit_not" );
} }
@ -696,21 +716,25 @@ public class CommonFunctionFactory {
public void bitandorxornot_binAndOrXorNot() { public void bitandorxornot_binAndOrXorNot() {
functionRegistry.namedDescriptorBuilder( "bin_and" ) functionRegistry.namedDescriptorBuilder( "bin_and" )
.setMinArgumentCount( 1 ) .setMinArgumentCount( 1 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
functionRegistry.registerAlternateKey( "bitand", "bin_and" ); functionRegistry.registerAlternateKey( "bitand", "bin_and" );
functionRegistry.namedDescriptorBuilder( "bin_or" ) functionRegistry.namedDescriptorBuilder( "bin_or" )
.setMinArgumentCount( 1 ) .setMinArgumentCount( 1 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
functionRegistry.registerAlternateKey( "bitor", "bin_or" ); functionRegistry.registerAlternateKey( "bitor", "bin_or" );
functionRegistry.namedDescriptorBuilder( "bin_xor" ) functionRegistry.namedDescriptorBuilder( "bin_xor" )
.setMinArgumentCount( 1 ) .setMinArgumentCount( 1 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
functionRegistry.registerAlternateKey( "bitxor", "bin_xor" ); functionRegistry.registerAlternateKey( "bitxor", "bin_xor" );
functionRegistry.namedDescriptorBuilder( "bin_not" ) functionRegistry.namedDescriptorBuilder( "bin_not" )
.setExactArgumentCount( 1 ) .setExactArgumentCount( 1 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
.register(); .register();
functionRegistry.registerAlternateKey( "bitnot", "bin_not" ); functionRegistry.registerAlternateKey( "bitnot", "bin_not" );
} }
@ -721,18 +745,22 @@ public class CommonFunctionFactory {
public void bitandorxornot_operator() { public void bitandorxornot_operator() {
functionRegistry.patternDescriptorBuilder( "bitand", "(?1&?2)" ) functionRegistry.patternDescriptorBuilder( "bitand", "(?1&?2)" )
.setExactArgumentCount( 2 ) .setExactArgumentCount( 2 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
functionRegistry.patternDescriptorBuilder( "bitor", "(?1|?2)" ) functionRegistry.patternDescriptorBuilder( "bitor", "(?1|?2)" )
.setExactArgumentCount( 2 ) .setExactArgumentCount( 2 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
functionRegistry.patternDescriptorBuilder( "bitxor", "(?1^?2)" ) functionRegistry.patternDescriptorBuilder( "bitxor", "(?1^?2)" )
.setExactArgumentCount( 2 ) .setExactArgumentCount( 2 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
functionRegistry.patternDescriptorBuilder( "bitnot", "~?1" ) functionRegistry.patternDescriptorBuilder( "bitnot", "~?1" )
.setExactArgumentCount( 1 ) .setExactArgumentCount( 1 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
.register(); .register();
} }
@ -742,10 +770,12 @@ public class CommonFunctionFactory {
public void bitAndOr() { public void bitAndOr() {
functionRegistry.namedAggregateDescriptorBuilder( "bit_and" ) functionRegistry.namedAggregateDescriptorBuilder( "bit_and" )
.setExactArgumentCount( 1 ) .setExactArgumentCount( 1 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
functionRegistry.namedAggregateDescriptorBuilder( "bit_or" ) functionRegistry.namedAggregateDescriptorBuilder( "bit_or" )
.setExactArgumentCount( 1 ) .setExactArgumentCount( 1 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
//MySQL has it but how is that even useful? //MySQL has it but how is that even useful?
@ -978,21 +1008,25 @@ public class CommonFunctionFactory {
functionRegistry.namedDescriptorBuilder( "to_number" ) functionRegistry.namedDescriptorBuilder( "to_number" )
//always 1 arg on HSQL and Cache, always 2 on Postgres //always 1 arg on HSQL and Cache, always 2 on Postgres
.setArgumentCountBetween( 1, 3 ) .setArgumentCountBetween( 1, 3 )
.setParameterTypes( STRING, STRING, STRING )
.setInvariantType(doubleType) .setInvariantType(doubleType)
.register(); .register();
functionRegistry.namedDescriptorBuilder( "to_char" ) functionRegistry.namedDescriptorBuilder( "to_char" )
.setArgumentCountBetween( 1, 3 ) .setArgumentCountBetween( 1, 3 )
.setParameterTypes( ANY, STRING, STRING )
//always 2 args on HSQL and Postgres //always 2 args on HSQL and Postgres
.setInvariantType(stringType) .setInvariantType(stringType)
.register(); .register();
functionRegistry.namedDescriptorBuilder( "to_date" ) functionRegistry.namedDescriptorBuilder( "to_date" )
//always 2 args on HSQL and Postgres //always 2 args on HSQL and Postgres
.setArgumentCountBetween( 1, 3 ) .setArgumentCountBetween( 1, 3 )
.setParameterTypes( STRING, STRING, STRING )
.setInvariantType(dateType) .setInvariantType(dateType)
.register(); .register();
functionRegistry.namedDescriptorBuilder( "to_timestamp" ) functionRegistry.namedDescriptorBuilder( "to_timestamp" )
//always 2 args on HSQL and Postgres //always 2 args on HSQL and Postgres
.setArgumentCountBetween( 1, 3 ) .setArgumentCountBetween( 1, 3 )
.setParameterTypes( STRING, STRING, STRING )
.setInvariantType(timestampType) .setInvariantType(timestampType)
.register(); .register();
} }
@ -1073,19 +1107,9 @@ public class CommonFunctionFactory {
functionRegistry.patternDescriptorBuilder( "concat", "(?1||?2...)" ) functionRegistry.patternDescriptorBuilder( "concat", "(?1||?2...)" )
.setInvariantType(stringType) .setInvariantType(stringType)
.setMinArgumentCount( 1 ) .setMinArgumentCount( 1 )
.setParameterTypes(STRING) .setArgumentTypeResolver(
.setArgumentListSignature( "(STRING string0[, STRING string1[, ...]])" ) StandardFunctionArgumentTypeResolvers.impliedOrInvariant( typeConfiguration, STRING )
.register(); )
}
/**
* Transact SQL-style
*/
public void concat_plusOperator() {
functionRegistry.patternDescriptorBuilder( "concat", "(?1+?2...)" )
.setInvariantType(stringType)
.setMinArgumentCount( 1 )
.setParameterTypes(STRING)
.setArgumentListSignature( "(STRING string0[, STRING string1[, ...]])" ) .setArgumentListSignature( "(STRING string0[, STRING string1[, ...]])" )
.register(); .register();
} }
@ -1297,6 +1321,7 @@ public class CommonFunctionFactory {
public void coalesce() { public void coalesce() {
functionRegistry.namedDescriptorBuilder( "coalesce" ) functionRegistry.namedDescriptorBuilder( "coalesce" )
.setMinArgumentCount( 1 ) .setMinArgumentCount( 1 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
} }
@ -1306,6 +1331,7 @@ public class CommonFunctionFactory {
public void coalesce_value() { public void coalesce_value() {
functionRegistry.namedDescriptorBuilder( "value" ) functionRegistry.namedDescriptorBuilder( "value" )
.setMinArgumentCount( 1 ) .setMinArgumentCount( 1 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
functionRegistry.registerAlternateKey( "coalesce", "value" ); functionRegistry.registerAlternateKey( "coalesce", "value" );
} }
@ -1313,6 +1339,7 @@ public class CommonFunctionFactory {
public void nullif() { public void nullif() {
functionRegistry.namedDescriptorBuilder( "nullif" ) functionRegistry.namedDescriptorBuilder( "nullif" )
.setExactArgumentCount( 2 ) .setExactArgumentCount( 2 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
} }
@ -1420,7 +1447,8 @@ public class CommonFunctionFactory {
"locate", "locate",
integerType, integerType,
"position(?1 in ?2)", "(position(?1 in substring(?2 from ?3))+(?3)-1)", "position(?1 in ?2)", "(position(?1 in substring(?2 from ?3))+(?3)-1)",
STRING, STRING, INTEGER STRING, STRING, INTEGER,
typeConfiguration
) )
.setArgumentListSignature( "(STRING pattern, STRING string[, INTEGER start])" ); .setArgumentListSignature( "(STRING pattern, STRING string[, INTEGER start])" );
} }
@ -1432,7 +1460,8 @@ public class CommonFunctionFactory {
"substring", "substring",
stringType, stringType,
"substring(?1 from ?2)", "substring(?1 from ?2 for ?3)", "substring(?1 from ?2)", "substring(?1 from ?2 for ?3)",
STRING, INTEGER, INTEGER STRING, INTEGER, INTEGER,
typeConfiguration
) )
.setArgumentListSignature( "(STRING string{ from|,} INTEGER start[{ for|,} INTEGER length])" ); .setArgumentListSignature( "(STRING string{ from|,} INTEGER start[{ for|,} INTEGER length])" );
} }
@ -1459,7 +1488,8 @@ public class CommonFunctionFactory {
stringType, stringType,
"substring(?1,?2,len(?1)-?2+1)", "substring(?1,?2,len(?1)-?2+1)",
"substring(?1,?2,?3)", "substring(?1,?2,?3)",
STRING, INTEGER, INTEGER STRING, INTEGER, INTEGER,
typeConfiguration
) )
.setArgumentListSignature( "(STRING string{ from|,} INTEGER start[{ for|,} INTEGER length])" ); .setArgumentListSignature( "(STRING string{ from|,} INTEGER start[{ for|,} INTEGER length])" );
} }
@ -1508,7 +1538,8 @@ public class CommonFunctionFactory {
stringType, stringType,
"overlay(?1 placing ?2 from ?3)", "overlay(?1 placing ?2 from ?3)",
"overlay(?1 placing ?2 from ?3 for ?4)", "overlay(?1 placing ?2 from ?3 for ?4)",
STRING, STRING, INTEGER, INTEGER STRING, STRING, INTEGER, INTEGER,
typeConfiguration
) )
.setArgumentListSignature( "(string placing replacement from start[ for length])" ); .setArgumentListSignature( "(string placing replacement from start[ for length])" );
} }
@ -1524,7 +1555,8 @@ public class CommonFunctionFactory {
//because DB2 doesn't like "length(?)" //because DB2 doesn't like "length(?)"
"overlay(?1 placing ?2 from ?3 for character_length(?2))", "overlay(?1 placing ?2 from ?3 for character_length(?2))",
"overlay(?1 placing ?2 from ?3 for ?4)", "overlay(?1 placing ?2 from ?3 for ?4)",
STRING, STRING, INTEGER, INTEGER STRING, STRING, INTEGER, INTEGER,
typeConfiguration
) )
.setArgumentListSignature( "(string placing replacement from start[ for length])" ); .setArgumentListSignature( "(string placing replacement from start[ for length])" );
} }
@ -1555,7 +1587,9 @@ public class CommonFunctionFactory {
functionRegistry.namedDescriptorBuilder( "concat" ) functionRegistry.namedDescriptorBuilder( "concat" )
.setInvariantType(stringType) .setInvariantType(stringType)
.setMinArgumentCount( 1 ) .setMinArgumentCount( 1 )
.setParameterTypes(STRING) .setArgumentTypeResolver(
StandardFunctionArgumentTypeResolvers.impliedOrInvariant( typeConfiguration, STRING )
)
.setArgumentListSignature( "(STRING string0[, STRING string1[, ...]])" ) .setArgumentListSignature( "(STRING string0[, STRING string1[, ...]])" )
.register(); .register();
} }
@ -1644,10 +1678,12 @@ public class CommonFunctionFactory {
functionRegistry.namedDescriptorBuilder( "least" ) functionRegistry.namedDescriptorBuilder( "least" )
.setMinArgumentCount( 2 ) .setMinArgumentCount( 2 )
.setParameterTypes(COMPARABLE, COMPARABLE) .setParameterTypes(COMPARABLE, COMPARABLE)
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
functionRegistry.namedDescriptorBuilder( "greatest" ) functionRegistry.namedDescriptorBuilder( "greatest" )
.setMinArgumentCount( 2 ) .setMinArgumentCount( 2 )
.setParameterTypes(COMPARABLE, COMPARABLE) .setParameterTypes(COMPARABLE, COMPARABLE)
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
} }
@ -1655,10 +1691,12 @@ public class CommonFunctionFactory {
functionRegistry.namedDescriptorBuilder( "least", "min" ) functionRegistry.namedDescriptorBuilder( "least", "min" )
.setMinArgumentCount( 2 ) .setMinArgumentCount( 2 )
.setParameterTypes(COMPARABLE, COMPARABLE) .setParameterTypes(COMPARABLE, COMPARABLE)
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
functionRegistry.namedDescriptorBuilder( "greatest", "max" ) functionRegistry.namedDescriptorBuilder( "greatest", "max" )
.setMinArgumentCount( 2 ) .setMinArgumentCount( 2 )
.setParameterTypes(COMPARABLE, COMPARABLE) .setParameterTypes(COMPARABLE, COMPARABLE)
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
} }
@ -1666,10 +1704,12 @@ public class CommonFunctionFactory {
functionRegistry.namedDescriptorBuilder( "least", "minvalue" ) functionRegistry.namedDescriptorBuilder( "least", "minvalue" )
.setMinArgumentCount( 2 ) .setMinArgumentCount( 2 )
.setParameterTypes(COMPARABLE, COMPARABLE) .setParameterTypes(COMPARABLE, COMPARABLE)
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
functionRegistry.namedDescriptorBuilder( "greatest", "maxvalue" ) functionRegistry.namedDescriptorBuilder( "greatest", "maxvalue" )
.setMinArgumentCount( 2 ) .setMinArgumentCount( 2 )
.setParameterTypes(COMPARABLE, COMPARABLE) .setParameterTypes(COMPARABLE, COMPARABLE)
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register(); .register();
} }
@ -1682,12 +1722,14 @@ public class CommonFunctionFactory {
.setArgumentRenderingMode( inferenceArgumentRenderingMode ) .setArgumentRenderingMode( inferenceArgumentRenderingMode )
.setExactArgumentCount( 1 ) .setExactArgumentCount( 1 )
.setParameterTypes(COMPARABLE) .setParameterTypes(COMPARABLE)
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
.register(); .register();
functionRegistry.namedAggregateDescriptorBuilder( "min" ) functionRegistry.namedAggregateDescriptorBuilder( "min" )
.setArgumentRenderingMode( inferenceArgumentRenderingMode ) .setArgumentRenderingMode( inferenceArgumentRenderingMode )
.setExactArgumentCount( 1 ) .setExactArgumentCount( 1 )
.setParameterTypes(COMPARABLE) .setParameterTypes(COMPARABLE)
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
.register(); .register();
functionRegistry.namedAggregateDescriptorBuilder( "sum" ) functionRegistry.namedAggregateDescriptorBuilder( "sum" )
@ -1835,26 +1877,43 @@ public class CommonFunctionFactory {
functionRegistry.namedWindowDescriptorBuilder( "lag" ) functionRegistry.namedWindowDescriptorBuilder( "lag" )
.setArgumentCountBetween( 1, 3 ) .setArgumentCountBetween( 1, 3 )
.setParameterTypes( ANY, INTEGER, ANY ) .setParameterTypes( ANY, INTEGER, ANY )
.setArgumentTypeResolver(
StandardFunctionArgumentTypeResolvers.composite(
StandardFunctionArgumentTypeResolvers.argumentsOrImplied( 2 ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, INTEGER ),
StandardFunctionArgumentTypeResolvers.argumentsOrImplied( 0 )
)
)
.setArgumentListSignature( "ANY value[, INTEGER offset[, ANY default]]" ) .setArgumentListSignature( "ANY value[, INTEGER offset[, ANY default]]" )
.register(); .register();
functionRegistry.namedWindowDescriptorBuilder( "lead" ) functionRegistry.namedWindowDescriptorBuilder( "lead" )
.setArgumentCountBetween( 1, 3 ) .setArgumentCountBetween( 1, 3 )
.setParameterTypes( ANY, INTEGER, ANY ) .setParameterTypes( ANY, INTEGER, ANY )
.setArgumentTypeResolver(
StandardFunctionArgumentTypeResolvers.composite(
StandardFunctionArgumentTypeResolvers.argumentsOrImplied( 2 ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, INTEGER ),
StandardFunctionArgumentTypeResolvers.argumentsOrImplied( 0 )
)
)
.setArgumentListSignature( "ANY value[, INTEGER offset[, ANY default]]" ) .setArgumentListSignature( "ANY value[, INTEGER offset[, ANY default]]" )
.register(); .register();
functionRegistry.namedWindowDescriptorBuilder( "first_value" ) functionRegistry.namedWindowDescriptorBuilder( "first_value" )
.setExactArgumentCount( 1 ) .setExactArgumentCount( 1 )
.setParameterTypes( ANY ) .setParameterTypes( ANY )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
.setArgumentListSignature( "ANY value" ) .setArgumentListSignature( "ANY value" )
.register(); .register();
functionRegistry.namedWindowDescriptorBuilder( "last_value" ) functionRegistry.namedWindowDescriptorBuilder( "last_value" )
.setExactArgumentCount( 1 ) .setExactArgumentCount( 1 )
.setParameterTypes( ANY ) .setParameterTypes( ANY )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
.setArgumentListSignature( "ANY value" ) .setArgumentListSignature( "ANY value" )
.register(); .register();
functionRegistry.namedWindowDescriptorBuilder( "nth_value" ) functionRegistry.namedWindowDescriptorBuilder( "nth_value" )
.setExactArgumentCount( 2 ) .setExactArgumentCount( 2 )
.setParameterTypes( ANY, INTEGER ) .setParameterTypes( ANY, INTEGER )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
.setArgumentListSignature( "ANY value, INTEGER nth" ) .setArgumentListSignature( "ANY value, INTEGER nth" )
.register(); .register();
} }
@ -1969,6 +2028,7 @@ public class CommonFunctionFactory {
public void crc32() { public void crc32() {
functionRegistry.namedDescriptorBuilder( "crc32" ) functionRegistry.namedDescriptorBuilder( "crc32" )
.setInvariantType(integerType) .setInvariantType(integerType)
.setParameterTypes( STRING )
.setExactArgumentCount( 1 ) .setExactArgumentCount( 1 )
.register(); .register();
} }
@ -1976,6 +2036,7 @@ public class CommonFunctionFactory {
public void sha1() { public void sha1() {
functionRegistry.namedDescriptorBuilder( "sha1" ) functionRegistry.namedDescriptorBuilder( "sha1" )
.setInvariantType(stringType) .setInvariantType(stringType)
.setParameterTypes( STRING )
.setExactArgumentCount( 1 ) .setExactArgumentCount( 1 )
.register(); .register();
} }
@ -1983,6 +2044,7 @@ public class CommonFunctionFactory {
public void sha2() { public void sha2() {
functionRegistry.namedDescriptorBuilder( "sha2" ) functionRegistry.namedDescriptorBuilder( "sha2" )
.setInvariantType(stringType) .setInvariantType(stringType)
.setParameterTypes( STRING, INTEGER )
.setExactArgumentCount( 2 ) .setExactArgumentCount( 2 )
.register(); .register();
} }
@ -1990,6 +2052,7 @@ public class CommonFunctionFactory {
public void sha() { public void sha() {
functionRegistry.namedDescriptorBuilder( "sha" ) functionRegistry.namedDescriptorBuilder( "sha" )
.setInvariantType(stringType) .setInvariantType(stringType)
.setParameterTypes( STRING )
.setExactArgumentCount( 1 ) .setExactArgumentCount( 1 )
.register(); .register();
} }
@ -2156,6 +2219,7 @@ public class CommonFunctionFactory {
public void format_formatdatetime() { public void format_formatdatetime() {
functionRegistry.namedDescriptorBuilder( "format", "formatdatetime" ) functionRegistry.namedDescriptorBuilder( "format", "formatdatetime" )
.setInvariantType(stringType) .setInvariantType(stringType)
.setParameterTypes( TEMPORAL, STRING )
.setArgumentsValidator( formatValidator() ) .setArgumentsValidator( formatValidator() )
.setArgumentListSignature( "(TEMPORAL datetime as STRING pattern)" ) .setArgumentListSignature( "(TEMPORAL datetime as STRING pattern)" )
.register(); .register();
@ -2169,6 +2233,7 @@ public class CommonFunctionFactory {
public void format_toChar() { public void format_toChar() {
functionRegistry.namedDescriptorBuilder( "format", "to_char" ) functionRegistry.namedDescriptorBuilder( "format", "to_char" )
.setInvariantType(stringType) .setInvariantType(stringType)
.setParameterTypes( TEMPORAL, STRING )
.setArgumentsValidator( formatValidator() ) .setArgumentsValidator( formatValidator() )
.setArgumentListSignature( "(TEMPORAL datetime as STRING pattern)" ) .setArgumentListSignature( "(TEMPORAL datetime as STRING pattern)" )
.register(); .register();
@ -2182,6 +2247,7 @@ public class CommonFunctionFactory {
public void format_dateFormat() { public void format_dateFormat() {
functionRegistry.namedDescriptorBuilder( "format", "date_format" ) functionRegistry.namedDescriptorBuilder( "format", "date_format" )
.setInvariantType(stringType) .setInvariantType(stringType)
.setParameterTypes( TEMPORAL, STRING )
.setArgumentsValidator( formatValidator() ) .setArgumentsValidator( formatValidator() )
.setArgumentListSignature( "(TEMPORAL datetime as STRING pattern)" ) .setArgumentListSignature( "(TEMPORAL datetime as STRING pattern)" )
.register(); .register();
@ -2195,6 +2261,7 @@ public class CommonFunctionFactory {
public void format_toVarchar() { public void format_toVarchar() {
functionRegistry.namedDescriptorBuilder( "format", "to_varchar" ) functionRegistry.namedDescriptorBuilder( "format", "to_varchar" )
.setInvariantType(stringType) .setInvariantType(stringType)
.setParameterTypes( TEMPORAL, STRING )
.setArgumentsValidator( formatValidator() ) .setArgumentsValidator( formatValidator() )
.setArgumentListSignature( "(TEMPORAL datetime as STRING pattern)" ) .setArgumentListSignature( "(TEMPORAL datetime as STRING pattern)" )
.register(); .register();
@ -2223,7 +2290,7 @@ public class CommonFunctionFactory {
functionRegistry.patternDescriptorBuilder("collate", "(?1 collate '?2')") functionRegistry.patternDescriptorBuilder("collate", "(?1 collate '?2')")
.setInvariantType(stringType) .setInvariantType(stringType)
.setExactArgumentCount( 2 ) .setExactArgumentCount( 2 )
.setParameterTypes(STRING, ANY) .setParameterTypes(STRING, COLLATION)
.setArgumentListSignature("(STRING string as COLLATION collation)") .setArgumentListSignature("(STRING string as COLLATION collation)")
.register(); .register();
} }

View File

@ -20,6 +20,7 @@ import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer; import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
import org.hibernate.query.sqm.sql.internal.AbstractSqmPathInterpretation; import org.hibernate.query.sqm.sql.internal.AbstractSqmPathInterpretation;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode; import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
@ -58,7 +59,8 @@ public class CountFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
StandardArgumentsValidators.exactly( 1 ), StandardArgumentsValidators.exactly( 1 ),
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.LONG ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.LONG )
) ),
null
); );
this.dialect = dialect; this.dialect = dialect;
this.defaultArgumentRenderingMode = defaultArgumentRenderingMode; this.defaultArgumentRenderingMode = defaultArgumentRenderingMode;
@ -102,9 +104,11 @@ public class CountFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
// In the end, the expression looks like the following: // In the end, the expression looks like the following:
// count(distinct coalesce(nullif(coalesce(col1 || '', '\0'), ''), '\01') || '\0' || coalesce(nullif(coalesce(col2 || '', '\0'), ''), '\02')) // count(distinct coalesce(nullif(coalesce(col1 || '', '\0'), ''), '\01') || '\0' || coalesce(nullif(coalesce(col2 || '', '\0'), ''), '\02'))
if ( caseWrapper ) { if ( caseWrapper ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
sqlAppender.appendSql( "case when " ); sqlAppender.appendSql( "case when " );
filter.accept( translator ); filter.accept( translator );
sqlAppender.appendSql( " then " ); sqlAppender.appendSql( " then " );
translator.getCurrentClauseStack().pop();
} }
sqlAppender.appendSql( "coalesce(nullif(coalesce(" ); sqlAppender.appendSql( "coalesce(nullif(coalesce(" );
renderCastedArgument( sqlAppender, translator, expressions.get( 0 ) ); renderCastedArgument( sqlAppender, translator, expressions.get( 0 ) );
@ -162,7 +166,9 @@ public class CountFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
else if ( !dialect.supportsTupleCounts() ) { else if ( !dialect.supportsTupleCounts() ) {
sqlAppender.appendSql( "case when " ); sqlAppender.appendSql( "case when " );
if ( caseWrapper ) { if ( caseWrapper ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
filter.accept( translator ); filter.accept( translator );
translator.getCurrentClauseStack().pop();
sqlAppender.appendSql( " and " ); sqlAppender.appendSql( " and " );
} }
translator.render( expressions.get( 0 ), defaultArgumentRenderingMode ); translator.render( expressions.get( 0 ), defaultArgumentRenderingMode );
@ -193,9 +199,11 @@ public class CountFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
} }
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
if ( filter != null && !caseWrapper ) { if ( filter != null && !caseWrapper ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
sqlAppender.appendSql( " filter (where " ); sqlAppender.appendSql( " filter (where " );
filter.accept( translator ); filter.accept( translator );
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
translator.getCurrentClauseStack().pop();
} }
} }
@ -250,8 +258,10 @@ public class CountFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
boolean caseWrapper, boolean caseWrapper,
SqlAstNode realArg) { SqlAstNode realArg) {
if ( caseWrapper ) { if ( caseWrapper ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
sqlAppender.appendSql( "case when " ); sqlAppender.appendSql( "case when " );
filter.accept( translator ); filter.accept( translator );
translator.getCurrentClauseStack().pop();
sqlAppender.appendSql( " then " ); sqlAppender.appendSql( " then " );
if ( realArg instanceof Star ) { if ( realArg instanceof Star ) {
sqlAppender.appendSql( "1" ); sqlAppender.appendSql( "1" );

View File

@ -31,7 +31,8 @@ public class CurrentFunction
super( super(
name, name,
StandardArgumentsValidators.NO_ARGS, StandardArgumentsValidators.NO_ARGS,
StandardFunctionReturnTypeResolvers.invariant( type ) StandardFunctionReturnTypeResolvers.invariant( type ),
null
); );
this.sql = sql; this.sql = sql;
} }

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function;
import org.hibernate.dialect.OracleDialect; import org.hibernate.dialect.OracleDialect;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
@ -20,6 +21,9 @@ import org.hibernate.type.spi.TypeConfiguration;
import java.util.List; import java.util.List;
import jakarta.persistence.TemporalType; import jakarta.persistence.TemporalType;
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING;
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL;
/** /**
* DB2's varchar_format() can't handle quoted literal strings in * DB2's varchar_format() can't handle quoted literal strings in
* the format pattern. So just split the pattern into bits, call * the format pattern. So just split the pattern into bits, call
@ -37,7 +41,8 @@ public class DB2FormatEmulation
CommonFunctionFactory.formatValidator(), CommonFunctionFactory.formatValidator(),
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
) ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, TEMPORAL, STRING )
); );
} }

View File

@ -11,6 +11,7 @@ import java.util.List;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode; import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
@ -36,7 +37,8 @@ public class DerbyLpadEmulation
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, INTEGER ), new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, INTEGER ),
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
) ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, STRING, INTEGER )
); );
} }

View File

@ -11,6 +11,7 @@ import java.util.List;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode; import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
@ -36,7 +37,8 @@ public class DerbyRpadEmulation
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, INTEGER ), new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, INTEGER ),
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
) ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, STRING, INTEGER )
); );
} }

View File

@ -12,7 +12,9 @@ import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescript
import org.hibernate.query.sqm.function.FunctionKind; import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -43,7 +45,8 @@ public class EveryAnyEmulation extends AbstractSqmSelfRenderingFunctionDescripto
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 1 ), BOOLEAN ), new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 1 ), BOOLEAN ),
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.BOOLEAN ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.BOOLEAN )
) ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, BOOLEAN )
); );
this.every = every; this.every = every;
} }
@ -56,7 +59,9 @@ public class EveryAnyEmulation extends AbstractSqmSelfRenderingFunctionDescripto
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
sqlAppender.appendSql( "(sum(case when " ); sqlAppender.appendSql( "(sum(case when " );
if ( filter != null ) { if ( filter != null ) {
walker.getCurrentClauseStack().push( Clause.WHERE );
filter.accept( walker ); filter.accept( walker );
walker.getCurrentClauseStack().pop();
sqlAppender.appendSql( " then case when " ); sqlAppender.appendSql( " then case when " );
sqlAstArguments.get( 0 ).accept( walker ); sqlAstArguments.get( 0 ).accept( walker );
if ( every ) { if ( every ) {

View File

@ -16,6 +16,7 @@ import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction; import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.query.sqm.tree.expression.*; import org.hibernate.query.sqm.tree.expression.*;
@ -44,14 +45,15 @@ public class ExtractFunction
private final Dialect dialect; private final Dialect dialect;
public ExtractFunction(Dialect dialect) { public ExtractFunction(Dialect dialect, TypeConfiguration typeConfiguration) {
super( super(
"extract", "extract",
new ArgumentTypesValidator( new ArgumentTypesValidator(
StandardArgumentsValidators.exactly( 2 ), StandardArgumentsValidators.exactly( 2 ),
TEMPORAL_UNIT, TEMPORAL TEMPORAL_UNIT, TEMPORAL
), ),
StandardFunctionReturnTypeResolvers.useArgType( 1 ) StandardFunctionReturnTypeResolvers.useArgType( 1 ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, TEMPORAL_UNIT, TEMPORAL )
); );
this.dialect = dialect; this.dialect = dialect;
} }

View File

@ -12,6 +12,7 @@ import java.util.List;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionKind; import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -32,7 +33,8 @@ public class HypotheticalSetFunction extends AbstractSqmSelfRenderingFunctionDes
null, null,
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( returnType ) typeConfiguration.getBasicTypeRegistry().resolve( returnType )
) ),
null
); );
} }
@ -74,6 +76,7 @@ public class HypotheticalSetFunction extends AbstractSqmSelfRenderingFunctionDes
} }
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
if ( withinGroup != null && !withinGroup.isEmpty() ) { if ( withinGroup != null && !withinGroup.isEmpty() ) {
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
sqlAppender.appendSql( " within group (order by " ); sqlAppender.appendSql( " within group (order by " );
withinGroup.get( 0 ).accept( translator ); withinGroup.get( 0 ).accept( translator );
for ( int i = 1; i < withinGroup.size(); i++ ) { for ( int i = 1; i < withinGroup.size(); i++ ) {
@ -81,11 +84,14 @@ public class HypotheticalSetFunction extends AbstractSqmSelfRenderingFunctionDes
withinGroup.get( i ).accept( translator ); withinGroup.get( i ).accept( translator );
} }
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
translator.getCurrentClauseStack().pop();
} }
if ( filter != null ) { if ( filter != null ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
sqlAppender.appendSql( " filter (where " ); sqlAppender.appendSql( " filter (where " );
filter.accept( translator ); filter.accept( translator );
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
translator.getCurrentClauseStack().pop();
} }
} }

View File

@ -15,6 +15,7 @@ import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor; import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.query.sqm.tree.expression.SqmBinaryArithmetic; import org.hibernate.query.sqm.tree.expression.SqmBinaryArithmetic;
@ -54,7 +55,8 @@ public class InsertSubstringOverlayEmulation
), ),
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
) ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, STRING, STRING, INTEGER, INTEGER )
); );
this.strictSubstring = strictSubstring; this.strictSubstring = strictSubstring;
} }

View File

@ -41,7 +41,7 @@ public class IntegralTimestampaddFunction
private final BasicType<Integer> integerType; private final BasicType<Integer> integerType;
public IntegralTimestampaddFunction(Dialect dialect, TypeConfiguration typeConfiguration) { public IntegralTimestampaddFunction(Dialect dialect, TypeConfiguration typeConfiguration) {
super( dialect ); super( dialect, typeConfiguration );
this.dialect = dialect; this.dialect = dialect;
this.integerType = typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ); this.integerType = typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER );
//This is kinda wrong, we're supposed to use findFunctionDescriptor("cast"), not instantiate CastFunction //This is kinda wrong, we're supposed to use findFunctionDescriptor("cast"), not instantiate CastFunction

View File

@ -20,10 +20,12 @@ import org.hibernate.query.sqm.function.SelfRenderingSqmOrderedSetAggregateFunct
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.FunctionParameterType; import org.hibernate.query.sqm.produce.function.FunctionParameterType;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter; import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.query.sqm.tree.predicate.SqmPredicate; import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
import org.hibernate.query.sqm.tree.select.SqmOrderByClause; import org.hibernate.query.sqm.tree.select.SqmOrderByClause;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -44,7 +46,10 @@ public class InverseDistributionFunction extends AbstractSqmSelfRenderingFunctio
parameterType == null parameterType == null
? StandardArgumentsValidators.exactly( 0 ) ? StandardArgumentsValidators.exactly( 0 )
: new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 1 ), parameterType ), : new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 1 ), parameterType ),
null null,
parameterType == null
? null
: StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, parameterType )
); );
} }
@ -103,6 +108,7 @@ public class InverseDistributionFunction extends AbstractSqmSelfRenderingFunctio
} }
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
if ( withinGroup != null && !withinGroup.isEmpty() ) { if ( withinGroup != null && !withinGroup.isEmpty() ) {
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
sqlAppender.appendSql( " within group (order by " ); sqlAppender.appendSql( " within group (order by " );
withinGroup.get( 0 ).accept( translator ); withinGroup.get( 0 ).accept( translator );
for ( int i = 1; i < withinGroup.size(); i++ ) { for ( int i = 1; i < withinGroup.size(); i++ ) {
@ -110,11 +116,14 @@ public class InverseDistributionFunction extends AbstractSqmSelfRenderingFunctio
withinGroup.get( i ).accept( translator ); withinGroup.get( i ).accept( translator );
} }
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
translator.getCurrentClauseStack().pop();
} }
if ( filter != null ) { if ( filter != null ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
sqlAppender.appendSql( " filter (where " ); sqlAppender.appendSql( " filter (where " );
filter.accept( translator ); filter.accept( translator );
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
translator.getCurrentClauseStack().pop();
} }
} }

View File

@ -13,7 +13,9 @@ import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescript
import org.hibernate.query.sqm.function.FunctionKind; import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -40,7 +42,8 @@ public class ListaggFunction extends AbstractSqmSelfRenderingFunctionDescriptor
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, STRING ), new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, STRING ),
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
) ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, STRING, STRING )
); );
this.emptyWithinReplacement = emptyWithinReplacement; this.emptyWithinReplacement = emptyWithinReplacement;
} }
@ -82,7 +85,9 @@ public class ListaggFunction extends AbstractSqmSelfRenderingFunctionDescriptor
} }
if ( caseWrapper ) { if ( caseWrapper ) {
sqlAppender.appendSql( "case when " ); sqlAppender.appendSql( "case when " );
translator.getCurrentClauseStack().push( Clause.WHERE );
filter.accept( translator ); filter.accept( translator );
translator.getCurrentClauseStack().pop();
sqlAppender.appendSql( " then " ); sqlAppender.appendSql( " then " );
arg.accept( translator ); arg.accept( translator );
sqlAppender.appendSql( " else null end" ); sqlAppender.appendSql( " else null end" );
@ -96,6 +101,7 @@ public class ListaggFunction extends AbstractSqmSelfRenderingFunctionDescriptor
} }
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
if ( withinGroup != null && !withinGroup.isEmpty() ) { if ( withinGroup != null && !withinGroup.isEmpty() ) {
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
sqlAppender.appendSql( " within group (order by " ); sqlAppender.appendSql( " within group (order by " );
withinGroup.get( 0 ).accept( translator ); withinGroup.get( 0 ).accept( translator );
for ( int i = 1; i < withinGroup.size(); i++ ) { for ( int i = 1; i < withinGroup.size(); i++ ) {
@ -103,15 +109,18 @@ public class ListaggFunction extends AbstractSqmSelfRenderingFunctionDescriptor
withinGroup.get( i ).accept( translator ); withinGroup.get( i ).accept( translator );
} }
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
translator.getCurrentClauseStack().pop();
} }
else if ( emptyWithinReplacement != null ) { else if ( emptyWithinReplacement != null ) {
sqlAppender.appendSql( ' ' ); sqlAppender.appendSql( ' ' );
sqlAppender.appendSql( emptyWithinReplacement ); sqlAppender.appendSql( emptyWithinReplacement );
} }
if ( !caseWrapper && filter != null ) { if ( !caseWrapper && filter != null ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
sqlAppender.appendSql( " filter (where " ); sqlAppender.appendSql( " filter (where " );
filter.accept( translator ); filter.accept( translator );
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
translator.getCurrentClauseStack().pop();
} }
} }

View File

@ -13,7 +13,9 @@ import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescript
import org.hibernate.query.sqm.function.FunctionKind; import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -41,7 +43,8 @@ public class ListaggGroupConcatEmulation extends AbstractSqmSelfRenderingFunctio
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, STRING ), new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, STRING ),
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
) ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, STRING, STRING )
); );
} }
@ -81,22 +84,26 @@ public class ListaggGroupConcatEmulation extends AbstractSqmSelfRenderingFunctio
arg = (Expression) firstArg; arg = (Expression) firstArg;
} }
if ( caseWrapper ) { if ( caseWrapper ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
sqlAppender.appendSql( "case when " ); sqlAppender.appendSql( "case when " );
filter.accept( translator ); filter.accept( translator );
sqlAppender.appendSql( " then " ); sqlAppender.appendSql( " then " );
arg.accept( translator ); arg.accept( translator );
sqlAppender.appendSql( " else null end" ); sqlAppender.appendSql( " else null end" );
translator.getCurrentClauseStack().pop();
} }
else { else {
arg.accept( translator ); arg.accept( translator );
} }
if ( withinGroup != null && !withinGroup.isEmpty() ) { if ( withinGroup != null && !withinGroup.isEmpty() ) {
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
sqlAppender.appendSql( " order by " ); sqlAppender.appendSql( " order by " );
withinGroup.get( 0 ).accept( translator ); withinGroup.get( 0 ).accept( translator );
for ( int i = 1; i < withinGroup.size(); i++ ) { for ( int i = 1; i < withinGroup.size(); i++ ) {
sqlAppender.appendSql( ',' ); sqlAppender.appendSql( ',' );
withinGroup.get( i ).accept( translator ); withinGroup.get( i ).accept( translator );
} }
translator.getCurrentClauseStack().pop();
} }
if ( sqlAstArguments.size() != 1 ) { if ( sqlAstArguments.size() != 1 ) {
SqlAstNode separator = sqlAstArguments.get( 1 ); SqlAstNode separator = sqlAstArguments.get( 1 );
@ -109,9 +116,11 @@ public class ListaggGroupConcatEmulation extends AbstractSqmSelfRenderingFunctio
} }
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
if ( !caseWrapper && filter != null ) { if ( !caseWrapper && filter != null ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
sqlAppender.appendSql( " filter (where " ); sqlAppender.appendSql( " filter (where " );
filter.accept( translator ); filter.accept( translator );
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
translator.getCurrentClauseStack().pop();
} }
} }

View File

@ -15,7 +15,9 @@ import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescript
import org.hibernate.query.sqm.function.FunctionKind; import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -51,7 +53,8 @@ public class ListaggStringAggEmulation extends AbstractSqmSelfRenderingFunctionD
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, STRING ), new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, STRING ),
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
) ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, STRING, STRING )
); );
this.functionName = functionName; this.functionName = functionName;
this.stringType = stringType; this.stringType = stringType;
@ -95,11 +98,13 @@ public class ListaggStringAggEmulation extends AbstractSqmSelfRenderingFunctionD
arg = (Expression) firstArg; arg = (Expression) firstArg;
} }
if ( caseWrapper ) { if ( caseWrapper ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
sqlAppender.appendSql( "case when " ); sqlAppender.appendSql( "case when " );
filter.accept( translator ); filter.accept( translator );
sqlAppender.appendSql( " then " ); sqlAppender.appendSql( " then " );
renderAsString( sqlAppender, translator, arg ); renderAsString( sqlAppender, translator, arg );
sqlAppender.appendSql( " else null end" ); sqlAppender.appendSql( " else null end" );
translator.getCurrentClauseStack().pop();
} }
else { else {
renderAsString( sqlAppender, translator, arg ); renderAsString( sqlAppender, translator, arg );
@ -113,16 +118,19 @@ public class ListaggStringAggEmulation extends AbstractSqmSelfRenderingFunctionD
sqlAppender.appendSql( ',' ); sqlAppender.appendSql( ',' );
separator.accept( translator ); separator.accept( translator );
if ( !withinGroupClause && withinGroup != null && !withinGroup.isEmpty() ) { if ( !withinGroupClause && withinGroup != null && !withinGroup.isEmpty() ) {
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
sqlAppender.appendSql( " order by " ); sqlAppender.appendSql( " order by " );
withinGroup.get( 0 ).accept( translator ); withinGroup.get( 0 ).accept( translator );
for ( int i = 1; i < withinGroup.size(); i++ ) { for ( int i = 1; i < withinGroup.size(); i++ ) {
sqlAppender.appendSql( ',' ); sqlAppender.appendSql( ',' );
withinGroup.get( i ).accept( translator ); withinGroup.get( i ).accept( translator );
} }
translator.getCurrentClauseStack().pop();
} }
} }
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
if ( withinGroupClause && withinGroup != null && !withinGroup.isEmpty() ) { if ( withinGroupClause && withinGroup != null && !withinGroup.isEmpty() ) {
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
sqlAppender.appendSql( " within group (order by " ); sqlAppender.appendSql( " within group (order by " );
withinGroup.get( 0 ).accept( translator ); withinGroup.get( 0 ).accept( translator );
for ( int i = 1; i < withinGroup.size(); i++ ) { for ( int i = 1; i < withinGroup.size(); i++ ) {
@ -130,11 +138,14 @@ public class ListaggStringAggEmulation extends AbstractSqmSelfRenderingFunctionD
withinGroup.get( i ).accept( translator ); withinGroup.get( i ).accept( translator );
} }
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
translator.getCurrentClauseStack().pop();
} }
if ( !caseWrapper && filter != null ) { if ( !caseWrapper && filter != null ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
sqlAppender.appendSql( " filter (where " ); sqlAppender.appendSql( " filter (where " );
filter.accept( translator ); filter.accept( translator );
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
translator.getCurrentClauseStack().pop();
} }
} }

View File

@ -12,6 +12,7 @@ import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction; import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
@ -34,7 +35,8 @@ public class LocatePositionEmulation extends AbstractSqmFunctionDescriptor {
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, STRING ), new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, STRING ),
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER )
) ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, STRING, STRING )
); );
} }

View File

@ -13,6 +13,7 @@ import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction; import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.query.sqm.tree.expression.SqmTrimSpecification; import org.hibernate.query.sqm.tree.expression.SqmTrimSpecification;
@ -47,7 +48,8 @@ public class LpadRpadPadEmulation
), ),
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
) ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, STRING, INTEGER, TRIM_SPEC, STRING )
); );
} }

View File

@ -13,7 +13,9 @@ import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.FunctionParameterType; import org.hibernate.query.sqm.produce.function.FunctionParameterType;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -41,7 +43,8 @@ public class MinMaxCaseEveryAnyEmulation extends AbstractSqmSelfRenderingFunctio
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 1 ), FunctionParameterType.BOOLEAN ), new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 1 ), FunctionParameterType.BOOLEAN ),
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.BOOLEAN ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.BOOLEAN )
) ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, FunctionParameterType.BOOLEAN )
); );
this.every = every; this.every = every;
} }
@ -59,7 +62,9 @@ public class MinMaxCaseEveryAnyEmulation extends AbstractSqmSelfRenderingFunctio
sqlAppender.appendSql( "max(case when " ); sqlAppender.appendSql( "max(case when " );
} }
if ( filter != null ) { if ( filter != null ) {
walker.getCurrentClauseStack().push( Clause.WHERE );
filter.accept( walker ); filter.accept( walker );
walker.getCurrentClauseStack().pop();
sqlAppender.appendSql( " then case when " ); sqlAppender.appendSql( " then case when " );
sqlAstArguments.get( 0 ).accept( walker ); sqlAstArguments.get( 0 ).accept( walker );
sqlAppender.appendSql( " then 1 else 0 end else null end)" ); sqlAppender.appendSql( " then 1 else 0 end else null end)" );

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function;
import java.util.List; import java.util.List;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -43,19 +44,27 @@ public class ModeStatsModeEmulation extends InverseDistributionFunction {
throw new IllegalArgumentException( "MODE function requires a WITHIN GROUP clause with exactly one order by item!" ); throw new IllegalArgumentException( "MODE function requires a WITHIN GROUP clause with exactly one order by item!" );
} }
if ( caseWrapper ) { if ( caseWrapper ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
sqlAppender.appendSql( "case when " ); sqlAppender.appendSql( "case when " );
filter.accept( translator ); filter.accept( translator );
translator.getCurrentClauseStack().pop();
sqlAppender.appendSql( " then " ); sqlAppender.appendSql( " then " );
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
withinGroup.get( 0 ).accept( translator ); withinGroup.get( 0 ).accept( translator );
sqlAppender.appendSql( " else null end)" ); sqlAppender.appendSql( " else null end)" );
translator.getCurrentClauseStack().pop();
} }
else { else {
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
withinGroup.get( 0 ).accept( translator ); withinGroup.get( 0 ).accept( translator );
translator.getCurrentClauseStack().pop();
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
if ( filter != null ) { if ( filter != null ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
sqlAppender.appendSql( " filter (where " ); sqlAppender.appendSql( " filter (where " );
filter.accept( translator ); filter.accept( translator );
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
translator.getCurrentClauseStack().pop();
} }
} }
} }

View File

@ -12,6 +12,7 @@ import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction; import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor; import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.query.sqm.tree.expression.SqmExpression; import org.hibernate.query.sqm.tree.expression.SqmExpression;
@ -35,7 +36,8 @@ public class NvlCoalesceEmulation
super( super(
"coalesce", "coalesce",
StandardArgumentsValidators.min( 2 ), StandardArgumentsValidators.min( 2 ),
StandardFunctionReturnTypeResolvers.useFirstNonNull() StandardFunctionReturnTypeResolvers.useFirstNonNull(),
StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE
); );
} }

View File

@ -11,6 +11,7 @@ import java.util.List;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
@ -32,7 +33,8 @@ public class QuantifiedLeastGreatestEmulation
super( super(
least ? "least" : "greatest", least ? "least" : "greatest",
new ArgumentTypesValidator( StandardArgumentsValidators.min( 2 ), COMPARABLE, COMPARABLE ), new ArgumentTypesValidator( StandardArgumentsValidators.min( 2 ), COMPARABLE, COMPARABLE ),
StandardFunctionReturnTypeResolvers.useFirstNonNull() StandardFunctionReturnTypeResolvers.useFirstNonNull(),
StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE
); );
this.operator = least ? "<=" : ">="; this.operator = least ? "<=" : ">=";
} }

View File

@ -11,8 +11,11 @@ import java.util.List;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionKind; import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.FunctionParameterType;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -42,7 +45,8 @@ public class SQLServerEveryAnyEmulation extends AbstractSqmSelfRenderingFunction
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 1 ), BOOLEAN ), new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 1 ), BOOLEAN ),
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.BOOLEAN ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.BOOLEAN )
) ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, FunctionParameterType.BOOLEAN )
); );
this.every = every; this.every = every;
} }
@ -60,7 +64,9 @@ public class SQLServerEveryAnyEmulation extends AbstractSqmSelfRenderingFunction
sqlAppender.appendSql( "max(iif(" ); sqlAppender.appendSql( "max(iif(" );
} }
if ( filter != null ) { if ( filter != null ) {
walker.getCurrentClauseStack().push( Clause.WHERE );
filter.accept( walker ); filter.accept( walker );
walker.getCurrentClauseStack().pop();
sqlAppender.appendSql( ",iif(" ); sqlAppender.appendSql( ",iif(" );
sqlAstArguments.get( 0 ).accept( walker ); sqlAstArguments.get( 0 ).accept( walker );
sqlAppender.appendSql( ",1,0),null))" ); sqlAppender.appendSql( ",1,0),null))" );

View File

@ -11,6 +11,7 @@ import jakarta.persistence.TemporalType;
import org.hibernate.dialect.SQLServerDialect; import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
@ -20,6 +21,9 @@ import org.hibernate.sql.ast.tree.expression.Format;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING;
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL;
/** /**
* SQL Server behaves strangely when the first argument to format is of the type time, so we cast to datetime. * SQL Server behaves strangely when the first argument to format is of the type time, so we cast to datetime.
* *
@ -35,7 +39,8 @@ public class SQLServerFormatEmulation extends AbstractSqmSelfRenderingFunctionDe
CommonFunctionFactory.formatValidator(), CommonFunctionFactory.formatValidator(),
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
) ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, TEMPORAL, STRING )
); );
this.dialect = dialect; this.dialect = dialect;
} }

View File

@ -29,7 +29,8 @@ public class SqlFunction
super( super(
"sql", "sql",
StandardArgumentsValidators.min( 1 ), StandardArgumentsValidators.min( 1 ),
StandardFunctionReturnTypeResolvers.invariant( JavaObjectType.INSTANCE ) StandardFunctionReturnTypeResolvers.invariant( JavaObjectType.INSTANCE ),
null
); );
} }

View File

@ -15,6 +15,7 @@ import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescript
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression; import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer; import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
@ -22,6 +23,7 @@ import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.DurationUnit; import org.hibernate.sql.ast.tree.expression.DurationUnit;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.spi.TypeConfiguration;
import java.util.List; import java.util.List;
@ -46,14 +48,15 @@ public class TimestampaddFunction
private final Dialect dialect; private final Dialect dialect;
public TimestampaddFunction(Dialect dialect) { public TimestampaddFunction(Dialect dialect, TypeConfiguration typeConfiguration) {
super( super(
"timestampadd", "timestampadd",
new ArgumentTypesValidator( new ArgumentTypesValidator(
StandardArgumentsValidators.exactly( 3 ), StandardArgumentsValidators.exactly( 3 ),
TEMPORAL_UNIT, INTEGER, TEMPORAL TEMPORAL_UNIT, INTEGER, TEMPORAL
), ),
StandardFunctionReturnTypeResolvers.useArgType( 3 ) StandardFunctionReturnTypeResolvers.useArgType( 3 ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, TEMPORAL_UNIT, INTEGER, TEMPORAL )
); );
this.dialect = dialect; this.dialect = dialect;
} }

View File

@ -8,7 +8,6 @@ package org.hibernate.dialect.function;
import java.util.List; import java.util.List;
import jakarta.persistence.TemporalType;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.query.ReturnableType; import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.TemporalUnit; import org.hibernate.query.sqm.TemporalUnit;
@ -16,6 +15,7 @@ import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescript
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression; import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer; import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
@ -26,6 +26,8 @@ import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
import jakarta.persistence.TemporalType;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL; import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL;
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL_UNIT; import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL_UNIT;
@ -54,7 +56,8 @@ public class TimestampdiffFunction
), ),
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.LONG ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.LONG )
) ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, TEMPORAL_UNIT, TEMPORAL, TEMPORAL )
); );
this.dialect = dialect; this.dialect = dialect;
} }

View File

@ -11,6 +11,7 @@ import org.hibernate.query.sqm.TrimSpec;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer; import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
@ -50,7 +51,8 @@ public class TrimFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
), ),
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
) ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, TRIM_SPEC, STRING, STRING )
); );
this.dialect = dialect; this.dialect = dialect;
} }

View File

@ -3191,7 +3191,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
null, null,
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
resolveExpressibleTypeBasic( Object.class ) resolveExpressibleTypeBasic( Object.class )
) ),
null
); );
} }
return functionTemplate.generateSqmExpression( return functionTemplate.generateSqmExpression(
@ -3262,6 +3263,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
StandardFunctionReturnTypeResolvers.invariant( StandardFunctionReturnTypeResolvers.invariant(
resolveExpressibleTypeBasic( Object.class ) resolveExpressibleTypeBasic( Object.class )
), ),
null,
functionName, functionName,
functionKind, functionKind,
null, null,

View File

@ -6,45 +6,52 @@
*/ */
package org.hibernate.query.sqm.function; package org.hibernate.query.sqm.function;
import java.util.List;
import org.hibernate.query.ReturnableType; import org.hibernate.query.ReturnableType;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator; import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.FunctionArgumentTypeResolver;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver; import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.query.sqm.tree.SqmVisitableNode;
import org.hibernate.query.sqm.tree.predicate.SqmPredicate; import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
import org.hibernate.query.sqm.tree.select.SqmOrderByClause; import org.hibernate.query.sqm.tree.select.SqmOrderByClause;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
import java.util.ArrayList;
import java.util.List;
import static java.util.Collections.emptyList;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public abstract class AbstractSqmFunctionDescriptor implements SqmFunctionDescriptor { public abstract class AbstractSqmFunctionDescriptor implements SqmFunctionDescriptor {
private final ArgumentsValidator argumentsValidator; private final ArgumentsValidator argumentsValidator;
private final FunctionReturnTypeResolver returnTypeResolver; private final FunctionReturnTypeResolver returnTypeResolver;
private final FunctionArgumentTypeResolver functionArgumentTypeResolver;
private final String name; private final String name;
public AbstractSqmFunctionDescriptor(String name) { public AbstractSqmFunctionDescriptor(String name) {
this( name, null, null ); this( name, null, null, null );
} }
public AbstractSqmFunctionDescriptor(String name, ArgumentsValidator argumentsValidator) { public AbstractSqmFunctionDescriptor(
this( name, argumentsValidator, null ); String name,
ArgumentsValidator argumentsValidator) {
this( name, argumentsValidator, null, null );
} }
public AbstractSqmFunctionDescriptor( public AbstractSqmFunctionDescriptor(
String name, String name,
ArgumentsValidator argumentsValidator, ArgumentsValidator argumentsValidator,
FunctionReturnTypeResolver returnTypeResolver) { FunctionArgumentTypeResolver argumentTypeResolver) {
this( name, argumentsValidator, null, argumentTypeResolver );
}
public AbstractSqmFunctionDescriptor(
String name,
ArgumentsValidator argumentsValidator,
FunctionReturnTypeResolver returnTypeResolver,
FunctionArgumentTypeResolver argumentTypeResolver) {
this.name = name; this.name = name;
this.argumentsValidator = argumentsValidator == null this.argumentsValidator = argumentsValidator == null
? StandardArgumentsValidators.NONE ? StandardArgumentsValidators.NONE
@ -52,6 +59,9 @@ public abstract class AbstractSqmFunctionDescriptor implements SqmFunctionDescri
this.returnTypeResolver = returnTypeResolver == null this.returnTypeResolver = returnTypeResolver == null
? StandardFunctionReturnTypeResolvers.useFirstNonNull() ? StandardFunctionReturnTypeResolvers.useFirstNonNull()
: returnTypeResolver; : returnTypeResolver;
this.functionArgumentTypeResolver = argumentTypeResolver == null
? StandardFunctionArgumentTypeResolvers.NULL
: argumentTypeResolver;
} }
public String getName() { public String getName() {
@ -71,6 +81,10 @@ public abstract class AbstractSqmFunctionDescriptor implements SqmFunctionDescri
return returnTypeResolver; return returnTypeResolver;
} }
public FunctionArgumentTypeResolver getArgumentTypeResolver() {
return functionArgumentTypeResolver;
}
public String getReturnSignature() { public String getReturnSignature() {
String result = returnTypeResolver.getReturnType(); String result = returnTypeResolver.getReturnType();
return result.isEmpty() ? "" : result + " "; return result.isEmpty() ? "" : result + " ";
@ -81,23 +95,6 @@ public abstract class AbstractSqmFunctionDescriptor implements SqmFunctionDescri
return alwaysIncludesParentheses() ? args : "()".equals(args) ? "" : "[" + args + "]"; return alwaysIncludesParentheses() ? args : "()".equals(args) ? "" : "[" + args + "]";
} }
private static SqlAstNode toSqlAstNode(Object arg, SqmToSqlAstConverter walker) {
return (SqlAstNode) arg;
}
public static List<SqlAstNode> resolveSqlAstArguments(List<? extends SqmTypedNode<?>> sqmArguments, SqmToSqlAstConverter walker) {
if ( sqmArguments == null || sqmArguments.isEmpty() ) {
return emptyList();
}
final ArrayList<SqlAstNode> sqlAstArguments = new ArrayList<>();
for ( SqmTypedNode<?> sqmArgument : sqmArguments ) {
sqlAstArguments.add( toSqlAstNode( ((SqmVisitableNode) sqmArgument).accept( walker ), walker ) );
}
return sqlAstArguments;
}
@Override @Override
public final <T> SelfRenderingSqmFunction<T> generateSqmExpression( public final <T> SelfRenderingSqmFunction<T> generateSqmExpression(
List<? extends SqmTypedNode<?>> arguments, List<? extends SqmTypedNode<?>> arguments,

View File

@ -9,6 +9,7 @@ package org.hibernate.query.sqm.function;
import org.hibernate.query.ReturnableType; import org.hibernate.query.ReturnableType;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator; import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.FunctionArgumentTypeResolver;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver; import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.query.sqm.tree.predicate.SqmPredicate; import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
@ -33,8 +34,9 @@ public abstract class AbstractSqmSelfRenderingFunctionDescriptor
public AbstractSqmSelfRenderingFunctionDescriptor( public AbstractSqmSelfRenderingFunctionDescriptor(
String name, String name,
ArgumentsValidator argumentsValidator, ArgumentsValidator argumentsValidator,
FunctionReturnTypeResolver returnTypeResolver) { FunctionReturnTypeResolver returnTypeResolver,
super( name, argumentsValidator, returnTypeResolver ); FunctionArgumentTypeResolver argumentTypeResolver) {
super( name, argumentsValidator, returnTypeResolver, argumentTypeResolver );
this.functionKind = FunctionKind.NORMAL; this.functionKind = FunctionKind.NORMAL;
} }
@ -42,8 +44,9 @@ public abstract class AbstractSqmSelfRenderingFunctionDescriptor
String name, String name,
FunctionKind functionKind, FunctionKind functionKind,
ArgumentsValidator argumentsValidator, ArgumentsValidator argumentsValidator,
FunctionReturnTypeResolver returnTypeResolver) { FunctionReturnTypeResolver returnTypeResolver,
super( name, argumentsValidator, returnTypeResolver ); FunctionArgumentTypeResolver argumentTypeResolver) {
super( name, argumentsValidator, returnTypeResolver, argumentTypeResolver );
this.functionKind = functionKind; this.functionKind = functionKind;
} }

View File

@ -11,6 +11,7 @@ import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.FunctionParameterType; import org.hibernate.query.sqm.produce.function.FunctionParameterType;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
@ -60,6 +61,7 @@ public class MultipatternSqmFunctionDescriptor extends AbstractSqmFunctionDescri
String name, String name,
SqmFunctionDescriptor[] functions, SqmFunctionDescriptor[] functions,
BasicType<?> type, BasicType<?> type,
TypeConfiguration typeConfiguration,
FunctionParameterType... parameterTypes) { FunctionParameterType... parameterTypes) {
super( super(
name, name,
@ -70,7 +72,8 @@ public class MultipatternSqmFunctionDescriptor extends AbstractSqmFunctionDescri
), ),
parameterTypes parameterTypes
), ),
StandardFunctionReturnTypeResolvers.invariant( type ) StandardFunctionReturnTypeResolvers.invariant( type ),
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, parameterTypes )
); );
this.functions = functions; this.functions = functions;
} }

View File

@ -7,7 +7,9 @@
package org.hibernate.query.sqm.function; package org.hibernate.query.sqm.function;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator; import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.FunctionArgumentTypeResolver;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver; import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode; import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
@ -47,6 +49,7 @@ public class NamedSqmFunctionDescriptor
useParenthesesWhenNoArgs, useParenthesesWhenNoArgs,
argumentsValidator, argumentsValidator,
returnTypeResolver, returnTypeResolver,
null,
functionName, functionName,
FunctionKind.NORMAL, FunctionKind.NORMAL,
null, null,
@ -59,11 +62,31 @@ public class NamedSqmFunctionDescriptor
boolean useParenthesesWhenNoArgs, boolean useParenthesesWhenNoArgs,
ArgumentsValidator argumentsValidator, ArgumentsValidator argumentsValidator,
FunctionReturnTypeResolver returnTypeResolver, FunctionReturnTypeResolver returnTypeResolver,
FunctionArgumentTypeResolver argumentTypeResolver) {
this(
functionName,
useParenthesesWhenNoArgs,
argumentsValidator,
returnTypeResolver,
argumentTypeResolver,
functionName,
FunctionKind.NORMAL,
null,
SqlAstNodeRenderingMode.DEFAULT
);
}
public NamedSqmFunctionDescriptor(
String functionName,
boolean useParenthesesWhenNoArgs,
ArgumentsValidator argumentsValidator,
FunctionReturnTypeResolver returnTypeResolver,
FunctionArgumentTypeResolver argumentTypeResolver,
String name, String name,
FunctionKind functionKind, FunctionKind functionKind,
String argumentListSignature, String argumentListSignature,
SqlAstNodeRenderingMode argumentRenderingMode) { SqlAstNodeRenderingMode argumentRenderingMode) {
super( name, functionKind, argumentsValidator, returnTypeResolver ); super( name, functionKind, argumentsValidator, returnTypeResolver, argumentTypeResolver );
this.functionName = functionName; this.functionName = functionName;
this.useParenthesesWhenNoArgs = useParenthesesWhenNoArgs; this.useParenthesesWhenNoArgs = useParenthesesWhenNoArgs;
@ -150,8 +173,10 @@ public class NamedSqmFunctionDescriptor
sqlAppender.appendSql( "," ); sqlAppender.appendSql( "," );
} }
if ( caseWrapper && !( arg instanceof Distinct ) ) { if ( caseWrapper && !( arg instanceof Distinct ) ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
sqlAppender.appendSql( "case when " ); sqlAppender.appendSql( "case when " );
filter.accept( translator ); filter.accept( translator );
translator.getCurrentClauseStack().pop();
sqlAppender.appendSql( " then " ); sqlAppender.appendSql( " then " );
if ( ( arg instanceof Star ) ) { if ( ( arg instanceof Star ) ) {
sqlAppender.appendSql( "1" ); sqlAppender.appendSql( "1" );
@ -172,6 +197,7 @@ public class NamedSqmFunctionDescriptor
} }
if ( withinGroup != null && !withinGroup.isEmpty() ) { if ( withinGroup != null && !withinGroup.isEmpty() ) {
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
sqlAppender.appendSql( " within group (order by" ); sqlAppender.appendSql( " within group (order by" );
translator.render( withinGroup.get( 0 ), argumentRenderingMode ); translator.render( withinGroup.get( 0 ), argumentRenderingMode );
for ( int i = 1; i < withinGroup.size(); i++ ) { for ( int i = 1; i < withinGroup.size(); i++ ) {
@ -179,6 +205,7 @@ public class NamedSqmFunctionDescriptor
translator.render( withinGroup.get( 0 ), argumentRenderingMode ); translator.render( withinGroup.get( 0 ), argumentRenderingMode );
} }
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
translator.getCurrentClauseStack().pop();
} }
if ( fromFirst != null ) { if ( fromFirst != null ) {
@ -199,9 +226,11 @@ public class NamedSqmFunctionDescriptor
} }
if ( filter != null && !caseWrapper ) { if ( filter != null && !caseWrapper ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
sqlAppender.appendSql( " filter (where " ); sqlAppender.appendSql( " filter (where " );
filter.accept( translator ); filter.accept( translator );
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
translator.getCurrentClauseStack().pop();
} }
} }

View File

@ -7,6 +7,7 @@
package org.hibernate.query.sqm.function; package org.hibernate.query.sqm.function;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator; import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.FunctionArgumentTypeResolver;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver; import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer; import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
@ -48,6 +49,7 @@ public class PatternBasedSqmFunctionDescriptor
PatternRenderer renderer, PatternRenderer renderer,
ArgumentsValidator argumentsValidator, ArgumentsValidator argumentsValidator,
FunctionReturnTypeResolver returnTypeResolver, FunctionReturnTypeResolver returnTypeResolver,
FunctionArgumentTypeResolver argumentTypeResolver,
String name, String name,
FunctionKind functionKind, FunctionKind functionKind,
String argumentListSignature) { String argumentListSignature) {
@ -63,7 +65,8 @@ public class PatternBasedSqmFunctionDescriptor
: renderer.hasVarargs() : renderer.hasVarargs()
? StandardArgumentsValidators.min( renderer.getParamCount() ) ? StandardArgumentsValidators.min( renderer.getParamCount() )
: StandardArgumentsValidators.exactly( renderer.getParamCount() ), : StandardArgumentsValidators.exactly( renderer.getParamCount() ),
returnTypeResolver returnTypeResolver,
argumentTypeResolver
); );
this.renderer = renderer; this.renderer = renderer;
this.argumentListSignature = argumentListSignature; this.argumentListSignature = argumentListSignature;

View File

@ -8,6 +8,7 @@ package org.hibernate.query.sqm.function;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Supplier;
import org.hibernate.metamodel.mapping.BasicValuedMapping; import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.MappingModelExpressible; import org.hibernate.metamodel.mapping.MappingModelExpressible;
@ -16,7 +17,9 @@ import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator; import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.FunctionArgumentTypeResolver;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver; import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter; import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.tree.SqmCopyContext; import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;
@ -97,14 +100,38 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
return returnTypeResolver; return returnTypeResolver;
} }
protected static List<SqlAstNode> resolveSqlAstArguments(List<? extends SqmTypedNode<?>> sqmArguments, SqmToSqlAstConverter walker) { protected List<SqlAstNode> resolveSqlAstArguments(List<? extends SqmTypedNode<?>> sqmArguments, SqmToSqlAstConverter walker) {
if ( sqmArguments == null || sqmArguments.isEmpty() ) { if ( sqmArguments == null || sqmArguments.isEmpty() ) {
return emptyList(); return emptyList();
} }
final FunctionArgumentTypeResolver argumentTypeResolver;
if ( getFunctionDescriptor() instanceof AbstractSqmFunctionDescriptor ) {
argumentTypeResolver = ( (AbstractSqmFunctionDescriptor) getFunctionDescriptor() ).getArgumentTypeResolver();
}
else {
argumentTypeResolver = null;
}
if ( argumentTypeResolver == null ) {
final ArrayList<SqlAstNode> sqlAstArguments = new ArrayList<>( sqmArguments.size() );
for ( int i = 0; i < sqmArguments.size(); i++ ) {
sqlAstArguments.add(
(SqlAstNode) ( (SqmVisitableNode) sqmArguments.get( i ) ).accept( walker )
);
}
return sqlAstArguments;
}
final FunctionArgumentTypeResolverTypeAccess typeAccess = new FunctionArgumentTypeResolverTypeAccess(
walker,
this,
argumentTypeResolver
);
final ArrayList<SqlAstNode> sqlAstArguments = new ArrayList<>( sqmArguments.size() ); final ArrayList<SqlAstNode> sqlAstArguments = new ArrayList<>( sqmArguments.size() );
for ( SqmTypedNode<?> sqmArgument : sqmArguments ) { for ( int i = 0; i < sqmArguments.size(); i++ ) {
sqlAstArguments.add( (SqlAstNode) ( (SqmVisitableNode) sqmArgument ).accept( walker ) ); typeAccess.argumentIndex = i;
sqlAstArguments.add(
(SqlAstNode) walker.visitWithInferredType( (SqmVisitableNode) sqmArguments.get( i ), typeAccess )
);
} }
return sqlAstArguments; return sqlAstArguments;
} }
@ -184,4 +211,26 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
return mapping; return mapping;
} }
private static class FunctionArgumentTypeResolverTypeAccess implements Supplier<MappingModelExpressible<?>> {
private final SqmToSqlAstConverter converter;
private final SqmFunction<?> function;
private final FunctionArgumentTypeResolver argumentTypeResolver;
private int argumentIndex;
public FunctionArgumentTypeResolverTypeAccess(
SqmToSqlAstConverter converter,
SqmFunction<?> function,
FunctionArgumentTypeResolver argumentTypeResolver) {
this.converter = converter;
this.function = function;
this.argumentTypeResolver = argumentTypeResolver;
}
@Override
public MappingModelExpressible<?> get() {
return argumentTypeResolver.resolveFunctionArgumentType( function, argumentIndex, converter );
}
}
} }

View File

@ -107,7 +107,7 @@ public class SelfRenderingSqmOrderedSetAggregateFunction<T> extends SelfRenderin
withinGroup = Collections.emptyList(); withinGroup = Collections.emptyList();
} }
else { else {
walker.getCurrentClauseStack().push( Clause.ORDER ); walker.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
try { try {
final List<SqmSortSpecification> sortSpecifications = this.withinGroup.getSortSpecifications(); final List<SqmSortSpecification> sortSpecifications = this.withinGroup.getSortSpecifications();
withinGroup = new ArrayList<>( sortSpecifications.size() ); withinGroup = new ArrayList<>( sortSpecifications.size() );

View File

@ -15,6 +15,7 @@ import org.hibernate.query.sqm.produce.function.FunctionParameterType;
import org.hibernate.query.sqm.produce.function.NamedFunctionDescriptorBuilder; import org.hibernate.query.sqm.produce.function.NamedFunctionDescriptorBuilder;
import org.hibernate.query.sqm.produce.function.PatternFunctionDescriptorBuilder; import org.hibernate.query.sqm.produce.function.PatternFunctionDescriptorBuilder;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.hibernate.type.spi.TypeConfiguration;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -305,8 +306,16 @@ public class SqmFunctionRegistry {
BasicType type, BasicType type,
String pattern0, String pattern0,
String pattern1, String pattern1,
FunctionParameterType parameterType) { FunctionParameterType parameterType,
return registerPatterns( name, type, new FunctionParameterType[]{parameterType}, pattern0, pattern1 ); TypeConfiguration typeConfiguration) {
return registerPatterns(
name,
type,
new FunctionParameterType[] { parameterType },
typeConfiguration,
pattern0,
pattern1
);
} }
/** /**
@ -320,10 +329,17 @@ public class SqmFunctionRegistry {
String pattern1, String pattern1,
String pattern2, String pattern2,
FunctionParameterType parameterType1, FunctionParameterType parameterType1,
FunctionParameterType parameterType2) { FunctionParameterType parameterType2,
return registerPatterns( name, type, TypeConfiguration typeConfiguration) {
new FunctionParameterType[]{parameterType1,parameterType2}, return registerPatterns(
null, pattern1, pattern2 ); name,
type,
new FunctionParameterType[] { parameterType1, parameterType2 },
typeConfiguration,
null,
pattern1,
pattern2
);
} }
/** /**
@ -338,10 +354,18 @@ public class SqmFunctionRegistry {
String pattern3, String pattern3,
FunctionParameterType parameterType1, FunctionParameterType parameterType1,
FunctionParameterType parameterType2, FunctionParameterType parameterType2,
FunctionParameterType parameterType3) { FunctionParameterType parameterType3,
return registerPatterns( name, type, TypeConfiguration typeConfiguration) {
new FunctionParameterType[]{parameterType1,parameterType2,parameterType3}, return registerPatterns(
null, null, pattern2, pattern3 ); name,
type,
new FunctionParameterType[] { parameterType1, parameterType2, parameterType3 },
typeConfiguration,
null,
null,
pattern2,
pattern3
);
} }
/** /**
@ -357,16 +381,31 @@ public class SqmFunctionRegistry {
FunctionParameterType parameterType1, FunctionParameterType parameterType1,
FunctionParameterType parameterType2, FunctionParameterType parameterType2,
FunctionParameterType parameterType3, FunctionParameterType parameterType3,
FunctionParameterType parameterType4) { FunctionParameterType parameterType4,
return registerPatterns( name, type, TypeConfiguration typeConfiguration) {
new FunctionParameterType[]{parameterType1,parameterType2,parameterType3, parameterType4}, return registerPatterns(
null, null, null, pattern3, pattern4 ); name,
type,
new FunctionParameterType[] {
parameterType1,
parameterType2,
parameterType3,
parameterType4
},
typeConfiguration,
null,
null,
null,
pattern3,
pattern4
);
} }
private MultipatternSqmFunctionDescriptor registerPatterns( private MultipatternSqmFunctionDescriptor registerPatterns(
String name, String name,
BasicType<?> type, BasicType<?> type,
FunctionParameterType[] parameterTypes, FunctionParameterType[] parameterTypes,
TypeConfiguration typeConfiguration,
String... patterns) { String... patterns) {
SqmFunctionDescriptor[] descriptors = SqmFunctionDescriptor[] descriptors =
new SqmFunctionDescriptor[patterns.length]; new SqmFunctionDescriptor[patterns.length];
@ -383,7 +422,7 @@ public class SqmFunctionRegistry {
} }
MultipatternSqmFunctionDescriptor function = MultipatternSqmFunctionDescriptor function =
new MultipatternSqmFunctionDescriptor( name, descriptors, type, parameterTypes ); new MultipatternSqmFunctionDescriptor( name, descriptors, type, typeConfiguration, parameterTypes );
register( name, function ); register( name, function );
return function; return function;
} }

View File

@ -1340,7 +1340,8 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
name, name,
true, true,
null, null,
StandardFunctionReturnTypeResolvers.invariant( resultType ) StandardFunctionReturnTypeResolvers.invariant( resultType ),
null
); );
} }

View File

@ -402,18 +402,18 @@ public class SqmUtil {
List<SqmParameter<?>> sqmParameters, List<SqmParameter<?>> sqmParameters,
SqmParameterMappingModelResolutionAccess mappingModelResolutionAccess, SqmParameterMappingModelResolutionAccess mappingModelResolutionAccess,
SessionFactoryImplementor sessionFactory) { SessionFactoryImplementor sessionFactory) {
if ( binding.getType() != null ) { if ( binding.getBindType() instanceof Bindable ) {
return binding.getType();
}
if ( binding.getBindType() != null && binding.getBindType() instanceof Bindable ) {
return (Bindable) binding.getBindType(); return (Bindable) binding.getBindType();
} }
if ( parameter.getHibernateType() != null && parameter.getHibernateType() instanceof Bindable ) { if ( parameter.getHibernateType() instanceof Bindable ) {
return (Bindable) parameter.getHibernateType(); return (Bindable) parameter.getHibernateType();
} }
if ( binding.getType() != null ) {
return binding.getType();
}
for ( int i = 0; i < sqmParameters.size(); i++ ) { for ( int i = 0; i < sqmParameters.size(); i++ ) {
final MappingModelExpressible<?> mappingModelType = mappingModelResolutionAccess final MappingModelExpressible<?> mappingModelType = mappingModelResolutionAccess
.getResolvedMappingModelType( sqmParameters.get( i ) ); .getResolvedMappingModelType( sqmParameters.get( i ) );
@ -425,8 +425,7 @@ public class SqmUtil {
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration(); final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
// assume we have (or can create) a mapping for the parameter's Java type // assume we have (or can create) a mapping for the parameter's Java type
BasicType basicType = typeConfiguration.standardBasicTypeForJavaType( parameter.getParameterType() ); return typeConfiguration.standardBasicTypeForJavaType( parameter.getParameterType() );
return basicType;
} }
public static SqmStatement.ParameterResolutions resolveParameters(SqmStatement<?> statement) { public static SqmStatement.ParameterResolutions resolveParameters(SqmStatement<?> statement) {

View File

@ -0,0 +1,32 @@
/*
* 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.metamodel.mapping.MappingModelExpressible;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.tree.expression.SqmFunction;
/**
* Pluggable strategy for resolving a function argument type for a specific call.
*
* @author Christian Beikov
*/
public interface FunctionArgumentTypeResolver {
/**
* Resolve the argument type for a function given its context-implied return type.
* <p/>
* NOTE : the _context-implied_ type is the type implied by where the function's
* occurs in the query. E.g., for an equality predicate (`something = some_function`)
* the implied type would be defined by the type of `something`.
*
* @return The resolved type.
*/
MappingModelExpressible<?> resolveFunctionArgumentType(
SqmFunction<?> function,
int argumentIndex,
SqmToSqlAstConverter converter);
}

View File

@ -26,6 +26,7 @@ public class NamedFunctionDescriptorBuilder {
private ArgumentsValidator argumentsValidator; private ArgumentsValidator argumentsValidator;
private FunctionReturnTypeResolver returnTypeResolver; private FunctionReturnTypeResolver returnTypeResolver;
private FunctionArgumentTypeResolver argumentTypeResolver;
private boolean useParenthesesWhenNoArgs = true; private boolean useParenthesesWhenNoArgs = true;
private String argumentListSignature; private String argumentListSignature;
@ -47,6 +48,11 @@ public class NamedFunctionDescriptorBuilder {
return this; return this;
} }
public NamedFunctionDescriptorBuilder setArgumentTypeResolver(FunctionArgumentTypeResolver argumentTypeResolver) {
this.argumentTypeResolver = argumentTypeResolver;
return this;
}
public NamedFunctionDescriptorBuilder setArgumentCountBetween(int min, int max) { public NamedFunctionDescriptorBuilder setArgumentCountBetween(int min, int max) {
return setArgumentsValidator( StandardArgumentsValidators.between( min, max ) ); return setArgumentsValidator( StandardArgumentsValidators.between( min, max ) );
} }
@ -71,6 +77,7 @@ public class NamedFunctionDescriptorBuilder {
public NamedFunctionDescriptorBuilder setParameterTypes(FunctionParameterType... types) { public NamedFunctionDescriptorBuilder setParameterTypes(FunctionParameterType... types) {
setArgumentsValidator( new ArgumentTypesValidator(argumentsValidator, types) ); setArgumentsValidator( new ArgumentTypesValidator(argumentsValidator, types) );
setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.invariant( types ) );
return this; return this;
} }
@ -99,6 +106,7 @@ public class NamedFunctionDescriptorBuilder {
useParenthesesWhenNoArgs, useParenthesesWhenNoArgs,
argumentsValidator, argumentsValidator,
returnTypeResolver, returnTypeResolver,
argumentTypeResolver,
registrationKey, registrationKey,
functionKind, functionKind,
argumentListSignature, argumentListSignature,

View File

@ -26,6 +26,7 @@ public class PatternFunctionDescriptorBuilder {
private ArgumentsValidator argumentsValidator; private ArgumentsValidator argumentsValidator;
private FunctionReturnTypeResolver returnTypeResolver; private FunctionReturnTypeResolver returnTypeResolver;
private FunctionArgumentTypeResolver argumentTypeResolver;
private SqlAstNodeRenderingMode argumentRenderingMode = SqlAstNodeRenderingMode.DEFAULT; private SqlAstNodeRenderingMode argumentRenderingMode = SqlAstNodeRenderingMode.DEFAULT;
public PatternFunctionDescriptorBuilder( public PatternFunctionDescriptorBuilder(
@ -44,8 +45,14 @@ public class PatternFunctionDescriptorBuilder {
return this; return this;
} }
public PatternFunctionDescriptorBuilder setArgumentTypeResolver(FunctionArgumentTypeResolver argumentTypeResolver) {
this.argumentTypeResolver = argumentTypeResolver;
return this;
}
public PatternFunctionDescriptorBuilder setParameterTypes(FunctionParameterType... types) { public PatternFunctionDescriptorBuilder setParameterTypes(FunctionParameterType... types) {
setArgumentsValidator( new ArgumentTypesValidator(argumentsValidator, types) ); setArgumentsValidator( new ArgumentTypesValidator(argumentsValidator, types) );
setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.invariant( types ) );
return this; return this;
} }
@ -62,7 +69,7 @@ public class PatternFunctionDescriptorBuilder {
return this; return this;
} }
public PatternFunctionDescriptorBuilder setInvariantType(BasicType invariantType) { public PatternFunctionDescriptorBuilder setInvariantType(BasicType<?> invariantType) {
setReturnTypeResolver( StandardFunctionReturnTypeResolvers.invariant( invariantType ) ); setReturnTypeResolver( StandardFunctionReturnTypeResolvers.invariant( invariantType ) );
return this; return this;
} }
@ -86,6 +93,7 @@ public class PatternFunctionDescriptorBuilder {
new PatternRenderer( pattern, argumentRenderingMode ), new PatternRenderer( pattern, argumentRenderingMode ),
argumentsValidator, argumentsValidator,
returnTypeResolver, returnTypeResolver,
argumentTypeResolver,
registrationKey, registrationKey,
functionKind, functionKind,
argumentListSignature argumentListSignature

View File

@ -0,0 +1,161 @@
/*
* 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 java.math.BigDecimal;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.List;
import org.hibernate.metamodel.mapping.MappingModelExpressible;
import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.type.spi.TypeConfiguration;
/**
* @author Christian Beikov
*/
public final class StandardFunctionArgumentTypeResolvers {
/**
* Disallow instantiation
*/
private StandardFunctionArgumentTypeResolvers() {
}
public static final FunctionArgumentTypeResolver NULL = (function, argumentIndex, converter) -> {
return null;
};
public static final FunctionArgumentTypeResolver IMPLIED_RESULT_TYPE = (function, argumentIndex, converter) -> {
return converter.resolveFunctionImpliedReturnType();
};
public static final FunctionArgumentTypeResolver ARGUMENT_OR_IMPLIED_RESULT_TYPE = (function, argumentIndex, converter) -> {
final List<? extends SqmTypedNode<?>> arguments = function.getArguments();
final int argumentsSize = arguments.size();
for ( int i = 0 ; i < argumentIndex; i++ ) {
final SqmTypedNode<?> node = arguments.get( i );
if ( node instanceof SqmExpression<?> ) {
final MappingModelExpressible<?> expressible = converter.determineValueMapping( (SqmExpression<?>) node );
if ( expressible != null ) {
return expressible;
}
}
}
for ( int i = argumentIndex + 1 ; i < argumentsSize; i++ ) {
final SqmTypedNode<?> node = arguments.get( i );
if ( node instanceof SqmExpression<?> ) {
final MappingModelExpressible<?> expressible = converter.determineValueMapping( (SqmExpression<?>) node );
if ( expressible != null ) {
return expressible;
}
}
}
return converter.resolveFunctionImpliedReturnType();
};
public static FunctionArgumentTypeResolver invariant(
TypeConfiguration typeConfiguration,
FunctionParameterType type) {
final MappingModelExpressible<?> expressible = getMappingModelExpressible( typeConfiguration, type );
return (function, argumentIndex, converter) -> expressible;
}
public static FunctionArgumentTypeResolver invariant(
TypeConfiguration typeConfiguration,
FunctionParameterType... types) {
final MappingModelExpressible<?>[] expressibles = new MappingModelExpressible[types.length];
for ( int i = 0; i < types.length; i++ ) {
expressibles[i] = getMappingModelExpressible( typeConfiguration, types[i] );
}
return (function, argumentIndex, converter) -> expressibles[argumentIndex];
}
public static FunctionArgumentTypeResolver invariant(FunctionParameterType... types) {
return (function, argumentIndex, converter) -> getMappingModelExpressible(
function.nodeBuilder().getTypeConfiguration(),
types[argumentIndex]
);
}
public static FunctionArgumentTypeResolver impliedOrInvariant(
TypeConfiguration typeConfiguration,
FunctionParameterType type) {
final MappingModelExpressible<?> expressible = getMappingModelExpressible( typeConfiguration, type );
return (function, argumentIndex, converter) -> {
final MappingModelExpressible<?> mappingModelExpressible = converter.resolveFunctionImpliedReturnType();
if ( mappingModelExpressible != null ) {
return mappingModelExpressible;
}
return expressible;
};
}
public static FunctionArgumentTypeResolver argumentsOrImplied(int... indices) {
return (function, argumentIndex, converter) -> {
final List<? extends SqmTypedNode<?>> arguments = function.getArguments();
final int argumentsSize = arguments.size();
for ( int index : indices ) {
if ( index >= argumentIndex || index >= argumentsSize ) {
break;
}
final SqmTypedNode<?> node = arguments.get( index );
if ( node instanceof SqmExpression<?> ) {
final MappingModelExpressible<?> expressible = converter.determineValueMapping( (SqmExpression<?>) node );
if ( expressible != null ) {
return expressible;
}
}
}
for ( int index : indices ) {
if ( index <= argumentIndex || index >= argumentsSize ) {
break;
}
final SqmTypedNode<?> node = arguments.get( index );
if ( node instanceof SqmExpression<?> ) {
final MappingModelExpressible<?> expressible = converter.determineValueMapping( (SqmExpression<?>) node );
if ( expressible != null ) {
return expressible;
}
}
}
return converter.resolveFunctionImpliedReturnType();
};
}
public static FunctionArgumentTypeResolver composite(FunctionArgumentTypeResolver... resolvers) {
return (function, argumentIndex, converter) -> {
return resolvers[argumentIndex].resolveFunctionArgumentType( function, argumentIndex, converter );
};
}
private static MappingModelExpressible<?> getMappingModelExpressible(
TypeConfiguration typeConfiguration,
FunctionParameterType type) {
switch ( type ) {
case STRING:
return typeConfiguration.getBasicTypeForJavaType( String.class );
case NUMERIC:
return typeConfiguration.getBasicTypeForJavaType( BigDecimal.class );
case INTEGER:
return typeConfiguration.getBasicTypeForJavaType( Integer.class );
case TEMPORAL:
return typeConfiguration.getBasicTypeForJavaType( Timestamp.class );
case DATE:
return typeConfiguration.getBasicTypeForJavaType( Date.class );
case TIME:
return typeConfiguration.getBasicTypeForJavaType( Time.class );
case BOOLEAN:
return typeConfiguration.getBasicTypeForJavaType( Boolean.class );
}
return null;
}
}

View File

@ -8,6 +8,7 @@ package org.hibernate.query.sqm.produce.function.internal;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode; import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
@ -189,8 +190,10 @@ public class PatternRenderer {
if ( arg != null ) { if ( arg != null ) {
sqlAppender.appendSql( chunks[i] ); sqlAppender.appendSql( chunks[i] );
if ( caseWrapper && !( arg instanceof Distinct ) && !( arg instanceof Star ) ) { if ( caseWrapper && !( arg instanceof Distinct ) && !( arg instanceof Star ) ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
sqlAppender.appendSql( "case when " ); sqlAppender.appendSql( "case when " );
filter.accept( translator ); filter.accept( translator );
translator.getCurrentClauseStack().pop();
sqlAppender.appendSql( " then " ); sqlAppender.appendSql( " then " );
translator.render( arg, argumentRenderingMode ); translator.render( arg, argumentRenderingMode );
sqlAppender.appendSql( " else null end" ); sqlAppender.appendSql( " else null end" );
@ -209,8 +212,10 @@ public class PatternRenderer {
} }
if ( arg != null ) { if ( arg != null ) {
if ( caseWrapper && !( arg instanceof Distinct ) && !( arg instanceof Star ) ) { if ( caseWrapper && !( arg instanceof Distinct ) && !( arg instanceof Star ) ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
sqlAppender.appendSql( "case when " ); sqlAppender.appendSql( "case when " );
filter.accept( translator ); filter.accept( translator );
translator.getCurrentClauseStack().pop();
sqlAppender.appendSql( " then " ); sqlAppender.appendSql( " then " );
translator.render( arg, argumentRenderingMode ); translator.render( arg, argumentRenderingMode );
sqlAppender.appendSql( " else null end" ); sqlAppender.appendSql( " else null end" );
@ -226,6 +231,7 @@ public class PatternRenderer {
} }
if ( withinGroup != null && !withinGroup.isEmpty() ) { if ( withinGroup != null && !withinGroup.isEmpty() ) {
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
sqlAppender.appendSql( " within group (order by" ); sqlAppender.appendSql( " within group (order by" );
translator.render( withinGroup.get( 0 ), argumentRenderingMode ); translator.render( withinGroup.get( 0 ), argumentRenderingMode );
for ( int i = 1; i < withinGroup.size(); i++ ) { for ( int i = 1; i < withinGroup.size(); i++ ) {
@ -233,6 +239,7 @@ public class PatternRenderer {
translator.render( withinGroup.get( 0 ), argumentRenderingMode ); translator.render( withinGroup.get( 0 ), argumentRenderingMode );
} }
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
translator.getCurrentClauseStack().pop();
} }
if ( fromFirst != null ) { if ( fromFirst != null ) {
@ -253,9 +260,11 @@ public class PatternRenderer {
} }
if ( filter != null && !caseWrapper ) { if ( filter != null && !caseWrapper ) {
translator.getCurrentClauseStack().push( Clause.WHERE );
sqlAppender.appendSql( " filter (where " ); sqlAppender.appendSql( " filter (where " );
filter.accept( translator ); filter.accept( translator );
sqlAppender.appendSql( ')' ); sqlAppender.appendSql( ')' );
translator.getCurrentClauseStack().pop();
} }
} }
} }

View File

@ -140,6 +140,7 @@ import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
import org.hibernate.query.sqm.tree.SqmJoinType; import org.hibernate.query.sqm.tree.SqmJoinType;
import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.query.sqm.tree.SqmVisitableNode;
import org.hibernate.query.sqm.tree.cte.SqmCteContainer; import org.hibernate.query.sqm.tree.cte.SqmCteContainer;
import org.hibernate.query.sqm.tree.cte.SqmCteStatement; import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
import org.hibernate.query.sqm.tree.cte.SqmCteTable; import org.hibernate.query.sqm.tree.cte.SqmCteTable;
@ -393,6 +394,8 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
private final QueryOptions queryOptions; private final QueryOptions queryOptions;
private final LoadQueryInfluencers loadQueryInfluencers; private final LoadQueryInfluencers loadQueryInfluencers;
private final Map<SqmParameter<?>, List<List<JdbcParameter>>> jdbcParamsBySqmParam = new IdentityHashMap<>();
private final JdbcParameters jdbcParameters = new JdbcParametersImpl();
private final DomainParameterXref domainParameterXref; private final DomainParameterXref domainParameterXref;
private final QueryParameterBindings domainParameterBindings; private final QueryParameterBindings domainParameterBindings;
private final Map<SqmParameter<?>, MappingModelExpressible<?>> sqmParameterMappingModelTypes = new LinkedHashMap<>(); private final Map<SqmParameter<?>, MappingModelExpressible<?>> sqmParameterMappingModelTypes = new LinkedHashMap<>();
@ -407,6 +410,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
private ForeignKeyDescriptor.Nature currentlyResolvingForeignKeySide; private ForeignKeyDescriptor.Nature currentlyResolvingForeignKeySide;
private SqmQueryPart<?> currentSqmQueryPart; private SqmQueryPart<?> currentSqmQueryPart;
private boolean containsCollectionFetches; private boolean containsCollectionFetches;
private boolean trackSelectionsForGroup;
private final Map<String, PredicateCollector> collectionFilterPredicates = new HashMap<>(); private final Map<String, PredicateCollector> collectionFilterPredicates = new HashMap<>();
private List<Map.Entry<OrderByFragment, TableGroup>> orderByFragments; private List<Map.Entry<OrderByFragment, TableGroup>> orderByFragments;
@ -436,6 +440,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
); );
private final Stack<List<QueryTransformer>> queryTransformers = new StandardStack<>(); private final Stack<List<QueryTransformer>> queryTransformers = new StandardStack<>();
private boolean inTypeInference; private boolean inTypeInference;
private Supplier<MappingModelExpressible<?>> functionImpliedResultTypeAccess;
private SqmByUnit appliedByUnit; private SqmByUnit appliedByUnit;
private Expression adjustedTimestamp; private Expression adjustedTimestamp;
@ -1573,8 +1578,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
return cteContainer; return cteContainer;
} }
private boolean trackSelectionsForGroup;
@Override @Override
public QueryPart visitQueryPart(SqmQueryPart<?> queryPart) { public QueryPart visitQueryPart(SqmQueryPart<?> queryPart) {
return (QueryPart) super.visitQueryPart( queryPart ); return (QueryPart) super.visitQueryPart( queryPart );
@ -4079,6 +4082,17 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
return inferredType; return inferredType;
} }
@Override
public MappingModelExpressible<?> resolveFunctionImpliedReturnType() {
if ( inTypeInference || functionImpliedResultTypeAccess == null ) {
return null;
}
inTypeInference = true;
final MappingModelExpressible<?> inferredType = functionImpliedResultTypeAccess.get();
inTypeInference = false;
return inferredType;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// General expressions // General expressions
@ -4284,9 +4298,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
} }
} }
private final Map<SqmParameter<?>, List<List<JdbcParameter>>> jdbcParamsBySqmParam = new IdentityHashMap<>();
private final JdbcParameters jdbcParameters = new JdbcParametersImpl();
@Override @Override
public Map<SqmParameter<?>, List<List<JdbcParameter>>> getJdbcParamsBySqmParam() { public Map<SqmParameter<?>, List<List<JdbcParameter>>> getJdbcParamsBySqmParam() {
return jdbcParamsBySqmParam; return jdbcParamsBySqmParam;
@ -4434,7 +4445,8 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
); );
} }
protected MappingModelExpressible<?> determineValueMapping(SqmExpression<?> sqmExpression) { @Override
public MappingModelExpressible<?> determineValueMapping(SqmExpression<?> sqmExpression) {
if ( sqmExpression instanceof SqmParameter ) { if ( sqmExpression instanceof SqmParameter ) {
return determineValueMapping( (SqmParameter<?>) sqmExpression ); return determineValueMapping( (SqmParameter<?>) sqmExpression );
} }
@ -4562,16 +4574,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final QueryParameterImplementor<?> queryParameter = domainParameterXref.getQueryParameter( sqmParameter ); final QueryParameterImplementor<?> queryParameter = domainParameterXref.getQueryParameter( sqmParameter );
final QueryParameterBinding<?> binding = domainParameterBindings.getBinding( queryParameter ); final QueryParameterBinding<?> binding = domainParameterBindings.getBinding( queryParameter );
if ( sqmParameter.getAnticipatedType() == null ) {
// this should indicate the condition that the user query did not define an
// explicit type in regard to this parameter. Here we should prefer the
// inferrable type and fallback to the binding type
final MappingModelExpressible<?> inferredValueMapping = getInferredValueMapping();
if ( inferredValueMapping != null ) {
return inferredValueMapping;
}
}
BindableType<?> paramType = binding.getBindType(); BindableType<?> paramType = binding.getBindType();
if ( paramType == null ) { if ( paramType == null ) {
paramType = queryParameter.getHibernateType(); paramType = queryParameter.getHibernateType();
@ -4581,12 +4583,25 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
} }
if ( paramType == null ) { if ( paramType == null ) {
final MappingModelExpressible<?> inferredValueMapping = getInferredValueMapping();
if ( inferredValueMapping != null ) {
return inferredValueMapping;
}
// Default to the Object type // Default to the Object type
return basicType( Object.class ); return basicType( Object.class );
} }
else if ( paramType instanceof MappingModelExpressible<?> && paramType.getBindableJavaType() == Object.class ) { else if ( paramType instanceof MappingModelExpressible<?> ) {
return (MappingModelExpressible<?>) paramType; return (MappingModelExpressible<?>) paramType;
} }
else if ( sqmParameter.getAnticipatedType() == null ) {
// this should indicate the condition that the user query did not define an
// explicit type in regard to this parameter. Here we should prefer the
// inferrable type and fallback to resolving the binding type
final MappingModelExpressible<?> inferredValueMapping = getInferredValueMapping();
if ( inferredValueMapping != null ) {
return inferredValueMapping;
}
}
final SqmExpressible<?> paramSqmType = paramType.resolveExpressible( creationContext.getSessionFactory() ); final SqmExpressible<?> paramSqmType = paramType.resolveExpressible( creationContext.getSessionFactory() );
@ -4742,12 +4757,15 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
@Override @Override
public Expression visitFunction(SqmFunction<?> sqmFunction) { public Expression visitFunction(SqmFunction<?> sqmFunction) {
final Supplier<MappingModelExpressible<?>> oldFunctionImpliedResultTypeAccess = functionImpliedResultTypeAccess;
functionImpliedResultTypeAccess = inferrableTypeAccessStack.getCurrent();
inferrableTypeAccessStack.push( () -> null ); inferrableTypeAccessStack.push( () -> null );
try { try {
return sqmFunction.convertToSqlAst( this ); return sqmFunction.convertToSqlAst( this );
} }
finally { finally {
inferrableTypeAccessStack.pop(); inferrableTypeAccessStack.pop();
functionImpliedResultTypeAccess = oldFunctionImpliedResultTypeAccess;
} }
} }
@ -5426,35 +5444,18 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
} }
} }
// private <X> X visitWithLenientInferredType(SqmExpression<?> expression, SqmExpression<?> inferred) { @Override
// inferrableTypeAccessStack.push( public Object visitWithInferredType(
// () -> { SqmVisitableNode node,
// MappingModelExpressible<?> definedType = creationContext Supplier<MappingModelExpressible<?>> inferredTypeAccess) {
// .getDomainModel() inferrableTypeAccessStack.push( inferredTypeAccess );
// .resolveMappingExpressible( try {
// expression.getNodeType(), return node.accept( this );
// getFromClauseIndex()::findTableGroup }
// ); finally {
// if ( definedType != null ) { inferrableTypeAccessStack.pop();
// return definedType; }
// } }
// definedType = creationContext
// .getDomainModel()
// .lenientlyResolveMappingExpressible(
// inferred.getNodeType(),
// getFromClauseIndex()::findTableGroup
// );
// return definedType;
// }
// );
//
// try {
// return (X) expression.accept( this );
// }
// finally {
// inferrableTypeAccessStack.pop();
// }
// }
@Override @Override
public Object visitAny(SqmAny<?> sqmAny) { public Object visitAny(SqmAny<?> sqmAny) {

View File

@ -7,10 +7,14 @@
package org.hibernate.query.sqm.sql; package org.hibernate.query.sqm.sql;
import java.util.List; import java.util.List;
import java.util.function.Supplier;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.internal.util.collections.Stack; import org.hibernate.internal.util.collections.Stack;
import org.hibernate.metamodel.mapping.MappingModelExpressible;
import org.hibernate.query.sqm.spi.BaseSemanticQueryWalker; import org.hibernate.query.sqm.spi.BaseSemanticQueryWalker;
import org.hibernate.query.sqm.tree.SqmVisitableNode;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmParameter; import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.predicate.SqmPredicate; import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.Clause;
@ -80,6 +84,23 @@ public class FakeSqmToSqlAstConverter extends BaseSemanticQueryWalker implements
public void registerQueryTransformer(QueryTransformer transformer) { public void registerQueryTransformer(QueryTransformer transformer) {
} }
@Override
public MappingModelExpressible<?> resolveFunctionImpliedReturnType() {
return null;
}
@Override
public MappingModelExpressible<?> determineValueMapping(SqmExpression<?> sqmExpression) {
return null;
}
@Override
public Object visitWithInferredType(
SqmVisitableNode node,
Supplier<MappingModelExpressible<?>> inferredTypeAccess) {
return node.accept( this );
}
@Override @Override
public List<Expression> expandSelfRenderingFunctionMultiValueParameter(SqmParameter<?> sqmParameter) { public List<Expression> expandSelfRenderingFunctionMultiValueParameter(SqmParameter<?> sqmParameter) {
return null; return null;

View File

@ -7,9 +7,13 @@
package org.hibernate.query.sqm.sql; package org.hibernate.query.sqm.sql;
import java.util.List; import java.util.List;
import java.util.function.Supplier;
import org.hibernate.internal.util.collections.Stack; import org.hibernate.internal.util.collections.Stack;
import org.hibernate.metamodel.mapping.MappingModelExpressible;
import org.hibernate.query.sqm.SemanticQueryWalker; import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.tree.SqmVisitableNode;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmParameter; import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.predicate.SqmPredicate; import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
import org.hibernate.sql.ast.spi.SqlAstCreationState; import org.hibernate.sql.ast.spi.SqlAstCreationState;
@ -28,6 +32,19 @@ public interface SqmToSqlAstConverter extends SemanticQueryWalker<Object>, SqlAs
void registerQueryTransformer(QueryTransformer transformer); void registerQueryTransformer(QueryTransformer transformer);
/**
* Returns the function return type implied from the context within which it is used.
* If there is no current function being processed or no context implied type, the return is <code>null</code>.
*/
MappingModelExpressible<?> resolveFunctionImpliedReturnType();
MappingModelExpressible<?> determineValueMapping(SqmExpression<?> sqmExpression);
/**
* Visits the given node with the given inferred type access.
*/
Object visitWithInferredType(SqmVisitableNode node, Supplier<MappingModelExpressible<?>> inferredTypeAccess);
List<Expression> expandSelfRenderingFunctionMultiValueParameter(SqmParameter<?> sqmParameter); List<Expression> expandSelfRenderingFunctionMultiValueParameter(SqmParameter<?> sqmParameter);
Predicate visitNestedTopLevelPredicate(SqmPredicate predicate); Predicate visitNestedTopLevelPredicate(SqmPredicate predicate);

View File

@ -52,6 +52,7 @@ public enum Clause {
FETCH, FETCH,
FOR_UPDATE, FOR_UPDATE,
OVER, OVER,
WITHIN_GROUP,
PARTITION, PARTITION,
CALL, CALL,

View File

@ -8,6 +8,7 @@ package org.hibernate.sql.ast;
import java.util.Set; import java.util.Set;
import org.hibernate.internal.util.collections.Stack;
import org.hibernate.query.spi.QueryOptions; import org.hibernate.query.spi.QueryOptions;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.select.QueryPart; import org.hibernate.sql.ast.tree.select.QueryPart;
@ -34,6 +35,8 @@ public interface SqlAstTranslator<T extends JdbcOperation> extends SqlAstWalker
*/ */
QueryPart getCurrentQueryPart(); QueryPart getCurrentQueryPart();
Stack<Clause> getCurrentClauseStack();
/** /**
* Not the best spot for this. Its the table names collected while walking the SQL AST. * Not the best spot for this. Its the table names collected while walking the SQL AST.
* Its ok here because the translator is consider a one-time-use. It just needs to be called * Its ok here because the translator is consider a one-time-use. It just needs to be called

View File

@ -587,11 +587,13 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
return ( (ComparisonPredicate) predicate ).getLeftHandExpression(); return ( (ComparisonPredicate) predicate ).getLeftHandExpression();
} }
protected boolean inOverClause() { protected boolean inOverOrWithinGroupClause() {
return clauseStack.findCurrentFirst( return clauseStack.findCurrentFirst(
clause -> { clause -> {
if ( clause == Clause.OVER ) { switch ( clause ) {
return true; case OVER:
case WITHIN_GROUP:
return true;
} }
return null; return null;
} }
@ -611,6 +613,11 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
return queryPartStack.getCurrent(); return queryPartStack.getCurrent();
} }
@Override
public Stack<Clause> getCurrentClauseStack() {
return clauseStack;
}
@Override @Override
public T translate(JdbcParameterBindings jdbcParameterBindings, QueryOptions queryOptions) { public T translate(JdbcParameterBindings jdbcParameterBindings, QueryOptions queryOptions) {
try { try {
@ -2208,7 +2215,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
emulateSortSpecificationNullPrecedence( sortExpression, nullPrecedence ); emulateSortSpecificationNullPrecedence( sortExpression, nullPrecedence );
} }
if ( inOverClause() ) { if ( inOverOrWithinGroupClause() ) {
resolveAliasedExpression( sortExpression ).accept( this ); resolveAliasedExpression( sortExpression ).accept( this );
} }
else { else {

View File

@ -62,7 +62,6 @@ public class CoalesceTest extends BaseCoreFunctionalTestCase {
} }
@Test @Test
@SkipForDialect(jiraKey = "HHH-10463", value = PostgreSQLDialect.class)
public void HHH_10463_NullInCoalesce() { public void HHH_10463_NullInCoalesce() {
doInHibernate( this::sessionFactory, session -> { doInHibernate( this::sessionFactory, session -> {
TypedQuery<Person> query = session.createQuery( "from Person p where p.name = coalesce(:name, p.name) ", Person.class ); TypedQuery<Person> query = session.createQuery( "from Person p where p.name = coalesce(:name, p.name) ", Person.class );

View File

@ -54,7 +54,7 @@ public class SubqueryTest extends BaseSessionFactoryFunctionalTest {
String name, String name,
ArgumentsValidator argumentsValidator, ArgumentsValidator argumentsValidator,
FunctionReturnTypeResolver returnTypeResolver) { FunctionReturnTypeResolver returnTypeResolver) {
super( name, argumentsValidator, returnTypeResolver ); super( name, argumentsValidator, returnTypeResolver, null );
} }
@Override @Override

View File

@ -54,7 +54,8 @@ public class OrderByFragmentFunction extends AbstractSqmFunctionDescriptor {
super( super(
FUNCTION_NAME, FUNCTION_NAME,
StandardArgumentsValidators.exactly( 2 ), StandardArgumentsValidators.exactly( 2 ),
StandardFunctionReturnTypeResolvers.useArgType( 1 ) StandardFunctionReturnTypeResolvers.useArgType( 1 ),
null
); );
} }
@Override @Override
@ -174,9 +175,6 @@ public class OrderByFragmentFunction extends AbstractSqmFunctionDescriptor {
@Override @Override
public Expression convertToSqlAst(SqmToSqlAstConverter walker) { public Expression convertToSqlAst(SqmToSqlAstConverter walker) {
final ReturnableType<?> resultType = resolveResultType(
walker.getCreationContext().getMappingMetamodel().getTypeConfiguration()
);
final String sqmAlias = ( (SqmLiteral<String>) getArguments().get( 0 ) ).getLiteralValue(); final String sqmAlias = ( (SqmLiteral<String>) getArguments().get( 0 ) ).getLiteralValue();
final String attributeRole = ( (SqmLiteral<String>) getArguments().get( 1 ) ).getLiteralValue(); final String attributeRole = ( (SqmLiteral<String>) getArguments().get( 1 ) ).getLiteralValue();
final TableGroup tableGroup = ( (FromClauseIndex) walker.getFromClauseAccess() ).findTableGroup( final TableGroup tableGroup = ( (FromClauseIndex) walker.getFromClauseAccess() ).findTableGroup(