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.sql.CaseFragment;
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.SequenceInformationExtractorNoOpImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
@ -109,6 +111,11 @@ public class DerbyDialect extends DB2Dialect {
return new DerbyCaseFragment();
}
@Override
public CaseExpressionWalker getCaseExpressionWalker() {
return DerbyCaseExpressionWalker.INSTANCE;
}
@Override
public boolean dropConstraints() {
return true;

View File

@ -108,6 +108,8 @@ import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.ForUpdateFragment;
import org.hibernate.sql.JoinFragment;
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.StandardSqlAstTranslatorFactory;
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
@ -1785,32 +1787,15 @@ public abstract class Dialect implements ConversionContext {
return new ANSICaseFragment();
}
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" );
String columnExpression = caseSearchedExpression.getColumnExpression();
if ( columnExpression != null ) {
sqlBuffer.append( " as " ).append( columnExpression );
}
/**
* Create a {@link CaseExpressionWalker} responsible
* for handling this dialect's variations in how CASE statements are
* handled.
*
* @return This dialect's {@link CaseFragment} strategy.
*/
public CaseExpressionWalker getCaseExpressionWalker() {
return ANSICaseExpressionWalker.INSTANCE;
}
/**

View File

@ -22,6 +22,8 @@ import org.hibernate.dialect.lock.UpdateLockingStrategy;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.MckoiCaseFragment;
import org.hibernate.sql.ast.spi.CaseExpressionWalker;
import org.hibernate.sql.ast.spi.MckoiCaseExpressionWalker;
import org.hibernate.type.StandardBasicTypes;
/**
@ -108,6 +110,11 @@ public class MckoiDialect extends Dialect {
return new MckoiCaseFragment();
}
@Override
public CaseExpressionWalker getCaseExpressionWalker() {
return MckoiCaseExpressionWalker.INSTANCE;
}
@Override
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
// 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.JoinFragment;
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.spi.SequenceInformationExtractor;
import org.hibernate.type.StandardBasicTypes;
@ -298,6 +300,11 @@ public class Oracle8iDialect extends Dialect {
return new DecodeCaseFragment();
}
@Override
public CaseExpressionWalker getCaseExpressionWalker() {
return DecodeCaseExpressionWalker.INSTANCE;
}
@Override
public LimitHandler getLimitHandler() {
return LIMIT_HANDLER;

View File

@ -16,6 +16,8 @@ import org.hibernate.dialect.pagination.LimitHelper;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.sql.ANSICaseFragment;
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.
@ -102,6 +104,11 @@ public class Oracle9iDialect extends Oracle8iDialect {
return new ANSICaseFragment();
}
@Override
public CaseExpressionWalker getCaseExpressionWalker() {
return ANSICaseExpressionWalker.INSTANCE;
}
@Override
public LimitHandler getLimitHandler() {
return LIMIT_HANDLER;

View File

@ -14,6 +14,8 @@ import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.DecodeCaseFragment;
import org.hibernate.sql.JoinFragment;
import org.hibernate.sql.OracleJoinFragment;
import org.hibernate.sql.ast.spi.CaseExpressionWalker;
import org.hibernate.sql.ast.spi.DecodeCaseExpressionWalker;
import org.jboss.logging.Logger;
@ -54,6 +56,11 @@ public class OracleDialect extends Oracle9Dialect {
return new DecodeCaseFragment();
}
@Override
public CaseExpressionWalker getCaseExpressionWalker() {
return DecodeCaseExpressionWalker.INSTANCE;
}
@Override
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.sql.CaseFragment;
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.jboss.logging.Logger;
@ -363,6 +365,11 @@ public class RDMSOS2200Dialect extends Dialect {
return new DecodeCaseFragment();
}
@Override
public CaseExpressionWalker getCaseExpressionWalker() {
return DecodeCaseExpressionWalker.INSTANCE;
}
@Override
public LimitHandler getLimitHandler() {
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.sql.CaseFragment;
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.spi.SequenceInformationExtractor;
import org.hibernate.type.StandardBasicTypes;
@ -218,6 +220,11 @@ public class SAPDBDialect extends Dialect {
return new DecodeCaseFragment();
}
@Override
public CaseExpressionWalker getCaseExpressionWalker() {
return DecodeCaseExpressionWalker.INSTANCE;
}
@Override
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
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
public void visitCaseSearchedExpression(CaseSearchedExpression caseSearchedExpression) {
dialect.visitCaseSearchedExpression( caseSearchedExpression, sqlBuffer, this );
dialect.getCaseExpressionWalker().visitCaseSearchedExpression( caseSearchedExpression, sqlBuffer, this );
}
@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.sql.ast.spi.SqlAstWalker;
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.domain.basic.BasicResult;
import org.hibernate.sql.results.spi.DomainResult;
@ -53,7 +53,7 @@ public class CaseSearchedExpression implements Expression, DomainResultProducer
return otherwise;
}
public void when(Predicate predicate, Expression result) {
public void when(CasePredicate predicate, Expression result) {
whenFragments.add( new WhenFragment( predicate, result ) );
}
@ -109,15 +109,15 @@ public class CaseSearchedExpression implements Expression, DomainResultProducer
}
public static class WhenFragment {
private final Predicate predicate;
private final CasePredicate predicate;
private final Expression result;
public WhenFragment(Predicate predicate, Expression result) {
public WhenFragment(CasePredicate predicate, Expression result) {
this.predicate = predicate;
this.result = result;
}
public Predicate getPredicate() {
public CasePredicate getPredicate() {
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
*/
public class ComparisonPredicate implements Predicate {
public class ComparisonPredicate implements Predicate, CasePredicate {
private final Expression leftHandExpression;
private ComparisonOperator operator;
private final Expression rightHandExpression;
@ -27,6 +27,7 @@ public class ComparisonPredicate implements Predicate {
this.rightHandExpression = rightHandExpression;
}
@Override
public Expression getLeftHandExpression() {
return leftHandExpression;
}

View File

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