Skip to content

Copy a graph block for block, which is what AS COPY OF asked for - #207

Merged
tamnd merged 1 commit into
mainfrom
g2-graph-copy
Aug 15, 2026
Merged

tamnd merged 1 commit into
mainfrom
g2-graph-copy

Conversation

@tamnd

@tamnd tamnd commented Aug 15, 2026

Copy link
Copy Markdown
Owner

A graph created AS COPY OF another one used to be refused when the source held tables, because a props directory names the blocks its columns live in and a copy that walked them wrong would be a copy that read as data. It walks them right now, and the mirror of free_graph_storage is what says which ones there are: a table per table in the catalog, keeping the name and taking a new id, and per id the segments the old id addressed, read whole and written into blocks of their own.

The copy is by value and shares nothing with the source. A copy that pointed at the same segments would be a second name for one graph and the first write to either would show up in both. Every segment block is copied byte for byte, so it costs a read and a write per block and no decode, and what a column holds is none of the copy's business: the labels, the validity, the key index, the CSR pair per group, the edge properties and the tombstones a node table has all carry over the same way. The directories are re-encoded, because a directory names the blocks its segments live in and those are now different blocks. The statistics carry over too, since the copy holds the same rows and gathering them again would read every column for numbers the file already has.

AS COPY OF now also takes CURRENT_PROPERTY_GRAPH, which is the graph the statement is against, the same thing a USE clause names. That is what a copy of a loaded file means, and it is what the gql-compat case for GG05 uses, since what the working graph is called is the adapter's business.

Nothing is published along the way. The table index and the statistics are staged and the checkpoint that stores the catalog makes all three visible together, so a copy that fails halfway leaves the file exactly as it was. A graph asked to be replaced by a copy of itself is refused rather than emptied, because a replacement frees what the old graph held before it writes the new one.

Three tests: the storage one asserts the copy's blocks are different blocks holding the same bytes, entry for entry over both tables, and the session one asserts the copy answers the query the source answers and still does after the copy is dropped, which is what proves the blocks were its own. The paired harness change is tamnd/gql-compat#26, which adds optional/gg05/graph-as-copy-of-holds-the-rows, and zu passes it: the corpus is at 225 passing, was 224.

A graph created AS COPY OF another one used to be refused when the source held tables, because a props directory names the blocks its columns live in and a copy that walked them wrong would be a copy that read as data. It walks them right now, and the mirror of free_graph_storage is what says which ones there are: a table per table in the catalog, keeping the name and taking a new id, and per id the segments the old id addressed, read whole and written into blocks of their own.

The copy is by value and shares nothing with the source. A copy that pointed at the same segments would be a second name for one graph and the first write to either would show up in both. Every segment block is copied byte for byte, so it costs a read and a write per block and no decode, and what a column holds is none of the copy's business: the labels, the validity, the key index, the CSR pair per group, the edge properties and the tombstones a node table has all carry over the same way. The directories are re-encoded, because a directory names the blocks its segments live in and those are now different blocks. The statistics carry over too, since the copy holds the same rows and gathering them again would read every column for numbers the file already has.

AS COPY OF now also takes CURRENT_PROPERTY_GRAPH, which is the graph the statement is against, the same thing a USE clause names. That is what a copy of a loaded file means, and it is what the gql-compat case for GG05 uses, since what the working graph is called is the adapter's business.

Nothing is published along the way. The table index and the statistics are staged and the checkpoint that stores the catalog makes all three visible together, so a copy that fails halfway leaves the file exactly as it was. A graph asked to be replaced by a copy of itself is refused rather than emptied, because a replacement frees what the old graph held before it writes the new one.

optional/gg05/graph-as-copy-of-holds-the-rows passes, so the corpus is at 225 passing, was 224.
@tamnd
tamnd merged commit 93d9c99 into main Aug 15, 2026
27 checks passed
@tamnd
tamnd deleted the g2-graph-copy branch August 17, 2026 09:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant