-
Notifications
You must be signed in to change notification settings - Fork 175
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
Fix for JPQL queries where identifier clashes with function #2218
Changes from 6 commits
e7f1fba
5d1620a
e07df3a
a0c5fa1
20fa01a
a09bfc9
6221df4
4b7b8f9
87fad3c
5a0a76b
ec20853
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
/* | ||
* Copyright (c) 2006, 2024 Oracle and/or its affiliates. All rights reserved. | ||
* Copyright (c) 2022 IBM Corporation. All rights reserved. | ||
* Copyright (c) 2024 Contributors to the Eclipse Foundation. 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 | ||
|
@@ -1791,35 +1792,6 @@ protected final boolean isNewerThanOrEqual(JPAVersion version) { | |
return getJPAVersion().isNewerThanOrEqual(version); | ||
} | ||
|
||
/** | ||
* Determines whether the given sequence of characters is a numeric literal or not. There are | ||
* two types of numeric literal that is supported: | ||
* <ul> | ||
* <li>Decimal literal</li> | ||
* <li>Hexadecimal literal</li> | ||
* </ul> | ||
* | ||
* @param text The sequence of characters to validate | ||
* @return <code>true</code> if the given sequence of characters is a valid numeric literal; | ||
* <code>false</code> otherwise | ||
*/ | ||
protected boolean isNumericLiteral(String text) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't delete this method, just moved it to the NumericLiteral class and renamed to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So you did an API change in a public API. Is it required to fix the bug? If so, re-do it in a backward compatible way, with appropriate deprecation step eventually, please. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I found a different way to fix the bug, so I reverted removing this method. |
||
|
||
// The ending 'l' or 'L' for a long number has to be removed, Java will not parse it | ||
if (text.endsWith("l") || text.endsWith("L")) { | ||
text = text.substring(0, text.length() - 1); | ||
} | ||
|
||
// Simply try to parse it as a double number (integer and hexadecimal are handled as well) | ||
try { | ||
Double.parseDouble(text); | ||
return true; | ||
} | ||
catch (Exception e2) { | ||
return false; | ||
} | ||
} | ||
|
||
/** | ||
* Determines whether the JPA version for which the JPQL grammar was defined represents a version | ||
* that is older than the given version. | ||
|
@@ -4394,15 +4366,14 @@ public void visit(NullIfExpression expression) { | |
@Override | ||
public void visit(NumericLiteral expression) { | ||
|
||
String text = expression.getText(); | ||
|
||
// - Exact numeric literals support the use of Java integer literal syntax as well as SQL | ||
// exact numeric literal syntax | ||
// - Approximate literals support the use Java floating point literal syntax as well as SQL | ||
// approximate numeric literal syntax | ||
// - Appropriate suffixes can be used to indicate the specific type of a numeric literal in | ||
// accordance with the Java Language Specification | ||
if (!isNumericLiteral(text)) { | ||
if (!expression.hasValidValue()) { | ||
String text = expression.getText(); | ||
int startPosition = position(expression); | ||
int endPosition = startPosition + text.length(); | ||
addProblem(expression, startPosition, endPosition, NumericLiteral_Invalid, text); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
/* | ||
* Copyright (c) 2006, 2022 Oracle and/or its affiliates. All rights reserved. | ||
* Copyright (c) 2022 IBM Corporation. All rights reserved. | ||
* Copyright (c) 2024 Contributors to the Eclipse Foundation. 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 | ||
|
@@ -256,6 +257,7 @@ public int length() { | |
*/ | ||
public void moveBackward(CharSequence word) { | ||
cursor -= word.length(); | ||
wordEndPosition(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Needed to reset the word parser |
||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
/* | ||
* Copyright (c) 2006, 2024 Oracle and/or its affiliates. All rights reserved. | ||
* Copyright (c) 2024 Contributors to the Eclipse Foundation. 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 | ||
|
@@ -516,6 +517,22 @@ public final JPQLExpression getRoot() { | |
return (parent == null) ? (JPQLExpression) this : parent.getRoot(); | ||
} | ||
|
||
/** | ||
* Returns closest nested expression that encapsulates this expression, | ||
* or the root expression if not inside a nested expression. | ||
* | ||
* @return Parent expression | ||
*/ | ||
public final ParentExpression getParentExpression() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For a query "SELECT e Employee e WHERE (SELECT COUNT(m) FROM managedEmployees m) > 0)", it will return root expression for subexpressions related to the |
||
if (this instanceof ParentExpression parentExpression) { | ||
return parentExpression; | ||
} else if (parent == null) { | ||
return null; | ||
} else { | ||
return parent.getParentExpression(); | ||
} | ||
} | ||
|
||
/** | ||
* Returns the encapsulated text of this {@link AbstractExpression}, which can be used in various | ||
* ways, it can be a keyword, a literal, etc. | ||
|
@@ -1133,6 +1150,17 @@ public String toParsedText() { | |
*/ | ||
protected abstract void toParsedText(StringBuilder writer, boolean actual); | ||
|
||
/** | ||
* Whether this expression is not valid and should be discarded. If it returns true, | ||
* the parser will be reverted to the state before this expression was parsed | ||
* and it will attempt to parse a different expression. | ||
* | ||
* @return True if this expression is invalid and should be discarded, otherwise false. By default returns false, should be overriden if expression should be reverted. | ||
*/ | ||
protected boolean shouldBeReverted() { | ||
return false; | ||
} | ||
|
||
@Override | ||
public final String toString() { | ||
// toString() should only be called during debugging, thus the cached parsed text | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no single use of hamcrest in the repo and the project itself is happy without it, so do not add it, please.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed Hamcrest assertions. The hamcrest dependency is transitively brought to the project by junit. Maybe it would be good to exclude hamcrest from the project. I wouldn't use it if I saw it's excluded.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inability to avoid hamcrest dependency is known junit 3/4 issue - see ie junit-team/junit4#1145 and/or junit-team/junit4#1741 if you're interested in details
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is no longer true with latest versions of JUnit 4. The Hamcrest dependency of JUnit can be excluded, see: OmniFish-EE@1e6a11c. Should I raise a PR to do it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did it in #2226
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks not so easy in EclipseLink project. There are test failures in #2226
mvn clean verify -pl :org.eclipse.persistence.jpa.jpql
throws exception inorg.eclipse.persistence.jpa.tests.jpql.AllHermesTests
. I think it's releated with@RunWith
,org.junit.runner.RunWith
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/eclipse-ee4j/eclipselink/actions/runs/10266202341/job/28404036811
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like hamcrest is used somewhere. Maybe by JUnit itself. Here seems to be the same problem: #261. At that time, it looks like it was necessary to add hamcrest on the classpath in Ant configuration. But the problem was the same - something needed Hamcrest.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, JUnit 4 uses hamcrest in several places: https://github.com/search?q=repo%3Ajunit-team%2Fjunit4+hamcrest+language%3AJava&type=code&l=Java. So it's not possible to completely remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A solution could be to make hamcrest a runtime dependency. JUnit would work but it couldn't be used in compiled code.