php-cypher-dsl icon indicating copy to clipboard operation
php-cypher-dsl copied to clipboard

Restrict where clauses can be inserted into the query

Open marijnvanwezel opened this issue 3 years ago • 0 comments

The current version has no built-in mechanism to prevent invalid clause orders, as nothing prevents or warns the user from doing the following:

$n = Query::node()->withVariable('n');

$query = Query::new()
    ->match($n)
    ->orderBy($n->property('age'))
    ->returning($n)
    ->build();

// MATCH (n) ORDER BY n.age RETURN n

The above query is invalid, since ORDER BY may only be used after a RETURN or WITH clause.

The fact that the DSL allows this is undesirable for two reasons:

  1. An invalid query may be executed on a database, leading to a runtime error;
  2. It weakens the static analysis capabilities of the DSL, since there is no way for your IDE to warn you about the invalid query or to give hints about which clauses can follow the previous.

Possible solution

My proposal to fix this is as follows:

  1. Create an interface for each clause that only contains the signatures for the builder methods that make sense on that clause (for example, the ReturnQuery interface would have the signature for orderBy, but the CreateQuery interface would not).
  2. Have each builder method specify as a type hint the interface of the clause it adds to the query. That is, the returning method specific it returns a ReturnQuery, the call method a CallQuery and so on.
  3. Have the Query class implement all interfaces.

If a user now tries to build the query above, their IDE should warn them that the orderBy method is not part of the MatchQuery interface.

marijnvanwezel avatar Aug 16 '22 13:08 marijnvanwezel