OPENJPA-2849 proper handling of different Date types
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 0f22630..e39556e 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
@@ -132,6 +132,11 @@
         throws SQLException {
         Class<?> type = getType();
         int typeCode = type != null ? JavaTypes.getTypeCode(type) : JavaSQLTypes.JDBC_DEFAULT;
+        if (typeCode == JavaTypes.DATE) {
+            // further clarify which date exactly
+            typeCode = JavaSQLTypes.getDateTypeCode(type);
+        }
+
         Object value = res.getObject(this, typeCode, null);
         if (value == null) {
             if (nullableValue(ctx, state)) {  // OPENJPA-1794
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jira1794/AggEntity.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jira1794/AggEntity.java
index 28ca63f..ccb58db 100644
--- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jira1794/AggEntity.java
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jira1794/AggEntity.java
@@ -1,160 +1,184 @@
-/*

- * 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.jira1794;

-

-import javax.persistence.Entity;

-import javax.persistence.GeneratedValue;

-import javax.persistence.Id;

-import javax.persistence.Table;

-

-@Entity

-@Table(name = "j1794_ae")

-public class AggEntity {

-

-    @Id

-    @GeneratedValue

-    private int id;

-

-    private short pshortVal;

-    private Short shortVal;

-

-    private int pintVal;

-    private Integer intVal;

-

-    private long plongVal;

-    private Long longVal;

-

-    private float pfloatVal;

-    private Float floatVal;

-

-    private double pdblVal;

-    private Double dblVal;

-

-    private String stringVal;

-

-    public void setId(int id) {

-        this.id = id;

-    }

-

-    public int getId() {

-        return id;

-    }

-

-    public void setPshortVal(short pshortVal) {

-        this.pshortVal = pshortVal;

-    }

-

-    public short getPshortVal() {

-        return pshortVal;

-    }

-

-    public void setShortVal(Short pShortVal) {

-        this.shortVal = pShortVal;

-    }

-

-    public Short getShortVal() {

-        return shortVal;

-    }

-

-    public void setPintVal(int pintVal) {

-        this.pintVal = pintVal;

-    }

-

-    public int getPintVal() {

-        return pintVal;

-    }

-

-    public void setIntVal(Integer intVal) {

-        this.intVal = intVal;

-    }

-

-    public Integer getIntVal() {

-        return intVal;

-    }

-

-    public void setPlongVal(long plongVal) {

-        this.plongVal = plongVal;

-    }

-

-    public long getPlongVal() {

-        return plongVal;

-    }

-

-    public void setLongVal(Long longVal) {

-        this.longVal = longVal;

-    }

-

-    public Long getLongVal() {

-        return longVal;

-    }

-

-    public void setPfloatVal(float pfloatVal) {

-        this.pfloatVal = pfloatVal;

-    }

-

-    public float getPfloatVal() {

-        return pfloatVal;

-    }

-

-    public void setFloatVal(Float floatVal) {

-        this.floatVal = floatVal;

-    }

-

-    public Float getFloatVal() {

-        return floatVal;

-    }

-

-    public void setPdblVal(double pdblVal) {

-        this.pdblVal = pdblVal;

-    }

-

-    public double getPdblVal() {

-        return pdblVal;

-    }

-

-    public void setDblVal(Double dblVal) {

-        this.dblVal = dblVal;

-    }

-

-    public Double getDblVal() {

-        return dblVal;

-    }

-

-    public void setStringVal(String stringVal) {

-        this.stringVal = stringVal;

-    }

-

-    public String getStringVal() {

-        return stringVal;

-    }

-

-    public void init() {

-        setPshortVal((short) 1);

-        setShortVal((short) 1);

-        setIntVal(1);

-        setPintVal(1);

-        setLongVal(1L);

-        setPlongVal(1L);

-        setDblVal(1d);

-        setPdblVal(1d);

-        setFloatVal(1f);

-        setPfloatVal(1f);

-        setStringVal("1");

-    }

-}

+/*
+ * 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.jira1794;
+
+import java.util.Date;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "j1794_ae")
+public class AggEntity {
+
+    @Id
+    @GeneratedValue
+    private int id;
+
+    private short pshortVal;
+    private Short shortVal;
+
+    private int pintVal;
+    private Integer intVal;
+
+    private long plongVal;
+    private Long longVal;
+
+    private float pfloatVal;
+    private Float floatVal;
+
+    private double pdblVal;
+    private Double dblVal;
+
+    private String stringVal;
+
+    private java.util.Date utilDate;
+
+    private java.sql.Date sqlDate;
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setPshortVal(short pshortVal) {
+        this.pshortVal = pshortVal;
+    }
+
+    public short getPshortVal() {
+        return pshortVal;
+    }
+
+    public void setShortVal(Short pShortVal) {
+        this.shortVal = pShortVal;
+    }
+
+    public Short getShortVal() {
+        return shortVal;
+    }
+
+    public void setPintVal(int pintVal) {
+        this.pintVal = pintVal;
+    }
+
+    public int getPintVal() {
+        return pintVal;
+    }
+
+    public void setIntVal(Integer intVal) {
+        this.intVal = intVal;
+    }
+
+    public Integer getIntVal() {
+        return intVal;
+    }
+
+    public void setPlongVal(long plongVal) {
+        this.plongVal = plongVal;
+    }
+
+    public long getPlongVal() {
+        return plongVal;
+    }
+
+    public void setLongVal(Long longVal) {
+        this.longVal = longVal;
+    }
+
+    public Long getLongVal() {
+        return longVal;
+    }
+
+    public void setPfloatVal(float pfloatVal) {
+        this.pfloatVal = pfloatVal;
+    }
+
+    public float getPfloatVal() {
+        return pfloatVal;
+    }
+
+    public void setFloatVal(Float floatVal) {
+        this.floatVal = floatVal;
+    }
+
+    public Float getFloatVal() {
+        return floatVal;
+    }
+
+    public void setPdblVal(double pdblVal) {
+        this.pdblVal = pdblVal;
+    }
+
+    public double getPdblVal() {
+        return pdblVal;
+    }
+
+    public void setDblVal(Double dblVal) {
+        this.dblVal = dblVal;
+    }
+
+    public Double getDblVal() {
+        return dblVal;
+    }
+
+    public void setStringVal(String stringVal) {
+        this.stringVal = stringVal;
+    }
+
+    public String getStringVal() {
+        return stringVal;
+    }
+
+    public Date getUtilDate() {
+        return utilDate;
+    }
+
+    public void setUtilDate(Date utilDate) {
+        this.utilDate = utilDate;
+    }
+
+    public java.sql.Date getSqlDate() {
+        return sqlDate;
+    }
+
+    public void setSqlDate(java.sql.Date sqlDate) {
+        this.sqlDate = sqlDate;
+    }
+
+    public void init() {
+        setPshortVal((short) 1);
+        setShortVal((short) 1);
+        setIntVal(1);
+        setPintVal(1);
+        setLongVal(1L);
+        setPlongVal(1L);
+        setDblVal(1d);
+        setPdblVal(1d);
+        setFloatVal(1f);
+        setPfloatVal(1f);
+        setStringVal("1");
+        setUtilDate(new java.util.Date());
+        setSqlDate(new java.sql.Date(getUtilDate().getTime()));
+    }
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jira1794/TestAggregateFunctions.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jira1794/TestAggregateFunctions.java
index 9225d28..71af87c 100644
--- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jira1794/TestAggregateFunctions.java
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jira1794/TestAggregateFunctions.java
@@ -75,6 +75,9 @@
         verifyResult(em, stringAggregateFunctions,

                 new String[] { "ae.stringVal" }, true, true);

 

+        verifyResult(em, stringAggregateFunctions,

+                new String[]{"ae.utilDate", "ae.sqlDate"}, true, true);

+

         // Add a row to the table and re-test

         AggEntity ae = new AggEntity();

         ae.init();

@@ -82,6 +85,8 @@
         em.persist(ae);

         em.getTransaction().commit();

 

+        verifyResult(em, stringAggregateFunctions,  "ae.sqlDate", java.sql.Date.class);

+

         // Verify all numeric types for all aggregate functions return a

         // non-null value when there is a query result

         verifyResult(em, numericAggregateFunctions, numericAttributes, false);

@@ -90,6 +95,8 @@
         verifyResult(em, stringAggregateFunctions,

                 new String[] { "ae.stringVal" }, false);

 

+        verifyResult(em, stringAggregateFunctions,  "ae.utilDate", java.util.Date.class);

+

         em.close();

     }

 

@@ -241,6 +248,21 @@
         }

     }

 

+    private <T> void verifyResult(EntityManager em, String[] aggregates,

+                              String attr, Class<T> expectedType) {

+        for (String func : aggregates) {

+            // JPQL with aggregate and aggregate in subselect

+            String sql = "SELECT " + func + "(" + attr + ")"

+                    + " FROM AggEntity ae WHERE " + attr + " <= "

+                    + "(SELECT " + func + "("

+                    + attr.replaceFirst("^ae.", "ae2.")

+                    + ") FROM AggEntity ae2)";

+            TypedQuery<T> q = em.createQuery(sql, expectedType);

+            T intance = q.getSingleResult();

+            assertEquals(intance.getClass(), expectedType);

+        }

+    }

+

     private void verifyQueryResult(Query q, boolean emptyRs) {

         verifyQueryResult(q, emptyRs, false);

     }