HHH-15929 Handle the possibility of different JdbcMappings for the same column

This commit is contained in:
Christian Beikov 2023-05-31 10:49:11 +02:00
parent 3e56e0c6af
commit 5fb312e558
44 changed files with 580 additions and 190 deletions

View File

@ -360,7 +360,7 @@ public class OracleLegacySqlAstTranslator<T extends JdbcOperation> extends Abstr
} }
final QuerySpec subquery = new QuerySpec( false, 1 ); final QuerySpec subquery = new QuerySpec( false, 1 );
for ( ColumnReference idColumnReference : idColumnReferences ) { for ( ColumnReference idColumnReference : idColumnReferences ) {
subquery.getSelectClause().addSqlSelection( new SqlSelectionImpl( 0, -1, idColumnReference ) ); subquery.getSelectClause().addSqlSelection( new SqlSelectionImpl( idColumnReference ) );
} }
subquery.getFromClause().addRoot( rootTableGroup ); subquery.getFromClause().addRoot( rootTableGroup );
subquery.applyPredicate( querySpec.getWhereClauseRestrictions() ); subquery.applyPredicate( querySpec.getWhereClauseRestrictions() );

View File

@ -308,7 +308,7 @@ public class OracleSqlAstTranslator<T extends JdbcOperation> extends SqlAstTrans
} }
final QuerySpec subquery = new QuerySpec( false, 1 ); final QuerySpec subquery = new QuerySpec( false, 1 );
for ( ColumnReference idColumnReference : idColumnReferences ) { for ( ColumnReference idColumnReference : idColumnReferences ) {
subquery.getSelectClause().addSqlSelection( new SqlSelectionImpl( 0, -1, idColumnReference ) ); subquery.getSelectClause().addSqlSelection( new SqlSelectionImpl( idColumnReference ) );
} }
subquery.getFromClause().addRoot( rootTableGroup ); subquery.getFromClause().addRoot( rootTableGroup );
subquery.applyPredicate( querySpec.getWhereClauseRestrictions() ); subquery.applyPredicate( querySpec.getWhereClauseRestrictions() );

View File

