Skip to main content

BICS Protocol Deep Dive

This guide covers the BICS (BI Consumer Services) interface in ERPL: how to discover InfoProviders and BEx queries, build OLAP cross-tabs, fetch result sets, and trace end-to-end lineage from source tables to BEx queries — all from SQL in DuckDB.

What is BICS?

BICS (BI Consumer Services) is the SAP interface that tools like SAP Analysis for Office use to consume SAP Business Warehouse (BW) data. ERPL talks to BICS through the SAP NetWeaver RFC SDK — it calls the BICS_PROV_* RFC function modules to open a query, manipulate its OLAP state, and read result sets. It is not a separate HTTP/web protocol: there is no BICS port, no XML payload, and no SAML. Connectivity and authentication are exactly the same as for the RFC protocol — a DuckDB secret of type sap_rfc.

How it works

ERPL uses two RFC paths:

  • Query execution drives an OLAP query through the BICS provider modules (BICS_CONS_CREATE_DATA_AREA, BICS_PROV_OPEN, BICS_PROV_GET_INITIAL_STATE, BICS_PROV_SET_STATE, BICS_PROV_GET_RESULT_SET, BICS_PROV_CLOSE). These power sap_bics_begin / rows / columns / filter / result.
  • Metadata & lineage read BW dictionary tables via RFC_READ_TABLE (e.g. RSRREPDIR, RSZCOMPDIR, RSDCUBE, RSTRAN, ROOSFIELD, RSHIEDIR, RSOOBJXREF). These power the sap_bics_show*, sap_bics_meta_*, and sap_bics_lineage_* functions.

Connecting

Every BICS function uses a DuckDB secret of type sap_rfc — the same secret used by the RFC extension. Create one once per session (the example below uses the ABAP Platform Trial defaults):

CREATE SECRET abap_trial (
TYPE sap_rfc,
ASHOST 'localhost',
SYSNR '00',
CLIENT '001',
USER 'DEVELOPER',
PASSWD 'ABAPtr2023#00',
LANG 'EN'
);

If a single unnamed/default secret exists, ERPL uses it automatically. When you keep several secrets, pass the one you want with the secret named parameter that every BICS function accepts, e.g. sap_bics_show_cubes(secret => 'abap_trial'). For encrypted connections, add the SNC parameters (SNC_QOP, SNC_MYNAME, SNC_PARTNERNAME, SNC_LIB) to the secret — see the security guide. All examples below assume a usable secret exists and omit the parameter for brevity.

Discovering objects

-- InfoProviders (cubes, ADSOs, CompositeProviders, …)
SELECT * FROM sap_bics_show(obj_type => 'INFOPROVIDER');

-- Just cubes, or just queries (dedicated helpers with search)
SELECT * FROM sap_bics_show_cubes();
SELECT * FROM sap_bics_show_queries();

-- Search by technical name or text
SELECT technical_name, text, type
FROM sap_bics_show_queries(search => '0D_FC_NW_C01_Q0011', search_in_key => true);

sap_bics_show(obj_type => ...) accepts INFOPROVIDER, CUBE, QUERY, or INFOAREA, and returns technical_name, text, type, cube_name, is_folder, last_changed, last_changed_by, and level.

Querying a cube (OLAP cross-tabs)

BICS queries are stateful. You open a query state, identify it with an id, mutate that state with separate calls, and finally read the result set by the same id. Unlike ordinary table functions, the BICS query functions are not nested inside one another — they are chained by passing the state id string from one call to the next.

-- 1. Open a query state on the cube and give it an id
SELECT state_id, state_version
FROM sap_bics_begin('0D_NW_C01', id => 'q1');

-- 2. Place characteristics on the ROWS axis (the cross-tab "drilldown")
SELECT state_id, state_version
FROM sap_bics_rows('q1', '0D_NW_PROD', op => 'SET');

-- 3. Place a characteristic on the COLUMNS axis
SELECT state_id, state_version
FROM sap_bics_columns('q1', '0CALMONTH', op => 'SET');

