Skip to content

Restrict where clauses can be inserted into the query #70

@marijnvanwezel

Description

@marijnvanwezel

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.

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions