Skip to content

Commit dfa9cd5

Browse files
committed
HHH-17637 improve an error message
1 parent 2b6bef6 commit dfa9cd5

File tree

1 file changed

+46
-25
lines changed

1 file changed

+46
-25
lines changed

hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/ArgumentTypesValidator.java

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.hibernate.type.JavaObjectType;
2828
import org.hibernate.type.descriptor.java.JavaType;
2929
import org.hibernate.type.descriptor.java.spi.JdbcTypeRecommendationException;
30+
import org.hibernate.type.descriptor.jdbc.JdbcType;
3031
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
3132
import org.hibernate.type.spi.TypeConfiguration;
3233

@@ -103,7 +104,7 @@ public void validate(
103104
switch (type) {
104105
case TEMPORAL_UNIT:
105106
if ( !(argument instanceof SqmExtractUnit) && !(argument instanceof SqmDurationUnit) ) {
106-
throwError(type, Object.class, functionName, count);
107+
throwError(type, Object.class, null, functionName, count);
107108
}
108109
break;
109110
// the following are not really necessary for the functions we have today
@@ -112,12 +113,12 @@ public void validate(
112113
// something crazy by the parser
113114
case TRIM_SPEC:
114115
if ( !(argument instanceof SqmTrimSpecification) ) {
115-
throwError(type, Object.class, functionName, count);
116+
throwError(type, Object.class, null, functionName, count);
116117
}
117118
break;
118119
case COLLATION:
119120
if ( !(argument instanceof SqmCollation) ) {
120-
throwError(type, Object.class, functionName, count);
121+
throwError(type, Object.class, null, functionName, count);
121122
}
122123
break;
123124
case NO_UNTYPED:
@@ -149,9 +150,11 @@ private void checkArgumentType(
149150
if ( !isUnknown( javaType ) ) {
150151
DomainType<?> domainType = argument.getExpressible().getSqmType();
151152
if ( domainType instanceof JdbcMapping ) {
153+
JdbcType jdbcType = ((JdbcMapping) domainType).getJdbcType();
152154
checkArgumentType(
153155
count, functionName, type,
154-
((JdbcMapping) domainType).getJdbcType().getDefaultSqlTypeCode(),
156+
jdbcType.getDefaultSqlTypeCode(),
157+
jdbcType.getFriendlyName(),
155158
javaType.getJavaTypeClass()
156159
);
157160
}
@@ -161,6 +164,7 @@ private void checkArgumentType(
161164
checkArgumentType(
162165
count, functionName, type,
163166
getJdbcType( indicators, javaType ),
167+
null,
164168
javaType.getJavaTypeClass()
165169
);
166170
}
@@ -229,14 +233,16 @@ private int validateArgument(int paramNumber, JdbcMappingContainer expressionTyp
229233
functionName,
230234
type,
231235
mapping.getJdbcType().getDefaultSqlTypeCode(),
236+
mapping.getJdbcType().getFriendlyName(),
232237
mapping.getJavaTypeDescriptor().getJavaType()
233238
);
234239
}
235240
}
236241
return paramNumber;
237242
}
238243

239-
private static void checkArgumentType(int paramNumber, String functionName, FunctionParameterType type, int code, Type javaType) {
244+
private static void checkArgumentType(
245+
int paramNumber, String functionName, FunctionParameterType type, int code, String sqlType, Type javaType) {
240246
switch (type) {
241247
case COMPARABLE:
242248
if ( !isCharacterType(code) && !isTemporalType(code) && !isNumericType(code) && !isEnumType( code )
@@ -246,68 +252,83 @@ private static void checkArgumentType(int paramNumber, String functionName, Func
246252
// as a special case, we consider a binary column
247253
// comparable when it is mapped by a Java UUID
248254
&& !( javaType == java.util.UUID.class && code == Types.BINARY ) ) {
249-
throwError(type, javaType, functionName, paramNumber);
255+
throwError(type, javaType, sqlType, functionName, paramNumber);
250256
}
251257
break;
252258
case STRING:
253259
if ( !isCharacterType(code) && !isEnumType(code) ) {
254-
throwError(type, javaType, functionName, paramNumber);
260+
throwError(type, javaType, sqlType, functionName, paramNumber);
255261
}
256262
break;
257263
case STRING_OR_CLOB:
258264
if ( !isCharacterOrClobType(code) ) {
259-
throwError(type, javaType, functionName, paramNumber);
265+
throwError(type, javaType, sqlType, functionName, paramNumber);
260266
}
261267
break;
262268
case NUMERIC:
263269
if ( !isNumericType(code) ) {
264-
throwError(type, javaType, functionName, paramNumber);
270+
throwError(type, javaType, sqlType, functionName, paramNumber);
265271
}
266272
break;
267273
case INTEGER:
268274
if ( !isIntegral(code) ) {
269-
throwError(type, javaType, functionName, paramNumber);
275+
throwError(type, javaType, sqlType, functionName, paramNumber);
270276
}
271277
break;
272278
case BOOLEAN:
273279
// ugh, need to be careful here, need to accept all the
274280
// JDBC type codes that a Dialect might use for BOOLEAN
275281
if ( code != BOOLEAN && code != BIT && code != TINYINT && code != SMALLINT ) {
276-
throwError(type, javaType, functionName, paramNumber);
282+
throwError(type, javaType, sqlType, functionName, paramNumber);
277283
}
278284
break;
279285
case TEMPORAL:
280286
if ( !isTemporalType(code) ) {
281-
throwError(type, javaType, functionName, paramNumber);
287+
throwError(type, javaType, sqlType, functionName, paramNumber);
282288
}
283289
break;
284290
case DATE:
285291
if ( !hasDatePart(code) ) {
286-
throwError(type, javaType, functionName, paramNumber);
292+
throwError(type, javaType, sqlType, functionName, paramNumber);
287293
}
288294
break;
289295
case TIME:
290296
if ( !hasTimePart(code) ) {
291-
throwError(type, javaType, functionName, paramNumber);
297+
throwError(type, javaType, sqlType, functionName, paramNumber);
292298
}
293299
break;
294300
case SPATIAL:
295301
if ( !isSpatialType( code ) ) {
296-
throwError( type, javaType, functionName, paramNumber );
302+
throwError( type, javaType, sqlType, functionName, paramNumber );
297303
}
298304
}
299305
}
300306

301-
private static void throwError(FunctionParameterType type, Type javaType, String functionName, int paramNumber) {
302-
throw new FunctionArgumentException(
303-
String.format(
304-
"Parameter %d of function '%s()' has type '%s', but argument is of type '%s'",
305-
paramNumber,
306-
functionName,
307-
type,
308-
javaType.getTypeName()
309-
)
310-
);
307+
private static void throwError(
308+
FunctionParameterType type, Type javaType, String sqlType, String functionName, int paramNumber) {
309+
if ( sqlType == null ) {
310+
throw new FunctionArgumentException(
311+
String.format(
312+
"Parameter %d of function '%s()' has type '%s', but argument is of type '%s'",
313+
paramNumber,
314+
functionName,
315+
type,
316+
javaType.getTypeName()
317+
)
318+
);
319+
}
320+
else {
321+
throw new FunctionArgumentException(
322+
String.format(
323+
"Parameter %d of function '%s()' has type '%s', but argument is of type '%s' mapped to '%s'",
324+
paramNumber,
325+
functionName,
326+
type,
327+
javaType.getTypeName(),
328+
sqlType
329+
)
330+
);
331+
}
311332
}
312333

313334
@Override

0 commit comments

Comments
 (0)