Changed second fraction precision of LocalDateTime and OffsetDateTime MySQL related type. (#1456)
Signed-off-by: Tomas Kraus <tomas.kraus@oracle.com>
diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/MySQLPlatform.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/MySQLPlatform.java
index e7f855b..9d6d700 100644
--- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/MySQLPlatform.java
+++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/MySQLPlatform.java
@@ -215,7 +215,7 @@
if (!isFractionalTimeSupported) {
fd.setIsSizeAllowed(false);
} else {
- fd.setDefaultSize(3);
+ fd.setDefaultSize(6);
fd.setIsSizeRequired(true);
}
fieldTypeMapping.put(java.time.LocalDateTime.class,fd); //no timezone info
@@ -224,7 +224,7 @@
if (!isFractionalTimeSupported) {
fd.setIsSizeAllowed(false);
} else {
- fd.setDefaultSize(3);
+ fd.setDefaultSize(6);
fd.setIsSizeRequired(true);
}
fieldTypeMapping.put(java.time.LocalTime.class, fd);
@@ -233,7 +233,7 @@
if (!isFractionalTimeSupported) {
fd.setIsSizeAllowed(false);
} else {
- fd.setDefaultSize(3);
+ fd.setDefaultSize(6);
fd.setIsSizeRequired(true);
}
fieldTypeMapping.put(java.time.OffsetDateTime.class, fd); //no timezone info
@@ -242,7 +242,7 @@
if (!isFractionalTimeSupported) {
fd.setIsSizeAllowed(false);
} else {
- fd.setDefaultSize(3);
+ fd.setDefaultSize(6);
fd.setIsSizeRequired(true);
}
fieldTypeMapping.put(java.time.OffsetTime.class, fd);
@@ -384,6 +384,11 @@
@Override
protected void initializePlatformOperators() {
super.initializePlatformOperators();
+ addOperator(currentTimeStamp());
+ addOperator(today());
+ addOperator(currentTime());
+ addOperator(localTime());
+ addOperator(localDateTime());
addOperator(logOperator());
addOperator(ExpressionOperator.simpleTwoArgumentFunction(ExpressionOperator.Atan2, "ATAN2"));
addOperator(ExpressionOperator.simpleTwoArgumentFunction(ExpressionOperator.Concat, "CONCAT"));
@@ -399,6 +404,60 @@
/**
* INTERNAL:
+ * MySQL specific {@code currentTimeStamp} operator.
+ *
+ * @return new {@link ExpressionOperator} instance with {@code currentTimeStamp}
+ */
+ public static ExpressionOperator currentTimeStamp() {
+ return ExpressionOperator.simpleFunctionNoParentheses(
+ ExpressionOperator.Today, "CURRENT_TIMESTAMP(6)");
+ }
+
+ /**
+ * INTERNAL:
+ * MySQL specific {@code today} operator.
+ *
+ * @return new {@link ExpressionOperator} instance with {@code today}
+ */
+ public static ExpressionOperator today() {
+ return currentTimeStamp();
+ }
+
+ /**
+ * INTERNAL:
+ * MySQL specific {@code currentTime} operator.
+ *
+ * @return new {@link ExpressionOperator} instance with {@code currentTime}
+ */
+ public static ExpressionOperator currentTime() {
+ return ExpressionOperator.simpleFunctionNoParentheses(
+ ExpressionOperator.CurrentTime, "CURRENT_TIME(6)");
+ }
+
+ /**
+ * INTERNAL:
+ * MySQL specific {@code localTime} operator.
+ *
+ * @return new {@link ExpressionOperator} instance with {@code localTime}
+ */
+ public static ExpressionOperator localTime() {
+ return ExpressionOperator.simpleFunctionNoParentheses(
+ ExpressionOperator.LocalTime, "CURRENT_TIME(6)");
+ }
+
+ /**
+ * INTERNAL:
+ * MySQL specific {@code localDateTime} operator.
+ *
+ * @return new {@link ExpressionOperator} instance with {@code localDateTime}
+ */
+ public static ExpressionOperator localDateTime() {
+ return ExpressionOperator.simpleFunctionNoParentheses(
+ ExpressionOperator.LocalDateTime, "CURRENT_TIMESTAMP(6)");
+ }
+
+ /**
+ * INTERNAL:
* Create the 10 based log operator for this platform.
*/
protected ExpressionOperator logOperator() {
diff --git a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/criteria/TestDateTimeFunctions.java b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/criteria/TestDateTimeFunctions.java
index d48bd9a..3a436d8 100644
--- a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/criteria/TestDateTimeFunctions.java
+++ b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/criteria/TestDateTimeFunctions.java
@@ -20,6 +20,7 @@
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Period;
+import java.time.temporal.ChronoUnit;
import java.util.List;
import jakarta.persistence.EntityManager;
@@ -34,6 +35,8 @@
import org.eclipse.persistence.jpa.test.framework.Emf;
import org.eclipse.persistence.jpa.test.framework.EmfRunner;
import org.eclipse.persistence.jpa.test.framework.Property;
+import org.eclipse.persistence.logging.AbstractSessionLog;
+import org.eclipse.persistence.logging.SessionLog;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.After;
@@ -80,6 +83,33 @@
// testCriteriaQuerySelectLocalDateTime
};
+ // Database vs. Java timezone offset in seconds. Must be applied to LocalDateTime calculations.
+ private long dbOffset = 0;
+
+ // Update database vs. Java timezone offset using current database time.
+ private void updateDbOffset() {
+ final EntityManager em = emf.createEntityManager();
+ try {
+ CriteriaBuilder cb = em.getCriteriaBuilder();
+ CriteriaQuery<LocalTime> cq = cb.createQuery(LocalTime.class);
+ cq.select(cb.localTime());
+ Root<DateTimeEntity> entity = cq.from(DateTimeEntity.class);
+ cq.where(cb.equal(entity.get("id"), 1));
+ LocalTime dbTime = em.createQuery(cq).getSingleResult();
+ LocalTime javaTime = LocalTime.now();
+ this.dbOffset = dbTime.truncatedTo(ChronoUnit.SECONDS).toSecondOfDay() - javaTime.truncatedTo(ChronoUnit.SECONDS).toSecondOfDay();
+ } catch (Throwable t) {
+ AbstractSessionLog.getLog().log(SessionLog.WARNING, "Can't update DB offset: " + t.getMessage());
+ t.printStackTrace();
+ } finally {
+ if (em.getTransaction().isActive()) {
+ em.getTransaction().rollback();
+ }
+ em.close();
+ }
+
+ }
+
@Before
public void setup() {
final EntityManager em = emf.createEntityManager();
@@ -96,6 +126,7 @@
}
em.close();
}
+ updateDbOffset();
}
@After
@@ -134,7 +165,7 @@
em.getTransaction().commit();
// Verify updated entity
DateTimeEntity data = em.find(DateTimeEntity.class, 1);
- long diffMilis = Duration.between(data.getTime(), LocalTime.now()).toMillis();
+ long diffMilis = Duration.between(data.getTime(), LocalTime.now().plusSeconds(dbOffset + 1)).toMillis();
// Positive value means that test did not pass midnight.
if (diffMilis > 0) {
MatcherAssert.assertThat(diffMilis, Matchers.lessThan(30000L));
@@ -203,7 +234,7 @@
em.getTransaction().commit();
// Verify updated entity
DateTimeEntity data = em.find(DateTimeEntity.class, 3);
- long diffMilis = Duration.between(data.getDatetime(), LocalDateTime.now()).toMillis();
+ long diffMilis = Duration.between(data.getDatetime(), LocalDateTime.now().plusSeconds(dbOffset + 1)).toMillis();
MatcherAssert.assertThat(diffMilis, Matchers.lessThan(30000L));
} finally {
if (em.getTransaction().isActive()) {
@@ -370,7 +401,7 @@
cq.where(cb.equal(entity.get("id"), 4));
LocalTime time = em.createQuery(cq).getSingleResult();
em.getTransaction().commit();
- long diffMilis = Duration.between(time, LocalTime.now()).toMillis();
+ long diffMilis = Duration.between(time, LocalTime.now().plusSeconds(1 + dbOffset)).toMillis();
// Positive value means that test did not pass midnight.
if (diffMilis > 0) {
MatcherAssert.assertThat(diffMilis, Matchers.lessThan(30000L));
@@ -424,7 +455,7 @@
cq.where(cb.equal(entity.get("id"), 4));
LocalDateTime datetime = em.createQuery(cq).getSingleResult();
em.getTransaction().commit();
- long diffMilis = Duration.between(datetime, LocalDateTime.now()).toMillis();
+ long diffMilis = Duration.between(datetime, LocalDateTime.now().plusSeconds(dbOffset + 1)).toMillis();
MatcherAssert.assertThat(diffMilis, Matchers.lessThan(30000L));
} finally {
if (em.getTransaction().isActive()) {
diff --git a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/query/TestDateTimeFunctions.java b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/query/TestDateTimeFunctions.java
index 6c481b0..89ca823 100644
--- a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/query/TestDateTimeFunctions.java
+++ b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/query/TestDateTimeFunctions.java
@@ -16,6 +16,7 @@
package org.eclipse.persistence.jpa.test.query;
import java.time.LocalDateTime;
+import java.util.List;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
@@ -52,11 +53,13 @@
private EntityManagerFactory emf;
private final LocalDateTime[] TS = {
- LocalDateTime.of(2022, 3, 9, 14, 30, 25, 0)
+ LocalDateTime.of(2022, 3, 9, 14, 30, 25, 0),
+ LocalDateTime.now()
};
private final DateTimeQueryEntity[] ENTITY = {
- new DateTimeQueryEntity(1, TS[0].toLocalTime(), TS[0].toLocalDate(), TS[0])
+ new DateTimeQueryEntity(1, TS[0].toLocalTime(), TS[0].toLocalDate(), TS[0]),
+ new DateTimeQueryEntity(2, TS[1].toLocalTime(), TS[1].toLocalDate(), TS[1])
};
@Before
@@ -389,4 +392,26 @@
}
}
+ // Test LocalDateTime.now() in WHERE clause
+ // SELECT e FROM DateTimeQueryEntity e WHERE e.datetime = :dateTime
+ @Test
+ public void testLocalDateTime() {
+ final EntityManager em = emf.createEntityManager();
+ try {
+ em.getTransaction().begin();
+ TypedQuery<DateTimeQueryEntity> query = em.createNamedQuery("DateTimeQueryEntity.findByLocalDateTime", DateTimeQueryEntity.class);
+ query.setParameter("dateTime", TS[1]);
+ List<DateTimeQueryEntity> result = query.getResultList();
+ MatcherAssert.assertThat(result.size(), Matchers.equalTo(1));
+ } catch (Throwable t) {
+ t.printStackTrace();
+ throw t;
+ } finally {
+ if (em.getTransaction().isActive()) {
+ em.getTransaction().rollback();
+ }
+ em.close();
+ }
+ }
+
}
diff --git a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/query/model/DateTimeQueryEntity.java b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/query/model/DateTimeQueryEntity.java
index d754cac..127b83f 100644
--- a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/query/model/DateTimeQueryEntity.java
+++ b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/query/model/DateTimeQueryEntity.java
@@ -21,11 +21,13 @@
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
+import jakarta.persistence.NamedQuery;
/**
* JPA Entity used in {@code LocalTime}/{@code LocalDate}/{@code LocalDateTime} tests.
*/
@Entity
+@NamedQuery(name = "DateTimeQueryEntity.findByLocalDateTime", query = "SELECT e FROM DateTimeQueryEntity e WHERE e.datetime = :dateTime")
public class DateTimeQueryEntity {
@Id