Implemented CaseExpressionWalker for different Dialects

This commit is contained in:
Andrea Boriero 2019-11-07 11:11:13 +00:00
parent bef4fc1fde
commit 0a6fd5ba46
18 changed files with 318 additions and 34 deletions

View File

@ -28,6 +28,8 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.sql.CaseFragment; import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.DerbyCaseFragment; import org.hibernate.sql.DerbyCaseFragment;
import org.hibernate.sql.ast.spi.CaseExpressionWalker;
import org.hibernate.sql.ast.spi.DerbyCaseExpressionWalker;
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorDerbyDatabaseImpl; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorDerbyDatabaseImpl;
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
@ -109,6 +111,11 @@ public class DerbyDialect extends DB2Dialect {
return new DerbyCaseFragment(); return new DerbyCaseFragment();
} }
@Override
public CaseExpressionWalker getCaseExpressionWalker() {
return DerbyCaseExpressionWalker.INSTANCE;
}
@Override @Override
public boolean dropConstraints() { public boolean dropConstraints() {
return true; return true;

View File

@ -108,6 +108,8 @@ import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.ForUpdateFragment; import org.hibernate.sql.ForUpdateFragment;
import org.hibernate.sql.JoinFragment; import org.hibernate.sql.JoinFragment;
import org.hibernate.sql.ast.SqlAstTranslatorFactory; import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.ANSICaseExpressionWalker;
import org.hibernate.sql.ast.spi.CaseExpressionWalker;
import org.hibernate.sql.ast.spi.SqlAstWalker; import org.hibernate.sql.ast.spi.SqlAstWalker;
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory; import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression; import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
@ -1785,32 +1787,15 @@ public abstract class Dialect implements ConversionContext {
return new ANSICaseFragment(); return new ANSICaseFragment();
} }
public void visitCaseSearchedExpression( /**
CaseSearchedExpression caseSearchedExpression, * Create a {@link CaseExpressionWalker} responsible
StringBuilder sqlBuffer, * for handling this dialect's variations in how CASE statements are
SqlAstWalker sqlAstWalker) { * handled.
sqlBuffer.append( "case " ); *
* @return This dialect's {@link CaseFragment} strategy.
for ( CaseSearchedExpression.WhenFragment whenFragment : caseSearchedExpression.getWhenFragments() ) { */
sqlBuffer.append( " when " ); public CaseExpressionWalker getCaseExpressionWalker() {
whenFragment.getPredicate().accept( sqlAstWalker ); return ANSICaseExpressionWalker.INSTANCE;
sqlBuffer.append( " then " );
whenFragment.getResult().accept( sqlAstWalker );
}
Expression otherwise = caseSearchedExpression.getOtherwise();
if ( otherwise != null ) {
sqlBuffer.append( " else " );
otherwise.accept( sqlAstWalker );
}
sqlBuffer.append( " end" );
String columnExpression = caseSearchedExpression.getColumnExpression();
if ( columnExpression != null ) {
sqlBuffer.append( " as " ).append( columnExpression );
}
} }
/** /**

View File

@ -22,6 +22,8 @@ import org.hibernate.dialect.lock.UpdateLockingStrategy;
import org.hibernate.persister.entity.Lockable; import org.hibernate.persister.entity.Lockable;
import org.hibernate.sql.CaseFragment; import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.MckoiCaseFragment; import org.hibernate.sql.MckoiCaseFragment;
import org.hibernate.sql.ast.spi.CaseExpressionWalker;
import org.hibernate.sql.ast.spi.MckoiCaseExpressionWalker;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
/** /**
@ -108,6 +110,11 @@ public class MckoiDialect extends Dialect {
return new MckoiCaseFragment(); return new MckoiCaseFragment();
} }
@Override
public CaseExpressionWalker getCaseExpressionWalker() {
return MckoiCaseExpressionWalker.INSTANCE;
}
@Override @Override
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) { public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
// Mckoi has no known variation of a "SELECT ... FOR UPDATE" syntax... // Mckoi has no known variation of a "SELECT ... FOR UPDATE" syntax...

View File

@ -43,6 +43,8 @@ import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.DecodeCaseFragment; import org.hibernate.sql.DecodeCaseFragment;
import org.hibernate.sql.JoinFragment; import org.hibernate.sql.JoinFragment;
import org.hibernate.sql.OracleJoinFragment; import org.hibernate.sql.OracleJoinFragment;
import org.hibernate.sql.ast.spi.CaseExpressionWalker;
import org.hibernate.sql.ast.spi.DecodeCaseExpressionWalker;
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorOracleDatabaseImpl; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorOracleDatabaseImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
@ -298,6 +300,11 @@ public class Oracle8iDialect extends Dialect {
return new DecodeCaseFragment(); return new DecodeCaseFragment();
} }
@Override
public CaseExpressionWalker getCaseExpressionWalker() {
return DecodeCaseExpressionWalker.INSTANCE;
}
@Override @Override
public LimitHandler getLimitHandler() { public LimitHandler getLimitHandler() {
return LIMIT_HANDLER; return LIMIT_HANDLER;

View File

@ -16,6 +16,8 @@ import org.hibernate.dialect.pagination.LimitHelper;
import org.hibernate.engine.spi.RowSelection; import org.hibernate.engine.spi.RowSelection;
import org.hibernate.sql.ANSICaseFragment; import org.hibernate.sql.ANSICaseFragment;
import org.hibernate.sql.CaseFragment; import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.ast.spi.ANSICaseExpressionWalker;
import org.hibernate.sql.ast.spi.CaseExpressionWalker;
/** /**
* A dialect for Oracle 9i databases. * A dialect for Oracle 9i databases.
@ -102,6 +104,11 @@ public class Oracle9iDialect extends Oracle8iDialect {
return new ANSICaseFragment(); return new ANSICaseFragment();
} }
@Override
public CaseExpressionWalker getCaseExpressionWalker() {
return ANSICaseExpressionWalker.INSTANCE;
}
@Override @Override
public LimitHandler getLimitHandler() { public LimitHandler getLimitHandler() {
return LIMIT_HANDLER; return LIMIT_HANDLER;

View File

@ -14,6 +14,8 @@ import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.DecodeCaseFragment; import org.hibernate.sql.DecodeCaseFragment;
import org.hibernate.sql.JoinFragment; import org.hibernate.sql.JoinFragment;
import org.hibernate.sql.OracleJoinFragment; import org.hibernate.sql.OracleJoinFragment;
import org.hibernate.sql.ast.spi.CaseExpressionWalker;
import org.hibernate.sql.ast.spi.DecodeCaseExpressionWalker;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -54,6 +56,11 @@ public class OracleDialect extends Oracle9Dialect {
return new DecodeCaseFragment(); return new DecodeCaseFragment();
} }
@Override
public CaseExpressionWalker getCaseExpressionWalker() {
return DecodeCaseExpressionWalker.INSTANCE;
}
@Override @Override
public String getLimitString(String sql, boolean hasOffset) { public String getLimitString(String sql, boolean hasOffset) {

View File

@ -28,6 +28,8 @@ import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.persister.entity.Lockable; import org.hibernate.persister.entity.Lockable;
import org.hibernate.sql.CaseFragment; import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.DecodeCaseFragment; import org.hibernate.sql.DecodeCaseFragment;
import org.hibernate.sql.ast.spi.CaseExpressionWalker;
import org.hibernate.sql.ast.spi.DecodeCaseExpressionWalker;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -363,6 +365,11 @@ public class RDMSOS2200Dialect extends Dialect {
return new DecodeCaseFragment(); return new DecodeCaseFragment();
} }
@Override
public CaseExpressionWalker getCaseExpressionWalker() {
return DecodeCaseExpressionWalker.INSTANCE;
}
@Override @Override
public LimitHandler getLimitHandler() { public LimitHandler getLimitHandler() {
if ( isLegacyLimitHandlerBehaviorEnabled() ) { if ( isLegacyLimitHandlerBehaviorEnabled() ) {

View File

@ -19,6 +19,8 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.sql.CaseFragment; import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.DecodeCaseFragment; import org.hibernate.sql.DecodeCaseFragment;
import org.hibernate.sql.ast.spi.CaseExpressionWalker;
import org.hibernate.sql.ast.spi.DecodeCaseExpressionWalker;
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorSAPDBDatabaseImpl; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorSAPDBDatabaseImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
@ -218,6 +220,11 @@ public class SAPDBDialect extends Dialect {
return new DecodeCaseFragment(); return new DecodeCaseFragment();
} }
@Override
public CaseExpressionWalker getCaseExpressionWalker() {
return DecodeCaseExpressionWalker.INSTANCE;
}
@Override @Override
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) { public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
throw new NotYetImplementedFor6Exception( getClass() ); throw new NotYetImplementedFor6Exception( getClass() );

View File

@ -0,0 +1,46 @@
/*
* 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.sql.ast.spi;
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
import org.hibernate.sql.ast.tree.expression.Expression;
/**
* @author Andrea Boriero
*/
public class ANSICaseExpressionWalker implements CaseExpressionWalker {
public static ANSICaseExpressionWalker INSTANCE = new ANSICaseExpressionWalker();
public void visitCaseSearchedExpression(
CaseSearchedExpression caseSearchedExpression,
StringBuilder sqlBuffer,
SqlAstWalker sqlAstWalker){
sqlBuffer.append( "case " );
for ( CaseSearchedExpression.WhenFragment whenFragment : caseSearchedExpression.getWhenFragments() ) {
sqlBuffer.append( " when " );
whenFragment.getPredicate().accept( sqlAstWalker );
sqlBuffer.append( " then " );
whenFragment.getResult().accept( sqlAstWalker );
}
Expression otherwise = caseSearchedExpression.getOtherwise();
if ( otherwise != null ) {
sqlBuffer.append( " else " );
otherwise.accept( sqlAstWalker );
}
sqlBuffer.append( " end" );
final String columnExpression = caseSearchedExpression.getColumnExpression();
if ( columnExpression != null ) {
sqlBuffer.append( " as " ).append( columnExpression );
}
}
}

