Install
$ agentstack add skill-efeumutaslan-sap-skills-sap-hana-tools ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ● Filesystem access Used
- ● Shell / process execution Used
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
SAP HANA Developer Tools & CLI
Related Skills
sap-hana-cloud— HANA Cloud database development (SQL, HDI, multi-model)sap-devops-cicd— HANA artifact deployment in CI/CD pipelinessap-cap-advanced— CAP projects with HANA Cloud persistence
Quick Start
Key tools:
| Tool | Purpose | Install | |------|---------|---------| | hdbsql | Interactive SQL client | SAP HANA Client package | | hdbuserstore | Secure credential store | SAP HANA Client package | | @sap/hdi-deploy | HDI container deployer | npm install @sap/hdi-deploy | | HANA Database Explorer | Web-based SQL editor | BTP cockpit → HANA Cloud | | HANA Cloud Central | Instance management | BTP cockpit | | @sap/hana-client | Node.js HANA driver | npm install @sap/hana-client |
Connect with hdbsql:
# Store credentials securely
hdbuserstore SET HANACLOUD :443
# Connect and run query
hdbsql -U HANACLOUD "SELECT * FROM M_DATABASE"
# Connect directly
hdbsql -n :443 -u -p -encrypt
Core Concepts
HDI Container Lifecycle (CLI)
# HDI deploy from command line (CI/CD)
npx @sap/hdi-deploy \
--service-replacements '{"hdi-container":"my-hdi-service-key"}' \
--deploy '["src/**"]' \
--undeploy '["src/old_table.hdbtable"]'
# Environment variables for HDI deploy
export HDI_DEPLOY_OPTIONS='{"auto_undeploy":false,"treat_warnings_as_errors":true}'
Connection Methods
| Method | Use Case | Security | |--------|----------|----------| | hdbuserstore | Persistent, scripted access | Encrypted local store | | Direct params | One-off queries | Password on command line (avoid in prod) | | JWT token | BTP app auth | Short-lived, OAuth 2.0 | | X.509 certificate | Service-to-service | Mutual TLS | | Service key (JSON) | BTP service binding | From BTP cockpit |
hdbsql Output Formats
# CSV output (for data export)
hdbsql -U HANACLOUD -o output.csv -c "," -a "SELECT * FROM MY_TABLE"
# JSON output (pipe to jq)
hdbsql -U HANACLOUD -j "SELECT TOP 10 * FROM M_SQL_PLAN_CACHE ORDER BY total_execution_time DESC"
# Aligned column output (human-readable)
hdbsql -U HANACLOUD -A "SELECT * FROM M_SERVICE_MEMORY"
Common Patterns
Pattern 1: HANA Health Check Script
#!/bin/bash
# hana_health_check.sh — Daily HANA Cloud health report
STORE_KEY="HANACLOUD"
echo "=== HANA Cloud Health Check $(date) ==="
echo -e "\n--- Database Info ---"
hdbsql -U $STORE_KEY -j "SELECT DATABASE_NAME, VERSION, USAGE FROM M_DATABASE"
echo -e "\n--- Memory Usage ---"
hdbsql -U $STORE_KEY -A "
SELECT HOST,
ROUND(USED_PHYSICAL_MEMORY/1024/1024/1024, 2) AS USED_GB,
ROUND(FREE_PHYSICAL_MEMORY/1024/1024/1024, 2) AS FREE_GB,
ROUND(USED_PHYSICAL_MEMORY * 100.0 / (USED_PHYSICAL_MEMORY + FREE_PHYSICAL_MEMORY), 1) AS USED_PCT
FROM M_HOST_RESOURCE_UTILIZATION"
echo -e "\n--- Top 5 Expensive Queries (Last 24h) ---"
hdbsql -U $STORE_KEY -A "
SELECT TOP 5
SUBSTRING(STATEMENT_STRING, 1, 80) AS QUERY,
ROUND(DURATION_MICROSEC/1000000, 2) AS DURATION_SEC,
RECORDS AS ROWS_AFFECTED
FROM M_EXPENSIVE_STATEMENTS
WHERE START_TIME > ADD_SECONDS(CURRENT_TIMESTAMP, -86400)
ORDER BY DURATION_MICROSEC DESC"
echo -e "\n--- Active Connections ---"
hdbsql -U $STORE_KEY -A "
SELECT CONNECTION_STATUS, COUNT(*) AS CNT
FROM M_CONNECTIONS
GROUP BY CONNECTION_STATUS"
echo -e "\n--- Table Growth (Top 10 by size) ---"
hdbsql -U $STORE_KEY -A "
SELECT TOP 10
SCHEMA_NAME, TABLE_NAME,
ROUND(TABLE_SIZE/1024/1024, 2) AS SIZE_MB,
RECORD_COUNT
FROM M_CS_TABLES
ORDER BY TABLE_SIZE DESC"
Pattern 2: Node.js HANA Client
const hana = require('@sap/hana-client');
class HANAConnection {
constructor(serviceKey) {
this.connParams = {
host: serviceKey.host,
port: serviceKey.port,
uid: serviceKey.user,
pwd: serviceKey.password,
encrypt: true,
sslValidateCertificate: true
};
}
async query(sql, params = []) {
const conn = hana.createConnection();
try {
await new Promise((resolve, reject) =>
conn.connect(this.connParams, (err) => err ? reject(err) : resolve())
);
return await new Promise((resolve, reject) =>
conn.exec(sql, params, (err, result) => err ? reject(err) : resolve(result))
);
} finally {
conn.disconnect();
}
}
async streamLargeResult(sql, params, onRow) {
const conn = hana.createConnection();
await new Promise((resolve, reject) =>
conn.connect(this.connParams, (err) => err ? reject(err) : resolve())
);
const stmt = conn.prepare(sql);
const rs = stmt.execQuery(params);
while (rs.next()) {
await onRow(rs.getValues());
}
rs.close();
stmt.drop();
conn.disconnect();
}
}
// Usage
const db = new HANAConnection(JSON.parse(process.env.HANA_SERVICE_KEY));
const results = await db.query(
'SELECT * FROM ORDERS WHERE CUSTOMER_ID = ? AND ORDER_DATE > ?',
['CUST001', '2026-01-01']
);
Pattern 3: HDI Container Management Script
#!/bin/bash
# Manage HDI containers for multi-tenant scenario
SERVICE_INSTANCE="my-hdi-shared"
# List all HDI containers
cf service-keys $SERVICE_INSTANCE | grep -E "^name"
# Create tenant-specific container
create_tenant_container() {
local TENANT_ID=$1
local CONTAINER_NAME="hdi-${TENANT_ID}"
cf create-service-key $SERVICE_INSTANCE $CONTAINER_NAME \
-c "{\"permissions\":\"development\"}"
# Get connection details
cf service-key $SERVICE_INSTANCE $CONTAINER_NAME | tail -n +2 > /tmp/${CONTAINER_NAME}.json
# Deploy schema to new container
HDI_SERVICE_KEY=$(cat /tmp/${CONTAINER_NAME}.json)
npx @sap/hdi-deploy --service-replacements "[{\"key\":\"hdi-container\",\"service\":\"$HDI_SERVICE_KEY\"}]"
}
# Delete tenant container
delete_tenant_container() {
local TENANT_ID=$1
cf delete-service-key $SERVICE_INSTANCE "hdi-${TENANT_ID}" -f
}
Pattern 4: Performance Analysis Queries
-- Find slow queries in plan cache
SELECT TOP 20
STATEMENT_HASH,
EXECUTION_COUNT,
ROUND(TOTAL_EXECUTION_TIME/1000000, 2) AS TOTAL_SEC,
ROUND(AVG_EXECUTION_TIME/1000000, 2) AS AVG_SEC,
ROUND(MAX_EXECUTION_TIME/1000000, 2) AS MAX_SEC,
TOTAL_LOCK_WAIT_COUNT,
SUBSTR(STATEMENT_STRING, 1, 100) AS QUERY_PREVIEW
FROM M_SQL_PLAN_CACHE
WHERE EXECUTION_COUNT > 10
ORDER BY AVG_EXECUTION_TIME DESC;
-- Table column memory consumption
SELECT SCHEMA_NAME, TABLE_NAME, COLUMN_NAME,
ROUND(MEMORY_SIZE_IN_TOTAL/1024/1024, 2) AS TOTAL_MB,
ROUND(PERSISTENT_MEMORY_SIZE_IN_TOTAL/1024/1024, 2) AS DISK_MB,
LOADED AS IS_LOADED
FROM M_CS_COLUMNS
WHERE SCHEMA_NAME = 'MY_SCHEMA'
ORDER BY MEMORY_SIZE_IN_TOTAL DESC;
-- Index advisor suggestions
SELECT * FROM M_CS_INDEXES_ADVISOR
WHERE SCHEMA_NAME = 'MY_SCHEMA'
ORDER BY ESTIMATED_BENEFIT DESC;
-- Check delta merge status
SELECT SCHEMA_NAME, TABLE_NAME, PART_ID,
RAW_RECORD_COUNT_IN_DELTA AS DELTA_ROWS,
RAW_RECORD_COUNT_IN_MAIN AS MAIN_ROWS,
ROUND(RAW_RECORD_COUNT_IN_DELTA * 100.0 /
NULLIF(RAW_RECORD_COUNT_IN_MAIN + RAW_RECORD_COUNT_IN_DELTA, 0), 1) AS DELTA_PCT
FROM M_CS_TABLES
WHERE RAW_RECORD_COUNT_IN_DELTA > 100000
ORDER BY RAW_RECORD_COUNT_IN_DELTA DESC;
Pattern 5: Python HANA Client (hdbcli)
from hdbcli import dbapi
import json
def connect_from_service_key(key_path):
"""Connect using BTP service key JSON."""
with open(key_path) as f:
key = json.load(f)
return dbapi.connect(
address=key["host"],
port=key["port"],
user=key["user"],
password=key["password"],
encrypt=True
)
def export_to_csv(conn, sql, output_path):
"""Export query results to CSV."""
import csv
cursor = conn.cursor()
cursor.execute(sql)
columns = [desc[0] for desc in cursor.description]
with open(output_path, 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(columns)
while True:
rows = cursor.fetchmany(10000)
if not rows:
break
writer.writerows(rows)
cursor.close()
def bulk_insert(conn, table_name, data, batch_size=5000):
"""Efficient bulk insert with parameterized batches."""
if not data:
return
columns = list(data[0].keys())
placeholders = ','.join(['?' for _ in columns])
sql = f"INSERT INTO {table_name} ({','.join(columns)}) VALUES ({placeholders})"
cursor = conn.cursor()
for i in range(0, len(data), batch_size):
batch = data[i:i+batch_size]
params = [tuple(row[c] for c in columns) for row in batch]
cursor.executemany(sql, params)
conn.commit()
cursor.close()
Error Catalog
| Error | Message | Root Cause | Fix | |-------|---------|------------|-----| | hdbsql: -10709 | Connection failed | Wrong host/port or network issue | Check host:443 (HANA Cloud always uses 443) | | hdbsql: -10104 | Invalid credentials | Wrong user/password | Reset password; check hdbuserstore entry | | hdbsql: -10 | Encryption required | Missing -encrypt flag | Add -encrypt or encrypt=true | | hdi-deploy: 403 | Insufficient privilege | Missing HDI admin role | Grant HDI container admin to technical user | | hdi-deploy: Build failed | Artifact compilation error | Invalid HDB artifact syntax | Check .hdbcds/.hdbprocedure syntax | | npm: @sap/hana-client | Install failed (native module) | Missing C++ build tools | Install node-gyp prereqs; use prebuild binary | | SQLCODE -131 | Transaction rolled back | Lock timeout during bulk insert | Reduce batch size; check for concurrent access | | SQLCODE -10001 | SQL syntax error | HANA SQL ≠ ANSI SQL | Check HANA-specific syntax (e.g., TOP N not LIMIT N) |
Performance Tips
- Use hdbuserstore — Avoid passwords in scripts;
hdbuserstoreis encrypted and reusable - Batch size for hdbsql — Use
-B(batch mode) for non-interactive execution in CI/CD - Parameterized queries — Always use
?placeholders; prevents SQL injection and enables plan reuse - Connection pooling — In Node.js/Python apps, reuse connections; don't connect per query
- hdbsql -j for JSON — JSON output is parse-friendly for automation scripts
- HDI deploy incremental — Only deploy changed files; use
--deploywith specific file paths - Export large datasets — Use
hdbsql -owith CSV format for data export instead of SELECT in app code
Gotchas
- HANA Cloud port: Always 443 (not 30015/30013 like on-premise)
- hdbsql LIMIT: HANA uses
SELECT TOP NnotLIMIT N(though recent versions support both) - Node.js driver versions:
@sap/hana-client(native, faster) vshdb(pure JS, slower but no native deps) - hdbuserstore scope: Keys are per-OS-user; CI/CD needs its own userstore setup
- SSL certificates: HANA Cloud uses DigiCert root CA; ensure it's in your trust store
- Time zone: HANA Cloud always runs in UTC; convert in queries with
UTCTOLOCAL()
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: efeumutaslan
- Source: efeumutaslan/SAP-SKILLS
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.