diff --git a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/criteria/TestNegFunction.java b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/criteria/TestNegFunction.java new file mode 100644 index 00000000000..35856c8751a --- /dev/null +++ b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/criteria/TestNegFunction.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022 IBM Corporation. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, + * or the Eclipse Distribution License v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +// Contributors: +// 04/19/2022: Jody Grassel +// - Issue 579726: CriteriaBuilder neg() only returns Integer type, instead of it's argument expression type. +package org.eclipse.persistence.jpa.test.criteria; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Expression; +import jakarta.persistence.criteria.Root; +import jakarta.persistence.criteria.Selection; + +import org.eclipse.persistence.jpa.test.criteria.model.CoalesceEntity; +import org.eclipse.persistence.jpa.test.criteria.model.CritEntity; +import org.eclipse.persistence.jpa.test.framework.DDLGen; +import org.eclipse.persistence.jpa.test.framework.Emf; +import org.eclipse.persistence.jpa.test.framework.EmfRunner; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(EmfRunner.class) +public class TestNegFunction { + @Emf(createTables = DDLGen.DROP_CREATE, classes = { CritEntity.class }) + private EntityManagerFactory emf; + + @Test + public void testNegFunction() throws Exception { + EntityManager em = emf.createEntityManager(); + + try { + CritEntity ce = new CritEntity(); + ce.setId(1); + ce.setValue(new BigDecimal("3.14")); + + em.getTransaction().begin(); + em.persist(ce);; + em.getTransaction().commit(); + em.clear(); + + CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(DecHolder.class); + Root entityRoot = criteriaQuery.from(CritEntity.class); + + Collection> selections = new ArrayList>(); + + Expression valExpr = entityRoot.get("value"); + + selections.add(criteriaBuilder.sum( + criteriaBuilder. selectCase() + .when(criteriaBuilder.equal(entityRoot.get("id"), 0), valExpr) + .otherwise(criteriaBuilder.neg(valExpr)))); + + criteriaQuery.multiselect(selections.toArray(new Selection[] {})); + + List retList = em.createQuery(criteriaQuery).getResultList(); + } finally { + if (em.getTransaction().isActive()) { + em.getTransaction().rollback(); + } + if(em.isOpen()) { + em.close(); + } + } + } + + public static class DecHolder { + private BigDecimal value; + + public DecHolder(Object value) { + super(); + this.value = (BigDecimal) value; + } + + public BigDecimal getValue() { + return value; + } + + public void setValue(BigDecimal value) { + this.value = value; + } + + @Override + public String toString() { + return "DecHolder [value=" + value + "]"; + } + } +} diff --git a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/criteria/model/CritEntity.java b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/criteria/model/CritEntity.java new file mode 100644 index 00000000000..fc6e3b64ccb --- /dev/null +++ b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/criteria/model/CritEntity.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022 IBM Corporation. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, + * or the Eclipse Distribution License v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +// Contributors: +// 04/19/2022: Jody Grassel +// - Issue 579726: CriteriaBuilder neg() only returns Integer type, instead of it's argument expression type. +package org.eclipse.persistence.jpa.test.criteria.model; + +import java.math.BigDecimal; + +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; + +@Entity +public class CritEntity { + @Id + private int id; + + @Basic + @Column(precision = 10, scale = 2) + private BigDecimal value; + + public CritEntity() { + + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public BigDecimal getValue() { + return value; + } + + public void setValue(BigDecimal bigDec) { + this.value = bigDec; + } + + @Override + public String toString() { + return "CritEntity [id=" + id + ", value=" + value + "]"; + } + + +} + + diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CriteriaBuilderImpl.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CriteriaBuilderImpl.java index 8d4a72a917f..ea146aa06d8 100644 --- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CriteriaBuilderImpl.java +++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CriteriaBuilderImpl.java @@ -14,6 +14,9 @@ // Contributors: // Gordon Yorke - Initial development // +// Contributors: +// 04/19/2022: Jody Grassel +// - Issue 579726: CriteriaBuilder neg() only returns Integer type, instead of it's argument expression type. package org.eclipse.persistence.internal.jpa.querydef; import java.io.Serializable; @@ -650,7 +653,7 @@ public Predicate equal(Expression x, Object y){ if (((InternalSelection)x).getCurrentNode() == null){ throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION")); } - if (y instanceof ParameterExpression) + if (y instanceof ParameterExpression) return this.equal(x, (ParameterExpression)y); return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().equal(y), buildList(x, internalLiteral(y)), "equal"); @@ -670,7 +673,7 @@ public Predicate notEqual(Expression x, Object y){ if (((InternalSelection)x).getCurrentNode() == null){ throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION")); } - if (y instanceof ParameterExpression) + if (y instanceof ParameterExpression) return this.notEqual(x, (ParameterExpression)y); return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().notEqual(y), buildList(x, internalLiteral(y)), "not equal"); @@ -999,7 +1002,7 @@ public Predicate le(Expression x, Number y){ */ @Override public Expression neg(Expression x){ - return new FunctionExpressionImpl(this.metamodel, ClassConstants.INTEGER, ExpressionMath.negate(((InternalSelection)x).getCurrentNode()), buildList(x), "neg"); + return new FunctionExpressionImpl(this.metamodel, (Class) x.getJavaType(), ExpressionMath.negate(((InternalSelection)x).getCurrentNode()), buildList(x), "neg"); } /**