This is an automated email from the ASF dual-hosted git repository.

struberg pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openjpa.git

commit 0530b5b72ba00a3014e67c9ee4c3e8bfcddabb76
Author: Mark Struberg <strub...@apache.org>
AuthorDate: Thu Nov 1 21:06:41 2018 +0100

    OPENJPA-2755 OPENJPA-2555 support fractions of a second
    
    For now just in MySQL. Should also get added to PostgreSQL.
    Txs also to Ancoron Luciferis for a patch which also
    gave some important input!
---
 .../org/apache/openjpa/jdbc/sql/DBDictionary.java  |  2 +-
 .../persistence/kernel/TestDateQueries.java        | 82 +++++++++++++++++++---
 .../kernel/common/apps/AllFieldTypesTest.java      | 72 ++++++++++++++-----
 3 files changed, 127 insertions(+), 29 deletions(-)

diff --git 
a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java 
b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
index 233e184..888e35a 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
@@ -432,7 +432,7 @@ public class DBDictionary
     /**
      * set of types that only accept a single precision...
      */
-    protected final Set<String> fractionalTypeNameSet = new HashSet<>();
+    public final Set<String> fractionalTypeNameSet = new HashSet<>();
 
     /**
      * Default amount of digits for fractional Types.
diff --git 
a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/kernel/TestDateQueries.java
 
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/kernel/TestDateQueries.java
index 7677340..dc01b06 100644
--- 
a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/kernel/TestDateQueries.java
+++ 
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/kernel/TestDateQueries.java
@@ -35,6 +35,8 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.jdbc.sql.DBDictionary;
 import org.apache.openjpa.persistence.OpenJPAEntityManager;
 import org.apache.openjpa.persistence.OpenJPAQuery;
 import org.apache.openjpa.persistence.kernel.common.apps.AllFieldTypesTest;
@@ -45,6 +47,7 @@ public class TestDateQueries extends BaseKernelTest {
     private Date _date = null;
     private Date _before = null;
     private Date _after = null;
+    private final Timestamp referenceTst = new Timestamp(10000000000L);
 
     /**
      * Creates a new instance of TestDateQueries
@@ -74,12 +77,18 @@ public class TestDateQueries extends BaseKernelTest {
         test.setTestDate(_date);
 
         // prepare scale test fields
-        Timestamp tst = new Timestamp(1000000000L);
-        tst.setNanos(123456789);
-        test.setTestDateMaxScale(tst);
-        test.setTestDateScale0(tst);
-        test.setTestDateScale3(tst);
-        test.setTestDateScale6(tst);
+        Timestamp tst = new Timestamp(referenceTst.getTime());
+
+        // we stay under 5 to avoid rounding issues with some databases
+        tst.setNanos(123412341);
+
+        test.setTestTstMaxScale(tst);
+        test.setTestTstScale0(tst);
+        test.setTestTstScale3(tst);
+        test.setTestTstScale6(tst);
+        test.setTestDateMaxScale(new Date(tst.getTime()));
+        test.setTestDateScale0(new Date(tst.getTime()));
+        test.setTestDateScale3(new Date(tst.getTime()));
 
         _pm.persist(test);
 
@@ -108,18 +117,71 @@ public class TestDateQueries extends BaseKernelTest {
     }
 
     public void testDateScale() {
-        Timestamp referenceTst = new Timestamp(1000000000L);
+        DBDictionary dbDictionary = ((JDBCConfiguration) 
_pm.getConfiguration()).getDBDictionaryInstance();
+        if 
(!dbDictionary.fractionalTypeNameSet.contains(dbDictionary.timestampTypeName)) {
+            getLog().info("skipping testDateScale because DB doesn't support 
different fractions in timestamps");
+            return;
+        }
 
         Collection vals = executeQuery("testDate = :date");
         AllFieldTypesTest aft = (AllFieldTypesTest) vals.iterator().next();
         assertNotNull(aft);
 
-        long time = aft.getTestDateMaxScale().getTime();
-        long nanos = aft.getTestDateMaxScale().getNanos();
+        long time = aft.getTestTstMaxScale().getTime();
+        long nanos = aft.getTestTstMaxScale().getNanos();
 
         // cut of the ms
-        assertEquals(referenceTst, time - (time%1000));
+        assertEquals(referenceTst.getTime(), time - (time % 1000));
+
+        // we have to do some guessing as not every database
+        // is able to store fractions of a second.
+        int maxDigitsFromDb = getNonZeroDigits(nanos);
+        if (maxDigitsFromDb >= 3) {
+            {
+                time = aft.getTestTstScale0().getTime();
+                nanos = aft.getTestTstScale0().getNanos();
+                assertEquals(referenceTst.getTime(), time - (time % 1000));
+                assertEquals(0, getNonZeroDigits(nanos));
+            }
+
+            {
+                time = aft.getTestDateScale0().getTime();
+                assertEquals(referenceTst.getTime(), time - (time % 1000));
+            }
+
+            {
+                time = aft.getTestTstScale3().getTime();
+                nanos = aft.getTestTstScale3().getNanos();
+                assertEquals(referenceTst.getTime(), time - (time % 1000));
+                assertEquals(3, getNonZeroDigits(nanos));
+            }
+
+            {
+                time = aft.getTestDateMaxScale().getTime();
+                assertEquals(referenceTst.getTime() + 123, time);
+            }
+
+            {
+                time = aft.getTestDateScale3().getTime();
+                assertEquals(referenceTst.getTime() + 123, time);
+            }
+
+        }
+
+        if (maxDigitsFromDb >= 6) {
+            time = aft.getTestTstScale6().getTime();
+            nanos = aft.getTestTstScale6().getNanos();
+            assertEquals(referenceTst.getTime(), time - (time % 1000));
+            assertEquals(6, getNonZeroDigits(nanos));
+        }
+    }
+
+    private int getNonZeroDigits(long val) {
+        String sval = Long.toString(val);
+        int digits = 0;
+        for (; digits < sval.length() && sval.charAt(digits) != '0'; digits++);
 
+        return digits;
     }
 
     public void testBefore() {
diff --git 
a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/kernel/common/apps/AllFieldTypesTest.java
 
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/kernel/common/apps/AllFieldTypesTest.java
index eb99c3c..22d09b5 100644
--- 
a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/kernel/common/apps/AllFieldTypesTest.java
+++ 
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/kernel/common/apps/AllFieldTypesTest.java
@@ -66,18 +66,31 @@ public class AllFieldTypesTest {
 
     @Temporal(TemporalType.TIMESTAMP)
     @Column(scale=-1)
-    private Timestamp testDateScale0;
+    private Timestamp testTstScale0;
 
     @Temporal(TemporalType.TIMESTAMP)
     @Column(scale=3)
-    private Timestamp testDateScale3;
+    private Timestamp testTstScale3;
 
     @Temporal(TemporalType.TIMESTAMP)
     @Column(scale=6)
-    private Timestamp testDateScale6;
+    private Timestamp testTstScale6;
 
     @Temporal(TemporalType.TIMESTAMP)
-    private Timestamp testDateMaxScale;
+    private Timestamp testTstMaxScale;
+
+
+    @Temporal(TemporalType.TIMESTAMP)
+    @Column(scale=-1)
+    private Date testDateScale0;
+
+    @Temporal(TemporalType.TIMESTAMP)
+    @Column(scale=3)
+    private Date testDateScale3;
+
+
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date testDateMaxScale;
 
     private Object testObject;
     private BigInteger testBigInteger;
@@ -208,38 +221,61 @@ public class AllFieldTypesTest {
         this.testBigDecimal = testBigDecimal;
     }
 
-    public Timestamp getTestDateScale0() {
-        return testDateScale0;
+    public Timestamp getTestTstScale0() {
+        return testTstScale0;
     }
 
-    public void setTestDateScale0(Timestamp testDateScale0) {
-        this.testDateScale0 = testDateScale0;
+    public void setTestTstScale0(Timestamp testTstScale0) {
+        this.testTstScale0 = testTstScale0;
     }
 
-    public Timestamp getTestDateScale3() {
-        return testDateScale3;
+    public Timestamp getTestTstScale3() {
+        return testTstScale3;
     }
 
-    public void setTestDateScale3(Timestamp testDateScale3) {
-        this.testDateScale3 = testDateScale3;
+    public void setTestTstScale3(Timestamp testTstScale3) {
+        this.testTstScale3 = testTstScale3;
     }
 
-    public Timestamp getTestDateScale6() {
-        return testDateScale6;
+    public Timestamp getTestTstScale6() {
+        return testTstScale6;
     }
 
-    public void setTestDateScale6(Timestamp testDateScale6) {
-        this.testDateScale6 = testDateScale6;
+    public void setTestTstScale6(Timestamp testTstScale6) {
+        this.testTstScale6 = testTstScale6;
     }
 
-    public Timestamp getTestDateMaxScale() {
+    public Timestamp getTestTstMaxScale() {
+        return testTstMaxScale;
+    }
+
+    public void setTestTstMaxScale(Timestamp testTstMaxScale) {
+        this.testTstMaxScale = testTstMaxScale;
+    }
+
+    public Date getTestDateMaxScale() {
         return testDateMaxScale;
     }
 
-    public void setTestDateMaxScale(Timestamp testDateMaxScale) {
+    public void setTestDateMaxScale(Date testDateMaxScale) {
         this.testDateMaxScale = testDateMaxScale;
     }
 
+    public Date getTestDateScale0() {
+        return testDateScale0;
+    }
+
+    public void setTestDateScale0(Date testDateScale0) {
+        this.testDateScale0 = testDateScale0;
+    }
+
+    public Date getTestDateScale3() {
+        return testDateScale3;
+    }
+
+    public void setTestDateScale3(Date testDateScale3) {
+        this.testDateScale3 = testDateScale3;
+    }
 
     public void randomize(boolean objects, boolean blobs) {
         testint = AbstractTestCase.randomInt().intValue();

Reply via email to