Fix rendering of negated boolean expression predicate
This commit is contained in:
parent
96931d8094
commit
b9d4a74693
|
@ -54,7 +54,14 @@ public class FirebirdSqlAstTranslator<T extends JdbcOperation> extends AbstractS
|
|||
@Override
|
||||
public void visitBooleanExpressionPredicate(BooleanExpressionPredicate booleanExpressionPredicate) {
|
||||
if ( getDialect().getVersion().isSameOrAfter( 3 ) ) {
|
||||
final boolean isNegated = booleanExpressionPredicate.isNegated();
|
||||
if ( isNegated ) {
|
||||
appendSql( "not(" );
|
||||
}
|
||||
booleanExpressionPredicate.getExpression().accept( this );
|
||||
if ( isNegated ) {
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
}
|
||||
else {
|
||||
super.visitBooleanExpressionPredicate( booleanExpressionPredicate );
|
||||
|
|
|
@ -37,7 +37,19 @@ public class CockroachSqlAstTranslator<T extends JdbcOperation> extends Abstract
|
|||
|
||||
@Override
|
||||
public void visitBooleanExpressionPredicate(BooleanExpressionPredicate booleanExpressionPredicate) {
|
||||
if ( booleanExpressionPredicate.isNegated() ) {
|
||||
super.visitBooleanExpressionPredicate( booleanExpressionPredicate );
|
||||
}
|
||||
else {
|
||||
final boolean isNegated = booleanExpressionPredicate.isNegated();
|
||||
if ( isNegated ) {
|
||||
appendSql( "not(" );
|
||||
}
|
||||
booleanExpressionPredicate.getExpression().accept( this );
|
||||
if ( isNegated ) {
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -52,7 +52,14 @@ public class DB2SqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAst
|
|||
@Override
|
||||
public void visitBooleanExpressionPredicate(BooleanExpressionPredicate booleanExpressionPredicate) {
|
||||
if ( getDB2Version().isSameOrAfter( 11 ) ) {
|
||||
final boolean isNegated = booleanExpressionPredicate.isNegated();
|
||||
if ( isNegated ) {
|
||||
appendSql( "not(" );
|
||||
}
|
||||
booleanExpressionPredicate.getExpression().accept( this );
|
||||
if ( isNegated ) {
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
}
|
||||
else {
|
||||
super.visitBooleanExpressionPredicate( booleanExpressionPredicate );
|
||||
|
|
|
@ -48,7 +48,14 @@ public class DerbySqlAstTranslator<T extends JdbcOperation> extends AbstractSqlA
|
|||
|
||||
@Override
|
||||
public void visitBooleanExpressionPredicate(BooleanExpressionPredicate booleanExpressionPredicate) {
|
||||
final boolean isNegated = booleanExpressionPredicate.isNegated();
|
||||
if ( isNegated ) {
|
||||
appendSql( "not(" );
|
||||
}
|
||||
booleanExpressionPredicate.getExpression().accept( this );
|
||||
if ( isNegated ) {
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
}
|
||||
|
||||
// Derby does not allow CASE expressions where all result arms contain plain parameters.
|
||||
|
|
|
@ -47,7 +47,14 @@ public class H2SqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstT
|
|||
|
||||
@Override
|
||||
public void visitBooleanExpressionPredicate(BooleanExpressionPredicate booleanExpressionPredicate) {
|
||||
final boolean isNegated = booleanExpressionPredicate.isNegated();
|
||||
if ( isNegated ) {
|
||||
appendSql( "not(" );
|
||||
}
|
||||
booleanExpressionPredicate.getExpression().accept( this );
|
||||
if ( isNegated ) {
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -47,7 +47,14 @@ public class HSQLSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAs
|
|||
|
||||
@Override
|
||||
public void visitBooleanExpressionPredicate(BooleanExpressionPredicate booleanExpressionPredicate) {
|
||||
final boolean isNegated = booleanExpressionPredicate.isNegated();
|
||||
if ( isNegated ) {
|
||||
appendSql( "not(" );
|
||||
}
|
||||
booleanExpressionPredicate.getExpression().accept( this );
|
||||
if ( isNegated ) {
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
}
|
||||
|
||||
// HSQL does not allow CASE expressions where all result arms contain plain parameters.
|
||||
|
|
|
@ -39,7 +39,14 @@ public class MariaDBSqlAstTranslator<T extends JdbcOperation> extends AbstractSq
|
|||
|
||||
@Override
|
||||
public void visitBooleanExpressionPredicate(BooleanExpressionPredicate booleanExpressionPredicate) {
|
||||
final boolean isNegated = booleanExpressionPredicate.isNegated();
|
||||
if ( isNegated ) {
|
||||
appendSql( "not(" );
|
||||
}
|
||||
booleanExpressionPredicate.getExpression().accept( this );
|
||||
if ( isNegated ) {
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -40,7 +40,14 @@ public class MySQLSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlA
|
|||
|
||||
@Override
|
||||
public void visitBooleanExpressionPredicate(BooleanExpressionPredicate booleanExpressionPredicate) {
|
||||
final boolean isNegated = booleanExpressionPredicate.isNegated();
|
||||
if ( isNegated ) {
|
||||
appendSql( "not(" );
|
||||
}
|
||||
booleanExpressionPredicate.getExpression().accept( this );
|
||||
if ( isNegated ) {
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -40,7 +40,14 @@ public class PostgreSQLSqlAstTranslator<T extends JdbcOperation> extends Abstrac
|
|||
|
||||
@Override
|
||||
public void visitBooleanExpressionPredicate(BooleanExpressionPredicate booleanExpressionPredicate) {
|
||||
final boolean isNegated = booleanExpressionPredicate.isNegated();
|
||||
if ( isNegated ) {
|
||||
appendSql( "not(" );
|
||||
}
|
||||
booleanExpressionPredicate.getExpression().accept( this );
|
||||
if ( isNegated ) {
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -40,7 +40,14 @@ public class TiDBSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAs
|
|||
|
||||
@Override
|
||||
public void visitBooleanExpressionPredicate(BooleanExpressionPredicate booleanExpressionPredicate) {
|
||||
final boolean isNegated = booleanExpressionPredicate.isNegated();
|
||||
if ( isNegated ) {
|
||||
appendSql( "not(" );
|
||||
}
|
||||
booleanExpressionPredicate.getExpression().accept( this );
|
||||
if ( isNegated ) {
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean shouldEmulateFetchClause(QueryPart queryPart) {
|
||||
|
|
|
@ -13,6 +13,7 @@ import jakarta.persistence.criteria.Expression;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.sql.ast.tree.predicate.NegatedPredicate;
|
||||
|
||||
/**
|
||||
* Represents an expression whose type is boolean, and can therefore be used as a predicate.
|
||||
|
|
|
@ -4630,8 +4630,14 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
// Most databases do not support boolean expressions in a predicate context, so we render `expr=true`
|
||||
booleanExpressionPredicate.getExpression().accept( this );
|
||||
appendSql( '=' );
|
||||
if ( booleanExpressionPredicate.isNegated() ) {
|
||||
getDialect().appendBooleanValueString( this, false );
|
||||
|
||||
}
|
||||
else {
|
||||
getDialect().appendBooleanValueString( this, true );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBetweenPredicate(BetweenPredicate betweenPredicate) {
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* 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.orm.test.jpa.compliance;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.Jpa;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.OneToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@Jpa(
|
||||
annotatedClasses = {
|
||||
CriteriaIsFalseTest.Person.class,
|
||||
CriteriaIsFalseTest.Address.class
|
||||
}
|
||||
)
|
||||
public class CriteriaIsFalseTest {
|
||||
|
||||
@Test
|
||||
public void testIsFalse(EntityManagerFactoryScope scope) {
|
||||
|
||||
Address validAddress = new Address( 1, "Lollard street London", true );
|
||||
Address invalidAddress = new Address( 2, "Oxfort street London", false );
|
||||
Person personWithValidAddress = new Person( 1, "Luigi", validAddress );
|
||||
Person personWithInvalidAddredd = new Person( 2, "Andrea", invalidAddress );
|
||||
|
||||
scope.inTransaction(
|
||||
entityManager -> {
|
||||
entityManager.persist( validAddress );
|
||||
entityManager.persist( invalidAddress );
|
||||
entityManager.persist( personWithValidAddress );
|
||||
entityManager.persist( personWithInvalidAddredd );
|
||||
}
|
||||
);
|
||||
|
||||
scope.inEntityManager(
|
||||
entityManager -> {
|
||||
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
|
||||
|
||||
final CriteriaQuery<Integer> query = criteriaBuilder.createQuery( Integer.class );
|
||||
final Root<Person> personRoot = query.from( Person.class );
|
||||
query.select( personRoot.get( "id" ) );
|
||||
query.where( criteriaBuilder.isFalse( personRoot.get( "address" ).get( "valid" ) ) );
|
||||
|
||||
final List<Integer> ids = entityManager.createQuery( query ).getResultList();
|
||||
|
||||
assertEquals( 1, ids.size() );
|
||||
assertEquals( personWithInvalidAddredd.getId(), ids.get( 0 ) );
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "Person")
|
||||
@Table(name = "PERSON_TABLE")
|
||||
public static class Person {
|
||||
@Id
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
|
||||
@OneToOne
|
||||
private Address address;
|
||||
|
||||
public Person() {
|
||||
}
|
||||
|
||||
public Person(Integer id, String name, Address address) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Address getAddress() {
|
||||
return address;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Address")
|
||||
@Table(name = "ADDRESS_TABLE")
|
||||
public static class Address {
|
||||
|
||||
@Id
|
||||
private Integer id;
|
||||
|
||||
private String street;
|
||||
|
||||
private boolean valid;
|
||||
|
||||
public Address() {
|
||||
}
|
||||
|
||||
public Address(Integer id, String street, boolean valid) {
|
||||
this.id = id;
|
||||
this.street = street;
|
||||
this.valid = valid;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue