Compare commits

...
Author SHA1 Message Date
Sonarly Claude Code 904f17e1e7 Hardcoded join column name derivation breaks for renamed relation fields in nested queries
https://sonarly.com/issue/14017?type=bug

The nested relations processor derives join column names from field names (`${name}Id`) instead of using the authoritative `settings.joinColumnName`, causing TypeORM `EntityPropertyNotFoundError` when these diverge.

Fix: Changed `fieldMetadataTargetRelationColumnName` computation in `process-nested-relations-v2.helper.ts` to use `targetRelation?.settings?.joinColumnName` for ALL relation types (not just MORPH_RELATION), with `${targetRelationName}Id` retained as a fallback.

**Before:** The code only read `settings.joinColumnName` for `MORPH_RELATION` types, and for regular `RELATION` types it derived the column name from the field name (`${targetRelationName}Id`). This assumption breaks when a relation field's `name` diverges from its `joinColumnName` (e.g., after renaming a custom relation field — the `name` changes but the database column name in `settings.joinColumnName` correctly stays the same).

**After:** Uses `targetRelation?.settings?.joinColumnName ?? ${targetRelationName}Id` — the same pattern already used 3 lines above for the source-side relation (`sourceFieldMetadata.settings.joinColumnName ?? ${sourceFieldName}Id`). This ensures the TypeORM select uses the actual database column name registered in the entity schema, not a derived guess from the field name.

The fix also simplifies the code by removing the now-unnecessary MORPH_RELATION type check, since `settings.joinColumnName` is the correct source of truth for both RELATION and MORPH_RELATION types.
2026-03-12 23:37:21 +00:00
@@ -195,13 +195,8 @@ export class ProcessNestedRelationsV2Helper {
});
const fieldMetadataTargetRelationColumnName =
targetRelation &&
isFieldMetadataEntityOfType(
targetRelation,
FieldMetadataType.MORPH_RELATION,
)
? `${targetRelation.settings?.joinColumnName}`
: `${targetRelationName}Id`;
targetRelation?.settings?.joinColumnName ??
`${targetRelationName}Id`;
const { relationResults, relationAggregatedFieldsResult } =
await this.findRelations({