Skip to content

fix: preserve original FK value when identity lookup misses#1738

Merged
gugu merged 1 commit into
mainfrom
feature/fix-fk-empty-object-fallback
Apr 27, 2026
Merged

fix: preserve original FK value when identity lookup misses#1738
gugu merged 1 commit into
mainfrom
feature/fix-fk-empty-object-fallback

Conversation

@gugu
Copy link
Copy Markdown
Contributor

@gugu gugu commented Apr 25, 2026

GetTableRowsUseCase was overwriting null and orphaned foreign key values with {} because the merge step's else branch assigned an empty object whenever the identity lookup map missed. Null FKs (filtered out before the identity query) and orphaned FKs (referenced row deleted) both trigger this path, silently destroying the original cell value.

Fall back to the original cell value instead, so null stays null and orphaned ids are preserved as primitives.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed API response handling for foreign key fields when the foreign key is NULL or contains an orphaned (invalid) reference. The API now correctly preserves these original values instead of converting them to empty objects.

GetTableRowsUseCase was overwriting null and orphaned foreign key values
with `{}` because the merge step's else branch assigned an empty object
whenever the identity lookup map missed. Null FKs (filtered out before
the identity query) and orphaned FKs (referenced row deleted) both
trigger this path, silently destroying the original cell value.

Fall back to the original cell value instead, so null stays null and
orphaned ids are preserved as primitives.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 25, 2026 12:29
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 25, 2026

📝 Walkthrough

Walkthrough

These changes address foreign-key handling in the table rows API when FK metadata exists but the FK value is NULL or orphaned. The logic now preserves the original FK value instead of substituting an empty object, with a corresponding end-to-end test validating this behavior.

Changes

Cohort / File(s) Summary
Foreign Key Value Preservation
backend/src/entities/table/use-cases/get-table-rows.use.case.ts, backend/test/ava-tests/complex-table-tests/complex-postgres-table-e2e.test.ts
Updated FK substitution logic to preserve original FK values when identity lookup fails or returns a non-object result (NULL or orphaned FKs), instead of substituting empty objects. Added comprehensive E2E test covering valid, NULL, and orphaned FK states.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A foreign key once lost would vanish away,
Now preserved in its orphaned state it will stay,
No empty objects to masquerade,
Just NULL and true values, forever displayed! 🔑

🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main fix: preserving the original FK value when identity lookup fails, which is the core change across both modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Security Check ✅ Passed The pull request preserves foreign key values from trusted database sources with proper type checking and maintains existing permission controls without introducing security risks.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/fix-fk-empty-object-fallback

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes FK cell-value corruption in GetTableRowsUseCase when the identity lookup doesn’t return a match (e.g., NULL FKs filtered out of the identity query, or orphaned FK values), ensuring the original FK value is preserved instead of being replaced with {}.

Changes:

  • Update FK identity-merge logic to fall back to the original row value when the lookup map misses.
  • Add a Postgres E2E test covering both NULL FK and orphaned FK scenarios to prevent regressions.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
backend/src/entities/table/use-cases/get-table-rows.use.case.ts Preserves original FK value on identity lookup miss (keeps null and orphaned IDs intact).
backend/test/ava-tests/complex-table-tests/complex-postgres-table-e2e.test.ts Adds regression test ensuring NULL/orphaned FK values aren’t converted to empty objects.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
backend/test/ava-tests/complex-table-tests/complex-postgres-table-e2e.test.ts (1)

255-332: Consider cleaning up FKBugFix_Parent / FKBugFix_Child after the test.

The test creates two custom tables and a NOT VALID FK constraint but never drops them. The leading dropTableIfExists makes reruns idempotent, but the artifacts persist in the shared test DB after the suite completes and will appear in any later test that enumerates tables on the same connection (e.g. GET /connection/tables/:connectionId - Should list all complex test tables in connection at line 1004 — currently safe because it only asserts inclusion, but the coupling is fragile).

♻️ Proposed cleanup
 		// Bug: previously these were assigned `{}`. Both should preserve the original value.
 		t.is(nullRow.parent_id, null, 'null FK must remain null, not be converted to {}');
 		t.is(orphanRow.parent_id, orphanedParentId, 'orphaned FK must keep its raw value, not become {}');
+
+		await knex.schema.dropTableIfExists(childTableName);
+		await knex.schema.dropTableIfExists(parentTableName);
 	},
 );

For stronger guarantees against test failures leaking state, wrap the body in try { … } finally { await knex.schema.dropTableIfExists(childTableName); await knex.schema.dropTableIfExists(parentTableName); }.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@backend/test/ava-tests/complex-table-tests/complex-postgres-table-e2e.test.ts`
around lines 255 - 332, Wrap the test body in a try { … } finally { … } using
the existing knex and the parentTableName/childTableName variables so the
cleanup always runs; in the finally block call await
knex.schema.dropTableIfExists(childTableName) and await
knex.schema.dropTableIfExists(parentTableName) (or additionally drop the FK
constraint via knex.raw if you prefer) to remove FKBugFix_Child and
FKBugFix_Parent regardless of test success.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@backend/test/ava-tests/complex-table-tests/complex-postgres-table-e2e.test.ts`:
- Around line 255-332: Wrap the test body in a try { … } finally { … } using the
existing knex and the parentTableName/childTableName variables so the cleanup
always runs; in the finally block call await
knex.schema.dropTableIfExists(childTableName) and await
knex.schema.dropTableIfExists(parentTableName) (or additionally drop the FK
constraint via knex.raw if you prefer) to remove FKBugFix_Child and
FKBugFix_Parent regardless of test success.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ec742a4c-e6e8-4a24-b8d5-c72b0836113a

📥 Commits

Reviewing files that changed from the base of the PR and between eeb1622 and 07654b6.

📒 Files selected for processing (2)
  • backend/src/entities/table/use-cases/get-table-rows.use.case.ts
  • backend/test/ava-tests/complex-table-tests/complex-postgres-table-e2e.test.ts

@gugu gugu merged commit ae90d17 into main Apr 27, 2026
22 of 23 checks passed
@gugu gugu deleted the feature/fix-fk-empty-object-fallback branch April 27, 2026 08:47
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