sap_hana
Reads rows from a SAP HANA table.
Reads rows from a SAP HANA table. Supports five modes:
-
bulk: reads all rows once then the input terminates (wrap it inread_untilwithrestart_input: truefor periodic re-reads). -
incrementing: polls for rows whereincrementing_columnexceeds the last seen value, emitting only net-new rows. Values from anIDENTITYcolumn or a sequence are assigned when a row is inserted, not when it commits: with concurrent writers a lower value can commit after a higher one has been read, and that row is never emitted. Usetimestamp+incrementingwith atimestamp_delaylonger than your longest write transaction when the table has concurrent writers. -
query: executes a user-supplied SQL statement and emits one message per result row. -
timestamp: polls for rows wheretimestamp_columnfalls within(last_hwm, database_now - timestamp_delay]. The bound is read from the database clock (seetimestamp_clock) and the delay absorbs commit lag. The HWM advances to the window bound once the window is fully consumed. Mid-window, a batch checkpoints the timestamp of its last row when the next row has a later one, so a restart re-reads only the rows of the timestamp that was in progress (rows sharing a timestamp cannot be split). -
timestamp+incrementing: liketimestampbut orders by(timestamp_column, incrementing_column)and resumes after the exact(timestamp, incrementing)pair of the last delivered row, so rows sharing a timestamp are neither duplicated nor missed and a restart mid-window continues from the last acknowledged batch rather than the window start.
Metadata
Messages produced in bulk, incrementing, timestamp, and timestamp+incrementing modes carry the following metadata fields (query mode attaches none):
-
table_name: The HANA table name. -
database_schema: The configuredschema_name. Only present whenschema_nameis set. -
schema: Avro-compatible schema derived fromSYS.TABLE_COLUMNS, suitable for use withschema_registry_encode. Column additions are detected automatically without a pipeline restart. Only present whenschema_nameis configured. -
primary_key_columns: JSON array of the table’s primary-key column names in key order. Only present whenschema_nameis configured and the table has a primary key.
Permissions
The connecting user needs SELECT on the source table, or on the statement’s tables in query mode. The user also needs read access to system views in these cases:
-
When
schema_nameis set, the input readsSYS.TABLE_COLUMNS,SYS.INDEX_COLUMNS, andSYS.INDEXESto build theschemaandprimary_key_columnsmetadata. -
In the
timestampandtimestamp+incrementingmodes, the input readsSYS.TABLE_COLUMNS(orSYS.VIEW_COLUMNSfor a view) to check the type oftimestamp_columnwhen it connects. Without access, the check is skipped and a warning is logged. -
When
incrementing_initial_valueis set and no checkpoint exists yet, the input readsSYS.TABLE_COLUMNS(orSYS.VIEW_COLUMNSfor a view) to bind the initial value with the type ofincrementing_column. Without catalog rows, it test-binds the value against the column (as a number when it parses as one, then as the literal string) and fails to connect when neither binds.
HANA lists catalog rows for the objects a user holds a privilege on, so SELECT on a table or view is enough for these reads. A view has no rows in SYS.TABLE_COLUMNS whatever the privileges, so it is read without schema and primary_key_columns metadata. For other objects the user cannot see in the catalog, grant CATALOG READ.
Known limitations
-
Polling only: deleted rows are never seen, and
incrementingmode never sees updates to existing rows. The timestamp modes see an update only when the application also updatestimestamp_column. -
Rows whose
incrementing_columnortimestamp_columnis NULL are never emitted. -
timestamp_columnmust be a TIMESTAMP, LONGDATE or SECONDDATE column. Change times stored asDEC(15,0)UTC timestamps or as separate date and time character columns, as in many SAP application tables, cannot drive the timestamp modes. -
schemaandprimary_key_columnsmetadata come fromSYS.TABLE_COLUMNS, which does not describe views or calculation views, so those are read without schema metadata. -
schema_registry_encodederives Avro field names from column names. Column names that are not valid Avro names, such as SAP’s/BIC/namespaced columns, fail to encode; register the schema yourself and rename the columns in amappinginstead of usingschema_metadata. Table names are sanitised automatically. -
bulkandqueryhave no position to resume from: an error part-way through a read restarts it from the first row, re-sending the rows already delivered. -
queryruns its statement once and then the input ends, likebulk, and attaches no metadata. Calculation views with input parameters can only be read this way. -
The cursor stays open while downstream components apply backpressure. On a busy HANA system a long-open cursor holds back MVCC garbage collection, so index the
incrementing_columnortimestamp_columnand avoid outputs that stall for long periods. The first poll of a polling mode without an initial value reads the whole table in key order; setincrementing_initial_valueortimestamp_initial_valueto skip history you do not need. Raisefetch_size(for example to 1000 to 5000) on high-latency links, together withcheckpoint_limit.
Troubleshooting
checkpoint key … holds the position of … on connect. Two sap_hana inputs share a checkpoint_cache and checkpoint_cache_key. Give each input its own checkpoint_cache_key. The error also appears when schema_name or table changed for an existing input: the stored position is for the old reference, so delete the key to start over or set incrementing_initial_value/timestamp_initial_value under a new key.
Cannot connect to SAP HANA Cloud. HANA Cloud accepts TLS connections only, on port 443. go-hdb enables TLS when a TLS parameter is present, so add TLSServerName=<host> to the DSN (and TLSRootCAFile=<path> if the CA is not in the system trust store).
schema and primary_key_columns metadata are missing. The input reads them from SYS.TABLE_COLUMNS and SYS.INDEX_COLUMNS; when that read fails it logs a warning and carries on without them. Views never have them. For a table, check the warning in the logs, grant the connecting user SELECT on the table (or CATALOG READ), and make sure schema_name is set.
"invalid table name" or "invalid column name" for a table that exists. Identifiers in this configuration are quoted when sent to HANA, so they must match the catalog’s case exactly. HANA upper-cases identifiers that were created without quotes: a table created as create table orders is ORDERS in the catalog and must be configured as such.
Batches arrive one at a time. fetch_size larger than checkpoint_limit means a batch cannot be handed on until the previous one is acknowledged (a warning is logged at startup). Raise checkpoint_limit or lower fetch_size.
Rows written around the time of a poll are missing in timestamp modes. The poll window ends at the database clock minus timestamp_delay; a row whose timestamp was assigned before that bound but committed after the poll is never seen. Set timestamp_delay longer than your longest write transaction, and pick the timestamp_clock that matches how the column is populated.
-
Common
-
Advanced
input:
label: ""
sap_hana:
dsn: "" # No default (required)
schema_name: "" # No default (optional)
table: "" # No default (optional)
mode: bulk
query: "" # No default (optional)
incrementing_column: "" # No default (optional)
incrementing_initial_value: ""
poll_interval: 60s
timestamp_column: "" # No default (optional)
timestamp_initial_value: ""
timestamp_delay: 5s
numeric_mapping: none
checkpoint_cache: "" # No default (optional)
auto_replay_nacks: true
input:
label: ""
sap_hana:
dsn: "" # No default (required)
fetch_size: 128
schema_name: "" # No default (optional)
table: "" # No default (optional)
mode: bulk
query: "" # No default (optional)
incrementing_column: "" # No default (optional)
incrementing_initial_value: ""
poll_interval: 60s
timestamp_column: "" # No default (optional)
timestamp_initial_value: ""
timestamp_delay: 5s
timestamp_clock: database
numeric_mapping: none
max_retries: 3
retry_backoff: 1s
checkpoint_cache: "" # No default (optional)
checkpoint_cache_key: sap_hana_hwm
checkpoint_limit: 1024
auto_replay_nacks: true
Fields
auto_replay_nacks
Whether to automatically replay rejected messages (negative acknowledgements, or nacks) at the output level. If the cause of rejections persists, leaving this option enabled can result in back pressure.
Set auto_replay_nacks to false to delete rejected messages. Disabling auto replays can greatly improve memory efficiency of high throughput streams, as the original shape of the data is discarded immediately upon consumption and mutation.
Type: bool
Default: true
checkpoint_cache
Name of a cache resource to persist the high-water mark across restarts. When set, the connector resumes from where it left off rather than starting from scratch. Only effective in incrementing, timestamp, and timestamp+incrementing modes. The cache must be declared under cache_resources. Choose a durable backend (redpanda, redis, PostgreSQL via sql) for production; memory and lru caches lose the position on every restart or redeploy, and the input then re-reads from the initial value. Without this field the position is also kept in memory only, and a warning is logged at startup.
Type: string
# Examples:
checkpoint_cache: redis_cache
checkpoint_cache_key
Key used to store the checkpoint in checkpoint_cache. Every sap_hana input sharing a cache resource needs its own key: the stored checkpoint records its table, and an input refuses to start from another table’s checkpoint.
Type: string
Default: sap_hana_hwm
checkpoint_limit
The maximum number of messages that can be in flight (read but not yet acknowledged) at a given time. The high-water mark is only checkpointed once every message before it has been acknowledged, preserving at-least-once delivery even when batches are acknowledged out of order. When fetch_size exceeds this limit, batches are delivered one at a time (each waits for the previous batch’s acknowledgement), so raise this alongside large fetch_size values to keep batches flowing concurrently.
Type: int
Default: 1024
dsn
SAP HANA connection DSN in hdb://user:password@host:port[?param=value&…] form. URL-encode reserved characters in the user name and password (# as %23, @ as %40, % as %25). Useful parameters: databaseName selects a tenant database when connecting through the system database port, defaultSchema sets the schema unqualified names resolve against, and TLSServerName, TLSRootCAFile and TLSInsecureSkipVerify configure TLS, which SAP HANA Cloud requires.
|
This field contains sensitive information that usually shouldn’t be added to a configuration directly. For more information, see Secrets. |
Type: string
# Examples:
dsn: hdb://user:password@host:39017
# ---
dsn: hdb://user:password@host:30013?databaseName=HXE
# ---
dsn: hdb://user:password@<instance-id>.hana.prod-eu10.hanacloud.ondemand.com:443?TLSServerName=<instance-id>.hana.prod-eu10.hanacloud.ondemand.com
fetch_size
Number of rows requested per FetchNext round-trip. Larger values reduce round-trips on high-latency connections.
Type: int
Default: 128
incrementing_column
Column to use as the high-water mark for incrementing mode. Must be strictly monotonically increasing with no duplicate values. A BIGINT auto-increment column is ideal. Columns that produce duplicate values (for example, a plain TIMESTAMP) will cause rows whose value ties span a fetch_size boundary to be re-delivered. Use timestamp+incrementing mode to handle timestamp columns safely.
Type: string
incrementing_initial_value
Initial high-water mark value. When empty, all existing rows are emitted on the first run. The value is converted to the incrementing_column’s type from the catalog on connect: integers for integer columns, RFC3339 or `YYYY-MM-DD[ HH:MM:SS] for DATE/TIMESTAMP columns (the column’s wall time, with no offset other than Z or +00:00), hexadecimal for BINARY/VARBINARY columns, and the literal string (leading zeros preserved) for character columns. A persisted checkpoint takes precedence over this value.
Type: string
Default: ""
max_retries
Maximum number of times to retry a failed query before returning an error. Set to 0 to disable retries; negative values are rejected.
Type: int
Default: 3
mode
Operation mode.
Type: string
Default: bulk
Options: bulk, incrementing, query, timestamp, timestamp+incrementing
numeric_mapping
Controls how DECIMAL/NUMERIC columns are emitted:
-
none: emit as a canonical decimal string preserving full precision, except integer-typed columns (DECIMAL(p,0)with precision ⇐ 18) which are emitted as integers. -
best_fit: additionally emit columns whose precision fits a double (precision ⇐ 15) as floating-point numbers; wider values fall back to canonical decimal strings.
Type: string
Default: none
Options: none, best_fit
poll_interval
How long to wait between polls in incrementing, timestamp, and timestamp+incrementing modes.
Type: string
Default: 60s
# Examples:
poll_interval: 10s
# ---
poll_interval: 5m
retry_backoff
Base delay between query retries. The delay grows linearly with the attempt number (attempt N waits N times this value).
Type: string
Default: 1s
schema_name
Database schema for the table. When set, an Avro-compatible schema metadata field is attached to every message using data from SYS.TABLE_COLUMNS.
Type: string
timestamp_clock
Which database clock bounds each timestamp-mode poll window. The bound is always read from HANA, never from the connector host, so it shares the clock and timezone convention of the column it is compared against:
-
database:CURRENT_TIMESTAMP(session timezone), matching columns populated byDEFAULT CURRENT_TIMESTAMPorNOW(). -
database_utc:CURRENT_UTCTIMESTAMP, for columns populated with UTC values.
Type: string
Default: database
Options: database, database_utc
timestamp_column
Column to use as the high-water mark for timestamp and timestamp+incrementing modes. Must be a TIMESTAMP or LONGDATE column.
Type: string
timestamp_delay
Commit-lag buffer for timestamp modes. The upper bound for each poll is the database clock minus timestamp_delay, so rows whose timestamp was assigned slightly before a still-uncommitted transaction finished are not missed. Set it longer than your longest write transaction: a row whose transaction commits after the poll window covering its timestamp has closed is never emitted. Negative values are rejected.
Type: string
Default: 5s
# Examples:
timestamp_delay: 0s
# ---
timestamp_delay: 30s
timestamp_initial_value
Initial high-water mark in RFC3339 format (for example, 2024-01-01T00:00:00Z). When empty, all existing rows are emitted on the first run. timestamp_column has no timezone, so write its wall-clock value as-is, tagged with a Z or +00:00 offset, rather than converting it. Any other offset is rejected when the configuration is parsed.
Type: string
Default: ""
Examples
Incremental reads with a durable checkpoint
Polls an orders table for new rows by primary key every 30 seconds and persists the high-water mark in a file cache so a restart resumes where it left off.
input:
sap_hana:
dsn: hdb://user:password@hana-host:39017
mode: incrementing
schema_name: SALES
table: ORDERS
incrementing_column: ORDER_ID
poll_interval: 30s
checkpoint_cache: hana_checkpoints
checkpoint_cache_key: sales_orders
cache_resources:
- label: hana_checkpoints
file:
directory: /var/lib/redpanda-connect/sap_hana
Change tracking by timestamp with automatic Avro schema registration
Follows an updated-at column together with the primary key so rows sharing a timestamp are neither duplicated nor missed, bounds each poll by the database’s UTC clock with a commit-lag buffer, and registers the table’s schema from the emitted metadata before encoding. The checkpoint is kept in a Redpanda topic, which survives redeploys and needs no local disk (use a compacted topic).
input:
sap_hana:
dsn: hdb://user:password@hana-host:39017
mode: timestamp+incrementing
schema_name: SALES
table: ORDERS
timestamp_column: UPDATED_AT
incrementing_column: ORDER_ID
timestamp_clock: database_utc
timestamp_delay: 30s
poll_interval: 10s
checkpoint_cache: hana_checkpoints
checkpoint_cache_key: sales_orders_changes
pipeline:
processors:
- schema_registry_encode:
url: http://schema-registry:8081
subject: sales.orders-value
schema_metadata: schema
format: avro
avro:
raw_json: true
output:
redpanda:
seed_brokers: [ "broker:9092" ]
topic: sales.orders
cache_resources:
- label: hana_checkpoints
redpanda:
seed_brokers: [ "broker:9092" ]
topic: sap_hana_checkpoints
Run a custom query
Runs a SQL statement once and emits one message per result row. In query mode, table and schema_name are not required and no metadata is attached.
input:
sap_hana:
dsn: hdb://user:password@hana-host:39017
mode: query
query: |
SELECT ORDER_ID, CUSTOMER_ID, STATUS
FROM SALES.ORDERS
WHERE STATUS = 'PENDING'