Wires and named tables
A wire on the canvas carries one port’s rows into one input port on the node you drew it to. That input port’s id is the wire’s handle, and the handle is also the name an operation reads the wire by. A node with three wires has three handles, and nothing about those three rows sets is combined until an operation on the node says how.
One handle, one wire
Section titled “One handle, one wire”The first wire into a node lands on its default input port, input. Each further wire mints its own input port, named after the source node’s title (prices, prices-2 when that name is taken). Select the wire and open the Overview panel to read its handle and rename it; the rename moves the input port with it, so the label on the canvas and the name your formula uses stay the same word.
One handle carries one wire. Drawing a second wire onto a node gives it a new handle rather than stacking two sources on one port, so every table a node reads has exactly one source.
What the first operation receives
Section titled “What the first operation receives”| Wires into the node | The first operation’s rows | Named tables |
|---|---|---|
| None, as on a Load file, a Static Data table or a trigger | Empty | None |
| One | That wire’s rows, with their schema, audit, lineage and styles | That wire, on its handle |
| Several | Empty | Every wire, on its own handle |
With one wire, the common case, the node reads it and you write nothing. With several, the node starts empty and the merge formula builds the row set, which is why a new node carries a merge slot in front of its native operation. See Operation node.
Reading a table
Section titled “Reading a table”inputs() is the node’s set of named tables, and inputs().prop(handle) is one of them:
setProp("venue_name", inputs().prop("venues").find("code", prop("venue")).prop("name"))find returns the first matching row, findAll every matching row, and rows() all of them. A value you read out of a table row brings that cell’s data styles with it, so an enriched column keeps the marks of the column it came from.
A Schema node names the same tables in a property’s source path, as <handle>.<field>. A Jinja template and an AI prompt read them as {{ inputs }}. A script reads them as ctx["tables"].
Merge formulas
Section titled “Merge formulas”These five shapes cover what per-edge merge settings used to do. Each one is a formula operation in the node’s merge slot.
let(name, value, body) is a three-argument expression, so a let binding never survives to the next statement: each column reads the table in its own statement, and a statement that needs the matched row twice holds the let inside itself.
Append both wires
appendRows(inputs().prop("trades_eu"))appendRows(inputs().prop("trades_us"))Enrich one wire from another by key
appendRows(inputs().prop("trades"))setProp("price", inputs().prop("prices").find("ISIN", prop("ISIN")).prop("price"))setProp("priceDate", inputs().prop("prices").find("ISIN", prop("ISIN")).prop("asOf"))Enrich without overwriting a value the row already has
appendRows(inputs().prop("trades"))if( empty(prop("currency")), setProp("currency", inputs().prop("reference").find("ISIN", prop("ISIN")).prop("currency")))Full merge by key: keep the rows only one side has
appendRows(inputs().prop("left"))appendRows(inputs().prop("right"))groupBy(prop("id"))setProp("id", prop("id").first())setProp("amount", prop("amount").filter(not(empty(current))).first())Both sides stack, then the key collapses them. A column only one side carries reads empty on the other side’s rows, so the aggregate skips empties and keeps the first value that is there, which is the left side where both carry one. A key only one side has still gets its row. appendRows takes a table, never a filtered row list, so the one-sided rows are kept this way rather than appended on their own.
Match by position
appendRows(inputs().prop("a"))setProp("amount", inputs().prop("b").rows().at(rowIndex()).prop("amount"))rowIndex() is the current row’s zero-based position in the row set at that statement, and at() past the end is empty, so a shorter second table leaves those cells empty rather than failing the node.
Statements are ordered, so where two of them write the same field the later one wins, and the style on that cell belongs to the write that landed last. That order is the whole rule: a wire has no priority of its own.
Exceptions on a wire
Section titled “Exceptions on a wire”An operation that reads a wire whose upstream port carries a warning or error exception fails closed: the node writes no rows and does not run its remaining operations. Reading a clean wire beside it does not rescue the node. Clear the upstream exceptions, or branch the graph so the clean path is separate. See Exception management.
Related
Section titled “Related”- Operation node - the operations list, and the merge slot
- Formula - every statement and function
- Static Data - reference tables kept in the workflow
- Schema Node -
<handle>.<field>source paths