This is an automated email from the ASF dual-hosted git repository.
ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git
The following commit(s) were added to refs/heads/master by this push:
new b8046c88c CAY-2736 Can't use function names as a path in a
string-based expression
b8046c88c is described below
commit b8046c88c92f5a7617403c292efa8e177ddcafa6
Author: Nikita Timofeev <[email protected]>
AuthorDate: Fri May 20 18:14:03 2022 +0300
CAY-2736 Can't use function names as a path in a string-based expression
---
RELEASE-NOTES.txt | 1 +
.../cayenne/exp/parser/ExpressionParser.java | 201 +++++++++++++++++----
.../exp/parser/ExpressionParserTokenManager.java | 3 +-
.../exp/parser/ExpressionParserTreeConstants.java | 4 +-
.../exp/parser/JJTExpressionParserState.java | 4 +-
.../apache/cayenne/exp/parser/ParseException.java | 48 +++--
.../apache/cayenne/exp/parser/TokenMgrError.java | 37 ++--
.../apache/cayenne/exp/parser/ExpressionParser.jjt | 57 +++++-
.../org/apache/cayenne/exp/ExpressionTest.java | 22 +++
9 files changed, 292 insertions(+), 85 deletions(-)
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index bd6d25c29..b5467ba26 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -23,6 +23,7 @@ CAY-2727 Modeler: cgen destDir Unix platform path separator
CAY-2729 Unable to use custom templates from a folder at upper level then
datamap
CAY-2730 Duplicating lines in a cgen config saved to datamap.xml
CAY-2731 Exception when setting a CLOB on H2 v2.0.202
+CAY-2736 Can't use function names as a path in a string-based expression
----------------------------------
Release: 4.2.B1
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParser.java
b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParser.java
index ece560dae..4c710a485 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParser.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParser.java
@@ -1,3 +1,4 @@
+/* ExpressionParser.java */
/* Generated By:JJTree&JavaCC: Do not edit this line. ExpressionParser.java */
/*****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
@@ -21,6 +22,8 @@
package org.apache.cayenne.exp.parser;
+import java.math.BigDecimal;
+import java.math.BigInteger;
import org.apache.cayenne.exp.Expression;
/**
@@ -2829,69 +2832,69 @@ if (jjtc001) {
}
case 68:{
jj_consume_token(68);
- t = jj_consume_token(PROPERTY_PATH);
+ t = pathToken();
ASTObjPath jjtn002 = new ASTObjPath(JJTOBJPATH);
- boolean jjtc002 = true;
- jjtree.openNodeScope(jjtn002);
+ boolean jjtc002 = true;
+ jjtree.openNodeScope(jjtn002);
try {
jjtree.closeNodeScope(jjtn002, 0);
- jjtc002 = false;
+ jjtc002 = false;
ExpressionUtils.parsePath(jjtn002, t.image);
} finally {
if (jjtc002) {
- jjtree.closeNodeScope(jjtn002, 0);
- }
+ jjtree.closeNodeScope(jjtn002, 0);
+ }
}
break;
}
case 69:{
jj_consume_token(69);
- t = jj_consume_token(PROPERTY_PATH);
+ t = pathToken();
ASTDbPath jjtn003 = new ASTDbPath(JJTDBPATH);
- boolean jjtc003 = true;
- jjtree.openNodeScope(jjtn003);
+ boolean jjtc003 = true;
+ jjtree.openNodeScope(jjtn003);
try {
jjtree.closeNodeScope(jjtn003, 0);
- jjtc003 = false;
+ jjtc003 = false;
ExpressionUtils.parsePath(jjtn003, t.image);
} finally {
if (jjtc003) {
- jjtree.closeNodeScope(jjtn003, 0);
- }
+ jjtree.closeNodeScope(jjtn003, 0);
+ }
}
break;
}
case 70:{
jj_consume_token(70);
- t = jj_consume_token(PROPERTY_PATH);
+ t = pathToken();
ASTEnum jjtn004 = new ASTEnum(JJTENUM);
- boolean jjtc004 = true;
- jjtree.openNodeScope(jjtn004);
+ boolean jjtc004 = true;
+ jjtree.openNodeScope(jjtn004);
try {
jjtree.closeNodeScope(jjtn004, 0);
- jjtc004 = false;
+ jjtc004 = false;
jjtn004.setEnumValue(t.image);
} finally {
if (jjtc004) {
- jjtree.closeNodeScope(jjtn004, 0);
- }
+ jjtree.closeNodeScope(jjtn004, 0);
+ }
}
break;
}
case 71:{
jj_consume_token(71);
- t = jj_consume_token(PROPERTY_PATH);
+ t = pathToken();
ASTDbIdPath jjtn005 = new ASTDbIdPath(JJTDBIDPATH);
- boolean jjtc005 = true;
- jjtree.openNodeScope(jjtn005);
+ boolean jjtc005 = true;
+ jjtree.openNodeScope(jjtn005);
try {
jjtree.closeNodeScope(jjtn005, 0);
- jjtc005 = false;
+ jjtc005 = false;
ExpressionUtils.parsePath(jjtn005, t.image);
} finally {
if (jjtc005) {
- jjtree.closeNodeScope(jjtn005, 0);
- }
+ jjtree.closeNodeScope(jjtn005, 0);
+ }
}
break;
}
@@ -2902,6 +2905,134 @@ if (jjtc005) {
}
}
+// this rule returns single token that could be used as a path definition
+ final public Token pathToken() throws ParseException {Token t ;
+ switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
+ case PROPERTY_PATH:{
+ t = jj_consume_token(PROPERTY_PATH);
+ break;
+ }
+ case AVG:{
+ t = jj_consume_token(AVG);
+ break;
+ }
+ case MIN:{
+ t = jj_consume_token(MIN);
+ break;
+ }
+ case MAX:{
+ t = jj_consume_token(MAX);
+ break;
+ }
+ case SUM:{
+ t = jj_consume_token(SUM);
+ break;
+ }
+ case COUNT:{
+ t = jj_consume_token(COUNT);
+ break;
+ }
+ case DISTINCT:{
+ t = jj_consume_token(DISTINCT);
+ break;
+ }
+ case CONCAT:{
+ t = jj_consume_token(CONCAT);
+ break;
+ }
+ case SUBSTRING:{
+ t = jj_consume_token(SUBSTRING);
+ break;
+ }
+ case TRIM:{
+ t = jj_consume_token(TRIM);
+ break;
+ }
+ case LOWER:{
+ t = jj_consume_token(LOWER);
+ break;
+ }
+ case UPPER:{
+ t = jj_consume_token(UPPER);
+ break;
+ }
+ case LENGTH:{
+ t = jj_consume_token(LENGTH);
+ break;
+ }
+ case LOCATE:{
+ t = jj_consume_token(LOCATE);
+ break;
+ }
+ case ABS:{
+ t = jj_consume_token(ABS);
+ break;
+ }
+ case SQRT:{
+ t = jj_consume_token(SQRT);
+ break;
+ }
+ case MOD:{
+ t = jj_consume_token(MOD);
+ break;
+ }
+ case CURRENT_DATE:{
+ t = jj_consume_token(CURRENT_DATE);
+ break;
+ }
+ case CURRENT_TIME:{
+ t = jj_consume_token(CURRENT_TIME);
+ break;
+ }
+ case CURRENT_TIMESTAMP:{
+ t = jj_consume_token(CURRENT_TIMESTAMP);
+ break;
+ }
+ case YEAR:{
+ t = jj_consume_token(YEAR);
+ break;
+ }
+ case MONTH:{
+ t = jj_consume_token(MONTH);
+ break;
+ }
+ case DAY:{
+ t = jj_consume_token(DAY);
+ break;
+ }
+ case HOUR:{
+ t = jj_consume_token(HOUR);
+ break;
+ }
+ case MINUTE:{
+ t = jj_consume_token(MINUTE);
+ break;
+ }
+ case SECOND:{
+ t = jj_consume_token(SECOND);
+ break;
+ }
+ case DAY_OF_MONTH:{
+ t = jj_consume_token(DAY_OF_MONTH);
+ break;
+ }
+ case DAY_OF_WEEK:{
+ t = jj_consume_token(DAY_OF_WEEK);
+ break;
+ }
+ case DAY_OF_YEAR:{
+ t = jj_consume_token(DAY_OF_YEAR);
+ break;
+ }
+ default:
+ jj_la1[47] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+{if ("" != null) return t;}
+ throw new Error("Missing return statement in function");
+}
+
/** Generated Token Manager. */
public ExpressionParserTokenManager token_source;
JavaCharStream jj_input_stream;
@@ -2911,7 +3042,7 @@ if (jjtc005) {
public Token jj_nt;
private int jj_ntk;
private int jj_gen;
- final private int[] jj_la1 = new int[47];
+ final private int[] jj_la1 = new int[48];
static private int[] jj_la1_0;
static private int[] jj_la1_1;
static private int[] jj_la1_2;
@@ -2921,13 +3052,13 @@ if (jjtc005) {
jj_la1_init_2();
}
private static void jj_la1_init_0() {
- jj_la1_0 = new int[]
{0x2,0x4,0x18,0x16010018,0x60,0x180,0x10000,0x4fff8,0x4fff8,0x16010000,0x18,0x10000,0x4e000,0x80000,0x16010000,0x0,0x0,0x0,0x16010000,0x0,0x100000,0x200000,0x400000,0x1800000,0x1800000,0x6000000,0x6000000,0x8000000,0x8000000,0x16010000,0x2000000,0x6010000,0x10000,0x0,0x80000,0x16010000,0x80000,0x16010000,0x80000,0x80000,0x0,0x80000,0x0,0x0,0x0,0x0,0x0,};
+ jj_la1_0 = new int[]
{0x2,0x4,0x18,0x16010018,0x60,0x180,0x10000,0x4fff8,0x4fff8,0x16010000,0x18,0x10000,0x4e000,0x80000,0x16010000,0x0,0x0,0x0,0x16010000,0x0,0x100000,0x200000,0x400000,0x1800000,0x1800000,0x6000000,0x6000000,0x8000000,0x8000000,0x16010000,0x2000000,0x6010000,0x10000,0x0,0x80000,0x16010000,0x80000,0x16010000,0x80000,0x80000,0x0,0x80000,0x0,0x0,0x0,0x0,0x0,0x0,};
}
private static void jj_la1_init_1() {
- jj_la1_1 = new int[]
{0x0,0x0,0x0,0xfffffdfe,0x0,0x0,0x0,0x0,0x0,0xfffffdfe,0x0,0x0,0x0,0x0,0xfffffdf2,0x7c00,0x0,0x7c00,0xfffffdfe,0xc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xff8f8000,0x0,0xff8f8000,0xff8f8000,0x7c00,0x0,0xff8ffc00,0x0,0xff8ffc00,0x0,0x0,0xff8f8000,0x0,0x1f0,0x200,0x700000,0xff800000,0x0,};
+ jj_la1_1 = new int[]
{0x0,0x0,0x0,0xfffffdfe,0x0,0x0,0x0,0x0,0x0,0xfffffdfe,0x0,0x0,0x0,0x0,0xfffffdf2,0x7c00,0x0,0x7c00,0xfffffdfe,0xc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xff8f8000,0x0,0xff8f8000,0xff8f8000,0x7c00,0x0,0xff8ffc00,0x0,0xff8ffc00,0x0,0x0,0xff8f8000,0x0,0x1f0,0x200,0x700000,0xff800000,0x0,0xfdfffff0,};
}
private static void jj_la1_init_2() {
- jj_la1_2 = new int[]
{0x0,0x0,0x0,0xe402ff,0x0,0x0,0x8,0x0,0x0,0xe402ff,0x0,0x8,0x0,0x0,0xe402ff,0x2402f0,0x240000,0x240000,0xe402ff,0xe40008,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100,0x100,0xc002ff,0x0,0xc002ff,0xc002ff,0x0,0x0,0xe402ff,0x0,0xe402ff,0x0,0x0,0x1,0x0,0x0,0x3f0,0x0,0x1,0x2f0,};
+ jj_la1_2 = new int[]
{0x0,0x0,0x0,0xe402ff,0x0,0x0,0x8,0x0,0x0,0xe402ff,0x0,0x8,0x0,0x0,0xe402ff,0x2402f0,0x240000,0x240000,0xe402ff,0xe40008,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100,0x100,0xc002ff,0x0,0xc002ff,0xc002ff,0x0,0x0,0xe402ff,0x0,0xe402ff,0x0,0x0,0x1,0x0,0x0,0x3f0,0x0,0x1,0x2f0,0x201,};
}
/** Constructor with InputStream. */
@@ -2941,7 +3072,7 @@ if (jjtc005) {
token = new Token();
jj_ntk = -1;
jj_gen = 0;
- for (int i = 0; i < 47; i++) jj_la1[i] = -1;
+ for (int i = 0; i < 48; i++) jj_la1[i] = -1;
}
/** Reinitialise. */
@@ -2956,7 +3087,7 @@ if (jjtc005) {
jj_ntk = -1;
jjtree.reset();
jj_gen = 0;
- for (int i = 0; i < 47; i++) jj_la1[i] = -1;
+ for (int i = 0; i < 48; i++) jj_la1[i] = -1;
}
/** Constructor. */
@@ -2966,7 +3097,7 @@ if (jjtc005) {
token = new Token();
jj_ntk = -1;
jj_gen = 0;
- for (int i = 0; i < 47; i++) jj_la1[i] = -1;
+ for (int i = 0; i < 48; i++) jj_la1[i] = -1;
}
/** Reinitialise. */
@@ -2985,7 +3116,7 @@ if (jjtc005) {
jj_ntk = -1;
jjtree.reset();
jj_gen = 0;
- for (int i = 0; i < 47; i++) jj_la1[i] = -1;
+ for (int i = 0; i < 48; i++) jj_la1[i] = -1;
}
/** Constructor with generated Token Manager. */
@@ -2994,7 +3125,7 @@ if (jjtc005) {
token = new Token();
jj_ntk = -1;
jj_gen = 0;
- for (int i = 0; i < 47; i++) jj_la1[i] = -1;
+ for (int i = 0; i < 48; i++) jj_la1[i] = -1;
}
/** Reinitialise. */
@@ -3004,7 +3135,7 @@ if (jjtc005) {
jj_ntk = -1;
jjtree.reset();
jj_gen = 0;
- for (int i = 0; i < 47; i++) jj_la1[i] = -1;
+ for (int i = 0; i < 48; i++) jj_la1[i] = -1;
}
private Token jj_consume_token(int kind) throws ParseException {
@@ -3060,7 +3191,7 @@ if (jjtc005) {
la1tokens[jj_kind] = true;
jj_kind = -1;
}
- for (int i = 0; i < 47; i++) {
+ for (int i = 0; i < 48; i++) {
if (jj_la1[i] == jj_gen) {
for (int j = 0; j < 32; j++) {
if ((jj_la1_0[i] & (1<<j)) != 0) {
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserTokenManager.java
b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserTokenManager.java
index 697688090..2bcb7bfcf 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserTokenManager.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserTokenManager.java
@@ -1,3 +1,4 @@
+/* ExpressionParserTokenManager.java */
/* Generated By:JJTree&JavaCC: Do not edit this line.
ExpressionParserTokenManager.java */
/*****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
@@ -2792,5 +2793,5 @@ static final long[] jjtoMore = {
private StringBuilder image = jjimage;
private int jjimageLen;
private int lengthOfMatch;
- protected char curChar;
+ protected int curChar;
}
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserTreeConstants.java
b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserTreeConstants.java
index c3b3539a8..ab38843b2 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserTreeConstants.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserTreeConstants.java
@@ -1,4 +1,4 @@
-/* Generated By:JavaCC: Do not edit this line.
ExpressionParserTreeConstants.java Version 7.0.5 */
+/* Generated By:JavaCC: Do not edit this line.
ExpressionParserTreeConstants.java Version 7.0.11 */
package org.apache.cayenne.exp.parser;
public interface ExpressionParserTreeConstants
@@ -130,4 +130,4 @@ public interface ExpressionParserTreeConstants
"DbIdPath",
};
}
-/* JavaCC - OriginalChecksum=cd72c6d845f6bcd460bdcd71d3700282 (do not edit
this line) */
+/* JavaCC - OriginalChecksum=a6c359f491d0d2af8555386242238a43 (do not edit
this line) */
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/JJTExpressionParserState.java
b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/JJTExpressionParserState.java
index 063fef2d9..139896c7a 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/JJTExpressionParserState.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/JJTExpressionParserState.java
@@ -1,4 +1,4 @@
-/* Generated By:JavaCC: Do not edit this line. JJTExpressionParserState.java
Version 7.0.5 */
+/* Generated By:JavaCC: Do not edit this line. JJTExpressionParserState.java
Version 7.0.11 */
package org.apache.cayenne.exp.parser;
public class JJTExpressionParserState {
@@ -120,4 +120,4 @@ public class JJTExpressionParserState {
}
}
}
-/* JavaCC - OriginalChecksum=4600ff3b66322d8f3f50176b034a1b48 (do not edit
this line) */
+/* JavaCC - OriginalChecksum=2565d2cc35252acbdc49135562b6fa02 (do not edit
this line) */
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ParseException.java
b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ParseException.java
index d8c439e41..f20110b8f 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ParseException.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ParseException.java
@@ -1,5 +1,5 @@
-/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 5.0
*/
-/* JavaCCOptions:KEEP_LINE_COL=null */
+/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 7.0
*/
+/* JavaCCOptions:KEEP_LINE_COLUMN=true */
/*****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -40,6 +40,11 @@ public class ParseException extends Exception {
*/
private static final long serialVersionUID = 1L;
+ /**
+ * The end of line string for this machine.
+ */
+ protected static String EOL = System.getProperty("line.separator", "\n");
+
/**
* This constructor is used by the method "generateParseException"
* in the generated parser. Calling this constructor generates
@@ -80,7 +85,7 @@ public class ParseException extends Exception {
/**
* This is the last token that has been consumed successfully. If
* this object has been created due to a parse error, the token
- * followng this token will (therefore) be the first error token.
+ * following this token will (therefore) be the first error token.
*/
public Token currentToken;
@@ -108,8 +113,8 @@ public class ParseException extends Exception {
private static String initialise(Token currentToken,
int[][] expectedTokenSequences,
String[] tokenImage) {
- String eol = System.getProperty("line.separator", "\n");
- StringBuffer expected = new StringBuffer();
+
+ StringBuilder expected = new StringBuilder();
int maxSize = 0;
for (int i = 0; i < expectedTokenSequences.length; i++) {
if (maxSize < expectedTokenSequences[i].length) {
@@ -121,7 +126,7 @@ public class ParseException extends Exception {
if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] !=
0) {
expected.append("...");
}
- expected.append(eol).append(" ");
+ expected.append(EOL).append(" ");
}
String retval = "Encountered \"";
Token tok = currentToken.next;
@@ -137,21 +142,26 @@ public class ParseException extends Exception {
retval += " \"";
tok = tok.next;
}
- retval += "\" at line " + currentToken.next.beginLine + ", column " +
currentToken.next.beginColumn;
- retval += "." + eol;
- if (expectedTokenSequences.length == 1) {
- retval += "Was expecting:" + eol + " ";
+ if (currentToken.next != null) {
+ retval += "\" at line " + currentToken.next.beginLine + ", column " +
currentToken.next.beginColumn;
+ }
+ retval += "." + EOL;
+
+
+ if (expectedTokenSequences.length == 0) {
+ // Nothing to add here
} else {
- retval += "Was expecting one of:" + eol + " ";
+ if (expectedTokenSequences.length == 1) {
+ retval += "Was expecting:" + EOL + " ";
+ } else {
+ retval += "Was expecting one of:" + EOL + " ";
+ }
+ retval += expected.toString();
}
- retval += expected.toString();
+
return retval;
}
- /**
- * The end of line string for this machine.
- */
- protected String eol = System.getProperty("line.separator", "\n");
/**
* Used to convert raw characters to their escaped version
@@ -159,13 +169,11 @@ public class ParseException extends Exception {
* string literal.
*/
static String add_escapes(String str) {
- StringBuffer retval = new StringBuffer();
+ StringBuilder retval = new StringBuilder();
char ch;
for (int i = 0; i < str.length(); i++) {
switch (str.charAt(i))
{
- case 0 :
- continue;
case '\b':
retval.append("\\b");
continue;
@@ -204,4 +212,4 @@ public class ParseException extends Exception {
}
}
-/* JavaCC - OriginalChecksum=eb8dac072dfd4dad1a11088427fd2da3 (do not edit
this line) */
+/* JavaCC - OriginalChecksum=7691b3e8db296ac7fb754fa94b972967 (do not edit
this line) */
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/TokenMgrError.java
b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/TokenMgrError.java
index c7850b17e..1289469eb 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/TokenMgrError.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/TokenMgrError.java
@@ -1,4 +1,4 @@
-/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 5.0
*/
+/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 7.0
*/
/* JavaCCOptions: */
/*****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
@@ -40,22 +40,22 @@ public class TokenMgrError extends Error
/**
* Lexical error occurred.
*/
- static final int LEXICAL_ERROR = 0;
+ public static final int LEXICAL_ERROR = 0;
/**
* An attempt was made to create a second instance of a static token manager.
*/
- static final int STATIC_LEXER_ERROR = 1;
+ public static final int STATIC_LEXER_ERROR = 1;
/**
* Tried to change to an invalid lexical state.
*/
- static final int INVALID_LEXICAL_STATE = 2;
+ public static final int INVALID_LEXICAL_STATE = 2;
/**
* Detected (and bailed out of) an infinite loop in the token manager.
*/
- static final int LOOP_DETECTED = 3;
+ public static final int LOOP_DETECTED = 3;
/**
* Indicates the reason why the exception is thrown. It will have
@@ -68,13 +68,11 @@ public class TokenMgrError extends Error
* equivalents in the given string
*/
protected static final String addEscapes(String str) {
- StringBuffer retval = new StringBuffer();
+ StringBuilder retval = new StringBuilder();
char ch;
for (int i = 0; i < str.length(); i++) {
switch (str.charAt(i))
{
- case 0 :
- continue;
case '\b':
retval.append("\\b");
continue;
@@ -117,19 +115,21 @@ public class TokenMgrError extends Error
* token manager to indicate a lexical error.
* Parameters :
* EOFSeen : indicates if EOF caused the lexical error
- * curLexState : lexical state in which this error occurred
+ * lexState : lexical state in which this error occurred
* errorLine : line number when the error occurred
* errorColumn : column number when the error occurred
* errorAfter : prefix that was seen before this error occurred
* curchar : the offending character
* Note: You can customize the lexical error message by modifying this
method.
*/
- protected static String LexicalError(boolean EOFSeen, int lexState, int
errorLine, int errorColumn, String errorAfter, char curChar) {
- return("Lexical error at line " +
- errorLine + ", column " +
- errorColumn + ". Encountered: " +
- (EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) +
"\"") + " (" + (int)curChar + "), ") +
- "after : \"" + addEscapes(errorAfter) + "\"");
+ protected static String LexicalErr(boolean EOFSeen, int lexState, int
errorLine, int errorColumn, String errorAfter, int curChar) {
+ char curChar1 = (char)curChar;
+ return("Lexical error at line " + //
+ errorLine + ", column " + //
+ errorColumn + ". Encountered: " + //
+ (EOFSeen ? "<EOF>" : ("'" + addEscapes(String.valueOf(curChar)) + "'
(" + (int)curChar + "),")) + //
+ (errorAfter == null || errorAfter.length() == 0 ? "" : " after
prefix \"" + addEscapes(errorAfter) + "\"")) + //
+ (lexState == 0 ? "" : " (in lexical state " + lexState + ")");
}
/**
@@ -141,6 +141,7 @@ public class TokenMgrError extends Error
*
* from this method for such cases in the release version of your parser.
*/
+ @Override
public String getMessage() {
return super.getMessage();
}
@@ -160,8 +161,8 @@ public class TokenMgrError extends Error
}
/** Full Constructor. */
- public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int
errorColumn, String errorAfter, char curChar, int reason) {
- this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter,
curChar), reason);
+ public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int
errorColumn, String errorAfter, int curChar, int reason) {
+ this(LexicalErr(EOFSeen, lexState, errorLine, errorColumn, errorAfter,
curChar), reason);
}
}
-/* JavaCC - OriginalChecksum=347e14790694eecc248c9f72c50d0b1d (do not edit
this line) */
+/* JavaCC - OriginalChecksum=5088d3d182ac63ec68e3c489b6f0b93c (do not edit
this line) */
diff --git
a/cayenne-server/src/main/jjtree/org/apache/cayenne/exp/parser/ExpressionParser.jjt
b/cayenne-server/src/main/jjtree/org/apache/cayenne/exp/parser/ExpressionParser.jjt
index 90fbea299..0b3200340 100644
---
a/cayenne-server/src/main/jjtree/org/apache/cayenne/exp/parser/ExpressionParser.jjt
+++
b/cayenne-server/src/main/jjtree/org/apache/cayenne/exp/parser/ExpressionParser.jjt
@@ -440,7 +440,7 @@ void dateTimeExtractingFunction() #Extract(1) : {
void distinct() #Distinct : { }
{
- <DISTINCT> "(" ( pathExpression() ) ")"
+ <DISTINCT> "(" pathExpression() ")"
}
TOKEN_MGR_DECLS:
@@ -606,23 +606,66 @@ void pathExpression() : {
Token t;
}
{
- (
t = <PROPERTY_PATH> { ExpressionUtils.parsePath(jjtThis,
t.image); } #ObjPath(0)
|
- "obj:" t = <PROPERTY_PATH> { ExpressionUtils.parsePath(jjtThis,
t.image); } #ObjPath(0)
+ "obj:" t = pathToken() { ExpressionUtils.parsePath(jjtThis, t.image); }
#ObjPath(0)
|
- "db:" t = <PROPERTY_PATH> { ExpressionUtils.parsePath(jjtThis,
t.image); } #DbPath(0)
+ "db:" t = pathToken() { ExpressionUtils.parsePath(jjtThis, t.image); }
#DbPath(0)
|
- "enum:" t = <PROPERTY_PATH> { jjtThis.setEnumValue(t.image); } #Enum(0)
+ "enum:" t = pathToken() { jjtThis.setEnumValue(t.image); } #Enum(0)
|
- "dbid:" t = <PROPERTY_PATH> { ExpressionUtils.parsePath(jjtThis,
t.image); } #DbIdPath(0)
- )
+ "dbid:" t = pathToken() { ExpressionUtils.parsePath(jjtThis, t.image); }
#DbIdPath(0)
}
TOKEN : {
<ASTERISK: "*">
}
+// this rule returns single token that could be used as a path definition
+Token pathToken() : {
+ Token t ;
+}
+{
+ (
+ t = <PROPERTY_PATH>
+
+ | t = <AVG>
+ | t = <MIN>
+ | t = <MAX>
+ | t = <SUM>
+ | t = <COUNT>
+ | t = <DISTINCT>
+
+ | t = <CONCAT>
+ | t = <SUBSTRING>
+ | t = <TRIM>
+ | t = <LOWER>
+ | t = <UPPER>
+
+ | t = <LENGTH>
+ | t = <LOCATE>
+ | t = <ABS>
+ | t = <SQRT>
+ | t = <MOD>
+
+ | t = <CURRENT_DATE>
+ | t = <CURRENT_TIME>
+ | t = <CURRENT_TIMESTAMP>
+
+ | t = <YEAR>
+ | t = <MONTH>
+ | t = <DAY>
+ | t = <HOUR>
+ | t = <MINUTE>
+ | t = <SECOND>
+ | t = <DAY_OF_MONTH>
+ | t = <DAY_OF_WEEK>
+ | t = <DAY_OF_YEAR>
+
+ )
+ {return t;}
+}
+
TOKEN : {
<PROPERTY_PATH: <IDENTIFIER> ( "." <IDENTIFIER>) *>
}
diff --git
a/cayenne-server/src/test/java/org/apache/cayenne/exp/ExpressionTest.java
b/cayenne-server/src/test/java/org/apache/cayenne/exp/ExpressionTest.java
index 86aa667e7..5af763f74 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/exp/ExpressionTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/ExpressionTest.java
@@ -19,6 +19,7 @@
package org.apache.cayenne.exp;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.ArrayList;
@@ -26,7 +27,9 @@ import java.util.Date;
import java.util.List;
import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.exp.parser.ASTDbPath;
import org.apache.cayenne.exp.parser.ASTFalse;
+import org.apache.cayenne.exp.parser.ASTObjPath;
import org.apache.cayenne.exp.parser.SimpleNode;
import org.apache.cayenne.testdo.testmap.Artist;
import org.junit.Test;
@@ -442,4 +445,23 @@ public class ExpressionTest {
assertEquals("true and true", transformed.toString());
}
+ @Test
+ public void testObjPathFunctionName() throws IOException {
+ Expression exp =
ExpressionFactory.exp("obj:year.month.day.avg");
+ assertTrue(exp instanceof ASTObjPath);
+
+ StringBuilder buffer = new StringBuilder();
+ exp.appendAsString(buffer);
+ assertEquals("year.month.day.avg", buffer.toString());
+ }
+
+ @Test
+ public void testDbPathFunctionName() throws IOException {
+ Expression exp = ExpressionFactory.exp("db:year.month.day.avg");
+ assertTrue(exp instanceof ASTDbPath);
+
+ StringBuilder buffer = new StringBuilder();
+ exp.appendAsString(buffer);
+ assertEquals("db:year.month.day.avg", buffer.toString());
+ }
}