ERPL Function Reference
Complete reference for all ERPL functions organized by protocol. This reference covers RFC, BICS, and ODP functions with parameters, return types, and examples.
RFC Functions
Core RFC Functions
sap_read_table()
Read data from SAP tables.
Signature:
sap_read_table(table_name VARCHAR, [COLUMNS LIST(VARCHAR)], [FILTER VARCHAR], [MAX_ROWS UINTEGER], [THREADS UINTEGER], [READ_TABLE_FUNCTION VARCHAR], [READ_TABLE_DELIMITER VARCHAR], [SECRET VARCHAR])
Parameters:
| Parameter | Type | Description | Example |
|---|---|---|---|
table_name | VARCHAR (positional) | SAP table name | 'KNA1' |
COLUMNS | LIST(VARCHAR) | Restrict to a subset of columns | COLUMNS => ['KUNNR', 'NAME1'] |
FILTER | VARCHAR | OpenSQL-style WHERE-fragment passed straight to RFC. Use for filters too complex to push down. | FILTER => 'LAND1 = ''DE''' |
MAX_ROWS | UINTEGER | Maximum rows to return | MAX_ROWS => 1000 |
THREADS | UINTEGER | Number of parallel RFC threads to read partitions (default: 5) | THREADS => 4 |
READ_TABLE_FUNCTION | VARCHAR | Override the underlying RFC function module (e.g. /SAPDS/RFC_READ_TABLE2 for wide rows) | READ_TABLE_FUNCTION => '/SAPDS/RFC_READ_TABLE2' |
READ_TABLE_DELIMITER | VARCHAR | Delimiter used by RFC when packing rows. Override for tables whose values may contain whitespace. | `READ_TABLE_DELIMITER => ' |
SECRET | VARCHAR | Name of the DuckDB secret to authenticate with (if multiple SAP connections are configured) | SECRET => 'erp_prod' |
A regular SQL WHERE clause is automatically pushed down to RFC — you don't need the FILTER named parameter for simple predicates:
SELECT KUNNR, NAME1 FROM sap_read_table('KNA1') WHERE LAND1 = 'DE';
COLUMNS is similarly inferred from the SELECT list. Reach for the named parameters when you need precise control over what RFC receives — for example, complex multi-table filters that DuckDB's optimizer can't safely lower.
RFC's underlying RFC_READ_TABLE has no server-side sort. Apply ORDER BY in DuckDB after the read; it executes client-side.
Example:
SELECT * FROM sap_read_table('KNA1', MAX_ROWS => 100);
sap_rfc_invoke()
Call SAP function modules and BAPIs.
Signature:
sap_rfc_invoke(function_name VARCHAR, [parameters...], [path VARCHAR], [secret VARCHAR])
Input parameters are passed as positional struct arguments after the function name — one struct per import / changing parameter the BAPI expects. DuckDB struct syntax ({'KEY': value, ...}) lets you express nested structures and tables naturally.
Parameters:
| Parameter | Type | Description | Example |
|---|---|---|---|
function_name | VARCHAR (positional) | SAP function module / BAPI name | 'BAPI_FLIGHT_GETLIST' |
parameters... | STRUCT (positional varargs) | One struct per RFC import/changing parameter | {'AIRLINE': 'LH', 'DESTINATION_FROM': {'AIRPORTID': 'FRA'}} |
path | VARCHAR (named) | Optional path into the response structure — picks a sub-table of the result | path => '/FLIGHT_LIST' |
secret | VARCHAR (named) | Name of the DuckDB secret to authenticate with | secret => 'erp_prod' |
Example:
-- Simple call with named import parameters
SELECT trim(ECHOTEXT)
FROM sap_rfc_invoke('STFC_CONNECTION', {'REQUTEXT': 'Hello'});
-- BAPI call selecting a nested result table via path
SELECT *
FROM sap_rfc_invoke(
'BAPI_FLIGHT_GETLIST',
{'AIRLINE': 'LH', 'DESTINATION_FROM': {'AIRPORTID': 'FRA'}},
path => '/FLIGHT_LIST'
);
RFC Metadata Functions
sap_rfc_describe_function()
Get detailed information about RFC function parameters.
Signature:
sap_rfc_describe_function(function_name VARCHAR)
Example:
SELECT * FROM sap_rfc_describe_function('BAPI_FLIGHT_GETLIST');
sap_describe_fields()
Get table structure and field information.
Signature:
sap_describe_fields(table_name VARCHAR)
Example:
SELECT * FROM sap_describe_fields('KNA1');
sap_rfc_authorizations()
List which SAP RFC function module each ERPL function invokes — useful when requesting RFC
authorizations from SAP Basis. Returns extension, duckdb_function, rfc_function_module,
invocation, and purpose. Takes no arguments and needs no SAP connection.
Signature:
sap_rfc_authorizations()
Example:
SELECT DISTINCT rfc_function_module
FROM sap_rfc_authorizations()
WHERE extension = 'erpl_rfc';
sap_rfc_show_function()
List all available RFC functions.
Signature:
sap_rfc_show_function()
Example:
SELECT * FROM sap_rfc_show_function();
sap_rfc_show_groups()
List all RFC function groups.
Signature:
sap_rfc_show_groups()
Example:
SELECT * FROM sap_rfc_show_groups();
sap_show_tables()
List all available SAP tables.
Signature:
sap_show_tables()
Example:
SELECT * FROM sap_show_tables();
BICS Functions
BICS queries are built compositionally by chaining functions: begin → columns / rows / filter → result. Each step returns a state identifier that the next step consumes. Set return => 'DESCRIBE' (default) to inspect the in-progress query plan, or return => 'RESULT' to short-circuit and execute.
Basic Query Functions
sap_bics_show()
List InfoProviders (default), cubes, queries, or InfoAreas registered on the BW system.
Signature:
sap_bics_show()
Parameters (all named):
| Parameter | Type | Description | Example |
|---|---|---|---|
obj_type | ENUM | One of 'INFOPROVIDER' (default), 'QUERY', 'CUBE', 'INFOAREA' | obj_type => 'CUBE' |
search | VARCHAR | Glob pattern to filter results | search => '0D_NW*' |
search_in_key | BOOLEAN | Match against object key (default: true) | search_in_key => false |
search_in_text | BOOLEAN | Match against display text (default: true) | search_in_text => true |
fetch_levels | UINTEGER | Hierarchy depth to traverse (default: 0) | fetch_levels => 2 |
secret | VARCHAR | DuckDB secret name | secret => 'erp_prod' |
Example:
SELECT * FROM sap_bics_show();
SELECT * FROM sap_bics_show(obj_type => 'CUBE', search => '0D_NW*');
sap_bics_show_cubes()
Convenience wrapper — list cubes only. Equivalent to sap_bics_show(obj_type => 'CUBE') with a slightly different result shape tuned for cubes.
Signature:
sap_bics_show_cubes()
Parameters (all named): search, search_in_key, search_in_text, secret (same semantics as sap_bics_show).
Example:
SELECT * FROM sap_bics_show_cubes(search => '0D_NW*');
sap_bics_show_queries()
Convenience wrapper — list BEx queries only.
Signature:
sap_bics_show_queries()
Parameters (all named): search, search_in_key, search_in_text, secret.
Example:
SELECT * FROM sap_bics_show_queries(search => 'ZFI*');
sap_bics_describe()
Describe cube structure or query.
Signature:
sap_bics_describe([cube_name VARCHAR], [query_name VARCHAR])
Example:
SELECT * FROM sap_bics_describe('0D_NW_C01');
sap_bics_begin()
Open a BICS query state against an InfoProvider or query. Pass an id to name the state; the
other query functions reference that string id — they are called in sequence, not
nested inside one another.
Signature:
sap_bics_begin(cube_or_query_name VARCHAR, [id => VARCHAR, return => 'DESCRIBE'|'RESULT', rows => VARCHAR[], columns => VARCHAR[], filters => VARCHAR[], secret => VARCHAR])
Example:
SELECT state_id FROM sap_bics_begin('0D_NW_C01', id => 'q1');
sap_bics_columns()
Manipulate the column axis: add, set, or remove characteristics and key figures.
Signature:
sap_bics_columns(state_id VARCHAR, characteristic VARCHAR, [characteristic2 VARCHAR, ...])
Parameters:
| Parameter | Type | Description | Example |
|---|---|---|---|
state_id | VARCHAR (positional) | State produced by sap_bics_begin or a prior chain step | (chained) |
characteristic... | VARCHAR (positional varargs) | One or more characteristics / key figures to operate on | '0CALMONTH', '0SALES_AMOUNT' |
id | VARCHAR (named) | Override the state id passed in (rarely needed) | id => 'my_state' |
op | ENUM (named) | 'SET' (replace, default), 'ADD' (append), 'REMOVE' (drop) | op => 'ADD' |
return | ENUM (named) | 'DESCRIBE' (return plan, default) or 'RESULT' (execute now) | return => 'RESULT' |
secret | VARCHAR (named) | DuckDB secret name | secret => 'erp_prod' |
Example:
-- Add a characteristic to the column axis of state 'q1'
SELECT state_id FROM sap_bics_columns('q1', '0CALMONTH', op => 'ADD');
sap_bics_rows()
Manipulate the row axis. Same parameter shape as sap_bics_columns.
Signature:
sap_bics_rows(state_id VARCHAR, characteristic VARCHAR, [characteristic2 VARCHAR, ...])
Parameters (named): id, op ('SET' / 'ADD' / 'REMOVE'), return ('DESCRIBE' / 'RESULT'), secret.
Example:
SELECT state_id FROM sap_bics_rows('q1', '0D_NW_PROD', op => 'ADD');
sap_bics_filter()
Apply a filter on a specific characteristic.
Signature:
sap_bics_filter(state_id VARCHAR, characteristic VARCHAR, value VARCHAR, [value2 VARCHAR, ...])
Parameters:
| Parameter | Type | Description | Example |
|---|---|---|---|
state_id | VARCHAR (positional) | State produced by sap_bics_begin or a prior chain step | (chained) |
characteristic | VARCHAR (positional) | Characteristic to filter | '0CALMONTH' |
value... | VARCHAR (positional varargs) | One or more filter values | '202401', '202402' |
op | ENUM (named) | 'SET' / 'ADD' / 'REMOVE' | op => 'ADD' |
return | ENUM (named) | 'DESCRIBE' (default) / 'RESULT' | return => 'RESULT' |
secret | VARCHAR (named) | DuckDB secret name | secret => 'erp_prod' |
Example:
SELECT state_id FROM sap_bics_filter('q1', '0CALMONTH', '202401', op => 'SET');
sap_bics_result()
Execute the chained query and return the result rows.
Signature:
sap_bics_result(state_id VARCHAR)
Example:
-- Full sequence: open a state, shape it, then read the result by id
SELECT state_id FROM sap_bics_begin('0D_NW_C01', id => 'q1');
SELECT state_id FROM sap_bics_rows('q1', '0D_NW_PROD', op => 'SET');
SELECT state_id FROM sap_bics_filter('q1', '0CALMONTH', '202401', op => 'SET');
SELECT * FROM sap_bics_result('q1');
Intermediate Query Functions
sap_bics_show_hierarchies()
List available hierarchies.
Signature:
sap_bics_show_hierarchies()
Example:
SELECT * FROM sap_bics_show_hierarchies();
sap_bics_hierarchy()
Query hierarchy data — flat list (default) or as a recursive tree.
Signature:
sap_bics_hierarchy(hierarchy_name VARCHAR)
Parameters (all named):
| Parameter | Type | Description | Example |
|---|---|---|---|
version | VARCHAR | Hierarchy version | version => '01' |
date_to | VARCHAR | Valid-to date (time-dependent hierarchies) | date_to => '20261231' |
as_tree | BOOLEAN | Return as nested tree instead of flat list (default: false) | as_tree => true |
secret | VARCHAR | DuckDB secret name | secret => 'erp_prod' |
Example:
SELECT * FROM sap_bics_hierarchy('0MATERIAL_HIER', version => '01');
sap_bics_describe_infoobject()
Get InfoObject details.
Signature:
sap_bics_describe_infoobject(infoobject_name VARCHAR)
Example:
SELECT * FROM sap_bics_describe_infoobject('0MATERIAL');
Lineage Functions
End-to-end lineage from ERP source tables through DataSources, transformations, InfoProviders, and BEx queries. All three functions return system-wide data; filter by query, provider, or source in SQL.
sap_bics_lineage_edges()
Lineage as a flat edge list. Each row is one source-to-target edge across the BW data flow graph.
Signature:
sap_bics_lineage_edges()
Parameters (all named):
| Parameter | Type | Description | Example |
|---|---|---|---|
scope | VARCHAR | Optional scoping filter (object pattern) to limit the returned edges | scope => '0D_FC_NW*' |
secret | VARCHAR | DuckDB secret name | secret => 'erp_prod' |
Example:
-- All lineage edges
SELECT * FROM sap_bics_lineage_edges();
-- Filter edges related to a specific query
SELECT *
FROM sap_bics_lineage_edges()
WHERE tgt_name = '0D_FC_NW_C01_Q0008' OR src_name = '0D_FC_NW_C01_Q0008';
sap_bics_lineage_trace()
Trace lineage forward from a specific source object/field. Useful for impact analysis ("if this table changes, what downstream BEx queries are affected?").
Signature:
sap_bics_lineage_trace()
Parameters (all named):
| Parameter | Type | Description | Example |
|---|---|---|---|
source_object | VARCHAR | Source object name (e.g. ERP table) | source_object => 'VBAK' |
source_field | VARCHAR | Optional source field for field-level trace | source_field => 'NETWR' |
secret | VARCHAR | DuckDB secret name | secret => 'erp_prod' |
Example:
SELECT * FROM sap_bics_lineage_trace(source_object => 'VBAK');
SELECT * FROM sap_bics_lineage_trace(source_object => 'VBAK', source_field => 'NETWR');
sap_bics_lineage_graph_json()
Returns the full lineage graph as a JSON document. Use for visualization or export to graph tooling.
Signature:
sap_bics_lineage_graph_json()
Parameters (named): secret.
Example:
SELECT * FROM sap_bics_lineage_graph_json();
Metadata Functions
Each returns BW system metadata as a DuckDB table. Most are zero-positional; six take one VARCHAR positional. All accept an optional secret named parameter.
sap_bics_meta_providers()
InfoProvider metadata.
Signature:
sap_bics_meta_providers()
Named parameters:
| Parameter | Type | Description |
|---|---|---|
type | VARCHAR | Filter by provider type (e.g. 'CUBE', 'ODSO', 'MPRO') |
secret | VARCHAR | DuckDB secret name |
Example:
SELECT * FROM sap_bics_meta_providers();
SELECT * FROM sap_bics_meta_providers(type => 'CUBE');
sap_bics_meta_datasources()
DataSource metadata.
Signature:
sap_bics_meta_datasources()
Named parameters:
| Parameter | Type | Description |
|---|---|---|
appcomp | VARCHAR | Filter by application component |
secret | VARCHAR | DuckDB secret name |
Example:
SELECT * FROM sap_bics_meta_datasources(appcomp => 'FI');
sap_bics_meta_transformations()
Transformation metadata.
Signature:
sap_bics_meta_transformations()
Named parameters:
| Parameter | Type | Description |
|---|---|---|
active_only | BOOLEAN | If true, only active transformations |
secret | VARCHAR | DuckDB secret name |
Example:
SELECT * FROM sap_bics_meta_transformations(active_only => true);
sap_bics_meta_queries()
Query metadata.
Signature:
sap_bics_meta_queries()
Named parameters: secret (DuckDB secret name).
Example:
SELECT * FROM sap_bics_meta_queries();
sap_bics_meta_query_elements()
Query-element metadata for a specific query.
Signature:
sap_bics_meta_query_elements(query_name VARCHAR)
Named parameters: secret.
Example:
SELECT * FROM sap_bics_meta_query_elements('0D_FC_NW_C01_Q0008');
sap_bics_meta_query_stats()
Query runtime statistics.
Signature:
sap_bics_meta_query_stats()
Named parameters:
| Parameter | Type | Description |
|---|---|---|
query_name | VARCHAR | Filter to one query |
from_date | VARCHAR | Start of the time window (YYYYMMDD) |
to_date | VARCHAR | End of the time window (YYYYMMDD) |
secret | VARCHAR | DuckDB secret name |
Example:
SELECT * FROM sap_bics_meta_query_stats(
query_name => '0D_FC_NW_C01_Q0008',
from_date => '20260101',
to_date => '20260501'
);
sap_bics_meta_query_usage()
Query usage metadata for a specific query.
Signature:
sap_bics_meta_query_usage(query_name VARCHAR)
Named parameters: secret.
Example:
SELECT * FROM sap_bics_meta_query_usage('0D_FC_NW_C01_Q0008');
sap_bics_meta_provider_fields()
Field metadata for one InfoProvider.
Signature:
sap_bics_meta_provider_fields(provider_name VARCHAR)
Named parameters:
| Parameter | Type | Description |
|---|---|---|
provider_type | VARCHAR | Override the inferred provider type if needed |
secret | VARCHAR | DuckDB secret name |
Example:
SELECT * FROM sap_bics_meta_provider_fields('0D_NW_C01', provider_type => 'CUBE');
sap_bics_meta_datasource_fields()
Field metadata for one DataSource.
Signature:
sap_bics_meta_datasource_fields(datasource_name VARCHAR)
Named parameters: secret.
Example:
SELECT * FROM sap_bics_meta_datasource_fields('0FI_GL_4');
sap_bics_meta_transform_fields()
Field-level metadata for one transformation.
Signature:
sap_bics_meta_transform_fields(transformation_id VARCHAR)
Named parameters: secret.
Example:
SELECT * FROM sap_bics_meta_transform_fields('TRAN_ID_HERE');
sap_bics_meta_hcpr_components()
Composite provider component metadata.
Signature:
sap_bics_meta_hcpr_components(composite_provider VARCHAR)
Named parameters: secret.
Example:
SELECT * FROM sap_bics_meta_hcpr_components('0COPC1');
sap_bics_meta_hcpr_mapping()
Composite provider field mapping.
Signature:
sap_bics_meta_hcpr_mapping()
Named parameters:
| Parameter | Type | Description |
|---|---|---|
composite_provider | VARCHAR | Filter to one composite provider |
secret | VARCHAR | DuckDB secret name |
Example:
SELECT * FROM sap_bics_meta_hcpr_mapping(composite_provider => '0COPC1');
sap_bics_meta_infoobjects()
InfoObject metadata.
Signature:
sap_bics_meta_infoobjects()
Named parameters:
| Parameter | Type | Description |
|---|---|---|
iobjnm | VARCHAR | Filter by InfoObject name |
iobjtp | VARCHAR | Filter by InfoObject type ('CHA' characteristic, 'KYF' key figure, etc.) |
secret | VARCHAR | DuckDB secret name |
Example:
SELECT * FROM sap_bics_meta_infoobjects(iobjtp => 'KYF');
sap_bics_meta_objxref()
Object cross-reference metadata.
Signature:
sap_bics_meta_objxref()
Named parameters:
| Parameter | Type | Description |
|---|---|---|
tlogo | VARCHAR | Source object type code |
objnm | VARCHAR | Source object name |
tlogo_dep | VARCHAR | Dependent object type code |
secret | VARCHAR | DuckDB secret name |
Example:
SELECT * FROM sap_bics_meta_objxref(tlogo => 'CUBE', objnm => '0D_NW_C01');
ODP Functions
Basic ODP Functions
sap_odp_show_contexts()
List all available ODP contexts.
Signature:
sap_odp_show_contexts()
Example:
SELECT * FROM sap_odp_show_contexts();
ERPL exposes two distinct ODP extraction functions:
sap_odp_read_fullis one-shot — it opens a FULL cursor on the SAP side, streams the snapshot, then auto-closes the cursor when the scan completes. No state survives.sap_odp_read_deltatakes asubscriber_processidentifier. The first call with a new identifier performs SAP's auto-DELTAINIT (returns the full current snapshot AND registers a server-side delta pointer); subsequent calls with the same identifier resume from that pointer and return only the changes since the last call.
Close delta cursors when your pipeline finishes with PRAGMA sap_odp_close_delta_cursor (graceful — keeps the subscription resumable) or PRAGMA sap_odp_drop (hard reset — next call re-snapshots). Inspect active cursors with sap_odp_show_cursors.
sap_odp_show()
List data sources in a specific context.
Signature:
sap_odp_show(context_name VARCHAR, [search VARCHAR], [secret VARCHAR])
Parameters:
| Parameter | Type | Description | Example |
|---|---|---|---|
context_name | VARCHAR (positional) | ODP context | 'BW' |
search | VARCHAR | Glob pattern to filter data source names | search => '*COST*' |
secret | VARCHAR | DuckDB secret name | secret => 'erp_prod' |
Example:
SELECT * FROM sap_odp_show('BW', search => '*COST*');
sap_odp_describe()
Describe data source structure.
Signature:
sap_odp_describe(context_name VARCHAR, data_source VARCHAR, [secret VARCHAR])
Example:
SELECT * FROM sap_odp_describe('BW', 'VBAK$F');
sap_odp_preview()
Preview data without opening a delta cursor. Useful for one-off inspection.
Signature:
sap_odp_preview(context_name VARCHAR, data_source VARCHAR, [max_rows UINTEGER], [secret VARCHAR])
Example:
SELECT * FROM sap_odp_preview('BW', 'VBAK$F', max_rows => 100);
sap_odp_read_full()
Full one-shot extraction of an ODP source. Opens a FULL cursor on the SAP side, streams the snapshot, and auto-closes the cursor when the scan ends — no server-side state survives. For incremental extraction use sap_odp_read_delta.
Signature:
sap_odp_read_full(context_name VARCHAR, data_source VARCHAR, [threads UINTEGER], [columns LIST(VARCHAR)], [filters LIST(STRUCT)], [secret VARCHAR])
Parameters:
| Parameter | Type | Description | Example |
|---|---|---|---|
context_name | VARCHAR (positional) | ODP context name | 'BW' |
data_source | VARCHAR (positional) | Data source name | 'VBAK$F' |
threads | UINTEGER | Number of parallel RFC fetch threads (default: 5) | threads => 4 |
columns | LIST(VARCHAR) | Restrict to a subset of columns | columns => ['BUSINESSPARTNER'] |
filters | LIST(STRUCT) | Server-side select predicates (see ODP_SELECT_SIGN / ODP_SELECT_OP) | filters => [{...}] |
secret | VARCHAR | DuckDB secret name | secret => 'erp_prod' |
Example:
SELECT * FROM sap_odp_read_full('ABAP_CDS', 'Z_MY_CDS_VIEW');
-- Tune parallelism and project columns
SELECT * FROM sap_odp_read_full('BW', 'MY_DATASOURCE', threads => 4);
SELECT * FROM sap_odp_read_full('ABAP_CDS', 'SEPM_IBUPA$P', columns => ['BUSINESSPARTNER']);
sap_odp_read_delta()
Incremental delta extraction. The first call with a given subscriber_process performs SAP's auto-DELTAINIT — returns the full current snapshot AND registers a server-side delta pointer keyed by the subscriber tuple. Subsequent calls with the same subscriber_process resume from the previous pointer and return only the changes since then.
The delta cursor persists across calls. Close it explicitly with PRAGMA sap_odp_close_delta_cursor when your pipeline is done.
Signature:
sap_odp_read_delta(context_name VARCHAR, data_source VARCHAR, subscriber_process VARCHAR,
[threads UINTEGER], [columns LIST(VARCHAR)], [filters LIST(STRUCT)],
[recover BOOLEAN], [secret VARCHAR])
Parameters:
| Parameter | Type | Description | Example |
|---|---|---|---|
context_name | VARCHAR (positional) | ODP context name | 'BW' |
data_source | VARCHAR (positional) | Data source name | '0D_FC_C01$F' |
subscriber_process | VARCHAR (positional) | Stable identifier that keys the server-side delta pointer across calls. Pick a deterministic name per pipeline. | 'NIGHTLY_ETL' |
threads | UINTEGER | Number of parallel RFC fetch threads (default: 5) | threads => 4 |
columns | LIST(VARCHAR) | Restrict to a subset of columns | columns => ['BUSINESSPARTNER'] |
filters | LIST(STRUCT) | Server-side select predicates (same shape as sap_odp_read_full) | filters => [{...}] |
recover | BOOLEAN | Re-stream the last unconfirmed packet (I_EXTRACTION_MODE='R') without advancing the pointer. Useful after an interrupted fetch. | recover => true |
secret | VARCHAR | DuckDB secret name | secret => 'erp_prod' |
Do not run two sap_odp_read_delta calls with the same subscriber_process in parallel — they will race the server-side pointer.
Example:
-- First call: auto-DELTAINIT — full snapshot + delta-pointer registered under 'NIGHTLY_ETL'.
SELECT * FROM sap_odp_read_delta('BW', '0D_FC_C01$F', 'NIGHTLY_ETL');
-- Run the same call later: only the rows that changed since the previous call.
SELECT * FROM sap_odp_read_delta('BW', '0D_FC_C01$F', 'NIGHTLY_ETL');
-- Recover the last packet if a previous call was interrupted:
SELECT * FROM sap_odp_read_delta('BW', '0D_FC_C01$F', 'NIGHTLY_ETL', recover => true);
-- Release the cursor when the pipeline is done:
PRAGMA sap_odp_close_delta_cursor('BW', 'NIGHTLY_ETL', '0D_FC_C01$F');
Delta-capable sources are identified by supports_delta=true in sap_odp_describe. Not every CDS view is delta-capable — the underlying DDL must carry the @Analytics.dataExtraction.delta.byElement annotation; BW fact tables (*$F) are typically delta-capable.
sap_odp_get_last_modified()
Cheap probe that returns the most-recent modification timestamp of an ODP source without opening a cursor or fetching rows. Use it before a heavy sap_odp_read_delta call to skip pipelines when nothing has changed since the last run. Backed by RODPS_REPL_ODP_GET_LAST_MODIF.
Signature:
sap_odp_get_last_modified(context_name VARCHAR, data_source VARCHAR, [secret VARCHAR])
Returns: odp_name VARCHAR, last_modified DECIMAL(21,7) (UTC, format YYYYMMDDhhmmss.fffffff). Returns 0.0 for unknown ODP names — the SAP RFM does not surface "not found" as an error.
Example:
SELECT * FROM sap_odp_get_last_modified('ABAP_CDS', 'SEPM_IBUPA$P');
-- Bail out early if nothing changed
WITH probe AS (
SELECT last_modified FROM sap_odp_get_last_modified('BW', 'MY_SRC')
)
SELECT *
FROM sap_odp_read_delta('BW', 'MY_SRC', 'MY_PIPELINE')
WHERE (SELECT last_modified FROM probe) > 20260516000000.0;
Advanced ODP Functions
sap_odp_show_subscriptions()
View active subscriptions (cursors that hold ODP state).
Signature:
sap_odp_show_subscriptions([ERPL_ONLY BOOLEAN], [secret VARCHAR])
Parameters:
| Parameter | Type | Description | Example |
|---|---|---|---|
ERPL_ONLY | BOOLEAN | When true (default), show only subscriptions created by ERPL. When false, show all ODP subscribers. | ERPL_ONLY => FALSE |
secret | VARCHAR | DuckDB secret name | secret => 'erp_prod' |
Example:
SELECT * FROM sap_odp_show_subscriptions();
SELECT * FROM sap_odp_show_subscriptions(ERPL_ONLY => FALSE);
sap_odp_get_subscriptions()
List every subscription registered against a given ODP source — across all subscribers, not just ERPL. Useful for cross-team visibility ("who else is reading from this CDS view?") and for stuck-subscription forensics before a PRAGMA sap_odp_drop. Backed by RODPS_REPL_ODP_GET_SUBSCR.
Signature:
sap_odp_get_subscriptions(context_name VARCHAR, data_source VARCHAR,
[subscriber_name VARCHAR], [subscriber_process VARCHAR], [secret VARCHAR])
Parameters:
| Parameter | Type | Description | Example |
|---|---|---|---|
context_name | VARCHAR (positional) | ODP context ('ABAP_CDS', 'BW', 'SAPI') | 'ABAP_CDS' |
data_source | VARCHAR (positional) | ODP object name | 'SEPM_IBUPA$P' |
subscriber_name | VARCHAR | Filter by subscriber name | subscriber_name => 'ERPL' |
subscriber_process | VARCHAR | Filter by subscriber process | subscriber_process => 'NIGHTLY_ETL' |
secret | VARCHAR | DuckDB secret name | secret => 'erp_prod' |
Returns: subscriber_type, subscriber_name, subscriber_process, model_name, queue_name, subscription_id.
Example:
-- All subscribers on a source (across teams)
SELECT * FROM sap_odp_get_subscriptions('ABAP_CDS', 'SEPM_IBUPA$P');
-- Just my pipeline
SELECT * FROM sap_odp_get_subscriptions('BW', '0D_FC_C01$F', subscriber_name => 'ERPL');
sap_odp_show_cursors()
Inspect ODP cursors — the server-side state behind sap_odp_read_delta. Delta cursors created by sap_odp_read_delta appear here with is_delta_extension=true; their subscriber_proc column matches the subscriber_process argument you passed.
Returned columns: queue_name, subscriber_proc, subscriber_id, pointer, is_closed, is_delta_extension, request_date.
Signature:
sap_odp_show_cursors([erpl_only BOOLEAN], [subscriber_name VARCHAR], [context VARCHAR], [replication_mode ODP_REPLICATION_MODE], [secret VARCHAR])
Parameters:
| Parameter | Type | Description | Example |
|---|---|---|---|
erpl_only | BOOLEAN | Filter to cursors owned by the ERPL subscriber | erpl_only => TRUE |
subscriber_name | VARCHAR | Filter by subscriber name | subscriber_name => 'ERPL' |
context | VARCHAR | Filter by ODP context | context => 'ABAP_CDS' |
replication_mode | ODP_REPLICATION_MODE | Filter by cursor mode | replication_mode => 'FULL' |
secret | VARCHAR | DuckDB secret name | secret => 'erp_prod' |
Example:
SELECT * FROM sap_odp_show_cursors();
SELECT * FROM sap_odp_show_cursors(erpl_only => TRUE);
SELECT * FROM sap_odp_show_cursors(context => 'ABAP_CDS', replication_mode => 'FULL');
ODP Pragma Functions
PRAGMA sap_odp_close_delta_cursor()
Graceful counterpart to sap_odp_drop. Looks up the delta cursor for the given subscriber tuple and calls RODPS_REPL_ODP_CLOSE on its pointer. Idempotent: returns 'CLOSED' if a cursor existed (open or already closed) and 'NOT_FOUND' if no cursor of that name was found.
Prefer this over sap_odp_drop at the end of a delta pipeline — close leaves the subscription registered and resumable from its last pointer; drop wipes the subscription so the next call performs DELTAINIT again.
Signature:
PRAGMA sap_odp_close_delta_cursor(odp_context, subscriber_process, odp_name [, secret => ...]);
Parameters:
| Parameter | Description | Example |
|---|---|---|
odp_context | ODP context | 'BW' |
subscriber_process | Subscriber process identifier (the one passed to sap_odp_read_delta) | 'NIGHTLY_ETL' |
odp_name | Data source name | '0D_FC_C01$F' |
Optionally takes a named secret parameter to select the DuckDB secret.
Example:
PRAGMA sap_odp_close_delta_cursor('BW', 'NIGHTLY_ETL', '0D_FC_C01$F');
If a pipeline crashes mid-fetch the cursor may not be closeable via this pragma — fall back to sap_odp_drop to fully reset (accepting that the next call will re-snapshot via DELTAINIT).
PRAGMA sap_odp_drop()
Hard reset of an ODP subscription server-side (invokes RODPS_REPL_ODP_RESET). The next call to sap_odp_read_delta for the same subscriber tuple re-creates the subscription via auto-DELTAINIT and returns a fresh full snapshot.
Signature:
PRAGMA sap_odp_drop(odp_context, subscriber_name, subscriber_process, odp_name);
Parameters:
| Parameter | Description | Example |
|---|---|---|
odp_context | ODP context | 'ABAP_CDS' |
subscriber_name | Subscriber name as stored on SAP (ERPL default: 'ERPL') | 'ERPL' |
subscriber_process | Subscriber process identifier | 'erpl_subs_proc' |
odp_name | Data source name | 'Z_MY_CDS_VIEW' |
Optionally takes a named secret parameter to select the DuckDB secret.
Example:
PRAGMA sap_odp_drop('ABAP_CDS', 'ERPL', 'erpl_subs_proc', 'Z_MY_CDS_VIEW');
Custom Types
BICS Types
BICS_RETURN
Enum type for BICS return codes.
Values:
SUCCESSERRORWARNING
BICS_OPERATION
Enum type for BICS operations.
Values:
BEGINFILTERCOLUMNSRESULT
ODP Types
ODP_REPLICATION_MODE
Enum type for ODP replication modes.
Values:
FULL- Complete data loadDELTA- Only changed recordsRECOVER- Recovery mode
ODP_SELECT_SIGN
Enum type for ODP selection signs.
Values:
I- IncludeE- Exclude
ODP_SELECT_OP
Enum type for ODP selection operations.
Values:
EQ- EqualNE- Not equalGT- Greater thanLT- Less thanGE- Greater than or equalLE- Less than or equal
Function Categories
By Complexity Level
Beginner Functions:
sap_read_table()sap_rfc_invoke()sap_bics_show()sap_bics_begin()sap_bics_result()sap_odp_show_contexts()sap_odp_read_full()
Intermediate Functions:
sap_rfc_describe_function()sap_describe_fields()sap_bics_describe()sap_bics_filter()sap_bics_hierarchy()sap_odp_describe()sap_odp_preview()
Advanced Functions:
sap_rfc_authorizations()sap_bics_lineage_edges(),sap_bics_lineage_trace(),sap_bics_lineage_graph_json()sap_bics_meta_*()(all metadata functions)sap_odp_read_delta()sap_odp_get_last_modified()sap_odp_show_subscriptions(),sap_odp_get_subscriptions()sap_odp_show_cursors()PRAGMA sap_odp_close_delta_cursor(),PRAGMA sap_odp_drop()
By Protocol
RFC Functions (8):
sap_read_table()sap_rfc_invoke()sap_rfc_describe_function()sap_describe_fields()sap_rfc_authorizations()sap_rfc_show_function()sap_rfc_show_groups()sap_show_tables()
BICS Functions (25+):
- Basic query functions (7)
- Metadata functions (15)
- Lineage functions (3)
ODP Functions (12):
sap_odp_show_contexts()sap_odp_show()sap_odp_describe()sap_odp_preview()sap_odp_read_full()sap_odp_read_delta()sap_odp_get_last_modified()sap_odp_show_subscriptions()sap_odp_get_subscriptions()sap_odp_show_cursors()PRAGMA sap_odp_close_delta_cursor()PRAGMA sap_odp_drop()
Common Patterns
Basic Query Pattern (BICS)
-- Standard BICS query pattern: open a state by id, shape it, read by the same id
SELECT state_id FROM sap_bics_begin('CUBE_NAME', id => 'q1');
SELECT state_id FROM sap_bics_rows('q1', 'ROW_CHARACTERISTIC', op => 'SET');
SELECT state_id FROM sap_bics_filter('q1', 'FILTER_FIELD', 'FILTER_VALUE', op => 'SET');
SELECT * FROM sap_bics_result('q1');
Delta Replication Pattern (ODP)
-- Standard ODP delta pattern: one function, stable subscriber_process.
-- 1. First call: auto-DELTAINIT — full snapshot + delta-pointer registered.
SELECT * FROM sap_odp_read_delta('BW', 'VBAK$F', 'NIGHTLY_ETL');
-- 2. Subsequent calls return only changes since the last call.
SELECT * FROM sap_odp_read_delta('BW', 'VBAK$F', 'NIGHTLY_ETL');
-- 3. Release the cursor when the pipeline is done.
PRAGMA sap_odp_close_delta_cursor('BW', 'NIGHTLY_ETL', 'VBAK$F');
Function Discovery Pattern (RFC)
-- Discover and analyze functions
SELECT * FROM sap_rfc_show_function(FUNCNAME => 'BAPI*');
SELECT * FROM sap_rfc_describe_function('FUNCTION_NAME');
Error Handling
Common Error Patterns
Function Not Found:
-- Check if function exists
SELECT * FROM sap_rfc_show_function(FUNCNAME => 'FUNCTION_NAME');
Table Not Found:
-- Check if table exists
SELECT * FROM sap_show_tables()
WHERE table_name = 'TABLE_NAME';
Subscription Errors:
-- List the registered subscriptions (cols: queue_name, subscriber_type, subscriber_name, subscriber_proc)
SELECT * FROM sap_odp_show_subscriptions();
Performance Tips
Optimization Strategies
Use LIMIT for large datasets:
SELECT * FROM sap_read_table('KNA1', MAX_ROWS => 1000);
Filter early in BICS queries:
SELECT state_id FROM sap_bics_begin('CUBE', id => 'q1');
SELECT state_id FROM sap_bics_filter('q1', 'FILTER_FIELD', 'VALUE', op => 'SET');
SELECT * FROM sap_bics_result('q1');
Use DELTA mode for ODP:
SELECT * FROM sap_odp_read_full(
'BW', 'VBAK$F'
);
Next Steps
🚀 Ready for More?
- RFC Protocol Guide - Complete RFC documentation
- BICS Protocol Guide - Complete BICS documentation
- ODP Protocol Guide - Complete ODP documentation
🔧 Advanced Topics
- BICS Lineage Tracking - Advanced lineage analysis
- ODP Subscription Management - Advanced subscription patterns
- RFC Metadata Extraction - Advanced metadata analysis
💡 Examples
- ERPL Examples - Real-world examples
- Real-World Use Cases - Complete scenarios
Need help? Check our troubleshooting guide or browse more examples.