OriginChain docs
examples · sql · 12 / 13 · use a transaction

12. DELETE via /sql

← SQL examples
read this first

A bare DELETE FROM ... outside a transaction does not reliably remove the row - the response echoes the translated delete (the resolved pk) but the row can survive. Delete rows through the typed row delete path, or wrap the DELETE in an explicit BEGIN; ... COMMIT; transaction (below) - that route applies the removal durably on commit.

supported - delete inside a transaction

Inside an open transaction, a primary-key DELETE buffers a row-removal op and the COMMIT applies it durably in one frame. Carry the same session id across all three calls so they share one transaction buffer.

POST /v1/tenants/:t/sql (BEGIN / DELETE / COMMIT)
# Supported SQL route: wrap the DELETE in an explicit transaction.
# The same session id must accompany BEGIN, the DELETE, and COMMIT so
# the buffered row-removal is applied atomically on COMMIT.
SID="sess-$(date +%s)"

# 1. open the transaction
curl -X POST "https://$OC_HOST/v1/tenants/$OC_TENANT/sql" \
  -H "Authorization: Bearer $OC_TOKEN" \
  -H "X-OC-Session-Id: $SID" \
  -H "Content-Type: application/json" \
  -d '{ "sql": "BEGIN" }'

# 2. buffer the delete (matched by primary key)
curl -X POST "https://$OC_HOST/v1/tenants/$OC_TENANT/sql" \
  -H "Authorization: Bearer $OC_TOKEN" \
  -H "X-OC-Session-Id: $SID" \
  -H "Content-Type: application/json" \
  -d '{ "sql": "DELETE FROM shop.orders WHERE id = '\''o_003'\''" }'

# 3. commit - the buffered row-removal lands durably here
curl -X POST "https://$OC_HOST/v1/tenants/$OC_TENANT/sql" \
  -H "Authorization: Bearer $OC_TOKEN" \
  -H "X-OC-Session-Id: $SID" \
  -H "Content-Type: application/json" \
  -d '{ "sql": "COMMIT" }'
responses
// the DELETE step, inside the open transaction:
{
  "kind":          "delete",
  "schema":        "shop.orders",
  "pk":            "o_003",
  "rows_buffered": 1
}

// the COMMIT step - the buffered op is now durable:
{
  "kind":          "tx",
  "op":            "commit",
  "ops_committed": 1
}

rows_buffered is 1 when the row existed (and 0 when it didn't). The removal is not visible to other readers until COMMIT returns ops_committed: 1.

also supported - typed row delete

When you already hold the primary key and don't need SQL, delete the row through the typed row endpoints. The row delete path carries the same idempotency-key plumbing as the rest of the typed /rows surface.

not reliable - bare DELETE outside a transaction

For reference, this is the shape that does not guarantee removal. The response is a translation of the statement, not a confirmation the row is gone - don't depend on it to delete data.

POST /v1/tenants/:t/sql (translation only - row may persist)
# A bare DELETE outside a transaction does NOT reliably remove the row.
# The response echoes the translated delete (the pk it resolved) - treat
# it as a translation, not a confirmation that the row is gone.
curl -X POST "https://$OC_HOST/v1/tenants/$OC_TENANT/sql" \
  -H "Authorization: Bearer $OC_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "sql": "DELETE FROM shop.orders WHERE id = '\''o_003'\''"
  }'
response (a translation - not a confirmed delete)
{
  "kind":   "delete",
  "schema": "shop.orders",
  "pk":     "o_003"
}