View File

@ -742,7 +742,7 @@ public abstract class AbstractSqlAstWalker
@Override @Override
public void visitCaseSearchedExpression(CaseSearchedExpression caseSearchedExpression) { public void visitCaseSearchedExpression(CaseSearchedExpression caseSearchedExpression) {
dialect.visitCaseSearchedExpression( caseSearchedExpression, sqlBuffer, this ); dialect.getCaseExpressionWalker().visitCaseSearchedExpression( caseSearchedExpression, sqlBuffer, this );
} }
@Override @Override

View File

@ -0,0 +1,19 @@
/*
* 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.sql.ast.spi;
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
/**
* @author Andrea Boriero
*/
public interface CaseExpressionWalker {
void visitCaseSearchedExpression(
CaseSearchedExpression caseSearchedExpression,
StringBuilder sqlBuffer,
SqlAstWalker sqlAstWalker);
}

View File

@ -0,0 +1,52 @@
/*
* 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.sql.ast.spi;
import java.util.List;
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
import org.hibernate.sql.ast.tree.expression.Expression;
/**
* @author Andrea Boriero
*/
public class DecodeCaseExpressionWalker implements CaseExpressionWalker {
public static final DecodeCaseExpressionWalker INSTANCE = new DecodeCaseExpressionWalker();
@Override
public void visitCaseSearchedExpression(
CaseSearchedExpression caseSearchedExpression, StringBuilder sqlBuffer, SqlAstWalker sqlAstWalker) {
sqlBuffer.append( "decode( " );
List<CaseSearchedExpression.WhenFragment> whenFragments = caseSearchedExpression.getWhenFragments();
int caseNumber = whenFragments.size();
for ( int i = 0; i < caseNumber; i++ ) {
final CaseSearchedExpression.WhenFragment whenFragment = whenFragments.get( i );
if ( i != 0 ) {
sqlBuffer.append( ", " );
}
whenFragment.getPredicate().getLeftHandExpression().accept( sqlAstWalker );
sqlBuffer.append( ", " );
whenFragment.getResult().accept( sqlAstWalker );
}
Expression otherwise = caseSearchedExpression.getOtherwise();
if ( otherwise != null ) {
sqlBuffer.append( ", " );
otherwise.accept( sqlAstWalker );
}
sqlBuffer.append( "')'" );
final String columnExpression = caseSearchedExpression.getColumnExpression();
if ( columnExpression != null ) {
sqlBuffer.append( " as " ).append( columnExpression );
}
}
}

