THE INCQL BOOK
2. Build deferred work
Transform the logical source while keeping execution behind the Session boundary.
Part I
Model the work
Chapter 2 of 2
Goal
Build a review plan from the CSV-backed LazyFrame and run the checkpoint without collecting rows. The important result is a new logical plan, not a local table.
Add one honest relational step
IncQL method calls append relational intent to the lazy carrier. This tutorial deliberately adds only limit(3), producing a simple ReadNamedTable → Limit plan. A limit constrains the eventual result; it does not materialize that result by itself.
IncQL also has filter, ordering, projection, aggregation, and query-block surfaces. They remain available in Guides and Reference. The book keeps this first plan deliberately small so the relationship between one authored operation, its Prism representation, and the later execution evidence stays easy to inspect.
With this example, you are turning the source-rooted carrier into a new LazyFrame[Order] whose Prism tip is a Limit node with a count of three. The function returns that carrier directly and never calls collect(...) or a Session execution method, so the runnable checkpoint demonstrates that the plan changed while the data remained unmaterialized. The trace below follows that boundary from named source, through the appended node, to the still-deferred result.
Plan construction · no execution attempt
Follow one operation into the logical plan
The source registration supplies the plan root. limit(3) appends bounded relational intent: the eventual result may contain at most three rows, with no ordering promise.
-
01
Registered sourceStart from the named-table carrierorders: LazyFrame[Order] = session.read_csv( "tutorial_orders", # (1)! "orders.csv", # (2)! )?Logical plan name.
tutorial_ordersis the non-empty, Session-local identity that the Prism plan records in itsReadNamedTableroot. It must be unique among this Session's registrations.CSV location.
orders.csvis the non-empty source URI registered under that logical name. In the tutorial it resolves relative to the project directory; changing this argument changes the physical source, not the plan's logical identity.
- Owner
Session- Artifact
LazyFrame[Order]rooted atReadNamedTable- Knowable now
- The source identity and planned CSV columns
-
02
Append bounded intentAdd one Prism plan node without collectingreturn Ok(orders.limit(3)) # (1)!Receiver and row cap.
ordersis the deferred carrier, andlimit(3)returns a new carrier with aLimitnode whose count must be non-negative. It caps the eventual result at three rows; it neither defines which three rows come first nor executes or materializes them. Useorder_by(...)beforelimit(...)when row order matters.
- Owner
- IncQL relational carrier
- Artifact
ReadNamedTable → Limit(3)logical plan- Knowable now
- The eventual result is capped at three rows
-
03
Deferred plan stateKeep backend work behind the Session boundary- Plan shape
ReadNamedTable → Limit- Output bound
- At most 3 rows
- Backend attempt
- None
Prism logical plan
Execution still absent
Open the complete Chapter 2 checkpoint
"""Chapter 2: add a relational step while keeping execution deferred."""
from domain import Order
from pub::incql import LazyFrame, Session, SessionError, report_session_error
def plan_orders(mut session: Session) -> Result[LazyFrame[Order], SessionError]:
"""Return a bounded three-row plan over the typed CSV source."""
orders: LazyFrame[Order] = session.read_csv("tutorial_orders", "orders.csv")?
return Ok(orders.limit(3))
def main() -> None:
mut session = Session.default()
match plan_orders(session):
Ok(_) => println("Chapter 2: planned ReadNamedTable -> Limit; execution is still deferred")
Err(error) => report_session_error("tutorial.chapter_02", error)
Run it from examples/tutorial_book:
incan run src/chapter_02.incn
The source file deliberately stops before collect(...). The returned value is still a LazyFrame[Order], so further relational operations or inspection can be composed before runtime binding and execution.
Expected output
Chapter 2: planned ReadNamedTable -> Limit; execution is still deferred
There is no materialized row count or table preview. That absence is meaningful: no DataFrame exists yet.
For the complete method surface, use Dataset methods. The book stays with the verified operation set needed by this one flow.
Try it
Reduce the final limit by one and rerun the checkpoint. Explain why this changes the plan but still gives you no local rows. Restore the original limit before Chapter 3.
Chapter complete
You can identify the logical source, the appended carrier operations, and the missing execution call. You can also explain why a LazyFrame is not an in-memory DataFrame.