Qwiratry β Qwiratry-TaOP-Prerequisites
Qwiratry TaOP Prerequisites
Specification for Qwiratry core changes required before rebuilding TaOP on Qwiratry. This document is not the TaOP product surface.
Parent plan: Qwiratry-TaOP-Plan.md.TaOP layer (Relation, Memory, Postgres, Tables, anonymous Table front-end): Qwiratry-TaOP-Basics.md.
Status: Prerequisites substantially complete (post-0.0.9 / toward
0.10.0). Landed: text-chunk walkable/pull; sector vocabulary; WalkCursor /
QueryCursor tree; Topic slang; TypedIterator (File .of = Str); text-adaptor
checks; QueryIterator does TypedIterator. Remaining doc polish may trail
in Extending; row sinks / table Locations β Basics.Scope (prerequisites only): Streaming-shaped Location I/O; TypedIterator
as the common element-kind face (I/O pull and query match streams);
WalkCursor tree contract; no Qwiratry::Storage::*.
1. Goals
Streaming-shaped Location I/O (walkable + optional pull/sink) so adaptors can carry Iterators without always materialising a giant
Str.TypedIteratorso pull streams advertise element kind (Location chunks today; query matches viaQueryIterator; later rows in Basics) without parallelread-rowsAPIs.WalkCursor tree contract as the movement API TOP/SQL cursors will reuse. (
WalkCursoritself does not return an Iterator;QueryCursor.iteratoris the optional match-stream bridge.)No parallel Storage hierarchy β when TaOP lands, table backends extend Location (see Basics); Qwiratry core must not ship a competing Storage tree.
Adaptor operators that do not assume every pull stream is text (no blind
.Strcoerce).SourceOperatorstays walkable-shaped β it does not return an Iterator; Location pull is composed by Parse (or, later, by Basics when a table Source is used in a pipeline that needs rows). Dirs/globs keep current return shapes.
2. Non-goals (TaOP work β see Basics)
These are out of scope for prerequisites. Spec and acceptance live in Qwiratry-TaOP-Basics.md:
Relation /
use-table/ live Table handlesMemory Location (and anonymous default storage)
Postgres (and other SQL) Location
Tables / Database / Field / Tuple front-end, FieldMode plugins as TaOP API
CSV Location, HalfHuman, WithBorders (plan sequencing)
Multi-dialect / Red-style SQL encoding (plan Β§12)
Graduating
CSVdemointo a production FormatFull Format push (
Supply) edges β not needed for TaOP Basics; destination text sinks suffice for blob streaming today (see Streaming proposal v2 later)Interim row
.oftype and Destination row sinks β Basics (table Locations not in prerequisites)Making bare
SourceOperatorreturn a pullIteratorβ rejected for now; walkable evaluate is intentional
3. Current baseline (after 0.0.9 β Unreleased / 0.10.0)
| Piece | Behaviour |
|---|---|
Qwiratry::Location::Base::SourceWalkable | read-walkable(Str $location --> Mu) β whole payload |
Qwiratry::Location::Base::DestinationWalkable | write-walkable(Str $location, Mu $content --> Mu) |
Qwiratry::Location::Base::SourcePull | Optional read-pull(--> Iterator); prefer TypedIterator |
Qwiratry::Location::Base::DestinationPush | Optional open-sink-push β sink with write-chunk / close |
Qwiratry::Format::Base::ParseWalkable / RenderWalkable | parse-walkable / render-walkable |
Qwiratry::Format::Base::ParsePull / RenderPull | Optional parse-pull / render-pull |
SourceOperator | Always whole-value read-walkable (dirs/globs/return shapes). Does not return an Iterator. Pull composition is chosen by ParseOperator when both source and parser support pull. |
DestinationOperator | Prefer open-sink-push when upstream is a text-chunk Iterator; else join and write-walkable. Rejects non-text .of / non-Str untyped elements. |
ParseOperator / RenderOperator | Prefer pull when format (and source, for parse) advertise it; else walkable fallback. Same text-kind checks as Destination. |
| File | Walkable + SourcePull + DestinationPush; read-pull β TypedIterator with .of = Str |
| HTTP | Walkable only (sibling package) |
| NDJSONdemo | Walkable + ParsePull / RenderPull |
Qwiratry::Location factory | Discovers ::Source / ::Destination; validates against Walkable bases |
Qwiratry::Table::Catalog / Schema | Existing FK-aware navigation over named collections / row lists (not TaOP Table front-end) |
| Navigation vocabulary | Former βaxisβ naming β sector |
WalkCursor / Sector / Axis | Generic position/fetch-*/move-* (lib/WalkCursor.rakumod) β not an Iterator factory |
Qwiratry::QueryCursor | Tree specialization; Plan.cursor; optional Strategy :cursor; .iterator β QueryIterator (match bridge) |
Qwiratry::QueryIterator | Query match pull stream (+ Context); does TypedIterator (default .of = Mu) |
| Tree Navigator | Multi-step sector helpers; walk-local caches |
Qwiratry::Query::Slang + ::Ops + ::Topic | Topic slang after Slang for given / bare nav / universe ops |
TypedIterator | Top-level role + TypedIterator::Wrapper; .of default Mu |
Still missing for TaOP to plug in cleanly: Basics Locations (Memory, β¦) that
yield row TypedIterators, plus Destination row sinks / Parse skip for
structured .of β specified in Basics, not here.
4. Pipeline face (prerequisite concern)
SourceOperator and DestinationOperator remain the adaptor pipeline operators:
Source = pull data from a location into the pipeline.
Destination = push pipeline data out to a location.
| Location capability | Source yields (via Location APIs) | Destination accepts |
|---|---|---|
| Blob (File, HTTP, β¦) | read-walkable, or read-pull β TypedIterator with .of = Str (used when Parse composes pull) | write-walkable, or text-chunk sink |
| Structured / table-capable (TaOP Locations) | Same read-pull surface with row .of β Basics | Row sink when elements are rows β Basics |
SourceOperator.evaluate always uses read-walkable. It does not return an
Iterator. That keeps directory/glob shapes stable. Pull is an optional Location
capability consumed by ParseOperator today (and by Basics pipelines that call
read-pull / structured adaptors later).
Parse/Render stay on Format when the pipeline deals with encoded text. When a pipeline already has structured values, Parse may be skipped (Basics).
The object face (Relation / Table.new) is TaOP Basics, not a prerequisite
module. Both faces SHOULD eventually share row I/O on the same backend β that
sharing rule is specified in Basics.
Adaptor operators MUST NOT assume every Location is Str-only.
5. Prerequisite A0 β Streaming-shaped Location I/O
5.1 Why first
TOP table Sources are only honest if the Location and operator stack can carry
Iterators (chunks or later rows) without forcing full materialisation. Text
walkable/pull has landed. QueryIterator does TypedIterator and Extending
.of docs are landed. Row sinks / table Locations are Basics.
Align names with Streaming-Qwiratry-Proposal.md.
5.2 Landed contracts (text / blob)
class Qwiratry::Location::Base::SourceWalkable {
method read-walkable(Str $location --> Mu) { ... }
}
class Qwiratry::Location::Base::DestinationWalkable {
method write-walkable(Str $location, Mu $content --> Mu) { ... }
}
role Qwiratry::Location::Base::SourcePull {
method read-pull(Str:D $location --> Iterator:D) { ... }
}
role Qwiratry::Location::Base::DestinationPush {
method open-sink-push(Str:D $location --> Mu) { ... } # write-chunk / close
}
class Qwiratry::Format::Base::ParseWalkable {
method parse-walkable(Str $input-string --> Mu) { ... }
}
class Qwiratry::Format::Base::RenderWalkable {
method render-walkable(Mu $data, Associative :%options --> Str) { ... }
}
role Qwiratry::Format::Base::ParsePull {
method parse-pull(Iterator:D $chunks, *%options --> Mu) { ... }
}
role Qwiratry::Format::Base::RenderPull {
method render-pull(Mu $data, Associative :%options --> Iterator:D) { ... }
}Operators choose pull when both sides advertise it; otherwise walkable fallback.
Full Supply push roles are deferred.
5.3 TypedIterator (element kind on pull streams)
Decision: one Location pull/sink surface (SourcePull / DestinationPush),
not parallel read-rows APIs. Advertise element kind with TypedIterator.
Same role is the element-kind face for query match streams:
# lib/TypedIterator.rakumod
role TypedIterator does Iterator {
method of(--> Mu:U) { Mu } # default = untyped / per-element
}
# TypedIterator::Wrapper β wrap a foreign Iterator with an explicit :of
role QueryIterator does TypedIterator { ... } # match streams + Context
# QueryCursor.iterator / Plan.iterator β QueryIterator β also TypedIterator
# Default .of = Mu (heterogeneous matches); walkers may override later.of means βelement kind of this pull stream,β whether the producer is Location
I/O (chunks/rows) or a query match bridge β not I/O-only.
.of | Behaviour |
|---|---|
Str | Text-chunk path: Parse may consume; Destination may write-chunk (landed) |
Row / Associative / Tuple | Structured path: skip text Parse; Destination row sink β Basics (no interim row type until table Locations) |
Mu or plain Iterator | Per-element; text adaptors require Str or error (no blind .Str) (landed for text) |
Landed: File .of = Str; text adaptors raise X::Qwiratry::IO::ElementType;
QueryIterator does TypedIterator.Basics: row .of, row sinks, Parse skip for structured streams.
Do not invent a second Storage tree; do not require a Format round-trip as the only way to get rows out of a future table Location.
5.4 Operator requirements (settled for prerequisites)
SourceOperatordoes not return an Iterator (walkable evaluate only).Location
read-pullSHOULD return aTypedIteratorwhose.ofmatches the payload (File:Str).Text Parse/Destination MUST NOT treat every
Iteratoras text chunks (landed).Blob Destination + non-text
.ofβ clear error (landed via ElementType); structured sinks are Basics.They SHOULD NOT force a lazy Seq into a full
Listunless required downstream.
5.5 Acceptance criteria
Text-chunk / walkable-pull (done):
Walkable + optional pull/sink roles on Format and Location bases.
File implements
read-pullandopen-sink-push.Parse / Render / Destination compose pull without forcing full materialisation where both sides support it.
NDJSONdemo reference format with walkable + pull.
Documented rename map / Extending docs for walkable method names.
Unit coverage in
t/unit/streaming-io.rakutest.
TypedIterator readiness:
TypedIteratorwith.of(--> Mu:U)(defaultMu); plainIterator= untyped.File pull returns
TypedIteratorwith.of = Str.Destination / Parse text path: non-text
.ofβ error;.of = Muβ per-elementStror error.SourceOperatorremains walkable-only (does not return Iterator) β settled.QueryIterator does TypedIterator(default.of = Mu);QueryCursor.iterator/Plan.iteratorare then TypedIterators.Extending docs describe
.offor Location pull and for query match streams.Pull vs walkable discovery:
~~ SourcePull/~~ DestinationPush(document in Extending); element kind lives on the Iterator via.of.
Row sink / Parse skip when .of is structured β Basics.
5.6 Soft foundation β WalkCursor / QueryCursor (tree done)
Normative design: Cursor-Proposal.md. Tree first landing shipped. Memory/Postgres/Relation cursor backends are TaOP Basics.
Done (Tree proof):
Generic
WalkCursor+Sector/Axisinlib/WalkCursor.rakumod.Qwiratry::QueryCursor;Plan.cursor; walk-local Navigator.Strategy optional
WalkCursor :$cursor; Navigation Evaluator delegation.QueryCursor.iteratormatch bridge βQueryIterator(not a visit-every-node stream).Extending docs;
t/unit/query-cursor.rakutest.Sector vocabulary; Cursor Axis = bidirectional sector pair.
Postgres-style
fetch-*/move-*documented for later TaOP backends.
Settled: WalkCursor has no Iterator factory. Optional pull from a cursor is
QueryCursor.iterator only. That bridge returns a QueryIterator, which
does TypedIterator (default .of = Mu; still typed as QueryIterator in
signatures).
Do not force Location Source Iterators through QueryCursor.
6. Implementation order (prerequisites)
Text-chunk streamingβ landed (Β§5.2 / Β§5.5).WalkCursor tree landingβ landed (Β§5.6).Sector vocabulary + Topic slangβ landed.β landed (Β§5.3).TypedIterator+ File.of = Str+ text-adaptor checksβ settled (Β§5.4).SourceOperatorstays walkable-onlyβ landed (Β§5.3 / Β§5.5).QueryIterator does TypedIterator+ Extending docsThen Qwiratry-TaOP-Basics.md: Relation, Memory, Tables, Postgres, row sinks, row
.of, β¦
7. Open points (prerequisite)
Whether specific Tree/Table
QueryIterators should override.ofsoon, or leaveMuuntil Basics (default leaveMu).
Moved to Basics / deferred: interim row .of type; Destination row sink + Parse
skip; full Supply push; bare Source returning Iterator.
8. References
Qwiratry-TaOP-Basics.md β Relation, Memory, Postgres, Tables
lib/Qwiratry/Location.rakumod,Location/Base.rakumod,Operator/IO.rakumodlib/TypedIterator.rakumod,lib/WalkCursor.rakumod,lib/Qwiratry/QueryCursor.rakumodt/unit/streaming-io.rakutest,t/unit/typed-iterator.rakutest,t/unit/query-cursor.rakutestRaku TOP reference tree:
~/src/TOP/Raku-TOP/main(read-only)