Skip to content

Commit 72cf9f8

Browse files
Tomas-Krauslukasj
authored andcommitted
Added missing EXTRACT(QUARTER FROM date/datetime) for Derby platform. Covered EXTRACT queries with jUnit.
Signed-off-by: Tomas Kraus <[email protected]>
1 parent da512f0 commit 72cf9f8

File tree

4 files changed

+544
-32
lines changed

4 files changed

+544
-32
lines changed

foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/DerbyPlatform.java

+68-4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import java.util.Hashtable;
3333
import java.util.Iterator;
3434
import java.util.List;
35+
import java.util.Locale;
3536
import java.util.Vector;
3637

3738
import org.eclipse.persistence.exceptions.ValidationException;
@@ -41,6 +42,7 @@
4142
import org.eclipse.persistence.internal.databaseaccess.FieldTypeDefinition;
4243
import org.eclipse.persistence.internal.expressions.ExpressionJavaPrinter;
4344
import org.eclipse.persistence.internal.expressions.ExpressionSQLPrinter;
45+
import org.eclipse.persistence.internal.expressions.LiteralExpression;
4446
import org.eclipse.persistence.internal.expressions.SQLSelectStatement;
4547
import org.eclipse.persistence.internal.helper.ClassConstants;
4648
import org.eclipse.persistence.internal.helper.DatabaseField;
@@ -345,7 +347,7 @@ protected void initializePlatformOperators() {
345347
addOperator(ExpressionOperator.simpleFunction(ExpressionOperator.ToNumber, "DOUBLE"));
346348
// LocalTime should be processed as TIMESTAMP
347349
addOperator(ExpressionOperator.simpleFunctionNoParentheses(ExpressionOperator.LocalTime, "CAST(CURRENT_TIME AS TIMESTAMP)"));
348-
addOperator(extractOperator());
350+
addOperator(derbyExtractOperator());
349351
addOperator(derbyPowerOperator());
350352
addOperator(derbyRoundOperator());
351353
}
@@ -495,12 +497,74 @@ public void printJavaCollection(List items, ExpressionJavaPrinter printer) {
495497
* INTERNAL:
496498
* Derby does not support EXTRACT, but does have YEAR, MONTH, DAY, etc.
497499
*/
498-
public static ExpressionOperator extractOperator() {
499-
ExpressionOperator exOperator = new ExpressionOperator();
500+
public static ExpressionOperator derbyExtractOperator() {
501+
502+
ExpressionOperator exOperator = new ExpressionOperator() {
503+
504+
// QUARTER emulation: ((MONTH(:first)+2)/3)
505+
private final String[] QUARTER_STRINGS = new String[] {"((MONTH(", ")+2)/3)"};
506+
507+
private void printQuarterSQL(final Expression first, final ExpressionSQLPrinter printer) {
508+
printer.printString(QUARTER_STRINGS[0]);
509+
first.printSQL(printer);
510+
printer.printString(QUARTER_STRINGS[1]);
511+
}
512+
513+
private void printQuarterJava(final Expression first, final ExpressionJavaPrinter printer) {
514+
printer.printString(QUARTER_STRINGS[0]);
515+
first.printJava(printer);
516+
printer.printString(QUARTER_STRINGS[1]);
517+
}
518+
519+
@Override
520+
public void printDuo(Expression first, Expression second, ExpressionSQLPrinter printer) {
521+
if (second instanceof LiteralExpression && "QUARTER".equals(((LiteralExpression)second).getValue().toUpperCase())) {
522+
printQuarterSQL(first, printer);
523+
} else {
524+
super.printDuo(first, second, printer);
525+
}
526+
}
527+
528+
@Override
529+
public void printCollection(List items, ExpressionSQLPrinter printer) {
530+
if (items.size() == 2) {
531+
Expression first = (Expression)items.get(0);
532+
Expression second = (Expression)items.get(1);
533+
if (second instanceof LiteralExpression && "QUARTER".equals(((LiteralExpression)second).getValue().toUpperCase())) {
534+
printQuarterSQL(first, printer);
535+
return;
536+
}
537+
}
538+
super.printCollection(items, printer);
539+
}
540+
541+
@Override
542+
public void printJavaDuo(Expression first, Expression second, ExpressionJavaPrinter printer) {
543+
if (second instanceof LiteralExpression && "QUARTER".equals(((LiteralExpression)second).getValue().toUpperCase())) {
544+
printQuarterJava(first, printer);
545+
} else {
546+
super.printJavaDuo(first, second, printer);
547+
}
548+
}
549+
550+
@Override
551+
public void printJavaCollection(List items, ExpressionJavaPrinter printer) {
552+
if (items.size() == 2) {
553+
Expression first = (Expression)items.get(0);
554+
Expression second = (Expression)items.get(1);
555+
if (second instanceof LiteralExpression && "QUARTER".equals(((LiteralExpression)second).getValue().toUpperCase())) {
556+
printQuarterJava(first, printer);
557+
return;
558+
}
559+
}
560+
super.printJavaCollection(items, printer);
561+
}
562+
};
563+
500564
exOperator.setType(ExpressionOperator.FunctionOperator);
501565
exOperator.setSelector(ExpressionOperator.Extract);
502566
exOperator.setName("EXTRACT");
503-
List<String> v = new ArrayList<>(5);
567+
List<String> v = new ArrayList<>(3);
504568
v.add("");
505569
v.add("(");
506570
v.add(")");
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// Contributors:
1414
// 02/01/2022: Tomas Kraus
1515
// - Issue 1442: Implement New JPA API 3.1.0 Features
16-
package org.eclipse.persistence.jpa.test.criteria.model;
16+
package org.eclipse.persistence.jpa.test.criteria;
1717

1818
import java.time.Duration;
1919
import java.time.LocalDate;
@@ -29,6 +29,7 @@
2929
import jakarta.persistence.criteria.CriteriaUpdate;
3030
import jakarta.persistence.criteria.Root;
3131

32+
import org.eclipse.persistence.jpa.test.criteria.model.DateTimeEntity;
3233
import org.eclipse.persistence.jpa.test.framework.DDLGen;
3334
import org.eclipse.persistence.jpa.test.framework.Emf;
3435
import org.eclipse.persistence.jpa.test.framework.EmfRunner;
@@ -227,9 +228,6 @@ public void testCriteriaQueryWhereLocalTime() {
227228
cq.where(cb.and(cb.lessThan(entity.get("time"), cb.localTime()), cb.equal(entity.get("id"), 4)));
228229
em.createQuery(cq).getSingleResult();
229230
em.getTransaction().commit();
230-
} catch (Throwable t) {
231-
t.printStackTrace();
232-
throw t;
233231
} finally {
234232
if (em.getTransaction().isActive()) {
235233
em.getTransaction().rollback();
@@ -255,9 +253,6 @@ public void testCriteriaQueryWhereLocalTimeReturnsEmpty() {
255253
List<DateTimeEntity> data = em.createQuery(cq).getResultList();
256254
em.getTransaction().commit();
257255
MatcherAssert.assertThat(data.size(), Matchers.equalTo(0));
258-
} catch (Throwable t) {
259-
t.printStackTrace();
260-
throw t;
261256
} finally {
262257
if (em.getTransaction().isActive()) {
263258
em.getTransaction().rollback();
@@ -281,9 +276,6 @@ public void testCriteriaQueryWhereLocalDate() {
281276
cq.where(cb.and(cb.lessThan(entity.get("date"), cb.localDate()), cb.equal(entity.get("id"), 4)));
282277
em.createQuery(cq).getSingleResult();
283278
em.getTransaction().commit();
284-
} catch (Throwable t) {
285-
t.printStackTrace();
286-
throw t;
287279
} finally {
288280
if (em.getTransaction().isActive()) {
289281
em.getTransaction().rollback();
@@ -309,9 +301,6 @@ public void testCriteriaQueryWhereLocalDateReturnsEmpty() {
309301
List<DateTimeEntity> data = em.createQuery(cq).getResultList();
310302
em.getTransaction().commit();
311303
MatcherAssert.assertThat(data.size(), Matchers.equalTo(0));
312-
} catch (Throwable t) {
313-
t.printStackTrace();
314-
throw t;
315304
} finally {
316305
if (em.getTransaction().isActive()) {
317306
em.getTransaction().rollback();
@@ -335,9 +324,6 @@ public void testCriteriaQueryWhereLocalDateTime() {
335324
cq.where(cb.and(cb.lessThan(entity.get("datetime"), cb.localDateTime()), cb.equal(entity.get("id"), 4)));
336325
em.createQuery(cq).getSingleResult();
337326
em.getTransaction().commit();
338-
} catch (Throwable t) {
339-
t.printStackTrace();
340-
throw t;
341327
} finally {
342328
if (em.getTransaction().isActive()) {
343329
em.getTransaction().rollback();
@@ -363,9 +349,6 @@ public void testCriteriaQueryWhereLocalDateTimeReturnsEmpty() {
363349
List<DateTimeEntity> data = em.createQuery(cq).getResultList();
364350
em.getTransaction().commit();
365351
MatcherAssert.assertThat(data.size(), Matchers.equalTo(0));
366-
} catch (Throwable t) {
367-
t.printStackTrace();
368-
throw t;
369352
} finally {
370353
if (em.getTransaction().isActive()) {
371354
em.getTransaction().rollback();
@@ -395,9 +378,6 @@ public void testCriteriaQuerySelectLocalTime() {
395378
} else {
396379
MatcherAssert.assertThat(86400000L + diffMilis, Matchers.lessThan(30000L));
397380
}
398-
} catch (Throwable t) {
399-
t.printStackTrace();
400-
throw t;
401381
} finally {
402382
if (em.getTransaction().isActive()) {
403383
em.getTransaction().rollback();
@@ -423,9 +403,6 @@ public void testCriteriaQuerySelectLocalDate() {
423403
MatcherAssert.assertThat(diff.getYears(), Matchers.equalTo(0));
424404
MatcherAssert.assertThat(diff.getMonths(), Matchers.equalTo(0));
425405
MatcherAssert.assertThat(diff.getDays(), Matchers.lessThan(2));
426-
} catch (Throwable t) {
427-
t.printStackTrace();
428-
throw t;
429406
} finally {
430407
if (em.getTransaction().isActive()) {
431408
em.getTransaction().rollback();
@@ -449,9 +426,6 @@ public void testCriteriaQuerySelectLocalDateTime() {
449426
em.getTransaction().commit();
450427
long diffMilis = Duration.between(datetime, LocalDateTime.now()).toMillis();
451428
MatcherAssert.assertThat(diffMilis, Matchers.lessThan(30000L));
452-
} catch (Throwable t) {
453-
t.printStackTrace();
454-
throw t;
455429
} finally {
456430
if (em.getTransaction().isActive()) {
457431
em.getTransaction().rollback();

0 commit comments

Comments
 (0)