Transactions

specdraftimplproposal

Atomic and batch transactions over multiple feature collections.

Scope

Provides a single resource POST /transactions that accepts a transaction document describing one or more insert, replace, update or delete actions across one or more feature collections of the API. The canonical request encoding is application/ogc-tx+json; the response is application/json.

Two semantics are supported: atomic transactions execute all actions as a single database transaction (rollback on failure), batch transactions execute each action independently and report per-action results.

For interoperability with WFS 2.0 producers the building block can additionally accept wfs:Transaction XML payloads in atomic mode.

The Prefer request header is honoured per RFC 7240: return=representation (the default), return=minimal, or return=none controls how much of the transaction response is returned; handling=strict validates every insert and replace payload against the feature-type schema before any provider write (this only takes effect when the collection has schema validation configured \u2014 JSON Schema for GeoJSON payloads, XSD for GML payloads). respond-async is rejected with 501.

The Content-Crs request header declares the CRS of coordinates in the request body. When omitted, the API's default CRS (CRS84 unless overridden) is assumed; values that are syntactically invalid or name a CRS not in the API's supported list are rejected with a 4xx error.

Both successful and atomic-failed responses use the same Part 11 Transaction Response document shape (with summary, the per-action result arrays, and an exceptions[] array when applicable), so clients do not need to branch on the response status to parse the body.

Limitations

