HHH-16801 add HQL 'is true', 'is not true', 'is false', 'is not false' operators
This commit is contained in:
parent
158bf7e697
commit
987a0dfe3c
|
@ -622,6 +622,8 @@ predicate
|
|||
: LEFT_PAREN predicate RIGHT_PAREN # GroupedPredicate
|
||||
| expression IS NOT? NULL # IsNullPredicate
|
||||
| expression IS NOT? EMPTY # IsEmptyPredicate
|
||||
| expression IS NOT? TRUE # IsTruePredicate
|
||||
| expression IS NOT? FALSE # IsFalsePredicate
|
||||
| expression NOT? IN inList # InPredicate
|
||||
| expression NOT? BETWEEN expression AND expression # BetweenPredicate
|
||||
| expression NOT? (LIKE | ILIKE) expression likeEscape? # LikePredicate
|
||||
|
|
|
@ -860,6 +860,11 @@ public class DB2Dialect extends Dialect {
|
|||
return new CteInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsIsTrue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsCurrentTimestampSelection() {
|
||||
return true;
|
||||
|
|
|
@ -280,5 +280,4 @@ public class DerbySqlAstTranslator<T extends JdbcOperation> extends AbstractSqlA
|
|||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2924,6 +2924,18 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this dialect support the {@code is true} and {@code is false}
|
||||
* operators?
|
||||
*
|
||||
* @return {@code true} if the database supports {@code is true} and
|
||||
* {@code is false}, or {@code false} if it does not. The
|
||||
* default is {@code is false}.
|
||||
*/
|
||||
public boolean supportsIsTrue() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Meant as a means for end users to affect the select strings being sent
|
||||
* to the database and perhaps manipulate them in some fashion.
|
||||
|
|
|
@ -591,6 +591,11 @@ public class H2Dialect extends Dialect {
|
|||
return TimeZoneSupport.NATIVE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsIsTrue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendBooleanValueString(SqlAppender appender, boolean bool) {
|
||||
appender.appendSql( bool );
|
||||
|
|
|
@ -1120,6 +1120,11 @@ public class MySQLDialect extends Dialect {
|
|||
return 64;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsIsTrue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsCurrentTimestampSelection() {
|
||||
return true;
|
||||
|
|
|
@ -19,7 +19,6 @@ import org.hibernate.query.sqm.ComparisonOperator;
|
|||
import org.hibernate.query.sqm.FetchClauseType;
|
||||
import org.hibernate.query.sqm.FrameExclusion;
|
||||
import org.hibernate.query.sqm.FrameKind;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteMaterialization;
|
||||
|
|
|
@ -891,6 +891,11 @@ public class PostgreSQLDialect extends Dialect {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsIsTrue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresParensForTupleDistinctCounts() {
|
||||
return true;
|
||||
|
|
|
@ -10,7 +10,6 @@ import java.util.List;
|
|||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.sqm.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
|
@ -18,7 +17,6 @@ import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
|
|||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression;
|
||||
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
|
||||
import org.hibernate.sql.ast.tree.expression.CaseSimpleExpression;
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.hibernate.query.sqm.tree.expression.SqmEvery;
|
|||
import org.hibernate.query.sqm.tree.from.SqmCteJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmDerivedJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmTruthnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectQuery;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.query.hql.spi.SqmCreationOptions;
|
||||
|
@ -1177,6 +1178,16 @@ public class QuerySplitter {
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitIsTruePredicate(SqmTruthnessPredicate predicate) {
|
||||
return new SqmTruthnessPredicate(
|
||||
(SqmExpression<?>) predicate.getExpression().accept( this ),
|
||||
predicate.getBooleanValue(),
|
||||
predicate.isNegated(),
|
||||
predicate.nodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmBetweenPredicate visitBetweenPredicate(SqmBetweenPredicate predicate) {
|
||||
return new SqmBetweenPredicate(
|
||||
|
|
|
@ -188,6 +188,7 @@ import org.hibernate.query.sqm.tree.predicate.SqmNegatablePredicate;
|
|||
import org.hibernate.query.sqm.tree.predicate.SqmNegatedPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmTruthnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||
import org.hibernate.query.sqm.tree.select.AbstractSqmSelectQuery;
|
||||
import org.hibernate.query.sqm.tree.select.SqmAliasedNode;
|
||||
|
@ -2312,7 +2313,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
@Override
|
||||
public SqmGroupedPredicate visitGroupedPredicate(HqlParser.GroupedPredicateContext ctx) {
|
||||
return new SqmGroupedPredicate(
|
||||
(SqmPredicate) ctx.getChild( 1 ).accept( this ),
|
||||
(SqmPredicate) ctx.predicate().accept( this ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
@ -2321,8 +2322,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
public SqmPredicate visitAndPredicate(HqlParser.AndPredicateContext ctx) {
|
||||
return junction(
|
||||
Predicate.BooleanOperator.AND,
|
||||
(SqmPredicate) ctx.getChild( 0 ).accept( this ),
|
||||
(SqmPredicate) ctx.getChild( 2 ).accept( this )
|
||||
(SqmPredicate) ctx.predicate( 0 ).accept( this ),
|
||||
(SqmPredicate) ctx.predicate( 1 ).accept( this )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2330,8 +2331,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
public SqmPredicate visitOrPredicate(HqlParser.OrPredicateContext ctx) {
|
||||
return junction(
|
||||
Predicate.BooleanOperator.OR,
|
||||
(SqmPredicate) ctx.getChild( 0 ).accept( this ),
|
||||
(SqmPredicate) ctx.getChild( 2 ).accept( this )
|
||||
(SqmPredicate) ctx.predicate( 0 ).accept( this ),
|
||||
(SqmPredicate) ctx.predicate( 1 ).accept( this )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2360,7 +2361,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
|
||||
@Override
|
||||
public SqmPredicate visitNegatedPredicate(HqlParser.NegatedPredicateContext ctx) {
|
||||
SqmPredicate predicate = (SqmPredicate) ctx.getChild( 1 ).accept( this );
|
||||
SqmPredicate predicate = (SqmPredicate) ctx.predicate().accept( this );
|
||||
if ( predicate instanceof SqmNegatablePredicate ) {
|
||||
( (SqmNegatablePredicate) predicate ).negate();
|
||||
return predicate;
|
||||
|
@ -2372,13 +2373,11 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
|
||||
@Override
|
||||
public SqmBetweenPredicate visitBetweenPredicate(HqlParser.BetweenPredicateContext ctx) {
|
||||
final boolean negated = ( (TerminalNode) ctx.getChild( 1 ) ).getSymbol().getType() == HqlParser.NOT;
|
||||
final int startIndex = negated ? 3 : 2;
|
||||
return new SqmBetweenPredicate(
|
||||
(SqmExpression<?>) ctx.getChild( 0 ).accept( this ),
|
||||
(SqmExpression<?>) ctx.getChild( startIndex ).accept( this ),
|
||||
(SqmExpression<?>) ctx.getChild( startIndex + 2 ).accept( this ),
|
||||
negated,
|
||||
(SqmExpression<?>) ctx.expression( 0 ).accept( this ),
|
||||
(SqmExpression<?>) ctx.expression( 1 ).accept( this ),
|
||||
(SqmExpression<?>) ctx.expression( 2 ).accept( this ),
|
||||
ctx.NOT() != null,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
@ -2386,22 +2385,20 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
|
||||
@Override
|
||||
public SqmNullnessPredicate visitIsNullPredicate(HqlParser.IsNullPredicateContext ctx) {
|
||||
final boolean negated = ctx.getChildCount() == 4;
|
||||
return new SqmNullnessPredicate(
|
||||
(SqmExpression<?>) ctx.expression().accept( this ),
|
||||
negated,
|
||||
ctx.NOT() != null,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmEmptinessPredicate visitIsEmptyPredicate(HqlParser.IsEmptyPredicateContext ctx) {
|
||||
final boolean negated = ctx.getChildCount() == 4;
|
||||
SqmExpression<?> expression = (SqmExpression<?>) ctx.expression().accept(this);
|
||||
if ( expression instanceof SqmPluralValuedSimplePath ) {
|
||||
return new SqmEmptinessPredicate(
|
||||
(SqmPluralValuedSimplePath<?>) expression,
|
||||
negated,
|
||||
ctx.NOT() != null,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
@ -2410,6 +2407,26 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitIsTruePredicate(HqlParser.IsTruePredicateContext ctx) {
|
||||
return new SqmTruthnessPredicate(
|
||||
(SqmExpression<?>) ctx.expression().accept( this ),
|
||||
true,
|
||||
ctx.NOT() != null,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitIsFalsePredicate(HqlParser.IsFalsePredicateContext ctx) {
|
||||
return new SqmTruthnessPredicate(
|
||||
(SqmExpression<?>) ctx.expression().accept( this ),
|
||||
false,
|
||||
ctx.NOT() != null,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitComparisonOperator(HqlParser.ComparisonOperatorContext ctx) {
|
||||
final TerminalNode firstToken = (TerminalNode) ctx.getChild( 0 );
|
||||
|
|
|
@ -103,6 +103,7 @@ import org.hibernate.query.sqm.tree.predicate.SqmMemberOfPredicate;
|
|||
import org.hibernate.query.sqm.tree.predicate.SqmNegatedPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmTruthnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
|
||||
import org.hibernate.query.sqm.tree.select.SqmJpaCompoundSelection;
|
||||
|
@ -361,6 +362,8 @@ public interface SemanticQueryWalker<T> {
|
|||
|
||||
T visitIsNullPredicate(SqmNullnessPredicate predicate);
|
||||
|
||||
T visitIsTruePredicate(SqmTruthnessPredicate predicate);
|
||||
|
||||
T visitBetweenPredicate(SqmBetweenPredicate predicate);
|
||||
|
||||
T visitLikePredicate(SqmLikePredicate predicate);
|
||||
|
|
|
@ -94,6 +94,7 @@ import org.hibernate.query.sqm.tree.predicate.SqmMemberOfPredicate;
|
|||
import org.hibernate.query.sqm.tree.predicate.SqmNegatedPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmTruthnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
|
||||
import org.hibernate.query.sqm.tree.select.SqmJpaCompoundSelection;
|
||||
|
@ -937,6 +938,17 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitIsTruePredicate(SqmTruthnessPredicate predicate) {
|
||||
processStanza(
|
||||
(predicate.isNegated() ? "is-not-" : "is-") + predicate.getBooleanValue(),
|
||||
true,
|
||||
() -> predicate.getExpression().accept( this )
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitBetweenPredicate(SqmBetweenPredicate predicate) {
|
||||
processStanza(
|
||||
|
|
|
@ -93,6 +93,7 @@ import org.hibernate.query.sqm.tree.predicate.SqmMemberOfPredicate;
|
|||
import org.hibernate.query.sqm.tree.predicate.SqmNegatedPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmTruthnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
|
||||
import org.hibernate.query.sqm.tree.select.SqmJpaCompoundSelection;
|
||||
|
@ -462,6 +463,12 @@ public abstract class BaseSemanticQueryWalker implements SemanticQueryWalker<Obj
|
|||
return predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitIsTruePredicate(SqmTruthnessPredicate predicate) {
|
||||
predicate.getExpression().accept( this );
|
||||
return predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitBetweenPredicate(SqmBetweenPredicate predicate) {
|
||||
predicate.getExpression().accept( this );
|
||||
|
|
|
@ -261,6 +261,7 @@ import org.hibernate.query.sqm.tree.predicate.SqmMemberOfPredicate;
|
|||
import org.hibernate.query.sqm.tree.predicate.SqmNegatedPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmTruthnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||
import org.hibernate.query.sqm.tree.select.SqmAliasedNode;
|
||||
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
|
||||
|
@ -365,6 +366,7 @@ import org.hibernate.sql.ast.tree.predicate.NullnessPredicate;
|
|||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.PredicateCollector;
|
||||
import org.hibernate.sql.ast.tree.predicate.SelfRenderingPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.ThruthnessPredicate;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
|
@ -7539,6 +7541,16 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitIsTruePredicate(SqmTruthnessPredicate predicate) {
|
||||
return new ThruthnessPredicate(
|
||||
(Expression) visitWithInferredType( predicate.getExpression(), () -> basicType( Boolean.class )),
|
||||
predicate.getBooleanValue(),
|
||||
predicate.isNegated(),
|
||||
getBooleanType()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate visitInListPredicate(SqmInListPredicate<?> predicate) {
|
||||
// special case: if there is just a single "value" element and it is a parameter
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.hibernate.query.sqm.tree.predicate.SqmInSubQueryPredicate;
|
|||
import org.hibernate.query.sqm.tree.predicate.SqmLikePredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmMemberOfPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmTruthnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||
|
||||
/**
|
||||
|
@ -260,6 +261,12 @@ public class ParameterCollector extends BaseSemanticQueryWalker {
|
|||
return predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitIsTruePredicate(SqmTruthnessPredicate predicate) {
|
||||
withTypeInference( null, () -> super.visitIsTruePredicate( predicate ) );
|
||||
return predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitComparisonPredicate(SqmComparisonPredicate predicate) {
|
||||
withTypeInference( predicate.getRightHandExpression(), () -> predicate.getLeftHandExpression().accept( this ) );
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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.query.sqm.tree.predicate;
|
||||
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
|
||||
/**
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class SqmTruthnessPredicate extends AbstractNegatableSqmPredicate {
|
||||
private final SqmExpression<?> expression;
|
||||
private final boolean value;
|
||||
|
||||
public SqmTruthnessPredicate(SqmExpression<?> expression, boolean value, boolean negated, NodeBuilder nodeBuilder) {
|
||||
super( negated, nodeBuilder );
|
||||
this.expression = expression;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean getBooleanValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmTruthnessPredicate copy(SqmCopyContext context) {
|
||||
final SqmTruthnessPredicate existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmTruthnessPredicate predicate = context.registerCopy(
|
||||
this,
|
||||
new SqmTruthnessPredicate(
|
||||
expression.copy( context ),
|
||||
getBooleanValue(),
|
||||
isNegated(),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( predicate, context );
|
||||
return predicate;
|
||||
}
|
||||
|
||||
public SqmExpression<?> getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(SemanticQueryWalker<T> walker) {
|
||||
return walker.visitIsTruePredicate( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHqlString(StringBuilder sb) {
|
||||
expression.appendHqlString( sb );
|
||||
sb.append(" is ");
|
||||
if ( isNegated() ) {
|
||||
sb.append( "not " );
|
||||
}
|
||||
sb.append( getBooleanValue() );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SqmNegatablePredicate createNegatedNode() {
|
||||
return new SqmTruthnessPredicate( expression, getBooleanValue(), !isNegated(), nodeBuilder() );
|
||||
}
|
||||
}
|
|
@ -62,6 +62,7 @@ import org.hibernate.sql.ast.tree.predicate.LikePredicate;
|
|||
import org.hibernate.sql.ast.tree.predicate.NegatedPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.NullnessPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.SelfRenderingPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.ThruthnessPredicate;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
|
@ -202,6 +203,8 @@ public interface SqlAstWalker {
|
|||
|
||||
void visitNullnessPredicate(NullnessPredicate nullnessPredicate);
|
||||
|
||||
void visitThruthnessPredicate(ThruthnessPredicate predicate);
|
||||
|
||||
void visitRelationalPredicate(ComparisonPredicate comparisonPredicate);
|
||||
|
||||
void visitSelfRenderingPredicate(SelfRenderingPredicate selfRenderingPredicate);
|
||||
|
|
|
@ -164,6 +164,7 @@ import org.hibernate.sql.ast.tree.predicate.NegatedPredicate;
|
|||
import org.hibernate.sql.ast.tree.predicate.NullnessPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.SelfRenderingPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.ThruthnessPredicate;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
|
@ -389,7 +390,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
/**
|
||||
* A lazy session implementation that is needed for rendering literals.
|
||||
* Usually, only the {@link WrapperOptions} interface is needed,
|
||||
* but for creating LOBs, it might be to have a full blown session.
|
||||
* but for creating LOBs, it might be to have a full-blown session.
|
||||
*/
|
||||
private static class LazySessionWrapperOptions extends AbstractDelegatingWrapperOptions {
|
||||
|
||||
|
@ -7369,13 +7370,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
@Override
|
||||
public void visitNullnessPredicate(NullnessPredicate nullnessPredicate) {
|
||||
final Expression expression = nullnessPredicate.getExpression();
|
||||
final String predicateValue;
|
||||
if ( nullnessPredicate.isNegated() ) {
|
||||
predicateValue = " is not null";
|
||||
}
|
||||
else {
|
||||
predicateValue = " is null";
|
||||
}
|
||||
final String predicateValue = nullnessPredicate.isNegated() ? " is not null" : " is null";
|
||||
final SqlTuple tuple;
|
||||
if ( ( tuple = SqlTupleContainer.getSqlTuple( expression ) ) != null ) {
|
||||
String separator = NO_SEPARATOR;
|
||||
|
@ -7408,6 +7403,37 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitThruthnessPredicate(ThruthnessPredicate thruthnessPredicate) {
|
||||
if ( dialect.supportsIsTrue() ) {
|
||||
thruthnessPredicate.getExpression().accept( this );
|
||||
appendSql(" is ");
|
||||
if ( thruthnessPredicate.isNegated() ) {
|
||||
appendSql("not ");
|
||||
}
|
||||
appendSql( thruthnessPredicate.getBooleanValue() );
|
||||
}
|
||||
else {
|
||||
String literalTrue = dialect.toBooleanValueString(true);
|
||||
String literalFalse = dialect.toBooleanValueString(false);
|
||||
appendSql("(case ");
|
||||
thruthnessPredicate.getExpression().accept(this);
|
||||
appendSql(" when ");
|
||||
appendSql(thruthnessPredicate.getBooleanValue() ? literalTrue : literalFalse);
|
||||
appendSql(" then ");
|
||||
appendSql(thruthnessPredicate.isNegated()? literalFalse : literalTrue);
|
||||
appendSql(" when ");
|
||||
appendSql(thruthnessPredicate.getBooleanValue() ? literalFalse : literalTrue);
|
||||
appendSql(" then ");
|
||||
appendSql(thruthnessPredicate.isNegated()? literalTrue : literalFalse);
|
||||
appendSql(" else ");
|
||||
appendSql(thruthnessPredicate.isNegated()? literalTrue : literalFalse);
|
||||
appendSql(" end = ");
|
||||
appendSql(literalTrue);
|
||||
appendSql(")");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitRelationalPredicate(ComparisonPredicate comparisonPredicate) {
|
||||
// todo (6.0) : do we want to allow multi-valued parameters in a relational predicate?
|
||||
|
|
|
@ -70,6 +70,7 @@ import org.hibernate.sql.ast.tree.predicate.NegatedPredicate;
|
|||
import org.hibernate.sql.ast.tree.predicate.NullnessPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.SelfRenderingPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.ThruthnessPredicate;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
|
@ -235,6 +236,11 @@ public class AbstractSqlAstWalker implements SqlAstWalker {
|
|||
nullnessPredicate.getExpression().accept( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitThruthnessPredicate(ThruthnessPredicate thruthnessPredicate) {
|
||||
thruthnessPredicate.getExpression().accept( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitRelationalPredicate(ComparisonPredicate comparisonPredicate) {
|
||||
comparisonPredicate.getLeftHandExpression().accept( this );
|
||||
|
|
|
@ -68,6 +68,7 @@ import org.hibernate.sql.ast.tree.predicate.NegatedPredicate;
|
|||
import org.hibernate.sql.ast.tree.predicate.NullnessPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.SelfRenderingPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.ThruthnessPredicate;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
|
@ -441,6 +442,22 @@ public class ExpressionReplacementWalker implements SqlAstWalker {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitThruthnessPredicate(ThruthnessPredicate thruthnessPredicate) {
|
||||
final Expression expression = replaceExpression( thruthnessPredicate.getExpression() );
|
||||
if ( expression != thruthnessPredicate.getExpression() ) {
|
||||
returnedNode = new ThruthnessPredicate(
|
||||
expression,
|
||||
thruthnessPredicate.getBooleanValue(),
|
||||
thruthnessPredicate.isNegated(),
|
||||
thruthnessPredicate.getExpressionType()
|
||||
);
|
||||
}
|
||||
else {
|
||||
returnedNode = thruthnessPredicate;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitRelationalPredicate(ComparisonPredicate comparisonPredicate) {
|
||||
final Expression lhs = replaceExpression( comparisonPredicate.getLeftHandExpression() );
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.metamodel.mapping.JdbcMappingContainer;
|
||||
import org.hibernate.sql.ast.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
|
||||
/**
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class ThruthnessPredicate extends AbstractPredicate {
|
||||
private final Expression expression;
|
||||
private final boolean value;
|
||||
|
||||
public ThruthnessPredicate(Expression expression, boolean value, boolean negated, JdbcMappingContainer expressionType) {
|
||||
super( expressionType, negated );
|
||||
this.expression = expression;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean getBooleanValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Expression getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(SqlAstWalker sqlTreeWalker) {
|
||||
sqlTreeWalker.visitThruthnessPredicate( this );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package org.hibernate.orm.test.hql;
|
||||
|
||||
import org.hibernate.dialect.DerbyDialect;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.SkipForDialect;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@SessionFactory
|
||||
@DomainModel
|
||||
public class BooleanPredicateTest {
|
||||
@Test void test(SessionFactoryScope scope) {
|
||||
scope.inSession(session -> {
|
||||
assertEquals(1, session.createSelectionQuery("select 1 where true is true").getResultList().size());
|
||||
assertEquals(0, session.createSelectionQuery("select 1 where false is true").getResultList().size());
|
||||
assertEquals(0, session.createSelectionQuery("select 1 where true is not true").getResultList().size());
|
||||
assertEquals(1, session.createSelectionQuery("select 1 where false is not true").getResultList().size());
|
||||
|
||||
assertEquals(0, session.createSelectionQuery("select 1 where true is false").getResultList().size());
|
||||
assertEquals(1, session.createSelectionQuery("select 1 where false is false").getResultList().size());
|
||||
assertEquals(1, session.createSelectionQuery("select 1 where true is not false").getResultList().size());
|
||||
assertEquals(0, session.createSelectionQuery("select 1 where false is not false").getResultList().size());
|
||||
});
|
||||
}
|
||||
|
||||
@SkipForDialect(dialectClass = DerbyDialect.class, reason = "Derby doesn't accept literal null in case")
|
||||
@Test void testNulls(SessionFactoryScope scope) {
|
||||
scope.inSession(session -> {
|
||||
assertEquals(1, session.createSelectionQuery("select 1 where true is true").getResultList().size());
|
||||
assertEquals(0, session.createSelectionQuery("select 1 where false is true").getResultList().size());
|
||||
assertEquals(0, session.createSelectionQuery("select 1 where null is true").getResultList().size());
|
||||
assertEquals(0, session.createSelectionQuery("select 1 where true is not true").getResultList().size());
|
||||
assertEquals(1, session.createSelectionQuery("select 1 where false is not true").getResultList().size());
|
||||
assertEquals(1, session.createSelectionQuery("select 1 where null is not true").getResultList().size());
|
||||
|
||||
assertEquals(0, session.createSelectionQuery("select 1 where true is false").getResultList().size());
|
||||
assertEquals(1, session.createSelectionQuery("select 1 where false is false").getResultList().size());
|
||||
assertEquals(0, session.createSelectionQuery("select 1 where null is false").getResultList().size());
|
||||
assertEquals(1, session.createSelectionQuery("select 1 where true is not false").getResultList().size());
|
||||
assertEquals(0, session.createSelectionQuery("select 1 where false is not false").getResultList().size());
|
||||
assertEquals(1, session.createSelectionQuery("select 1 where null is not false").getResultList().size());
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue