Skip to content

Fix LDF datamart SPs: guard unguarded SUBSTRING idiom across 6 per-condition SPs#840

Open
nullflux wants to merge 2 commits into
mainfrom
aw/app-471/bug-8
Open

Fix LDF datamart SPs: guard unguarded SUBSTRING idiom across 6 per-condition SPs#840
nullflux wants to merge 2 commits into
mainfrom
aw/app-471/bug-8

Conversation

@nullflux
Copy link
Copy Markdown
Contributor

Description

Six per-condition LDF datamart SPs (bmird, foodborne, mumps, tetanus, vaccine_prevent_diseases, hepatitis) build a comma-separated @dynamiccolumnUpdate from INFORMATION_SCHEMA.COLUMNS, then unconditionally strip the trailing comma with SUBSTRING(@dynamiccolumnUpdate, 1, LEN(@dynamiccolumnUpdate) - 1). When the per-condition LDF_<COND> table has only its baseline-key columns (no dynamic LDF answer columns added yet), the SELECT matches zero rows, @dynamiccolumnUpdate stays '', and SUBSTRING('', 1, -1) raises Msg 537. The outer TRY/CATCH swallows it into a job_flow_log ERROR row.

Three peer sites in the same files already wrap the SUBSTRING + EXEC in IF @dynamiccolumnUpdate IS NOT NULL AND @dynamiccolumnUpdate != '' BEGIN ... END. This applies that same guard to the six unguarded sites:

  • 285-sp_ldf_bmird_datamart_postprocessing-001.sql:603
  • 290-sp_ldf_foodborne_datamart_postprocessing-001.sql:893
  • 295-sp_ldf_mumps_datamart_postprocessing-001.sql:627
  • 300-sp_ldf_tetanus_datamart_postprocessing-001.sql:833
  • 305-sp_ldf_vaccine_prevent_diseases_datamart_postprocessing-001.sql:1105
  • 320-sp_ldf_hepatitis_datamart_postprocessing-001.sql:594

Verified locally: none of the six SPs emit a Msg 537 ERROR row in job_flow_log when executed against an empty per-condition LDF table.

Related Issue

APP-471

Additional Notes

Independent of bug #7 — fires on a clean liquibase-applied DB the first time any per-condition LDF SP runs, before its dynamic columns are ever added.

Site `290` (foodborne) was already guarded with a different form (`IF LEN(@dynamiccolumnUpdate) > 0`); rewritten to match the `IS NOT NULL AND != ''` form used at the five peer sites.

Includes a `testData/unit` fixture that EXECs the tetanus SP against an empty `LDF_TETANUS` and asserts no Msg 537 ERROR row in `job_flow_log`.

Checklist

  • I have ensured that the pull request is of a manageable size, allowing it to be reviewed within a single session.
  • I have reviewed my changes to ensure they are clear, concise, and well-documented.
  • I have updated the documentation, if applicable.
  • I have added or updated test cases to cover my changes, if applicable.

nullflux added 2 commits May 17, 2026 19:27
… SPs

The "UPDATE LDF_<CONDITION> when there is no record in the
LDF_DIMENSIONAL_DATA" block in each per-condition LDF datamart SP built
@dynamiccolumnUpdate by accumulating column names from
INFORMATION_SCHEMA.COLUMNS, then unconditionally stripped a trailing
comma with SUBSTRING(@dynamiccolumnUpdate, 1, LEN(@dynamiccolumnUpdate) - 1).
When the table has only the 7 baseline-key columns (the state on a clean
liquibase-applied DB before dynamic LDF answer columns are added),
@dynamiccolumnUpdate stays as '' and SUBSTRING('', 1, -1) raises Msg 537,
which the outer TRY/CATCH swallows into a job_flow_log ERROR row.

Three peer sites in the same files (285:530, 295:527, 320:523) already
wrap an identical SUBSTRING+EXEC with
IF @<var> IS NOT NULL AND @<var>!='' BEGIN ... END. This applies the same
guard pattern to the six previously-unguarded sites: 285:603, 290:893,
295:627, 300:833, 305:1105, 320:594.
Asserts sp_ldf_tetanus_datamart_postprocessing produces no Msg 537
("Invalid length parameter passed to LEFT or SUBSTRING") row in
job_flow_log when invoked against an LDF_TETANUS table that has only
its 7 baseline-key columns (the freshly-applied liquibase state).
Tetanus is the representative case for the 6-instance bug family --
the same SUBSTRING guard fix is applied to the 5 peer per-condition
LDF datamart SPs.
@nullflux nullflux requested a review from a team as a code owner May 20, 2026 16:51
nullflux added a commit that referenced this pull request May 20, 2026
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
-- Tetanus is the representative case (the bug was originally surfaced
-- there); the same fix is applied to the 5 peer per-condition LDF SPs.

EXEC dbo.sp_ldf_tetanus_datamart_postprocessing
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is it worth making 6 different calls here, 1 for each stored proc we're updating?

nullflux added a commit that referenced this pull request May 20, 2026
…PR routines in orchestrator

Two changes:

1. Extend bug #5b's patient_id-NULL fix to the 10 multi-condition
   nrt_investigation variants (22000010-22000100) and the Tetanus
   variant (22000200). The original cherry-pick (bb7cec9) only set
   patient_id on the foundation Inv (20000100); the Tier 3 variants
   left it NULL, so the same DELETE-by-sentinel-PATIENT_UID cascade
   that blocks HEPATITIS_DATAMART would block any condition-datamart
   SP whose query path goes through F_PAGE_CASE -> D_PATIENT lookup.

2. New orchestrator step 2.5 apply_pending_pr_routines pulls each
   pending-PR routine (PRs #837, #839, #840) from its bug branch via
   `git show` and applies it to the freshly-reset DB before fixtures.
   Without this the orchestrator aborts at step 8 on
   ldf_answers_tetanus.sql (bug #7 early-RETURN guard fires on a SUB
   data_type ldf_uid, and bug #8 SUBSTRING fires on the tetanus
   datamart SP). Remove a branch from the list once its PR merges and
   the baseline image is refreshed.

End-to-end coverage uplift vs. coverage_tier_3.md baseline:
  HEPATITIS_DATAMART         0 -> 1    (5b)
  COVID_CASE_DATAMART        0 -> 1    (5b on 22000070)
  BMIRD_STREP_PNEUMO_DATAMART 0 -> 1   (5b on 22000100)
  F_PAGE_CASE                1 -> 6    (multi-condition + 5b)
  LDF_DIMENSIONAL_DATA       0 -> 5    (PR #839 bug-7)
  MORB_RPT_USER_COMMENT      0 -> 1    (PR #837 bug-3)

Still 0 (separate per-condition blockers, not 5b-related): HEPATITIS_CASE,
HEP100, F_STD_PAGE_CASE, STD_HIV_DATAMART, TB_DATAMART, VAR_DATAMART,
LDF_TETANUS, LDF_HEPATITIS — see coverage_hep_datamart_investigation.md
for per-condition diagnoses.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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.

2 participants