Skip to content

Commit

Permalink
New JPQL 3.2 and || as a String concat operator (#1903)
Browse files Browse the repository at this point in the history
This commit contains following changes:

    New JPQL Grammar 3.2 (version matches upcoming Jakarta Persistence 3.2) and EclipseLink JPQL Grammar 4.1
    New JPQL String expression category with related classes (like arithmetic expression)
    New JPQL String operator || for string concatenation like JPQL CONCAT(....) function
    Tests are available in JPQL parser and JPA JSE test module
    EclipseLink issue is described at 

Implement new JPQLGrammar for upcoming Jakarta Persistence 3.2 #1885 and JPA specification request at the JPQL || operator for string concatenation jakartaee/persistence#397
|| operator is handled at JPQL level, but translated into SQL function CONCAT(...) as not every database supports || or is mentioned as OR logical operator (MySQL).

Signed-off-by: Radek Felcman <radek.felcman@oracle.com>
  • Loading branch information
rfelcman committed Jul 17, 2023
1 parent eea7f20 commit 9cb4c43
Show file tree
Hide file tree
Showing 51 changed files with 1,914 additions and 55 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand All @@ -14,6 +14,8 @@
// Oracle - initial API and implementation from Oracle TopLink
// 04/21/2022: Tomas Kraus
// - Issue 1474: Update JPQL Grammar for Jakarta Persistence 2.2, 3.0 and 3.1
// 06/02/2023: Radek Felcman
// - Issue 1885: Implement new JPQLGrammar for upcoming Jakarta Persistence 3.2
package org.eclipse.persistence.config;

/**
Expand All @@ -34,6 +36,7 @@ public class ParserValidationType {
public static final String JPA22 = "JPA 2.2";
public static final String JPA30 = "JPA 3.0";
public static final String JPA31 = "JPA 3.1";
public static final String JPA32 = "JPA 3.2";
public static final String None = "None";

public static final String DEFAULT = EclipseLink;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2022 IBM Corporation. All rights reserved.
*
* This program and the accompanying materials are made available under the
Expand All @@ -20,6 +20,8 @@
// - 530214: trim operation should not bind parameters
// 02/01/2022: Tomas Kraus
// - Issue 1442: Implement New Jakarta Persistence 3.1 Features
// 06/02/2023: Radek Felcman
// - Issue 1885: Implement new JPQLGrammar for upcoming Jakarta Persistence 3.2
package org.eclipse.persistence.expressions;

import java.io.Serializable;
Expand Down Expand Up @@ -260,6 +262,9 @@ public class ExpressionOperator implements Serializable {
public static final int Cot = 95;
public static final int Negate = 135;

// String
public static final int ConcatPipes = 152;

// Object-relational
public static final int Deref = 82;
public static final int Ref = 83;
Expand Down Expand Up @@ -736,6 +741,16 @@ public static ExpressionOperator concat() {
return operator;
}

/**
* INTERNAL:
* Build operator.
*/
public static ExpressionOperator concatPipes() {
ExpressionOperator operator = simpleMath(ConcatPipes, "||");
operator.setIsBindingSupported(false);
return operator;
}

/**
* INTERNAL:
* Compare between in memory.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/

// Contributors:
// Oracle - initial API and implementation
// 06/02/2023: Radek Felcman
// - Issue 1885: Implement new JPQLGrammar for upcoming Jakarta Persistence 3.2
package org.eclipse.persistence.expressions;

/**
* <p>
* <b>Purpose</b>: This class contains String operators.</p>
* <p>Example:
* <blockquote><pre>
* ExpressionBuilder builder = new ExpressionBuilder();
* Expression stringResult = ExpressionString.concatPipes("abcd", "xyz");
* session.readAllObjects(Company.class, stringResult);
* </pre></blockquote>
*/
public final class ExpressionString {

private ExpressionString() {
}

/**
* PUBLIC:
* Return a new expression that applies the function to the given expression.
*/
public static Expression concatPipes(Expression right, Object left) {
ExpressionOperator anOperator = Expression.getOperator(ExpressionOperator.ConcatPipes);
return anOperator.expressionFor(right, left);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
// - 529602: Added support for CLOBs in DELETE statements for Oracle
// 02/01/2022: Tomas Kraus
// - Issue 1442: Implement New Jakarta Persistence 3.1 Features
// 06/02/2023: Radek Felcman
// - Issue 1885: Implement new JPQLGrammar for upcoming Jakarta Persistence 3.2
package org.eclipse.persistence.internal.databaseaccess;

import java.io.IOException;
Expand Down Expand Up @@ -452,6 +454,7 @@ protected void initializePlatformOperators() {
addOperator(ExpressionOperator.toLowerCase());
addOperator(ExpressionOperator.chr());
addOperator(ExpressionOperator.concat());
addOperator(ExpressionOperator.concatPipes());
addOperator(ExpressionOperator.hexToRaw());
addOperator(ExpressionOperator.initcap());
addOperator(ExpressionOperator.instring());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2021 IBM Corporation. All rights reserved.
*
* This program and the accompanying materials are made available under the
Expand All @@ -24,6 +24,8 @@
// 04/21/2022: Tomas Kraus
// - Issue 1474: Update JPQL Grammar for Jakarta Persistence 2.2, 3.0 and 3.1
// - Issue 317: Implement LOCAL DATE, LOCAL TIME and LOCAL DATETIME.
// 06/02/2023: Radek Felcman
// - Issue 1885: Implement new JPQLGrammar for upcoming Jakarta Persistence 3.2
package org.eclipse.persistence.internal.jpa.jpql;

import java.sql.Date;
Expand Down Expand Up @@ -78,6 +80,7 @@
import org.eclipse.persistence.jpa.jpql.parser.CollectionValuedPathExpression;
import org.eclipse.persistence.jpa.jpql.parser.ComparisonExpression;
import org.eclipse.persistence.jpa.jpql.parser.ConcatExpression;
import org.eclipse.persistence.jpa.jpql.parser.ConcatPipesExpression;
import org.eclipse.persistence.jpa.jpql.parser.ConnectByClause;
import org.eclipse.persistence.jpa.jpql.parser.ConstructorExpression;
import org.eclipse.persistence.jpa.jpql.parser.CountFunction;
Expand Down Expand Up @@ -797,6 +800,31 @@ public void visit(ConcatExpression expression) {
type[0] = String.class;
}

@Override
public void visit(ConcatPipesExpression expression) {
//Convert || string operator into function CONCAT() as not every DB supports it
//but DB platform should translate it into platform valid SQL
List<org.eclipse.persistence.jpa.jpql.parser.Expression> expressions = new ArrayList<>(2);
expressions.add(expression.getLeftExpression());
expressions.add(expression.getRightExpression());
Expression newExpression = null;

for (org.eclipse.persistence.jpa.jpql.parser.Expression child : expressions) {
child.accept(this);
if (newExpression == null) {
newExpression = queryExpression;
}
else {
newExpression = newExpression.concat(queryExpression);
}
}

queryExpression = newExpression;

// Set the expression type
type[0] = String.class;
}

@Override
public void visit(ConnectByClause expression) {
expression.getExpression().accept(this);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand All @@ -14,6 +14,8 @@
// Oracle - initial API and implementation
// 04/21/2022: Tomas Kraus
// - Issue 1474: Update JPQL Grammar for Jakarta Persistence 2.2, 3.0 and 3.1
// 06/02/2023: Radek Felcman
// - Issue 1885: Implement new JPQLGrammar for upcoming Jakarta Persistence 3.2
package org.eclipse.persistence.internal.jpa.jpql;

import java.text.MessageFormat;
Expand Down Expand Up @@ -43,6 +45,7 @@
import org.eclipse.persistence.jpa.jpql.parser.JPQLGrammar2_2;
import org.eclipse.persistence.jpa.jpql.parser.JPQLGrammar3_0;
import org.eclipse.persistence.jpa.jpql.parser.JPQLGrammar3_1;
import org.eclipse.persistence.jpa.jpql.parser.JPQLGrammar3_2;
import org.eclipse.persistence.jpa.jpql.parser.SelectStatement;
import org.eclipse.persistence.jpa.jpql.parser.UpdateStatement;
import org.eclipse.persistence.queries.DatabaseQuery;
Expand Down Expand Up @@ -240,6 +243,8 @@ private JPQLGrammar jpqlGrammar() {
return JPQLGrammar3_0.instance();
case ParserValidationType.JPA31:
return JPQLGrammar3_1.instance();
case ParserValidationType.JPA32:
return JPQLGrammar3_2.instance();
default:
return DefaultEclipseLinkJPQLGrammar.instance();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019 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
// 04/21/2022: Tomas Kraus
// - Issue 1474: Update JPQL Grammar for Jakarta Persistence 2.2, 3.0 and 3.1
// 06/02/2023: Radek Felcman
// - Issue 1885: Implement new JPQLGrammar for upcoming Jakarta Persistence 3.2
package org.eclipse.persistence.internal.jpa.jpql;

import java.util.ArrayList;
Expand All @@ -34,6 +36,7 @@
import org.eclipse.persistence.jpa.jpql.parser.CollectionExpression;
import org.eclipse.persistence.jpa.jpql.parser.CollectionValuedPathExpression;
import org.eclipse.persistence.jpa.jpql.parser.ConcatExpression;
import org.eclipse.persistence.jpa.jpql.parser.ConcatPipesExpression;
import org.eclipse.persistence.jpa.jpql.parser.ConstructorExpression;
import org.eclipse.persistence.jpa.jpql.parser.CountFunction;
import org.eclipse.persistence.jpa.jpql.parser.DateTime;
Expand Down Expand Up @@ -231,6 +234,18 @@ public void visit(ConcatExpression expression) {
addAttribute(ExpressionTools.EMPTY_STRING, queryExpression, type[0]);
}

@Override
public void visit(ConcatPipesExpression expression) {

Expression queryExpression = queryContext.buildExpression(expression, type);

if (type[0] == Object.class) {
type[0] = null;
}

addAttribute("ConcatPipes", queryExpression, type[0]);
}

@Override
public void visit(ConstructorExpression expression) {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand All @@ -15,6 +15,8 @@
// 04/21/2022: Tomas Kraus
// - Issue 1474: Update JPQL Grammar for Jakarta Persistence 2.2, 3.0 and 3.1
// - Issue 317: Implement LOCAL DATE, LOCAL TIME and LOCAL DATETIME.
// 06/02/2023: Radek Felcman
// - Issue 1885: Implement new JPQLGrammar for upcoming Jakarta Persistence 3.2
package org.eclipse.persistence.internal.jpa.jpql;

import java.lang.reflect.Field;
Expand Down Expand Up @@ -547,6 +549,11 @@ public void visit(ConcatExpression expression) {
type = String.class;
}

@Override
public void visit(ConcatPipesExpression expression) {
type = String.class;
}

@Override
public void visit(ConnectByClause expression) {
type = Object.class;
Expand Down

0 comments on commit 9cb4c43

Please sign in to comment.