Targets
The target side of a pipeline owns the PIPELINE.WRITE phase plus the pre-write clear (truncate / deleteSlice) that full-refresh and partial-refresh modes need. A target adapter reports its capabilities() so addPipeline can reject incompatible configs at registration time rather than halfway through the first run.
Every write is dispatched through the resolved target adapter. Non-db targets without a target.adapter class reference are rejected at registration — there is no silent fallback to the local DB.
Resolution order
addPipeline(...) resolves the target adapter in this order:
config.target.adapter— class reference extendingBaseTargetAdapter. Full control; takes precedence overtarget.service.config.target.serviceunset or'db'→ built-inDbTargetAdapter.config.target.kind('odata' | 'odata-v2') — explicit transport selector. Takes precedence over the connected service's auto-detected kind.- Auto-detected
service.options.kind('odata' | 'odata-v2') on the connected remote service → built-inODataTargetAdapter. - Any other
config.target.servicewith notarget.adapter→ registration error pointing to Custom target adapter.
Built-in target adapters
| Adapter | Resolved when | Capabilities | Page |
|---|---|---|---|
DbTargetAdapter | target.service unset or 'db' | batchInsert, keyAddressableUpsert, batchDelete, truncate | Local DB |
ODataTargetAdapter | target.kind is 'odata' / 'odata-v2', or the connected service advertises that kind | batchInsert, keyAddressableUpsert, batchDelete, truncate | OData |
| Any other transport | Register a custom target adapter | Whatever the adapter advertises |
Local DB — The default. Resolved automatically when
target.serviceis unset or'db'. WritesUPSERT/INSERT/DELETEvia CAP'scds.connect.to('db').OData — Forward writes to a remote OData V2 / V4 service through CAP's remote runtime —
UPSERT.entries(...)→ POST / PUT / PATCH, with$batchchange sets where the provider supports them.Custom target adapter — Extend
BaseTargetAdapterfor non-db, non-OData destinations (message buses, custom HTTP APIs, …). Worked example: a reporting service oversrv.send().
Capability gating
addPipeline rejects incompatible configs by consulting the target adapter's capabilities():
| Config | Required capability |
|---|---|
mode: 'delta' | keyAddressableUpsert |
mode: 'full' | truncate or batchDelete |
source.query (query-shape) | batchInsert |
Omitted keys default to false. Report only what your adapter actually supports — addPipeline rejects users at registration rather than halfway through the first run. The default DbTargetAdapter reports all four capabilities as true.
Transactional semantics
Query-shape (snapshot) pipelines run inside a cds.tx transaction — so truncate / deleteSlice + batch INSERTs commit atomically and a mid-run crash leaves the previous snapshot intact. Entity-shape (UPSERT) pipelines run without an outer transaction: each batch commits on its own so partial progress survives interruptions.
Target adapters do not have to manage cds.tx themselves; they inherit the ambient cds.context / transaction. Custom remote-protocol adapters (e.g. a reporting-service adapter) need to surface their own atomicity guarantees at the service boundary — cds.tx does not span remote HTTP calls.
See also
- Concepts → Inference rules — target adapter selection and the full registration matrix.
- Sources — the peer section covering the READ phase.
- Recipes → Custom target adapter — end-to-end reporting-service example.