Skip to content

INSERT cannot choose a node's id, and a keyed node table takes no appended rows #293

Description

@tamnd

Found while giving graph-bench a zu column for the linkbench, snb-update and finbench write operations. Two refusals, both about the same thing, which is that a node's identity is not something a write statement can name.

The first is that an INSERT carrying an id is rejected outright:

INSERT (:Obj {id: 9000001, otype: 1, version: 0, time: 0, payload: 'x'})
-- invalid argument: the element carries 'id', which is not a column of the table it is created in

That is crates/zu/src/insert.rs around line 505. It is accurate about the storage: a zu node id is the dense row offset the loader handed out, and id is not a column. But it means a statement cannot decide what the row it just created is called, so nothing written ahead of the run can refer to it afterwards.

The second is that a node table that does have a key index refuses appended rows at all:

INSERT (:Person {id: 9000001, name: 'x'})
-- invalid argument: unsupported folding appended rows into a keyed table id 2

That is crates/zu-zu1/src/fold.rs around line 747, the guard Some(_) if new_from != old.from_count. zu copy builds a key index for any node table whose ids are not dense, so a store loaded from real data usually has one, and on those stores no node can be created at all.

What this costs in graph-bench, which is the concrete reason to raise it:

  • lb-update-node and lb-delete-node skip. Their setup creates a scratch object and the timed statement has to find it again. On every other engine the setup gives it an id. On zu it lands at whatever offset the store was next free at, and no id written ahead of the run names it. Matching on the payload instead would put a full table scan inside the timed statement, which is not the point operation LinkBench is measuring, so the honest outcome is a skip.
  • fb-w2 skips for the same reason, and so does every one of the six snb-update shapes, which all create an entity at a negative literal id and then refer to it.

That is three workloads out of the write side of the matrix, and none of them come back without this.

The fix worth having is a node key that a write statement can name: either accept id in an INSERT and have the store map it to an offset through the key index, or accept the key label set the graph type declares and use that. Both need the keyed table to take appended rows first, so the fold guard is the prerequisite either way.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestqueryParser, planner, executorstorageStorage engines and file formats

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions