Skip to content

Commit

Permalink
Implement New JPA API 3.1.0 Features
Browse files Browse the repository at this point in the history
Signed-off-by: Tomas Kraus <tomas.kraus@oracle.com>
  • Loading branch information
Tomas-Kraus authored and lukasj committed Mar 3, 2022
1 parent 5c37a24 commit 243dd93
Show file tree
Hide file tree
Showing 13 changed files with 1,099 additions and 75 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021 IBM Corporation. All rights reserved.
*
* This program and the accompanying materials are made available under the
Expand All @@ -15,6 +15,8 @@
// Oracle - initial API and implementation from Oracle TopLink
// 05/24/2011-2.3 Guy Pelletier
// - 345962: Join fetch query when using tenant discriminator column fails.
// 02/01/2022: Tomas Kraus
// - Issue 1442: Implement New JPA API 3.1.0 Features
package org.eclipse.persistence.expressions;

import java.io.BufferedWriter;
Expand Down Expand Up @@ -1196,6 +1198,34 @@ public Expression currentTime() {
return getFunction(ExpressionOperator.CurrentTime);
}

/**
* PUBLIC:
* This gives access to the local date and time on the database through expression.
*/
public Expression localDateTime() {
return getFunction(ExpressionOperator.LocalDateTime);
}

/**
* PUBLIC:
* This gives access to the local date only on the database through expression.
* Note the difference between localDate() and this method. This method does
* not return the time portion of local datetime where as localDate() does.
*/
public Expression localDate() {
return getFunction(ExpressionOperator.LocalDate);
}

/**
* PUBLIC:
* This gives access to the local time only on the database through expression.
* Note the difference between localDate() and this method. This method does
* not return the date portion of local datetime where as localDate() does.
*/
public Expression localTime() {
return getFunction(ExpressionOperator.LocalTime);
}

/**
* PUBLIC:
* Function, Return the difference between the queried part of a date(i.e. years, days etc.)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021 IBM Corporation. All rights reserved.
*
* This program and the accompanying materials are made available under the
Expand All @@ -18,6 +18,8 @@
// - 263904: [PATCH] ExpressionOperator doesn't compare arrays correctly
// 01/23/2018-2.7 Will Dazey
// - 530214: trim operation should not bind parameters
// 02/01/2022: Tomas Kraus
// - Issue 1442: Implement New JPA API 3.1.0 Features
package org.eclipse.persistence.expressions;

import java.io.IOException;
Expand Down Expand Up @@ -215,6 +217,10 @@ public class ExpressionOperator implements Serializable {
*/
public static final int CurrentTime = 128;

public static final int LocalDate = 149;
public static final int LocalTime = 150;
public static final int LocalDateTime = 151;

// Math
public static final int Ceil = 55;
public static final int Cos = 56;
Expand Down Expand Up @@ -2980,6 +2986,30 @@ public static ExpressionOperator currentTime() {
return simpleFunctionNoParentheses(CurrentTime, "CURRENT_TIME");
}

/**
* INTERNAL:
* Build operator.
*/
public static ExpressionOperator localDate() {
return simpleFunctionNoParentheses(LocalDate, "CURRENT_DATE");
}

/**
* INTERNAL:
* Build operator.
*/
public static ExpressionOperator localTime() {
return simpleFunctionNoParentheses(LocalTime, "CURRENT_TIME");
}

/**
* INTERNAL:
* Build operator.
*/
public static ExpressionOperator localDateTime() {
return simpleFunctionNoParentheses(LocalDateTime, "CURRENT_TIMESTAMP");
}

