Skip to content

Commit

Permalink
HHH-16392 Add column qualifier support to Dialect
Browse files Browse the repository at this point in the history
  • Loading branch information
mbladel committed Apr 28, 2023
1 parent 094f243 commit 792a355
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 56 deletions.
Expand Up @@ -24,6 +24,7 @@
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.BooleanDecoder;
import org.hibernate.dialect.DmlTargetColumnQualifierSupport;
import org.hibernate.dialect.DatabaseVersion;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.OracleBooleanJdbcType;
Expand Down Expand Up @@ -96,7 +97,6 @@
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
import org.hibernate.type.descriptor.jdbc.ArrayJdbcType;
import org.hibernate.type.descriptor.jdbc.BlobJdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.OracleJsonBlobJdbcType;
Expand Down Expand Up @@ -1443,4 +1443,9 @@ public String getCreateUserDefinedTypeKindString() {
public String rowId(String rowId) {
return "rowid";
}

@Override
public DmlTargetColumnQualifierSupport getDmlTargetColumnQualifierSupport() {
return DmlTargetColumnQualifierSupport.TABLE_ALIAS;
}
}
Expand Up @@ -514,14 +514,6 @@ private boolean supportsOffsetFetchClause() {
return getDialect().supportsFetchClause( FetchClauseType.ROWS_ONLY );
}

@Override
protected boolean renderNamedTableReference(NamedTableReference tableReference, LockMode lockMode) {
appendSql( tableReference.getTableExpression() );
registerAffectedTable( tableReference );
renderTableReferenceIdentificationVariable( tableReference );
return false;
}

@Override
protected void visitSetAssignment(Assignment assignment) {
final List<ColumnReference> columnReferences = assignment.getAssignable().getColumnReferences();
Expand Down Expand Up @@ -549,15 +541,4 @@ protected void visitSetAssignment(Assignment assignment) {
assignment.getAssignedValue().accept( this );
}
}

@Override
public void visitColumnReference(ColumnReference columnReference) {
columnReference.appendReadExpression( this );
}

@Override
public void visitAggregateColumnWriteExpression(AggregateColumnWriteExpression aggregateColumnWriteExpression) {
aggregateColumnWriteExpression.appendWriteExpression( this, this );
}

}
Expand Up @@ -5247,4 +5247,13 @@ public int rowIdSqlType() {
public String getRowIdColumnString(String rowId) {
return null;
}

/**
* Get the minimum {@link DmlTargetColumnQualifierSupport} required by this dialect.
*
* @return the column qualifier support required by this dialect
*/
public DmlTargetColumnQualifierSupport getDmlTargetColumnQualifierSupport() {
return DmlTargetColumnQualifierSupport.NONE;
}
}
@@ -0,0 +1,32 @@
/*
* 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.dialect;

/**
* Indicates the level of qualifier support used by
* the dialect when referencing a column.
*
* @author Marco Belladelli
*/
public enum DmlTargetColumnQualifierSupport {
/**
* Qualify the column using the table expression,
* ignoring a possible table alias.
*/
TABLE_EXPRESSION,

/**
* Qualify the column using the table alias, whenever available,
* and fallback to the table expression.
*/
TABLE_ALIAS,

/**
* No need to explicitly qualify the column.
*/
NONE;
}
Expand Up @@ -1449,4 +1449,9 @@ public MutationOperation createOptionalTableUpdateOperation(
final OracleSqlAstTranslator<?> translator = new OracleSqlAstTranslator<>( factory, optionalTableUpdate );
return translator.createMergeOperation( optionalTableUpdate );
}

@Override
public DmlTargetColumnQualifierSupport getDmlTargetColumnQualifierSupport() {
return DmlTargetColumnQualifierSupport.TABLE_ALIAS;
}
}
Expand Up @@ -512,14 +512,6 @@ private boolean supportsOffsetFetchClause() {
return getDialect().supportsFetchClause( FetchClauseType.ROWS_ONLY );
}

@Override
protected boolean renderNamedTableReference(NamedTableReference tableReference, LockMode lockMode) {
appendSql( tableReference.getTableExpression() );
registerAffectedTable( tableReference );
renderTableReferenceIdentificationVariable( tableReference );
return false;
}

@Override
protected void visitSetAssignment(Assignment assignment) {
final List<ColumnReference> columnReferences = assignment.getAssignable().getColumnReferences();
Expand Down Expand Up @@ -548,16 +540,6 @@ protected void visitSetAssignment(Assignment assignment) {
}
}

@Override
public void visitColumnReference(ColumnReference columnReference) {
columnReference.appendReadExpression( this );
}

@Override
public void visitAggregateColumnWriteExpression(AggregateColumnWriteExpression aggregateColumnWriteExpression) {
aggregateColumnWriteExpression.appendWriteExpression( this, this );
}

