Skip to content

Conversation

@brfrn169
Copy link
Collaborator

Description

This PR changes the behavior of Snapshot.putIntoWriteSet() when a Put (Insert/Upsert/Update) operation is performed on a record that was previously deleted within the same transaction.

Previous behavior

  • Threw IllegalArgumentException when Put was called after Delete on the same record

New behavior

  • Moves the record from deleteSet to writeSet
  • Sets null values for non-key columns that are not explicitly specified in the Put operation (since Delete clears all column values)
  • Disables insert mode (since the record previously existed, the operation should be treated as an update)
  • Enables implicit pre-read for proper preparation

Use case

This change enables scenarios where a user wants to delete a record and then insert/upsert a new record with the same key within a single transaction, which is a common pattern in "replace" operations.

Related issues and/or PRs

N/A

Changes made

  • Snapshot.java: Modified putIntoWriteSet() to handle Put after Delete
  • CoreError.java: Removed unused error code CONSENSUS_COMMIT_WRITING_ALREADY_DELETED_DATA_NOT_ALLOWED
  • SnapshotTest.java: Added/updated unit tests for the new behavior
  • CommitHandlerTest.java, CommitHandlerWithGroupCommitTest.java: Updated method signatures to propagate CrudException
  • Integration tests: Updated tests to verify the new behavior instead of expecting exceptions

Checklist

The following is a best-effort checklist. If any items in this checklist are not applicable to this PR or are dependent on other, unmerged PRs, please still mark the checkboxes after you have read and understood each item.

  • I have commented my code, particularly in hard-to-understand areas.
  • I have updated the documentation to reflect the changes.
  • I have considered whether similar issues could occur in other products, components, or modules if this PR is for bug fixes.
  • Any remaining open issues linked to this PR are documented and up-to-date (Jira, GitHub, etc.).
  • Tests (unit, integration, etc.) have been added for the changes.
  • My changes generate no new warnings.
  • Any dependent changes in other PRs have been merged and published.

Additional notes (optional)

N/A

Release notes

Changed the behavior of Consensus Commit transactions to allow Insert/Upsert/Update operations after Delete on the same record within the same transaction. Previously, this operation threw an IllegalArgumentException, but now it properly handles the case by treating it as a new record insertion with null values for unspecified columns.

@brfrn169 brfrn169 self-assigned this Jan 22, 2026
Copilot AI review requested due to automatic review settings January 22, 2026 08:15
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @brfrn169, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the flexibility of Consensus Commit transactions by modifying the behavior when a Put operation is attempted on a record that has already been deleted within the same transaction. Previously, this sequence of operations would result in an IllegalArgumentException. The new implementation intelligently handles this scenario by moving the record from the transaction's delete set to its write set, automatically nullifying unspecified non-key columns, disabling insert mode to treat it as an update, and enabling implicit pre-reads. This change streamlines "replace" operations, allowing users to delete and then re-insert or upsert records with the same key within a single, atomic transaction.

Highlights

  • Flexible Transaction Operations: Consensus Commit transactions now permit Put (Insert/Upsert/Update) operations on records that were previously deleted within the same transaction, removing a previous IllegalArgumentException.
  • Automated Nullification: When a Put follows a Delete for the same record, any non-key columns not explicitly specified in the Put operation are automatically set to null, ensuring data consistency.
  • Operation Reinterpretation: Such Put operations are automatically treated as updates (insert mode disabled) and implicit pre-reads are enabled to correctly reflect the record's state after deletion and before the new Put.
  • Enhanced "Replace" Patterns: This change directly supports common "replace" patterns where a record is logically deleted and then re-inserted or updated with the same key within a single atomic transaction.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a significant and beneficial change to the Consensus Commit transaction model, allowing Put operations to follow Delete operations on the same record within a single transaction. This addresses a common 'replace' use case and enhances the flexibility of the transaction API. The implementation correctly handles the state transition by moving the record from the delete set to the write set, setting unspecified columns to null, disabling insert mode, and enabling implicit pre-read for proper preparation. The refactoring of createNullColumn into ScalarDbUtils improves code reusability and maintainability. All unit and integration tests have been updated to reflect the new behavior, ensuring correctness and consistency. The changes are well-implemented and align with the stated goals of the pull request.

Copy link
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

This pull request modifies the Consensus Commit transaction behavior to allow Put (Insert/Upsert/Update) operations after Delete on the same record within a single transaction. Previously, this operation would throw an IllegalArgumentException.

Changes:

  • Modified Snapshot.putIntoWriteSet() to move records from deleteSet to writeSet when Put is called after Delete, with automatic null-setting for unspecified non-key columns
  • Extracted createNullColumn() utility method to ScalarDbUtils for reuse across the codebase
  • Removed unused error code CONSENSUS_COMMIT_WRITING_ALREADY_DELETED_DATA_NOT_ALLOWED from CoreError.java

Reviewed changes

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

Show a summary per file
File Description
core/src/main/java/com/scalar/db/transaction/consensuscommit/Snapshot.java Modified putIntoWriteSet() to handle Put after Delete by moving records from deleteSet to writeSet with null columns for unspecified fields
core/src/main/java/com/scalar/db/util/ScalarDbUtils.java Added createNullColumn() utility method to create null columns for all supported data types
core/src/main/java/com/scalar/db/transaction/consensuscommit/MergedResult.java Refactored to use ScalarDbUtils.createNullColumn() instead of private getNullColumn() method
core/src/main/java/com/scalar/db/common/CoreError.java Removed unused error code CONSENSUS_COMMIT_WRITING_ALREADY_DELETED_DATA_NOT_ALLOWED
core/src/test/java/com/scalar/db/transaction/consensuscommit/SnapshotTest.java Updated tests to verify new behavior with comprehensive test cases for Put after Delete scenarios
core/src/test/java/com/scalar/db/transaction/consensuscommit/CommitHandlerTest.java Updated method signatures to propagate CrudException
core/src/test/java/com/scalar/db/transaction/consensuscommit/CommitHandlerWithGroupCommitTest.java Updated method signatures to propagate CrudException
integration-test/src/main/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitIntegrationTestBase.java Updated integration tests to verify Put after Delete produces correct results with null columns
integration-test/src/main/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitSpecificIntegrationTestBase.java Updated integration tests to verify new behavior instead of expecting exceptions
integration-test/src/main/java/com/scalar/db/transaction/consensuscommit/TwoPhaseConsensusCommitSpecificIntegrationTestBase.java Updated integration tests to verify new behavior instead of expecting exceptions

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

@brfrn169 brfrn169 force-pushed the allow-put-after-delete-in-consensus-commit branch from 1c612b7 to 79fd3a2 Compare January 23, 2026 07:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant