Fix criteria mod failing on derby

This commit is contained in:
Andrea Boriero 2022-01-18 11:26:25 +01:00 committed by Andrea Boriero
parent 181217ef1f
commit 0ea5528250
4 changed files with 189 additions and 0 deletions

View File

@ -10,6 +10,7 @@ import java.util.List;
import java.util.function.Consumer;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.BinaryArithmeticOperator;
import org.hibernate.query.ComparisonOperator;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
@ -17,6 +18,7 @@ import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.Statement;
import org.hibernate.sql.ast.tree.cte.CteContainer;
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;
import org.hibernate.sql.ast.tree.expression.Expression;
@ -267,4 +269,21 @@ public class DerbySqlAstTranslator<T extends JdbcOperation> extends AbstractSqlA
return getDialect().getVersion().isSameOrAfter( 10, 5 );
}
@Override
public void visitBinaryArithmeticExpression(BinaryArithmeticExpression arithmeticExpression) {
final BinaryArithmeticOperator operator = arithmeticExpression.getOperator();
if ( operator == BinaryArithmeticOperator.MODULO ) {
append( "mod" );
appendSql( OPEN_PARENTHESIS );
arithmeticExpression.getLeftHandOperand().accept( this );
appendSql( ',' );
arithmeticExpression.getRightHandOperand().accept( this );
appendSql( CLOSE_PARENTHESIS );
return;
}
else {
super.visitBinaryArithmeticExpression( arithmeticExpression );
}
}
}

View File

@ -10,12 +10,14 @@ import java.util.List;
import java.util.function.Consumer;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.BinaryArithmeticOperator;
import org.hibernate.query.ComparisonOperator;
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;
import org.hibernate.sql.ast.tree.expression.Expression;
@ -217,4 +219,21 @@ public class HSQLSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAs
private boolean supportsOffsetFetchClause() {
return getDialect().getVersion().isSameOrAfter( 2, 5 );
}
@Override
public void visitBinaryArithmeticExpression(BinaryArithmeticExpression arithmeticExpression) {
final BinaryArithmeticOperator operator = arithmeticExpression.getOperator();
if ( operator == BinaryArithmeticOperator.MODULO ) {
append( "mod" );
appendSql( OPEN_PARENTHESIS );
arithmeticExpression.getLeftHandOperand().accept( this );
appendSql( ',' );
arithmeticExpression.getRightHandOperand().accept( this );
appendSql( CLOSE_PARENTHESIS );
return;
}
else {
super.visitBinaryArithmeticExpression( arithmeticExpression );
}
}
}

View File

@ -10,6 +10,7 @@ import java.util.List;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.collections.Stack;
import org.hibernate.query.BinaryArithmeticOperator;
import org.hibernate.query.ComparisonOperator;
import org.hibernate.query.FetchClauseType;
import org.hibernate.query.IllegalQueryOperationException;
@ -17,6 +18,7 @@ import org.hibernate.sql.ast.Clause;
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.expression.BinaryArithmeticExpression;
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.FunctionExpression;
@ -418,4 +420,21 @@ public class OracleSqlAstTranslator<T extends JdbcOperation> extends AbstractSql
return getDialect().supportsFetchClause( FetchClauseType.ROWS_ONLY );
}
@Override
public void visitBinaryArithmeticExpression(BinaryArithmeticExpression arithmeticExpression) {
final BinaryArithmeticOperator operator = arithmeticExpression.getOperator();
if ( operator == BinaryArithmeticOperator.MODULO ) {
append( "mod" );
appendSql( OPEN_PARENTHESIS );
arithmeticExpression.getLeftHandOperand().accept( this );
appendSql( ',' );
arithmeticExpression.getRightHandOperand().accept( this );
appendSql( CLOSE_PARENTHESIS );
return;
}
else {
super.visitBinaryArithmeticExpression( arithmeticExpression );
}
}
}

View File

@ -0,0 +1,132 @@
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.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Root;
import jakarta.persistence.metamodel.EntityType;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@Jpa(
annotatedClasses = ModulusTest.Person.class
)
public class ModulusTest {
@BeforeEach
public void setUp(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
for ( int i = 0; i < 10; i++ ) {
Person person;
if ( i == 3 ) {
person = new Person( i, "Andrea", 5 );
}
else if ( i == 4 ) {
person = new Person( i, "Andrew", 5 );
}
else {
person = new Person( i, "Luigi " + i, 42 );
}
entityManager.persist( person );
}
}
);
}
@AfterEach
public void tearDown(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager ->
entityManager.createQuery( "delete from Person" ).executeUpdate()
);
}
@Test
public void testCriteriaMod(EntityManagerFactoryScope scope) {
scope.inEntityManager(
entityManager -> {
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
final CriteriaQuery<Integer> query = criteriaBuilder.createQuery( Integer.class );
final Root<Person> person = query.from( Person.class );
query.select( person.get( "id" ) );
final EntityType<Person> Person_ = entityManager.getMetamodel().entity( Person.class );
final Expression<Integer> mod = criteriaBuilder.mod(
criteriaBuilder.literal( 45 ),
criteriaBuilder.literal( 10 )
);
final Path<Integer> ageAttribute = person.get( Person_.getSingularAttribute(
"age",
Integer.class
) );
query.where( criteriaBuilder.equal( mod, ageAttribute ) );
final List<Integer> ids = entityManager.createQuery( query ).getResultList();
assertEquals( 2, ids.size() );
assertTrue( ids.contains( 3 ) );
assertTrue( ids.contains( 4 ) );
}
);
}
@Test
public void testQueryMod(EntityManagerFactoryScope scope) {
scope.inEntityManager(
entityManager -> {
final List<Integer> ids = entityManager.createQuery( "select p.id from Person p where p.age = 45%40" )
.getResultList();
assertEquals( 2, ids.size() );
assertTrue( ids.contains( 3 ) );
assertTrue( ids.contains( 4 ) );
}
);
}
@Entity(name = "Person")
@Table(name = "PERSON_TABLE")
public static class Person {
@Id
private Integer id;
private String name;
private Integer age;
Person() {
}
public Person(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
}
}