@Override
protected void renderMergeTargetAlias() {
appendSql( " t" );
Expand Down
Expand Up @@ -34,6 +34,7 @@
import org.hibernate.LockMode;
import org.hibernate.QueryException;
import org.hibernate.boot.model.process.internal.InferredBasicValueResolver;
import org.hibernate.dialect.DmlTargetColumnQualifierSupport;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.function.TimestampaddFunction;
import org.hibernate.dialect.function.TimestampdiffFunction;
Expand Down Expand Up @@ -831,7 +832,7 @@ public UpdateStatement visitUpdateStatement(SqmUpdateStatement<?> sqmStatement)
(filterPredicate) -> additionalRestrictions = combinePredicates( additionalRestrictions, filterPredicate),
entityDescriptor,
rootTableGroup,
AbstractSqlAstTranslator.rendersTableReferenceAlias( Clause.UPDATE ),
getDialect().getDmlTargetColumnQualifierSupport() == DmlTargetColumnQualifierSupport.TABLE_ALIAS,
getLoadQueryInfluencers(),
this
);
Expand Down Expand Up @@ -1088,7 +1089,7 @@ public DeleteStatement visitDeleteStatement(SqmDeleteStatement<?> statement) {
(filterPredicate) -> additionalRestrictions = combinePredicates( additionalRestrictions, filterPredicate),
entityDescriptor,
rootTableGroup,
AbstractSqlAstTranslator.rendersTableReferenceAlias( Clause.DELETE ),
getDialect().getDmlTargetColumnQualifierSupport() == DmlTargetColumnQualifierSupport.TABLE_ALIAS,
getLoadQueryInfluencers(),
this
);
Expand Down
Expand Up @@ -27,6 +27,7 @@
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.QueryException;
import org.hibernate.dialect.DmlTargetColumnQualifierSupport;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.RowLockStrategy;
import org.hibernate.dialect.SelectItemReferenceStrategy;
Expand Down Expand Up @@ -5478,13 +5479,13 @@ protected final void renderTableReferenceIdentificationVariable(TableReference t
}
}

public static boolean rendersTableReferenceAlias(Clause clause) {
protected boolean rendersTableReferenceAlias(Clause clause) {
// todo (6.0) : For now we just skip the alias rendering in the delete and update clauses
// We need some dialect support if we want to support joins in delete and update statements
switch ( clause ) {
case DELETE:
case UPDATE:
return false;
return getDialect().getDmlTargetColumnQualifierSupport() == DmlTargetColumnQualifierSupport.TABLE_ALIAS;
}
return true;
}
Expand Down Expand Up @@ -6018,19 +6019,24 @@ public void visitTableReferenceJoin(TableReferenceJoin tableReferenceJoin) {
public void visitColumnReference(ColumnReference columnReference) {
final String dmlTargetTableAlias = getDmlTargetTableAlias();
if ( dmlTargetTableAlias != null && dmlTargetTableAlias.equals( columnReference.getQualifier() ) ) {
// todo (6.0) : use the Dialect to determine how to handle column references
// - specifically should they use the table-alias, the table-expression
// or neither for its qualifier

final String tableExpression = getCurrentDmlStatement().getTargetTable().getTableExpression();
// Qualify the column reference with the table expression only in subqueries
final boolean qualifyColumn = !queryPartStack.isEmpty();
final DmlTargetColumnQualifierSupport qualifierSupport = getDialect().getDmlTargetColumnQualifierSupport();
final String qualifier;
if ( qualifierSupport == DmlTargetColumnQualifierSupport.TABLE_ALIAS ) {
qualifier = dmlTargetTableAlias;
}
// Qualify the column reference with the table expression also when in subqueries
else if ( qualifierSupport != DmlTargetColumnQualifierSupport.NONE || !queryPartStack.isEmpty() ) {
qualifier = getCurrentDmlStatement().getTargetTable().getTableExpression();
}
else {
qualifier = null;
}
if ( columnReference.isColumnExpressionFormula() ) {
// For formulas, we have to replace the qualifier as the alias was already rendered into the formula
// This is fine for now as this is only temporary anyway until we render aliases for table references
final String replacement;
if ( qualifyColumn ) {
replacement = "$1" + tableExpression + ".$3";
if ( qualifier != null ) {
replacement = "$1" + qualifier + ".$3";
}
else {
replacement = "$1$3";
Expand All @@ -6041,7 +6047,7 @@ public void visitColumnReference(ColumnReference columnReference) {
);
}
else {
columnReference.appendReadExpression( this, qualifyColumn ? tableExpression : null );
columnReference.appendReadExpression( this, qualifier );
}
}
else {
Expand All @@ -6054,10 +6060,19 @@ public void visitAggregateColumnWriteExpression(AggregateColumnWriteExpression a
final String dmlTargetTableAlias = getDmlTargetTableAlias();
final ColumnReference columnReference = aggregateColumnWriteExpression.getColumnReference();
if ( dmlTargetTableAlias != null && dmlTargetTableAlias.equals( columnReference.getQualifier() ) ) {
final String tableExpression = getCurrentDmlStatement().getTargetTable().getTableExpression();
// Qualify the column reference with the table expression only in subqueries
final boolean qualifyColumn = !queryPartStack.isEmpty();
aggregateColumnWriteExpression.appendWriteExpression( this, this, qualifyColumn ? tableExpression : null );
final DmlTargetColumnQualifierSupport qualifierSupport = getDialect().getDmlTargetColumnQualifierSupport();
final String qualifier;
if ( qualifierSupport == DmlTargetColumnQualifierSupport.TABLE_ALIAS ) {
qualifier = dmlTargetTableAlias;
}
// Qualify the column reference with the table expression also when in subqueries
else if ( qualifierSupport != DmlTargetColumnQualifierSupport.NONE || !queryPartStack.isEmpty() ) {
qualifier = getCurrentDmlStatement().getTargetTable().getTableExpression();
}
else {
qualifier = null;
}
aggregateColumnWriteExpression.appendWriteExpression( this, this, qualifier );
}
else {
aggregateColumnWriteExpression.appendWriteExpression( this, this );
Expand Down

0 comments on commit 792a355

Please sign in to comment.