Skip to content

feat(postgres): append and upsert - #76

Merged
carolsimone merged 6 commits into
mainfrom
feat/write-modes-postgres
Oct 10, 2026
Merged

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

Conversation

@carolsimone

Copy link
Copy Markdown
Owner

Third runtime PR of the write-modes series (spec R3). Stacked on #75 (engine port, contract 0.8.0) — base is feat/write-modes-engine-port; retarget to main as the stack merges.

  • Refactor (D20): _insert_rows and _transaction are the one insert path and transaction shape behind load, append and _upsert; load is unchanged in behavior.
  • PostgresAdapter(WarehouseAdapter, AppendCapable, UpsertCapable): table_columns (information_schema, LookupError when absent), append, _upsert (INSERT ... ON CONFLICT (key) DO UPDATE SET c = EXCLUDED.c, DO NOTHING when every column is in the key). Zero rows open no transaction.
  • ensure_table(..., primary_key=...) declares the key as PRIMARY KEY in the CREATE TABLE; without a key the DDL is unchanged.
  • The engine-contract conformance suite (introspection, append, upsert) runs in the postgres integration job, plus postgres-only checks: an enforced constraint, and an upsert into a table without it fails and writes nothing.

🤖 Generated with Claude Code

https://claude.ai/code/session_0137E9XmyUXhwPTRrtNfivDw

@carolsimone
carolsimone force-pushed the feat/write-modes-engine-port branch 2 times, most recently from 1161ec3 to 28b6402 Compare October 10, 2026 12:43
Base automatically changed from feat/write-modes-engine-port to main October 10, 2026 14:24
@carolsimone carolsimone self-assigned this Oct 10, 2026
carolsimone and others added 5 commits October 10, 2026 16:27
load now writes through _insert_rows and _transaction, which append and
upsert will share: batched execute_values inserts naming the data's columns,
with the existing percent escaping, inside an explicit BEGIN and COMMIT that
rolls back on error. No behavior change.

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
PostgresAdapter declares TableIntrospection and reports each column's name
and nullability, raising LookupError for a missing table. The engine-contract
conformance suite runs against the postgres stack from here on.

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
PostgresAdapter declares AppendCapable: one explicit transaction of batched
inserts through the shared insert helper; zero rows write nothing. Passes the
append conformance cases, including atomicity across insert pages, quoted
names and a different column order.

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
A primary_key passed to ensure_table becomes the created table's enforced,
indexed PRIMARY KEY; a key on an undeclared column is rejected before any DDL.
Without a key the CREATE TABLE is byte-identical to before.

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
PostgresAdapter declares UpsertCapable: one transaction of batched inserts
with ON CONFLICT (key) DO UPDATE SET each non-key column from EXCLUDED, or DO
NOTHING when every column is in the key. A table without the key constraint
fails instead of collecting duplicates. Passes the upsert conformance cases.

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-postgres branch from fdd7a69 to efbe27b Compare October 10, 2026 14:28
The engine-contract conformance suite moved to
continuo_engine_contract.testing.conformance in #75; the postgres
integration test still imported the pre-move path and failed collection
once #75 merged to main.

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 merged commit bd48d2a into main Oct 10, 2026
28 checks passed
@carolsimone
carolsimone deleted the feat/write-modes-postgres branch October 10, 2026 21:25
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