diff --git a/hibernate-core/src/main/antlr/hql-sql.g b/hibernate-core/src/main/antlr/hql-sql.g index 7fecd6ef12..4a9ddde079 100644 --- a/hibernate-core/src/main/antlr/hql-sql.g +++ b/hibernate-core/src/main/antlr/hql-sql.g @@ -409,7 +409,7 @@ selectExpr | functionCall | count | collectionFunction // elements() or indices() - | literal + | constant | arithmeticExpr | logicalExpr | query diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/ejb/criteria/nulliteral/CriteriaLiteralInSelectExpressionTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/criteria/nulliteral/CriteriaLiteralInSelectExpressionTest.java new file mode 100644 index 0000000000..a9f7094d8d --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/criteria/nulliteral/CriteriaLiteralInSelectExpressionTest.java @@ -0,0 +1,304 @@ +/* + * 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 . + */ +package org.hibernate.ejb.criteria.nulliteral; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EntityManager; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Tuple; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; +import java.io.Serializable; +import java.util.List; + +import org.hibernate.ejb.test.BaseEntityManagerFunctionalTestCase; + +import org.junit.Before; +import org.junit.Test; + +import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.TestForIssue; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; + +/** + * @author Andrea Boriero + */ +public class CriteriaLiteralInSelectExpressionTest extends BaseEntityManagerFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] {MyEntity.class}; + } + + @Before + public void init() throws Exception { + final EntityManager entityManager = getOrCreateEntityManager(); + try { + entityManager.getTransaction().begin(); + entityManager.persist( new MyEntity( "Fab", "A" ) ); + entityManager.getTransaction().commit(); + } + catch (Exception e) { + if ( entityManager.getTransaction().isActive() ) { + entityManager.getTransaction().rollback(); + } + throw e; + } + finally { + entityManager.close(); + } + } + + @Test + @TestForIssue(jiraKey = "HHH-10729") + @FailureExpected(jiraKey = "HHH-10729") + public void testBooleanLiteral() throws Exception { + final EntityManager entityManager = getOrCreateEntityManager(); + try { + entityManager.getTransaction().begin(); + + final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + final CriteriaQuery query = criteriaBuilder.createQuery( MyEntityDTO.class ); + final Root entity = query.from( MyEntity.class ); + + query.multiselect( criteriaBuilder.literal( false ), entity.get( "name" ) ); + + final List dtos = entityManager.createQuery( query ).getResultList(); + + assertThat( dtos.size(), is( 1 ) ); + assertThat( dtos.get( 0 ).active, is( false ) ); + assertThat( dtos.get( 0 ).name, is( "Fab" ) ); + assertThat( dtos.get( 0 ).surname, nullValue() ); + + entityManager.getTransaction().commit(); + } + catch (Exception e) { + if ( entityManager.getTransaction().isActive() ) { + entityManager.getTransaction().rollback(); + } + throw e; + } + finally { + entityManager.close(); + } + } + + @Test + @TestForIssue(jiraKey = "HHH-10861") + @FailureExpected(jiraKey = "HHH-10861") + public void testNullLiteral() throws Exception { + final EntityManager entityManager = getOrCreateEntityManager(); + try { + entityManager.getTransaction().begin(); + + final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + final CriteriaQuery query = criteriaBuilder.createQuery( MyEntityDTO.class ); + final Root entity = query.from( MyEntity.class ); + + query.multiselect( criteriaBuilder.literal( false ), criteriaBuilder.nullLiteral( String.class ) ); + + final List dtos = entityManager.createQuery( query ).getResultList(); + + assertThat( dtos.size(), is( 1 ) ); + assertThat( dtos.get( 0 ).active, is( false ) ); + assertThat( dtos.get( 0 ).name, nullValue() ); + assertThat( dtos.get( 0 ).surname, nullValue() ); + + entityManager.getTransaction().commit(); + } + catch (Exception e) { + if ( entityManager.getTransaction().isActive() ) { + entityManager.getTransaction().rollback(); + } + throw e; + } + finally { + entityManager.close(); + } + } + + @Test + @TestForIssue(jiraKey = "HHH-10861") + @FailureExpected(jiraKey = "HHH-10861") + public void testNullLiteralFirst() throws Exception { + final EntityManager entityManager = getOrCreateEntityManager(); + try { + entityManager.getTransaction().begin(); + + final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + final CriteriaQuery query = criteriaBuilder.createQuery( MyEntityDTO.class ); + final Root entity = query.from( MyEntity.class ); + + query.multiselect( criteriaBuilder.nullLiteral( String.class ), entity.get( "surname" ) ); + + final List dtos = entityManager.createQuery( query ).getResultList(); + + assertThat( dtos.size(), is( 1 ) ); + assertThat( dtos.get( 0 ).name, nullValue() ); + assertThat( dtos.get( 0 ).surname, is( "A" ) ); + assertThat( dtos.get( 0 ).active, is( false ) ); + + entityManager.getTransaction().commit(); + } + catch (Exception e) { + if ( entityManager.getTransaction().isActive() ) { + entityManager.getTransaction().rollback(); + } + throw e; + } + finally { + entityManager.close(); + } + } + + @Test + @TestForIssue(jiraKey = "HHH-10729") + public void testStringLiteral() throws Exception { + final EntityManager entityManager = getOrCreateEntityManager(); + try { + entityManager.getTransaction().begin(); + + final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + final CriteriaQuery query = criteriaBuilder.createQuery( MyEntityDTO.class ); + final Root entity = query.from( MyEntity.class ); + + query.multiselect( criteriaBuilder.literal( "Leo" ), entity.get( "surname" ) ); + + final List dtos = entityManager.createQuery( query ).getResultList(); + + assertThat( dtos.size(), is( 1 ) ); + assertThat( dtos.get( 0 ).name, is( "Leo" ) ); + assertThat( dtos.get( 0 ).surname, is( "A" ) ); + assertThat( dtos.get( 0 ).active, is( false ) ); + + entityManager.getTransaction().commit(); + } + catch (Exception e) { + if ( entityManager.getTransaction().isActive() ) { + entityManager.getTransaction().rollback(); + } + throw e; + } + finally { + entityManager.close(); + } + } + + @Test + @TestForIssue(jiraKey = "HHH-9021") + public void testStringLiteral2() { + final EntityManager entityManager = getOrCreateEntityManager(); + try { + final CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = builder.createQuery( Tuple.class ); + criteriaQuery.from( MyEntity.class ); + criteriaQuery.multiselect( builder.equal( builder.literal( 1 ), builder.literal( 2 ) ) ); + + final TypedQuery typedQuery = entityManager.createQuery( criteriaQuery ); + + final List results = typedQuery.getResultList(); + + assertThat( results.size(), is( 1 ) ); + assertThat( results.get( 0 ).getElements().size(), is( 1 ) ); + assertThat( ( (Boolean) results.get( 0 ).get( 0 ) ), is( false ) ); + } + finally { + entityManager.close(); + } + } + + @Test + @TestForIssue(jiraKey = "HHH-9021") + public void testIntegerLiteral() throws Exception { + final EntityManager entityManager = getOrCreateEntityManager(); + try { + entityManager.getTransaction().begin(); + + final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + final CriteriaQuery query = criteriaBuilder.createQuery( MyEntityDTO.class ); + final Root entity = query.from( MyEntity.class ); + + query.multiselect( criteriaBuilder.literal( 1 ), entity.get( "surname" ) ); + + final List dtos = entityManager.createQuery( query ).getResultList(); + + assertThat( dtos.size(), is( 1 ) ); + assertThat( dtos.get( 0 ).age, is( 1 ) ); + assertThat( dtos.get( 0 ).surname, is( "A" ) ); + assertThat( dtos.get( 0 ).active, is( false ) ); + + entityManager.getTransaction().commit(); + } + catch (Exception e) { + if ( entityManager.getTransaction().isActive() ) { + entityManager.getTransaction().rollback(); + } + throw e; + } + finally { + entityManager.close(); + } + } + + @Entity(name = "MyEntity") + @Table(name = "MY_ENTITY") + public static class MyEntity implements Serializable { + @Id + @Column(name = "id") + @GeneratedValue + private Integer id; + private String name; + private String surname; + + public MyEntity() { + } + + public MyEntity(String name, String surname) { + this.name = name; + this.surname = surname; + } + + public MyEntity(String name, boolean surname) { + this.name = name; + } + } + + public static class MyEntityDTO { + private String name; + private String surname; + private boolean active; + private int age; + + public MyEntityDTO() { + } + + public MyEntityDTO(String name, String surname) { + this.name = name; + this.surname = surname; + this.age = 0; + } + + public MyEntityDTO(boolean active, String name) { + this.name = name; + this.active = active; + this.age = 0; + } + public MyEntityDTO(int age, String surname) { + this.surname = surname; + this.active = false; + this.age = age; + } + } +} diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/query/QueryWithLiteralsInSelectExpressionTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/query/QueryWithLiteralsInSelectExpressionTest.java new file mode 100644 index 0000000000..a6ccd0bab5 --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/query/QueryWithLiteralsInSelectExpressionTest.java @@ -0,0 +1,137 @@ +/* + * 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 . + */ +package org.hibernate.ejb.test.query; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EntityManager; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import java.io.Serializable; +import java.util.List; + +import org.hibernate.ejb.test.BaseEntityManagerFunctionalTestCase; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import org.hibernate.testing.TestForIssue; + +/** + * @author Andrea Boriero + */ +public class QueryWithLiteralsInSelectExpressionTest extends BaseEntityManagerFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] {MyEntity.class}; + } + + @Before + public void init() throws Exception{ + final EntityManager entityManager = getOrCreateEntityManager(); + try { + entityManager.getTransaction().begin(); + entityManager.persist( new MyEntity( "Fab", "A" ) ); + entityManager.getTransaction().commit(); + } + catch (Exception e) { + if ( entityManager.getTransaction().isActive() ) { + entityManager.getTransaction().rollback(); + } + throw e; + } + finally { + entityManager.close(); + } + } + + @Test + @TestForIssue(jiraKey = "HHH-10230") + public void testSelectLiterals() { + final EntityManager entityManager = getOrCreateEntityManager(); + try { + final List elements = entityManager.createQuery( + "SELECT true, false, e.name FROM MyEntity e", + Object[].class + ).getResultList(); + Assert.assertEquals( 1, elements.size() ); + Assert.assertEquals( 3, elements.get( 0 ).length ); + Assert.assertEquals( true, elements.get( 0 )[ 0 ] ); + Assert.assertEquals( false, elements.get( 0 )[ 1 ] ); + Assert.assertEquals( "Fab", elements.get( 0 )[ 2 ] ); + } + finally { + entityManager.close(); + } + } + + @Test + @TestForIssue(jiraKey = "HHH-10230") + public void testSelectNullLiterals() { + final EntityManager entityManager = getOrCreateEntityManager(); + try { + final List elements = entityManager.createQuery( + "SELECT cast(null as boolean), false, e.name FROM MyEntity e", + Object[].class + ).getResultList(); + Assert.assertEquals( 1, elements.size() ); + Assert.assertEquals( 3, elements.get( 0 ).length ); + Assert.assertEquals( null, elements.get( 0 )[ 0 ] ); + Assert.assertEquals( false, elements.get( 0 )[ 1 ] ); + Assert.assertEquals( "Fab", elements.get( 0 )[ 2 ] ); + } + finally { + entityManager.close(); + } + } + + @Entity(name = "MyEntity") + @Table(name = "MY_ENTITY") + public static class MyEntity implements Serializable { + @Id + @Column(name = "id") + @GeneratedValue + private Integer id; + private String name; + private String surname; + + public MyEntity() { + } + + public MyEntity(String name, String surname) { + this.name = name; + this.surname = surname; + } + + public MyEntity(String name, boolean surname) { + this.name = name; + } + } + + public static class MyEntityDTO { + private String name; + private String surname; + private boolean active; + + public MyEntityDTO() { + } + + public MyEntityDTO(String name, String surname) { + this.name = name; + this.surname = surname; + } + + public MyEntityDTO(String name, boolean active) { + this.name = name; + this.active = active; + } + } + +}