Binder¶
The binder performs semantic analysis on parsed Cypher queries, converting the AST into a bound query ready for physical planning.
Overview¶
AST (from Parser)
│
▼
┌──────────────────┐
│ Semantic Analysis │
│ - Validation │
│ - Type Checking │
│ - Resolution │
└──────────────────┘
│
▼
Bound Query
Binder Structure¶
The binder is organized into modular components in src/query/binder/:
Module Organization¶
src/query/binder/
├── mod.rs # Module exports
├── binder.rs # Main Binder struct
├── clause.rs # Clause binding (MATCH, RETURN, etc.)
├── statement.rs # Statement binding (queries vs schema)
├── expression.rs # Expression binding and evaluation
├── pattern.rs # Pattern binding (nodes, relationships)
└── types.rs # Bound query type definitions
Modular Design Benefits¶
The recent refactoring split the binder into focused modules:
- Maintainability: Each module has a single, clear responsibility
- Extensibility: Adding new Cypher features is easier
- Testability: Modules can be tested independently
- Readability: Code is more discoverable
Binding Process¶
1. Clause Binding¶
Located in clause.rs, handles binding of individual Cypher clauses:
Binding steps: 1. MATCH clause: Bind nodes and relationships to tables 2. WHERE clause: Bind and validate filter expressions 3. RETURN clause: Bind projection items
2. Pattern Binding¶
Located in pattern.rs, handles graph pattern binding:
Binding steps: 1. Node binding: Resolve labels to node tables 2. Relationship binding: Resolve types to relationship tables 3. Direction validation: Ensure relationship direction matches schema 4. Variable binding: Track variable scopes
3. Expression Binding¶
Located in expression.rs, handles expression binding and type checking:
Binding steps: 1. Property access: Validate property exists on node type 2. Operators: Type-check operands 3. Functions: Validate function names and argument types 4. Literals: Convert to internal Value types
Binder Context¶
The binder maintains context during binding:
BinderState¶
pub struct BinderState {
// Variable bindings
variables: HashMap<String, VariableBinding>,
// Current scope for variable resolution
scope: Vec<ScopeLevel>,
// Catalog for table/property lookups
catalog: Arc<Catalog>,
// Bound clauses being built
bound_clauses: Vec<BoundClause>,
}
Variable Binding¶
Variables are bound to their sources:
Produces bindings:
Type Checking¶
The binder performs type checking on expressions:
Property Access¶
Type checking:
1. Verify User table has property age
2. Verify age is numeric type
3. Verify literal 25 is compatible
Function Calls¶
Type checking:
1. Verify size() function exists
2. Verify u.name is string or list
3. Verify return type is numeric
Error Handling¶
The binder produces detailed errors for invalid queries:
Undefined Label¶
Error:
Type Mismatch¶
Error:
Undefined Variable¶
Error:
Scope Management¶
The binder manages variable scopes:
Single Clause Scope¶
Variables u is visible in WHERE and RETURN.
Multiple Match Patterns¶
Variable f from first pattern is available in second pattern.
WITH Clause Scope¶
Variables after WITH are only those projected.
Special Cases¶
Relationship Binding¶
Relationships require special handling:
Binding steps:
1. Bind r to relationship variable
2. Bind relationship type KNOWS to relationship table
3. Bind property access r.since
4. Verify KNOWS table has property since
Optional Match¶
OPTIONAL MATCH creates nullable bindings:
Binding:
- u is always bound (non-nullable)
- c may be null if no relationship exists
Pattern Comprehensions¶
Pattern comprehensions create list expressions:
Binding:
1. Create new scope for comprehension
2. Bind f within comprehension
3. Type-check comprehension expression
4. Verify return type is list
See Also¶
- Query Execution — Full query pipeline
- Architecture — System overview
- Operators — Physical operators
- Functions Reference — Built-in functions