@ -147,7 +147,6 @@ public class AggregateWindowEmulationQueryTransformer implements QueryTransforme
columnNames.add( columnName ); columnNames.add( columnName );
selectClause.addSqlSelection( selectClause.addSqlSelection(
new ResolvedSqlSelection( new ResolvedSqlSelection(
i + 1,
i, i,
finalExpression, finalExpression,
(BasicType<Object>) mapping.getJdbcMapping() (BasicType<Object>) mapping.getJdbcMapping()
@ -193,7 +192,6 @@ public class AggregateWindowEmulationQueryTransformer implements QueryTransforme
); );
final int subValuesPosition = subSelectClause.getSqlSelections().size(); final int subValuesPosition = subSelectClause.getSqlSelections().size();
final SqlSelection subSelection = new ResolvedSqlSelection( final SqlSelection subSelection = new ResolvedSqlSelection(
subValuesPosition + 1,
subValuesPosition, subValuesPosition,
realExpression, realExpression,
(BasicType<Object>) jdbcMapping (BasicType<Object>) jdbcMapping
@ -254,7 +252,6 @@ public class AggregateWindowEmulationQueryTransformer implements QueryTransforme
); );
final int subValuesPosition = subSelectClause.getSqlSelections().size(); final int subValuesPosition = subSelectClause.getSqlSelections().size();
final SqlSelection subSelection = new ResolvedSqlSelection( final SqlSelection subSelection = new ResolvedSqlSelection(
subValuesPosition + 1,
subValuesPosition, subValuesPosition,
realExpression, realExpression,
(BasicType<Object>) jdbcMapping (BasicType<Object>) jdbcMapping
@ -312,7 +309,6 @@ public class AggregateWindowEmulationQueryTransformer implements QueryTransforme
); );
final int subValuesPosition = subSelectClause.getSqlSelections().size(); final int subValuesPosition = subSelectClause.getSqlSelections().size();
final SqlSelection subSelection = new ResolvedSqlSelection( final SqlSelection subSelection = new ResolvedSqlSelection(
subValuesPosition + 1,
subValuesPosition, subValuesPosition,
realExpression, realExpression,
(BasicType<Object>) jdbcMapping (BasicType<Object>) jdbcMapping
@ -352,7 +348,6 @@ public class AggregateWindowEmulationQueryTransformer implements QueryTransforme
columnNames.add( columnName ); columnNames.add( columnName );
subSelectClause.addSqlSelection( subSelectClause.addSqlSelection(
new ResolvedSqlSelection( new ResolvedSqlSelection(
oldValueIndex + 1,
oldValueIndex, oldValueIndex,
sortExpression, sortExpression,
(BasicType<Object>) mapping.getJdbcMapping() (BasicType<Object>) mapping.getJdbcMapping()

View File

@ -1186,7 +1186,6 @@ public class LoaderSelectBuilder {
); );
subQuery.getSelectClause().addSqlSelection( subQuery.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
valuesPosition + 1,
valuesPosition, valuesPosition,
expression expression
) )

View File

@ -6,7 +6,9 @@
*/ */
package org.hibernate.metamodel.mapping; package org.hibernate.metamodel.mapping;
import java.util.List;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.IntFunction;
/** /**
* Consumer used to visit selectable (column/formula) mappings * Consumer used to visit selectable (column/formula) mappings
@ -157,7 +159,7 @@ public interface SelectableConsumer {
* Very limited functionality in terms of the visited SelectableMappings * Very limited functionality in terms of the visited SelectableMappings
* will not have any defined JdbcMapping, etc * will not have any defined JdbcMapping, etc
*/ */
default void accept(String tableName, String[] columnNames) { default void accept(String tableName, String[] columnNames, IntFunction<JdbcMapping> jdbcMappings) {
class SelectableMappingIterator implements SelectableMapping { class SelectableMappingIterator implements SelectableMapping {
private int index; private int index;
@ -229,7 +231,7 @@ public interface SelectableConsumer {
@Override @Override
public JdbcMapping getJdbcMapping() { public JdbcMapping getJdbcMapping() {
return null; return jdbcMappings.apply( index );
} }
} }
for ( for (

View File

@ -69,7 +69,11 @@ public abstract class AbstractDomainPath implements DomainPath {
selection.getContainingTableExpression() selection.getContainingTableExpression()
); );
return creationState.getSqlExpressionResolver().resolveSqlExpression( return creationState.getSqlExpressionResolver().resolveSqlExpression(
createColumnReferenceKey( tableReference, selection.getSelectionExpression() ), createColumnReferenceKey(
tableReference,
selection.getSelectionExpression(),
selection.getJdbcMapping()
),
processingState -> new ColumnReference( processingState -> new ColumnReference(
tableReference, tableReference,
selection selection
@ -250,7 +254,11 @@ public abstract class AbstractDomainPath implements DomainPath {
SqlAstCreationState creationState) { SqlAstCreationState creationState) {
final TableReference tableReference = tableGroup.resolveTableReference( getNavigablePath(), selection.getContainingTableExpression() ); final TableReference tableReference = tableGroup.resolveTableReference( getNavigablePath(), selection.getContainingTableExpression() );
final Expression expression = creationState.getSqlExpressionResolver().resolveSqlExpression( final Expression expression = creationState.getSqlExpressionResolver().resolveSqlExpression(
createColumnReferenceKey( tableReference, selection.getSelectionExpression() ), createColumnReferenceKey(
tableReference,
selection.getSelectionExpression(),
selection.getJdbcMapping()
),
processingState -> new ColumnReference( processingState -> new ColumnReference(
tableReference, tableReference,
selection selection
@ -271,7 +279,6 @@ public abstract class AbstractDomainPath implements DomainPath {
if ( selectClause.isDistinct() && selectClauseDoesNotContainOrderExpression( expression, selectClause ) ) { if ( selectClause.isDistinct() && selectClauseDoesNotContainOrderExpression( expression, selectClause ) ) {
final int valuesArrayPosition = selectClause.getSqlSelections().size(); final int valuesArrayPosition = selectClause.getSqlSelections().size();
SqlSelection sqlSelection = new SqlSelectionImpl( SqlSelection sqlSelection = new SqlSelectionImpl(
valuesArrayPosition + 1,
valuesArrayPosition, valuesArrayPosition,
expression expression
); );

View File

@ -108,7 +108,11 @@ public class CaseStatementDiscriminatorMappingImpl extends AbstractDiscriminator
SqlAstCreationState creationState) { SqlAstCreationState creationState) {
final SqlExpressionResolver expressionResolver = creationState.getSqlExpressionResolver(); final SqlExpressionResolver expressionResolver = creationState.getSqlExpressionResolver();
return expressionResolver.resolveSqlExpression( return expressionResolver.resolveSqlExpression(
createColumnReferenceKey( tableGroup.getPrimaryTableReference(), getSelectionExpression() ), createColumnReferenceKey(
tableGroup.getPrimaryTableReference(),
getSelectionExpression(),
jdbcMappingToUse
),
sqlAstProcessingState -> createCaseSearchedExpression( tableGroup ) sqlAstProcessingState -> createCaseSearchedExpression( tableGroup )
); );
} }

View File

@ -21,6 +21,9 @@ import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableReference; import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.ast.tree.select.QuerySpec; import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.sql.ast.tree.select.SortSpecification; import org.hibernate.sql.ast.tree.select.SortSpecification;
import org.hibernate.type.NullType;
import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey;
/** /**
* Represents a column-reference used in an order-by fragment * Represents a column-reference used in an order-by fragment
@ -53,13 +56,10 @@ public class ColumnReference implements OrderingExpression, SequencePart {
TableGroup tableGroup, TableGroup tableGroup,
String modelPartName, String modelPartName,
SqlAstCreationState creationState) { SqlAstCreationState creationState) {
TableReference tableReference; final TableReference tableReference = getTableReference( tableGroup );
tableReference = getTableReference( tableGroup );
final SqlExpressionResolver sqlExpressionResolver = creationState.getSqlExpressionResolver(); final SqlExpressionResolver sqlExpressionResolver = creationState.getSqlExpressionResolver();
return sqlExpressionResolver.resolveSqlExpression( return sqlExpressionResolver.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( tableReference, columnExpression ), createColumnReferenceKey( tableReference, columnExpression, NullType.INSTANCE ),
sqlAstProcessingState -> new org.hibernate.sql.ast.tree.expression.ColumnReference( sqlAstProcessingState -> new org.hibernate.sql.ast.tree.expression.ColumnReference(
tableReference, tableReference,
columnExpression, columnExpression,

View File

@ -920,7 +920,6 @@ public abstract class AbstractCollectionPersister
i, i,
new SqlSelectionImpl( new SqlSelectionImpl(
i, i,
i + 1,
new AliasedExpression( sqlSelections.get( i ).getExpression(), keyAlias + columnSuffix ) new AliasedExpression( sqlSelections.get( i ).getExpression(), keyAlias + columnSuffix )
) )
); );
@ -933,7 +932,6 @@ public abstract class AbstractCollectionPersister
i, i,
new SqlSelectionImpl( new SqlSelectionImpl(
i, i,
i + 1,
new AliasedExpression( sqlSelections.get( i ).getExpression(), indexAlias + columnSuffix ) new AliasedExpression( sqlSelections.get( i ).getExpression(), indexAlias + columnSuffix )
) )
); );
@ -945,7 +943,6 @@ public abstract class AbstractCollectionPersister
i, i,
new SqlSelectionImpl( new SqlSelectionImpl(
i, i,
i + 1,
new AliasedExpression( sqlSelections.get( i ).getExpression(), identifierColumnAlias + columnSuffix ) new AliasedExpression( sqlSelections.get( i ).getExpression(), identifierColumnAlias + columnSuffix )
) )
); );
@ -958,7 +955,6 @@ public abstract class AbstractCollectionPersister
i, i,
new SqlSelectionImpl( new SqlSelectionImpl(
sqlSelection.getValuesArrayPosition(), sqlSelection.getValuesArrayPosition(),
sqlSelection.getJdbcResultSetIndex(),
new AliasedExpression( sqlSelection.getExpression(), elementColumnAliases[columnIndex] + columnSuffix ) new AliasedExpression( sqlSelection.getExpression(), elementColumnAliases[columnIndex] + columnSuffix )
) )
); );

View File

@ -1353,7 +1353,11 @@ public abstract class AbstractEntityPersister
(columnIndex, selection) -> { (columnIndex, selection) -> {
final String rootPkColumnName = pkColumnNames[ columnIndex ]; final String rootPkColumnName = pkColumnNames[ columnIndex ];
final Expression pkColumnExpression = creationState.getSqlExpressionResolver().resolveSqlExpression( final Expression pkColumnExpression = creationState.getSqlExpressionResolver().resolveSqlExpression(
createColumnReferenceKey( rootTableReference, rootPkColumnName ), createColumnReferenceKey(
rootTableReference,
rootPkColumnName,
selection.getJdbcMapping()
),
sqlAstProcessingState -> new ColumnReference( sqlAstProcessingState -> new ColumnReference(
rootTableReference.getIdentificationVariable(), rootTableReference.getIdentificationVariable(),
rootPkColumnName, rootPkColumnName,
@ -1365,7 +1369,11 @@ public abstract class AbstractEntityPersister
final String fkColumnName = fkColumnNames[ columnIndex ]; final String fkColumnName = fkColumnNames[ columnIndex ];
final Expression fkColumnExpression = creationState.getSqlExpressionResolver().resolveSqlExpression( final Expression fkColumnExpression = creationState.getSqlExpressionResolver().resolveSqlExpression(
createColumnReferenceKey( joinedTableReference, fkColumnName ), createColumnReferenceKey(
joinedTableReference,
fkColumnName,
selection.getJdbcMapping()
),
sqlAstProcessingState -> new ColumnReference( sqlAstProcessingState -> new ColumnReference(
joinedTableReference.getIdentificationVariable(), joinedTableReference.getIdentificationVariable(),
fkColumnName, fkColumnName,
@ -1738,7 +1746,6 @@ public abstract class AbstractEntityPersister
i, i,
new SqlSelectionImpl( new SqlSelectionImpl(
i, i,
i + 1,
new AliasedExpression( sqlSelections.get( i ).getExpression(), identifierAlias + suffix ) new AliasedExpression( sqlSelections.get( i ).getExpression(), identifierAlias + suffix )
) )
); );
@ -1750,7 +1757,6 @@ public abstract class AbstractEntityPersister
i, i,
new SqlSelectionImpl( new SqlSelectionImpl(
i, i,
i + 1,
new AliasedExpression( sqlSelections.get( i ).getExpression(), getDiscriminatorAlias() + suffix ) new AliasedExpression( sqlSelections.get( i ).getExpression(), getDiscriminatorAlias() + suffix )
) )
); );
@ -1762,7 +1768,6 @@ public abstract class AbstractEntityPersister
i, i,
new SqlSelectionImpl( new SqlSelectionImpl(
i, i,
i + 1,
new AliasedExpression( sqlSelections.get( i ).getExpression(), ROWID_ALIAS + suffix ) new AliasedExpression( sqlSelections.get( i ).getExpression(), ROWID_ALIAS + suffix )
) )
); );
@ -1783,7 +1788,6 @@ public abstract class AbstractEntityPersister
i, i,
new SqlSelectionImpl( new SqlSelectionImpl(
sqlSelection.getValuesArrayPosition(), sqlSelection.getValuesArrayPosition(),
sqlSelection.getJdbcResultSetIndex(),
new AliasedExpression( sqlSelection.getExpression(), selectAlias ) new AliasedExpression( sqlSelection.getExpression(), selectAlias )
) )
); );
@ -2990,14 +2994,16 @@ public abstract class AbstractEntityPersister
discriminatorExpression = getDiscriminatorFormulaTemplate(); discriminatorExpression = getDiscriminatorFormulaTemplate();
columnReferenceKey = createColumnReferenceKey( columnReferenceKey = createColumnReferenceKey(
tableGroup.getPrimaryTableReference(), tableGroup.getPrimaryTableReference(),
getDiscriminatorFormulaTemplate() getDiscriminatorFormulaTemplate(),
getDiscriminatorType()
); );
} }
else { else {
discriminatorExpression = getDiscriminatorColumnName(); discriminatorExpression = getDiscriminatorColumnName();
columnReferenceKey = createColumnReferenceKey( columnReferenceKey = createColumnReferenceKey(
tableGroup.getPrimaryTableReference(), tableGroup.getPrimaryTableReference(),
getDiscriminatorColumnName() getDiscriminatorColumnName(),
getDiscriminatorType()
); );
} }

View File

@ -1417,7 +1417,11 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
final int tablePosition = i; final int tablePosition = i;
consumer.consume( consumer.consume(
tableName, tableName,
() -> columnConsumer -> columnConsumer.accept( tableName, constraintOrderedKeyColumnNames[tablePosition] ) () -> columnConsumer -> columnConsumer.accept(
tableName,
constraintOrderedKeyColumnNames[tablePosition],
getIdentifierMapping()::getJdbcMapping
)
); );
} }
} }

View File

@ -759,7 +759,8 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
tableName, tableName,
() -> columnConsumer -> columnConsumer.accept( () -> columnConsumer -> columnConsumer.accept(
tableName, tableName,
constraintOrderedKeyColumnNames[tablePosition] constraintOrderedKeyColumnNames[tablePosition],
getIdentifierMapping()::getJdbcMapping
) )
); );
} }

View File

@ -436,7 +436,11 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
final int tablePosition = i; final int tablePosition = i;
consumer.consume( consumer.consume(
tableName, tableName,
() -> columnConsumer -> columnConsumer.accept( tableName, constraintOrderedKeyColumnNames[tablePosition] ) () -> columnConsumer -> columnConsumer.accept(
tableName,
constraintOrderedKeyColumnNames[tablePosition],
getIdentifierMapping()::getJdbcMapping
)
); );
} }
} }

View File

@ -358,7 +358,8 @@ public class AnonymousTupleEntityValuedModelPart
(ColumnReference) sqlExpressionResolver.resolveSqlExpression( (ColumnReference) sqlExpressionResolver.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( SqlExpressionResolver.createColumnReferenceKey(
tableReference, tableReference,
keyMappings.get( i ).getSelectionExpression() keyMappings.get( i ).getSelectionExpression(),
keyMappings.get( i ).getJdbcMapping()
), ),
state -> new ColumnReference( state -> new ColumnReference(
tableReference, tableReference,
@ -378,7 +379,8 @@ public class AnonymousTupleEntityValuedModelPart
sqlExpressionResolver.resolveSqlExpression( sqlExpressionResolver.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( SqlExpressionResolver.createColumnReferenceKey(
tableReference, tableReference,
targetMappings.get( i ).getSelectionExpression() targetMappings.get( i ).getSelectionExpression(),
targetMappings.get( i ).getJdbcMapping()
), ),
state -> new ColumnReference( state -> new ColumnReference(
tableReference, tableReference,

View File

@ -66,11 +66,6 @@ public class ResultSetMappingSqlSelection implements SqlSelection, Expression, S
return valuesArrayPosition; return valuesArrayPosition;
} }
@Override
public int getJdbcResultSetIndex() {
return valuesArrayPosition + 1;
}
@Override @Override
public Expression getExpression() { public Expression getExpression() {
return this; return this;
@ -81,6 +76,11 @@ public class ResultSetMappingSqlSelection implements SqlSelection, Expression, S
return valueMapping; return valueMapping;
} }
@Override
public boolean isVirtual() {
return false;
}
@Override @Override
public void accept(SqlAstWalker sqlAstWalker) { public void accept(SqlAstWalker sqlAstWalker) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();

View File

@ -91,7 +91,22 @@ public class SelfRenderingFunctionSqlAstExpression
return new SqlSelectionImpl( return new SqlSelectionImpl(
jdbcPosition, jdbcPosition,
valuesArrayPosition, valuesArrayPosition,
this this,
false
);
}
@Override
public SqlSelection createSqlSelection(
int jdbcPosition,
int valuesArrayPosition,
JavaType javaType,
boolean virtual,
TypeConfiguration typeConfiguration) {
return new SqlSelectionImpl(
jdbcPosition,
valuesArrayPosition,
this,
virtual
); );
} }

View File

@ -165,7 +165,7 @@ public class SimpleDeleteQueryPlan implements NonSelectQueryPlan {
sqmInterpretation.getSqlExpressionResolver(), sqmInterpretation.getSqlExpressionResolver(),
factory factory
); );
matchingIdSubQuery.getSelectClause().addSqlSelection( new SqlSelectionImpl( 1, 0, fkTargetColumnExpression ) ); matchingIdSubQuery.getSelectClause().addSqlSelection( new SqlSelectionImpl( 0, fkTargetColumnExpression ) );
matchingIdSubQuery.getFromClause().addRoot( matchingIdSubQuery.getFromClause().addRoot(
tableGroup tableGroup

View File

@ -169,7 +169,6 @@ public class MatchingIdSelectionHelper {
idSelectionQuery.getSelectClause().addSqlSelection( idSelectionQuery.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
position, position,
position + 1,
expression expression
) )
); );

View File

@ -174,7 +174,7 @@ public abstract class AbstractCteMutationHandler extends AbstractMutationHandler
( (SqlExpressible) count).getJdbcMapping() ( (SqlExpressible) count).getJdbcMapping()
) )
); );
querySpec.getSelectClause().addSqlSelection( new SqlSelectionImpl( 1, 0, count ) ); querySpec.getSelectClause().addSqlSelection( new SqlSelectionImpl( 0, count ) );
querySpec.getFromClause().addRoot( querySpec.getFromClause().addRoot(
new CteTableGroup( new CteTableGroup(
new NamedTableReference( new NamedTableReference(
@ -280,7 +280,6 @@ public abstract class AbstractCteMutationHandler extends AbstractMutationHandler
final CteColumn cteColumn = cteColumns.get( i ); final CteColumn cteColumn = cteColumns.get( i );
subQuerySelectClause.addSqlSelection( subQuerySelectClause.addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
i + 1,
i, i,
new ColumnReference( new ColumnReference(
idSelectTableReference, idSelectTableReference,
@ -295,7 +294,6 @@ public abstract class AbstractCteMutationHandler extends AbstractMutationHandler
fkModelPart.forEachSelectable( fkModelPart.forEachSelectable(
(selectionIndex, selectableMapping) -> subQuerySelectClause.addSqlSelection( (selectionIndex, selectableMapping) -> subQuerySelectClause.addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
selectionIndex + 1,
selectionIndex, selectionIndex,
new ColumnReference( new ColumnReference(
idSelectTableReference, idSelectTableReference,

View File

@ -282,7 +282,6 @@ public class CteInsertHandler implements InsertHandler {
if ( !assignsId && entityDescriptor.getGenerator().generatedOnExecution() ) { if ( !assignsId && entityDescriptor.getGenerator().generatedOnExecution() ) {
querySpec.getSelectClause().addSqlSelection( querySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
SqmInsertStrategyHelper.createRowNumberingExpression( SqmInsertStrategyHelper.createRowNumberingExpression(
querySpec, querySpec,
@ -312,7 +311,6 @@ public class CteInsertHandler implements InsertHandler {
columnNames.add( columnReference.getColumnExpression() ); columnNames.add( columnReference.getColumnExpression() );
querySpec.getSelectClause().addSqlSelection( querySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
columnReference.getQualifier().equals( valuesAlias ) columnReference.getQualifier().equals( valuesAlias )
? columnReference ? columnReference
@ -420,7 +418,6 @@ public class CteInsertHandler implements InsertHandler {
); );
rowsWithSequenceQuery.getSelectClause().addSqlSelection( rowsWithSequenceQuery.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
rowNumberColumnReference rowNumberColumnReference
) )
@ -431,7 +428,6 @@ public class CteInsertHandler implements InsertHandler {
); );
rowsWithSequenceQuery.getSelectClause().addSqlSelection( rowsWithSequenceQuery.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
2,
1, 1,
new SelfRenderingSqlFragmentExpression( fragment ) new SelfRenderingSqlFragmentExpression( fragment )
) )
@ -502,7 +498,6 @@ public class CteInsertHandler implements InsertHandler {
entityQuery.getFromClause().addRoot( baseTableGroup ); entityQuery.getFromClause().addRoot( baseTableGroup );
entityQuery.getSelectClause().addSqlSelection( entityQuery.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
new BinaryArithmeticExpression( new BinaryArithmeticExpression(
new ColumnReference( new ColumnReference(
@ -546,7 +541,6 @@ public class CteInsertHandler implements InsertHandler {
final CteColumn cteColumn = cteColumns.get( i ); final CteColumn cteColumn = cteColumns.get( i );
entityQuery.getSelectClause().addSqlSelection( entityQuery.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
i + 1,
i, i,
new ColumnReference( new ColumnReference(
"e", "e",
@ -622,7 +616,7 @@ public class CteInsertHandler implements InsertHandler {
( (SqlExpressible) count).getJdbcMapping() ( (SqlExpressible) count).getJdbcMapping()
) )
); );
querySpec.getSelectClause().addSqlSelection( new SqlSelectionImpl( 1, 0, count ) ); querySpec.getSelectClause().addSqlSelection( new SqlSelectionImpl( 0, count ) );
querySpec.getFromClause().addRoot( querySpec.getFromClause().addRoot(
new CteTableGroup( new CteTableGroup(
new NamedTableReference( new NamedTableReference(
@ -877,7 +871,6 @@ public class CteInsertHandler implements InsertHandler {
final CteColumn idCteColumn = cteColumns.get( 0 ); final CteColumn idCteColumn = cteColumns.get( 0 );
querySpec.getSelectClause().addSqlSelection( querySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
new ColumnReference( new ColumnReference(
"t", "t",
@ -893,7 +886,6 @@ public class CteInsertHandler implements InsertHandler {
final CteColumn cteColumn = cteColumns.get( j ); final CteColumn cteColumn = cteColumns.get( j );
querySpec.getSelectClause().addSqlSelection( querySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
new ColumnReference( new ColumnReference(
"e", "e",
@ -933,14 +925,12 @@ public class CteInsertHandler implements InsertHandler {
); );
finalResultQuery.getSelectClause().addSqlSelection( finalResultQuery.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
idColumnReference idColumnReference
) )
); );
finalResultQuery.getSelectClause().addSqlSelection( finalResultQuery.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
SqmInsertStrategyHelper.createRowNumberingExpression( SqmInsertStrategyHelper.createRowNumberingExpression(
querySpec, querySpec,
@ -987,7 +977,6 @@ public class CteInsertHandler implements InsertHandler {
); );
insertSelectSpec.getSelectClause().addSqlSelection( insertSelectSpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
new ColumnReference( new ColumnReference(
"e", "e",
@ -1021,7 +1010,6 @@ public class CteInsertHandler implements InsertHandler {
final ColumnReference columnReference = assignmentReferences.get( j ); final ColumnReference columnReference = assignmentReferences.get( j );
insertSelectSpec.getSelectClause().addSqlSelection( insertSelectSpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
new ColumnReference( new ColumnReference(
"e", "e",

View File

@ -203,8 +203,6 @@ public class CteUpdateHandler extends AbstractCteMutationHandler implements Upda
final QuerySpec existsQuerySpec = new QuerySpec( false ); final QuerySpec existsQuerySpec = new QuerySpec( false );
existsQuerySpec.getSelectClause().addSqlSelection( existsQuerySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
-1,
0,
new QueryLiteral<>( new QueryLiteral<>(
1, 1,
factory.getTypeConfiguration().getBasicTypeForJavaType( Integer.class ) factory.getTypeConfiguration().getBasicTypeForJavaType( Integer.class )
@ -243,8 +241,6 @@ public class CteUpdateHandler extends AbstractCteMutationHandler implements Upda
targetColumnReferences.addAll( assignment.getAssignable().getColumnReferences() ); targetColumnReferences.addAll( assignment.getAssignable().getColumnReferences() );
querySpec.getSelectClause().addSqlSelection( querySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
0,
-1,
assignment.getAssignedValue() assignment.getAssignedValue()
) )
); );

View File

@ -450,7 +450,7 @@ public class InlineUpdateHandler implements UpdateHandler {
) )
); );
querySpec.getSelectClause().addSqlSelection( querySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( 1, 0, valuesColumnReference ) new SqlSelectionImpl( 0, valuesColumnReference )
); );
} }
); );
@ -482,7 +482,7 @@ public class InlineUpdateHandler implements UpdateHandler {
) )
); );
querySpec.getSelectClause().addSqlSelection( querySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( 1, 0, valuesColumnReference ) new SqlSelectionImpl( 0, valuesColumnReference )
); );
} }
final ValuesTableGroup valuesTableGroup = new ValuesTableGroup( final ValuesTableGroup valuesTableGroup = new ValuesTableGroup(
@ -528,8 +528,6 @@ public class InlineUpdateHandler implements UpdateHandler {
targetColumnReferences.addAll( assignment.getAssignable().getColumnReferences() ); targetColumnReferences.addAll( assignment.getAssignable().getColumnReferences() );
querySpec.getSelectClause().addSqlSelection( querySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
0,
-1,
assignment.getAssignedValue() assignment.getAssignedValue()
) )
); );

View File

@ -91,15 +91,14 @@ public final class ExecuteWithTemporaryTableHelper {
matchingIdSelection.getFromClause().addRoot( mutatingTableGroup ); matchingIdSelection.getFromClause().addRoot( mutatingTableGroup );
mutatingEntityDescriptor.getIdentifierMapping().forEachSelectable( mutatingEntityDescriptor.getIdentifierMapping().forEachSelectable(
(jdbcPosition, selection) -> { (selectionIndex, selection) -> {
final TableReference tableReference = mutatingTableGroup.resolveTableReference( final TableReference tableReference = mutatingTableGroup.resolveTableReference(
mutatingTableGroup.getNavigablePath(), mutatingTableGroup.getNavigablePath(),
selection.getContainingTableExpression() selection.getContainingTableExpression()
); );
matchingIdSelection.getSelectClause().addSqlSelection( matchingIdSelection.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
jdbcPosition, selectionIndex,
jdbcPosition + 1,
sqmConverter.getSqlExpressionResolver().resolveSqlExpression( sqmConverter.getSqlExpressionResolver().resolveSqlExpression(
tableReference, tableReference,
selection selection
@ -114,7 +113,6 @@ public final class ExecuteWithTemporaryTableHelper {
matchingIdSelection.getSelectClause().addSqlSelection( matchingIdSelection.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
jdbcPosition, jdbcPosition,
jdbcPosition + 1,
new QueryLiteral<>( new QueryLiteral<>(
UUID.fromString( sessionUidAccess.apply( executionContext.getSession() ) ), UUID.fromString( sessionUidAccess.apply( executionContext.getSession() ) ),
(BasicValuedMapping) idTable.getSessionUidColumn().getJdbcMapping() (BasicValuedMapping) idTable.getSessionUidColumn().getJdbcMapping()
@ -222,7 +220,6 @@ public final class ExecuteWithTemporaryTableHelper {
if ( temporaryTableColumn != idTable.getSessionUidColumn() ) { if ( temporaryTableColumn != idTable.getSessionUidColumn() ) {
querySpec.getSelectClause().addSqlSelection( querySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
i + 1,
i, i,
new ColumnReference( new ColumnReference(
tableReference, tableReference,
@ -241,7 +238,6 @@ public final class ExecuteWithTemporaryTableHelper {
(i, selectableMapping) -> { (i, selectableMapping) -> {
querySpec.getSelectClause().addSqlSelection( querySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
i + 1,
i, i,
new ColumnReference( new ColumnReference(
tableReference, tableReference,

View File

@ -58,7 +58,6 @@ public final class ExecuteWithoutIdTableHelper {
final SqlSelection sqlSelection = new SqlSelectionImpl( final SqlSelection sqlSelection = new SqlSelectionImpl(
// irrelevant // irrelevant
0, 0,
0,
columnReference columnReference
); );
matchingIdSelect.getSelectClause().addSqlSelection( sqlSelection ); matchingIdSelect.getSelectClause().addSqlSelection( sqlSelection );

View File

@ -339,7 +339,6 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
for ( ColumnReference columnReference : assignable.getColumnReferences() ) { for ( ColumnReference columnReference : assignable.getColumnReferences() ) {
querySpec.getSelectClause().addSqlSelection( querySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
new ColumnReference( new ColumnReference(
updatingTableReference.getIdentificationVariable(), updatingTableReference.getIdentificationVariable(),
@ -369,7 +368,7 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
identifierMapping.getJdbcMapping() identifierMapping.getJdbcMapping()
); );
idSelectQuerySpec.getSelectClause() idSelectQuerySpec.getSelectClause()
.addSqlSelection( new SqlSelectionImpl( 1, 0, columnReference ) ); .addSqlSelection( new SqlSelectionImpl( 0, columnReference ) );
idSelectQuerySpec.addSortSpecification( idSelectQuerySpec.addSortSpecification(
new SortSpecification( new SortSpecification(
columnReference, columnReference,
@ -528,7 +527,6 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
); );
querySpec.getSelectClause().addSqlSelection( querySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
new ColumnReference( new ColumnReference(
updatingTableReference.getIdentificationVariable(), updatingTableReference.getIdentificationVariable(),
@ -689,7 +687,6 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
for ( ColumnReference columnReference : assignment.getAssignable().getColumnReferences() ) { for ( ColumnReference columnReference : assignment.getAssignable().getColumnReferences() ) {
querySpec.getSelectClause().addSqlSelection( querySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
new ColumnReference( new ColumnReference(
updatingTableReference.getIdentificationVariable(), updatingTableReference.getIdentificationVariable(),
@ -734,7 +731,6 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
); );
querySpec.getSelectClause().addSqlSelection( querySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
new ColumnReference( new ColumnReference(
updatingTableReference.getIdentificationVariable(), updatingTableReference.getIdentificationVariable(),

View File

@ -219,7 +219,6 @@ public class TableBasedInsertHandler implements InsertHandler {
targetPathColumns.add( new Assignment( columnReference, columnReference ) ); targetPathColumns.add( new Assignment( columnReference, columnReference ) );
querySpec.getSelectClause().addSqlSelection( querySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
SqmInsertStrategyHelper.createRowNumberingExpression( SqmInsertStrategyHelper.createRowNumberingExpression(
querySpec, querySpec,
@ -237,13 +236,12 @@ public class TableBasedInsertHandler implements InsertHandler {
null, null,
sessionUidColumn.getJdbcMapping() sessionUidColumn.getJdbcMapping()
); );
insertStatement.getTargetColumns().add( sessionUidColumnReference );
targetPathColumns.add( new Assignment( sessionUidColumnReference, sessionUidParameter ) );
querySpec.getSelectClause().addSqlSelection( new SqlSelectionImpl( querySpec.getSelectClause().addSqlSelection( new SqlSelectionImpl(
insertStatement.getTargetColumns().size(), insertStatement.getTargetColumns().size(),
insertStatement.getTargetColumns().size() - 1,
sessionUidParameter sessionUidParameter
) ); ) );
insertStatement.getTargetColumns().add( sessionUidColumnReference );
targetPathColumns.add( new Assignment( sessionUidColumnReference, sessionUidParameter ) );
} }
} }
); );

View File

@ -345,7 +345,7 @@ public class UpdateExecutionDelegate implements TableBasedUpdateHandler.Executio
for ( Assignment assignment : assignments ) { for ( Assignment assignment : assignments ) {
targetColumnReferences.addAll( assignment.getAssignable().getColumnReferences() ); targetColumnReferences.addAll( assignment.getAssignable().getColumnReferences() );
insertSourceSelectQuerySpec.getSelectClause().addSqlSelection( insertSourceSelectQuerySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( 0, -1, assignment.getAssignedValue() ) new SqlSelectionImpl( assignment.getAssignedValue() )
); );
} }
@ -380,8 +380,6 @@ public class UpdateExecutionDelegate implements TableBasedUpdateHandler.Executio
final QuerySpec existsSubQuerySpec = new QuerySpec( false ); final QuerySpec existsSubQuerySpec = new QuerySpec( false );
existsSubQuerySpec.getSelectClause().addSqlSelection( existsSubQuerySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
-1,
0,
new QueryLiteral<>( new QueryLiteral<>(
1, 1,
sessionFactory.getTypeConfiguration().getBasicTypeForJavaType( Integer.class ) sessionFactory.getTypeConfiguration().getBasicTypeForJavaType( Integer.class )

View File

@ -1477,14 +1477,14 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
if ( versionExpression != null ) { if ( versionExpression != null ) {
if ( versionSelection == null ) { if ( versionSelection == null ) {
// The position is irrelevant as this is only needed for insert // The position is irrelevant as this is only needed for insert
versionSelection = new SqlSelectionImpl( 1, 0, versionExpression ); versionSelection = new SqlSelectionImpl( 0, versionExpression );
} }
selectClause.addSqlSelection( versionSelection ); selectClause.addSqlSelection( versionSelection );
} }
if ( discriminatorExpression != null ) { if ( discriminatorExpression != null ) {
if ( discriminatorSelection == null ) { if ( discriminatorSelection == null ) {
// The position is irrelevant as this is only needed for insert // The position is irrelevant as this is only needed for insert
discriminatorSelection = new SqlSelectionImpl( 1, 0, discriminatorExpression ); discriminatorSelection = new SqlSelectionImpl( 0, discriminatorExpression );
} }
selectClause.addSqlSelection( discriminatorSelection ); selectClause.addSqlSelection( discriminatorSelection );
} }
@ -1504,7 +1504,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
return false; return false;
} }
identifierSelection = new SqlSelectionImpl( identifierSelection = new SqlSelectionImpl(
1,
0, 0,
SqmInsertStrategyHelper.createRowNumberingExpression( querySpec, sessionFactory ) SqmInsertStrategyHelper.createRowNumberingExpression( querySpec, sessionFactory )
); );
@ -1518,7 +1517,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
); );
// The position is irrelevant as this is only needed for insert // The position is irrelevant as this is only needed for insert
identifierSelection = new SqlSelectionImpl( identifierSelection = new SqlSelectionImpl(
1,
0, 0,
new SelfRenderingSqlFragmentExpression( fragment ) new SelfRenderingSqlFragmentExpression( fragment )
); );
@ -2368,7 +2366,8 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
new QueryLiteral<>( new QueryLiteral<>(
selection.getValuesArrayPosition(), selection.getValuesArrayPosition(),
basicType( Integer.class ) basicType( Integer.class )
) ),
false
) )
) )
); );
@ -4468,7 +4467,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
integerType, integerType,
integerType integerType
); );
subQuerySpec.getSelectClause().addSqlSelection( new SqlSelectionImpl( 1, 0, expression ) ); subQuerySpec.getSelectClause().addSqlSelection( new SqlSelectionImpl( 0, expression ) );
subQuerySpec.applyPredicate( subQuerySpec.applyPredicate(
pluralAttributeMapping.getKeyDescriptor().generateJoinPredicate( pluralAttributeMapping.getKeyDescriptor().generateJoinPredicate(
@ -4652,7 +4651,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
).getJdbcMapping(), ).getJdbcMapping(),
modelPart modelPart
); );
subQuerySpec.getSelectClause().addSqlSelection( new SqlSelectionImpl( 1, 0, expression ) ); subQuerySpec.getSelectClause().addSqlSelection( new SqlSelectionImpl( 0, expression ) );
NavigablePath parent = pluralPartPath.getPluralDomainPath().getNavigablePath().getParent(); NavigablePath parent = pluralPartPath.getPluralDomainPath().getNavigablePath().getParent();
subQuerySpec.applyPredicate( subQuerySpec.applyPredicate(
@ -4786,7 +4785,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
for ( int i = 0; i < subQueryColumns.size(); i++ ) { for ( int i = 0; i < subQueryColumns.size(); i++ ) {
subQuerySpec.getSelectClause().addSqlSelection( subQuerySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
i + 1,
i, i,
subQueryColumns.get( i ) subQueryColumns.get( i )
) )
@ -4828,7 +4826,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
subQuerySpec.getSelectClause().addSqlSelection( subQuerySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
expression expression
) )
@ -7441,7 +7438,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final JdbcLiteral<Integer> jdbcLiteral = new JdbcLiteral<>( 1, basicType( Integer.class ) ); final JdbcLiteral<Integer> jdbcLiteral = new JdbcLiteral<>( 1, basicType( Integer.class ) );
subQuerySpec.getSelectClause().addSqlSelection( subQuerySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( 1, 0, jdbcLiteral ) new SqlSelectionImpl( 0, jdbcLiteral )
); );
return new ExistsPredicate( subQuerySpec, !predicate.isNegated(), getBooleanType() ); return new ExistsPredicate( subQuerySpec, !predicate.isNegated(), getBooleanType() );

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.query.sqm.sql.internal; package org.hibernate.query.sqm.sql.internal;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
@ -109,6 +110,7 @@ public class SqlAstQueryPartProcessingStateImpl
// SqlExpressionResolver // SqlExpressionResolver
private Map<?, ?> sqlSelectionMap; private Map<?, ?> sqlSelectionMap;
private int nextJdbcPosition = 1;
@Override @Override
public SqlSelection resolveSqlSelection( public SqlSelection resolveSqlSelection(
@ -128,29 +130,21 @@ public class SqlAstQueryPartProcessingStateImpl
-1, -1,
nestingFetchParent.getReferencedMappingType().getSelectableIndex( selectableName ), nestingFetchParent.getReferencedMappingType().getSelectableIndex( selectableName ),
javaType, javaType,
true,
typeConfiguration typeConfiguration
); );
} }
final Map<Expression, SqlSelection> selectionMap; final Map<Expression, Object> selectionMap;
if ( deduplicateSelectionItems ) { if ( deduplicateSelectionItems ) {
final SqlSelection existing;
if ( sqlSelectionMap == null ) { if ( sqlSelectionMap == null ) {
sqlSelectionMap = new HashMap<>(); sqlSelectionMap = new HashMap<>();
existing = null;
}
else {
existing = (SqlSelection) sqlSelectionMap.get( expression );
}
if ( existing != null ) {
return existing;
} }
//noinspection unchecked //noinspection unchecked
selectionMap = (Map<Expression, SqlSelection>) sqlSelectionMap; selectionMap = (Map<Expression, Object>) sqlSelectionMap;
} }
else if ( fetchParent != null ) { else if ( fetchParent != null ) {
// De-duplicate selection items within the root of a fetch parent // De-duplicate selection items within the root of a fetch parent
final Map<FetchParent, Map<Expression, SqlSelection>> fetchParentSqlSelectionMap; final Map<FetchParent, Map<Expression, Object>> fetchParentSqlSelectionMap;
final FetchParent root = fetchParent.getRoot(); final FetchParent root = fetchParent.getRoot();
if ( sqlSelectionMap == null ) { if ( sqlSelectionMap == null ) {
sqlSelectionMap = fetchParentSqlSelectionMap = new HashMap<>(); sqlSelectionMap = fetchParentSqlSelectionMap = new HashMap<>();
@ -158,8 +152,8 @@ public class SqlAstQueryPartProcessingStateImpl
} }
else { else {
//noinspection unchecked //noinspection unchecked
fetchParentSqlSelectionMap = (Map<FetchParent, Map<Expression, SqlSelection>>) sqlSelectionMap; fetchParentSqlSelectionMap = (Map<FetchParent, Map<Expression, Object>>) sqlSelectionMap;
final Map<Expression, SqlSelection> map = fetchParentSqlSelectionMap.get( root ); final Map<Expression, Object> map = fetchParentSqlSelectionMap.get( root );
if ( map == null ) { if ( map == null ) {
fetchParentSqlSelectionMap.put( root, selectionMap = new HashMap<>() ); fetchParentSqlSelectionMap.put( root, selectionMap = new HashMap<>() );
} }
@ -167,31 +161,60 @@ public class SqlAstQueryPartProcessingStateImpl
selectionMap = map; selectionMap = map;
} }
} }
final SqlSelection sqlSelection = selectionMap.get( expression );
if ( sqlSelection != null ) {
return sqlSelection;
}
} }
else { else {
selectionMap = null; selectionMap = null;
} }
final int jdbcPosition;
final Object existingSelection;
if ( selectionMap != null ) {
existingSelection = selectionMap.get( expression );
if ( existingSelection != null ) {
if ( existingSelection instanceof SqlSelection ) {
final SqlSelection sqlSelection = (SqlSelection) existingSelection;
if ( sqlSelection.getExpressionType() == expression.getExpressionType() ) {
return sqlSelection;
}
jdbcPosition = sqlSelection.getJdbcResultSetIndex();
}
else {
final SqlSelection[] selections = (SqlSelection[]) existingSelection;
for ( SqlSelection sqlSelection : selections ) {
if ( sqlSelection.getExpressionType() == expression.getExpressionType() ) {
return sqlSelection;
}
}
jdbcPosition = selections[0].getJdbcResultSetIndex();
}
}
else {
jdbcPosition = nextJdbcPosition++;
}
}
else {
jdbcPosition = nextJdbcPosition++;
existingSelection = null;
}
final boolean virtual = existingSelection != null;
final SelectClause selectClause = ( (QuerySpec) queryPart ).getSelectClause(); final SelectClause selectClause = ( (QuerySpec) queryPart ).getSelectClause();
final int valuesArrayPosition = selectClause.getSqlSelections().size(); final int valuesArrayPosition = selectClause.getSqlSelections().size();
final SqlSelection sqlSelection; final SqlSelection sqlSelection;
if ( isTopLevel() ) { if ( isTopLevel() ) {
sqlSelection = expression.createDomainResultSqlSelection( sqlSelection = expression.createDomainResultSqlSelection(
valuesArrayPosition + 1, jdbcPosition,
valuesArrayPosition, valuesArrayPosition,
javaType, javaType,
virtual,
typeConfiguration typeConfiguration
); );
} }
else { else {
sqlSelection = expression.createSqlSelection( sqlSelection = expression.createSqlSelection(
valuesArrayPosition + 1, jdbcPosition,
valuesArrayPosition, valuesArrayPosition,
javaType, javaType,
virtual,
typeConfiguration typeConfiguration
); );
} }
@ -199,7 +222,23 @@ public class SqlAstQueryPartProcessingStateImpl
selectClause.addSqlSelection( sqlSelection ); selectClause.addSqlSelection( sqlSelection );
if ( selectionMap != null ) { if ( selectionMap != null ) {
selectionMap.put( expression, sqlSelection ); if ( virtual ) {
final SqlSelection[] selections;
if ( existingSelection instanceof SqlSelection ) {
selections = new SqlSelection[2];
selections[0] = (SqlSelection) existingSelection;
}
else {
final SqlSelection[] existingSelections = (SqlSelection[]) existingSelection;
selections = new SqlSelection[existingSelections.length + 1];
System.arraycopy( existingSelections, 0, selections, 0, existingSelections.length );
}
selections[selections.length - 1] = sqlSelection;
selectionMap.put( expression, selections );
}
else {
selectionMap.put( expression, sqlSelection );
}
} }
return sqlSelection; return sqlSelection;

View File

@ -2916,7 +2916,6 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
for ( int i = 0; i < sqlSelectionsSize; i++ ) { for ( int i = 0; i < sqlSelectionsSize; i++ ) {
syntheticSelectClause.addSqlSelection( syntheticSelectClause.addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
i + 1,
i, i,
new ColumnReference( new ColumnReference(
queryGroupAlias, queryGroupAlias,
@ -4590,6 +4589,9 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
int offset = 0; int offset = 0;
for ( int i = 0; i < size; i++ ) { for ( int i = 0; i < size; i++ ) {
final SqlSelection sqlSelection = sqlSelections.get( i ); final SqlSelection sqlSelection = sqlSelections.get( i );
if ( sqlSelection.isVirtual() ) {
continue;
}
if ( selectItemsToInline != null && selectItemsToInline.get( i ) ) { if ( selectItemsToInline != null && selectItemsToInline.get( i ) ) {
parameterRenderingMode = SqlAstNodeRenderingMode.INLINE_ALL_PARAMETERS; parameterRenderingMode = SqlAstNodeRenderingMode.INLINE_ALL_PARAMETERS;
} }
@ -4640,6 +4642,9 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
String separator = NO_SEPARATOR; String separator = NO_SEPARATOR;
for ( int i = 0; i < size; i++ ) { for ( int i = 0; i < size; i++ ) {
final SqlSelection sqlSelection = sqlSelections.get( i ); final SqlSelection sqlSelection = sqlSelections.get( i );
if ( sqlSelection.isVirtual() ) {
continue;
}
appendSql( separator ); appendSql( separator );
if ( selectItemsToInline != null && selectItemsToInline.get( i ) ) { if ( selectItemsToInline != null && selectItemsToInline.get( i ) ) {
parameterRenderingMode = SqlAstNodeRenderingMode.INLINE_ALL_PARAMETERS; parameterRenderingMode = SqlAstNodeRenderingMode.INLINE_ALL_PARAMETERS;
@ -5331,7 +5336,6 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
columnNames.add( "sort_col_" + i ); columnNames.add( "sort_col_" + i );
sqlSelections.add( sqlSelections.add(
new SqlSelectionImpl( new SqlSelectionImpl(
sqlSelections.size() + 1,
sqlSelections.size(), sqlSelections.size(),
sortSpecification.getSortExpression() sortSpecification.getSortExpression()
) )
@ -5645,7 +5649,6 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
for ( ColumnReference columnReference : columnReferences ) { for ( ColumnReference columnReference : columnReferences ) {
lhsReferencesQuery.getSelectClause().addSqlSelection( lhsReferencesQuery.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
columnReference columnReference
) )
@ -5695,7 +5698,6 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
final QuerySpec existsQuery = new QuerySpec( false, 1 ); final QuerySpec existsQuery = new QuerySpec( false, 1 );
existsQuery.getSelectClause().addSqlSelection( existsQuery.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
new QueryLiteral<>( 1, getIntegerType() ) new QueryLiteral<>( 1, getIntegerType() )
) )
@ -5748,7 +5750,6 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
existsQuery.setHavingClauseRestrictions( querySpec.getHavingClauseRestrictions() ); existsQuery.setHavingClauseRestrictions( querySpec.getHavingClauseRestrictions() );
existsQuery.getSelectClause().addSqlSelection( existsQuery.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
new QueryLiteral<>( 1, getIntegerType() ) new QueryLiteral<>( 1, getIntegerType() )
) )
@ -5785,7 +5786,6 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
countQuery.setHavingClauseRestrictions( querySpec.getHavingClauseRestrictions() ); countQuery.setHavingClauseRestrictions( querySpec.getHavingClauseRestrictions() );
countQuery.getSelectClause().addSqlSelection( countQuery.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1,
0, 0,
new SelfRenderingAggregateFunctionSqlAstExpression( new SelfRenderingAggregateFunctionSqlAstExpression(
"count", "count",

View File

@ -8,12 +8,14 @@ package org.hibernate.sql.ast.spi;
import java.util.function.Function; import java.util.function.Function;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.metamodel.mapping.SelectableMapping;
import org.hibernate.metamodel.mapping.SelectablePath; import org.hibernate.metamodel.mapping.SelectablePath;
import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.from.TableReference; import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.results.graph.FetchParent; import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.type.NullType;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
@ -42,41 +44,42 @@ public interface SqlExpressionResolver {
* *
* @see #resolveSqlExpression * @see #resolveSqlExpression
*/ */
static ColumnReferenceKey createColumnReferenceKey(String tableExpression, String columnExpression) { static ColumnReferenceKey createColumnReferenceKey(String tableExpression, String columnExpression, JdbcMapping jdbcMapping) {
return new ColumnReferenceKey(tableExpression, new SelectablePath( columnExpression ) ); return createColumnReferenceKey( tableExpression, new SelectablePath( columnExpression ), jdbcMapping );
} }
/** /**
* Helper for generating an expression key for a column reference. * Helper for generating an expression key for a column reference.
* *
* @see #resolveSqlExpression * @see #resolveSqlExpression
*/ */
static ColumnReferenceKey createColumnReferenceKey(TableReference tableReference, String columnExpression) { static ColumnReferenceKey createColumnReferenceKey(TableReference tableReference, String columnExpression, JdbcMapping jdbcMapping) {
return createColumnReferenceKey( tableReference, new SelectablePath( columnExpression ) ); return createColumnReferenceKey( tableReference, new SelectablePath( columnExpression ), jdbcMapping );
} }
static ColumnReferenceKey createColumnReferenceKey(TableReference tableReference, SelectablePath selectablePath) { static ColumnReferenceKey createColumnReferenceKey(TableReference tableReference, SelectablePath selectablePath, JdbcMapping jdbcMapping) {
assert tableReference != null : "tableReference expected to be non-null"; assert tableReference != null : "tableReference expected to be non-null";
assert selectablePath != null : "selectablePath expected to be non-null"; assert selectablePath != null : "selectablePath expected to be non-null";
assert tableReference.getIdentificationVariable() != null : "tableReference#identificationVariable expected to be non-null"; assert tableReference.getIdentificationVariable() != null : "tableReference#identificationVariable expected to be non-null";
final String qualifier = tableReference.getIdentificationVariable(); final String qualifier = tableReference.getIdentificationVariable();
return createColumnReferenceKey( qualifier, selectablePath ); return createColumnReferenceKey( qualifier, selectablePath, jdbcMapping );
} }
static ColumnReferenceKey createColumnReferenceKey(String qualifier, SelectablePath selectablePath) { static ColumnReferenceKey createColumnReferenceKey(String qualifier, SelectablePath selectablePath, JdbcMapping jdbcMapping) {
assert qualifier != null : "qualifier expected to be non-null"; assert qualifier != null : "qualifier expected to be non-null";
assert selectablePath != null : "selectablePath expected to be non-null"; assert selectablePath != null : "selectablePath expected to be non-null";
return new ColumnReferenceKey( qualifier, selectablePath ); assert jdbcMapping != null : "jdbcMapping expected to be non-null";
return new ColumnReferenceKey( qualifier, selectablePath, jdbcMapping );
} }
static ColumnReferenceKey createColumnReferenceKey(String columnExpression) { static ColumnReferenceKey createColumnReferenceKey(String columnExpression) {
assert columnExpression != null : "columnExpression expected to be non-null"; assert columnExpression != null : "columnExpression expected to be non-null";
return new ColumnReferenceKey( "", new SelectablePath( columnExpression ) ); return createColumnReferenceKey( "", new SelectablePath( columnExpression ), NullType.INSTANCE );
} }
/** /**
* Convenience form for creating a key from table expression and SelectableMapping * Convenience form for creating a key from table expression and SelectableMapping
*/ */
static ColumnReferenceKey createColumnReferenceKey(String tableExpression, SelectableMapping selectable) { static ColumnReferenceKey createColumnReferenceKey(String tableExpression, SelectableMapping selectable) {
return createColumnReferenceKey( tableExpression, selectable.getSelectablePath() ); return createColumnReferenceKey( tableExpression, selectable.getSelectablePath(), selectable.getJdbcMapping() );
} }
/** /**
@ -85,7 +88,7 @@ public interface SqlExpressionResolver {
static ColumnReferenceKey createColumnReferenceKey(TableReference tableReference, SelectableMapping selectable) { static ColumnReferenceKey createColumnReferenceKey(TableReference tableReference, SelectableMapping selectable) {
assert tableReference.containsAffectedTableName( selectable.getContainingTableExpression() ) assert tableReference.containsAffectedTableName( selectable.getContainingTableExpression() )
: String.format( ROOT, "Expecting tables to match between TableReference (%s) and SelectableMapping (%s)", tableReference.getTableId(), selectable.getContainingTableExpression() ); : String.format( ROOT, "Expecting tables to match between TableReference (%s) and SelectableMapping (%s)", tableReference.getTableId(), selectable.getContainingTableExpression() );
return createColumnReferenceKey( tableReference, selectable.getSelectablePath() ); return createColumnReferenceKey( tableReference, selectable.getSelectablePath(), selectable.getJdbcMapping() );
} }
default Expression resolveSqlExpression(TableReference tableReference, SelectableMapping selectableMapping) { default Expression resolveSqlExpression(TableReference tableReference, SelectableMapping selectableMapping) {
@ -117,10 +120,12 @@ public interface SqlExpressionResolver {
final class ColumnReferenceKey { final class ColumnReferenceKey {
private final String tableQualifier; private final String tableQualifier;
private final SelectablePath selectablePath; private final SelectablePath selectablePath;
private final JdbcMapping jdbcMapping;
public ColumnReferenceKey(String tableQualifier, SelectablePath selectablePath) { public ColumnReferenceKey(String tableQualifier, SelectablePath selectablePath, JdbcMapping jdbcMapping) {
this.tableQualifier = tableQualifier; this.tableQualifier = tableQualifier;
this.selectablePath = selectablePath; this.selectablePath = selectablePath;
this.jdbcMapping = jdbcMapping;
} }
@Override @Override
@ -132,18 +137,17 @@ public interface SqlExpressionResolver {
return false; return false;
} }
ColumnReferenceKey that = (ColumnReferenceKey) o; final ColumnReferenceKey that = (ColumnReferenceKey) o;
return tableQualifier.equals( that.tableQualifier )
if ( !tableQualifier.equals( that.tableQualifier ) ) { && selectablePath.equals( that.selectablePath )
return false; && jdbcMapping.equals( that.jdbcMapping );
}
return selectablePath.equals( that.selectablePath );
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = tableQualifier.hashCode(); int result = tableQualifier.hashCode();
result = 31 * result + selectablePath.hashCode(); result = 31 * result + selectablePath.hashCode();
result = 31 * result + jdbcMapping.hashCode();
return result; return result;
} }
} }

View File

@ -56,6 +56,12 @@ public interface SqlSelection extends SqlAstNode {
*/ */
JdbcMappingContainer getExpressionType(); JdbcMappingContainer getExpressionType();
/**
* Whether this is a virtual or a real selection item.
* Virtual selection items are not rendered into the SQL select clause.
*/
boolean isVirtual();
void accept(SqlAstWalker sqlAstWalker); void accept(SqlAstWalker sqlAstWalker);
SqlSelection resolve(JdbcValuesMetadata jdbcResultsMetadata, SessionFactoryImplementor sessionFactory); SqlSelection resolve(JdbcValuesMetadata jdbcResultsMetadata, SessionFactoryImplementor sessionFactory);

View File

@ -21,10 +21,28 @@ public interface SqlSelectionProducer {
* @param valuesArrayPosition The position in our {@linkplain RowProcessingState#getJdbcValue(SqlSelection) "current JDBC values array"} * @param valuesArrayPosition The position in our {@linkplain RowProcessingState#getJdbcValue(SqlSelection) "current JDBC values array"}
* @param javaType The descriptor for the Java type to read the value as * @param javaType The descriptor for the Java type to read the value as
* @param typeConfiguration The associated TypeConfiguration * @param typeConfiguration The associated TypeConfiguration
* @deprecated Use {@link #createSqlSelection(int, int, JavaType, boolean, TypeConfiguration)} instead
*/ */
@Deprecated(forRemoval = true)
SqlSelection createSqlSelection( SqlSelection createSqlSelection(
int jdbcPosition, int jdbcPosition,
int valuesArrayPosition, int valuesArrayPosition,
JavaType javaType, JavaType javaType,
TypeConfiguration typeConfiguration); TypeConfiguration typeConfiguration);
/**
* Create a SqlSelection for the given JDBC ResultSet position
*
* @param jdbcPosition The index position used to read values from JDBC
* @param valuesArrayPosition The position in our {@linkplain RowProcessingState#getJdbcValue(SqlSelection) "current JDBC values array"}
* @param javaType The descriptor for the Java type to read the value as
* @param virtual Whether the select is virtual or real. See {@link SqlSelection#isVirtual()}
* @param typeConfiguration The associated TypeConfiguration
*/
SqlSelection createSqlSelection(
int jdbcPosition,
int valuesArrayPosition,
JavaType javaType,
boolean virtual,
TypeConfiguration typeConfiguration);
} }

View File

@ -39,14 +39,41 @@ public interface Expression extends SqlAstNode, SqlSelectionProducer {
jdbcPosition, jdbcPosition,
valuesArrayPosition, valuesArrayPosition,
javaType, javaType,
this this,
false
); );
} }
@Override
default SqlSelection createSqlSelection(
int jdbcPosition,
int valuesArrayPosition,
JavaType javaType,
boolean virtual,
TypeConfiguration typeConfiguration) {
return new SqlSelectionImpl(
jdbcPosition,
valuesArrayPosition,
javaType,
this,
virtual
);
}
@Deprecated(forRemoval = true)
default SqlSelection createDomainResultSqlSelection(
int jdbcPosition,
int valuesArrayPosition,
JavaType javaType,
TypeConfiguration typeConfiguration) {
return createDomainResultSqlSelection( jdbcPosition, valuesArrayPosition, javaType, false, typeConfiguration );
}
default SqlSelection createDomainResultSqlSelection( default SqlSelection createDomainResultSqlSelection(
int jdbcPosition, int jdbcPosition,
int valuesArrayPosition, int valuesArrayPosition,
JavaType javaType, JavaType javaType,
boolean virtual,
TypeConfiguration typeConfiguration) { TypeConfiguration typeConfiguration) {
// Apply possible jdbc type wrapping // Apply possible jdbc type wrapping
final Expression expression; final Expression expression;
@ -58,7 +85,7 @@ public interface Expression extends SqlAstNode, SqlSelectionProducer {
expression = expressionType.getJdbcMapping( 0 ).getJdbcType().wrapTopLevelSelectionExpression( this ); expression = expressionType.getJdbcMapping( 0 ).getJdbcType().wrapTopLevelSelectionExpression( this );
} }
return expression == this return expression == this
? createSqlSelection( jdbcPosition, valuesArrayPosition, javaType, typeConfiguration ) ? createSqlSelection( jdbcPosition, valuesArrayPosition, javaType, virtual, typeConfiguration )
: new SqlSelectionImpl( jdbcPosition, valuesArrayPosition, expression ); : new SqlSelectionImpl( jdbcPosition, valuesArrayPosition, expression, virtual );
} }
} }

View File

@ -58,6 +58,22 @@ public abstract class DelegatingTableGroup implements TableGroup {
); );
} }
@Override
public SqlSelection createSqlSelection(
int jdbcPosition,
int valuesArrayPosition,
JavaType javaType,
boolean virtual,
TypeConfiguration typeConfiguration) {
return getTableGroup().createSqlSelection(
jdbcPosition,
valuesArrayPosition,
javaType,
virtual,
typeConfiguration
);
}
@Override @Override
public TableReference getTableReference( public TableReference getTableReference(
NavigablePath navigablePath, NavigablePath navigablePath,

View File

@ -71,7 +71,8 @@ public abstract class AbstractJdbcParameter
jdbcPosition, jdbcPosition,
valuesArrayPosition, valuesArrayPosition,
javaType, javaType,
this this,
false
); );
} }

View File

@ -22,12 +22,20 @@ public class ResolvedSqlSelection extends SqlSelectionImpl {
private final BasicType<Object> resolvedType; private final BasicType<Object> resolvedType;
public ResolvedSqlSelection(
int valuesArrayPosition,
Expression sqlExpression,
BasicType<Object> resolvedType) {
super( valuesArrayPosition + 1, valuesArrayPosition, null, sqlExpression, false );
this.resolvedType = resolvedType;
}
public ResolvedSqlSelection( public ResolvedSqlSelection(
int jdbcPosition, int jdbcPosition,
int valuesArrayPosition, int valuesArrayPosition,
Expression sqlExpression, Expression sqlExpression,
BasicType<Object> resolvedType) { BasicType<Object> resolvedType) {
super( jdbcPosition, valuesArrayPosition, null, sqlExpression ); super( jdbcPosition, valuesArrayPosition, null, sqlExpression, false );
this.resolvedType = resolvedType; this.resolvedType = resolvedType;
} }
@ -41,6 +49,11 @@ public class ResolvedSqlSelection extends SqlSelectionImpl {
return resolvedType; return resolvedType;
} }
@Override
public boolean isVirtual() {
return false;
}
@Override @Override
public SqlSelection resolve(JdbcValuesMetadata jdbcResultsMetadata, SessionFactoryImplementor sessionFactory) { public SqlSelection resolve(JdbcValuesMetadata jdbcResultsMetadata, SessionFactoryImplementor sessionFactory) {
return this; return this;

View File

@ -116,7 +116,7 @@ public class RowProcessingStateStandardImpl extends BaseExecutionContext impleme
@Override @Override
public Object getJdbcValue(int position) { public Object getJdbcValue(int position) {
return jdbcValues.getCurrentRowValuesArray()[ position ]; return jdbcValues.getCurrentRowValue( position );
} }
@Override @Override
@ -130,6 +130,7 @@ public class RowProcessingStateStandardImpl extends BaseExecutionContext impleme
@Override @Override
public void finishRowProcessing() { public void finishRowProcessing() {
jdbcValues.finishRowProcessing( this );
} }
@Override @Override

View File

@ -46,16 +46,31 @@ public class SqlSelectionImpl implements SqlSelection, SqlExpressionAccess {
private final int valuesArrayPosition; private final int valuesArrayPosition;
private final Expression sqlExpression; private final Expression sqlExpression;
private final JavaType<?> jdbcJavaType; private final JavaType<?> jdbcJavaType;
private final boolean virtual;
public SqlSelectionImpl(int jdbcPosition, int valuesArrayPosition, Expression sqlExpression) { public SqlSelectionImpl(Expression sqlExpression) {
this( jdbcPosition, valuesArrayPosition, null, sqlExpression ); this( 0, -1, null, sqlExpression, false );
} }
public SqlSelectionImpl(int jdbcPosition, int valuesArrayPosition, JavaType<?> jdbcJavaType, Expression sqlExpression) { public SqlSelectionImpl(int valuesArrayPosition, Expression sqlExpression) {
this( valuesArrayPosition + 1, valuesArrayPosition, null, sqlExpression, false );
}
public SqlSelectionImpl(int jdbcPosition, int valuesArrayPosition, Expression sqlExpression, boolean virtual) {
this( jdbcPosition, valuesArrayPosition, null, sqlExpression, virtual );
}
public SqlSelectionImpl(
int jdbcPosition,
int valuesArrayPosition,
JavaType<?> jdbcJavaType,
Expression sqlExpression,
boolean virtual) {
this.jdbcPosition = jdbcPosition; this.jdbcPosition = jdbcPosition;
this.valuesArrayPosition = valuesArrayPosition; this.valuesArrayPosition = valuesArrayPosition;
this.jdbcJavaType = jdbcJavaType; this.jdbcJavaType = jdbcJavaType;
this.sqlExpression = sqlExpression; this.sqlExpression = sqlExpression;
this.virtual = virtual;
} }
@Override @Override
@ -87,6 +102,11 @@ public class SqlSelectionImpl implements SqlSelection, SqlExpressionAccess {
return getExpression().getExpressionType(); return getExpression().getExpressionType();
} }
@Override
public boolean isVirtual() {
return virtual;
}
@Override @Override
public Expression getSqlExpression() { public Expression getSqlExpression() {
return sqlExpression; return sqlExpression;
@ -126,11 +146,12 @@ public class SqlSelectionImpl implements SqlSelection, SqlExpressionAccess {
final SqlSelection that = (SqlSelection) o; final SqlSelection that = (SqlSelection) o;
return jdbcPosition == that.getJdbcResultSetIndex() && return jdbcPosition == that.getJdbcResultSetIndex() &&
valuesArrayPosition == that.getValuesArrayPosition() && valuesArrayPosition == that.getValuesArrayPosition() &&
Objects.equals( sqlExpression, that.getExpression() ); Objects.equals( sqlExpression, that.getExpression() ) &&
virtual == that.isVirtual();
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash( jdbcPosition, valuesArrayPosition, sqlExpression ); return Objects.hash( jdbcPosition, valuesArrayPosition, sqlExpression, virtual );
} }
} }

View File

@ -6,8 +6,6 @@
*/ */
package org.hibernate.sql.results.jdbc.internal; package org.hibernate.sql.results.jdbc.internal;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.sql.results.caching.QueryCachePutManager;
import org.hibernate.sql.results.jdbc.spi.JdbcValues; import org.hibernate.sql.results.jdbc.spi.JdbcValues;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
@ -15,22 +13,10 @@ import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public abstract class AbstractJdbcValues implements JdbcValues { public abstract class AbstractJdbcValues implements JdbcValues {
private final QueryCachePutManager queryCachePutManager;
public AbstractJdbcValues(QueryCachePutManager queryCachePutManager) {
if ( queryCachePutManager == null ) {
throw new IllegalArgumentException( "QueryCachePutManager cannot be null" );
}
this.queryCachePutManager = queryCachePutManager;
}
@Override @Override
public final boolean next(RowProcessingState rowProcessingState) { public final boolean next(RowProcessingState rowProcessingState) {
final boolean hadRow = processNext( rowProcessingState ); return processNext( rowProcessingState );
if ( hadRow ) {
queryCachePutManager.registerJdbcRow( getCurrentRowValuesArray() );
}
return hadRow;
} }
protected abstract boolean processNext(RowProcessingState rowProcessingState); protected abstract boolean processNext(RowProcessingState rowProcessingState);
@ -64,12 +50,4 @@ public abstract class AbstractJdbcValues implements JdbcValues {
} }
protected abstract boolean processPosition(int position, RowProcessingState rowProcessingState); protected abstract boolean processPosition(int position, RowProcessingState rowProcessingState);
@Override
public final void finishUp(SharedSessionContractImplementor session) {
queryCachePutManager.finishUp( session );
release();
}
protected abstract void release();
} }

View File

@ -8,9 +8,9 @@ package org.hibernate.sql.results.jdbc.internal;
import java.util.List; import java.util.List;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.sql.results.ResultsLogger; import org.hibernate.sql.results.ResultsLogger;
import org.hibernate.sql.results.caching.internal.QueryCachePutManagerDisabledImpl;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMapping; import org.hibernate.sql.results.jdbc.spi.JdbcValuesMapping;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata; import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
@ -29,12 +29,6 @@ public class JdbcValuesCacheHit extends AbstractJdbcValues {
private int position = -1; private int position = -1;
public JdbcValuesCacheHit(Object[][] cachedData, JdbcValuesMapping resolvedMapping) { public JdbcValuesCacheHit(Object[][] cachedData, JdbcValuesMapping resolvedMapping) {
// if we have a cache hit we should not be writing back to the cache.
// its silly because the state would always be the same.
//
// well actually, there are times when we want to write values back to the cache even though we had a hit...
// the case is related to the domain-data cache
super( QueryCachePutManagerDisabledImpl.INSTANCE );
this.cachedData = cachedData; this.cachedData = cachedData;
this.numberOfRows = cachedData.length; this.numberOfRows = cachedData.length;
this.resolvedMapping = resolvedMapping; this.resolvedMapping = resolvedMapping;
@ -237,7 +231,19 @@ public class JdbcValuesCacheHit extends AbstractJdbcValues {
} }
@Override @Override
protected void release() { public Object getCurrentRowValue(int valueIndex) {
if ( position >= numberOfRows ) {
return null;
}
return cachedData[position][valueIndex];
}
@Override
public void finishRowProcessing(RowProcessingState rowProcessingState) {
}
@Override
public void finishUp(SharedSessionContractImplementor session) {
cachedData = null; cachedData = null;
} }

View File

@ -9,6 +9,7 @@ package org.hibernate.sql.results.jdbc.internal;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Arrays; import java.util.Arrays;
import java.util.BitSet;
import org.hibernate.cache.spi.QueryKey; import org.hibernate.cache.spi.QueryKey;
import org.hibernate.cache.spi.QueryResultsCache; import org.hibernate.cache.spi.QueryResultsCache;
@ -32,11 +33,14 @@ import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
*/ */
public class JdbcValuesResultSetImpl extends AbstractJdbcValues { public class JdbcValuesResultSetImpl extends AbstractJdbcValues {
private final QueryCachePutManager queryCachePutManager;
private final ResultSetAccess resultSetAccess; private final ResultSetAccess resultSetAccess;
private final JdbcValuesMapping valuesMapping; private final JdbcValuesMapping valuesMapping;
private final ExecutionContext executionContext; private final ExecutionContext executionContext;
private final SqlSelection[] sqlSelections; private final SqlSelection[] sqlSelections;
private final SqlSelection[] eagerSqlSelections;
private final BitSet initializedIndexes;
private final Object[] currentRowJdbcValues; private final Object[] currentRowJdbcValues;
public JdbcValuesResultSetImpl( public JdbcValuesResultSetImpl(
@ -47,15 +51,61 @@ public class JdbcValuesResultSetImpl extends AbstractJdbcValues {
JdbcValuesMapping valuesMapping, JdbcValuesMapping valuesMapping,
JdbcValuesMetadata metadataForCache, JdbcValuesMetadata metadataForCache,
ExecutionContext executionContext) { ExecutionContext executionContext) {
super( resolveQueryCachePutManager( executionContext, queryOptions, queryCacheKey, queryIdentifier, metadataForCache ) ); this.queryCachePutManager = resolveQueryCachePutManager(
executionContext,
queryOptions,
queryCacheKey,
queryIdentifier,
metadataForCache
);
this.resultSetAccess = resultSetAccess; this.resultSetAccess = resultSetAccess;
this.valuesMapping = valuesMapping; this.valuesMapping = valuesMapping;
this.executionContext = executionContext; this.executionContext = executionContext;
this.sqlSelections = valuesMapping.getSqlSelections().toArray( new SqlSelection[0] ); this.sqlSelections = valuesMapping.getSqlSelections().toArray( new SqlSelection[0] );
this.eagerSqlSelections = extractEagerSqlSelections( sqlSelections );
this.initializedIndexes = new BitSet( valuesMapping.getRowSize() );
this.currentRowJdbcValues = new Object[ valuesMapping.getRowSize() ]; this.currentRowJdbcValues = new Object[ valuesMapping.getRowSize() ];
} }
/**
* Determine the selections which are eager i.e. safe to always extract.
* If a virtual selection exists, we must extract the value for that JDBC position lazily.
*/
private SqlSelection[] extractEagerSqlSelections(SqlSelection[] sqlSelections) {
BitSet lazyValuesPositions = null;
for ( int i = 0; i < sqlSelections.length; i++ ) {
final SqlSelection sqlSelection = sqlSelections[i];
if ( sqlSelection.isVirtual() ) {
if ( lazyValuesPositions == null ) {
lazyValuesPositions = new BitSet();
}
lazyValuesPositions.set( sqlSelection.getValuesArrayPosition() );
// Find the one preceding selection that refers to the same JDBC position
// and treat that as virtual to do lazy extraction
for ( int j = 0; j < i; j++ ) {
if ( sqlSelections[j].getJdbcResultSetIndex() == sqlSelection.getJdbcResultSetIndex() ) {
// There can only be a single selection which also has to be non-virtual
assert !sqlSelections[j].isVirtual();
lazyValuesPositions.set( sqlSelections[j].getValuesArrayPosition() );
break;
}
}
}
}
if ( lazyValuesPositions == null ) {
return sqlSelections;
}
final SqlSelection[] eagerSqlSelections = new SqlSelection[sqlSelections.length - lazyValuesPositions.cardinality()];
int i = 0;
for ( SqlSelection sqlSelection : sqlSelections ) {
if ( !lazyValuesPositions.get( sqlSelection.getValuesArrayPosition() ) ) {
eagerSqlSelections[i++] = sqlSelection;
}
}
return eagerSqlSelections;
}
private static QueryCachePutManager resolveQueryCachePutManager( private static QueryCachePutManager resolveQueryCachePutManager(
ExecutionContext executionContext, ExecutionContext executionContext,
QueryOptions queryOptions, QueryOptions queryOptions,
@ -257,7 +307,9 @@ public class JdbcValuesResultSetImpl extends AbstractJdbcValues {
private void readCurrentRowValues() { private void readCurrentRowValues() {
final ResultSet resultSet = resultSetAccess.getResultSet(); final ResultSet resultSet = resultSetAccess.getResultSet();
final SharedSessionContractImplementor session = executionContext.getSession(); final SharedSessionContractImplementor session = executionContext.getSession();
for ( final SqlSelection sqlSelection : sqlSelections ) { initializedIndexes.clear();
for ( final SqlSelection sqlSelection : eagerSqlSelections ) {
initializedIndexes.set( sqlSelection.getValuesArrayPosition() );
try { try {
currentRowJdbcValues[ sqlSelection.getValuesArrayPosition() ] = sqlSelection.getJdbcValueExtractor().extract( currentRowJdbcValues[ sqlSelection.getValuesArrayPosition() ] = sqlSelection.getJdbcValueExtractor().extract(
resultSet, resultSet,
@ -276,7 +328,8 @@ public class JdbcValuesResultSetImpl extends AbstractJdbcValues {
} }
@Override @Override
protected void release() { public final void finishUp(SharedSessionContractImplementor session) {
queryCachePutManager.finishUp( session );
resultSetAccess.release(); resultSetAccess.release();
} }
@ -290,6 +343,34 @@ public class JdbcValuesResultSetImpl extends AbstractJdbcValues {
return currentRowJdbcValues; return currentRowJdbcValues;
} }
@Override
public void finishRowProcessing(RowProcessingState rowProcessingState) {
queryCachePutManager.registerJdbcRow( currentRowJdbcValues );
}
@Override
public Object getCurrentRowValue(int valueIndex) {
if ( !initializedIndexes.get( valueIndex ) ) {
initializedIndexes.set( valueIndex );
final SqlSelection sqlSelection = sqlSelections[valueIndex];
try {
currentRowJdbcValues[valueIndex] = sqlSelection.getJdbcValueExtractor().extract(
resultSetAccess.getResultSet(),
sqlSelection.getJdbcResultSetIndex(),
executionContext.getSession()
);
}
catch ( SQLException e ) {
// do not want to wrap in ExecutionException here
throw executionContext.getSession().getJdbcServices().getSqlExceptionHelper().convert(
e,
"Could not extract column [" + sqlSelection.getJdbcResultSetIndex() + "] from JDBC ResultSet"
);
}
}
return currentRowJdbcValues[valueIndex];
}
@Override @Override
public void setFetchSize(int fetchSize) { public void setFetchSize(int fetchSize) {
try { try {

View File

@ -21,7 +21,7 @@ public interface JdbcValues {
/** /**
* Advances the "cursor position" and returns a boolean indicating whether * Advances the "cursor position" and returns a boolean indicating whether
* there is a row available to read via {@link #getCurrentRowValuesArray()}. * there is a row available to read via {@link #getCurrentRowValue(int)}.
* *
* @return {@code true} if there are results * @return {@code true} if there are results
*/ */
@ -29,7 +29,7 @@ public interface JdbcValues {
/** /**
* Advances the "cursor position" in reverse and returns a boolean indicating whether * Advances the "cursor position" in reverse and returns a boolean indicating whether
* there is a row available to read via {@link #getCurrentRowValuesArray()}. * there is a row available to read via {@link #getCurrentRowValue(int)}.
* *
* @return {@code true} if there are results available * @return {@code true} if there are results available
*/ */
@ -37,7 +37,7 @@ public interface JdbcValues {
/** /**
* Advances the "cursor position" the indicated number of rows and returns a boolean * Advances the "cursor position" the indicated number of rows and returns a boolean
* indicating whether there is a row available to read via {@link #getCurrentRowValuesArray()}. * indicating whether there is a row available to read via {@link #getCurrentRowValue(int)}.
* *
* @param numberOfRows The number of rows to advance. This can also be negative meaning to * @param numberOfRows The number of rows to advance. This can also be negative meaning to
* move in reverse * move in reverse
@ -74,6 +74,17 @@ public interface JdbcValues {
*/ */
Object[] getCurrentRowValuesArray(); Object[] getCurrentRowValuesArray();
/**
* Get the JDBC value at the given index for the row currently positioned at within
* this source.
*
* @return The current row's JDBC values, or {@code null} if the position
* is beyond the end of the available results.
*/
Object getCurrentRowValue(int valueIndex);
void finishRowProcessing(RowProcessingState rowProcessingState);
/** /**
* Give implementations a chance to finish processing * Give implementations a chance to finish processing
*/ */

View File

@ -0,0 +1,170 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.mapping.basic;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.type.SqlTypes;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
/**
* @author Christian Beikov
*/
@DomainModel(annotatedClasses = {
PolymorphicJsonTests.EntityWithJson.class,
PolymorphicJsonTests.EntityWithJsonA.class,
PolymorphicJsonTests.EntityWithJsonB.class
})
@SessionFactory
public abstract class PolymorphicJsonTests {
@ServiceRegistry(settings = @Setting(name = AvailableSettings.JSON_FORMAT_MAPPER, value = "jsonb"))
public static class JsonB extends PolymorphicJsonTests {
public JsonB() {
}
}
@ServiceRegistry(settings = @Setting(name = AvailableSettings.JSON_FORMAT_MAPPER, value = "jackson"))
public static class Jackson extends PolymorphicJsonTests {
public Jackson() {
}
}
@BeforeEach
public void setup(SessionFactoryScope scope) {
scope.inTransaction(
(session) -> {
session.persist( new EntityWithJsonA( 1, new PropertyA( "e1" ) ) );
session.persist( new EntityWithJsonB( 2, new PropertyB( 123 ) ) );
}
);
}
@AfterEach
public void tearDown(SessionFactoryScope scope) {
scope.inTransaction(
(session) -> {
session.remove( session.find( EntityWithJson.class, 1 ) );
session.remove( session.find( EntityWithJson.class, 2 ) );
}
);
}
@Test
public void verifyReadWorks(SessionFactoryScope scope) {
scope.inTransaction(
(session) -> {
EntityWithJson entityWithJsonA = session.find( EntityWithJson.class, 1 );
EntityWithJson entityWithJsonB = session.find( EntityWithJson.class, 2 );
assertThat( entityWithJsonA, instanceOf( EntityWithJsonA.class ) );
assertThat( entityWithJsonB, instanceOf( EntityWithJsonB.class ) );
assertThat( ( (EntityWithJsonA) entityWithJsonA ).property.value, is( "e1" ) );
assertThat( ( (EntityWithJsonB) entityWithJsonB ).property.value, is( 123 ) );
}
);
}
@Entity(name = "EntityWithJson")
@Table(name = "EntityWithJson")
public static abstract class EntityWithJson {
@Id
private Integer id;
public EntityWithJson() {
}
public EntityWithJson(Integer id) {
this.id = id;
}
}
@Entity(name = "EntityWithJsonA")
public static class EntityWithJsonA extends EntityWithJson {
@JdbcTypeCode( SqlTypes.JSON )
private PropertyA property;
public EntityWithJsonA() {
}
public EntityWithJsonA(Integer id, PropertyA property) {
super( id );
this.property = property;
}
}
@Entity(name = "EntityWithJsonB")
public static class EntityWithJsonB extends EntityWithJson {
@JdbcTypeCode( SqlTypes.JSON )
private PropertyB property;
public EntityWithJsonB() {
}
public EntityWithJsonB(Integer id, PropertyB property) {
super( id );
this.property = property;
}
}
public static class PropertyA {
private String value;
public PropertyA() {
}
public PropertyA(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
public static class PropertyB {
private int value;
public PropertyB() {
}
public PropertyB(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
}