Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.hibernate.query.common.FetchClauseType;
import org.hibernate.query.common.FrameExclusion;
import org.hibernate.query.common.FrameKind;
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
Expand Down Expand Up @@ -55,7 +56,9 @@
import org.hibernate.sql.ast.tree.select.QueryPart;
import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.sql.ast.tree.select.SelectClause;
import org.hibernate.sql.ast.tree.select.SelectStatement;
import org.hibernate.sql.ast.tree.select.SortSpecification;
import org.hibernate.sql.ast.tree.update.Assignable;
import org.hibernate.sql.ast.tree.update.Assignment;
import org.hibernate.sql.ast.tree.update.UpdateStatement;
import org.hibernate.sql.exec.spi.JdbcOperation;
Expand Down Expand Up @@ -668,13 +671,43 @@ private boolean supportsOffsetFetchClause() {
return getDialect().supportsFetchClause( FetchClauseType.ROWS_ONLY );
}

@Override
protected void renderNull(Literal literal) {
if ( getParameterRenderingMode() == SqlAstNodeRenderingMode.NO_UNTYPED ) {
switch ( literal.getJdbcMapping().getJdbcType().getDdlTypeCode() ) {
case SqlTypes.BLOB:
appendSql( "to_blob(null)" );
break;
case SqlTypes.CLOB:
appendSql( "to_clob(null)" );
break;
case SqlTypes.NCLOB:
appendSql( "to_nclob(null)" );
break;
default:
super.renderNull( literal );
break;
}
}
else {
super.renderNull( literal );
}
}