The following restrictions apply:

  • Provider and request scope:
  • Only feature types from an SQL feature provider that supports mutations
    (datasetChanges.mode CRUD) are supported.
  • Asynchronous transactions are not supported.
  • Responses are always JSON; the WFS wfs:TransactionResponse XML response is not produced.
  • wfs:Transaction XML payloads are accepted in atomic mode only.
  • Filters in update, replace, and delete actions:
  • Filters are restricted to selecting features by id. JSON action bodies accept either a
    CQL2 IN(<id-property>, [...]) or <id-property> = ... expression, where
    <id-property> is the schema name (or alias, if declared) of the feature type's
    property with role ID; other CQL2 predicates (comparison, spatial, temporal, or
    boolean operators on regular properties) are rejected with a 4xx error.
  • wfs:Transaction XML accepts only fes:ResourceId/@rid; no other fes:Filter element
    types are recognised.
  • update semantics:
  • An update action applies property-level partial updates to a single existing feature in
    place: each touched property is translated into a native SQL UPDATE (for columns on the
    feature's main table, including geometries) or a DELETE-then-INSERT against the
    associated child table (for VALUE_ARRAY and OBJECT_ARRAY properties). All statements
    run on the same session connection as the rest of the transaction, so an update can
    target a feature that was inserted, replaced, updated, or whose junction rows were
    touched earlier in the same atomic request.
  • The set of properties that may be the target of a partial update is governed by
    updatableProperties on the collection's TRANSACTIONS configuration; a property whose
    canonical path is not in that list is rejected with a 4xx error. The whitelist defaults
    to an empty list, which disables partial updates for the collection. Entries are the
    schema property identifiers, joined by . (e.g. lifetime.end for a nested property,
    name for a top-level scalar).
  • Property paths are resolved against the feature schema and the input format's useAlias
    setting. JSON-transaction name and delete paths use the canonical dotted form (the
    . separator; XPath-style / is reserved for wfs:ValueReference). A wfs:Update's
    wfs:ValueReference follows the XPath form and must include the intermediate
    object-type element (e.g. lifetime/Lifetime/end); XML namespace prefixes are stripped,
    only local names and the path structure are significant.
  • When the filter selects more than one id (e.g. IN(id, ['a','b']) or multiple
    fes:ResourceId/@rid), the same patch is applied to every selected feature.
  • An absent value (a <wfs:Property> with no <wfs:Value>, or a JSON-tx delete entry)
    clears the property: SQL NULL for a column on the main table, or an empty result for
    a VALUE_ARRAY / OBJECT_ARRAY (all junction rows for that property are removed and
    none are re-inserted).
  • Geometries: a wfs:Update may set a geometry property by placing the corresponding GML
    geometry element (e.g. <gml:Point>) inside <wfs:Value>. A JSON-transaction update
    uses a GeoJSON geometry object as the property value. Both forms re-use the same
    CRS-aware encoder as insert / replace. The geometry property must live on the
    feature's main table; geometry on a child table is not supported.
  • Value arrays (VALUE_ARRAY): multiple sibling <wfs:Property> elements with the same
    wfs:ValueReference collapse into one array on the WFS side (each value contributes
    one element). A JSON-transaction update uses a JSON array of scalars. The whole array
    is replaced.
  • Object arrays (OBJECT_ARRAY): a wfs:Update sets an OBJECT_ARRAY property by
    placing one or more object-type wrapper elements inside <wfs:Value> (one per array
    element); a JSON-transaction update uses a JSON array of objects. Object keys / child
    element local names are matched against the array's schema in the same way as scalar
    paths (id vs alias per useAlias); unknown keys are silently ignored. The whole array
    is replaced. Nested object children inside an array element, M:N junctions, and
    FEATURE_REF arrays are not yet supported.

Conformance Classes

The building block is based on the conformance classes "Transactions", "Atomic Semantics", "Batch Semantics", "JSON Encoding" and "Features" from the Draft OGC API - Features - Part 11: Atomic and Batch Transactionsopen in new window.

Configuration

Options

NameDefaultDescriptionTypeSince
buildingBlock
Always TRANSACTIONS.
string
v2.0
enabled
false
Enable the building block?
boolean
v2.0
atomic
true
Advertises the conformance class for atomic transactions. When enabled, requests without a semantic parameter or with semantic=atomic are executed as a single database transaction; any failure rolls back the whole request.
boolean
v4.8
batch
true
Advertises the conformance class for batch transactions. When enabled, requests with semantic=batch execute each action independently and report per-action results, including exceptions for failures.
boolean
v4.8
wfsTransaction
false
Enables decoding of WFS 2.0 wfs:Transaction XML payloads at POST /transactions. Only valid when atomic is true and the GML building block is enabled.
boolean
v4.8
defaultSemantic
ATOMIC
Semantic applied to requests that do not specify one. The default matches the OGC API Features Part 11 specification default.
string
v4.8
maxActionsPerRequest
0
Optional upper bound on the number of actions per request. A value of zero or null disables the limit.
number
v4.8
collectErrors
false
Only relevant for atomic semantics. When enabled, a failing action does not stop the processing of the transaction: the remaining actions are still executed, every error is collected, and the response reports all of them, while all changes are still rolled back. This lets clients fix every error in a large transaction in one pass instead of one error per attempt. Later actions see the changes of earlier successful actions, but not those of failed actions \u2014 an action that depends on a failed action therefore typically reports a follow-on error. Each action adds a small database overhead (a savepoint), which can be noticeable in very large transactions. Requires a SQL feature provider; otherwise the option is ignored. When disabled, processing stops at the first error, the remaining actions are skipped, and only the first error is reported.
boolean
v4.8
updatableProperties
[]
Whitelist of feature properties that may be the target of a partial update (the wfs:Update action of a wfs:Transaction, or the JSON-transaction update action). Each entry is a property path written as the schema property identifiers joined by ., e.g. lifetime.end for a nested property or name for a top-level scalar. Path segments are always the canonical schema identifiers, independent of the input format's alias setting. A partial update whose property path is not in this list is rejected with a 4xx error. Entries set at the API level apply to every collection; entries set on a specific collection are merged with the API-level list (duplicates de-duplicated). When the effective list for a collection is empty, partial updates are disabled for that collection.
array
v4.8
transactionSetup
null
SQL statements executed on the database transaction right after it begins, before any action runs. Typical uses are transaction-scoped settings (SET LOCAL \u2026) or calling a setup function. Each entry is a single statement run verbatim, in order, on the provider's transaction connection (PostgreSQL/PostGIS feature providers only). The always, strict and lenient lists select which statements run depending on the request's Prefer: handling preference. A statement that fails aborts the transaction.
object
v4.8
preCommit
null
SQL statements executed on the database transaction right before it is committed. Typical uses are calling functions that update derived data or verify consistency. Each entry is a single statement run verbatim, in order, on the provider's transaction connection (PostgreSQL/PostGIS feature providers only). The always, strict and lenient lists select which statements run depending on the request's Prefer: handling preference. A statement that raises an error aborts the transaction and rolls it back; a statement that only emits a warning (RAISE WARNING / RAISE NOTICE) lets the transaction commit and the warning is returned in the response. The error and warning text is relayed verbatim into the response (exceptions and warnings), and the statements run at the database level without access to the request actions, so write RAISE messages that identify the affected feature(s) \u2014 e.g. include the feature identifier \u2014 to make the response actionable.
object
v4.8
updatablePropertyPaths
array
v2.0

This building block does not require or support any additional configuration files.

Examples


- buildingBlock: TRANSACTIONS
 enabled: true
 atomic: true
 batch: true
 wfsTransaction: false
 defaultSemantic: ATOMIC
 collectErrors: true

Per-collection partial-update whitelist (allows wfs:Update / JSON-transaction update
actions to set the listed scalar/datetime/geometry/VALUE_ARRAY/OBJECT_ARRAY properties):


collections:
 places:
   api:
     - buildingBlock: TRANSACTIONS
       updatableProperties:
         - location           # geometry on the main table
 buildings:
   api:
     - buildingBlock: TRANSACTIONS
       updatableProperties:
         - name               # top-level scalar
         - lifetime.end       # nested property
         - tags               # VALUE_ARRAY
         - addresses          # OBJECT_ARRAY

Transaction-lifecycle hooks (PostgreSQL/PostGIS providers). Statements are selected by the
request's Prefer: handling preference; a pre-commit error rolls the transaction back, a
pre-commit warning lets it commit and is returned in the response:


- buildingBlock: TRANSACTIONS
 transactionSetup:
   always:
     - SET LOCAL myapp.geometry_validation.enabled = true
   strict:
     - SET LOCAL myapp.geometry_validation.error_if_invalid = true
   lenient:
     - SET LOCAL myapp.geometry_validation.error_if_invalid = false
 preCommit:
   always:
     - SELECT myapp.update_derived_data()
   strict:
     - SELECT myapp.assert_consistency()