-- 4. Read the result set for this state
SELECT * FROM sap_bics_result('q1');

Axes, not column projection

sap_bics_rows and sap_bics_columns are OLAP axes, not a SQL column projection. They decide which characteristics are drilled into the rows vs. the columns of the cross-tab — the same as dragging a characteristic onto Rows or Columns in Analysis for Office. The key figures of the cube are aggregated for whatever drilldown you choose. The op parameter controls how each call changes the axis:

opEffect
SETReplace the axis with exactly these characteristics
ADDAppend characteristics to the existing axis
REMOVERemove the named characteristics from the axis

Each mutating call returns the updated state_id and an incrementing state_version, so you can confirm the state advanced. The columns of sap_bics_result are the cube's own characteristic and key-figure technical names — for 0D_NW_C01 that includes "0D_NW_PROD", "0D_NW_NETV" (net value), "0D_NW_QUANT" (quantity), and so on. Because these names start with a digit, quote them with double quotes in SQL.

Fetch results in one call

begin, rows, columns, and filter accept return => 'RESULT' to return the result set directly instead of the default state description (return => 'DESCRIBE'). For example, SELECT * FROM sap_bics_rows('q1', '0D_NW_PROD', op => 'SET', return => 'RESULT') applies the axis change and hands back data in a single statement.

Filtering members

sap_bics_filter restricts a characteristic to one or more member values (a background filter / "slice"). Pass the characteristic, then one or more member keys as positional arguments:

SELECT state_id FROM sap_bics_begin('0D_NW_C01', id => 'f1');
SELECT state_id FROM sap_bics_rows('f1', '0D_NW_PROD', op => 'SET');

-- Single-member filter: Division = 7 ("High Tech")
SELECT state_id FROM sap_bics_filter('f1', '0D_NW_DIV', '7', op => 'SET');

SELECT * FROM sap_bics_result('f1');
-- Multi-member filter: pass several values to one filter() call
SELECT state_id FROM sap_bics_filter('f1', '0CALMONTH', '202401', '202402', '202403',
op => 'SET');

-- op => 'ADD' / 'REMOVE' adjust an existing selection instead of replacing it
SELECT state_id FROM sap_bics_filter('f1', '0D_NW_DIV', '15', op => 'ADD');

You can also seed a filter at begin time with the filters named parameter; ad-hoc sap_bics_filter calls remain the flexible way to slice an open state.

Hierarchies

-- List hierarchies available for an InfoObject
SELECT * FROM sap_bics_show_hierarchies(info_object => '0D_NW_PROD');

-- Read a hierarchy as a flat node list
SELECT * FROM sap_bics_hierarchy('0D_NW_PROD_HIER');

-- Pin a version / key date and return a recursive tree
SELECT * FROM sap_bics_hierarchy('0D_NW_PROD_HIER', date_to => '20151231', as_tree => true);

sap_bics_hierarchy returns node_id, parent_id, child_id, next_id, info_object, node_name, node_value, date_from, date_to, level, and path — enough to rebuild the tree yourself or filter by level.

Describing structures

-- Describe a cube: characteristics + key figures
SELECT technical_name, text FROM sap_bics_describe('0D_NW_C01');

-- Describe a BEx query on a cube (adds its variables)
SELECT technical_name, text, variables
FROM sap_bics_describe('0D_NW_C01', '0D_FC_NW_C01_Q0011');

-- Describe an open query state by its id
SELECT * FROM sap_bics_describe(id => 'q1');

sap_bics_describe returns technical_name, text, and the characteristics / keyfigures structs (plus variables for the query overload). For attributes of a single InfoObject:

SELECT info_object, data_type, length, decimals
FROM sap_bics_describe_infoobject('0D_NW_PROD');

sap_bics_describe_infoobject returns info_object, data_type, conv_exit, output_length, length, and decimals.

Presentation properties (AO-style)

