THE INCQL BOOK
3. Inspect the plan
Use Prism-backed inspection to explain the lazy work before a backend executes it.
Part II
Explain and execute it
Chapter 1 of 3
Goal
Inspect the review plan and its lineage without executing DataFusion. Locate the plan target, output schema, Prism nodes, and lineage relationships that explain the deferred work.
Prism is the planning layer
IncQL is the library and public data-logic surface. Prism is its internal logical planning engine; the two names are related but not interchangeable. Today, the LazyFrame path owns Prism state, which is why inspect_plan(...) and inspect_lineage(...) can read this plan locally.
Inspection is read-only. It does not bind a physical backend, inspect a DataFusion physical plan, or turn local evidence into a Substrait payload.
With this example, you are reading the same ReadNamedTable → Limit plan at two levels of detail. inspect_plan(plan.clone()) produces the full PlanInspection, while inspect_lineage(plan) returns only its lineage graph; cloning preserves a carrier for the second call. Both functions read the Prism store and current tip locally, so their node and edge counts explain authored intent rather than backend execution.
Query under glass · local plan evidence
See what Prism knows—and where inspection stops
The checkpoint builds one deferred carrier, then reads two views of its local Prism state. Neither inspection call crosses into backend execution.
-
01
Deferred review planDescribe a named read followed by a limitorders: LazyFrame[Order] = session.read_csv( "tutorial_orders", "orders.csv", )? plan = orders.limit(3) # (1)!Inspection target.
limit(3)returns the deferredLazyFramewhose current Prism tip is the newLimitnode. Assigning it toplangives both inspection functions the sameReadNamedTable → Limittarget; no backend work occurs here.
- Owner
- Authoring surface
- Artifact
LazyFrame[Order]- Knowable now
- The authored
ReadNamedTable → Limitintent
-
02
Prism inspectionRead structure and lineage from local plan stateinspection = inspect_plan(plan.clone()) # (1)! lineage = inspect_lineage(plan) # (2)!Full inspection.
inspect_plan(...)consumes aLazyFramevalue and returns the completePlanInspection: plan targets, schemas, authored and rewritten nodes, lineage, requirements, artifacts, diagnostics, and unsupported-evidence markers. Passingplan.clone()preserves another carrier value for the next call.Lineage-only view.
inspect_lineage(...)consumes the remaining carrier and returns itsLineageGraphdirectly. Use this narrower function when callers need relationships rather than the complete inspection record. Likeinspect_plan(...), it reads local Prism state without executing the plan.
- Owner
- Prism inspection
- Artifact
PlanInspectionand lineage graph- Knowable now
- Plan target, output schema, authored nodes, and lineage relationships
-
03
Local evidence returnReport plan facts without materialising rows- Plan target
- One local Prism identifier
- Authored nodes
- 2
- Lineage edges
- 8
PlanInspectionLineage graph
inspect_plan(...) returns a structured PlanInspection. inspect_lineage(...) exposes the lineage graph from the same Prism-backed state when that graph is all a caller needs. The plan identifier printed by the checkpoint is a local evidence anchor, not a global catalog ID.
Open the complete Chapter 3 checkpoint
"""Chapter 3: inspect the Prism plan and lineage before execution."""
from domain import Order
from pub::incql import LazyFrame, Session, SessionError, inspect_lineage, inspect_plan, report_session_error
def inspect_orders(mut session: Session) -> Result[None, SessionError]:
"""Build and inspect the tutorial plan without collecting rows."""
orders: LazyFrame[Order] = session.read_csv("tutorial_orders", "orders.csv")?
plan = orders.limit(3)
inspection = inspect_plan(plan.clone())
lineage = inspect_lineage(plan)
println(f"plan id: {inspection.plan_id}")
println(f"authored nodes: {inspection.authored_node_count}")
println(f"lineage edges: {len(lineage.edges)}")
return Ok(None)
def main() -> None:
mut session = Session.default()
match inspect_orders(session):
Ok(_) => println("Chapter 3: inspection completed without executing the plan")
Err(error) => report_session_error("tutorial.chapter_03", error)
Run it from the included tutorial project:
incan run src/chapter_03.incn
A successful run prints the local plan ID, two authored nodes, eight lineage edges, and confirmation that inspection completed without executing the plan.
The exact records and current limits are documented in Local inspection.
Try it
Print each lineage edge's relationship value. For every edge you see, point back to the carrier operation that caused it. Do not interpret a missing edge as proof that no relationship exists; unsupported or conservative evidence is represented separately.
Chapter complete
You can describe what Prism knows before execution and distinguish a local PlanInspection from the backend work that has not happened yet.