diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/UnaryOp.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/UnaryOp.java index d73cd458b..b7246ba20 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/UnaryOp.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/UnaryOp.java @@ -113,8 +113,12 @@ abstract class UnaryOp public Object load(ExpContext ctx, ExpState state, Result res) throws SQLException { - return Filters.convert(res.getObject(this, - JavaSQLTypes.JDBC_DEFAULT, null), getType()); + Object value = res.getObject(this, JavaSQLTypes.JDBC_DEFAULT, null); + Class type = getType(); + if (value == null && (type.isPrimitive() || Number.class.isAssignableFrom(type))) { + value = Filters.getDefaultForNull(Filters.wrap(type)); + } + return Filters.convert(value, type); } public void calculateValue(Select sel, ExpContext ctx, ExpState state, diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java index 8f68346a0..592fcdd14 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java @@ -974,5 +974,19 @@ public class Filters { || Time.class.isAssignableFrom(c) || Timestamp.class.isAssignableFrom(c)); } + + public static Object getDefaultForNull(Class nType) { + if (nType == Long.class) + return new Long(0); + if (nType == Integer.class) + return new Integer(0); + if (nType == Double.class) + return new Double(0.0); + if (nType == Float.class) + return new Float(0.0); + if (nType == Short.class) + return new Short((short)0); + return null; + } } diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestAggregateQueryWithNoResult.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestAggregateQueryWithNoResult.java new file mode 100644 index 000000000..5b095a8da --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestAggregateQueryWithNoResult.java @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.persistence.jdbc.query; + +import javax.persistence.EntityManager; + +import org.apache.openjpa.persistence.jdbc.query.domain.Chess; +import org.apache.openjpa.persistence.jdbc.query.domain.Game; +import org.apache.openjpa.persistence.jdbc.query.domain.IndoorGame; +import org.apache.openjpa.persistence.jdbc.query.domain.Scrabble; +import org.apache.openjpa.persistence.test.SingleEMFTestCase; + +/** + * Tests Aggregate Query that has no record. + * + * SUM() and COUNT() always return Long. + * AVG(), MAX(), MIN() preserves the type of aggregated field. + * + * @author Pinaki Poddar + * + */ +public class TestAggregateQueryWithNoResult extends SingleEMFTestCase { + EntityManager em; + public void setUp() { + super.setUp(CLEAR_TABLES, Game.class, IndoorGame.class, Scrabble.class, + Chess.class); + em = emf.createEntityManager(); + assertTrue(em.createQuery("select p from Scrabble p").getResultList().isEmpty()); + } + + + public void testSumWithNoResult() { + String jpql = "SELECT SUM(g.nTile) FROM Scrabble g"; + + Long result = (Long)em.createQuery(jpql).getSingleResult(); + + assertNotNull(result); + assertEquals(result, new Long(0)); + } + + public void testAvgWithNoResult() { + String jpql = "SELECT AVG(g.nTile) FROM Scrabble g"; + + Integer result = (Integer)em.createQuery(jpql).getSingleResult(); + + assertNotNull(result); + assertEquals(result, new Integer(0)); + } + + public void testCountWithNoResult() { + String jpql = "SELECT COUNT(g.nTile) FROM Scrabble g"; + + Long result = (Long)em.createQuery(jpql).getSingleResult(); + + assertNotNull(result); + assertEquals(result, new Long(0)); + } + + public void testMaxWithNoResult() { + String jpql = "SELECT MAX(g.nTile) FROM Scrabble g"; + + Integer result = (Integer)em.createQuery(jpql).getSingleResult(); + + assertNotNull(result); + assertEquals(result, new Integer(0)); + } + + public void testMinWithNoResult() { + String jpql = "SELECT MIN(g.nTile) FROM Scrabble g"; + + Integer result = (Integer)em.createQuery(jpql).getSingleResult(); + + assertNotNull(result); + assertEquals(result, new Integer(0)); + } +}