|
27 | 27 | import org.hibernate.query.derived.AnonymousTupleEntityValuedModelPart;
|
28 | 28 | import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
29 | 29 | import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
|
| 30 | +import org.hibernate.query.sqm.tree.domain.SqmPath; |
| 31 | +import org.hibernate.query.sqm.tree.expression.SqmExpression; |
| 32 | +import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation; |
| 33 | +import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiationArgument; |
| 34 | +import org.hibernate.query.sqm.tree.select.SqmQuerySpec; |
| 35 | +import org.hibernate.query.sqm.tree.select.SqmSelectableNode; |
| 36 | +import org.hibernate.query.sqm.tree.select.SqmSelection; |
30 | 37 | import org.hibernate.spi.NavigablePath;
|
| 38 | +import org.hibernate.sql.ast.Clause; |
31 | 39 | import org.hibernate.sql.ast.SqlAstWalker;
|
32 | 40 | import org.hibernate.sql.ast.spi.FromClauseAccess;
|
33 | 41 | import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
@@ -284,10 +292,28 @@ public static <T> EntityValuedPathInterpretation<T> from(
|
284 | 292 | EntityValuedModelPart mapping,
|
285 | 293 | EntityValuedModelPart treatedMapping,
|
286 | 294 | SqmToSqlAstConverter sqlAstCreationState) {
|
| 295 | + final boolean expandToAllColumns; |
| 296 | + final Clause currentClause = sqlAstCreationState.getCurrentClauseStack().getCurrent(); |
| 297 | + if ( currentClause == Clause.GROUP || currentClause == Clause.ORDER ) { |
| 298 | + final SqmQuerySpec<?> querySpec = (SqmQuerySpec<?>) sqlAstCreationState.getCurrentSqmQueryPart(); |
| 299 | + if ( currentClause == Clause.ORDER && !groupByClauseContains( navigablePath, querySpec ) ) { |
| 300 | + // We must ensure that the order by expression be expanded but only if the group by |
| 301 | + // contained the same expression, and that was expanded as well |
| 302 | + expandToAllColumns = false; |
| 303 | + } |
| 304 | + else { |
| 305 | + // When the table group is selected and the navigablePath is selected we need to expand |
| 306 | + // to all columns, as we also expand this to all columns in the select clause |
| 307 | + expandToAllColumns = isSelected( tableGroup, navigablePath, querySpec ); |
| 308 | + } |
| 309 | + } |
| 310 | + else { |
| 311 | + expandToAllColumns = false; |
| 312 | + } |
| 313 | + |
287 | 314 | final SqlExpressionResolver sqlExprResolver = sqlAstCreationState.getSqlExpressionResolver();
|
288 | 315 | final Expression sqlExpression;
|
289 |
| - |
290 |
| - if ( resultModelPart == null ) { |
| 316 | + if ( expandToAllColumns ) { |
291 | 317 | // Expand to all columns of the entity mapping type, as we already did for the selection
|
292 | 318 | final EntityMappingType entityMappingType = mapping.getEntityMappingType();
|
293 | 319 | final EntityIdentifierMapping identifierMapping = entityMappingType.getIdentifierMapping();
|
@@ -352,6 +378,47 @@ public static <T> EntityValuedPathInterpretation<T> from(
|
352 | 378 | );
|
353 | 379 | }
|
354 | 380 |
|
| 381 | + private static boolean isSelected(TableGroup tableGroup, NavigablePath path, SqmQuerySpec<?> sqmQuerySpec) { |
| 382 | + // If the table group is selected (initialized), check if the entity valued |
| 383 | + // navigable path or any child path appears in the select clause |
| 384 | + return tableGroup.isInitialized() && selectClauseContains( path, sqmQuerySpec ); |
| 385 | + } |
| 386 | + |
| 387 | + private static boolean selectClauseContains(NavigablePath path, SqmQuerySpec<?> sqmQuerySpec) { |
| 388 | + final List<SqmSelection<?>> selections = sqmQuerySpec.getSelectClause() == null |
| 389 | + ? Collections.emptyList() |
| 390 | + : sqmQuerySpec.getSelectClause().getSelections(); |
| 391 | + for ( SqmSelection<?> selection : selections ) { |
| 392 | + if ( selectableNodeContains( selection.getSelectableNode(), path ) ) { |
| 393 | + return true; |
| 394 | + } |
| 395 | + } |
| 396 | + return false; |
| 397 | + } |
| 398 | + |
| 399 | + private static boolean selectableNodeContains(SqmSelectableNode<?> selectableNode, NavigablePath path) { |
| 400 | + if ( selectableNode instanceof SqmPath && path.isParentOrEqual( ( (SqmPath<?>) selectableNode ).getNavigablePath() ) ) { |
| 401 | + return true; |
| 402 | + } |
| 403 | + else if ( selectableNode instanceof SqmDynamicInstantiation ) { |
| 404 | + for ( SqmDynamicInstantiationArgument<?> argument : ( (SqmDynamicInstantiation<?>) selectableNode ).getArguments() ) { |
| 405 | + if ( selectableNodeContains( argument.getSelectableNode(), path ) ) { |
| 406 | + return true; |
| 407 | + } |
| 408 | + } |
| 409 | + } |
| 410 | + return false; |
| 411 | + } |
| 412 | + |
| 413 | + private static boolean groupByClauseContains(NavigablePath path, SqmQuerySpec<?> sqmQuerySpec) { |
| 414 | + for ( SqmExpression<?> expression : sqmQuerySpec.getGroupByClauseExpressions() ) { |
| 415 | + if ( expression instanceof SqmPath && ( (SqmPath<?>) expression ).getNavigablePath() == path ) { |
| 416 | + return true; |
| 417 | + } |
| 418 | + } |
| 419 | + return false; |
| 420 | + } |
| 421 | + |
355 | 422 | private final Expression sqlExpression;
|
356 | 423 |
|
357 | 424 | public EntityValuedPathInterpretation(
|
|
0 commit comments