Skip to content

Fix: Update attachments in BE instead of cloning record - #8400

Open
CarolineDenis wants to merge 5 commits into
mainfrom
issue-8298
Open

Fix: Update attachments in BE instead of cloning record#8400
CarolineDenis wants to merge 5 commits into
mainfrom
issue-8298

Conversation

@CarolineDenis

@CarolineDenis CarolineDenis commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Fixes #8298

Changes

  • Added explicit identity-preservation support through the upload pipeline.
  • Added schema support so plans containing preserveIdentity validate.

Checklist

  • Self-review the PR after opening it to make sure the changes look good and
    self-explanatory (or properly documented)
  • Add relevant issue to release milestone
  • Add pr to documentation list
  • Add automated tests
  • Add a reverse migration if a migration is present in the PR
  • Add migration function to
    def fix_schema_config(stdout: WriteToStdOut | None = None):

Testing instructions

Notes:
Attachments were cloned because:

In upload_table.py:986:

  1. In update mode, non-one-to-one related records go through process_row unless preserveIdentity is set.
  • See BoundUpdateTable._process_to_ones.
  • Without preserveIdentity, attachment went down the process_row path, not save_row(force=True).
  1. process_row does match-first, then upload if no match.
  • See BoundUploadTable._handle_row and BoundUploadTable._match.
  • In that upload path, if current_id exists, upload means clone, not update.
  1. See BoundUploadTable._do_upload and BoundUploadTable._do_clone.

So when we changed attachment fields, the old record often no longer matched the match predicate, and the fallback was “create via clone” from current_id, which produced duplicate attachments.

For many non-one-to-one relationships, Specify treats records as potentially reusable/shared and avoids unconditional in-place mutation, that conservative default is useful broadly.

==> preserveIdentity flips that specific to-one node from match/clone semantics to forced in-place save when there is an existing id

Next

A better long-term model is an explicit per-node update strategy in the upload plan.
Each table instance in the relationship graph explicitly declares how updates should behave, instead of relying on one global default.

Summary by CodeRabbit

  • Bug Fixes

    • Fixed batch edits for existing attachment records, preserving their identities and relationships.
    • Attachment updates now keep record counts stable and maintain audit history.
    • Improved one-to-one upload handling to update existing records when configured.
  • New Features

    • Upload plans now support optional identity preservation settings for upload tables and related records.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

Warning

One or more dependencies are approaching or past End-of-Life.
Please plan upgrades accordingly.

STATUS=WARNING
NODE_VERSION=20
NODE_CYCLE=20
EOL_DATE=2026-04-30
DAYS_REMAINING=-97

--- Node.js ---
Version: 20
EOL: 2026-04-30
Status: WARNING

STATUS=OK
PYTHON_VERSION=3.12
PYTHON_CYCLE=3.12
EOL_DATE=2028-10-31
DAYS_REMAINING=818

--- Python ---
Version: 3.12
EOL: 2028-10-31
Status: OK

STATUS=WARNING
DJANGO_VERSION=4.2
DJANGO_CYCLE=4.2
EOL_DATE=2026-04-07
DAYS_REMAINING=-120

--- Django ---
Version: 4.2
EOL: 2026-04-07
Status: WARNING


@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c3e01843-c204-4a52-a9a4-21cbc38f79e3

📥 Commits

Reviewing files that changed from the base of the PR and between 752d6fe and 6582a9f.

📒 Files selected for processing (5)
  • specifyweb/backend/stored_queries/batch_edit.py
  • specifyweb/backend/workbench/upload/scoping.py
  • specifyweb/backend/workbench/upload/tests/test_batch_edit_table.py
  • specifyweb/backend/workbench/upload/upload_plan_schema.py
  • specifyweb/backend/workbench/upload/upload_table.py

📝 Walkthrough

Walkthrough

Changes

Attachment identity preservation

Layer / File(s) Summary
Upload identity contract
specifyweb/backend/workbench/upload/upload_plan_schema.py, specifyweb/backend/workbench/upload/upload_table.py, specifyweb/backend/workbench/upload/scoping.py
Upload plans accept preserveIdentity. The flag propagates through parsing, serialization, scoping, and binding.
Attachment in-place updates
specifyweb/backend/stored_queries/batch_edit.py, specifyweb/backend/workbench/upload/upload_table.py
Attachment tables enable identity preservation. Existing one-to-one records use in-place updates when the flag and current integer identity are present.
Attachment batch-edit validation
specifyweb/backend/workbench/upload/tests/test_batch_edit_table.py
Tests cover attachment updates through collection-object queries, direct attachment queries, and dataset commits. They verify retained identities, relationships, counts, titles, and audit entries.

Possibly related PRs

Suggested reviewers: alesan99, g1rly-c0d3r

🚥 Pre-merge checks | ✅ 6 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Testing Instructions ⚠️ Warning The Testing instructions section contains only template comments, but the change affects upload planning, schema parsing, and three attachment batch-edit flows. Add runnable test commands and steps for relationship and direct Attachment edits, dataset commit, preserveIdentity validation, ID/count/link preservation, and audit logging.
✅ 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 directly addresses the main objective: enabling in-place attachment updates through the backend instead of record duplication.
Linked Issues check ✅ Passed The PR implements the required fix for issue #8298 by adding preserveIdentity support to prevent attachment record duplication and preserve Edit History.
Out of Scope Changes check ✅ Passed All changes directly support the core objective of enabling identity preservation for attachment updates; no unrelated modifications are present.
Description check ✅ Passed The PR objectives clearly explain the purpose, linked issue, and technical approach without excessive detail.
Automatic Tests ✅ Passed PR includes comprehensive automatic tests: three new test methods in test_batch_edit_table.py covering attachment updates through collection-object relationship, direct attachment table queries,...
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-8298

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.

@CarolineDenis

Copy link
Copy Markdown
Contributor Author

@CodeRabbit full review

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 📋Back Log

Development

Successfully merging this pull request may close these issues.

Batch editing an attachment record does not edit the record and instead duplicates it

1 participant