sap_bics_set_char_prop toggles per-characteristic display properties that match the radio controls in SAP Analysis for Office's Properties panel. The mutation persists in the BICS state and is honoured by the next sap_bics_result call.

-- Build a 1D cross-tab on country
SELECT * FROM sap_bics_begin('0D_NW_C01', id => 'q1');
SELECT * FROM sap_bics_rows('q1', '0D_NW_CNTRY', op => 'SET');

-- Display member texts instead of keys ("Germany" vs "DE")
SELECT * FROM sap_bics_set_char_prop('q1', '0D_NW_CNTRY', 'DISPLAY', 'TEXT');

-- Show both key and text concatenated
SELECT * FROM sap_bics_set_char_prop('q1', '0D_NW_CNTRY', 'DISPLAY', 'BOTH');

-- Sort by member descending
SELECT * FROM sap_bics_set_char_prop('q1', '0D_NW_CNTRY', 'SORT', 'DESC');

-- Fetch with the new presentation
SELECT * FROM sap_bics_result('q1');
propAllowed valueMaps to BICS state field
DISPLAYKEY | TEXT | BOTHRESULT_SET_PRESENTATION bitflag (KEY=4, TEXT=32)
TOTALSSHOW | HIDERESULT_VISIBILITY ('A' / 'N')
SORTASC | DESC | NONERESULT_SET_SORTING.DIRECTION ('A' / 'D' / '')

The DESCRIBE payload of state_rows, state_columns, and state_free carries {display, totals, sort} so clients can read the current values without an extra round-trip.

Grand-total row visibility

BICS does not expose a state field for the SUMME / "Overall Result" grand-total row. TOTALS='HIDE' is persisted to per-characteristic RESULT_VISIBILITY but the server still returns the grand-total row in sap_bics_result. Clients that want AO's "Hide Result" behaviour can filter the row whose row-characteristic value matches SUMME / Overall Result / localised variants — that's what AO itself does.

Interactive: bics-tui

bics-tui (in bics/examples/tui/) is a terminal UI that wraps every BICS function above into a Textual app modelled on SAP Analysis for Office: log on, browse cubes / queries, build a cross-tab by moving characteristics between Rows / Columns / Background Filter, filter members, and toggle Display / Sort / Totals for a focused characteristic or Scaling Factor / Decimal Places for a focused key figure — all from a context-sensitive Properties panel on the right. Every server-side action is mirrored into an always-on SQL recorder, so the resulting script replays cleanly in a vanilla DuckDB shell.

Logon

The logon screen pre-fills the standard ABAP Platform Trial credentials — overwrite for your own system. The fields are wired straight into a DuckDB CREATE SECRET of type sap_rfc.

bics-tui Logon screen

Analysis screen

Three-column layout: cross-tab grid on the left, design panel in the middle (Data Source / Columns / Rows / Background Filter / Key Figures), context-sensitive Properties panel on the right. Hotkeys are shown next to each section header.

bics-tui Analysis screen with 0D_NW_PROD on Rows and 0D_NW_CNTRY on Background Filter

Properties — Characteristic on axis

Focus a characteristic in any axis list and the Properties panel switches to three radio groups: Display (Key / Text / Both), Totals (Show / Hide / Conditional), Sort (None / Asc / Desc). Display and Sort round-trip via sap_bics_set_char_prop; Totals Hide is applied client-side (BICS does not expose a state field for the grand-total row).

bics-tui Properties panel for a focused characteristic

Properties — Key figure

Focus a key figure and the panel switches to Scaling Factor and Decimal Places. Both are client-side numeric formatting — BICS state carries no field for them. The KF columns in the cross-tab re-format live as you change the controls.

bics-tui Properties panel for a focused key figure

Run it

GEN=ninja make release          # from erpl monorepo root
cd bics/examples/tui
uv sync
LD_LIBRARY_PATH=/path/to/erpl/nwrfcsdk/linux/lib uv run python -m bics_tui

