diff --git a/CHANGELOG.md b/CHANGELOG.md index 2974b08dab6512faab2ca7cc37a0b6ac8b0f309c..7996c53a80d5a7a363baa5bcddbec7e4bf0a6440 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +* #131 - CQL Parsing error when white space characters before some units. +* #134 - CQL Parsing error when multiple white space characters after `FROM`. * #130 - Error during `FIND ENTITY` when `QUERY_FILTER_ENTITIES_WITHOUT_RETRIEVE_PERMISSIONS=False`. * #125 - `bend_symlinks` script did not allow whitespace in filename. diff --git a/src/main/java/org/caosdb/server/query/CQLLexer.g4 b/src/main/java/org/caosdb/server/query/CQLLexer.g4 index 74331e0fa33a599e679e01a5b669c1c7ac9b4da5..71b41d480bc171aa02af3b2e61eadd16345b3c6d 100644 --- a/src/main/java/org/caosdb/server/query/CQLLexer.g4 +++ b/src/main/java/org/caosdb/server/query/CQLLexer.g4 @@ -502,7 +502,7 @@ mode DOUBLE_QUOTE_MODE; mode SELECT_MODE; FROM: - [Ff][Rr][Oo][Mm]([ \t\n\r])? -> mode(DEFAULT_MODE) + [Ff][Rr][Oo][Mm]([ \t\n\r])* -> mode(DEFAULT_MODE) ; SELECT_DOT: diff --git a/src/main/java/org/caosdb/server/query/CQLParser.g4 b/src/main/java/org/caosdb/server/query/CQLParser.g4 index 6c6aa748c1c5196936b0581031ecaa0aa5605d66..6aea8c55f006cd9127d68f0c09e1654d9f9842a9 100644 --- a/src/main/java/org/caosdb/server/query/CQLParser.g4 +++ b/src/main/java/org/caosdb/server/query/CQLParser.g4 @@ -495,8 +495,10 @@ number_with_unit unit : - TXT - | NUM SLASH TXT + (~(WHITE_SPACE | WHICH | HAS_A | WITH | WHERE | DOT | AND | OR )) + (~(WHITE_SPACE))* + | + NUM SLASH (~(WHITE_SPACE))+ ; location returns [String str] diff --git a/src/main/java/org/caosdb/server/query/POV.java b/src/main/java/org/caosdb/server/query/POV.java index a1008bd6a67a8712baf2c9b52ab164f619236263..b1a457529a0199edcc5061110ee97e416a264fff 100644 --- a/src/main/java/org/caosdb/server/query/POV.java +++ b/src/main/java/org/caosdb/server/query/POV.java @@ -70,8 +70,8 @@ public class POV implements EntityFilterInterface { private String propertiesTable = null; private String refIdsTable = null; private final HashMap<String, String> statistics = new HashMap<>(); - private Logger logger = LoggerFactory.getLogger(getClass()); - private Stack<String> prefix = new Stack<>(); + private final Logger logger = LoggerFactory.getLogger(getClass()); + private final Stack<String> prefix = new Stack<>(); private Unit getUnit(final String s) throws ParserException { return CaosDBSystemOfUnits.getUnit(s); @@ -116,7 +116,7 @@ public class POV implements EntityFilterInterface { // try and parse as integer try { - final Pattern dp = Pattern.compile("^(-?[0-9]++)([^(\\.[0-9])-][^-]*)?$"); + final Pattern dp = Pattern.compile("^(-?[0-9]++)\\s*([^(\\.[0-9])-][^-]*)?$"); final Matcher m = dp.matcher(value); if (!m.matches()) { throw new NumberFormatException(); @@ -133,7 +133,7 @@ public class POV implements EntityFilterInterface { this.vDouble = (double) this.vInt; } else { try { - final Pattern dp = Pattern.compile("^(-?[0-9]+(?:\\.[0-9]+))([^-]*)$"); + final Pattern dp = Pattern.compile("^(-?[0-9]+(?:\\.[0-9]+))\\s*([^-]*)$"); final Matcher m = dp.matcher(value); if (!m.matches()) { throw new NumberFormatException(); @@ -142,7 +142,7 @@ public class POV implements EntityFilterInterface { unitStr = m.group(2); this.vDouble = Double.parseDouble(vDoubleStr); - if ((this.vDouble % 1) == 0) { + if (this.vDouble % 1 == 0) { this.vInt = (int) Math.floor(this.vDouble); } } catch (final NumberFormatException e) { @@ -509,14 +509,16 @@ public class POV implements EntityFilterInterface { return this.aggregate; } - private String measurement(String m) { + private String measurement(final String m) { return String.join("", prefix) + m; } @Override public String getCacheKey() { - StringBuilder sb = new StringBuilder(); - if (this.getAggregate() != null) sb.append(this.aggregate); + final StringBuilder sb = new StringBuilder(); + if (this.getAggregate() != null) { + sb.append(this.aggregate); + } sb.append(toString()); if (this.hasSubProperty()) { sb.append(getSubProperty().getCacheKey()); diff --git a/src/test/java/org/caosdb/server/query/TestCQL.java b/src/test/java/org/caosdb/server/query/TestCQL.java index 92e82902215d5e127ef67941ba70a14d535bba82..154977a909a9d34ac2034c1ef352b81e7b2a3cb7 100644 --- a/src/test/java/org/caosdb/server/query/TestCQL.java +++ b/src/test/java/org/caosdb/server/query/TestCQL.java @@ -239,6 +239,8 @@ public class TestCQL { String queryIssue116 = "FIND *"; String queryIssue132a = "FIND ENTITY WHICH HAS BEEN INSERTED AFTER TODAY"; String queryIssue132b = "FIND ENTITY WHICH HAS BEEN CREATED TODAY BY ME"; + String queryIssue134 = "SELECT pname FROM ename"; + String queryIssue131 = "FIND ENTITY WITH pname = 13 €"; // File paths /////////////////////////////////////////////////////////////// String filepath_verb01 = "/foo/"; @@ -6718,4 +6720,25 @@ public class TestCQL { assertEquals("TRANS(Insert,(,Today,Transactor(null,=))", sfq.filter.toString()); } + + /** + * Multiple white space chars after `FROM`. + * + * <p>String queryIssue134 = "SELECT pname FROM ename"; + */ + @Test + public void testIssue134() { + // must not throw ParsingException + new Query(this.queryIssue134).parse(); + } + /** + * Space before special character unit + * + * <p>String queryIssue131= "FIND ENTITY WITH pname = 13 €"; + */ + @Test + public void testIssue131() { + // must not throw ParsingException + new Query(this.queryIssue131).parse(); + } }