HHH-8699 - Multiselect with boolean predicate
This commit is contained in:
parent
aab9112f37
commit
553f65a360
|
@ -409,6 +409,7 @@ selectExpr
|
||||||
| collectionFunction // elements() or indices()
|
| collectionFunction // elements() or indices()
|
||||||
| literal
|
| literal
|
||||||
| arithmeticExpr
|
| arithmeticExpr
|
||||||
|
| logicalExpr
|
||||||
| parameter
|
| parameter
|
||||||
| query
|
| query
|
||||||
;
|
;
|
||||||
|
|
|
@ -246,6 +246,7 @@ selectExpr
|
||||||
| aggregate
|
| aggregate
|
||||||
| c:constant { out(c); }
|
| c:constant { out(c); }
|
||||||
| arithmeticExpr
|
| arithmeticExpr
|
||||||
|
| selectBooleanExpr[false]
|
||||||
| parameter
|
| parameter
|
||||||
| sn:SQL_NODE { out(sn); }
|
| sn:SQL_NODE { out(sn); }
|
||||||
| { out("("); } selectStatement { out(")"); }
|
| { out("("); } selectStatement { out(")"); }
|
||||||
|
@ -306,6 +307,11 @@ booleanOp[ boolean parens ]
|
||||||
| #(NOT { out(" not ("); } booleanExpr[false] { out(")"); } )
|
| #(NOT { out(" not ("); } booleanExpr[false] { out(")"); } )
|
||||||
;
|
;
|
||||||
|
|
||||||
|
selectBooleanExpr[ boolean parens ]
|
||||||
|
: booleanOp [ parens ]
|
||||||
|
| comparisonExpr [ parens ]
|
||||||
|
;
|
||||||
|
|
||||||
booleanExpr[ boolean parens ]
|
booleanExpr[ boolean parens ]
|
||||||
: booleanOp [ parens ]
|
: booleanOp [ parens ]
|
||||||
| comparisonExpr [ parens ]
|
| comparisonExpr [ parens ]
|
||||||
|
@ -387,6 +393,7 @@ simpleExpr
|
||||||
| count
|
| count
|
||||||
| parameter
|
| parameter
|
||||||
| arithmeticExpr
|
| arithmeticExpr
|
||||||
|
| selectBooleanExpr[false]
|
||||||
;
|
;
|
||||||
|
|
||||||
constant
|
constant
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.hibernate.HibernateException;
|
||||||
import org.hibernate.TypeMismatchException;
|
import org.hibernate.TypeMismatchException;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes;
|
import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes;
|
||||||
|
import org.hibernate.hql.internal.ast.util.ColumnHelper;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.param.ParameterSpecification;
|
import org.hibernate.param.ParameterSpecification;
|
||||||
import org.hibernate.type.OneToOneType;
|
import org.hibernate.type.OneToOneType;
|
||||||
|
@ -43,7 +44,7 @@ import antlr.collections.AST;
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class BinaryLogicOperatorNode extends HqlSqlWalkerNode implements BinaryOperatorNode {
|
public class BinaryLogicOperatorNode extends AbstractSelectExpression implements BinaryOperatorNode {
|
||||||
/**
|
/**
|
||||||
* Performs the operator node initialization by seeking out any parameter
|
* Performs the operator node initialization by seeking out any parameter
|
||||||
* nodes and setting their expected type, if possible.
|
* nodes and setting their expected type, if possible.
|
||||||
|
@ -268,4 +269,8 @@ public class BinaryLogicOperatorNode extends HqlSqlWalkerNode implements BinaryO
|
||||||
public Node getRightHandOperand() {
|
public Node getRightHandOperand() {
|
||||||
return (Node) getFirstChild().getNextSibling();
|
return (Node) getFirstChild().getNextSibling();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setScalarColumnText(int i) throws SemanticException {
|
||||||
|
ColumnHelper.generateSingleScalarColumn( this, i );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.hql.internal.ast.tree;
|
package org.hibernate.hql.internal.ast.tree;
|
||||||
|
|
||||||
|
import antlr.SemanticException;
|
||||||
|
|
||||||
|
import org.hibernate.hql.internal.ast.util.ColumnHelper;
|
||||||
import org.hibernate.type.StandardBasicTypes;
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
@ -31,7 +34,7 @@ import org.hibernate.type.Type;
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class UnaryLogicOperatorNode extends HqlSqlWalkerNode implements UnaryOperatorNode {
|
public class UnaryLogicOperatorNode extends AbstractSelectExpression implements UnaryOperatorNode {
|
||||||
public Node getOperand() {
|
public Node getOperand() {
|
||||||
return (Node) getFirstChild();
|
return (Node) getFirstChild();
|
||||||
}
|
}
|
||||||
|
@ -45,4 +48,8 @@ public class UnaryLogicOperatorNode extends HqlSqlWalkerNode implements UnaryOpe
|
||||||
// logic operators by definition resolve to booleans
|
// logic operators by definition resolve to booleans
|
||||||
return StandardBasicTypes.BOOLEAN;
|
return StandardBasicTypes.BOOLEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setScalarColumnText(int i) throws SemanticException {
|
||||||
|
ColumnHelper.generateSingleScalarColumn( this, i );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,6 +133,7 @@ public class ASTParserLoadingTest extends BaseCoreFunctionalTestCase {
|
||||||
"hql/Image.hbm.xml",
|
"hql/Image.hbm.xml",
|
||||||
"hql/ComponentContainer.hbm.xml",
|
"hql/ComponentContainer.hbm.xml",
|
||||||
"hql/VariousKeywordPropertyEntity.hbm.xml",
|
"hql/VariousKeywordPropertyEntity.hbm.xml",
|
||||||
|
"hql/Constructor.hbm.xml",
|
||||||
"batchfetch/ProductLine.hbm.xml",
|
"batchfetch/ProductLine.hbm.xml",
|
||||||
"cid/Customer.hbm.xml",
|
"cid/Customer.hbm.xml",
|
||||||
"cid/Order.hbm.xml",
|
"cid/Order.hbm.xml",
|
||||||
|
@ -212,6 +213,31 @@ public class ASTParserLoadingTest extends BaseCoreFunctionalTestCase {
|
||||||
session.close();
|
session.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue( jiraKey = "HHH-8699" )
|
||||||
|
public void testBooleanPredicate() {
|
||||||
|
final Session session = openSession();
|
||||||
|
|
||||||
|
session.getTransaction().begin();
|
||||||
|
final Constructor constructor = new Constructor();
|
||||||
|
session.save( constructor );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
|
||||||
|
session.clear();
|
||||||
|
Constructor.resetConstructorExecutionCount();
|
||||||
|
|
||||||
|
session.getTransaction().begin();
|
||||||
|
final Constructor result = (Constructor) session.createQuery(
|
||||||
|
"select new Constructor( c.id, c.id is not null, c.id = c.id, c.id + 1, concat( c.id, 'foo' ) ) from Constructor c where c.id = :id"
|
||||||
|
).setParameter( "id", constructor.getId() ).uniqueResult();
|
||||||
|
session.getTransaction().commit();
|
||||||
|
|
||||||
|
assertEquals( 1, Constructor.getConstructorExecutionCount() );
|
||||||
|
assertEquals( new Constructor( constructor.getId(), true, true, constructor.getId() + 1, constructor.getId() + "foo" ), result );
|
||||||
|
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testJpaTypeOperator() {
|
public void testJpaTypeOperator() {
|
||||||
// just checking syntax here...
|
// just checking syntax here...
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE hibernate-mapping PUBLIC
|
||||||
|
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||||
|
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||||
|
<hibernate-mapping package="org.hibernate.test.hql">
|
||||||
|
<class name="Constructor">
|
||||||
|
<id name="id" column="ID" type="long">
|
||||||
|
<generator class="increment"/>
|
||||||
|
</id>
|
||||||
|
<property name="someString" type="string"/>
|
||||||
|
<property name="someNumber" type="int"/>
|
||||||
|
<property name="someBoolean" type="boolean"/>
|
||||||
|
<property name="anotherBoolean" type="boolean"/>
|
||||||
|
</class>
|
||||||
|
</hibernate-mapping>
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.hql;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
*/
|
||||||
|
public class Constructor implements Serializable {
|
||||||
|
private static int CONSTRUCTOR_EXECUTION_COUNT = 0;
|
||||||
|
|
||||||
|
private long id;
|
||||||
|
private String someString;
|
||||||
|
private Number someNumber;
|
||||||
|
private boolean someBoolean;
|
||||||
|
private boolean anotherBoolean;
|
||||||
|
|
||||||
|
public Constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Constructor(long id, boolean someBoolean, boolean anotherBoolean, Number someNumber, String someString) {
|
||||||
|
this.id = id;
|
||||||
|
this.someBoolean = someBoolean;
|
||||||
|
this.anotherBoolean = anotherBoolean;
|
||||||
|
this.someNumber = someNumber;
|
||||||
|
this.someString = someString;
|
||||||
|
++CONSTRUCTOR_EXECUTION_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if ( this == o ) return true;
|
||||||
|
if ( !( o instanceof Constructor ) ) return false;
|
||||||
|
|
||||||
|
Constructor that = (Constructor) o;
|
||||||
|
|
||||||
|
if ( anotherBoolean != that.anotherBoolean ) return false;
|
||||||
|
if ( id != that.id ) return false;
|
||||||
|
if ( someBoolean != that.someBoolean ) return false;
|
||||||
|
if ( someNumber != null ? !someNumber.equals( that.someNumber ) : that.someNumber != null ) return false;
|
||||||
|
if ( someString != null ? !someString.equals( that.someString ) : that.someString != null ) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = (int) (id ^ (id >>> 32));
|
||||||
|
result = 31 * result + (someString != null ? someString.hashCode() : 0);
|
||||||
|
result = 31 * result + (someNumber != null ? someNumber.hashCode() : 0);
|
||||||
|
result = 31 * result + (someBoolean ? 1 : 0);
|
||||||
|
result = 31 * result + (anotherBoolean ? 1 : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSomeBoolean() {
|
||||||
|
return someBoolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSomeBoolean(boolean someBoolean) {
|
||||||
|
this.someBoolean = someBoolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Number getSomeNumber() {
|
||||||
|
return someNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSomeNumber(Number someNumber) {
|
||||||
|
this.someNumber = someNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSomeString() {
|
||||||
|
return someString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSomeString(String someString) {
|
||||||
|
this.someString = someString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAnotherBoolean() {
|
||||||
|
return anotherBoolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAnotherBoolean(boolean anotherBoolean) {
|
||||||
|
this.anotherBoolean = anotherBoolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getConstructorExecutionCount() {
|
||||||
|
return CONSTRUCTOR_EXECUTION_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetConstructorExecutionCount() {
|
||||||
|
CONSTRUCTOR_EXECUTION_COUNT = 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -52,6 +52,8 @@ import org.hibernate.jpa.test.metamodel.ShelfLife;
|
||||||
import org.hibernate.jpa.test.metamodel.Spouse;
|
import org.hibernate.jpa.test.metamodel.Spouse;
|
||||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -214,6 +216,26 @@ public class QueryBuilderTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
em.close();
|
em.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue( jiraKey = "HHH-8699" )
|
||||||
|
public void testMultiselectWithPredicates() {
|
||||||
|
EntityManager em = getOrCreateEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
CriteriaBuilderImpl cb = (CriteriaBuilderImpl) em.getCriteriaBuilder();
|
||||||
|
CriteriaQuery<Customer> cq = cb.createQuery( Customer.class );
|
||||||
|
Root<Customer> r = cq.from( Customer.class );
|
||||||
|
cq.multiselect(
|
||||||
|
r.get( Customer_.id ), r.get( Customer_.name ),
|
||||||
|
cb.concat( "Hello ", r.get( Customer_.name ) ), cb.isNotNull( r.get( Customer_.age ) )
|
||||||
|
);
|
||||||
|
TypedQuery<Customer> tq = em.createQuery( cq );
|
||||||
|
tq.getResultList();
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDateTimeFunctions() {
|
public void testDateTimeFunctions() {
|
||||||
EntityManager em = getOrCreateEntityManager();
|
EntityManager em = getOrCreateEntityManager();
|
||||||
|
|
|
@ -62,6 +62,12 @@ public class Customer implements java.io.Serializable {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used by test case for HHH-8699.
|
||||||
|
public Customer(String id, String name, String greeting, Boolean something) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
public Customer(String id, String name, Country country) {
|
public Customer(String id, String name, Country country) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
Loading…
Reference in New Issue