Skip to content

feat(graph): add WITH clause with query chaining support#86

Merged
beinan merged 1 commit into
lance-format:mainfrom
dcfocus:dac/with_clause
Jan 16, 2026
Merged

feat(graph): add WITH clause with query chaining support#86
beinan merged 1 commit into
lance-format:mainfrom
dcfocus:dac/with_clause

Conversation

@dcfocus

@dcfocus dcfocus commented Jan 14, 2026

Copy link
Copy Markdown
Contributor

Adds WITH clause for intermediate projections, aggregations, and query chaining in Cypher queries.

Supported syntax:

  • WITH projection: WITH p.name AS name
  • WITH aggregation: WITH city, count(*) AS total
  • WITH ORDER BY/LIMIT: WITH p ORDER BY p.age DESC LIMIT 10
  • Post-WITH WHERE: WITH ... WHERE total > 1
  • Post-WITH MATCH: WITH ... MATCH (p2:Person) ...

Changes:

  • Add WithClause to AST with items, order_by, limit fields
  • Add with_clause, post_with_match_clauses, post_with_where_clause to CypherQuery
  • Parse WITH clause and post-WITH MATCH/WHERE in parser
  • Add semantic analysis for WITH scope
  • Add plan_with_clause in logical planner
  • Chain post-WITH MATCH using plan_match_clause_with_base
  • Add 5 comprehensive tests for WITH functionality

Note: WITH p (passing whole node) then MATCH (p)-[]->(f) requires explicit property projection. Use WITH p.id AS id ... instead.

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@ChunxuTang ChunxuTang left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the work! Just left some minor comments, mostly related to your comments in the code.

Comment thread rust/lance-graph/src/parser.rs Outdated
Comment thread rust/lance-graph/src/parser.rs Outdated
None => (input, vec![], None),
};

let (input, ret_clause) = return_clause(input)?;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ret_clause -> return_clause?

Comment thread rust/lance-graph/src/parser.rs Outdated
Comment thread rust/lance-graph/src/semantic.rs Outdated
}
}

// Phase 2.5: Validate WITH clause if present

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you remove the Phase 2.5 and Phase 2.6 from the comments? We actually don't have Phase 2.1 - 2.4.

}

#[tokio::test]
async fn test_with_post_where_filter() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you merge this test and the previous test test_with_order_by_limit? Looks like this test also covers ORDER_BY, so maybe just need to add LIMIT.

Comment thread rust/lance-graph/src/ast.rs Outdated
Comment on lines +335 to +336
/// the input for subsequent clauses. Variables not in the WITH projection
/// are no longer in scope after the WITH.

@ChunxuTang ChunxuTang Jan 14, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variables not in the WITH projection are no longer in scope after the WITH.

I don't think this PR enforces this scope restriction. Maybe remove this comment for now and leave a TODO for this type of enforcement.
If you have interests, you can send a follow-up PR for this impl.

@dcfocus dcfocus force-pushed the dac/with_clause branch 2 times, most recently from 6c523e2 to a5cc40a Compare January 14, 2026 06:27
Adds WITH clause for intermediate projections, aggregations, and
query chaining in Cypher queries.

Supported syntax:
- WITH projection: WITH p.name AS name
- WITH aggregation: WITH city, count(*) AS total
- WITH ORDER BY/LIMIT: WITH p ORDER BY p.age DESC LIMIT 10
- Post-WITH WHERE: WITH ... WHERE total > 1
- Post-WITH MATCH: WITH ... MATCH (p2:Person) ...

Changes:
- Add WithClause to AST with items, order_by, limit fields
- Add with_clause, post_with_match_clauses, post_with_where_clause to CypherQuery
- Parse WITH clause and post-WITH MATCH/WHERE in parser
- Add semantic analysis for WITH scope
- Add plan_with_clause in logical planner
- Chain post-WITH MATCH using plan_match_clause_with_base
- Add 5 comprehensive tests for WITH functionality

Note: WITH p (passing whole node) then MATCH (p)-[]->(f) requires
explicit property projection. Use WITH p.id AS id ... instead.
/// MATCH clauses after WITH (optional) - query chaining
pub post_with_match_clauses: Vec<MatchClause>,
/// WHERE clause after WITH (optional) - filters the WITH results
pub post_with_where_clause: Option<WhereClause>,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if there is more than one "with" in a query?

@beinan beinan merged commit d53fdd4 into lance-format:main Jan 16, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants