HHH-10463 Implement function argument type inference
This commit is contained in:
parent
260c738a5a
commit
dc6ad33cfc
|
@ -173,7 +173,8 @@ public class CacheDialect extends Dialect {
|
|||
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
|
||||
"$find(?2,?1)",
|
||||
"$find(?2,?1,?3)",
|
||||
STRING, STRING, INTEGER
|
||||
STRING, STRING, INTEGER,
|
||||
queryEngine.getTypeConfiguration()
|
||||
).setArgumentListSignature("(pattern, string[, start])");
|
||||
functionFactory.bitLength_pattern( "($length(?1)*8)" );
|
||||
|
||||
|
|
|
@ -284,7 +284,8 @@ public class FirebirdDialect extends Dialect {
|
|||
integerType,
|
||||
"position(?1 in ?2)",
|
||||
"position(?1,?2,?3)",
|
||||
STRING, STRING, INTEGER
|
||||
STRING, STRING, INTEGER,
|
||||
queryEngine.getTypeConfiguration()
|
||||
).setArgumentListSignature( "(pattern, string[, start])" );
|
||||
functionRegistry.namedDescriptorBuilder( "ascii_val" )
|
||||
.setExactArgumentCount( 1 )
|
||||
|
|
|
@ -288,7 +288,8 @@ public class IngresDialect extends Dialect {
|
|||
integerType,
|
||||
"position(?1 in ?2)",
|
||||
"(position(?1 in substring(?2 from ?3))+(?3)-1)",
|
||||
STRING, STRING, INTEGER
|
||||
STRING, STRING, INTEGER,
|
||||
queryEngine.getTypeConfiguration()
|
||||
).setArgumentListSignature("(pattern, string[, start])");
|
||||
|
||||
queryEngine.getSqmFunctionRegistry().registerPattern( "extract", "date_part('?1',?2)", integerType );
|
||||
|
|
|
@ -168,7 +168,8 @@ public class MaxDBDialect extends Dialect {
|
|||
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
|
||||
"locate",
|
||||
integerType, "index(?2,?1)", "index(?2,?1,?3)",
|
||||
STRING, STRING, INTEGER
|
||||
STRING, STRING, INTEGER,
|
||||
queryEngine.getTypeConfiguration()
|
||||
).setArgumentListSignature("(pattern, string[, start])");
|
||||
}
|
||||
|
||||
|
|
|
@ -277,21 +277,24 @@ public class SQLiteDialect extends Dialect {
|
|||
integerType,
|
||||
"instr(?2,?1)",
|
||||
"instr(?2,?1,?3)",
|
||||
STRING, STRING, INTEGER
|
||||
STRING, STRING, INTEGER,
|
||||
queryEngine.getTypeConfiguration()
|
||||
).setArgumentListSignature("(pattern, string[, start])");
|
||||
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
|
||||
"lpad",
|
||||
stringType,
|
||||
"(substr(replace(hex(zeroblob(?2)),'00',' '),1,?2-length(?1))||?1)",
|
||||
"(substr(replace(hex(zeroblob(?2)),'00',?3),1,?2-length(?1))||?1)",
|
||||
STRING, INTEGER, STRING
|
||||
STRING, INTEGER, STRING,
|
||||
queryEngine.getTypeConfiguration()
|
||||
).setArgumentListSignature("(string, length[, padding])");
|
||||
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
|
||||
"rpad",
|
||||
stringType,
|
||||
"(?1||substr(replace(hex(zeroblob(?2)),'00',' '),1,?2-length(?1)))",
|
||||
"(?1||substr(replace(hex(zeroblob(?2)),'00',?3),1,?2-length(?1)))",
|
||||
STRING, INTEGER, STRING
|
||||
STRING, INTEGER, STRING,
|
||||
queryEngine.getTypeConfiguration()
|
||||
).setArgumentListSignature("(string, length[, padding])");
|
||||
|
||||
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder("format", "strftime")
|
||||
|
|
|
@ -168,7 +168,8 @@ public class TimesTenDialect extends Dialect {
|
|||
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
|
||||
"instr(?2,?1)",
|
||||
"instr(?2,?1,?3)",
|
||||
STRING, STRING, INTEGER
|
||||
STRING, STRING, INTEGER,
|
||||
queryEngine.getTypeConfiguration()
|
||||
).setArgumentListSignature("(pattern, string[, start])");
|
||||
}
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@ import java.util.regex.Pattern;
|
|||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.query.sqm.produce.function.FunctionParameterType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* An abstract base class for SAP HANA dialects.
|
||||
|
@ -274,13 +275,15 @@ public abstract class AbstractHANADialect extends Dialect {
|
|||
@Override
|
||||
public void initializeFunctionRegistry(QueryEngine queryEngine) {
|
||||
super.initializeFunctionRegistry( queryEngine );
|
||||
final TypeConfiguration typeConfiguration = queryEngine.getTypeConfiguration();
|
||||
|
||||
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
|
||||
"locate",
|
||||
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
|
||||
"locate(?2,?1)",
|
||||
"locate(?2,?1,?3)",
|
||||
FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER
|
||||
FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER,
|
||||
typeConfiguration
|
||||
).setArgumentListSignature("(pattern, string[, start])");
|
||||
|
||||
CommonFunctionFactory functionFactory = new CommonFunctionFactory(queryEngine);
|
||||
|
@ -317,7 +320,7 @@ public abstract class AbstractHANADialect extends Dialect {
|
|||
functionFactory.hypotheticalOrderedSetAggregates_windowEmulation();
|
||||
|
||||
queryEngine.getSqmFunctionRegistry().register( "timestampadd",
|
||||
new IntegralTimestampaddFunction( this, queryEngine.getTypeConfiguration() ) );
|
||||
new IntegralTimestampaddFunction( this, typeConfiguration ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -142,7 +142,6 @@ public abstract class AbstractTransactSQLDialect extends Dialect {
|
|||
functionFactory.yearMonthDay();
|
||||
functionFactory.ascii();
|
||||
functionFactory.chr_char();
|
||||
functionFactory.concat_plusOperator();
|
||||
functionFactory.trim1();
|
||||
functionFactory.repeat_replicate();
|
||||
functionFactory.characterLength_len();
|
||||
|
|
|
@ -160,6 +160,7 @@ import org.hibernate.type.descriptor.jdbc.NCharJdbcType;
|
|||
import org.hibernate.type.descriptor.jdbc.NClobJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.NVarcharJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
||||
|
@ -769,7 +770,8 @@ public abstract class Dialect implements ConversionContext {
|
|||
* same names.
|
||||
*/
|
||||
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> dateType = basicTypeRegistry.resolve( StandardBasicTypes.DATE );
|
||||
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()
|
||||
|
||||
queryEngine.getSqmFunctionRegistry().register( "position",
|
||||
new LocatePositionEmulation( queryEngine.getTypeConfiguration() ) );
|
||||
new LocatePositionEmulation( typeConfiguration ) );
|
||||
|
||||
//very few databases support ANSI-style overlay() function, so emulate
|
||||
//it here in terms of either insert() or concat()/substring()
|
||||
|
||||
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
|
||||
//we care about, but on some it must be emulated using ltrim(), rtrim(),
|
||||
//and replace()
|
||||
|
||||
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
|
||||
//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
|
||||
|
||||
queryEngine.getSqmFunctionRegistry().register( "extract",
|
||||
new ExtractFunction( this ) );
|
||||
new ExtractFunction( this, typeConfiguration ) );
|
||||
|
||||
//comparison functions supported on most databases, emulated on others
|
||||
//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()
|
||||
|
||||
queryEngine.getSqmFunctionRegistry().register( "pad",
|
||||
new LpadRpadPadEmulation( queryEngine.getTypeConfiguration() ) );
|
||||
new LpadRpadPadEmulation( typeConfiguration ) );
|
||||
|
||||
//legacy Hibernate convenience function for casting to string, defined
|
||||
//here as an alias for cast(arg as String)
|
||||
|
||||
queryEngine.getSqmFunctionRegistry().register( "str",
|
||||
new CastStrEmulation( queryEngine.getTypeConfiguration() ) );
|
||||
new CastStrEmulation( typeConfiguration ) );
|
||||
|
||||
//format() function for datetimes, emulated on many databases using the
|
||||
//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
|
||||
|
||||
queryEngine.getSqmFunctionRegistry().register( "timestampadd",
|
||||
new TimestampaddFunction( this ) );
|
||||
new TimestampaddFunction( this, typeConfiguration ) );
|
||||
queryEngine.getSqmFunctionRegistry().register( "timestampdiff",
|
||||
new TimestampdiffFunction( this, queryEngine.getTypeConfiguration() ) );
|
||||
new TimestampdiffFunction( this, typeConfiguration ) );
|
||||
queryEngine.getSqmFunctionRegistry().registerAlternateKey( "dateadd", "timestampadd" );
|
||||
queryEngine.getSqmFunctionRegistry().registerAlternateKey( "datediff", "timestampdiff" );
|
||||
|
||||
|
|
|
@ -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.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.ANY;
|
||||
|
||||
|
@ -102,20 +103,22 @@ public class HANAColumnStoreDialect extends AbstractHANADialect {
|
|||
@Override
|
||||
public void initializeFunctionRegistry(QueryEngine queryEngine) {
|
||||
super.initializeFunctionRegistry( queryEngine );
|
||||
final TypeConfiguration typeConfiguration = queryEngine.getTypeConfiguration();
|
||||
|
||||
// full-text search functions
|
||||
queryEngine.getSqmFunctionRegistry().registerNamed(
|
||||
"score",
|
||||
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.DOUBLE )
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.DOUBLE )
|
||||
);
|
||||
queryEngine.getSqmFunctionRegistry().registerNamed( "snippets" );
|
||||
queryEngine.getSqmFunctionRegistry().registerNamed( "highlighted" );
|
||||
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
|
||||
"contains",
|
||||
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.BOOLEAN ),
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.BOOLEAN ),
|
||||
"contains(?1,?2)",
|
||||
"contains(?1,?2,?3)",
|
||||
ANY, ANY, ANY
|
||||
ANY, ANY, ANY,
|
||||
typeConfiguration
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -93,6 +93,8 @@ import static org.hibernate.query.sqm.TemporalUnit.SECOND;
|
|||
import static org.hibernate.query.sqm.TemporalUnit.YEAR;
|
||||
|
||||
import org.hibernate.query.sqm.produce.function.FunctionParameterType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import static org.hibernate.type.SqlTypes.*;
|
||||
|
||||
/**
|
||||
|
@ -136,6 +138,7 @@ public class OracleDialect extends Dialect {
|
|||
@Override
|
||||
public void initializeFunctionRegistry(QueryEngine queryEngine) {
|
||||
super.initializeFunctionRegistry( queryEngine );
|
||||
final TypeConfiguration typeConfiguration = queryEngine.getTypeConfiguration();
|
||||
|
||||
CommonFunctionFactory functionFactory = new CommonFunctionFactory(queryEngine);
|
||||
functionFactory.cosh();
|
||||
|
@ -185,10 +188,11 @@ public class OracleDialect extends Dialect {
|
|||
|
||||
queryEngine.getSqmFunctionRegistry().registerBinaryTernaryPattern(
|
||||
"locate",
|
||||
queryEngine.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ),
|
||||
"instr(?2,?1)",
|
||||
"instr(?2,?1,?3)",
|
||||
FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER
|
||||
FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER,
|
||||
typeConfiguration
|
||||
).setArgumentListSignature("(pattern, string[, start])");
|
||||
// The within group clause became optional in 18
|
||||
if ( getVersion().isSameOrAfter( 18 ) ) {
|
||||
|
@ -203,7 +207,7 @@ public class OracleDialect extends Dialect {
|
|||
// Oracle has a regular aggregate function named stats_mode
|
||||
queryEngine.getSqmFunctionRegistry().register(
|
||||
"mode",
|
||||
new ModeStatsModeEmulation( queryEngine.getTypeConfiguration() )
|
||||
new ModeStatsModeEmulation( typeConfiguration )
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,9 @@ import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescript
|
|||
import org.hibernate.query.sqm.function.FunctionKind;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
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.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
|
@ -49,7 +51,8 @@ public class AvgFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
|
|||
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 1 ), NUMERIC ),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.DOUBLE )
|
||||
)
|
||||
),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, NUMERIC )
|
||||
);
|
||||
this.defaultArgumentRenderingMode = defaultArgumentRenderingMode;
|
||||
doubleType = typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.DOUBLE );
|
||||
|
@ -80,8 +83,10 @@ public class AvgFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
|
|||
arg = (Expression) sqlAstArguments.get( 0 );
|
||||
}
|
||||
if ( caseWrapper ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
sqlAppender.appendSql( "case when " );
|
||||
filter.accept( translator );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
sqlAppender.appendSql( " then " );
|
||||
renderArgument( sqlAppender, translator, arg );
|
||||
sqlAppender.appendSql( " else null end)" );
|
||||
|
@ -90,9 +95,11 @@ public class AvgFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
|
|||
renderArgument( sqlAppender, translator, arg );
|
||||
sqlAppender.appendSql( ')' );
|
||||
if ( filter != null ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
sqlAppender.appendSql( " filter (where " );
|
||||
filter.accept( translator );
|
||||
sqlAppender.appendSql( ')' );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.List;
|
|||
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
|
@ -33,7 +34,8 @@ public class CaseLeastGreatestEmulation
|
|||
super(
|
||||
least ? "least" : "greatest",
|
||||
new ArgumentTypesValidator( StandardArgumentsValidators.min( 2 ), COMPARABLE, COMPARABLE ),
|
||||
StandardFunctionReturnTypeResolvers.useFirstNonNull()
|
||||
StandardFunctionReturnTypeResolvers.useFirstNonNull(),
|
||||
StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE
|
||||
);
|
||||
this.operator = least ? "<=" : ">=";
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.hibernate.metamodel.mapping.JdbcMapping;
|
|||
import org.hibernate.query.sqm.CastType;
|
||||
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
|
||||
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.internal.PatternRenderer;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
|
@ -38,7 +39,8 @@ public class CastFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
|
|||
super(
|
||||
"cast",
|
||||
StandardArgumentsValidators.exactly( 2 ),
|
||||
StandardFunctionReturnTypeResolvers.useArgType( 2 )
|
||||
StandardFunctionReturnTypeResolvers.useArgType( 2 ),
|
||||
StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE
|
||||
);
|
||||
this.dialect = dialect;
|
||||
this.booleanCastType = getBooleanCastType( preferredSqlTypeCodeForBoolean );
|
||||
|
|
|
@ -37,7 +37,8 @@ public class CastStrEmulation
|
|||
StandardArgumentsValidators.exactly( 1 ),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
|
||||
)
|
||||
),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -45,7 +46,7 @@ public class CastStrEmulation
|
|||
String name,
|
||||
ArgumentsValidator argumentsValidator,
|
||||
FunctionReturnTypeResolver returnTypeResolver) {
|
||||
super( name, argumentsValidator, returnTypeResolver );
|
||||
super( name, argumentsValidator, returnTypeResolver, null );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.hibernate.query.sqm.CastType;
|
|||
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
|
||||
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
|
||||
|
@ -42,10 +43,11 @@ public class CastingConcatFunction extends AbstractSqmSelfRenderingFunctionDescr
|
|||
TypeConfiguration typeConfiguration) {
|
||||
super(
|
||||
"concat",
|
||||
new ArgumentTypesValidator( StandardArgumentsValidators.min( 1 ), STRING ),
|
||||
StandardArgumentsValidators.min( 1 ),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
|
||||
)
|
||||
),
|
||||
StandardFunctionArgumentTypeResolvers.impliedOrInvariant( typeConfiguration, STRING )
|
||||
);
|
||||
this.dialect = dialect;
|
||||
this.concatOperator = concatOperator;
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.hibernate.query.spi.QueryEngine;
|
|||
import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
|
@ -25,7 +26,8 @@ public class CoalesceIfnullEmulation
|
|||
public CoalesceIfnullEmulation() {
|
||||
super(
|
||||
"ifnull",
|
||||
StandardArgumentsValidators.exactly( 2 )
|
||||
StandardArgumentsValidators.exactly( 2 ),
|
||||
StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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.ArgumentsValidator;
|
||||
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.type.BasicType;
|
||||
import org.hibernate.type.BasicTypeRegistry;
|
||||
|
@ -454,14 +455,16 @@ public class CommonFunctionFactory {
|
|||
stringType,
|
||||
"lpad(?1,?2,' ')",
|
||||
"lpad(?1,?2,?3)",
|
||||
STRING, INTEGER, STRING
|
||||
STRING, INTEGER, STRING,
|
||||
typeConfiguration
|
||||
).setArgumentListSignature( "(string, length[, padding])" );
|
||||
functionRegistry.registerBinaryTernaryPattern(
|
||||
"rpad",
|
||||
stringType,
|
||||
"rpad(?1,?2,' ')",
|
||||
"rpad(?1,?2,?3)",
|
||||
STRING, INTEGER, STRING
|
||||
STRING, INTEGER, STRING,
|
||||
typeConfiguration
|
||||
).setArgumentListSignature( "(string, length[, padding])" );
|
||||
}
|
||||
|
||||
|
@ -474,14 +477,16 @@ public class CommonFunctionFactory {
|
|||
stringType,
|
||||
"(space(?2-len(?1))+?1)",
|
||||
"(replicate(?3,?2-len(?1))+?1)",
|
||||
STRING, INTEGER, STRING
|
||||
STRING, INTEGER, STRING,
|
||||
typeConfiguration
|
||||
).setArgumentListSignature( "(string, length[, padding])" );
|
||||
functionRegistry.registerBinaryTernaryPattern(
|
||||
"rpad",
|
||||
stringType,
|
||||
"(?1+space(?2-len(?1)))",
|
||||
"(?1+replicate(?3,?2-len(?1)))",
|
||||
STRING, INTEGER, STRING
|
||||
STRING, INTEGER, STRING,
|
||||
typeConfiguration
|
||||
).setArgumentListSignature( "(string, length[, padding])" );
|
||||
}
|
||||
|
||||
|
@ -491,14 +496,16 @@ public class CommonFunctionFactory {
|
|||
stringType,
|
||||
"(repeat(' ',?2-character_length(?1))||?1)",
|
||||
"(repeat(?3,?2-character_length(?1))||?1)",
|
||||
STRING, INTEGER, STRING
|
||||
STRING, INTEGER, STRING,
|
||||
typeConfiguration
|
||||
).setArgumentListSignature( "(string, length[, padding])" );
|
||||
functionRegistry.registerBinaryTernaryPattern(
|
||||
"rpad",
|
||||
stringType,
|
||||
"(?1||repeat(' ',?2-character_length(?1)))",
|
||||
"(?1||repeat(?3,?2-character_length(?1)))",
|
||||
STRING, INTEGER, STRING
|
||||
STRING, INTEGER, STRING,
|
||||
typeConfiguration
|
||||
).setArgumentListSignature( "(string, length[, padding])" );
|
||||
}
|
||||
|
||||
|
@ -511,14 +518,16 @@ public class CommonFunctionFactory {
|
|||
stringType,
|
||||
"lfill(?1,' ',?2)",
|
||||
"lfill(?1,?3,?2)",
|
||||
STRING, INTEGER, STRING
|
||||
STRING, INTEGER, STRING,
|
||||
typeConfiguration
|
||||
).setArgumentListSignature( "(string, length[, padding])" );
|
||||
functionRegistry.registerBinaryTernaryPattern(
|
||||
"rpad",
|
||||
stringType,
|
||||
"rfill(?1,' ',?2)",
|
||||
"rfill(?1,?3,?2)",
|
||||
STRING, INTEGER, STRING
|
||||
STRING, INTEGER, STRING,
|
||||
typeConfiguration
|
||||
).setArgumentListSignature( "(string, length[, padding])" );
|
||||
}
|
||||
|
||||
|
@ -606,6 +615,7 @@ public class CommonFunctionFactory {
|
|||
functionRegistry.namedDescriptorBuilder( "md5" )
|
||||
.setInvariantType(stringType)
|
||||
.setExactArgumentCount( 1 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
}
|
||||
|
||||
|
@ -613,6 +623,7 @@ public class CommonFunctionFactory {
|
|||
functionRegistry.namedDescriptorBuilder( "initcap" )
|
||||
.setInvariantType(stringType)
|
||||
.setExactArgumentCount( 1 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
}
|
||||
|
||||
|
@ -638,30 +649,35 @@ public class CommonFunctionFactory {
|
|||
functionRegistry.namedDescriptorBuilder( "translate" )
|
||||
.setInvariantType(stringType)
|
||||
.setExactArgumentCount( 3 )
|
||||
.setParameterTypes( STRING, STRING, STRING )
|
||||
.register();
|
||||
}
|
||||
|
||||
public void bitand() {
|
||||
functionRegistry.namedDescriptorBuilder( "bitand" )
|
||||
.setExactArgumentCount( 2 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
}
|
||||
|
||||
public void bitor() {
|
||||
functionRegistry.namedDescriptorBuilder( "bitor" )
|
||||
.setExactArgumentCount( 2 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
}
|
||||
|
||||
public void bitxor() {
|
||||
functionRegistry.namedDescriptorBuilder( "bitxor" )
|
||||
.setExactArgumentCount( 2 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
}
|
||||
|
||||
public void bitnot() {
|
||||
functionRegistry.namedDescriptorBuilder( "bitnot" )
|
||||
.setExactArgumentCount( 1 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
}
|
||||
|
||||
|
@ -671,21 +687,25 @@ public class CommonFunctionFactory {
|
|||
public void bitandorxornot_bitAndOrXorNot() {
|
||||
functionRegistry.namedDescriptorBuilder( "bit_and" )
|
||||
.setExactArgumentCount( 2 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
functionRegistry.registerAlternateKey( "bitand", "bit_and" );
|
||||
|
||||
functionRegistry.namedDescriptorBuilder( "bit_or" )
|
||||
.setExactArgumentCount( 2 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
functionRegistry.registerAlternateKey( "bitor", "bit_or" );
|
||||
|
||||
functionRegistry.namedDescriptorBuilder( "bit_xor" )
|
||||
.setExactArgumentCount( 2 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
functionRegistry.registerAlternateKey( "bitxor", "bit_xor" );
|
||||
|
||||
functionRegistry.namedDescriptorBuilder( "bit_not" )
|
||||
.setExactArgumentCount( 1 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
functionRegistry.registerAlternateKey( "bitnot", "bit_not" );
|
||||
}
|
||||
|
@ -696,21 +716,25 @@ public class CommonFunctionFactory {
|
|||
public void bitandorxornot_binAndOrXorNot() {
|
||||
functionRegistry.namedDescriptorBuilder( "bin_and" )
|
||||
.setMinArgumentCount( 1 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
functionRegistry.registerAlternateKey( "bitand", "bin_and" );
|
||||
|
||||
functionRegistry.namedDescriptorBuilder( "bin_or" )
|
||||
.setMinArgumentCount( 1 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
functionRegistry.registerAlternateKey( "bitor", "bin_or" );
|
||||
|
||||
functionRegistry.namedDescriptorBuilder( "bin_xor" )
|
||||
.setMinArgumentCount( 1 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
functionRegistry.registerAlternateKey( "bitxor", "bin_xor" );
|
||||
|
||||
functionRegistry.namedDescriptorBuilder( "bin_not" )
|
||||
.setExactArgumentCount( 1 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
functionRegistry.registerAlternateKey( "bitnot", "bin_not" );
|
||||
}
|
||||
|
@ -721,18 +745,22 @@ public class CommonFunctionFactory {
|
|||
public void bitandorxornot_operator() {
|
||||
functionRegistry.patternDescriptorBuilder( "bitand", "(?1&?2)" )
|
||||
.setExactArgumentCount( 2 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
|
||||
functionRegistry.patternDescriptorBuilder( "bitor", "(?1|?2)" )
|
||||
.setExactArgumentCount( 2 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
|
||||
functionRegistry.patternDescriptorBuilder( "bitxor", "(?1^?2)" )
|
||||
.setExactArgumentCount( 2 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
|
||||
functionRegistry.patternDescriptorBuilder( "bitnot", "~?1" )
|
||||
.setExactArgumentCount( 1 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
}
|
||||
|
||||
|
@ -742,10 +770,12 @@ public class CommonFunctionFactory {
|
|||
public void bitAndOr() {
|
||||
functionRegistry.namedAggregateDescriptorBuilder( "bit_and" )
|
||||
.setExactArgumentCount( 1 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
|
||||
functionRegistry.namedAggregateDescriptorBuilder( "bit_or" )
|
||||
.setExactArgumentCount( 1 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
|
||||
//MySQL has it but how is that even useful?
|
||||
|
@ -978,21 +1008,25 @@ public class CommonFunctionFactory {
|
|||
functionRegistry.namedDescriptorBuilder( "to_number" )
|
||||
//always 1 arg on HSQL and Cache, always 2 on Postgres
|
||||
.setArgumentCountBetween( 1, 3 )
|
||||
.setParameterTypes( STRING, STRING, STRING )
|
||||
.setInvariantType(doubleType)
|
||||
.register();
|
||||
functionRegistry.namedDescriptorBuilder( "to_char" )
|
||||
.setArgumentCountBetween( 1, 3 )
|
||||
.setParameterTypes( ANY, STRING, STRING )
|
||||
//always 2 args on HSQL and Postgres
|
||||
.setInvariantType(stringType)
|
||||
.register();
|
||||
functionRegistry.namedDescriptorBuilder( "to_date" )
|
||||
//always 2 args on HSQL and Postgres
|
||||
.setArgumentCountBetween( 1, 3 )
|
||||
.setParameterTypes( STRING, STRING, STRING )
|
||||
.setInvariantType(dateType)
|
||||
.register();
|
||||
functionRegistry.namedDescriptorBuilder( "to_timestamp" )
|
||||
//always 2 args on HSQL and Postgres
|
||||
.setArgumentCountBetween( 1, 3 )
|
||||
.setParameterTypes( STRING, STRING, STRING )
|
||||
.setInvariantType(timestampType)
|
||||
.register();
|
||||
}
|
||||
|
@ -1073,19 +1107,9 @@ public class CommonFunctionFactory {
|
|||
functionRegistry.patternDescriptorBuilder( "concat", "(?1||?2...)" )
|
||||
.setInvariantType(stringType)
|
||||
.setMinArgumentCount( 1 )
|
||||
.setParameterTypes(STRING)
|
||||
.setArgumentListSignature( "(STRING string0[, STRING string1[, ...]])" )
|
||||
.register();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transact SQL-style
|
||||
*/
|
||||
public void concat_plusOperator() {
|
||||
functionRegistry.patternDescriptorBuilder( "concat", "(?1+?2...)" )
|
||||
.setInvariantType(stringType)
|
||||
.setMinArgumentCount( 1 )
|
||||
.setParameterTypes(STRING)
|
||||
.setArgumentTypeResolver(
|
||||
StandardFunctionArgumentTypeResolvers.impliedOrInvariant( typeConfiguration, STRING )
|
||||
)
|
||||
.setArgumentListSignature( "(STRING string0[, STRING string1[, ...]])" )
|
||||
.register();
|
||||
}
|
||||
|
@ -1297,6 +1321,7 @@ public class CommonFunctionFactory {
|
|||
public void coalesce() {
|
||||
functionRegistry.namedDescriptorBuilder( "coalesce" )
|
||||
.setMinArgumentCount( 1 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
}
|
||||
|
||||
|
@ -1306,6 +1331,7 @@ public class CommonFunctionFactory {
|
|||
public void coalesce_value() {
|
||||
functionRegistry.namedDescriptorBuilder( "value" )
|
||||
.setMinArgumentCount( 1 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
functionRegistry.registerAlternateKey( "coalesce", "value" );
|
||||
}
|
||||
|
@ -1313,6 +1339,7 @@ public class CommonFunctionFactory {
|
|||
public void nullif() {
|
||||
functionRegistry.namedDescriptorBuilder( "nullif" )
|
||||
.setExactArgumentCount( 2 )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
}
|
||||
|
||||
|
@ -1420,7 +1447,8 @@ public class CommonFunctionFactory {
|
|||
"locate",
|
||||
integerType,
|
||||
"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])" );
|
||||
}
|
||||
|
@ -1432,7 +1460,8 @@ public class CommonFunctionFactory {
|
|||
"substring",
|
||||
stringType,
|
||||
"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])" );
|
||||
}
|
||||
|
@ -1459,7 +1488,8 @@ public class CommonFunctionFactory {
|
|||
stringType,
|
||||
"substring(?1,?2,len(?1)-?2+1)",
|
||||
"substring(?1,?2,?3)",
|
||||
STRING, INTEGER, INTEGER
|
||||
STRING, INTEGER, INTEGER,
|
||||
typeConfiguration
|
||||
)
|
||||
.setArgumentListSignature( "(STRING string{ from|,} INTEGER start[{ for|,} INTEGER length])" );
|
||||
}
|
||||
|
@ -1508,7 +1538,8 @@ public class CommonFunctionFactory {
|
|||
stringType,
|
||||
"overlay(?1 placing ?2 from ?3)",
|
||||
"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])" );
|
||||
}
|
||||
|
@ -1524,7 +1555,8 @@ public class CommonFunctionFactory {
|
|||
//because DB2 doesn't like "length(?)"
|
||||
"overlay(?1 placing ?2 from ?3 for character_length(?2))",
|
||||
"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])" );
|
||||
}
|
||||
|
@ -1555,7 +1587,9 @@ public class CommonFunctionFactory {
|
|||
functionRegistry.namedDescriptorBuilder( "concat" )
|
||||
.setInvariantType(stringType)
|
||||
.setMinArgumentCount( 1 )
|
||||
.setParameterTypes(STRING)
|
||||
.setArgumentTypeResolver(
|
||||
StandardFunctionArgumentTypeResolvers.impliedOrInvariant( typeConfiguration, STRING )
|
||||
)
|
||||
.setArgumentListSignature( "(STRING string0[, STRING string1[, ...]])" )
|
||||
.register();
|
||||
}
|
||||
|
@ -1644,10 +1678,12 @@ public class CommonFunctionFactory {
|
|||
functionRegistry.namedDescriptorBuilder( "least" )
|
||||
.setMinArgumentCount( 2 )
|
||||
.setParameterTypes(COMPARABLE, COMPARABLE)
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
functionRegistry.namedDescriptorBuilder( "greatest" )
|
||||
.setMinArgumentCount( 2 )
|
||||
.setParameterTypes(COMPARABLE, COMPARABLE)
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
}
|
||||
|
||||
|
@ -1655,10 +1691,12 @@ public class CommonFunctionFactory {
|
|||
functionRegistry.namedDescriptorBuilder( "least", "min" )
|
||||
.setMinArgumentCount( 2 )
|
||||
.setParameterTypes(COMPARABLE, COMPARABLE)
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
functionRegistry.namedDescriptorBuilder( "greatest", "max" )
|
||||
.setMinArgumentCount( 2 )
|
||||
.setParameterTypes(COMPARABLE, COMPARABLE)
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
}
|
||||
|
||||
|
@ -1666,10 +1704,12 @@ public class CommonFunctionFactory {
|
|||
functionRegistry.namedDescriptorBuilder( "least", "minvalue" )
|
||||
.setMinArgumentCount( 2 )
|
||||
.setParameterTypes(COMPARABLE, COMPARABLE)
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
functionRegistry.namedDescriptorBuilder( "greatest", "maxvalue" )
|
||||
.setMinArgumentCount( 2 )
|
||||
.setParameterTypes(COMPARABLE, COMPARABLE)
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
}
|
||||
|
||||
|
@ -1682,12 +1722,14 @@ public class CommonFunctionFactory {
|
|||
.setArgumentRenderingMode( inferenceArgumentRenderingMode )
|
||||
.setExactArgumentCount( 1 )
|
||||
.setParameterTypes(COMPARABLE)
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
|
||||
functionRegistry.namedAggregateDescriptorBuilder( "min" )
|
||||
.setArgumentRenderingMode( inferenceArgumentRenderingMode )
|
||||
.setExactArgumentCount( 1 )
|
||||
.setParameterTypes(COMPARABLE)
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
|
||||
.register();
|
||||
|
||||
functionRegistry.namedAggregateDescriptorBuilder( "sum" )
|
||||
|
@ -1835,26 +1877,43 @@ public class CommonFunctionFactory {
|
|||
functionRegistry.namedWindowDescriptorBuilder( "lag" )
|
||||
.setArgumentCountBetween( 1, 3 )
|
||||
.setParameterTypes( ANY, INTEGER, ANY )
|
||||
.setArgumentTypeResolver(
|
||||
StandardFunctionArgumentTypeResolvers.composite(
|
||||
StandardFunctionArgumentTypeResolvers.argumentsOrImplied( 2 ),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, INTEGER ),
|
||||
StandardFunctionArgumentTypeResolvers.argumentsOrImplied( 0 )
|
||||
)
|
||||
)
|
||||
.setArgumentListSignature( "ANY value[, INTEGER offset[, ANY default]]" )
|
||||
.register();
|
||||
functionRegistry.namedWindowDescriptorBuilder( "lead" )
|
||||
.setArgumentCountBetween( 1, 3 )
|
||||
.setParameterTypes( ANY, INTEGER, ANY )
|
||||
.setArgumentTypeResolver(
|
||||
StandardFunctionArgumentTypeResolvers.composite(
|
||||
StandardFunctionArgumentTypeResolvers.argumentsOrImplied( 2 ),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, INTEGER ),
|
||||
StandardFunctionArgumentTypeResolvers.argumentsOrImplied( 0 )
|
||||
)
|
||||
)
|
||||
.setArgumentListSignature( "ANY value[, INTEGER offset[, ANY default]]" )
|
||||
.register();
|
||||
functionRegistry.namedWindowDescriptorBuilder( "first_value" )
|
||||
.setExactArgumentCount( 1 )
|
||||
.setParameterTypes( ANY )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
|
||||
.setArgumentListSignature( "ANY value" )
|
||||
.register();
|
||||
functionRegistry.namedWindowDescriptorBuilder( "last_value" )
|
||||
.setExactArgumentCount( 1 )
|
||||
.setParameterTypes( ANY )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
|
||||
.setArgumentListSignature( "ANY value" )
|
||||
.register();
|
||||
functionRegistry.namedWindowDescriptorBuilder( "nth_value" )
|
||||
.setExactArgumentCount( 2 )
|
||||
.setParameterTypes( ANY, INTEGER )
|
||||
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE )
|
||||
.setArgumentListSignature( "ANY value, INTEGER nth" )
|
||||
.register();
|
||||
}
|
||||
|
@ -1969,6 +2028,7 @@ public class CommonFunctionFactory {
|
|||
public void crc32() {
|
||||
functionRegistry.namedDescriptorBuilder( "crc32" )
|
||||
.setInvariantType(integerType)
|
||||
.setParameterTypes( STRING )
|
||||
.setExactArgumentCount( 1 )
|
||||
.register();
|
||||
}
|
||||
|
@ -1976,6 +2036,7 @@ public class CommonFunctionFactory {
|
|||
public void sha1() {
|
||||
functionRegistry.namedDescriptorBuilder( "sha1" )
|
||||
.setInvariantType(stringType)
|
||||
.setParameterTypes( STRING )
|
||||
.setExactArgumentCount( 1 )
|
||||
.register();
|
||||
}
|
||||
|
@ -1983,6 +2044,7 @@ public class CommonFunctionFactory {
|
|||
public void sha2() {
|
||||
functionRegistry.namedDescriptorBuilder( "sha2" )
|
||||
.setInvariantType(stringType)
|
||||
.setParameterTypes( STRING, INTEGER )
|
||||
.setExactArgumentCount( 2 )
|
||||
.register();
|
||||
}
|
||||
|
@ -1990,6 +2052,7 @@ public class CommonFunctionFactory {
|
|||
public void sha() {
|
||||
functionRegistry.namedDescriptorBuilder( "sha" )
|
||||
.setInvariantType(stringType)
|
||||
.setParameterTypes( STRING )
|
||||
.setExactArgumentCount( 1 )
|
||||
.register();
|
||||
}
|
||||
|
@ -2156,6 +2219,7 @@ public class CommonFunctionFactory {
|
|||
public void format_formatdatetime() {
|
||||
functionRegistry.namedDescriptorBuilder( "format", "formatdatetime" )
|
||||
.setInvariantType(stringType)
|
||||
.setParameterTypes( TEMPORAL, STRING )
|
||||
.setArgumentsValidator( formatValidator() )
|
||||
.setArgumentListSignature( "(TEMPORAL datetime as STRING pattern)" )
|
||||
.register();
|
||||
|
@ -2169,6 +2233,7 @@ public class CommonFunctionFactory {
|
|||
public void format_toChar() {
|
||||
functionRegistry.namedDescriptorBuilder( "format", "to_char" )
|
||||
.setInvariantType(stringType)
|
||||
.setParameterTypes( TEMPORAL, STRING )
|
||||
.setArgumentsValidator( formatValidator() )
|
||||
.setArgumentListSignature( "(TEMPORAL datetime as STRING pattern)" )
|
||||
.register();
|
||||
|
@ -2182,6 +2247,7 @@ public class CommonFunctionFactory {
|
|||
public void format_dateFormat() {
|
||||
functionRegistry.namedDescriptorBuilder( "format", "date_format" )
|
||||
.setInvariantType(stringType)
|
||||
.setParameterTypes( TEMPORAL, STRING )
|
||||
.setArgumentsValidator( formatValidator() )
|
||||
.setArgumentListSignature( "(TEMPORAL datetime as STRING pattern)" )
|
||||
.register();
|
||||
|
@ -2195,6 +2261,7 @@ public class CommonFunctionFactory {
|
|||
public void format_toVarchar() {
|
||||
functionRegistry.namedDescriptorBuilder( "format", "to_varchar" )
|
||||
.setInvariantType(stringType)
|
||||
.setParameterTypes( TEMPORAL, STRING )
|
||||
.setArgumentsValidator( formatValidator() )
|
||||
.setArgumentListSignature( "(TEMPORAL datetime as STRING pattern)" )
|
||||
.register();
|
||||
|
@ -2223,7 +2290,7 @@ public class CommonFunctionFactory {
|
|||
functionRegistry.patternDescriptorBuilder("collate", "(?1 collate '?2')")
|
||||
.setInvariantType(stringType)
|
||||
.setExactArgumentCount( 2 )
|
||||
.setParameterTypes(STRING, ANY)
|
||||
.setParameterTypes(STRING, COLLATION)
|
||||
.setArgumentListSignature("(STRING string as COLLATION collation)")
|
||||
.register();
|
||||
}
|
||||
|
|
|
@ -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.internal.PatternRenderer;
|
||||
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.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
|
@ -58,7 +59,8 @@ public class CountFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
|
|||
StandardArgumentsValidators.exactly( 1 ),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.LONG )
|
||||
)
|
||||
),
|
||||
null
|
||||
);
|
||||
this.dialect = dialect;
|
||||
this.defaultArgumentRenderingMode = defaultArgumentRenderingMode;
|
||||
|
@ -102,9 +104,11 @@ public class CountFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
|
|||
// In the end, the expression looks like the following:
|
||||
// count(distinct coalesce(nullif(coalesce(col1 || '', '\0'), ''), '\01') || '\0' || coalesce(nullif(coalesce(col2 || '', '\0'), ''), '\02'))
|
||||
if ( caseWrapper ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
sqlAppender.appendSql( "case when " );
|
||||
filter.accept( translator );
|
||||
sqlAppender.appendSql( " then " );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
sqlAppender.appendSql( "coalesce(nullif(coalesce(" );
|
||||
renderCastedArgument( sqlAppender, translator, expressions.get( 0 ) );
|
||||
|
@ -162,7 +166,9 @@ public class CountFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
|
|||
else if ( !dialect.supportsTupleCounts() ) {
|
||||
sqlAppender.appendSql( "case when " );
|
||||
if ( caseWrapper ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
filter.accept( translator );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
sqlAppender.appendSql( " and " );
|
||||
}
|
||||
translator.render( expressions.get( 0 ), defaultArgumentRenderingMode );
|
||||
|
@ -193,9 +199,11 @@ public class CountFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
|
|||
}
|
||||
sqlAppender.appendSql( ')' );
|
||||
if ( filter != null && !caseWrapper ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
sqlAppender.appendSql( " filter (where " );
|
||||
filter.accept( translator );
|
||||
sqlAppender.appendSql( ')' );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,8 +258,10 @@ public class CountFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
|
|||
boolean caseWrapper,
|
||||
SqlAstNode realArg) {
|
||||
if ( caseWrapper ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
sqlAppender.appendSql( "case when " );
|
||||
filter.accept( translator );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
sqlAppender.appendSql( " then " );
|
||||
if ( realArg instanceof Star ) {
|
||||
sqlAppender.appendSql( "1" );
|
||||
|
|
|
@ -31,7 +31,8 @@ public class CurrentFunction
|
|||
super(
|
||||
name,
|
||||
StandardArgumentsValidators.NO_ARGS,
|
||||
StandardFunctionReturnTypeResolvers.invariant( type )
|
||||
StandardFunctionReturnTypeResolvers.invariant( type ),
|
||||
null
|
||||
);
|
||||
this.sql = sql;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.dialect.function;
|
|||
|
||||
import org.hibernate.dialect.OracleDialect;
|
||||
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.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
|
@ -20,6 +21,9 @@ import org.hibernate.type.spi.TypeConfiguration;
|
|||
import java.util.List;
|
||||
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
|
||||
* the format pattern. So just split the pattern into bits, call
|
||||
|
@ -37,7 +41,8 @@ public class DB2FormatEmulation
|
|||
CommonFunctionFactory.formatValidator(),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
|
||||
)
|
||||
),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, TEMPORAL, STRING )
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.List;
|
|||
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
|
@ -36,7 +37,8 @@ public class DerbyLpadEmulation
|
|||
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, INTEGER ),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
|
||||
)
|
||||
),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, STRING, INTEGER )
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.List;
|
|||
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
|
@ -36,7 +37,8 @@ public class DerbyRpadEmulation
|
|||
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, INTEGER ),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
|
||||
)
|
||||
),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, STRING, INTEGER )
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,9 @@ import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescript
|
|||
import org.hibernate.query.sqm.function.FunctionKind;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
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.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
|
@ -43,7 +45,8 @@ public class EveryAnyEmulation extends AbstractSqmSelfRenderingFunctionDescripto
|
|||
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 1 ), BOOLEAN ),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.BOOLEAN )
|
||||
)
|
||||
),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, BOOLEAN )
|
||||
);
|
||||
this.every = every;
|
||||
}
|
||||
|
@ -56,7 +59,9 @@ public class EveryAnyEmulation extends AbstractSqmSelfRenderingFunctionDescripto
|
|||
SqlAstTranslator<?> walker) {
|
||||
sqlAppender.appendSql( "(sum(case when " );
|
||||
if ( filter != null ) {
|
||||
walker.getCurrentClauseStack().push( Clause.WHERE );
|
||||
filter.accept( walker );
|
||||
walker.getCurrentClauseStack().pop();
|
||||
sqlAppender.appendSql( " then case when " );
|
||||
sqlAstArguments.get( 0 ).accept( walker );
|
||||
if ( every ) {
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
|
|||
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.expression.*;
|
||||
|
@ -44,14 +45,15 @@ public class ExtractFunction
|
|||
|
||||
private final Dialect dialect;
|
||||
|
||||
public ExtractFunction(Dialect dialect) {
|
||||
public ExtractFunction(Dialect dialect, TypeConfiguration typeConfiguration) {
|
||||
super(
|
||||
"extract",
|
||||
new ArgumentTypesValidator(
|
||||
StandardArgumentsValidators.exactly( 2 ),
|
||||
TEMPORAL_UNIT, TEMPORAL
|
||||
),
|
||||
StandardFunctionReturnTypeResolvers.useArgType( 1 )
|
||||
StandardFunctionReturnTypeResolvers.useArgType( 1 ),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, TEMPORAL_UNIT, TEMPORAL )
|
||||
);
|
||||
this.dialect = dialect;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.List;
|
|||
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.function.FunctionKind;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
|
@ -32,7 +33,8 @@ public class HypotheticalSetFunction extends AbstractSqmSelfRenderingFunctionDes
|
|||
null,
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( returnType )
|
||||
)
|
||||
),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -74,6 +76,7 @@ public class HypotheticalSetFunction extends AbstractSqmSelfRenderingFunctionDes
|
|||
}
|
||||
sqlAppender.appendSql( ')' );
|
||||
if ( withinGroup != null && !withinGroup.isEmpty() ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
|
||||
sqlAppender.appendSql( " within group (order by " );
|
||||
withinGroup.get( 0 ).accept( translator );
|
||||
for ( int i = 1; i < withinGroup.size(); i++ ) {
|
||||
|
@ -81,11 +84,14 @@ public class HypotheticalSetFunction extends AbstractSqmSelfRenderingFunctionDes
|
|||
withinGroup.get( i ).accept( translator );
|
||||
}
|
||||
sqlAppender.appendSql( ')' );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
if ( filter != null ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
sqlAppender.appendSql( " filter (where " );
|
||||
filter.accept( translator );
|
||||
sqlAppender.appendSql( ')' );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
|
|||
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmBinaryArithmetic;
|
||||
|
@ -54,7 +55,8 @@ public class InsertSubstringOverlayEmulation
|
|||
),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
|
||||
)
|
||||
),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, STRING, STRING, INTEGER, INTEGER )
|
||||
);
|
||||
this.strictSubstring = strictSubstring;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ public class IntegralTimestampaddFunction
|
|||
private final BasicType<Integer> integerType;
|
||||
|
||||
public IntegralTimestampaddFunction(Dialect dialect, TypeConfiguration typeConfiguration) {
|
||||
super( dialect );
|
||||
super( dialect, typeConfiguration );
|
||||
this.dialect = dialect;
|
||||
this.integerType = typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER );
|
||||
//This is kinda wrong, we're supposed to use findFunctionDescriptor("cast"), not instantiate CastFunction
|
||||
|
|
|
@ -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.FunctionParameterType;
|
||||
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.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
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.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
|
@ -44,7 +46,10 @@ public class InverseDistributionFunction extends AbstractSqmSelfRenderingFunctio
|
|||
parameterType == null
|
||||
? StandardArgumentsValidators.exactly( 0 )
|
||||
: 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( ')' );
|
||||
if ( withinGroup != null && !withinGroup.isEmpty() ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
|
||||
sqlAppender.appendSql( " within group (order by " );
|
||||
withinGroup.get( 0 ).accept( translator );
|
||||
for ( int i = 1; i < withinGroup.size(); i++ ) {
|
||||
|
@ -110,11 +116,14 @@ public class InverseDistributionFunction extends AbstractSqmSelfRenderingFunctio
|
|||
withinGroup.get( i ).accept( translator );
|
||||
}
|
||||
sqlAppender.appendSql( ')' );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
if ( filter != null ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
sqlAppender.appendSql( " filter (where " );
|
||||
filter.accept( translator );
|
||||
sqlAppender.appendSql( ')' );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,9 @@ import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescript
|
|||
import org.hibernate.query.sqm.function.FunctionKind;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
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.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
|
@ -40,7 +42,8 @@ public class ListaggFunction extends AbstractSqmSelfRenderingFunctionDescriptor
|
|||
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, STRING ),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
|
||||
)
|
||||
),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, STRING, STRING )
|
||||
);
|
||||
this.emptyWithinReplacement = emptyWithinReplacement;
|
||||
}
|
||||
|
@ -82,7 +85,9 @@ public class ListaggFunction extends AbstractSqmSelfRenderingFunctionDescriptor
|
|||
}
|
||||
if ( caseWrapper ) {
|
||||
sqlAppender.appendSql( "case when " );
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
filter.accept( translator );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
sqlAppender.appendSql( " then " );
|
||||
arg.accept( translator );
|
||||
sqlAppender.appendSql( " else null end" );
|
||||
|
@ -96,6 +101,7 @@ public class ListaggFunction extends AbstractSqmSelfRenderingFunctionDescriptor
|
|||
}
|
||||
sqlAppender.appendSql( ')' );
|
||||
if ( withinGroup != null && !withinGroup.isEmpty() ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
|
||||
sqlAppender.appendSql( " within group (order by " );
|
||||
withinGroup.get( 0 ).accept( translator );
|
||||
for ( int i = 1; i < withinGroup.size(); i++ ) {
|
||||
|
@ -103,15 +109,18 @@ public class ListaggFunction extends AbstractSqmSelfRenderingFunctionDescriptor
|
|||
withinGroup.get( i ).accept( translator );
|
||||
}
|
||||
sqlAppender.appendSql( ')' );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
else if ( emptyWithinReplacement != null ) {
|
||||
sqlAppender.appendSql( ' ' );
|
||||
sqlAppender.appendSql( emptyWithinReplacement );
|
||||
}
|
||||
if ( !caseWrapper && filter != null ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
sqlAppender.appendSql( " filter (where " );
|
||||
filter.accept( translator );
|
||||
sqlAppender.appendSql( ')' );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,9 @@ import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescript
|
|||
import org.hibernate.query.sqm.function.FunctionKind;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
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.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
|
@ -41,7 +43,8 @@ public class ListaggGroupConcatEmulation extends AbstractSqmSelfRenderingFunctio
|
|||
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, STRING ),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
|
||||
)
|
||||
),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, STRING, STRING )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -81,22 +84,26 @@ public class ListaggGroupConcatEmulation extends AbstractSqmSelfRenderingFunctio
|
|||
arg = (Expression) firstArg;
|
||||
}
|
||||
if ( caseWrapper ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
sqlAppender.appendSql( "case when " );
|
||||
filter.accept( translator );
|
||||
sqlAppender.appendSql( " then " );
|
||||
arg.accept( translator );
|
||||
sqlAppender.appendSql( " else null end" );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
else {
|
||||
arg.accept( translator );
|
||||
}
|
||||
if ( withinGroup != null && !withinGroup.isEmpty() ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
|
||||
sqlAppender.appendSql( " order by " );
|
||||
withinGroup.get( 0 ).accept( translator );
|
||||
for ( int i = 1; i < withinGroup.size(); i++ ) {
|
||||
sqlAppender.appendSql( ',' );
|
||||
withinGroup.get( i ).accept( translator );
|
||||
}
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
if ( sqlAstArguments.size() != 1 ) {
|
||||
SqlAstNode separator = sqlAstArguments.get( 1 );
|
||||
|
@ -109,9 +116,11 @@ public class ListaggGroupConcatEmulation extends AbstractSqmSelfRenderingFunctio
|
|||
}
|
||||
sqlAppender.appendSql( ')' );
|
||||
if ( !caseWrapper && filter != null ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
sqlAppender.appendSql( " filter (where " );
|
||||
filter.accept( translator );
|
||||
sqlAppender.appendSql( ')' );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,9 @@ import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescript
|
|||
import org.hibernate.query.sqm.function.FunctionKind;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
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.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
|
@ -51,7 +53,8 @@ public class ListaggStringAggEmulation extends AbstractSqmSelfRenderingFunctionD
|
|||
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, STRING ),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
|
||||
)
|
||||
),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, STRING, STRING )
|
||||
);
|
||||
this.functionName = functionName;
|
||||
this.stringType = stringType;
|
||||
|
@ -95,11 +98,13 @@ public class ListaggStringAggEmulation extends AbstractSqmSelfRenderingFunctionD
|
|||
arg = (Expression) firstArg;
|
||||
}
|
||||
if ( caseWrapper ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
sqlAppender.appendSql( "case when " );
|
||||
filter.accept( translator );
|
||||
sqlAppender.appendSql( " then " );
|
||||
renderAsString( sqlAppender, translator, arg );
|
||||
sqlAppender.appendSql( " else null end" );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
else {
|
||||
renderAsString( sqlAppender, translator, arg );
|
||||
|
@ -113,16 +118,19 @@ public class ListaggStringAggEmulation extends AbstractSqmSelfRenderingFunctionD
|
|||
sqlAppender.appendSql( ',' );
|
||||
separator.accept( translator );
|
||||
if ( !withinGroupClause && withinGroup != null && !withinGroup.isEmpty() ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
|
||||
sqlAppender.appendSql( " order by " );
|
||||
withinGroup.get( 0 ).accept( translator );
|
||||
for ( int i = 1; i < withinGroup.size(); i++ ) {
|
||||
sqlAppender.appendSql( ',' );
|
||||
withinGroup.get( i ).accept( translator );
|
||||
}
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
}
|
||||
sqlAppender.appendSql( ')' );
|
||||
if ( withinGroupClause && withinGroup != null && !withinGroup.isEmpty() ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
|
||||
sqlAppender.appendSql( " within group (order by " );
|
||||
withinGroup.get( 0 ).accept( translator );
|
||||
for ( int i = 1; i < withinGroup.size(); i++ ) {
|
||||
|
@ -130,11 +138,14 @@ public class ListaggStringAggEmulation extends AbstractSqmSelfRenderingFunctionD
|
|||
withinGroup.get( i ).accept( translator );
|
||||
}
|
||||
sqlAppender.appendSql( ')' );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
if ( !caseWrapper && filter != null ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
sqlAppender.appendSql( " filter (where " );
|
||||
filter.accept( translator );
|
||||
sqlAppender.appendSql( ')' );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
|
|||
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
@ -34,7 +35,8 @@ public class LocatePositionEmulation extends AbstractSqmFunctionDescriptor {
|
|||
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 2 ), STRING, STRING ),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER )
|
||||
)
|
||||
),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, STRING, STRING )
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
|
|||
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmTrimSpecification;
|
||||
|
@ -47,7 +48,8 @@ public class LpadRpadPadEmulation
|
|||
),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
|
||||
)
|
||||
),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, STRING, INTEGER, TRIM_SPEC, STRING )
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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.FunctionParameterType;
|
||||
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.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
|
@ -41,7 +43,8 @@ public class MinMaxCaseEveryAnyEmulation extends AbstractSqmSelfRenderingFunctio
|
|||
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 1 ), FunctionParameterType.BOOLEAN ),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.BOOLEAN )
|
||||
)
|
||||
),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, FunctionParameterType.BOOLEAN )
|
||||
);
|
||||
this.every = every;
|
||||
}
|
||||
|
@ -59,7 +62,9 @@ public class MinMaxCaseEveryAnyEmulation extends AbstractSqmSelfRenderingFunctio
|
|||
sqlAppender.appendSql( "max(case when " );
|
||||
}
|
||||
if ( filter != null ) {
|
||||
walker.getCurrentClauseStack().push( Clause.WHERE );
|
||||
filter.accept( walker );
|
||||
walker.getCurrentClauseStack().pop();
|
||||
sqlAppender.appendSql( " then case when " );
|
||||
sqlAstArguments.get( 0 ).accept( walker );
|
||||
sqlAppender.appendSql( " then 1 else 0 end else null end)" );
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.dialect.function;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
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!" );
|
||||
}
|
||||
if ( caseWrapper ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
sqlAppender.appendSql( "case when " );
|
||||
filter.accept( translator );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
sqlAppender.appendSql( " then " );
|
||||
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
|
||||
withinGroup.get( 0 ).accept( translator );
|
||||
sqlAppender.appendSql( " else null end)" );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
else {
|
||||
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
|
||||
withinGroup.get( 0 ).accept( translator );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
sqlAppender.appendSql( ')' );
|
||||
if ( filter != null ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
sqlAppender.appendSql( " filter (where " );
|
||||
filter.accept( translator );
|
||||
sqlAppender.appendSql( ')' );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
|
|||
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
|
@ -35,7 +36,8 @@ public class NvlCoalesceEmulation
|
|||
super(
|
||||
"coalesce",
|
||||
StandardArgumentsValidators.min( 2 ),
|
||||
StandardFunctionReturnTypeResolvers.useFirstNonNull()
|
||||
StandardFunctionReturnTypeResolvers.useFirstNonNull(),
|
||||
StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.List;
|
|||
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
|
@ -32,7 +33,8 @@ public class QuantifiedLeastGreatestEmulation
|
|||
super(
|
||||
least ? "least" : "greatest",
|
||||
new ArgumentTypesValidator( StandardArgumentsValidators.min( 2 ), COMPARABLE, COMPARABLE ),
|
||||
StandardFunctionReturnTypeResolvers.useFirstNonNull()
|
||||
StandardFunctionReturnTypeResolvers.useFirstNonNull(),
|
||||
StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE
|
||||
);
|
||||
this.operator = least ? "<=" : ">=";
|
||||
}
|
||||
|
|
|
@ -11,8 +11,11 @@ import java.util.List;
|
|||
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.function.FunctionKind;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
|
||||
import org.hibernate.query.sqm.produce.function.FunctionParameterType;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
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.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
|
@ -42,7 +45,8 @@ public class SQLServerEveryAnyEmulation extends AbstractSqmSelfRenderingFunction
|
|||
new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 1 ), BOOLEAN ),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.BOOLEAN )
|
||||
)
|
||||
),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, FunctionParameterType.BOOLEAN )
|
||||
);
|
||||
this.every = every;
|
||||
}
|
||||
|
@ -60,7 +64,9 @@ public class SQLServerEveryAnyEmulation extends AbstractSqmSelfRenderingFunction
|
|||
sqlAppender.appendSql( "max(iif(" );
|
||||
}
|
||||
if ( filter != null ) {
|
||||
walker.getCurrentClauseStack().push( Clause.WHERE );
|
||||
filter.accept( walker );
|
||||
walker.getCurrentClauseStack().pop();
|
||||
sqlAppender.appendSql( ",iif(" );
|
||||
sqlAstArguments.get( 0 ).accept( walker );
|
||||
sqlAppender.appendSql( ",1,0),null))" );
|
||||
|
|
|
@ -11,6 +11,7 @@ import jakarta.persistence.TemporalType;
|
|||
|
||||
import org.hibernate.dialect.SQLServerDialect;
|
||||
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.sql.ast.SqlAstTranslator;
|
||||
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.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.
|
||||
*
|
||||
|
@ -35,7 +39,8 @@ public class SQLServerFormatEmulation extends AbstractSqmSelfRenderingFunctionDe
|
|||
CommonFunctionFactory.formatValidator(),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
|
||||
)
|
||||
),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, TEMPORAL, STRING )
|
||||
);
|
||||
this.dialect = dialect;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,8 @@ public class SqlFunction
|
|||
super(
|
||||
"sql",
|
||||
StandardArgumentsValidators.min( 1 ),
|
||||
StandardFunctionReturnTypeResolvers.invariant( JavaObjectType.INSTANCE )
|
||||
StandardFunctionReturnTypeResolvers.invariant( JavaObjectType.INSTANCE ),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescript
|
|||
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
|
||||
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.expression.DurationUnit;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -46,14 +48,15 @@ public class TimestampaddFunction
|
|||
|
||||
private final Dialect dialect;
|
||||
|
||||
public TimestampaddFunction(Dialect dialect) {
|
||||
public TimestampaddFunction(Dialect dialect, TypeConfiguration typeConfiguration) {
|
||||
super(
|
||||
"timestampadd",
|
||||
new ArgumentTypesValidator(
|
||||
StandardArgumentsValidators.exactly( 3 ),
|
||||
TEMPORAL_UNIT, INTEGER, TEMPORAL
|
||||
),
|
||||
StandardFunctionReturnTypeResolvers.useArgType( 3 )
|
||||
StandardFunctionReturnTypeResolvers.useArgType( 3 ),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, TEMPORAL_UNIT, INTEGER, TEMPORAL )
|
||||
);
|
||||
this.dialect = dialect;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.dialect.function;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.persistence.TemporalType;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.query.ReturnableType;
|
||||
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.produce.function.ArgumentTypesValidator;
|
||||
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.internal.PatternRenderer;
|
||||
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.spi.TypeConfiguration;
|
||||
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL;
|
||||
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL_UNIT;
|
||||
|
@ -54,7 +56,8 @@ public class TimestampdiffFunction
|
|||
),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.LONG )
|
||||
)
|
||||
),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, TEMPORAL_UNIT, TEMPORAL, TEMPORAL )
|
||||
);
|
||||
this.dialect = dialect;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.hibernate.query.sqm.TrimSpec;
|
|||
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
|
@ -50,7 +51,8 @@ public class TrimFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
|
|||
),
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING )
|
||||
)
|
||||
),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, TRIM_SPEC, STRING, STRING )
|
||||
);
|
||||
this.dialect = dialect;
|
||||
}
|
||||
|
|
|
@ -3191,7 +3191,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
null,
|
||||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
resolveExpressibleTypeBasic( Object.class )
|
||||
)
|
||||
),
|
||||
null
|
||||
);
|
||||
}
|
||||
return functionTemplate.generateSqmExpression(
|
||||
|
@ -3262,6 +3263,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
StandardFunctionReturnTypeResolvers.invariant(
|
||||
resolveExpressibleTypeBasic( Object.class )
|
||||
),
|
||||
null,
|
||||
functionName,
|
||||
functionKind,
|
||||
null,
|
||||
|
|
|
@ -6,45 +6,52 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.function;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.query.ReturnableType;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
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.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
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.SqmVisitableNode;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.select.SqmOrderByClause;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractSqmFunctionDescriptor implements SqmFunctionDescriptor {
|
||||
private final ArgumentsValidator argumentsValidator;
|
||||
private final FunctionReturnTypeResolver returnTypeResolver;
|
||||
private final FunctionArgumentTypeResolver functionArgumentTypeResolver;
|
||||
private final String name;
|
||||
|
||||
public AbstractSqmFunctionDescriptor(String name) {
|
||||
this( name, null, null );
|
||||
this( name, null, null, null );
|
||||
}
|
||||
|
||||
public AbstractSqmFunctionDescriptor(String name, ArgumentsValidator argumentsValidator) {
|
||||
this( name, argumentsValidator, null );
|
||||
public AbstractSqmFunctionDescriptor(
|
||||
String name,
|
||||
ArgumentsValidator argumentsValidator) {
|
||||
this( name, argumentsValidator, null, null );
|
||||
}
|
||||
|
||||
public AbstractSqmFunctionDescriptor(
|
||||
String name,
|
||||
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.argumentsValidator = argumentsValidator == null
|
||||
? StandardArgumentsValidators.NONE
|
||||
|
@ -52,6 +59,9 @@ public abstract class AbstractSqmFunctionDescriptor implements SqmFunctionDescri
|
|||
this.returnTypeResolver = returnTypeResolver == null
|
||||
? StandardFunctionReturnTypeResolvers.useFirstNonNull()
|
||||
: returnTypeResolver;
|
||||
this.functionArgumentTypeResolver = argumentTypeResolver == null
|
||||
? StandardFunctionArgumentTypeResolvers.NULL
|
||||
: argumentTypeResolver;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
@ -71,6 +81,10 @@ public abstract class AbstractSqmFunctionDescriptor implements SqmFunctionDescri
|
|||
return returnTypeResolver;
|
||||
}
|
||||
|
||||
public FunctionArgumentTypeResolver getArgumentTypeResolver() {
|
||||
return functionArgumentTypeResolver;
|
||||
}
|
||||
|
||||
public String getReturnSignature() {
|
||||
String result = returnTypeResolver.getReturnType();
|
||||
return result.isEmpty() ? "" : result + " ";
|
||||
|
@ -81,23 +95,6 @@ public abstract class AbstractSqmFunctionDescriptor implements SqmFunctionDescri
|
|||
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
|
||||
public final <T> SelfRenderingSqmFunction<T> generateSqmExpression(
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.query.sqm.function;
|
|||
import org.hibernate.query.ReturnableType;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
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.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
|
@ -33,8 +34,9 @@ public abstract class AbstractSqmSelfRenderingFunctionDescriptor
|
|||
public AbstractSqmSelfRenderingFunctionDescriptor(
|
||||
String name,
|
||||
ArgumentsValidator argumentsValidator,
|
||||
FunctionReturnTypeResolver returnTypeResolver) {
|
||||
super( name, argumentsValidator, returnTypeResolver );
|
||||
FunctionReturnTypeResolver returnTypeResolver,
|
||||
FunctionArgumentTypeResolver argumentTypeResolver) {
|
||||
super( name, argumentsValidator, returnTypeResolver, argumentTypeResolver );
|
||||
this.functionKind = FunctionKind.NORMAL;
|
||||
}
|
||||
|
||||
|
@ -42,8 +44,9 @@ public abstract class AbstractSqmSelfRenderingFunctionDescriptor
|
|||
String name,
|
||||
FunctionKind functionKind,
|
||||
ArgumentsValidator argumentsValidator,
|
||||
FunctionReturnTypeResolver returnTypeResolver) {
|
||||
super( name, argumentsValidator, returnTypeResolver );
|
||||
FunctionReturnTypeResolver returnTypeResolver,
|
||||
FunctionArgumentTypeResolver argumentTypeResolver) {
|
||||
super( name, argumentsValidator, returnTypeResolver, argumentTypeResolver );
|
||||
this.functionKind = functionKind;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.FunctionParameterType;
|
||||
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.tree.SqmTypedNode;
|
||||
import org.hibernate.type.BasicType;
|
||||
|
@ -60,6 +61,7 @@ public class MultipatternSqmFunctionDescriptor extends AbstractSqmFunctionDescri
|
|||
String name,
|
||||
SqmFunctionDescriptor[] functions,
|
||||
BasicType<?> type,
|
||||
TypeConfiguration typeConfiguration,
|
||||
FunctionParameterType... parameterTypes) {
|
||||
super(
|
||||
name,
|
||||
|
@ -70,7 +72,8 @@ public class MultipatternSqmFunctionDescriptor extends AbstractSqmFunctionDescri
|
|||
),
|
||||
parameterTypes
|
||||
),
|
||||
StandardFunctionReturnTypeResolvers.invariant( type )
|
||||
StandardFunctionReturnTypeResolvers.invariant( type ),
|
||||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, parameterTypes )
|
||||
);
|
||||
this.functions = functions;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
package org.hibernate.query.sqm.function;
|
||||
|
||||
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.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
|
@ -47,6 +49,7 @@ public class NamedSqmFunctionDescriptor
|
|||
useParenthesesWhenNoArgs,
|
||||
argumentsValidator,
|
||||
returnTypeResolver,
|
||||
null,
|
||||
functionName,
|
||||
FunctionKind.NORMAL,
|
||||
null,
|
||||
|
@ -59,11 +62,31 @@ public class NamedSqmFunctionDescriptor
|
|||
boolean useParenthesesWhenNoArgs,
|
||||
ArgumentsValidator argumentsValidator,
|
||||
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,
|
||||
FunctionKind functionKind,
|
||||
String argumentListSignature,
|
||||
SqlAstNodeRenderingMode argumentRenderingMode) {
|
||||
super( name, functionKind, argumentsValidator, returnTypeResolver );
|
||||
super( name, functionKind, argumentsValidator, returnTypeResolver, argumentTypeResolver );
|
||||
|
||||
this.functionName = functionName;
|
||||
this.useParenthesesWhenNoArgs = useParenthesesWhenNoArgs;
|
||||
|
@ -150,8 +173,10 @@ public class NamedSqmFunctionDescriptor
|
|||
sqlAppender.appendSql( "," );
|
||||
}
|
||||
if ( caseWrapper && !( arg instanceof Distinct ) ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
sqlAppender.appendSql( "case when " );
|
||||
filter.accept( translator );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
sqlAppender.appendSql( " then " );
|
||||
if ( ( arg instanceof Star ) ) {
|
||||
sqlAppender.appendSql( "1" );
|
||||
|
@ -172,6 +197,7 @@ public class NamedSqmFunctionDescriptor
|
|||
}
|
||||
|
||||
if ( withinGroup != null && !withinGroup.isEmpty() ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
|
||||
sqlAppender.appendSql( " within group (order by" );
|
||||
translator.render( withinGroup.get( 0 ), argumentRenderingMode );
|
||||
for ( int i = 1; i < withinGroup.size(); i++ ) {
|
||||
|
@ -179,6 +205,7 @@ public class NamedSqmFunctionDescriptor
|
|||
translator.render( withinGroup.get( 0 ), argumentRenderingMode );
|
||||
}
|
||||
sqlAppender.appendSql( ')' );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
|
||||
if ( fromFirst != null ) {
|
||||
|
@ -199,9 +226,11 @@ public class NamedSqmFunctionDescriptor
|
|||
}
|
||||
|
||||
if ( filter != null && !caseWrapper ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
sqlAppender.appendSql( " filter (where " );
|
||||
filter.accept( translator );
|
||||
sqlAppender.appendSql( ')' );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.query.sqm.function;
|
||||
|
||||
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.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
|
||||
|
@ -48,6 +49,7 @@ public class PatternBasedSqmFunctionDescriptor
|
|||
PatternRenderer renderer,
|
||||
ArgumentsValidator argumentsValidator,
|
||||
FunctionReturnTypeResolver returnTypeResolver,
|
||||
FunctionArgumentTypeResolver argumentTypeResolver,
|
||||
String name,
|
||||
FunctionKind functionKind,
|
||||
String argumentListSignature) {
|
||||
|
@ -63,7 +65,8 @@ public class PatternBasedSqmFunctionDescriptor
|
|||
: renderer.hasVarargs()
|
||||
? StandardArgumentsValidators.min( renderer.getParamCount() )
|
||||
: StandardArgumentsValidators.exactly( renderer.getParamCount() ),
|
||||
returnTypeResolver
|
||||
returnTypeResolver,
|
||||
argumentTypeResolver
|
||||
);
|
||||
this.renderer = renderer;
|
||||
this.argumentListSignature = argumentListSignature;
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.query.sqm.function;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
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.SqmExpressible;
|
||||
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.StandardFunctionArgumentTypeResolvers;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
|
@ -97,14 +100,38 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
|
|||
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() ) {
|
||||
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() );
|
||||
for ( SqmTypedNode<?> sqmArgument : sqmArguments ) {
|
||||
sqlAstArguments.add( (SqlAstNode) ( (SqmVisitableNode) sqmArgument ).accept( walker ) );
|
||||
for ( int i = 0; i < sqmArguments.size(); i++ ) {
|
||||
typeAccess.argumentIndex = i;
|
||||
sqlAstArguments.add(
|
||||
(SqlAstNode) walker.visitWithInferredType( (SqmVisitableNode) sqmArguments.get( i ), typeAccess )
|
||||
);
|
||||
}
|
||||
return sqlAstArguments;
|
||||
}
|
||||
|
@ -184,4 +211,26 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
|
|||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ public class SelfRenderingSqmOrderedSetAggregateFunction<T> extends SelfRenderin
|
|||
withinGroup = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
walker.getCurrentClauseStack().push( Clause.ORDER );
|
||||
walker.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
|
||||
try {
|
||||
final List<SqmSortSpecification> sortSpecifications = this.withinGroup.getSortSpecifications();
|
||||
withinGroup = new ArrayList<>( sortSpecifications.size() );
|
||||
|
|
|
@ -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.PatternFunctionDescriptorBuilder;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
|
@ -305,8 +306,16 @@ public class SqmFunctionRegistry {
|
|||
BasicType type,
|
||||
String pattern0,
|
||||
String pattern1,
|
||||
FunctionParameterType parameterType) {
|
||||
return registerPatterns( name, type, new FunctionParameterType[]{parameterType}, pattern0, pattern1 );
|
||||
FunctionParameterType parameterType,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return registerPatterns(
|
||||
name,
|
||||
type,
|
||||
new FunctionParameterType[] { parameterType },
|
||||
typeConfiguration,
|
||||
pattern0,
|
||||
pattern1
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -320,10 +329,17 @@ public class SqmFunctionRegistry {
|
|||
String pattern1,
|
||||
String pattern2,
|
||||
FunctionParameterType parameterType1,
|
||||
FunctionParameterType parameterType2) {
|
||||
return registerPatterns( name, type,
|
||||
new FunctionParameterType[]{parameterType1,parameterType2},
|
||||
null, pattern1, pattern2 );
|
||||
FunctionParameterType parameterType2,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return registerPatterns(
|
||||
name,
|
||||
type,
|
||||
new FunctionParameterType[] { parameterType1, parameterType2 },
|
||||
typeConfiguration,
|
||||
null,
|
||||
pattern1,
|
||||
pattern2
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -338,10 +354,18 @@ public class SqmFunctionRegistry {
|
|||
String pattern3,
|
||||
FunctionParameterType parameterType1,
|
||||
FunctionParameterType parameterType2,
|
||||
FunctionParameterType parameterType3) {
|
||||
return registerPatterns( name, type,
|
||||
new FunctionParameterType[]{parameterType1,parameterType2,parameterType3},
|
||||
null, null, pattern2, pattern3 );
|
||||
FunctionParameterType parameterType3,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return registerPatterns(
|
||||
name,
|
||||
type,
|
||||
new FunctionParameterType[] { parameterType1, parameterType2, parameterType3 },
|
||||
typeConfiguration,
|
||||
null,
|
||||
null,
|
||||
pattern2,
|
||||
pattern3
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -357,16 +381,31 @@ public class SqmFunctionRegistry {
|
|||
FunctionParameterType parameterType1,
|
||||
FunctionParameterType parameterType2,
|
||||
FunctionParameterType parameterType3,
|
||||
FunctionParameterType parameterType4) {
|
||||
return registerPatterns( name, type,
|
||||
new FunctionParameterType[]{parameterType1,parameterType2,parameterType3, parameterType4},
|
||||
null, null, null, pattern3, pattern4 );
|
||||
FunctionParameterType parameterType4,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return registerPatterns(
|
||||
name,
|
||||
type,
|
||||
new FunctionParameterType[] {
|
||||
parameterType1,
|
||||
parameterType2,
|
||||
parameterType3,
|
||||
parameterType4
|
||||
},
|
||||
typeConfiguration,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
pattern3,
|
||||
pattern4
|
||||
);
|
||||
}
|
||||
|
||||
private MultipatternSqmFunctionDescriptor registerPatterns(
|
||||
String name,
|
||||
BasicType<?> type,
|
||||
FunctionParameterType[] parameterTypes,
|
||||
TypeConfiguration typeConfiguration,
|
||||
String... patterns) {
|
||||
SqmFunctionDescriptor[] descriptors =
|
||||
new SqmFunctionDescriptor[patterns.length];
|
||||
|
@ -383,7 +422,7 @@ public class SqmFunctionRegistry {
|
|||
}
|
||||
|
||||
MultipatternSqmFunctionDescriptor function =
|
||||
new MultipatternSqmFunctionDescriptor( name, descriptors, type, parameterTypes );
|
||||
new MultipatternSqmFunctionDescriptor( name, descriptors, type, typeConfiguration, parameterTypes );
|
||||
register( name, function );
|
||||
return function;
|
||||
}
|
||||
|
|
|
@ -1340,7 +1340,8 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
name,
|
||||
true,
|
||||
null,
|
||||
StandardFunctionReturnTypeResolvers.invariant( resultType )
|
||||
StandardFunctionReturnTypeResolvers.invariant( resultType ),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -402,18 +402,18 @@ public class SqmUtil {
|
|||
List<SqmParameter<?>> sqmParameters,
|
||||
SqmParameterMappingModelResolutionAccess mappingModelResolutionAccess,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
if ( binding.getType() != null ) {
|
||||
return binding.getType();
|
||||
}
|
||||
|
||||
if ( binding.getBindType() != null && binding.getBindType() instanceof Bindable ) {
|
||||
if ( binding.getBindType() instanceof Bindable ) {
|
||||
return (Bindable) binding.getBindType();
|
||||
}
|
||||
|
||||
if ( parameter.getHibernateType() != null && parameter.getHibernateType() instanceof Bindable ) {
|
||||
if ( parameter.getHibernateType() instanceof Bindable ) {
|
||||
return (Bindable) parameter.getHibernateType();
|
||||
}
|
||||
|
||||
if ( binding.getType() != null ) {
|
||||
return binding.getType();
|
||||
}
|
||||
|
||||
for ( int i = 0; i < sqmParameters.size(); i++ ) {
|
||||
final MappingModelExpressible<?> mappingModelType = mappingModelResolutionAccess
|
||||
.getResolvedMappingModelType( sqmParameters.get( i ) );
|
||||
|
@ -425,8 +425,7 @@ public class SqmUtil {
|
|||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
|
||||
// assume we have (or can create) a mapping for the parameter's Java type
|
||||
BasicType basicType = typeConfiguration.standardBasicTypeForJavaType( parameter.getParameterType() );
|
||||
return basicType;
|
||||
return typeConfiguration.standardBasicTypeForJavaType( parameter.getParameterType() );
|
||||
}
|
||||
|
||||
public static SqmStatement.ParameterResolutions resolveParameters(SqmStatement<?> statement) {
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -26,6 +26,7 @@ public class NamedFunctionDescriptorBuilder {
|
|||
|
||||
private ArgumentsValidator argumentsValidator;
|
||||
private FunctionReturnTypeResolver returnTypeResolver;
|
||||
private FunctionArgumentTypeResolver argumentTypeResolver;
|
||||
|
||||
private boolean useParenthesesWhenNoArgs = true;
|
||||
private String argumentListSignature;
|
||||
|
@ -47,6 +48,11 @@ public class NamedFunctionDescriptorBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public NamedFunctionDescriptorBuilder setArgumentTypeResolver(FunctionArgumentTypeResolver argumentTypeResolver) {
|
||||
this.argumentTypeResolver = argumentTypeResolver;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedFunctionDescriptorBuilder setArgumentCountBetween(int min, int max) {
|
||||
return setArgumentsValidator( StandardArgumentsValidators.between( min, max ) );
|
||||
}
|
||||
|
@ -71,6 +77,7 @@ public class NamedFunctionDescriptorBuilder {
|
|||
|
||||
public NamedFunctionDescriptorBuilder setParameterTypes(FunctionParameterType... types) {
|
||||
setArgumentsValidator( new ArgumentTypesValidator(argumentsValidator, types) );
|
||||
setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.invariant( types ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -99,6 +106,7 @@ public class NamedFunctionDescriptorBuilder {
|
|||
useParenthesesWhenNoArgs,
|
||||
argumentsValidator,
|
||||
returnTypeResolver,
|
||||
argumentTypeResolver,
|
||||
registrationKey,
|
||||
functionKind,
|
||||
argumentListSignature,
|
||||
|
|
|
@ -26,6 +26,7 @@ public class PatternFunctionDescriptorBuilder {
|
|||
|
||||
private ArgumentsValidator argumentsValidator;
|
||||
private FunctionReturnTypeResolver returnTypeResolver;
|
||||
private FunctionArgumentTypeResolver argumentTypeResolver;
|
||||
private SqlAstNodeRenderingMode argumentRenderingMode = SqlAstNodeRenderingMode.DEFAULT;
|
||||
|
||||
public PatternFunctionDescriptorBuilder(
|
||||
|
@ -44,8 +45,14 @@ public class PatternFunctionDescriptorBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public PatternFunctionDescriptorBuilder setArgumentTypeResolver(FunctionArgumentTypeResolver argumentTypeResolver) {
|
||||
this.argumentTypeResolver = argumentTypeResolver;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PatternFunctionDescriptorBuilder setParameterTypes(FunctionParameterType... types) {
|
||||
setArgumentsValidator( new ArgumentTypesValidator(argumentsValidator, types) );
|
||||
setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.invariant( types ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -62,7 +69,7 @@ public class PatternFunctionDescriptorBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public PatternFunctionDescriptorBuilder setInvariantType(BasicType invariantType) {
|
||||
public PatternFunctionDescriptorBuilder setInvariantType(BasicType<?> invariantType) {
|
||||
setReturnTypeResolver( StandardFunctionReturnTypeResolvers.invariant( invariantType ) );
|
||||
return this;
|
||||
}
|
||||
|
@ -86,6 +93,7 @@ public class PatternFunctionDescriptorBuilder {
|
|||
new PatternRenderer( pattern, argumentRenderingMode ),
|
||||
argumentsValidator,
|
||||
returnTypeResolver,
|
||||
argumentTypeResolver,
|
||||
registrationKey,
|
||||
functionKind,
|
||||
argumentListSignature
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ package org.hibernate.query.sqm.produce.function.internal;
|
|||
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
|
@ -189,8 +190,10 @@ public class PatternRenderer {
|
|||
if ( arg != null ) {
|
||||
sqlAppender.appendSql( chunks[i] );
|
||||
if ( caseWrapper && !( arg instanceof Distinct ) && !( arg instanceof Star ) ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
sqlAppender.appendSql( "case when " );
|
||||
filter.accept( translator );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
sqlAppender.appendSql( " then " );
|
||||
translator.render( arg, argumentRenderingMode );
|
||||
sqlAppender.appendSql( " else null end" );
|
||||
|
@ -209,8 +212,10 @@ public class PatternRenderer {
|
|||
}
|
||||
if ( arg != null ) {
|
||||
if ( caseWrapper && !( arg instanceof Distinct ) && !( arg instanceof Star ) ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
sqlAppender.appendSql( "case when " );
|
||||
filter.accept( translator );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
sqlAppender.appendSql( " then " );
|
||||
translator.render( arg, argumentRenderingMode );
|
||||
sqlAppender.appendSql( " else null end" );
|
||||
|
@ -226,6 +231,7 @@ public class PatternRenderer {
|
|||
}
|
||||
|
||||
if ( withinGroup != null && !withinGroup.isEmpty() ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
|
||||
sqlAppender.appendSql( " within group (order by" );
|
||||
translator.render( withinGroup.get( 0 ), argumentRenderingMode );
|
||||
for ( int i = 1; i < withinGroup.size(); i++ ) {
|
||||
|
@ -233,6 +239,7 @@ public class PatternRenderer {
|
|||
translator.render( withinGroup.get( 0 ), argumentRenderingMode );
|
||||
}
|
||||
sqlAppender.appendSql( ')' );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
|
||||
if ( fromFirst != null ) {
|
||||
|
@ -253,9 +260,11 @@ public class PatternRenderer {
|
|||
}
|
||||
|
||||
if ( filter != null && !caseWrapper ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WHERE );
|
||||
sqlAppender.appendSql( " filter (where " );
|
||||
filter.accept( translator );
|
||||
sqlAppender.appendSql( ')' );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.SqmStatement;
|
||||
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.SqmCteStatement;
|
||||
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 LoadQueryInfluencers loadQueryInfluencers;
|
||||
|
||||
private final Map<SqmParameter<?>, List<List<JdbcParameter>>> jdbcParamsBySqmParam = new IdentityHashMap<>();
|
||||
private final JdbcParameters jdbcParameters = new JdbcParametersImpl();
|
||||
private final DomainParameterXref domainParameterXref;
|
||||
private final QueryParameterBindings domainParameterBindings;
|
||||
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 SqmQueryPart<?> currentSqmQueryPart;
|
||||
private boolean containsCollectionFetches;
|
||||
private boolean trackSelectionsForGroup;
|
||||
|
||||
private final Map<String, PredicateCollector> collectionFilterPredicates = new HashMap<>();
|
||||
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 boolean inTypeInference;
|
||||
private Supplier<MappingModelExpressible<?>> functionImpliedResultTypeAccess;
|
||||
|
||||
private SqmByUnit appliedByUnit;
|
||||
private Expression adjustedTimestamp;
|
||||
|
@ -1573,8 +1578,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
return cteContainer;
|
||||
}
|
||||
|
||||
private boolean trackSelectionsForGroup;
|
||||
|
||||
@Override
|
||||
public QueryPart visitQueryPart(SqmQueryPart<?> queryPart) {
|
||||
return (QueryPart) super.visitQueryPart( queryPart );
|
||||
|
@ -4079,6 +4082,17 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
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
|
||||
|
||||
|
@ -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
|
||||
public Map<SqmParameter<?>, List<List<JdbcParameter>>> getJdbcParamsBySqmParam() {
|
||||
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 ) {
|
||||
return determineValueMapping( (SqmParameter<?>) sqmExpression );
|
||||
}
|
||||
|
@ -4562,16 +4574,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
final QueryParameterImplementor<?> queryParameter = domainParameterXref.getQueryParameter( sqmParameter );
|
||||
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();
|
||||
if ( paramType == null ) {
|
||||
paramType = queryParameter.getHibernateType();
|
||||
|
@ -4581,12 +4583,25 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
}
|
||||
|
||||
if ( paramType == null ) {
|
||||
final MappingModelExpressible<?> inferredValueMapping = getInferredValueMapping();
|
||||
if ( inferredValueMapping != null ) {
|
||||
return inferredValueMapping;
|
||||
}
|
||||
// Default to the Object type
|
||||
return basicType( Object.class );
|
||||
}
|
||||
else if ( paramType instanceof MappingModelExpressible<?> && paramType.getBindableJavaType() == Object.class ) {
|
||||
else if ( paramType instanceof MappingModelExpressible<?> ) {
|
||||
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() );
|
||||
|
||||
|
@ -4742,12 +4757,15 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
|
||||
@Override
|
||||
public Expression visitFunction(SqmFunction<?> sqmFunction) {
|
||||
final Supplier<MappingModelExpressible<?>> oldFunctionImpliedResultTypeAccess = functionImpliedResultTypeAccess;
|
||||
functionImpliedResultTypeAccess = inferrableTypeAccessStack.getCurrent();
|
||||
inferrableTypeAccessStack.push( () -> null );
|
||||
try {
|
||||
return sqmFunction.convertToSqlAst( this );
|
||||
}
|
||||
finally {
|
||||
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) {
|
||||
// inferrableTypeAccessStack.push(
|
||||
// () -> {
|
||||
// MappingModelExpressible<?> definedType = creationContext
|
||||
// .getDomainModel()
|
||||
// .resolveMappingExpressible(
|
||||
// expression.getNodeType(),
|
||||
// getFromClauseIndex()::findTableGroup
|
||||
// );
|
||||
// if ( definedType != null ) {
|
||||
// return definedType;
|
||||
// }
|
||||
// definedType = creationContext
|
||||
// .getDomainModel()
|
||||
// .lenientlyResolveMappingExpressible(
|
||||
// inferred.getNodeType(),
|
||||
// getFromClauseIndex()::findTableGroup
|
||||
// );
|
||||
// return definedType;
|
||||
// }
|
||||
// );
|
||||
//
|
||||
// try {
|
||||
// return (X) expression.accept( this );
|
||||
// }
|
||||
// finally {
|
||||
// inferrableTypeAccessStack.pop();
|
||||
// }
|
||||
// }
|
||||
@Override
|
||||
public Object visitWithInferredType(
|
||||
SqmVisitableNode node,
|
||||
Supplier<MappingModelExpressible<?>> inferredTypeAccess) {
|
||||
inferrableTypeAccessStack.push( inferredTypeAccess );
|
||||
try {
|
||||
return node.accept( this );
|
||||
}
|
||||
finally {
|
||||
inferrableTypeAccessStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitAny(SqmAny<?> sqmAny) {
|
||||
|
|
|
@ -7,10 +7,14 @@
|
|||
package org.hibernate.query.sqm.sql;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
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.tree.SqmVisitableNode;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
|
@ -80,6 +84,23 @@ public class FakeSqmToSqlAstConverter extends BaseSemanticQueryWalker implements
|
|||
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
|
||||
public List<Expression> expandSelfRenderingFunctionMultiValueParameter(SqmParameter<?> sqmParameter) {
|
||||
return null;
|
||||
|
|
|
@ -7,9 +7,13 @@
|
|||
package org.hibernate.query.sqm.sql;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.internal.util.collections.Stack;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressible;
|
||||
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.predicate.SqmPredicate;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
|
@ -28,6 +32,19 @@ public interface SqmToSqlAstConverter extends SemanticQueryWalker<Object>, SqlAs
|
|||
|
||||
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);
|
||||
|
||||
Predicate visitNestedTopLevelPredicate(SqmPredicate predicate);
|
||||
|
|
|
@ -52,6 +52,7 @@ public enum Clause {
|
|||
FETCH,
|
||||
FOR_UPDATE,
|
||||
OVER,
|
||||
WITHIN_GROUP,
|
||||
PARTITION,
|
||||
CALL,
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.sql.ast;
|
|||
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.internal.util.collections.Stack;
|
||||
import org.hibernate.query.spi.QueryOptions;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
|
@ -34,6 +35,8 @@ public interface SqlAstTranslator<T extends JdbcOperation> extends SqlAstWalker
|
|||
*/
|
||||
QueryPart getCurrentQueryPart();
|
||||
|
||||
Stack<Clause> getCurrentClauseStack();
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
|
@ -587,11 +587,13 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
return ( (ComparisonPredicate) predicate ).getLeftHandExpression();
|
||||
}
|
||||
|
||||
protected boolean inOverClause() {
|
||||
protected boolean inOverOrWithinGroupClause() {
|
||||
return clauseStack.findCurrentFirst(
|
||||
clause -> {
|
||||
if ( clause == Clause.OVER ) {
|
||||
return true;
|
||||
switch ( clause ) {
|
||||
case OVER:
|
||||
case WITHIN_GROUP:
|
||||
return true;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -611,6 +613,11 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
return queryPartStack.getCurrent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stack<Clause> getCurrentClauseStack() {
|
||||
return clauseStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T translate(JdbcParameterBindings jdbcParameterBindings, QueryOptions queryOptions) {
|
||||
try {
|
||||
|
@ -2208,7 +2215,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
emulateSortSpecificationNullPrecedence( sortExpression, nullPrecedence );
|
||||
}
|
||||
|
||||
if ( inOverClause() ) {
|
||||
if ( inOverOrWithinGroupClause() ) {
|
||||
resolveAliasedExpression( sortExpression ).accept( this );
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -62,7 +62,6 @@ public class CoalesceTest extends BaseCoreFunctionalTestCase {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SkipForDialect(jiraKey = "HHH-10463", value = PostgreSQLDialect.class)
|
||||
public void HHH_10463_NullInCoalesce() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
TypedQuery<Person> query = session.createQuery( "from Person p where p.name = coalesce(:name, p.name) ", Person.class );
|
||||
|
|
|
@ -54,7 +54,7 @@ public class SubqueryTest extends BaseSessionFactoryFunctionalTest {
|
|||
String name,
|
||||
ArgumentsValidator argumentsValidator,
|
||||
FunctionReturnTypeResolver returnTypeResolver) {
|
||||
super( name, argumentsValidator, returnTypeResolver );
|
||||
super( name, argumentsValidator, returnTypeResolver, null );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -54,7 +54,8 @@ public class OrderByFragmentFunction extends AbstractSqmFunctionDescriptor {
|
|||
super(
|
||||
FUNCTION_NAME,
|
||||
StandardArgumentsValidators.exactly( 2 ),
|
||||
StandardFunctionReturnTypeResolvers.useArgType( 1 )
|
||||
StandardFunctionReturnTypeResolvers.useArgType( 1 ),
|
||||
null
|
||||
);
|
||||
}
|
||||
@Override
|
||||
|
@ -174,9 +175,6 @@ public class OrderByFragmentFunction extends AbstractSqmFunctionDescriptor {
|
|||
|
||||
@Override
|
||||
public Expression convertToSqlAst(SqmToSqlAstConverter walker) {
|
||||
final ReturnableType<?> resultType = resolveResultType(
|
||||
walker.getCreationContext().getMappingMetamodel().getTypeConfiguration()
|
||||
);
|
||||
final String sqmAlias = ( (SqmLiteral<String>) getArguments().get( 0 ) ).getLiteralValue();
|
||||
final String attributeRole = ( (SqmLiteral<String>) getArguments().get( 1 ) ).getLiteralValue();
|
||||
final TableGroup tableGroup = ( (FromClauseIndex) walker.getFromClauseAccess() ).findTableGroup(
|
||||
|
|
Loading…
Reference in New Issue