Skip to content

feat(harness): python node write modes (append, upsert) - #80

Merged
carolsimone merged 6 commits into
mainfrom
feat/write-modes-harness
Oct 11, 2026
Merged

carolsimone merged 6 commits into
mainfrom
feat/write-modes-harness

Conversation

@carolsimone

Copy link
Copy Markdown
Owner

Sixth runtime PR of the write-modes series (spec R6). Depends on R1–R5; stacked on #78 (Trino) locally — base is feat/write-modes-trino; retarget to main as the stack merges.

  • _WRITERS beside _PRODUCERS: replace -> load, append -> AppendCapable.append, upsert -> UpsertCapable.upsert. The capability is checked right after the config tripwire, so LoadError: <Adapter> does not support <mode> comes before the script runs or the warehouse is touched. (This replaces the interim guard added to feat(contract): mode_type and primary_key contract fields #74 after review — see that thread.)
  • The upsert key goes to ensure_table(primary_key=...) and upsert as written (the loader requires each key name to match an output column exactly).
  • continuo_python_runtime/shape.py: shape_diff (names case-insensitive, nullability exact, order and types ignored). Before an append or upsert the live TARGET_SCHEMA.TABLE_NAME is compared and any difference is one LoadError naming all of them.
  • DuplicateKeyError -> ConformError (the script's rows are at fault), caught before the generic wrapper; every other write failure stays LoadError.
  • End to end on all three engines: two append runs accumulate, two upsert runs overwrite by key (and keep the Postgres PRIMARY KEY); a drifted Postgres table is refused.
  • README "Write modes", error taxonomy, boundary contract §13.4.

The version bumps and the tag follow in a separate chore(release) PR after this merges.

🤖 Generated with Claude Code

https://claude.ai/code/session_0137E9XmyUXhwPTRrtNfivDw

@carolsimone carolsimone self-assigned this Oct 10, 2026
@carolsimone
carolsimone force-pushed the feat/write-modes-trino branch from 8d7772b to e335444 Compare October 11, 2026 11:31
Base automatically changed from feat/write-modes-trino to main October 11, 2026 12:28
carolsimone and others added 6 commits October 11, 2026 14:29
A pure comparison: names case-insensitively (exact spelling paired first),
nullability exactly, order and types ignored. ShapeDiff lists missing and
unexpected columns and nullability mismatches, and renders one message
naming all of them and the remedy.

Signed-off-by: Simone Carolini <simonecarolini.sc@gmail.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0137E9XmyUXhwPTRrtNfivDw
_WRITERS maps replace, append and upsert to the capability they need and the
write call. The capability is checked right after the config tripwire, so an
engine that cannot append fails before the script runs. The upsert key goes to
ensure_table and upsert as written; DuplicateKeyError
becomes ConformError, any other write failure stays LoadError.

Signed-off-by: Simone Carolini <simonecarolini.sc@gmail.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0137E9XmyUXhwPTRrtNfivDw
After ensure_table, an append or upsert compares the target table's columns
with output_columns (names case-insensitive, nullability exact, order and
types ignored) and fails with one LoadError naming every difference. It
inspects TARGET_SCHEMA.TABLE_NAME, the table actually written.

Signed-off-by: Simone Carolini <simonecarolini.sc@gmail.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0137E9XmyUXhwPTRrtNfivDw
Two append runs keep both runs' rows; two upsert runs overwrite by
(rate_date, base) and leave the PRIMARY KEY in place; an append into a table
missing a declared column fails with LoadError naming it and writes nothing.

Signed-off-by: Simone Carolini <simonecarolini.sc@gmail.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0137E9XmyUXhwPTRrtNfivDw
Two append runs keep both runs' rows; two upsert runs overwrite by
(rate_date, base) on the DuckLake stack.

Signed-off-by: Simone Carolini <simonecarolini.sc@gmail.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0137E9XmyUXhwPTRrtNfivDw
Two append runs keep both runs' rows; two upsert runs overwrite by
(rate_date, base) on the Trino plus Iceberg stack.

Signed-off-by: Simone Carolini <simonecarolini.sc@gmail.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0137E9XmyUXhwPTRrtNfivDw
@carolsimone
carolsimone force-pushed the feat/write-modes-harness branch from c43b433 to f37b28c Compare October 11, 2026 12:30
@carolsimone carolsimone added the documentation Improvements or additions to documentation label Oct 11, 2026
@carolsimone
carolsimone merged commit a2e9be1 into main Oct 11, 2026
28 checks passed
@carolsimone
carolsimone deleted the feat/write-modes-harness branch October 11, 2026 13:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant