cleishm / libcypher-parser

Cypher Parser Library
Apache License 2.0
147 stars 39 forks source link

unable to parse `apply` operator with `.` (membership operator) in funcName #19

Closed tungv closed 5 years ago

tungv commented 5 years ago

this works:

MATCH (a:Node) RETURN abc("args1") AS a;

output:

 @0   0..40  statement                body=@1
 @1   0..40  > query                  clauses=[@2, @8]
 @2   0..15  > > MATCH                pattern=@3
 @3   6..14  > > > pattern            paths=[@4]
 @4   6..14  > > > > pattern path     (@5)
 @5   6..14  > > > > > node pattern   (@6:@7)
 @6   7..8   > > > > > > identifier   `a`
 @7   8..13  > > > > > > label        :`Node`
 @8  15..39  > > RETURN               projections=[@9]
 @9  22..39  > > > projection         expression=@10, alias=@13
@10  22..34  > > > > apply            @11(@12)
@11  22..25  > > > > > function name  `abc`
@12  26..33  > > > > > string         "args1"
@13  38..39  > > > > identifier       `a`

but this doesn't

MATCH (a:Node) RETURN abc.fn("args1") AS a;

output:

<stdin>:1:29: Invalid input '(': expected '.', AND, OR, XOR, NOT, '=~', '=', '<>', '+', '-', '*', '/', '%', '^', IN, CONTAINS, STARTS WITH, ENDS WITH, '<=', '>=', '<', '>', IS NULL, IS NOT NULL, '[', '{', a label, AS, ',', ORDER BY, SKIP, LIMIT, ';' or a clause
MATCH (a:Node) RETURN abc.fn("args1") AS a;
                            ^
 @0   0..43  statement               body=@1
 @1   0..43  > query                 clauses=[@2, @8]
 @2   0..15  > > MATCH               pattern=@3
 @3   6..14  > > > pattern           paths=[@4]
 @4   6..14  > > > > pattern path    (@5)
 @5   6..14  > > > > > node pattern  (@6:@7)
 @6   7..8   > > > > > > identifier  `a`
 @7   8..13  > > > > > > label       :`Node`
 @8  15..28  > > RETURN              projections=[@9]
 @9  22..28  > > > projection        expression=@10, alias=@13
@10  22..28  > > > > property        @11.@12
@11  22..25  > > > > > identifier    `abc`
@12  26..28  > > > > > prop name     `fn`
@13  22..28  > > > > identifier      `abc.fn`
@14  28..42  > > error               >>("args1") AS a<<

I think apply should have higher priority than property

cleishm commented 5 years ago

So the issue here isn't one of precedence. It's that function application isn't available on a property of an object - I believe Cypher only supports explicitly named functions (i.e. Cypher does not have first-class functions).

Is this example taken from somewhere?

tungv commented 5 years ago

Thank Chris for responding. This is an oversimplified version of an automatically augmented query from the package https://github.com/neo4j-graphql/neo4j-graphql-js

The actual function is apoc.cypher.runFirstColumn which is from a neo4j plugin. When I try to escape the function name by wrapping it with backticks, it parses correctly:

MATCH (n)
RETURN `apoc.cypher.runFirstColumn`("<subquery>", { n: n }, false);
tungv commented 5 years ago

More information about Apoc plugin can be found here https://neo4j.com/developer/neo4j-apoc/

cleishm commented 5 years ago

Got it. I'm unsure when support for that was added to opencypher, but it's a trivial thing to add here as well.

That said, I might have to talk to the opencypher team, as it's very odd. Rather than supporting apply as an expression on an object property, they're just allowing dot's in the function name itself (which is why `apoc.cypher.runFirstColumn` works). That's potentially ambiguous, for the user at least!