[Parser] Validate and collect all properties from a clause
Opened this issue · 3 comments
I want to collect all the properties used for filtering the data and do some validation on them. For example:
String query = "MATCH (start {name: 'v1'}) RETURN count(*) AS COUNT";
var statement = CypherParser.parse(query, options)
In the above query I want to collect vertex property "name". Similarly, I want to collect the properties used in other clauses like WHERE
, WITH
etc. Is there any possible way to access Clause
list of Statement
without using reflection so I can collect the properties?
Is it possible to convert org.neo4j.cypherdsl.core.Clause
to org.neo4j.cypher.internal.ast.Clause
so I can modify the parsed clauses and use Neo4jASTFactory
class to create a new Statement
?
For retrieving the property filters, you can make use of the recent Catalog feature -> https://neo4j-contrib.github.io/cypher-dsl/2023.3.0/#catalog-support
Here is a simple example and the output
@Test
void catalog_usage() {
parseQuery("MATCH (start {name: 'v1'}) RETURN count(*) AS COUNT");
parseQuery("MATCH (n:Person {name: 'bob'}) WITH n WHERE n.age > 20 RETURN bob");
}
private void parseQuery(String query) {
Statement statement = CypherParser.parse(query);
var catalog = statement.getCatalog();
System.out.println("----");
catalog.getAllPropertyFilters().forEach((key, value) -> {
var labels = key.owningToken().stream().toList();
var label = labels.size() > 0 ? labels.get(0) : "NONE";
var propertyKey = key.name();
value.forEach(propertyFilter -> {
var clause = propertyFilter.clause().name();
var operator = propertyFilter.operator().name();
var left = propertyFilter.left().toString();
var right = propertyFilter.right().toString();
System.out.println("detected property filter on token `%s` for property `%s` during `%s` clause , operator is `%s`, left is `%s` and right is `%s`".formatted(
// owningType,
label,
propertyKey,
clause,
operator,
left,
right
));
});
});
}
----
detected property filter on token `NONE` for property `name` during `MATCH` clause , operator is `EQUALITY`, left is `InternalPropertyImpl{cypher=start.name}` and right is `StringLiteral{cypher='v1'}`
----
detected property filter on token `Token[type=NODE_LABEL, value=Person]` for property `name` during `MATCH` clause , operator is `EQUALITY`, left is `InternalPropertyImpl{cypher=n.name}` and right is `StringLiteral{cypher='bob'}`
detected property filter on token `Token[type=NODE_LABEL, value=Person]` for property `age` during `WITH` clause , operator is `GREATER_THAN`, left is `InternalPropertyImpl{cypher=n.age}` and right is `NumberLiteral{cypher=20}`
I cannot use 2023.3.0, as I'm using Java 11 and it requires Java 17. Is there any other possible way? Could you also suggest a way to add additional clause/filter in parsed dsl?
We don't have plans to backport the catalog feature to Java 8. And in addition, the recent Neo4j parser itself requires JDK 17, so we are bounded on that side anyway.