/**
* INTERNAL:
* Create the toLowerCase operator.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

// Contributors:
// Blaise Doughan - 2.5 - initial implementation
// 02/01/2022: Tomas Kraus
// - Issue 1442: Implement New JPA API 3.1.0 Features
package org.eclipse.persistence.internal.core.helper;

import java.io.File;
Expand All @@ -21,6 +23,9 @@
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
Expand Down Expand Up @@ -78,6 +83,9 @@ public class CoreClassConstants {
public static final Class<String> STRING = String.class;
public static final Class<Time> TIME = Time.class;
public static final Class<Timestamp> TIMESTAMP = Timestamp.class;
public static final Class<LocalDate> LOCAL_DATE = LocalDate.class;
public static final Class<LocalTime> LOCAL_TIME = LocalTime.class;
public static final Class<LocalDateTime> LOCAL_DATETIME = LocalDateTime.class;
public static final Class<UUID> UUID = UUID.class;
public static final Class<URL> URL_Class = URL.class;
public static final Class<java.util.Date> UTILDATE = java.util.Date.class;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
// - 522312: Add the eclipselink.sequencing.start-sequence-at-nextval property
// 02/20/2018-2.7 Will Dazey
// - 529602: Added support for CLOBs in DELETE statements for Oracle
// 02/01/2022: Tomas Kraus
// - Issue 1442: Implement New JPA API 3.1.0 Features
package org.eclipse.persistence.internal.databaseaccess;

import java.io.IOException;
Expand Down Expand Up @@ -470,6 +472,9 @@ protected void initializePlatformOperators() {
addOperator(ExpressionOperator.today());
addOperator(ExpressionOperator.currentDate());
addOperator(ExpressionOperator.currentTime());
addOperator(ExpressionOperator.localDateTime());
addOperator(ExpressionOperator.localTime());
addOperator(ExpressionOperator.localDate());
addOperator(ExpressionOperator.extract());

// Math
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2021 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2021 IBM Corporation. All rights reserved.
*
* This program and the accompanying materials are made available under the
Expand All @@ -18,33 +18,37 @@
// - 357533: Allow DDL queries to execute even when Multitenant entities are part of the PU
// 03/18/2015-2.6.0 Joe Grassel
// - 462498: Missing isolation level expression in SQL for Derby platform
// 02/01/2022: Tomas Kraus
// - Issue 1442: Implement New JPA API 3.1.0 Features
package org.eclipse.persistence.platform.database;

import java.io.IOException;
import java.io.Writer;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionOperator;
import org.eclipse.persistence.internal.databaseaccess.DatabaseCall;
import org.eclipse.persistence.internal.databaseaccess.FieldTypeDefinition;
import org.eclipse.persistence.internal.expressions.ExpressionJavaPrinter;
import org.eclipse.persistence.internal.expressions.ExpressionSQLPrinter;
import org.eclipse.persistence.internal.expressions.SQLSelectStatement;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.expressions.ExpressionOperator;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.queries.ValueReadQuery;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.io.Writer;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Hashtable;
import java.util.Collection;
import java.util.Iterator;
import org.eclipse.persistence.internal.helper.DatabaseField;

/**
* <p><b>Purpose</b>: Provides Derby DBMS specific behavior.
*
Expand Down Expand Up @@ -313,7 +317,7 @@ protected Hashtable<Class<?>, FieldTypeDefinition> buildFieldTypes() {

fieldTypeMapping.put(java.time.LocalDate.class, new FieldTypeDefinition("DATE"));
fieldTypeMapping.put(java.time.LocalDateTime.class, new FieldTypeDefinition("TIMESTAMP"));
fieldTypeMapping.put(java.time.LocalTime.class, new FieldTypeDefinition("TIMESTAMP"));
fieldTypeMapping.put(java.time.LocalTime.class, new FieldTypeDefinition("TIME"));
fieldTypeMapping.put(java.time.OffsetDateTime.class, new FieldTypeDefinition("TIMESTAMP"));
fieldTypeMapping.put(java.time.OffsetTime.class, new FieldTypeDefinition("TIMESTAMP"));

Expand All @@ -340,6 +344,149 @@ protected void initializePlatformOperators() {
// Derby does not support DECIMAL, but does have a DOUBLE function.
addOperator(ExpressionOperator.simpleFunction(ExpressionOperator.ToNumber, "DOUBLE"));
addOperator(extractOperator());
addOperator(derbyPowerOperator());
addOperator(derbyRoundOperator());
}

// Emulate POWER(:a,:b) as EXP((:b)*LN(:a))
private static ExpressionOperator derbyPowerOperator() {
ExpressionOperator exOperator = new ExpressionOperator() {
@Override
public void printDuo(Expression first, Expression second, ExpressionSQLPrinter printer) {
printer.printString(getDatabaseStrings()[0]);
if (second != null) {
second.printSQL(printer);
} else {
printer.printString("0");
}
printer.printString(getDatabaseStrings()[1]);
first.printSQL(printer);
printer.printString(getDatabaseStrings()[2]);
}
@Override
public void printCollection(List items, ExpressionSQLPrinter printer) {
if (printer.getPlatform().isDynamicSQLRequiredForFunctions() && !isBindingSupported()) {
printer.getCall().setUsesBinding(false);
}
if (items.size() > 0) {
Expression firstItem = (Expression)items.get(0);
Expression secondItem = items.size() > 1 ? (Expression)items.get(1) : null;
printDuo(firstItem, secondItem, printer);
} else {
throw new IllegalArgumentException("List of items shall contain at least one item");
}
}
@Override
public void printJavaDuo(Expression first, Expression second, ExpressionJavaPrinter printer) {
printer.printString(getDatabaseStrings()[0]);
if (second != null) {
second.printJava(printer);
} else {
printer.printString("0");
}
printer.printString(getDatabaseStrings()[1]);
first.printJava(printer);
printer.printString(getDatabaseStrings()[2]);
}
@Override
public void printJavaCollection(List items, ExpressionJavaPrinter printer) {
if (items.size() > 0) {
Expression firstItem = (Expression)items.get(0);
Expression secondItem = items.size() > 1 ? (Expression)items.get(1) : null;
printJavaDuo(firstItem, secondItem, printer);
} else {
throw new IllegalArgumentException("List of items shall contain at least one item");
}
}
};
exOperator.setType(ExpressionOperator.FunctionOperator);
exOperator.setSelector(ExpressionOperator.Power);
exOperator.setName("POWER");
List<String> v = new ArrayList<>(4);
v.add("EXP((");
v.add(")*LN(");
v.add("))");
exOperator.printsAs(v);
exOperator.bePrefix();
exOperator.setNodeClass(ClassConstants.FunctionExpression_Class);
return exOperator;
}

// Emulate ROUND as FLOOR((:x)*1e:n+0.5)/1e:n
private static ExpressionOperator derbyRoundOperator() {
ExpressionOperator exOperator = new ExpressionOperator() {
@Override
public void printDuo(Expression first, Expression second, ExpressionSQLPrinter printer) {
printer.printString(getDatabaseStrings()[0]);
first.printSQL(printer);
printer.printString(getDatabaseStrings()[1]);
if (second != null) {
second.printSQL(printer);
} else {
printer.printString("0");
}
printer.printString(getDatabaseStrings()[2]);
if (second != null) {
second.printSQL(printer);
} else {
printer.printString("0");
}
printer.printString(getDatabaseStrings()[3]);
}
@Override
public void printCollection(List items, ExpressionSQLPrinter printer) {
if (printer.getPlatform().isDynamicSQLRequiredForFunctions() && !isBindingSupported()) {
printer.getCall().setUsesBinding(false);
}
if (items.size() > 0) {
Expression firstItem = (Expression)items.get(0);
Expression secondItem = items.size() > 1 ? (Expression)items.get(1) : null;
printDuo(firstItem, secondItem, printer);
} else {
throw new IllegalArgumentException("List of items shall contain at least one item");
}
}
@Override
public void printJavaDuo(Expression first, Expression second, ExpressionJavaPrinter printer) {
printer.printString(getDatabaseStrings()[0]);
first.printJava(printer);
printer.printString(getDatabaseStrings()[1]);
if (second != null) {
second.printJava(printer);
} else {
printer.printString("0");
}
printer.printString(getDatabaseStrings()[2]);
if (second != null) {
second.printJava(printer);
} else {
printer.printString("0");
}
printer.printString(getDatabaseStrings()[3]);
}
@Override
public void printJavaCollection(List items, ExpressionJavaPrinter printer) {
if (items.size() > 0) {
Expression firstItem = (Expression)items.get(0);
Expression secondItem = items.size() > 1 ? (Expression)items.get(1) : null;
printJavaDuo(firstItem, secondItem, printer);
} else {
throw new IllegalArgumentException("List of items shall contain at least one item");
}
}
};
exOperator.setType(ExpressionOperator.FunctionOperator);
exOperator.setSelector(ExpressionOperator.Round);
exOperator.setName("ROUND");
List<String> v = new ArrayList<>(4);
v.add("FLOOR((");
v.add(")*1e");
v.add("+0.5)/1e");
v.add("");
exOperator.printsAs(v);
exOperator.bePrefix();
exOperator.setNodeClass(ClassConstants.FunctionExpression_Class);
return exOperator;
}

/**
Expand Down

0 comments on commit 243dd93

Please sign in to comment.