Skip to content

Migrate remaining ONPRC modules' SQL scripts to PostgreSQL - #1859

Open
labkey-adam wants to merge 14 commits into
release26.3-SNAPSHOTfrom
26.3_fb_final_onprc_scripts
Open

Migrate remaining ONPRC modules' SQL scripts to PostgreSQL#1859
labkey-adam wants to merge 14 commits into
release26.3-SNAPSHOTfrom
26.3_fb_final_onprc_scripts

Conversation

@labkey-adam

@labkey-adam labkey-adam commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Rationale

Consolidate and migrate SQL upgrade scripts in the last three ONPRC modules:

  • extscheduler
  • onprc_ehr_compliancedb
  • onprc_ssu

All three move from SupportedDatabases: mssql / ManageVersion: false to mssql, pgsql with managed versions.

Changes

extscheduler

Removed the 2020 Covid-19 scheduling scaffolding. The dateParts window these procedures read is frozen at 2020-05-01 through 2021-04-20, so they can only ever generate events dated 2020-2021; extBlockOutEvening additionally violates CHK_event_DateRangeValid and has never inserted a row.

  • Added extscheduler-26.000-26.001.sql to drop extBlockOutEvening, extBlockOutMorning, extBlockOutDays and the dateParts table from existing installs, and bumped getSchemaVersion() to 26.001. No PostgreSQL counterpart is needed: PostgreSQL support arrives at 26.000 with the consolidated script, which never creates these objects.
  • Omitted these objects from the PostgreSQL consolidated script. The SQL Server script still creates them, so the drop script's context stays visible.
  • Removed dateParts from extscheduler.xml.

onprc_ehr_compliancedb

  • Consolidated 0.000-24.000 and the twelve 24.001-24.012 scripts into a single SQL Server 0.000-25.000 script, and ported both it and 25.000-25.001 to PostgreSQL. Both dialects define the same seven tables and five routines.
  • Ported the SQL Server stored procedures as PostgreSQL functions returning integer. Nothing in the enlistment calls them, so any external caller (ETL or scheduled job) will need its invocation updated for PostgreSQL.
  • Added a requirementsperemployee.js query trigger that normalizes employeeid and requirementname lookup values on write, replacing the lower() calls the report procedures previously relied on for case-insensitive matching.
  • Bumped getSchemaVersion() to 26.000. No getEarliestUpgradeVersion() override is needed here since the installed version is 25.001, already at or above the platform floor of 25.000.

onprc_ssu

  • Consolidated 13.20-13.21 through 13.22-13.23 into a single SQL Server 0.000-25.000 script and added the PostgreSQL equivalent, which folds the three ALTER TABLE statements into the CREATE TABLE.
  • Bumped getSchemaVersion() to 26.000 with a getEarliestUpgradeVersion() of 13.23, required because 13.23 is below the platform floor of 25.000.

Tasks

  • Claude Code Review
  • Code Review

@labkey-adam

Copy link
Copy Markdown
Contributor Author

@ankurjuneja @labkey-martyp note the TODO in extscheduler-0.000-25.000.sql. There's a very fishy interval in procedure extBlockOutEvening(). Probably need to discuss with ONPRC to fix this or remove it if it's no longer used.

@labkey-adam labkey-adam added this to the 26.03 milestone Aug 22, 2026
ankurjuneja
ankurjuneja previously approved these changes Aug 24, 2026
The ExtScheduler overlap trigger carried the T-SQL spelling `PropertySets."Set"` into PostgreSQL, where the column is declared unquoted and therefore folds to lowercase `set`. Quoted identifiers are matched exactly, so the join referenced a column that does not exist. plpgsql does not plan a function body until first execution, so the install succeeded and every subsequent insert or update of an extscheduler.events row would have failed.

`p_SciShieldToPrimeProcess` and `p_ComplianceTranslatestringUpdate` relied on SQL Server's case-insensitive default collation. The SciShield import lowercases the employee id before matching, which found nothing on PostgreSQL and silently marked every incoming record as an invalid employee id; the lookups now compare with `lower()` on both sides and the insert writes the spelling stored in ehr_compliancedb.employees so the completiondates foreign key resolves. The "arrs" to "DCM" rename now uses `ILIKE` and `regexp_replace(..., 'gi')` so it reaches values that are not already lowercase.

Container EntityIds are a native `uniqueidentifier` on SQL Server but a `VARCHAR(36)` domain on PostgreSQL, and LabKey generates them in lowercase, so the hardcoded uppercase GUID literals matched nothing and wrote rows into a container that resolves to no folder. Lowercased in the PostgreSQL scripts only; the SQL Server scripts are correct as written.
…dures

The two report procedures join ehr_compliancedb.employeeperunit to ehr_compliancedb.requirementspercategory on `unit` or `category`. requirementspercategory constrains both columns with foreign keys to unit_names and employeecategory, but employeeperunit has no constraints at all, so its values are uncontrolled free text. SQL Server's case-insensitive collation absorbed any drift; on PostgreSQL a `DCM` against a `dcm` silently drops the employee from the compliance report rather than raising anything.

Applied to all six joins in each of the bootstrap and 25.000-25.001 scripts. NULL behavior is unchanged: employeeperunit.unit and .category are nullable, and `lower(NULL) = lower(NULL)` is NULL just as `NULL = NULL` was.
The ported PostgreSQL procedures wrapped every unit and category comparison in lower() to emulate the case-insensitive default collation the MS SQL originals relied on implicitly. All of those comparisons join employeeperunit against requirementspercategory, and requirementspercategory already canonicalizes unit and category on write through its trigger script, so the only source of drift was employeeperunit - the one table in ehr_compliancedb with no trigger script. Wrapping both sides also made the joins unindexable.

Adds a trigger script for onprc_ehr_compliancedb.requirementsperemployee, matching the ten in ehr_compliancedb. It is user-editable and declares employeeid and requirementname as lookups, but normalized neither.

Depends on employeeperunit.js and sopdates.js in the EHR_ComplianceDB module. Merge that change first, or reports will silently drop rows whose unit or category differs only by case.

The lower() calls in p_SciShieldToPrimeProcess are unchanged; they resolve arbitrary external SciShield text against canonical values, which is where case-insensitive matching belongs.
The extBlockOut* procedures and the dateParts table they read are one-off Covid-19 scaffolding from 2020 that nothing in the enlistment calls. The dateParts window is frozen at 2020-05-01 through 2021-04-20, so the procedures can only ever generate events dated 2020-2021, and extBlockOutEvening additionally violates CHK_event_DateRangeValid: its StartDate is date + 1530 hours, a 15:30 clock time misread as an hour count, so it has never inserted a row.

extscheduler-26.000-26.001.sql drops them from existing installs. The PostgreSQL consolidated script omits them; the SQL Server one still creates them so the drop script has visible context.
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.

3 participants