Skip to Content
We are live but in Staging 🎉

Update

Update matched rows with a flat column → value map. The predicate is a SQL WHERE clause. Keyed predicates (matching the table’s merge_keys) route through the write log; non-keyed predicates update Delta directly (WAL-bypass risk). See the Data hub for the full RPC list.

RPCHTTP
UpdatePOST /:bucket/tables/:table_name/update

gRPC setup — grpcurl, endpoints, reflection, and field-name casing — is covered once in Conventions → Using gRPC.

Update

Request

Keyed update (predicate matches the table’s merge_keys):

curl -sS -X POST "https://k3.dev.dodil.io/kb-prod/tables/events/update" \ -H "Authorization: Bearer $DODIL_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "bucket": "kb-prod", "tableName": "events", "predicate": "id = 1 AND user_id = '\''u-101'\''", "updates": { "event_type": "click_pricing" } }'

Non-keyed variant (⚠️ Delta-only, WAL-bypass):

curl -sS -X POST "https://k3.dev.dodil.io/kb-prod/tables/events/update" \ -H "Authorization: Bearer $DODIL_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "bucket": "kb-prod", "tableName": "events", "predicate": "occurred_at < TIMESTAMP '\''2025-01-01 00:00:00'\''", "updates": { "event_type": "archived" } }'

Response

{ "tableName": "events", "predicate": "id = 1 AND user_id = 'u-101'", "columnsUpdated": ["event_type"], "version": "0", "rowsWritten": "1", "pendingDrain": true }

⚠️ Wire-shape gotchaupdates is a flat JSON object of column → literal. Do NOT wrap with "fields" — pbjson maps the object’s top-level entries directly to the Struct’s fields. {"updates": {"fields": {...}}} parses as a meaningless single-column SET clause, the request succeeds but updates nothing.

Keyed vs non-keyed routing: if predicate references the table’s merge_keys (e.g. id = 1 AND user_id = 'u-101' against merge_keys: [id, user_id]), the planner picks KEYED_UPDATE and routes through the write log. Otherwise it picks NON_KEYED_UPDATE and updates Delta directly — see Execute → Update for the WAL-bypass risk.

See also