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();