Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changed second fraction precision of LocalDateTime and OffsetDateTime MySQL related type. #1456

Merged
merged 1 commit into from
Mar 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ protected Hashtable<Class<?>, FieldTypeDefinition> buildFieldTypes() {
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
Expand All @@ -224,7 +224,7 @@ protected Hashtable<Class<?>, FieldTypeDefinition> buildFieldTypes() {
if (!isFractionalTimeSupported) {
fd.setIsSizeAllowed(false);
} else {
fd.setDefaultSize(3);
fd.setDefaultSize(6);
fd.setIsSizeRequired(true);
}
fieldTypeMapping.put(java.time.LocalTime.class, fd);
Expand All @@ -233,7 +233,7 @@ protected Hashtable<Class<?>, FieldTypeDefinition> buildFieldTypes() {
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
Expand All @@ -242,7 +242,7 @@ protected Hashtable<Class<?>, FieldTypeDefinition> buildFieldTypes() {
if (!isFractionalTimeSupported) {
fd.setIsSizeAllowed(false);
} else {
fd.setDefaultSize(3);
fd.setDefaultSize(6);
fd.setIsSizeRequired(true);
}
fieldTypeMapping.put(java.time.OffsetTime.class, fd);
Expand Down Expand Up @@ -384,6 +384,11 @@ public boolean isMySQL() {
@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"));
Expand All @@ -397,6 +402,60 @@ protected void initializePlatformOperators() {
addOperator(rightTrim2());
}

/**
* 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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -80,6 +83,33 @@ public class TestDateTimeFunctions {
// 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();
Expand All @@ -96,6 +126,7 @@ public void setup() {
}
em.close();
}
updateDbOffset();
}

@After
Expand Down Expand Up @@ -134,7 +165,7 @@ public void testCriteriaUpdateLocalTime() {
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));
Expand Down Expand Up @@ -203,7 +234,7 @@ public void testCriteriaUpdateLocalDateTime() {
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()) {
Expand Down Expand Up @@ -370,7 +401,7 @@ public void testCriteriaQuerySelectLocalTime() {
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));
Expand Down Expand Up @@ -424,7 +455,7 @@ public void testCriteriaQuerySelectLocalDateTime() {
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()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -52,11 +53,13 @@ public class TestDateTimeFunctions {
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
Expand Down Expand Up @@ -389,4 +392,26 @@ public void testCriteriaExtractSecondFromDateTime() {
}
}

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

}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down