Skip to content

fix(pg): SCEP renewal + Windows MDM cleanup/re-enrollment SQL on PostgreSQL#7

Merged
dnplkndll merged 4 commits into
feat/pg-compat-rebasedfrom
pg-fix-interval-mult-and-pending-delete
Jul 8, 2026
Merged

fix(pg): SCEP renewal + Windows MDM cleanup/re-enrollment SQL on PostgreSQL#7
dnplkndll merged 4 commits into
feat/pg-compat-rebasedfrom
pg-fix-interval-mult-and-pending-delete

Conversation

@dnplkndll

@dnplkndll dnplkndll commented Jul 7, 2026

Copy link
Copy Markdown

Fixes the recurring SQL errors logged by the cleanups_then_aggregation cron on the deployed PG build (visible in cron_stats.errors every run since deploy), plus two same-class latent bugs found while reviewing the branch.

What changed (one commit per concern)

  1. rebind: $N * INTERVAL gets ::float8, not ::timestamptzreParamBeforeInterval cast every $N before [-+*] INTERVAL to timestamptz, so the SCEP expiry filter's (? * INTERVAL '1 day') became timestamptz * interval (SQLSTATE 42883, red every renew_scep_certificates run). +/- keep ::timestamptz; * now matches the INTERVAL ? UNIT rewrite's ::float8 convention.
  2. SCEP expiry query: PG GROUP BY strictness — the same query also selects ne.enrolled_from_migration/ne.type without grouping them (SQLSTATE 42803); this second failure was hiding behind the cast error and was caught by the new regression test. Both columns are functionally dependent on the group key, so MySQL semantics are unchanged.
  3. Windows MDM DELETEs: cross-dialect syntaxDELETE <alias> FROM ... (MySQL multi-table form, SQLSTATE 42601 on PG) in CleanupWindowsMDMPendingDeleteProfiles and in MDMWindowsDeleteEnrolledDeviceOnReenrollment (latent: would break Windows re-enrollment on PG; not covered by the TestPostgres* CI gate). Rewritten to the correlated NOT EXISTS / IN (subquery) forms used by CleanupHostIssues.
  4. PG regression coverageTestPostgresMDMCleanupQueries executes each of the three real statements against PG in CI, so the next dialect regression in these paths fails the gate instead of shipping silently.

Verification

  • go test ./server/platform/postgres/ green (new +/-/* cast cases).
  • Full POSTGRES_TEST=1 -run TestPostgres suite green locally (incl. the new regression test, which failed on the GROUP BY bug before the fix).
  • MySQL side unchanged semantically and green locally: TestMDMWindows/TestMDMWindowsEnrolledDevices, TestMDMShared/TestGetHostCertAssociationsToExpire, TestWindowsMDMPendingDeleteRetentionAndGC against mysql:8.0.44.
  • Statements also validated against the live fleet PG 16 (PREPARE/EXECUTE, EXPLAIN in rolled-back txn).

Net effect once deployed: SCEP identity-cert renewal scanning works (it has been silently broken since the PG cutover), Windows MDM pending-delete GC runs, and Windows device re-enrollment won't 500 on the PG build.

Checklist for submitter

  • Input data is properly validated, SELECT * is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters.

Testing

  • Added/updated automated tests
  • QA'd all new/changed functionality manually

https://claude.ai/code/session_01VLrsW7aZYZVcJgbpi44gzU

dnplkndll added 4 commits July 8, 2026 07:59
…mptz

reParamBeforeInterval stamped ::timestamptz on every $N before
[-+*] INTERVAL, so a param that scales an interval — the SCEP expiry
filter's (? * INTERVAL '1 day') — became timestamptz * interval and
failed with SQLSTATE 42883 on every renew_scep_certificates cron run.

Split the regex: +/- keep ::timestamptz (the param is a point in
time), * now gets ::float8, matching the INTERVAL ? UNIT rewrite
convention. Unit tests cover all three operators.

Claude-Session: https://claude.ai/code/session_01VLrsW7aZYZVcJgbpi44gzU
ne.enrolled_from_migration and ne.type are selected but were not
grouped; MySQL tolerates that, PG rejects it (SQLSTATE 42803) — the
second failure hiding behind the interval-cast error in the same
renew_scep_certificates query. Both columns are functionally dependent
on the existing group key (host_uuid = ne.id), so adding them changes
no MySQL semantics.

Claude-Session: https://claude.ai/code/session_01VLrsW7aZYZVcJgbpi44gzU
… syntax

DELETE <alias> FROM ... is MySQL multi-table syntax and fails to parse
on PostgreSQL (SQLSTATE 42601). Three statements were affected:

- CleanupWindowsMDMPendingDeleteProfiles (red in cron_stats every
  cleanups_then_aggregation run)
- MDMWindowsDeleteEnrolledDeviceOnReenrollment's setup-experience and
  upcoming-activities deletes (broke Windows re-enrollment on PG;
  latent because the flow is not in the TestPostgres CI suite)

Rewritten to the cross-dialect correlated NOT EXISTS / IN (subquery)
forms already used by CleanupHostIssues.

Claude-Session: https://claude.ai/code/session_01VLrsW7aZYZVcJgbpi44gzU
… suite

The renew_scep_certificates query, pending-delete GC, and Windows
re-enrollment cleanup were all PG-broken yet green in CI because none
of them run under -run TestPostgres. Execute each real statement
against PG so a dialect regression fails the gate instead of shipping.
This test caught the GROUP BY strictness bug fixed earlier in this
branch.

Claude-Session: https://claude.ai/code/session_01VLrsW7aZYZVcJgbpi44gzU
@dnplkndll dnplkndll force-pushed the pg-fix-interval-mult-and-pending-delete branch from e922ab9 to 9796f64 Compare July 8, 2026 12:01
@dnplkndll dnplkndll changed the title fix(pg): $N * INTERVAL float8 cast + pending-delete cleanup DELETE syntax fix(pg): SCEP renewal + Windows MDM cleanup/re-enrollment SQL on PostgreSQL Jul 8, 2026
@dnplkndll dnplkndll merged commit 885ce07 into feat/pg-compat-rebased Jul 8, 2026
5 checks passed
@dnplkndll dnplkndll deleted the pg-fix-interval-mult-and-pending-delete branch July 8, 2026 14:44
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