View File

@ -0,0 +1,61 @@
/*
* 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.sql.ast.spi;
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
/**
* @author Andrea Boriero
*/
public class DerbyCaseExpressionWalker implements CaseExpressionWalker {
public static DerbyCaseExpressionWalker INSTANCE = new DerbyCaseExpressionWalker();
@Override
public void visitCaseSearchedExpression(
CaseSearchedExpression caseSearchedExpression,
StringBuilder sqlBuffer,
SqlAstWalker sqlAstWalker) {
sqlBuffer.append( "case " );
for ( CaseSearchedExpression.WhenFragment whenFragment : caseSearchedExpression.getWhenFragments() ) {
sqlBuffer.append( " when " );
whenFragment.getPredicate().accept( sqlAstWalker );
sqlBuffer.append( " then " );
whenFragment.getResult().accept( sqlAstWalker );
}
// TODO (6.0) : not sure this is the correct way to managed the otherwise expression
Expression otherwise = caseSearchedExpression.getOtherwise();
if ( otherwise != null ) {
sqlBuffer.append( " else " );
if ( otherwise instanceof QueryLiteral ) {
Object value = ( (QueryLiteral) otherwise ).getValue();
if ( value == null ) {
// null is not considered the same type as Integer.
sqlBuffer.append( "-1" );
}
else {
otherwise.accept( sqlAstWalker );
}
}
else {
otherwise.accept( sqlAstWalker );
}
}
sqlBuffer.append( " end" );
final String columnExpression = caseSearchedExpression.getColumnExpression();
if ( columnExpression != null ) {
sqlBuffer.append( " as " ).append( columnExpression );
}
}
}

View File

