HHH-16392 Add column qualifier support to Dialect
This commit is contained in:
parent
a9080f5f7d
commit
c86c2b8300
|
@ -24,6 +24,7 @@ import org.hibernate.boot.model.FunctionContributions;
|
||||||
import org.hibernate.boot.model.TypeContributions;
|
import org.hibernate.boot.model.TypeContributions;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.dialect.BooleanDecoder;
|
import org.hibernate.dialect.BooleanDecoder;
|
||||||
|
import org.hibernate.dialect.DmlTargetColumnQualifierSupport;
|
||||||
import org.hibernate.dialect.DatabaseVersion;
|
import org.hibernate.dialect.DatabaseVersion;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.dialect.OracleBooleanJdbcType;
|
import org.hibernate.dialect.OracleBooleanJdbcType;
|
||||||
|
@ -96,7 +97,6 @@ import org.hibernate.type.SqlTypes;
|
||||||
import org.hibernate.type.StandardBasicTypes;
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
|
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
|
||||||
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
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.BlobJdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.OracleJsonBlobJdbcType;
|
import org.hibernate.type.descriptor.jdbc.OracleJsonBlobJdbcType;
|
||||||
|
@ -1443,4 +1443,9 @@ public class OracleLegacyDialect extends Dialect {
|
||||||
public String rowId(String rowId) {
|
public String rowId(String rowId) {
|
||||||
return "rowid";
|
return "rowid";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DmlTargetColumnQualifierSupport getDmlTargetColumnQualifierSupport() {
|
||||||
|
return DmlTargetColumnQualifierSupport.TABLE_ALIAS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -514,14 +514,6 @@ public class OracleLegacySqlAstTranslator<T extends JdbcOperation> extends Abstr
|
||||||
return getDialect().supportsFetchClause( FetchClauseType.ROWS_ONLY );
|
return getDialect().supportsFetchClause( FetchClauseType.ROWS_ONLY );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean renderNamedTableReference(NamedTableReference tableReference, LockMode lockMode) {
|
|
||||||
appendSql( tableReference.getTableExpression() );
|
|
||||||
registerAffectedTable( tableReference );
|
|
||||||
renderTableReferenceIdentificationVariable( tableReference );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void visitSetAssignment(Assignment assignment) {
|
protected void visitSetAssignment(Assignment assignment) {
|
||||||
final List<ColumnReference> columnReferences = assignment.getAssignable().getColumnReferences();
|
final List<ColumnReference> columnReferences = assignment.getAssignable().getColumnReferences();
|
||||||
|
@ -549,15 +541,4 @@ public class OracleLegacySqlAstTranslator<T extends JdbcOperation> extends Abstr
|
||||||
assignment.getAssignedValue().accept( this );
|
assignment.getAssignedValue().accept( this );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitColumnReference(ColumnReference columnReference) {
|
|
||||||
columnReference.appendReadExpression( this );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitAggregateColumnWriteExpression(AggregateColumnWriteExpression aggregateColumnWriteExpression) {
|
|
||||||
aggregateColumnWriteExpression.appendWriteExpression( this, this );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5224,4 +5224,13 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
|
||||||
public String getRowIdColumnString(String rowId) {
|
public String getRowIdColumnString(String rowId) {
|
||||||
return null;
|
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;
|
||||||
|
}
|
|
@ -1467,4 +1467,9 @@ public class OracleDialect extends Dialect {
|
||||||
final OracleSqlAstTranslator<?> translator = new OracleSqlAstTranslator<>( factory, optionalTableUpdate );
|
final OracleSqlAstTranslator<?> translator = new OracleSqlAstTranslator<>( factory, optionalTableUpdate );
|
||||||
return translator.createMergeOperation( optionalTableUpdate );
|
return translator.createMergeOperation( optionalTableUpdate );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DmlTargetColumnQualifierSupport getDmlTargetColumnQualifierSupport() {
|
||||||
|
return DmlTargetColumnQualifierSupport.TABLE_ALIAS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -512,14 +512,6 @@ public class OracleSqlAstTranslator<T extends JdbcOperation> extends SqlAstTrans
|
||||||
return getDialect().supportsFetchClause( FetchClauseType.ROWS_ONLY );
|
return getDialect().supportsFetchClause( FetchClauseType.ROWS_ONLY );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean renderNamedTableReference(NamedTableReference tableReference, LockMode lockMode) {
|
|
||||||
appendSql( tableReference.getTableExpression() );
|
|
||||||
registerAffectedTable( tableReference );
|
|
||||||
renderTableReferenceIdentificationVariable( tableReference );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void visitSetAssignment(Assignment assignment) {
|
protected void visitSetAssignment(Assignment assignment) {
|
||||||
final List<ColumnReference> columnReferences = assignment.getAssignable().getColumnReferences();
|
final List<ColumnReference> columnReferences = assignment.getAssignable().getColumnReferences();
|
||||||
|
@ -548,16 +540,6 @@ public class OracleSqlAstTranslator<T extends JdbcOperation> extends SqlAstTrans
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitColumnReference(ColumnReference columnReference) {
|
|
||||||
columnReference.appendReadExpression( this );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitAggregateColumnWriteExpression(AggregateColumnWriteExpression aggregateColumnWriteExpression) {
|
|
||||||
aggregateColumnWriteExpression.appendWriteExpression( this, this );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderMergeTargetAlias() {
|
protected void renderMergeTargetAlias() {
|
||||||
appendSql( " t" );
|
appendSql( " t" );
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.hibernate.Internal;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
import org.hibernate.boot.model.process.internal.InferredBasicValueResolver;
|
import org.hibernate.boot.model.process.internal.InferredBasicValueResolver;
|
||||||
|
import org.hibernate.dialect.DmlTargetColumnQualifierSupport;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.dialect.function.TimestampaddFunction;
|
import org.hibernate.dialect.function.TimestampaddFunction;
|
||||||
import org.hibernate.dialect.function.TimestampdiffFunction;
|
import org.hibernate.dialect.function.TimestampdiffFunction;
|
||||||
|
@ -831,7 +832,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
(filterPredicate) -> additionalRestrictions = combinePredicates( additionalRestrictions, filterPredicate),
|
(filterPredicate) -> additionalRestrictions = combinePredicates( additionalRestrictions, filterPredicate),
|
||||||
entityDescriptor,
|
entityDescriptor,
|
||||||
rootTableGroup,
|
rootTableGroup,
|
||||||
AbstractSqlAstTranslator.rendersTableReferenceAlias( Clause.UPDATE ),
|
getDialect().getDmlTargetColumnQualifierSupport() == DmlTargetColumnQualifierSupport.TABLE_ALIAS,
|
||||||
getLoadQueryInfluencers(),
|
getLoadQueryInfluencers(),
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
|
@ -1088,7 +1089,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
(filterPredicate) -> additionalRestrictions = combinePredicates( additionalRestrictions, filterPredicate),
|
(filterPredicate) -> additionalRestrictions = combinePredicates( additionalRestrictions, filterPredicate),
|
||||||
entityDescriptor,
|
entityDescriptor,
|
||||||
rootTableGroup,
|
rootTableGroup,
|
||||||
AbstractSqlAstTranslator.rendersTableReferenceAlias( Clause.DELETE ),
|
getDialect().getDmlTargetColumnQualifierSupport() == DmlTargetColumnQualifierSupport.TABLE_ALIAS,
|
||||||
getLoadQueryInfluencers(),
|
getLoadQueryInfluencers(),
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
|
|
|
@ -27,6 +27,7 @@ import java.util.function.Supplier;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
|
import org.hibernate.dialect.DmlTargetColumnQualifierSupport;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.dialect.RowLockStrategy;
|
import org.hibernate.dialect.RowLockStrategy;
|
||||||
import org.hibernate.dialect.SelectItemReferenceStrategy;
|
import org.hibernate.dialect.SelectItemReferenceStrategy;
|
||||||
|
@ -5478,13 +5479,13 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// 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
|
// We need some dialect support if we want to support joins in delete and update statements
|
||||||
switch ( clause ) {
|
switch ( clause ) {
|
||||||
case DELETE:
|
case DELETE:
|
||||||
case UPDATE:
|
case UPDATE:
|
||||||
return false;
|
return getDialect().getDmlTargetColumnQualifierSupport() == DmlTargetColumnQualifierSupport.TABLE_ALIAS;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -6018,19 +6019,24 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
||||||
public void visitColumnReference(ColumnReference columnReference) {
|
public void visitColumnReference(ColumnReference columnReference) {
|
||||||
final String dmlTargetTableAlias = getDmlTargetTableAlias();
|
final String dmlTargetTableAlias = getDmlTargetTableAlias();
|
||||||
if ( dmlTargetTableAlias != null && dmlTargetTableAlias.equals( columnReference.getQualifier() ) ) {
|
if ( dmlTargetTableAlias != null && dmlTargetTableAlias.equals( columnReference.getQualifier() ) ) {
|
||||||
// todo (6.0) : use the Dialect to determine how to handle column references
|
final DmlTargetColumnQualifierSupport qualifierSupport = getDialect().getDmlTargetColumnQualifierSupport();
|
||||||
// - specifically should they use the table-alias, the table-expression
|
final String qualifier;
|
||||||
// or neither for its qualifier
|
if ( qualifierSupport == DmlTargetColumnQualifierSupport.TABLE_ALIAS ) {
|
||||||
|
qualifier = dmlTargetTableAlias;
|
||||||
final String tableExpression = getCurrentDmlStatement().getTargetTable().getTableExpression();
|
}
|
||||||
// Qualify the column reference with the table expression only in subqueries
|
// Qualify the column reference with the table expression also when in subqueries
|
||||||
final boolean qualifyColumn = !queryPartStack.isEmpty();
|
else if ( qualifierSupport != DmlTargetColumnQualifierSupport.NONE || !queryPartStack.isEmpty() ) {
|
||||||
|
qualifier = getCurrentDmlStatement().getTargetTable().getTableExpression();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qualifier = null;
|
||||||
|
}
|
||||||
if ( columnReference.isColumnExpressionFormula() ) {
|
if ( columnReference.isColumnExpressionFormula() ) {
|
||||||
// For formulas, we have to replace the qualifier as the alias was already rendered into the formula
|
// 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
|
// This is fine for now as this is only temporary anyway until we render aliases for table references
|
||||||
final String replacement;
|
final String replacement;
|
||||||
if ( qualifyColumn ) {
|
if ( qualifier != null ) {
|
||||||
replacement = "$1" + tableExpression + ".$3";
|
replacement = "$1" + qualifier + ".$3";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
replacement = "$1$3";
|
replacement = "$1$3";
|
||||||
|
@ -6041,7 +6047,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
columnReference.appendReadExpression( this, qualifyColumn ? tableExpression : null );
|
columnReference.appendReadExpression( this, qualifier );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -6054,10 +6060,19 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
||||||
final String dmlTargetTableAlias = getDmlTargetTableAlias();
|
final String dmlTargetTableAlias = getDmlTargetTableAlias();
|
||||||
final ColumnReference columnReference = aggregateColumnWriteExpression.getColumnReference();
|
final ColumnReference columnReference = aggregateColumnWriteExpression.getColumnReference();
|
||||||
if ( dmlTargetTableAlias != null && dmlTargetTableAlias.equals( columnReference.getQualifier() ) ) {
|
if ( dmlTargetTableAlias != null && dmlTargetTableAlias.equals( columnReference.getQualifier() ) ) {
|
||||||
final String tableExpression = getCurrentDmlStatement().getTargetTable().getTableExpression();
|
final DmlTargetColumnQualifierSupport qualifierSupport = getDialect().getDmlTargetColumnQualifierSupport();
|
||||||
// Qualify the column reference with the table expression only in subqueries
|
final String qualifier;
|
||||||
final boolean qualifyColumn = !queryPartStack.isEmpty();
|
if ( qualifierSupport == DmlTargetColumnQualifierSupport.TABLE_ALIAS ) {
|
||||||
aggregateColumnWriteExpression.appendWriteExpression( this, this, qualifyColumn ? tableExpression : null );
|
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 {
|
else {
|
||||||
aggregateColumnWriteExpression.appendWriteExpression( this, this );
|
aggregateColumnWriteExpression.appendWriteExpression( this, this );
|
||||||
|
|
Loading…
Reference in New Issue