The screenshots above are regenerated headlessly via scripts/capture_screens.py (Textual's export_screenshot → SVG → PNG with a mock session for layout-only capture; no SAP connection needed).

Lineage Tracking (for SAP BW experts)

For BI Administrators

This section covers lineage tracking from ERP tables through DataSources, InfoProviders, and BEx queries. It reads the BW dictionary tables via RFC_READ_TABLE, so it does not need an open query state.

Complete lineage as edges

sap_bics_lineage_edges() returns the BW data flow as a flat edge list spanning ERP source tables → DataSources → transformations → InfoProviders → BEx queries. Each row is one source-to-target edge with these columns:

ColumnDescription
edge_typeEdge category (e.g. transformation, query-element)
src_kind, src_name, src_fieldSource object kind, name, and optional field
tgt_kind, tgt_name, tgt_fieldTarget object kind, name, and optional field

Use cases:

  • Impact analysis — what happens if a source table changes?
  • Data governance — track data flow and transformations
  • Documentation — automatic lineage documentation
  • Compliance — audit data lineage for regulations
-- All edges in the system
SELECT * FROM sap_bics_lineage_edges();

-- Edges related to a specific BEx query — filter in SQL
SELECT *
FROM sap_bics_lineage_edges()
WHERE tgt_name = '0D_FC_NW_C01_Q0008' OR src_name = '0D_FC_NW_C01_Q0008'
ORDER BY src_kind, tgt_kind;

-- Scope the underlying RFC reads to one object (faster on large landscapes)
SELECT * FROM sap_bics_lineage_edges(scope => '0D_NW_C01');

Forward trace from a source

sap_bics_lineage_trace() walks the graph forward from a specific source object/field — perfect for "if I change this object, what downstream BW objects break?". The result includes a hop column and a path column (the chain of objects walked) so you can see the full downstream blast radius.

-- Everything downstream of an InfoProvider
SELECT * FROM sap_bics_lineage_trace(source_object => '0D_NW_C01')
ORDER BY hop;

-- Field-level trace
SELECT * FROM sap_bics_lineage_trace(
source_object => '0D_NW_C01',
source_field => '0D_NW_NETV'
);

Lineage of a single query

sap_bics_query_lineage() resolves the lineage rooted at one BEx query:

SELECT * FROM sap_bics_query_lineage('0D_FC_NW_C01_Q0011');

Lineage as a JSON graph

sap_bics_lineage_graph_json() returns the full lineage as a JSON document, suitable for visualization libraries (D3, Cytoscape, etc.) or export to external graph tools.

SELECT * FROM sap_bics_lineage_graph_json();

Metadata mining

The sap_bics_meta_* functions expose the BW dictionary tables directly.

Several metadata functions require an argument

To avoid scanning an entire BW landscape by accident, some functions refuse a bare no-argument call and return a message telling you which parameter to supply. The functions that require at least one argument are sap_bics_meta_providers (type), sap_bics_meta_datasources (appcomp), sap_bics_meta_transformations (active_only), sap_bics_meta_query_stats (one of query_name / from_date / to_date), sap_bics_meta_objxref (tlogo / objnm / tlogo_dep), and sap_bics_meta_hcpr_mapping (composite_provider). The field-level helpers below take the object name positionally.

-- InfoProvider metadata (type is required: CUBE | ADSO | HCPR | ODSO | ODSVIEW)
SELECT * FROM sap_bics_meta_providers(type => 'CUBE');

-- DataSource metadata (application component is required)
SELECT * FROM sap_bics_meta_datasources(appcomp => 'NODE0000');

-- Transformation metadata
SELECT * FROM sap_bics_meta_transformations(active_only => true);

-- Query directory (no argument required)
SELECT * FROM sap_bics_meta_queries();

-- Query usage / runtime statistics
SELECT * FROM sap_bics_meta_query_usage('0D_FC_NW_C01_Q0011');
SELECT * FROM sap_bics_meta_query_stats(query_name => '0D_FC_NW_C01_Q0011');

-- Query elements (structures, selections, formulas)
SELECT * FROM sap_bics_meta_query_elements('0D_FC_NW_C01_Q0011');

Field-level & cross-reference metadata

-- DataSource fields (DataSource name is positional)
SELECT * FROM sap_bics_meta_datasource_fields('0FI_GL_4');

-- InfoProvider fields (provider name is positional; pass provider_type to disambiguate)
SELECT * FROM sap_bics_meta_provider_fields('0D_NW_C01', provider_type => 'CUBE');

-- Transformation field mappings (transformation id is positional)
SELECT * FROM sap_bics_meta_transform_fields('<transformation-id>');

-- CompositeProvider (HCPR) components and their part-provider mapping
SELECT * FROM sap_bics_meta_hcpr_components('<composite-provider>');
SELECT * FROM sap_bics_meta_hcpr_mapping(composite_provider => '<composite-provider>');

-- InfoObject catalog (no argument required; filter with iobjnm/iobjtp)
SELECT * FROM sap_bics_meta_infoobjects(iobjnm => '0D_NW_PROD');

-- Object cross-reference (which objects reference which)
SELECT * FROM sap_bics_meta_objxref(tlogo => 'CUBE', objnm => '0D_NW_C01');

The exact rows these return depend on what is configured in your BW system; the demo objects above are populated on the ABAP Platform Trial, while DataSources and transformations are typically richer on a productive landscape.

HCPR

HCPR is the SAP TLOGO type for a HANA CompositeProvider, not a "hierarchy change pointer". The *_hcpr_* helpers describe CompositeProviders and the part-providers they union/join.

Real-world examples

Net value by product

Build the state with separate statements, then query the result. Each call returns the state_id, so you can ignore those rows and read the data from sap_bics_result:

SELECT state_id FROM sap_bics_begin('0D_NW_C01', id => 'rep1');
SELECT state_id FROM sap_bics_rows('rep1', '0D_NW_PROD', op => 'SET');
SELECT state_id FROM sap_bics_filter('rep1', '0D_NW_DIV', '7', op => 'SET');

SELECT
"0D_NW_PROD" AS product,
"0D_NW_NETV" AS net_value,
"0D_NW_QUANT" AS quantity
FROM sap_bics_result('rep1')
ORDER BY net_value DESC
LIMIT 20;

Combine BW data with ERP master data

Once the rep1 state above exists, its result set joins to ERP master data read over RFC:

-- BW net value per product, joined to ERP material master via RFC
WITH bw_sales AS (
SELECT "0D_NW_PROD" AS product, "0D_NW_NETV" AS net_value
FROM sap_bics_result('rep1') -- the state built above
),
erp_materials AS (
SELECT MATNR AS material, MTART AS material_type, MEINS AS base_unit
FROM sap_read_table('MARA', MAX_ROWS => 10000)
)
SELECT
b.product, m.material_type, m.base_unit, b.net_value,
CASE
WHEN b.net_value > 1e9 THEN 'High Value'
WHEN b.net_value > 1e8 THEN 'Medium Value'
ELSE 'Low Value'
END AS value_category
FROM bw_sales b
LEFT JOIN erp_materials m ON b.product = m.material
ORDER BY b.net_value DESC;

Performance & good practice

  • Slice early with filters and axes. Restricting members with sap_bics_filter and limiting the drilldown with sap_bics_rows / sap_bics_columns is what reduces the result set — there is no SQL-style column projection at the BICS layer.
  • Reuse the query state. begin opens a server-side state; keep mutating the same id rather than re-opening for each variation. state_version confirms each change landed.
  • Scope metadata reads. Pass scope/object arguments to the lineage/meta functions so the underlying RFC_READ_TABLE calls stay bounded on large landscapes.
  • Reuse connections. ERPL caches RFC connections per secret; running several BICS statements in one DuckDB session avoids repeated logons.

Troubleshooting

Query or cube not found

-- Names are case-sensitive; search the catalog
SELECT * FROM sap_bics_show_queries(search => 'Q0011');
SELECT * FROM sap_bics_show(obj_type => 'CUBE', search => '0D_NW_C01');

Empty result set

-- Re-check filter member keys (use keys, not display texts)
SELECT * FROM sap_bics_describe_infoobject('0D_NW_DIV');

-- Drop filters to confirm the cube has data at all
SELECT * FROM sap_bics_begin('0D_NW_C01', id => 'probe', return => 'RESULT');

Metadata function errors with "requires named parameters" This is the guardrail described above — supply the named argument it asks for (e.g. sap_bics_meta_providers(type => 'CUBE')).

Enable tracing

ERPL has a built-in trace facility. Enable it to see the exact RFC calls and payloads:

SET erpl_trace_enabled = TRUE;
SET erpl_trace_level = 'DEBUG'; -- TRACE | DEBUG | INFO | WARN | ERROR
SET erpl_trace_output = 'console'; -- console | file | both

For SAP BW experts: the BICS interface in detail

BICS in ERPL is an RFC interface, not a network protocol of its own: it drives the same BICS_PROV_* consumer modules that SAP Analysis for Office uses, over the NetWeaver RFC SDK with your sap_rfc secret. Expand the deep dive below for the wire-level mechanics.

BICS protocol deep dive — handle lifecycle, state model & versioning, result-set decoding, variables, metadata, security

The handle lifecycle

A BICS session juggles three server-side handles, each a 4-character token:

  1. Application handleBICS_CONS_CREATE_DATA_AREA creates the consumer data area and returns E_APPLICATION_HANDLE. This is the umbrella context for the session.
  2. Data-provider handleBICS_PROV_OPEN opens the InfoProvider (or BEx query) and returns E_DATA_PROVIDER_HANDLE plus E_VARIABLE_CONTAINER_HANDLE. ERPL opens with I_STATE_VARIABLE_MODE = 'U' and I_OPTIMIZE_INIT_VERSION = 5. A variable-container handle of 0000 is normal for queries that declare no BEx variables — it is not an error.
  3. Initial stateBICS_PROV_GET_INITIAL_STATE (with I_RETRIEVE_SEL_SPACE_OPT = 'X') returns the complete default OLAP state: the characteristic catalog, the rows/columns/free axis assignments, the selection (filter) state, and the per-characteristic presentation state.

At session end BICS_PROV_CLOSE is called best-effort for the variable-container, data-provider, and application handles in turn (failures are swallowed).

The full mapping from SQL function to RFC module:

ERPL stepRFC function module(s)Key parameters
sap_bics_beginBICS_CONS_CREATE_DATA_AREABICS_PROV_OPENBICS_PROV_GET_INITIAL_STATEI_DATA_PROVIDER_INFO_PROVIDER, I_DATA_PROVIDER_NAME (query)
sap_bics_rows / columns / filter / set_char_propBICS_PROV_SET_STATEI_S_ROWS, I_S_COLUMNS, I_S_FREE, I_TH_CHARACTERISTICS, I_TSX_SELECTION_STATE, I_VALIDATE = 'X'
sap_bics_resultBICS_PROV_GET_RESULT_SETI_MAX_DATA_CELLS = 1000000
sap_bics_describe (query)BICS_PROV_GET_DESIGN_TIME_INFO, BICS_PROV_VAR_GET_VARIABLESI_VARIABLE_CONTAINER_HANDLE
(session end)BICS_PROV_CLOSEone call per handle

The state model and state_version

Although the OLAP state physically lives on the BW server between SET_STATE calls, ERPL also persists each state snapshot client-side in a DuckDB table keyed by (id, version). Every mutation — placing a characteristic on an axis, adding a filter, or changing a display/sort/ totals property — saves a new snapshot and increments state_version. That is why a typical begin → rows → columns → filter sequence returns versions 1 → 2 → 3 → 4. Because snapshots are immutable and addressed by id, several independent query states can coexist in one DuckDB session, and you can branch a state by re-using an earlier id.

BICS_PROV_SET_STATE carries the whole OLAP state, not a delta. The notable sub-structures:

  • AxesI_S_ROWS / I_S_COLUMNS / I_S_FREE and their characteristic-reference tables describe which characteristics sit on the rows axis, the columns axis, and the free (background-filter) axis. op => 'SET' clears the target axis first (key figures are kept on the column axis), 'ADD' appends, and 'REMOVE' moves a characteristic to the free axis.
  • Selection state (I_TSX_SELECTION_STATE) — one entry per filtered characteristic, each holding a SELECTION list of {SIGN ('I'/'E'), OPERATOR ('EQ'/'BT'/…), LOW, HIGH} rows. This is the BICS equivalent of an ABAP range table.
  • Per-characteristic presentation (I_TH_CHARACTERISTICS) — the fields sap_bics_set_char_prop manipulates: RESULT_SET_PRESENTATION (a bitflag, KEY=4, TEXT=32, BOTH=36), RESULT_VISIBILITY ('A' show / 'N' hide / 'C' conditional for totals), and RESULT_SET_SORTING.DIRECTION ('A' / 'D' / '').

Decoding the result set

BICS_PROV_GET_RESULT_SET returns a multidimensional cross-tab, not a flat table, which ERPL flattens:

  • Members & presentationE_T_MEMBER lists the axis members; each points into a E_T_MEMBER_PRESENTATION table via a PRESENTATION_INDEX_FROM/TO range. The display mode decides which presentation entry is used: KEY takes the key, TEXT the text, BOTH concatenates them.
  • Row / column tuplesE_T_ROWS and E_T_COLUMNS give the member references per axis position, including a LEVEL field that becomes the synthetic "<char>_HIER_LEVEL" integer column you see for hierarchy drilldowns.
  • Data cellsE_T_DATA_CELLS is a sparse {ROW, COLUMN, VALUE} list (cells equal to zero are omitted by the server). ERPL initialises every cell to NULL and fills only the returned ones, so an absent cell is NULL, not 0.0. Cell VALUEs are always DOUBLE; axis member columns are always VARCHAR.
  • Grand total — the "Overall Result" / SUMME row is an ordinary row in E_T_ROWS whose member key is the literal SUMME; it is not a separate structure (see the note under Presentation properties above for hiding it).
  • Cell budget — ERPL requests up to I_MAX_DATA_CELLS = 1,000,000 cells per fetch. A drilldown that would exceed that must be narrowed with filters or fewer axis characteristics.

Variables

BICS_PROV_VAR_GET_VARIABLES retrieves a query's variable definitions (used by sap_bics_describe), but variable filling is not implemented — there is no BICS_PROV_VAR_SET_VARIABLES call. Queries that declare variables execute with their default/empty values; restrict the result with sap_bics_filter instead.

Metadata and lineage

Discovery, sap_bics_meta_*, and sap_bics_lineage_* do not open a query. They read BW dictionary tables through RFC_READ_TABLE — among them RSRREPDIR and RSZCOMPDIR (queries), RSDCUBE (InfoCubes), RSTRAN (transformations), ROOSFIELD (DataSource fields), RSHIEDIR (hierarchies), and RSOOBJXREF (cross-references). Hierarchy nodes come from RSNDI_SHIE_STRUCTURE_GET3; single-InfoObject attributes from BAPI_IOBJ_GETDETAIL.

Security

Because BICS rides on RFC, its security model is the RFC model:

  1. Authentication — the sap_rfc secret (user/password) or SNC for certificate-based, encrypted logon. There is no Basic Auth or SAML at the BICS layer.
  2. Authorization — standard BW analysis authorizations (RSEC) govern which InfoProviders, queries, and characteristic values a user may read.
  3. Transport security — use SNC (or an SSH tunnel) to encrypt the RFC connection on untrusted networks.
  4. Auditing — SAP-side security audit log (SM19/SM20) records the RFC logons.

Next steps

🚀 Ready for More?

🔧 Advanced Topics

💡 Examples


Need help? Check our troubleshooting guide or browse more examples.