44 */
55package org .hibernate .dialect .function ;
66
7- import java .util .Arrays ;
87import java .util .List ;
98import java .util .Locale ;
109import java .util .function .Supplier ;
1110
11+ import org .hibernate .AssertionFailure ;
1212import org .hibernate .dialect .Dialect ;
1313import org .hibernate .metamodel .mapping .BasicValuedMapping ;
1414import org .hibernate .metamodel .mapping .JdbcMapping ;
1515import org .hibernate .metamodel .model .domain .DomainType ;
1616import org .hibernate .metamodel .model .domain .ReturnableType ;
1717import org .hibernate .type .BindingContext ;
18- import org .hibernate .query .sqm .SqmExpressible ;
1918import org .hibernate .query .sqm .function .AbstractSqmSelfRenderingFunctionDescriptor ;
2019import org .hibernate .query .sqm .function .FunctionKind ;
2120import org .hibernate .query .sqm .produce .function .ArgumentsValidator ;
3534import org .hibernate .sql .ast .tree .predicate .Predicate ;
3635import org .hibernate .type .BasicPluralType ;
3736import org .hibernate .type .BasicType ;
38- import org .hibernate .type .SqlTypes ;
3937import org .hibernate .type .StandardBasicTypes ;
40- import org .hibernate .type .descriptor .java .JavaType ;
4138import org .hibernate .type .descriptor .jdbc .ArrayJdbcType ;
4239import org .hibernate .type .descriptor .jdbc .JdbcType ;
4340import org .hibernate .type .descriptor .jdbc .ObjectJdbcType ;
4441import org .hibernate .type .spi .TypeConfiguration ;
4542
4643import org .checkerframework .checker .nullness .qual .Nullable ;
4744
45+ import static java .util .Arrays .asList ;
4846import static org .hibernate .query .sqm .produce .function .FunctionParameterType .NUMERIC ;
47+ import static org .hibernate .type .SqlTypes .isNumericType ;
4948
5049/**
5150 * @author Christian Beikov
@@ -90,15 +89,20 @@ public void render(
9089 Predicate filter ,
9190 ReturnableType <?> returnType ,
9291 SqlAstTranslator <?> translator ) {
93- final boolean caseWrapper = filter != null && !filterClauseSupported ( translator );
92+ final boolean caseWrapper =
93+ filter != null && !filterClauseSupported ( translator );
9494 sqlAppender .appendSql ( "avg(" );
9595 final Expression arg ;
96- if ( sqlAstArguments .get ( 0 ) instanceof Distinct ) {
96+ final var argNode = sqlAstArguments .get ( 0 );
97+ if ( argNode instanceof Distinct distinct ) {
9798 sqlAppender .appendSql ( "distinct " );
98- arg = ( (Distinct ) sqlAstArguments .get ( 0 ) ).getExpression ();
99+ arg = distinct .getExpression ();
100+ }
101+ else if ( argNode instanceof Expression expression ) {
102+ arg = expression ;
99103 }
100104 else {
101- arg = ( Expression ) sqlAstArguments . get ( 0 );
105+ throw new AssertionFailure ( "Unexpected argument type" );
102106 }
103107 if ( caseWrapper ) {
104108 translator .getCurrentClauseStack ().push ( Clause .WHERE );
@@ -128,7 +132,7 @@ private void renderArgument(SqlAppender sqlAppender, SqlAstTranslator<?> transla
128132 if ( sourceMapping .getJdbcType ().isInteger () ) {
129133 castFunction .render (
130134 sqlAppender ,
131- Arrays . asList ( realArg , new CastTarget ( doubleType ) ),
135+ asList ( realArg , new CastTarget ( doubleType ) ),
132136 doubleType ,
133137 translator
134138 );
@@ -163,49 +167,43 @@ public void validate(
163167 )
164168 );
165169 }
166- final SqmTypedNode <?> argument = arguments .get ( 0 );
167- final SqmExpressible <?> expressible = argument .getExpressible ();
168- final DomainType <?> domainType ;
169- if ( expressible != null && ( domainType = expressible .getSqmType () ) != null ) {
170- final JdbcType jdbcType = getJdbcType ( domainType , bindingContext .getTypeConfiguration () );
171- if ( !isNumeric ( jdbcType ) ) {
172- throw new FunctionArgumentException (
173- String .format (
174- "Parameter %d of function '%s()' has type '%s', but argument is of type '%s'" ,
175- 1 ,
176- functionName ,
177- NUMERIC ,
178- domainType .getTypeName ()
179- )
180- );
170+ final var expressible = arguments .get ( 0 ).getExpressible ();
171+ if ( expressible != null ) {
172+ final var domainType = expressible .getSqmType ();
173+ if ( domainType != null ) {
174+ final var jdbcType = getJdbcType ( domainType , bindingContext .getTypeConfiguration () );
175+ if ( !isNumeric ( jdbcType ) ) {
176+ throw new FunctionArgumentException (
177+ String .format (
178+ "Parameter %d of function '%s()' has type '%s', but argument is of type '%s'" ,
179+ 1 ,
180+ functionName ,
181+ NUMERIC ,
182+ domainType .getTypeName ()
183+ )
184+ );
185+ }
181186 }
182187 }
183188 }
184189
185190 private static boolean isNumeric (JdbcType jdbcType ) {
186191 final int sqlTypeCode = jdbcType .getDefaultSqlTypeCode ();
187- if ( SqlTypes .isNumericType ( sqlTypeCode ) ) {
188- return true ;
189- }
190- if ( jdbcType instanceof ArrayJdbcType arrayJdbcType ) {
191- return isNumeric ( arrayJdbcType .getElementJdbcType () );
192- }
193- return false ;
192+ return isNumericType ( sqlTypeCode )
193+ || jdbcType instanceof ArrayJdbcType arrayJdbcType
194+ && isNumeric ( arrayJdbcType .getElementJdbcType () );
194195 }
195196
196197 private static JdbcType getJdbcType (DomainType <?> domainType , TypeConfiguration typeConfiguration ) {
197198 if ( domainType instanceof JdbcMapping jdbcMapping ) {
198199 return jdbcMapping .getJdbcType ();
199200 }
200201 else {
201- final JavaType <?> javaType = domainType .getExpressibleJavaType ();
202- if ( javaType .getJavaTypeClass ().isEnum () ) {
203- // we can't tell if the enum is mapped STRING or ORDINAL
204- return ObjectJdbcType .INSTANCE ;
205- }
206- else {
207- return javaType .getRecommendedJdbcType ( typeConfiguration .getCurrentBaseSqlTypeIndicators () );
208- }
202+ final var javaType = domainType .getExpressibleJavaType ();
203+ return javaType .getJavaTypeClass ().isEnum ()
204+ // we can't tell if the enum is mapped STRING or ORDINAL
205+ ? ObjectJdbcType .INSTANCE
206+ : javaType .getRecommendedJdbcType ( typeConfiguration .getCurrentBaseSqlTypeIndicators () );
209207 }
210208 }
211209
@@ -220,23 +218,24 @@ public static class ReturnTypeResolver implements FunctionReturnTypeResolver {
220218 private final BasicType <Double > doubleType ;
221219
222220 public ReturnTypeResolver (TypeConfiguration typeConfiguration ) {
223- this . doubleType = typeConfiguration .getBasicTypeRegistry ().resolve ( StandardBasicTypes .DOUBLE );
221+ doubleType = typeConfiguration .getBasicTypeRegistry ().resolve ( StandardBasicTypes .DOUBLE );
224222 }
225223
226224 @ Override
227225 public BasicValuedMapping resolveFunctionReturnType (
228226 Supplier <BasicValuedMapping > impliedTypeAccess ,
229227 List <? extends SqlAstNode > arguments ) {
230- final BasicValuedMapping impliedType = impliedTypeAccess .get ();
228+ final var impliedType = impliedTypeAccess .get ();
231229 if ( impliedType != null ) {
232230 return impliedType ;
233231 }
234- Expression expression = (Expression ) arguments .get ( 0 );
235- final JdbcMapping jdbcMapping = expression .getExpressionType ().getSingleJdbcMapping ();
236- if ( jdbcMapping instanceof BasicPluralType <?, ?> ) {
237- return (BasicValuedMapping ) jdbcMapping ;
232+ else {
233+ var expression = (Expression ) arguments .get ( 0 );
234+ final var jdbcMapping = expression .getExpressionType ().getSingleJdbcMapping ();
235+ return jdbcMapping instanceof BasicPluralType <?, ?>
236+ ? (BasicValuedMapping ) jdbcMapping
237+ : doubleType ;
238238 }
239- return doubleType ;
240239 }
241240
242241 @ Override
@@ -245,9 +244,9 @@ public ReturnableType<?> resolveFunctionReturnType(
245244 @ Nullable SqmToSqlAstConverter converter ,
246245 List <? extends SqmTypedNode <?>> arguments ,
247246 TypeConfiguration typeConfiguration ) {
248- final SqmExpressible <?> expressible = arguments .get ( 0 ).getExpressible ();
249- final DomainType <?> domainType ;
250- if ( expressible != null && ( domainType = expressible .getSqmType () ) != null ) {
247+ final var expressible = arguments .get ( 0 ).getExpressible ();
248+ if ( expressible != null ) {
249+ final var domainType = expressible .getSqmType ();
251250 if ( domainType instanceof BasicPluralType <?, ?> ) {
252251 return (ReturnableType <?>) domainType ;
253252 }
0 commit comments