MemberJunction / MemberJunction/MJ
spDeleteEntityWithCoreDependencies covers ~18 of ~73 FK references to Entity — entity removal half-fails silently
- Dominant language
- TSQL
- Stars
- 29
- Forks
- 6
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 323
Description
## What
`spDeleteEntityWithCoreDependencies` is what CodeGen calls (via `checkAndRemoveMetadataForDeletedTables`, `packages/CodeGenLib/src/Database/manage-metadata.ts`) to prune an entity's metadata once its base table disappears. It cascades **~18** tables. The database currently has **~73** FK references to `Entity.ID`.
Anything not on the proc's list blocks the final `DELETE FROM Entity`, and the failure is caught and logged rather than raised:
```ts
catch (ex) {
logError(`Error removing metadata for entity ${(ex as any).Name}, error: ${ex}`);
}
```
## Why it matters
The entity is left **half-pruned** — the `Entity` row survives, but its `EntityField` rows are already gone. Every subsequent CodeGen run then emits:
```
SKIPPING SQL GENERATION: Entity has no primary key field in metadata.
```
...and that entity is silently excluded from generation from then on. The only signal is one grey log line in a long CodeGen run.
## How it was found
Phase 0 of the unified-workflow program (#3456) drops 11 entities. Ten pruned cleanly; `MJ: Scheduled Actions` did not, because 40 `ProcessRun` and 125 `ProcessRunDetail` rows referenced it. Neither table is in the proc — both postdate it (Record Set Processing).
The Phase 0 migration works around this by deleting the dangling rows itself for the entities it drops. That is a point fix, not the general one.
## Uncovered references (partial)
Beyond `ProcessRun` / `ProcessRunDetail`: `EntityAction` (`EntityID`, `ScopeEntityID`), `EntityFormOverride`, `EntityOrganicKey`, `EntityRecordDocument`, `QueryEntity`, `RecordProcess`, `RecordProcessWatermark`, `SearchScopeEntity`, `TaggedItem`, `TagScope`, `VersionLabel` / `VersionLabelItem`, `MLModelScoringBinding`, `MLTrainingPipeline`, `RecordLink`, `SignatureRequest`, `SystemEvent`, `ScopedPromptConfig` / `ScopedPromptPart`, and more.
## Suggested fix
1. Make the proc's cascade list exhaustive — each reference decided as delete-vs-null (nullable FKs like `ProcessRun.EntityID` could be nulled; non-nullable children must be deleted).
2. Consider generating the list from the FK graph instead of hand-maintaining it, so it cannot drift again.
3. Make the CodeGen caller **fail loudly** rather than log-and-continue, so a half-pruned entity can't slip through unnoticed.
Not attempted in #3456's Phase 0: fixing all ~55 uncovered references speculatively would be a large, under-tested change riding on an unrelated PR.
Contributor guide
Research direction
Start with spDeleteEntityWithCoreDependencies and its CodeGen entry point, checkAndRemoveMetadataForDeletedTables in packages/CodeGenLib/src/Database/manage-metadata.ts. Map the database's Entity.ID foreign-key references and compare them with the procedure's cascade list, then review the caller's catch-and-log behavior. Done means deletion handles every reference deliberately and a failed cleanup is surfaced instead of silently leaving partial metadata.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- sql, typescript
- Domain
- databases, tooling
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100