Load & edit

Upsert / merge by key

Insert, update, and delete rows in one atomic call with merge_rows - the default mutation tool.

merge_rows is the default tool for most mutations. It handles INSERT, UPDATE, and DELETE in a single atomic call - one Delta version - keyed on the primary key. If every row is new, plain insert_rows is simpler.

Merge

eddytor merge table eddytor sales orders --file ./changes.csv
{
  "table": "eddytor.cfg_xxx.<uuid>_products",
  "comment": "Q1 price update and product retirement",
  "rows": [
    { "_operation": "INSERT", "product_id": "P200", "name": "New Item", "category": "Clothing", "price": 19.99, "status": "active" },
    { "_operation": "UPDATE", "product_id": "P001", "price": 34.99 },
    { "_operation": "DELETE", "product_id": "P050" }
  ]
}

The rules

Heads up

_operation is required on every row in merge_rows - forgetting it errors. UPDATE rows need only the PK + changed fields (omitted columns keep their values). DELETE rows need only the PK. The whole batch is atomic - if any row violates a constraint or domain, the entire batch is rejected; partial success is impossible by design.

Add a comment - it's recorded on the Delta version, so the history tells you why a change was made.

Update by primary key

To change existing rows, send _operation: "UPDATE" rows keyed on the primary key:

eddytor merge table eddytor sales orders --file ./price-changes.csv
{ "table": "eddytor.cfg_xxx.<uuid>_products",
  "comment": "Q1 repricing",
  "rows": [
    { "_operation": "UPDATE", "product_id": "P001", "price": 34.99 },
    { "_operation": "UPDATE", "product_id": "P002", "price": 12.50, "status": "active" }
  ]}

Send PK + changed fields only. Sending every column wastes bandwidth and risks clobbering a concurrent change to a field you didn't mean to touch.

Update by condition

merge_rows keys on the PK, so to update "all rows where …":

  1. query_rows with the filter to get the matching PKs.
  2. Build UPDATE rows for those PKs.
  3. merge_rows with a comment.

Data-sync pattern

  1. query_rows → understand current state.
  2. Compute the diff → which rows INSERT / UPDATE / DELETE.
  3. merge_rows with a comment → one atomic version.
  4. validate_constraints + validate_domain_values.

On this page