Skip to content

Commit 0afa3eb

Browse files
committed
improve error messages in SQLQueryParser
1 parent 520e27a commit 0afa3eb

File tree

1 file changed

+29
-24
lines changed

1 file changed

+29
-24
lines changed

hibernate-core/src/main/java/org/hibernate/query/sql/internal/SQLQueryParser.java

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -165,22 +165,21 @@ private void handleAliases(String token, StringBuilder result) {
165165
}
166166
else {
167167
final String aliasName = token.substring( 0, firstDot );
168+
final String propertyName = token.substring( firstDot + 1 );
168169
if ( context.isCollectionAlias( aliasName ) ) {
169170
// The current alias is referencing the collection to be eagerly fetched
170-
String propertyName = token.substring( firstDot + 1 );
171-
result.append( resolveCollectionProperties( aliasName, propertyName ) );
171+
result.append( resolveCollectionProperties( aliasName, propertyName, token ) );
172172
aliasesFound++;
173173
}
174174
else if ( context.isEntityAlias( aliasName ) ) {
175175
// it is a property reference {foo.bar}
176-
String propertyName = token.substring( firstDot + 1 );
177-
result.append( resolveProperties( aliasName, propertyName ) );
176+
result.append( resolveProperties( aliasName, propertyName, token ) );
178177
aliasesFound++;
179178
}
180179
else {
181180
// passing through anything we do not know
182181
// to support jdbc escape sequences HB-898
183-
result.append( '{' ).append(token).append( '}' );
182+
result.append( '{' ).append( token ).append( '}' );
184183
}
185184
}
186185
}
@@ -217,42 +216,48 @@ private void handlePlaceholder(String token, StringBuilder result) {
217216
}
218217
}
219218

220-
private String resolveCollectionProperties(
221-
String aliasName,
222-
String propertyName) {
223-
final Map<String, String[]> fieldResults = context.getPropertyResultsMap( aliasName );
224-
final CollectionPersister collectionPersister = context.getCollectionPersister( aliasName );
219+
private String resolveCollectionProperties(String aliasName, String propertyName, String token) {
220+
final var fieldResults = context.getPropertyResultsMap( aliasName );
221+
final var collectionPersister = context.getCollectionPersister( aliasName );
225222
final String collectionSuffix = context.getCollectionSuffix( aliasName );
226223
switch ( propertyName ) {
227224
case "*":
228225
if ( !fieldResults.isEmpty() ) {
229-
throw new QueryException( "Using return-property together with * syntax is not supported" );
226+
throw new QueryException(
227+
"Illegal interpolation '%s' ('%s' is a field alias)"
228+
.formatted( token, aliasName ),
229+
originalQueryString
230+
);
230231
}
231232
aliasesFound++;
232233
return collectionPersister.selectFragment( aliasName, collectionSuffix )
233-
+ ", " + resolveProperties( aliasName, propertyName );
234+
+ ", " + resolveProperties( aliasName, propertyName, token );
234235
case "element.*":
235-
return resolveProperties( aliasName, "*" );
236+
return resolveProperties( aliasName, "*", token );
236237
default:
237238
// Let return-properties override whatever the persister has for aliases.
238239
String[] columnAliases = fieldResults.get( propertyName );
239240
if ( columnAliases == null ) {
240241
columnAliases =
241242
collectionPersister.getCollectionPropertyColumnAliases( propertyName, collectionSuffix );
242243
}
243-
validate( aliasName, propertyName, columnAliases );
244+
validate( aliasName, propertyName, columnAliases, token );
244245
aliasesFound++;
245246
return columnAliases[0];
246247
}
247248
}
248249

249-
private String resolveProperties(String aliasName, String propertyName) {
250-
final Map<String, String[]> fieldResults = context.getPropertyResultsMap( aliasName );
251-
final EntityPersister persister = context.getEntityPersister( aliasName );
250+
private String resolveProperties(String aliasName, String propertyName, String token) {
251+
final var fieldResults = context.getPropertyResultsMap( aliasName );
252+
final var persister = context.getEntityPersister( aliasName );
252253
final String suffix = context.getEntitySuffix( aliasName );
253254
if ( "*".equals( propertyName ) ) {
254255
if ( !fieldResults.isEmpty() ) {
255-
throw new QueryException( "Using return-property together with * syntax is not supported" );
256+
throw new QueryException(
257+
"Illegal interpolation '%s' ('%s' is a field alias)"
258+
.formatted( token, aliasName ),
259+
originalQueryString
260+
);
256261
}
257262
aliasesFound++;
258263
return persister.selectFragment( aliasName, suffix ) ;
@@ -263,24 +268,24 @@ private String resolveProperties(String aliasName, String propertyName) {
263268
if ( columnAliases == null ) {
264269
columnAliases = persister.getSubclassPropertyColumnAliases( propertyName, suffix );
265270
}
266-
validate( aliasName, propertyName, columnAliases );
271+
validate( aliasName, propertyName, columnAliases, token );
267272
aliasesFound++;
268273
return columnAliases[0];
269274
}
270275
}
271276

272-
private void validate(String aliasName, String propertyName, String[] columnAliases) {
277+
private void validate(String aliasName, String propertyName, String[] columnAliases, String token) {
273278
if ( columnAliases == null || columnAliases.length == 0 ) {
274279
throw new QueryException(
275-
"No column name found for property [" + propertyName + "] for alias [" + aliasName + "]",
280+
"No column for interpolation '%s'"
281+
.formatted( token ),
276282
originalQueryString
277283
);
278284
}
279285
if ( columnAliases.length != 1 ) {
280-
// TODO: better error message since we actually support composites if names are explicitly listed
281286
throw new QueryException(
282-
"SQL queries only support properties mapped to a single column - property [" +
283-
propertyName + "] is mapped to " + columnAliases.length + " columns.",
287+
"Multiple columns for interpolation '%s' ('%s' is mapped to %s columns)"
288+
.formatted( token, propertyName, columnAliases.length ),
284289
originalQueryString
285290
);
286291
}

0 commit comments

Comments
 (0)