Architecture Overview#
The Entity Query Language (EQL) is built on a clear separation between query definition and execution. This architectural pattern allows for complex query manipulation, optimization, and deferred evaluation.
The Three Stages of a Query#
Every EQL query passes through three distinct lifecycle stages:
Builder (Blueprint): The user interacts with
Querythat uses builders of typeExpressionBuilders to define the query’s structure (where, having, grouped_by, etc.).Expression (Execution Graph): When
.build()is called on theQueryobject, the builders materialize into nodes of typeSymbolicExpression, forming a symbolic execution graph.Execution (Evaluation): The graph is traversed using
evaluate(), which yields results as a stream of bindings.
Builders vs. Expressions#
Stage |
Class |
Responsibility |
|---|---|---|
Builder |
|
Collects metadata, validates structure, and stores constraints. |
Expression |
|
Implements the actual evaluation logic ( |
Hint
The separation allows EQL to validate the query structure (e.g., checking if aggregators are used correctly in having) before the expensive evaluation process begins.
The Query Lifecycle#
Definition: You call
entity(v).where(...). This populates the internal builders of theQueryobject.Building: When you call
evaluate()method or use the query as part of another query, the.build()method is triggered. It converts all builders into their corresponding expression nodes.Evaluation: The root expression (a
ResultQuantifier) calls_evaluate_()on its children, starting the recursive evaluation process.
Note
The @modifies_query_structure decorator ensures that once a query has been built into an execution graph, its structure cannot be modified further.
Warning
Directly manipulating expression nodes is discouraged for end-users. Always use the factories and Query methods to build your queries.
Simplified Visualization of the Pipeline#
graph LR
A[User Code] --> B[Builders]
B -- .build() --> C[Expression Graph]
C -- .evaluate() --> D[Result Stream]