@Override
protected void visitSetAssignment(Assignment assignment) {
final Assignable assignable = assignment.getAssignable();
if ( assignable instanceof SqmPathInterpretation<?> ) {
final String affectedTableName = ( (SqmPathInterpretation<?>) assignable ).getAffectedTableName();
if ( affectedTableName != null ) {
addAffectedTableName( affectedTableName );
}
}
final List<ColumnReference> columnReferences = assignment.getAssignable().getColumnReferences();
final Expression assignedValue = assignment.getAssignedValue();
if ( columnReferences.size() == 1 ) {
columnReferences.get( 0 ).appendColumnForWrite( this );
appendSql( '=' );
final Expression assignedValue = assignment.getAssignedValue();
final SqlTuple sqlTuple = SqlTupleContainer.getSqlTuple( assignedValue );
if ( sqlTuple != null ) {
assert sqlTuple.getExpressions().size() == 1;
Expand All @@ -684,7 +717,7 @@ protected void visitSetAssignment(Assignment assignment) {
assignedValue.accept( this );
}
}
else {
else if ( assignedValue instanceof SelectStatement ) {
char separator = OPEN_PARENTHESIS;
for ( ColumnReference columnReference : columnReferences ) {
appendSql( separator );
Expand All @@ -694,5 +727,18 @@ protected void visitSetAssignment(Assignment assignment) {
appendSql( ")=" );
assignment.getAssignedValue().accept( this );
}
else {
assert assignedValue instanceof SqlTupleContainer;
final List<? extends Expression> expressions = ( (SqlTupleContainer) assignedValue ).getSqlTuple().getExpressions();
columnReferences.get( 0 ).appendColumnForWrite( this, null );
appendSql( '=' );
expressions.get( 0 ).accept( this );
for ( int i = 1; i < columnReferences.size(); i++ ) {
appendSql( ',' );
columnReferences.get( i ).appendColumnForWrite( this, null );
appendSql( '=' );
expressions.get( i ).accept( this );
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.hibernate.query.common.FetchClauseType;
import org.hibernate.query.common.FrameExclusion;
import org.hibernate.query.common.FrameKind;
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.spi.SqlSelection;
Expand Down Expand Up @@ -53,7 +54,9 @@
import org.hibernate.sql.ast.tree.select.QueryPart;
import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.sql.ast.tree.select.SelectClause;
import org.hibernate.sql.ast.tree.select.SelectStatement;
import org.hibernate.sql.ast.tree.select.SortSpecification;
import org.hibernate.sql.ast.tree.update.Assignable;
import org.hibernate.sql.ast.tree.update.Assignment;
import org.hibernate.sql.ast.tree.update.UpdateStatement;
import org.hibernate.sql.exec.spi.JdbcOperation;
Expand Down Expand Up @@ -625,13 +628,43 @@ private boolean supportsOffsetFetchClause() {
return getDialect().supportsFetchClause( FetchClauseType.ROWS_ONLY );
}

@Override
protected void renderNull(Literal literal) {
if ( getParameterRenderingMode() == SqlAstNodeRenderingMode.NO_UNTYPED ) {
switch ( literal.getJdbcMapping().getJdbcType().getDdlTypeCode() ) {
case SqlTypes.BLOB:
appendSql( "to_blob(null)" );
break;
case SqlTypes.CLOB:
appendSql( "to_clob(null)" );
break;
case SqlTypes.NCLOB:
appendSql( "to_nclob(null)" );
break;
default:
super.renderNull( literal );
break;
}
}
else {
super.renderNull( literal );
}
}

@Override
protected void visitSetAssignment(Assignment assignment) {
final Assignable assignable = assignment.getAssignable();
if ( assignable instanceof SqmPathInterpretation<?> ) {
final String affectedTableName = ( (SqmPathInterpretation<?>) assignable ).getAffectedTableName();
if ( affectedTableName != null ) {
addAffectedTableName( affectedTableName );
}
}
final List<ColumnReference> columnReferences = assignment.getAssignable().getColumnReferences();
final Expression assignedValue = assignment.getAssignedValue();
if ( columnReferences.size() == 1 ) {
columnReferences.get( 0 ).appendColumnForWrite( this );
appendSql( '=' );
final Expression assignedValue = assignment.getAssignedValue();
final SqlTuple sqlTuple = SqlTupleContainer.getSqlTuple( assignedValue );
if ( sqlTuple != null ) {
assert sqlTuple.getExpressions().size() == 1;
Expand All @@ -641,15 +674,28 @@ protected void visitSetAssignment(Assignment assignment) {
assignedValue.accept( this );
}
}
else {
else if ( assignedValue instanceof SelectStatement ) {
char separator = OPEN_PARENTHESIS;
for ( ColumnReference columnReference : columnReferences ) {
appendSql( separator );
columnReference.appendColumnForWrite( this );
separator = COMMA_SEPARATOR_CHAR;
}
appendSql( ")=" );
assignment.getAssignedValue().accept( this );
assignedValue.accept( this );
}
else {
assert assignedValue instanceof SqlTupleContainer;
final List<? extends Expression> expressions = ( (SqlTupleContainer) assignedValue ).getSqlTuple().getExpressions();
columnReferences.get( 0 ).appendColumnForWrite( this, null );
appendSql( '=' );
expressions.get( 0 ).accept( this );
for ( int i = 1; i < columnReferences.size(); i++ ) {
appendSql( ',' );
columnReferences.get( i ).appendColumnForWrite( this, null );
appendSql( '=' );
expressions.get( i ).accept( this );
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1299,7 +1299,7 @@ private List<Assignment> getCompatibleAssignments(InsertSelectStatement dmlState
final List<Assignment> assignments = conflictClause.getAssignments();
for ( Assignment assignment : assignments ) {
for ( ColumnReference targetColumn : dmlStatement.getTargetColumns() ) {
if ( targetColumn.equals( assignment.getAssignable() ) ) {
if ( assignment.getAssignable().getColumnReferences().contains( targetColumn ) ) {
if ( compatibleAssignments == null ) {
compatibleAssignments = new ArrayList<>( assignments.size() );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -858,36 +858,57 @@ public List<Assignment> visitSetClause(SqmSetClause setClause) {
final SqmExpression<?> assignmentValue = sqmAssignment.getValue();
final SqmParameter<?> assignmentValueParameter = getSqmParameter( assignmentValue );
final Expression pathSqlExpression = assignedPathInterpretation.getSqlExpression();
final List<? extends Expression> targetColumnReferences =
pathSqlExpression instanceof SqlTuple sqlTuple
? sqlTuple.getExpressions()
//noinspection unchecked
final List<ColumnReference> targetColumnReferences =
pathSqlExpression instanceof SqlTupleContainer sqlTuple
? (List<ColumnReference>) sqlTuple.getSqlTuple().getExpressions()
: pathSqlExpression.getColumnReference().getColumnReferences();
if ( assignmentValueParameter != null ) {
final ArrayList<Expression> expressions = new ArrayList<>( targetColumnReferences.size() );
consumeSqmParameter(
assignmentValueParameter,
assignedPathInterpretation.getExpressionType(),
(index, jdbcParameter) -> addAssignment(
assignments,
aggregateColumnAssignmentHandler,
targetColumnReferences.get( index ),
jdbcParameter
)
(index, jdbcParameter) -> expressions.add( jdbcParameter )
);
}
else if ( assignmentValue instanceof SqmLiteralNull<?> ) {
for ( Expression columnReference : targetColumnReferences ) {
if ( pathSqlExpression instanceof SqlTupleContainer ) {
addAssignment(
assignments,
aggregateColumnAssignmentHandler,
columnReference,
new QueryLiteral<>( null, (BasicValuedMapping) columnReference.getExpressionType() )
(Assignable) assignedPathInterpretation,
targetColumnReferences,
new SqlTuple( expressions, assignedPathInterpretation.getExpressionType() )
);
}
else {
assert expressions.size() == 1;
addAssignment(
assignments,
aggregateColumnAssignmentHandler,
(Assignable) assignedPathInterpretation,
targetColumnReferences,
expressions.get( 0 )
);
}
}
else if ( pathSqlExpression instanceof SqlTupleContainer
&& assignmentValue instanceof SqmLiteralNull<?> ) {
final ArrayList<Expression> expressions = new ArrayList<>( targetColumnReferences.size() );
for ( ColumnReference targetColumnReference : targetColumnReferences ) {
expressions.add( new QueryLiteral<>( null,
(SqlExpressible) targetColumnReference.getExpressionType() ) );
}
addAssignment(
assignments,
aggregateColumnAssignmentHandler,
(Assignable) assignedPathInterpretation,
targetColumnReferences,
new SqlTuple( expressions, assignedPathInterpretation.getExpressionType() )
);
}
else {
addAssignments(
(Expression) assignmentValue.accept( this ),
assignedPathInterpretation.getExpressionType(),
assignedPathInterpretation,
targetColumnReferences,
assignments,
aggregateColumnAssignmentHandler
Expand All @@ -909,35 +930,18 @@ else if ( assignmentValue instanceof SqmLiteralNull<?> ) {

private void addAssignments(
Expression valueExpression,
ModelPart assignedPathType,
List<? extends Expression> targetColumnReferences,
SqmPathInterpretation<?> assignedPathInterpretation,
List<ColumnReference> targetColumnReferences,
ArrayList<Assignment> assignments,
AggregateColumnAssignmentHandler assignmentHandler) {
checkAssignment( valueExpression, assignedPathType );
if ( valueExpression instanceof SqlTuple sqlTuple ) {
addTupleAssignments( targetColumnReferences, assignments, assignmentHandler, sqlTuple );
}
else if ( valueExpression instanceof EmbeddableValuedPathInterpretation<?> embeddable ) {
addTupleAssignments( targetColumnReferences, assignments, assignmentHandler, embeddable.getSqlTuple() );
}
else {
for ( Expression columnReference : targetColumnReferences ) {
addAssignment( assignments, assignmentHandler, columnReference, valueExpression );
}
}
}

private void addTupleAssignments(
List<? extends Expression> targetColumnReferences,
ArrayList<Assignment> assignments,
AggregateColumnAssignmentHandler aggregateColumnAssignmentHandler,
SqlTuple sqlTuple) {
final List<? extends Expression> expressions = sqlTuple.getExpressions();
assert targetColumnReferences.size() == expressions.size();
for ( int i = 0; i < targetColumnReferences.size(); i++ ) {
final ColumnReference columnReference = (ColumnReference) targetColumnReferences.get( i );
addAssignment( assignments, aggregateColumnAssignmentHandler, columnReference, expressions.get( i ) );
}
AggregateColumnAssignmentHandler aggregateColumnAssignmentHandler) {
checkAssignment( valueExpression, assignedPathInterpretation.getExpressionType() );
addAssignment(
assignments,
aggregateColumnAssignmentHandler,
(Assignable) assignedPathInterpretation,
targetColumnReferences,
valueExpression
);
}

private void checkAssignment(Expression valueExpression, ModelPart assignedPathType) {
Expand All @@ -958,12 +962,15 @@ private void checkAssignment(Expression valueExpression, ModelPart assignedPathT
private void addAssignment(
List<Assignment> assignments,
AggregateColumnAssignmentHandler aggregateColumnAssignmentHandler,
Expression columnReference,
Assignable assignable,
List<ColumnReference> targetColumnReferences,
Expression valueExpression) {
if ( aggregateColumnAssignmentHandler != null ) {
aggregateColumnAssignmentHandler.addAssignment( assignments.size(), (ColumnReference) columnReference );
for ( ColumnReference targetColumnReference : targetColumnReferences ) {
aggregateColumnAssignmentHandler.addAssignment( assignments.size(), targetColumnReference );
}
}
assignments.add( new Assignment( (ColumnReference) columnReference, valueExpression ) );
assignments.add( new Assignment( assignable, valueExpression ) );
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import org.hibernate.metamodel.MappingMetamodel;
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.EntityAssociationMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.MappingType;
import org.hibernate.metamodel.mapping.ModelPart;
Expand All @@ -31,6 +32,8 @@
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.ast.tree.update.Assignable;

import org.checkerframework.checker.nullness.qual.Nullable;

import static jakarta.persistence.metamodel.Type.PersistenceType.ENTITY;
import static org.hibernate.internal.util.NullnessUtil.castNonNull;
import static org.hibernate.query.sqm.internal.SqmUtil.getTargetMappingIfNeeded;
Expand Down Expand Up @@ -124,15 +127,37 @@ else if ( expression instanceof SqlSelectionExpression ) {
}

private final ColumnReference columnReference;
private final @Nullable String affectedTableName;

public BasicValuedPathInterpretation(
ColumnReference columnReference,
NavigablePath navigablePath,
BasicValuedModelPart mapping,
TableGroup tableGroup) {
this( columnReference, navigablePath, mapping, tableGroup, determineAffectedTableName( tableGroup, mapping ) );
}

private static @Nullable String determineAffectedTableName(TableGroup tableGroup, BasicValuedModelPart mapping) {
final ModelPartContainer modelPart = tableGroup.getModelPart();
if ( modelPart instanceof EntityAssociationMapping ) {
final EntityAssociationMapping associationMapping = (EntityAssociationMapping) modelPart;
if ( !associationMapping.containsTableReference( mapping.getContainingTableExpression() ) ) {
return associationMapping.getAssociatedEntityMappingType().getMappedTableDetails().getTableName();
}
}
return null;
}

public BasicValuedPathInterpretation(
ColumnReference columnReference,
NavigablePath navigablePath,
BasicValuedModelPart mapping,
TableGroup tableGroup,
@Nullable String affectedTableName) {
super( navigablePath, mapping, tableGroup );
assert columnReference != null;
this.columnReference = columnReference;
this.affectedTableName = affectedTableName;
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -143,6 +168,11 @@ public Expression getSqlExpression() {
return columnReference;
}

@Override
public @Nullable String getAffectedTableName() {
return affectedTableName;
}

@Override
public ColumnReference getColumnReference() {
return columnReference;
Expand Down
Loading