@ -0,0 +1,49 @@
/*
* 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.sql.ast.spi;
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.predicate.NullnessPredicate;
/**
* @author Andrea Boriero
*/
public class MckoiCaseExpressionWalker implements CaseExpressionWalker {
public static final MckoiCaseExpressionWalker INSTANCE = new MckoiCaseExpressionWalker();
@Override
public void visitCaseSearchedExpression(
CaseSearchedExpression caseSearchedExpression, StringBuilder sqlBuffer, SqlAstWalker sqlAstWalker) {
sqlBuffer.append( "case " );
StringBuilder buf2= new StringBuilder( );
for ( CaseSearchedExpression.WhenFragment whenFragment : caseSearchedExpression.getWhenFragments() ) {
sqlBuffer.append( " if( " );
whenFragment.getPredicate().accept( sqlAstWalker );
sqlBuffer.append( ", " );
whenFragment.getResult().accept( sqlAstWalker );
sqlBuffer.append(", ");
buf2.append(")");
}
Expression otherwise = caseSearchedExpression.getOtherwise();
if ( otherwise != null ) {
otherwise.accept( sqlAstWalker );
}
else {
sqlBuffer.append( "null" );
}
sqlBuffer.append(buf2);
final String columnExpression = caseSearchedExpression.getColumnExpression();
if ( columnExpression != null ) {
sqlBuffer.append( " as " ).append( columnExpression );
}
}
}

View File

@ -14,7 +14,7 @@ import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.query.sqm.sql.internal.DomainResultProducer; import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
import org.hibernate.sql.ast.spi.SqlAstWalker; import org.hibernate.sql.ast.spi.SqlAstWalker;
import org.hibernate.sql.ast.spi.SqlSelection; import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.predicate.Predicate; import org.hibernate.sql.ast.tree.predicate.CasePredicate;
import org.hibernate.sql.results.internal.SqlSelectionImpl; import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.sql.results.internal.domain.basic.BasicResult; import org.hibernate.sql.results.internal.domain.basic.BasicResult;
import org.hibernate.sql.results.spi.DomainResult; import org.hibernate.sql.results.spi.DomainResult;
@ -53,7 +53,7 @@ public class CaseSearchedExpression implements Expression, DomainResultProducer
return otherwise; return otherwise;
} }
public void when(Predicate predicate, Expression result) { public void when(CasePredicate predicate, Expression result) {
whenFragments.add( new WhenFragment( predicate, result ) ); whenFragments.add( new WhenFragment( predicate, result ) );
} }
@ -109,15 +109,15 @@ public class CaseSearchedExpression implements Expression, DomainResultProducer
} }
public static class WhenFragment { public static class WhenFragment {
private final Predicate predicate; private final CasePredicate predicate;
private final Expression result; private final Expression result;
public WhenFragment(Predicate predicate, Expression result) { public WhenFragment(CasePredicate predicate, Expression result) {
this.predicate = predicate; this.predicate = predicate;
this.result = result; this.result = result;
} }
public Predicate getPredicate() { public CasePredicate getPredicate() {
return predicate; return predicate;
} }

View File

@ -0,0 +1,17 @@
/*
* 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.sql.ast.tree.predicate;
import org.hibernate.sql.ast.tree.expression.Expression;
/**
* @author Andrea Boriero
*/
public interface CasePredicate extends Predicate {
Expression getLeftHandExpression();
}

View File

@ -13,7 +13,7 @@ import org.hibernate.sql.ast.tree.expression.Expression;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class ComparisonPredicate implements Predicate { public class ComparisonPredicate implements Predicate, CasePredicate {
private final Expression leftHandExpression; private final Expression leftHandExpression;
private ComparisonOperator operator; private ComparisonOperator operator;
private final Expression rightHandExpression; private final Expression rightHandExpression;
@ -27,6 +27,7 @@ public class ComparisonPredicate implements Predicate {
this.rightHandExpression = rightHandExpression; this.rightHandExpression = rightHandExpression;
} }
@Override
public Expression getLeftHandExpression() { public Expression getLeftHandExpression() {
return leftHandExpression; return leftHandExpression;
} }

View File

@ -12,7 +12,7 @@ import org.hibernate.sql.ast.tree.expression.Expression;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class NullnessPredicate implements Predicate { public class NullnessPredicate implements Predicate, CasePredicate {
private final Expression expression; private final Expression expression;
private final boolean negated; private final boolean negated;
@ -38,4 +38,9 @@ public class NullnessPredicate implements Predicate {
public void accept(SqlAstWalker sqlTreeWalker) { public void accept(SqlAstWalker sqlTreeWalker) {
sqlTreeWalker.visitNullnessPredicate( this ); sqlTreeWalker.visitNullnessPredicate( this );
} }
@Override
public Expression getLeftHandExpression() {
return expression;
}
} }