Summary
ALTER TABLE ... RENAME TO ... (via the execute tool) re-stubs the
target table's _table_catalog row and drops all prose metadata
(source_url, source_description, purpose, notes, license).
It also resets load_tool, load_params, created_by, and
last_modified_by to NULL/unknown, and overwrites loaded_at /
last_refreshed_at with the rename time (so the row looks like a
fresh load that didn't actually happen).
The rename succeeds and the data is fine — only the catalog
provenance is lost.
Steps to reproduce
// 1. Load and annotate
load_file({
table: "population",
path: "/tmp/owid/population.csv",
database: "persistent"
})
set_table_metadata({
table: "population",
database: "persistent",
source_url: "https://ourworldindata.org/grapher/population",
purpose: "Population denominators for per-person analyses.",
notes: "Refresh: curl ..."
})
// Catalog row now has source_url, purpose, notes populated.
// 2. Rename
execute({
database: "persistent",
sql: ["ALTER TABLE population RENAME TO owid_population"]
})
// 3. Inspect catalog
query({
database: "persistent",
sql: "SELECT table_name, source_url, purpose, notes, load_tool,
loaded_at, created_by
FROM _table_catalog WHERE table_name = 'owid_population'"
})
Expected
The row should follow the rename — the same provenance, with only
table_name updated. loaded_at and last_refreshed_at should
stay anchored to the original load time.
Actual
table_name | owid_population
source_url | NULL ← lost
purpose | NULL ← lost
notes | NULL ← lost
load_tool | unknown ← was "load_file"
loaded_at | 2026-05-27 18:40 ← reset to rename time
(was 2026-05-27 18:21,
the original load time)
created_by | NULL ← was "claude-code 2.1.152"
The old row (table_name = 'population') is gone — so this is a
delete-and-restub on rename, not an update.
Why it matters
The catalog is the user-visible record of "where did this data come
from and why is it here." Losing it on rename means:
- Any prose set via
set_table_metadata is silent collateral.
load_params (which records the original source path / mode /
schema overrides) is gone, so notes-based "refresh by re-running
this command" instructions become the only recovery path — and
those are exactly what was just deleted.
- Renames are a normal organizational operation (e.g. adding a
source-prefix like owid_ to group related tables); users
shouldn't have to choose between tidy names and provenance.
Suggested fix
When ALTER TABLE ... RENAME TO ... is observed (either via
execute SQL inspection or post-hoc reconciliation against
SHOW TABLES), update _table_catalog.table_name in place rather
than dropping the row and lazily re-stubbing on next access.
If in-place update isn't feasible (e.g. catalog reconciliation runs
on a different timer), at minimum carry forward the prose fields
from the old row when the new stub is written.
OR
Add a dedicated rename_table tool would let the server handle the catalog update atomically: update table_name in place, preserve all prose fields, and keep
loaded_at/created_by anchored. The execute path can't do that cleanly because the server only sees raw SQL, not the intent.
Worth adding to the issue as a "Suggested fix / new tool" option alongside the in-place-update approach.
Workaround
After every rename, re-run set_table_metadata with the same
fields. Tedious but works. Verified on hyper-rust-api 0.2.3.re93d08d2.
Environment
hyper-rust-api version: 0.2.3.re93d08d2
- macOS 25.4.0 (Darwin)
- Persistent database (
~/Library/Application Support/hyperdb/workspace.hyper)
Summary
ALTER TABLE ... RENAME TO ...(via theexecutetool) re-stubs thetarget table's
_table_catalogrow and drops all prose metadata(
source_url,source_description,purpose,notes,license).It also resets
load_tool,load_params,created_by, andlast_modified_byto NULL/unknown, and overwritesloaded_at/last_refreshed_atwith the rename time (so the row looks like afresh load that didn't actually happen).
The rename succeeds and the data is fine — only the catalog
provenance is lost.
Steps to reproduce
Expected
The row should follow the rename — the same provenance, with only
table_nameupdated.loaded_atandlast_refreshed_atshouldstay anchored to the original load time.
Actual
The old row (
table_name = 'population') is gone — so this is adelete-and-restub on rename, not an update.
Why it matters
The catalog is the user-visible record of "where did this data come
from and why is it here." Losing it on rename means:
set_table_metadatais silent collateral.load_params(which records the original source path / mode /schema overrides) is gone, so
notes-based "refresh by re-runningthis command" instructions become the only recovery path — and
those are exactly what was just deleted.
source-prefix like
owid_to group related tables); usersshouldn't have to choose between tidy names and provenance.
Suggested fix
When
ALTER TABLE ... RENAME TO ...is observed (either viaexecuteSQL inspection or post-hoc reconciliation againstSHOW TABLES), update_table_catalog.table_namein place ratherthan dropping the row and lazily re-stubbing on next access.
If in-place update isn't feasible (e.g. catalog reconciliation runs
on a different timer), at minimum carry forward the prose fields
from the old row when the new stub is written.
OR
Add a dedicated rename_table tool would let the server handle the catalog update atomically: update table_name in place, preserve all prose fields, and keep
loaded_at/created_by anchored. The execute path can't do that cleanly because the server only sees raw SQL, not the intent.
Worth adding to the issue as a "Suggested fix / new tool" option alongside the in-place-update approach.
Workaround
After every rename, re-run
set_table_metadatawith the samefields. Tedious but works. Verified on
hyper-rust-api 0.2.3.re93d08d2.Environment
hyper-rust-apiversion:0.2.3.re93d08d2~/Library/Application Support/hyperdb/workspace.hyper)