Skip to content

refactor: Change HANA trigger to be statement based#272

Draft
stefanrudi wants to merge 2 commits intomainfrom
perf/statement-trigger
Draft

refactor: Change HANA trigger to be statement based#272
stefanrudi wants to merge 2 commits intomainfrom
perf/statement-trigger

Conversation

@stefanrudi
Copy link
Collaborator

@stefanrudi stefanrudi commented Mar 24, 2026

Refactor: Convert HANA Triggers to Statement-Level

♻️ Refactor: Migrated HANA database triggers from row-level (FOR EACH ROW) to statement-level (FOR EACH STATEMENT) execution, replacing :old/:new row references with transition table aliases (ot/nt via REFERENCING OLD TABLE old_tab / REFERENCING NEW TABLE new_tab).

Changes

This refactor eliminates the dependency on a dummy table (CHANGE_TRACKING_DUMMY) and rewrites all trigger SQL generation to use set-based INSERT ... SELECT patterns instead of per-row procedural logic.

  • index.cds: Removed the CHANGE_TRACKING_DUMMY entity definition that was previously required as a workaround for HANA HDI triggers.
  • lib/TriggerCQN2SQL.js: Updated trigger row reference regex to support nt/ot table aliases; removed the custom from() override that handled the now-deleted dummy table.
  • lib/hana/triggers.js: Switched all three trigger types (INSERT, UPDATE, DELETE) from REFERENCING NEW/OLD ROW to REFERENCING NEW/OLD TABLE ... FOR EACH STATEMENT. Added getFromClause() helper to generate the appropriate FROM clause with transition table aliases. Updated all row references from new/old to nt/ot. Rewrote buildInsertSQL to embed all column expressions directly in the UNION ALL sub-selects, removing the outer wrapping SELECT.
  • lib/hana/composition.js: Updated all composition parent context builders to use transition table aliases (nt/ot) instead of :new/:old row references. Replaced procedural DECLARE/IF/END IF SQL blocks with set-based INSERT ... SELECT DISTINCT patterns. Removed buildParentLookupSQL (row-level helper). Added parentLookupExpr as a correlated subquery for parent ID resolution.
  • lib/hana/sql-expressions.js: Replaced all :old.column / :new.column references with ot.column / nt.column. Updated nullSafeChanged, getValueExpr, getWhereCondition, buildAssocLookup, buildObjectIDExpr, and buildGrandParentObjectIDExpr accordingly. Changed SELECT.one.from(...) to SELECT.from(...) throughout.
  • lib/hana/register.js: Removed the HDI compiler hook logic that injected the dummy CSV data and patched the CSN definition for CHANGE_TRACKING_DUMMY.
  • tests/build/hana-build.test.js: Removed test assertion for CHANGE_TRACKING_DUMMY CSV generation.
  • 🔄 Regenerate and Update Summary

📬 Subscribe to the Hyperspace PR Bot DL to get the latest announcements and pilot features!

PR Bot Information

Version: 1.19.3 | 📖 Documentation | 🚨 Create Incident | 💬 Feedback

  • Output Template: Default Template
  • Summary Prompt: Default Prompt
  • Correlation ID: a4f96c20-27a6-11f1-82b7-8bfcfe8a6519
  • Event Trigger: pull_request.opened
  • LLM: anthropic--claude-4.6-sonnet

Copy link
Contributor

@hyperspace-insights hyperspace-insights bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The refactor successfully migrates HANA triggers from row-level (FOR EACH ROW) to statement-level (FOR EACH STATEMENT) semantics, eliminating the CHANGE_TRACKING_DUMMY table workaround and replacing procedural variable-based logic with set-based INSERT … SELECT DISTINCT patterns. The overall approach is sound, but there are four issues worth addressing: a dead variable left from the old implementation (entityKey in generateDeleteTrigger), another dead code block (grandParentWhereSubquery in buildGrandParentObjectIDExpr), a correctness problem with SELECT DISTINCT in buildCompositionOfOneParentContext where the correlated parentKeyExpr subquery prevents effective deduplication across multiple child rows belonging to the same parent, and a potential SQL corruption risk in TriggerCQN2SQL where subquery-valued val strings (e.g. (SELECT … WHERE pk = nt.ID)) fall through to super.val() and get quoted as string literals instead of being emitted verbatim.

PR Bot Information

Version: 1.19.3 | 📖 Documentation | 🚨 Create Incident | 💬 Feedback

  • LLM: anthropic--claude-4.6-sonnet
  • Correlation ID: a4f96c20-27a6-11f1-82b7-8bfcfe8a6519
  • Event Trigger: pull_request.opened

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant