HHH-8699 - Multiselect with boolean predicate
This commit is contained in:
parent
aab9112f37
commit
553f65a360
|
@ -409,6 +409,7 @@ selectExpr
|
|||
| collectionFunction // elements() or indices()
|
||||
| literal
|
||||
| arithmeticExpr
|
||||
| logicalExpr
|
||||
| parameter
|
||||
| query
|
||||
;
|
||||
|
|
|
@ -246,6 +246,7 @@ selectExpr
|
|||
| aggregate
|
||||
| c:constant { out(c); }
|
||||
| arithmeticExpr
|
||||
| selectBooleanExpr[false]
|
||||
| parameter
|
||||
| sn:SQL_NODE { out(sn); }
|
||||
| { out("("); } selectStatement { out(")"); }
|
||||
|
@ -306,6 +307,11 @@ booleanOp[ boolean parens ]
|
|||
| #(NOT { out(" not ("); } booleanExpr[false] { out(")"); } )
|
||||
;
|
||||
|
||||
selectBooleanExpr[ boolean parens ]
|
||||
: booleanOp [ parens ]
|
||||
| comparisonExpr [ parens ]
|
||||
;
|
||||
|
||||
booleanExpr[ boolean parens ]
|
||||
: booleanOp [ parens ]
|
||||
| comparisonExpr [ parens ]
|
||||
|
@ -387,6 +393,7 @@ simpleExpr
|
|||
| count
|
||||
| parameter
|
||||
| arithmeticExpr
|
||||
| selectBooleanExpr[false]
|
||||
;
|
||||
|
||||
constant
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.TypeMismatchException;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes;
|
||||
import org.hibernate.hql.internal.ast.util.ColumnHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.param.ParameterSpecification;
|
||||
import org.hibernate.type.OneToOneType;
|
||||
|
@ -43,7 +44,7 @@ import antlr.collections.AST;
|
|||
*
|
||||
* @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
|
||||
* nodes and setting their expected type, if possible.
|
||||
|
@ -268,4 +269,8 @@ public class BinaryLogicOperatorNode extends HqlSqlWalkerNode implements BinaryO
|
|||
public Node getRightHandOperand() {
|
||||
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;
|
||||
|
||||
import antlr.SemanticException;
|
||||
|
||||
import org.hibernate.hql.internal.ast.util.ColumnHelper;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
|
@ -31,7 +34,7 @@ import org.hibernate.type.Type;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class UnaryLogicOperatorNode extends HqlSqlWalkerNode implements UnaryOperatorNode {
|
||||
public class UnaryLogicOperatorNode extends AbstractSelectExpression implements UnaryOperatorNode {
|
||||
public Node getOperand() {
|
||||
return (Node) getFirstChild();
|
||||
}
|
||||
|
@ -45,4 +48,8 @@ public class UnaryLogicOperatorNode extends HqlSqlWalkerNode implements UnaryOpe
|
|||
// logic operators by definition resolve to booleans
|
||||
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/ComponentContainer.hbm.xml",
|
||||
"hql/VariousKeywordPropertyEntity.hbm.xml",
|
||||
"hql/Constructor.hbm.xml",
|
||||
"batchfetch/ProductLine.hbm.xml",
|
||||
"cid/Customer.hbm.xml",
|
||||
"cid/Order.hbm.xml",
|
||||
|
@ -212,6 +213,31 @@ public class ASTParserLoadingTest extends BaseCoreFunctionalTestCase {
|
|||
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
|
||||
public void testJpaTypeOperator() {
|
||||
// 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.BaseEntityManagerFunctionalTestCase;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
|
@ -214,6 +216,26 @@ public class QueryBuilderTest extends BaseEntityManagerFunctionalTestCase {
|
|||
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
|
||||
public void testDateTimeFunctions() {
|
||||
EntityManager em = getOrCreateEntityManager();
|
||||
|
|
|
@ -62,6 +62,12 @@ public class Customer implements java.io.Serializable {
|
|||
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) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
|
|
Loading…
Reference in New Issue