Skip to content

Commit fe631ec

Browse files
committed
HHH-19712 Rework select fragment generation to work with column selection deduplication
1 parent 2f50e98 commit fe631ec

File tree

1 file changed

+88
-81
lines changed

1 file changed

+88
-81
lines changed

hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java

Lines changed: 88 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1791,61 +1791,62 @@ public String selectFragment(String alias, String suffix) {
17911791
// Wrap expressions with aliases
17921792
final SelectClause selectClause = rootQuerySpec.getSelectClause();
17931793
final List<SqlSelection> sqlSelections = selectClause.getSqlSelections();
1794+
final Set<String> processedExpressions = new HashSet<>( sqlSelections.size() );
17941795
int i = 0;
1795-
int columnIndex = 0;
1796-
final String[] columnAliases = getSubclassColumnAliasClosure();
1797-
final int columnAliasesSize = columnAliases.length;
1798-
for ( String identifierAlias : identifierAliases ) {
1799-
sqlSelections.set(
1800-
i,
1801-
new SqlSelectionImpl(
1802-
i,
1803-
new AliasedExpression( sqlSelections.get( i ).getExpression(), identifierAlias + suffix )
1804-
)
1805-
);
1806-
if ( i < columnAliasesSize && columnAliases[i].equals( identifierAlias ) ) {
1807-
columnIndex++;
1796+
final int identifierSelectionSize = identifierMapping.getJdbcTypeCount();
1797+
for ( int j = 0; j < identifierSelectionSize; j++ ) {
1798+
final SelectableMapping selectableMapping = identifierMapping.getSelectable( j );
1799+
if ( processedExpressions.add( selectableMapping.getSelectionExpression() ) ) {
1800+
aliasSelection( sqlSelections, i, identifierAliases[j] + suffix );
1801+
i++;
18081802
}
1809-
i++;
18101803
}
18111804

1812-
if ( entityMetamodel.hasSubclasses() ) {
1813-
sqlSelections.set(
1814-
i,
1815-
new SqlSelectionImpl(
1816-
i,
1817-
new AliasedExpression( sqlSelections.get( i ).getExpression(), getDiscriminatorAlias() + suffix )
1818-
)
1819-
);
1820-
i++;
1805+
if ( hasSubclasses() ) {
1806+
assert discriminatorMapping.getJdbcTypeCount() == 1;
1807+
final SelectableMapping selectableMapping = discriminatorMapping.getSelectable( 0 );
1808+
if ( processedExpressions.add( selectableMapping.getSelectionExpression() ) ) {
1809+
aliasSelection( sqlSelections, i, getDiscriminatorAlias() + suffix );
1810+
i++;
1811+
}
18211812
}
18221813

18231814
if ( hasRowId() ) {
1824-
sqlSelections.set(
1825-
i,
1826-
new SqlSelectionImpl(
1827-
i,
1828-
new AliasedExpression( sqlSelections.get( i ).getExpression(), ROWID_ALIAS + suffix )
1829-
)
1830-
);
1831-
i++;
1815+
final SelectableMapping selectableMapping = rowIdMapping;
1816+
if ( processedExpressions.add( selectableMapping.getSelectionExpression() ) ) {
1817+
aliasSelection( sqlSelections, i, ROWID_ALIAS + suffix );
1818+
i++;
1819+
}
18321820
}
18331821

1822+
final String[] columnAliases = getSubclassColumnAliasClosure();
18341823
final String[] formulaAliases = getSubclassFormulaAliasClosure();
1824+
int columnIndex = 0;
18351825
int formulaIndex = 0;
1836-
for ( ; i < sqlSelections.size(); i++ ) {
1837-
final SqlSelection sqlSelection = sqlSelections.get( i );
1838-
final ColumnReference columnReference = (ColumnReference) sqlSelection.getExpression();
1839-
final String selectAlias = !columnReference.isColumnExpressionFormula()
1840-
? columnAliases[columnIndex++] + suffix
1841-
: formulaAliases[formulaIndex++] + suffix;
1842-
sqlSelections.set(
1843-
i,
1844-
new SqlSelectionImpl(
1845-
sqlSelection.getValuesArrayPosition(),
1846-
new AliasedExpression( sqlSelection.getExpression(), selectAlias )
1847-
)
1848-
);
1826+
final int size = getNumberOfFetchables();
1827+
// getSubclassColumnAliasClosure contains the _identifierMapper columns when it has an id class,
1828+
// which need to be skipped
1829+
if ( identifierMapping instanceof NonAggregatedIdentifierMapping
1830+
&& ( (NonAggregatedIdentifierMapping) identifierMapping ).getIdClassEmbeddable() != null ) {
1831+
columnIndex = identifierSelectionSize;
1832+
}
1833+
for ( int j = 0; j < size; j++ ) {
1834+
final AttributeMapping fetchable = getFetchable( j );
1835+
if ( !(fetchable instanceof PluralAttributeMapping)
1836+
&& !skipFetchable( fetchable, fetchable.getMappedFetchOptions().getTiming() )
1837+
&& fetchable.isSelectable() ) {
1838+
final int jdbcTypeCount = fetchable.getJdbcTypeCount();
1839+
for ( int k = 0; k < jdbcTypeCount; k++ ) {
1840+
final SelectableMapping selectableMapping = fetchable.getSelectable( k );
1841+
if ( processedExpressions.add( selectableMapping.getSelectionExpression() ) ) {
1842+
final String baseAlias = selectableMapping.isFormula()
1843+
? formulaAliases[formulaIndex++]
1844+
: columnAliases[columnIndex++];
1845+
aliasSelection( sqlSelections, i, baseAlias + suffix );
1846+
i++;
1847+
}
1848+
}
1849+
}
18491850
}
18501851

18511852
final String sql = getFactory().getJdbcServices()
@@ -1865,6 +1866,17 @@ public String selectFragment(String alias, String suffix) {
18651866
return expression;
18661867
}
18671868

1869+
private static void aliasSelection(
1870+
List<SqlSelection> sqlSelections,
1871+
int selectionIndex,
1872+
String alias) {
1873+
final Expression expression = sqlSelections.get( selectionIndex ).getExpression();
1874+
sqlSelections.set(
1875+
selectionIndex,
1876+
new SqlSelectionImpl( selectionIndex, new AliasedExpression( expression, alias ) )
1877+
);
1878+
}
1879+
18681880
private ImmutableFetchList fetchProcessor(FetchParent fetchParent, LoaderSqlAstCreationState creationState) {
18691881
final FetchableContainer fetchableContainer = fetchParent.getReferencedMappingContainer();
18701882
final int size = fetchableContainer.getNumberOfFetchables();
@@ -1874,51 +1886,46 @@ private ImmutableFetchList fetchProcessor(FetchParent fetchParent, LoaderSqlAstC
18741886
final Fetchable fetchable = fetchableContainer.getFetchable( i );
18751887
// Ignore plural attributes
18761888
if ( !( fetchable instanceof PluralAttributeMapping ) ) {
1877-
final FetchTiming fetchTiming;
1878-
if ( fetchable instanceof BasicValuedModelPart ) {
1879-
// Ignore lazy basic columns
1880-
fetchTiming = fetchable.getMappedFetchOptions().getTiming();
1881-
if ( fetchTiming == FetchTiming.DELAYED ) {
1882-
continue;
1883-
}
1884-
}
1885-
else if ( fetchable instanceof Association ) {
1886-
final Association association = (Association) fetchable;
1887-
// Ignore the fetchable if the FK is on the other side
1888-
if ( association.getSideNature() == ForeignKeyDescriptor.Nature.TARGET ) {
1889-
continue;
1889+
final FetchTiming fetchTiming = fetchable.getMappedFetchOptions().getTiming();
1890+
if ( !skipFetchable( fetchable, fetchTiming ) ) {
1891+
if ( fetchTiming == null ) {
1892+
throw new AssertionFailure( "fetchTiming was null" );
18901893
}
1891-
// Ensure the FK comes from the root table
1892-
if ( !getRootTableName().equals( association.getForeignKeyDescriptor().getKeyTable() ) ) {
1893-
continue;
1894+
if ( fetchable.isSelectable() ) {
1895+
final Fetch fetch = fetchParent.generateFetchableFetch(
1896+
fetchable,
1897+
fetchParent.resolveNavigablePath( fetchable ),
1898+
fetchTiming,
1899+
false,
1900+
null,
1901+
creationState
1902+
);
1903+
fetches.add( fetch );
18941904
}
1895-
fetchTiming = FetchTiming.DELAYED;
1896-
}
1897-
else {
1898-
fetchTiming = fetchable.getMappedFetchOptions().getTiming();
1899-
}
1900-
1901-
if ( fetchTiming == null ) {
1902-
throw new AssertionFailure("fetchTiming was null");
1903-
}
1904-
1905-
if ( fetchable.isSelectable() ) {
1906-
final Fetch fetch = fetchParent.generateFetchableFetch(
1907-
fetchable,
1908-
fetchParent.resolveNavigablePath( fetchable ),
1909-
fetchTiming,
1910-
true,
1911-
null,
1912-
creationState
1913-
);
1914-
fetches.add( fetch );
19151905
}
19161906
}
19171907
}
19181908

19191909
return fetches.build();
19201910
}
19211911

1912+
private boolean skipFetchable(Fetchable fetchable, FetchTiming fetchTiming) {
1913+
if ( fetchable.asBasicValuedModelPart() != null ) {
1914+
// Ignore lazy basic columns
1915+
return fetchTiming == FetchTiming.DELAYED;
1916+
}
1917+
else if ( fetchable instanceof Association ) {
1918+
final Association association = (Association) fetchable;
1919+
// Ignore the fetchable if the FK is on the other side
1920+
return association.getSideNature() == ForeignKeyDescriptor.Nature.TARGET
1921+
// Ensure the FK comes from the root table
1922+
|| !getRootTableName().equals( association.getForeignKeyDescriptor().getKeyTable() );
1923+
}
1924+
else {
1925+
return false;
1926+
}
1927+
}
1928+
19221929
/**
19231930
* @deprecated use {@link Fetchable#isSelectable()} instead.
19241931
*/
@@ -5907,7 +5914,7 @@ public Fetchable getKeyFetchable(int position) {
59075914
}
59085915

59095916
@Override
5910-
public Fetchable getFetchable(int position) {
5917+
public AttributeMapping getFetchable(int position) {
59115918
return getStaticFetchableList().get( position );
59125919
}
59135920

0 commit comments

Comments
 (0)