7
7
package org .hibernate .query .sqm .produce .function ;
8
8
9
9
import java .lang .reflect .Type ;
10
- import java .sql .Types ;
11
10
import java .util .List ;
12
11
12
+ import org .hibernate .Internal ;
13
13
import org .hibernate .metamodel .MappingMetamodel ;
14
14
import org .hibernate .metamodel .mapping .JdbcMapping ;
15
15
import org .hibernate .metamodel .mapping .JdbcMappingContainer ;
26
26
import org .hibernate .type .BasicType ;
27
27
import org .hibernate .type .JavaObjectType ;
28
28
import org .hibernate .type .descriptor .java .JavaType ;
29
- import org .hibernate .type .descriptor .java .spi .JdbcTypeRecommendationException ;
30
29
import org .hibernate .type .descriptor .jdbc .JdbcType ;
31
- import org .hibernate .type .descriptor .jdbc .JdbcTypeIndicators ;
32
30
import org .hibernate .type .spi .TypeConfiguration ;
33
31
34
- import static org .hibernate .type .SqlTypes .BIT ;
35
- import static org .hibernate .type .SqlTypes .BOOLEAN ;
36
- import static org .hibernate .type .SqlTypes .SMALLINT ;
37
- import static org .hibernate .type .SqlTypes .TINYINT ;
38
- import static org .hibernate .type .SqlTypes .UUID ;
39
- import static org .hibernate .type .SqlTypes .hasDatePart ;
40
- import static org .hibernate .type .SqlTypes .hasTimePart ;
41
- import static org .hibernate .type .SqlTypes .isCharacterOrClobType ;
42
- import static org .hibernate .type .SqlTypes .isCharacterType ;
43
- import static org .hibernate .type .SqlTypes .isEnumType ;
44
- import static org .hibernate .type .SqlTypes .isIntegral ;
45
- import static org .hibernate .type .SqlTypes .isNumericType ;
46
- import static org .hibernate .type .SqlTypes .isSpatialType ;
47
- import static org .hibernate .type .SqlTypes .isTemporalType ;
32
+ import static org .hibernate .query .sqm .produce .function .FunctionParameterType .COMPARABLE ;
48
33
import static org .hibernate .type .descriptor .java .JavaTypeHelper .isUnknown ;
49
34
50
35
66
51
public class ArgumentTypesValidator implements ArgumentsValidator {
67
52
// a JDBC type code of an enum when we don't know if it's mapped STRING or ORDINAL
68
53
// this number has to be distinct from every code in SqlTypes!
69
- private static final int ENUM_UNKNOWN_JDBC_TYPE = -101977 ;
54
+ // private static final int ENUM_UNKNOWN_JDBC_TYPE = -101977;
70
55
71
56
final ArgumentsValidator delegate ;
72
57
private final FunctionParameterType [] types ;
@@ -93,13 +78,13 @@ public void validate(
93
78
delegate .validate ( arguments , functionName , typeConfiguration );
94
79
int count = 0 ;
95
80
for (SqmTypedNode <?> argument : arguments ) {
96
- JdbcTypeIndicators indicators = typeConfiguration .getCurrentBaseSqlTypeIndicators ();
81
+ // JdbcTypeIndicators indicators = typeConfiguration.getCurrentBaseSqlTypeIndicators();
97
82
SqmExpressible <?> nodeType = argument .getNodeType ();
98
83
FunctionParameterType type = count < types .length ? types [count ++] : types [types .length - 1 ];
99
84
if ( nodeType != null && type != FunctionParameterType .ANY ) {
100
85
JavaType <?> javaType = nodeType .getRelationalJavaType ();
101
86
if (javaType != null ) {
102
- checkArgumentType ( functionName , count , argument , indicators , type , javaType );
87
+ checkArgumentType ( functionName , count , argument , type , javaType );
103
88
}
104
89
switch (type ) {
105
90
case TEMPORAL_UNIT :
@@ -144,46 +129,44 @@ private void checkArgumentType(
144
129
String functionName ,
145
130
int count ,
146
131
SqmTypedNode <?> argument ,
147
- JdbcTypeIndicators indicators ,
148
132
FunctionParameterType type ,
149
133
JavaType <?> javaType ) {
150
134
if ( !isUnknown ( javaType ) ) {
151
135
DomainType <?> domainType = argument .getExpressible ().getSqmType ();
152
136
if ( domainType instanceof JdbcMapping ) {
153
- JdbcType jdbcType = (( JdbcMapping ) domainType ). getJdbcType () ;
137
+ JdbcMapping jdbcMapping = (JdbcMapping ) domainType ;
154
138
checkArgumentType (
155
139
count , functionName , type ,
156
- jdbcType .getDefaultSqlTypeCode (),
157
- jdbcType .getFriendlyName (),
140
+ jdbcMapping .getJdbcType (),
158
141
javaType .getJavaTypeClass ()
159
142
);
160
143
}
161
- else {
162
- //TODO: this branch is now probably obsolete and can be deleted!
163
- try {
164
- checkArgumentType (
165
- count , functionName , type ,
166
- getJdbcType ( indicators , javaType ),
167
- null ,
168
- javaType .getJavaTypeClass ()
169
- );
170
- }
171
- catch (JdbcTypeRecommendationException e ) {
172
- // it's a converter or something like that, and we will check it later
173
- }
174
- }
144
+ // else {
145
+ // //TODO: this branch is now probably obsolete and can be deleted!
146
+ // try {
147
+ // checkArgumentType(
148
+ // count, functionName, type,
149
+ // getJdbcType( indicators, javaType ),
150
+ // null,
151
+ // javaType.getJavaTypeClass()
152
+ // );
153
+ // }
154
+ // catch (JdbcTypeRecommendationException e) {
155
+ // // it's a converter or something like that, and we will check it later
156
+ // }
157
+ // }
175
158
}
176
159
}
177
160
178
- private int getJdbcType (JdbcTypeIndicators indicators , JavaType <?> javaType ) {
179
- if ( javaType .getJavaTypeClass ().isEnum () ) {
180
- // we can't tell if the enum is mapped STRING or ORDINAL
181
- return ENUM_UNKNOWN_JDBC_TYPE ;
182
- }
183
- else {
184
- return javaType .getRecommendedJdbcType ( indicators ).getDefaultSqlTypeCode ();
185
- }
186
- }
161
+ // private int getJdbcType(JdbcTypeIndicators indicators, JavaType<?> javaType) {
162
+ // if ( javaType.getJavaTypeClass().isEnum() ) {
163
+ // // we can't tell if the enum is mapped STRING or ORDINAL
164
+ // return ENUM_UNKNOWN_JDBC_TYPE;
165
+ // }
166
+ // else {
167
+ // return javaType.getRecommendedJdbcType( indicators ).getDefaultSqlTypeCode();
168
+ // }
169
+ // }
187
170
188
171
/**
189
172
* This is the final validation phase with the fully-typed SQL nodes. Note that these
@@ -232,8 +215,7 @@ private int validateArgument(int paramNumber, JdbcMappingContainer expressionTyp
232
215
paramNumber ,
233
216
functionName ,
234
217
type ,
235
- mapping .getJdbcType ().getDefaultSqlTypeCode (),
236
- mapping .getJdbcType ().getFriendlyName (),
218
+ mapping .getJdbcType (),
237
219
mapping .getJavaTypeDescriptor ().getJavaType ()
238
220
);
239
221
}
@@ -242,65 +224,49 @@ private int validateArgument(int paramNumber, JdbcMappingContainer expressionTyp
242
224
}
243
225
244
226
private static void checkArgumentType (
245
- int paramNumber , String functionName , FunctionParameterType type , int code , String sqlType , Type javaType ) {
246
- switch (type ) {
227
+ int paramNumber , String functionName , FunctionParameterType type , JdbcType jdbcType , Type javaType ) {
228
+ if ( !isCompatible ( type , jdbcType )
229
+ // as a special case, we consider a binary column
230
+ // comparable when it is mapped by a Java UUID
231
+ && !( type == COMPARABLE && isBinaryUuid ( jdbcType , javaType ) ) ) {
232
+ throwError ( type , javaType , jdbcType .getFriendlyName (), functionName , paramNumber );
233
+ }
234
+ }
235
+
236
+ private static boolean isBinaryUuid (JdbcType jdbcType , Type javaType ) {
237
+ return javaType == java .util .UUID .class
238
+ && jdbcType .isBinary ();
239
+ }
240
+
241
+ @ Internal
242
+ private static boolean isCompatible (FunctionParameterType type , JdbcType jdbcType ) {
243
+ switch ( type ) {
247
244
case COMPARABLE :
248
- if ( !isCharacterType (code ) && !isTemporalType (code ) && !isNumericType (code ) && !isEnumType ( code )
249
- // both Java and the database consider UUIDs
250
- // comparable, so go ahead and accept them
251
- && code != UUID
252
- // as a special case, we consider a binary column
253
- // comparable when it is mapped by a Java UUID
254
- && !( javaType == java .util .UUID .class && code == Types .BINARY ) ) {
255
- throwError (type , javaType , sqlType , functionName , paramNumber );
256
- }
257
- break ;
245
+ return jdbcType .isComparable ();
258
246
case STRING :
259
- if ( !isCharacterType (code ) && !isEnumType (code ) ) {
260
- throwError (type , javaType , sqlType , functionName , paramNumber );
261
- }
262
- break ;
247
+ return jdbcType .isStringLikeExcludingClob ();
263
248
case STRING_OR_CLOB :
264
- if ( !isCharacterOrClobType (code ) ) {
265
- throwError (type , javaType , sqlType , functionName , paramNumber );
266
- }
267
- break ;
249
+ return jdbcType .isString (); // should it be isStringLike()
268
250
case NUMERIC :
269
- if ( !isNumericType (code ) ) {
270
- throwError (type , javaType , sqlType , functionName , paramNumber );
271
- }
272
- break ;
251
+ return jdbcType .isNumber ();
273
252
case INTEGER :
274
- if ( !isIntegral (code ) ) {
275
- throwError (type , javaType , sqlType , functionName , paramNumber );
276
- }
277
- break ;
253
+ return jdbcType .isInteger ();
278
254
case BOOLEAN :
279
- // ugh, need to be careful here, need to accept all the
280
- // JDBC type codes that a Dialect might use for BOOLEAN
281
- if ( code != BOOLEAN && code != BIT && code != TINYINT && code != SMALLINT ) {
282
- throwError (type , javaType , sqlType , functionName , paramNumber );
283
- }
284
- break ;
255
+ return jdbcType .isBoolean ()
256
+ // some Dialects map Boolean to SMALLINT or TINYINT
257
+ // TODO: check with Dialect.getPreferredSqlTypeCodeForBoolean
258
+ || jdbcType .isSmallInteger ();
285
259
case TEMPORAL :
286
- if ( !isTemporalType (code ) ) {
287
- throwError (type , javaType , sqlType , functionName , paramNumber );
288
- }
289
- break ;
260
+ return jdbcType .isTemporal ();
290
261
case DATE :
291
- if ( !hasDatePart (code ) ) {
292
- throwError (type , javaType , sqlType , functionName , paramNumber );
293
- }
294
- break ;
262
+ return jdbcType .hasDatePart ();
295
263
case TIME :
296
- if ( !hasTimePart (code ) ) {
297
- throwError (type , javaType , sqlType , functionName , paramNumber );
298
- }
299
- break ;
264
+ return jdbcType .hasTimePart ();
300
265
case SPATIAL :
301
- if ( !isSpatialType ( code ) ) {
302
- throwError ( type , javaType , sqlType , functionName , paramNumber );
303
- }
266
+ return jdbcType .isSpatial ();
267
+ default :
268
+ // TODO: should we throw here?
269
+ return true ;
304
270
}
305
271
}
306
272
0 commit comments