Skip to content

fix: transaction commit fails when indexes are dropped mid-transaction#3673

Merged
robfrank merged 1 commit into
mainfrom
fix/failing-tests-on-main
Mar 17, 2026
Merged

fix: transaction commit fails when indexes are dropped mid-transaction#3673
robfrank merged 1 commit into
mainfrom
fix/failing-tests-on-main

Conversation

@robfrank

Copy link
Copy Markdown
Collaborator

Summary

  • TransactionIndexContext: commit() and addFilesToLock() threw SchemaException when iterating index entries that referenced indexes dropped during the same transaction (e.g., via dropType()). Now pruned before processing.
  • MCPConfiguration: isUserAllowed() threw NPE when called with a null username. Added null guard.

Test plan

  • DropIndexTest.dropAndRecreateTypeWithIndex — passes (was failing)
  • TruncateClassStatementExecutionTest.truncateClass — passes (was failing)
  • MCPPermissionsTest.mcpNullUserNotAllowed — passes (was failing)
  • All other tests in those classes still pass

🤖 Generated with Claude Code

TransactionIndexContext.commit() and addFilesToLock() threw SchemaException
when iterating index entries that referenced indexes dropped during the same
transaction (e.g. via dropType). Now pruned before processing.

Also fix NPE in MCPConfiguration.isUserAllowed() when username is null.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, 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 addresses critical stability issues related to transaction management and user permission checks. It ensures that database transactions can commit successfully even when indexes are dropped mid-transaction, and it fortifies the user permission system against null input, thereby enhancing the overall robustness and reliability of the system.

Highlights

  • Transaction Index Handling: Modified TransactionIndexContext to correctly handle index entries and file locking when indexes are dropped within the same transaction, preventing SchemaException.
  • Null Username Handling: Added a null guard to MCPConfiguration.isUserAllowed() to prevent NullPointerException when a null username is provided.

🧠 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.

Changelog
  • engine/src/main/java/com/arcadedb/database/TransactionIndexContext.java
    • Added a step in commit() to remove entries for indexes that no longer exist in the schema, preventing errors during transaction finalization.
    • Introduced a check in addFilesToLock() to skip indexes that were dropped during the transaction, avoiding attempts to lock non-existent indexes.
  • server/src/main/java/com/arcadedb/server/mcp/MCPConfiguration.java
    • Implemented a null check at the beginning of isUserAllowed() to gracefully handle cases where a null username is passed, returning false instead of throwing a NullPointerException.
Activity
  • Verified DropIndexTest.dropAndRecreateTypeWithIndex now passes.
  • Confirmed TruncateClassStatementExecutionTest.truncateClass now passes.
  • Ensured MCPPermissionsTest.mcpNullUserNotAllowed now passes.
  • Validated that all other tests within the affected classes continue to pass.
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.

@claude

claude Bot commented Mar 17, 2026

Copy link
Copy Markdown

Code Review

Good, targeted fix for two independent bugs. The changes are minimal, defensive, and well-tested. A few observations:

TransactionIndexContext — commit() (line 168)

indexEntries.keySet().removeIf(indexName -> !database.getSchema().existsIndex(indexName));

Correct placement. The prune happens before checkUniqueIndexKeys(), which calls database.getSchema().getIndexByName(...) without null/existence guards — so this ordering is load-bearing. If the order were reversed, those private methods could still throw SchemaException.

Alternative worth considering: removeIndex(String indexName) already exists (line 147) as a public method to clean up stale entries. If the schema's dropType()/dropIndex() were made to call it proactively, the defensive removeIf in commit() wouldn't be needed. That said, the current defensive approach is safe and handles cases where callers forget to do so, so it's a fine solution.

Minor: The removeIf modifies indexEntries as a side-effect of commit(). It's harmless since indexEntries.clear() is called at the end of commit() regardless, but worth being aware of.

TransactionIndexContext — addFilesToLock() (line 230)

if (!schema.existsIndex(indexName))
    continue;

Correct. Independently prevents SchemaException in this method, which is called on a separate code path from commit(). The redundancy between this guard and the removeIf in commit() is fine — addFilesToLock() may be called before commit().

MCPConfiguration — isUserAllowed() (line 174)

if (username == null)
    return false;

Correct. Without this, username.startsWith("apitoken:") at line 180 would throw NPE. Note: CopyOnWriteArrayList.contains(null) would not itself throw, so the NPE was only triggered when the wildcard check failed and execution reached the startsWith call — making it a latent bug rather than an always-crash. The fix is correct and follows the security principle of denying access on ambiguous/invalid input.

Test Coverage

All three fixes have regression tests (dropAndRecreateTypeWithIndex, TruncateClassStatementExecutionTest.truncateClass, mcpNullUserNotAllowed). The MCP test is minimal but sufficient. The dropAndRecreateTypeWithIndex test exercises the real scenario (insert records → commit → drop sub-type → continue in same transaction), which is good.

Summary

The PR is correct and well-scoped. The two bug categories (transaction lifecycle and null-safety) are unrelated but grouping minor fixes together is pragmatic. No issues blocking merge.

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

Copy link
Copy Markdown
Contributor

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 effectively addresses two critical issues. The TransactionIndexContext now correctly handles scenarios where indexes are dropped mid-transaction, preventing SchemaException during commit and file locking operations. Additionally, a NullPointerException in MCPConfiguration.isUserAllowed() has been resolved by adding a null check for the username parameter. These changes significantly improve the stability and robustness of the system.

Comment on lines +230 to +232
if (!schema.existsIndex(indexName))
// INDEX WAS DROPPED DURING THE TRANSACTION (e.g. TYPE DROP), SKIP IT
continue;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

While the logic is correct, it is generally considered best practice in Java to always use curly braces {} with if statements, even for single-line bodies. This improves readability and prevents potential bugs if more statements are added later.

For example:

if (!schema.existsIndex(indexName)) {
  // INDEX WAS DROPPED DURING THE TRANSACTION (e.g. TYPE DROP), SKIP IT
  continue;
}
Suggested change
if (!schema.existsIndex(indexName))
// INDEX WAS DROPPED DURING THE TRANSACTION (e.g. TYPE DROP), SKIP IT
continue;
if (!schema.existsIndex(indexName)) {
// INDEX WAS DROPPED DURING THE TRANSACTION (e.g. TYPE DROP), SKIP IT
continue;
}

Comment on lines +174 to +175
if (username == null)
return false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Similar to the previous comment, it's a good practice to use curly braces {} with if statements for consistency and to prevent future errors, even for single-line conditions.

For example:

if (username == null) {
  return false;
}
Suggested change
if (username == null)
return false;
if (username == null) {
return false;
}

@mergify

mergify Bot commented Mar 17, 2026

Copy link
Copy Markdown
Contributor

🧪 CI Insights

Here's what we observed from your CI run for 01c2058.

🟢 All jobs passed!

But CI Insights is watching 👀

@robfrank
robfrank merged commit 364e0a0 into main Mar 17, 2026
22 of 26 checks passed
@codacy-production

Copy link
Copy Markdown

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
-8.83% 100.00%
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (4b82425) 109877 81322 74.01%
Head commit (01c2058) 140832 (+30955) 91794 (+10472) 65.18% (-8.83%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#3673) 5 5 100.00%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

@codecov

codecov Bot commented Mar 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 65.73%. Comparing base (4b82425) to head (01c2058).
⚠️ Report is 7 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3673      +/-   ##
==========================================
+ Coverage   65.20%   65.73%   +0.52%     
==========================================
  Files        1550     1550              
  Lines      109877   109888      +11     
  Branches    22936    22940       +4     
==========================================
+ Hits        71645    72231     +586     
+ Misses      28581    27948     -633     
- Partials     9651     9709      +58     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

robfrank added a commit that referenced this pull request May 12, 2026
mergify Bot added a commit that referenced this pull request May 24, 2026
Bumps [pg](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg) from 8.20.0 to 8.21.0.
Changelog

*Sourced from [pg's changelog](https://github.com/brianc/node-postgres/blob/master/CHANGELOG.md).*

> pg@8.21.0
> ---------
>
> * Handle [SASL SCRAM](https://redirect.github.com/brianc/node-postgres/pull/3521) server error responses properly.
> * Add support for [node@26](https://redirect.github.com/brianc/node-postgres/pull/3667).
> * Add `scramMaxIterations` [config option](https://redirect.github.com/brianc/node-postgres/pull/3677).
> * Add `client.getTransactionStatus()` [method](https://redirect.github.com/brianc/node-postgres/pull/3645).


Commits

* [`544b1ce`](brianc/node-postgres@544b1ce) Publish
* [`cc03fa5`](brianc/node-postgres@cc03fa5) Add scramMaxIterations option to limit SCRAM iteration count ([#3677](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg/issues/3677))
* [`f776327`](brianc/node-postgres@f776327) Remove compatibility code for unsupported versions of Node (<16) ([#3678](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg/issues/3678))
* [`f252870`](brianc/node-postgres@f252870) cleanup: pg utils ([#3675](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg/issues/3675))
* [`c8da6ab`](brianc/node-postgres@c8da6ab) Assorted test cleanup ([#3673](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg/issues/3673))
* [`fa47e73`](brianc/node-postgres@fa47e73) fix: `Client#end` callback being called multiple times when first is no-op (#...
* [`88a7e60`](brianc/node-postgres@88a7e60) cleanup: Move declaration to more natural place
* [`2095247`](brianc/node-postgres@2095247) cleanup: Combine duplicated code in `Client#query` and avoid unneeded early n...
* [`0ac3edd`](brianc/node-postgres@0ac3edd) fix: apply SASLprep (RFC 4013) to passwords before SCRAM-SHA-256 PBKDF2 ([#3669](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg/issues/3669))
* [`be880d4`](brianc/node-postgres@be880d4) Assorted test fixes and cleanup ([#3672](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg/issues/3672))
* Additional commits viewable in [compare view](https://github.com/brianc/node-postgres/commits/pg@8.21.0/packages/pg)
  
[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility\_score?dependency-name=pg&package-manager=npm\_and\_yarn&previous-version=8.20.0&new-version=8.21.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
Dependabot commands and options
  
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot show  ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
tae898 pushed a commit to humemai/arcadedb-embedded-python that referenced this pull request Jun 28, 2026
tae898 pushed a commit to humemai/arcadedb-embedded-python that referenced this pull request Jun 28, 2026
Bumps [pg](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg) from 8.20.0 to 8.21.0.
Changelog

*Sourced from [pg's changelog](https://github.com/brianc/node-postgres/blob/master/CHANGELOG.md).*

> pg@8.21.0
> ---------
>
> * Handle [SASL SCRAM](https://redirect.github.com/brianc/node-postgres/pull/3521) server error responses properly.
> * Add support for [node@26](https://redirect.github.com/brianc/node-postgres/pull/3667).
> * Add `scramMaxIterations` [config option](https://redirect.github.com/brianc/node-postgres/pull/3677).
> * Add `client.getTransactionStatus()` [method](https://redirect.github.com/brianc/node-postgres/pull/3645).


Commits

* [`544b1ce`](brianc/node-postgres@544b1ce) Publish
* [`cc03fa5`](brianc/node-postgres@cc03fa5) Add scramMaxIterations option to limit SCRAM iteration count ([ArcadeData#3677](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg/issues/3677))
* [`f776327`](brianc/node-postgres@f776327) Remove compatibility code for unsupported versions of Node (<16) ([ArcadeData#3678](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg/issues/3678))
* [`f252870`](brianc/node-postgres@f252870) cleanup: pg utils ([ArcadeData#3675](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg/issues/3675))
* [`c8da6ab`](brianc/node-postgres@c8da6ab) Assorted test cleanup ([ArcadeData#3673](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg/issues/3673))
* [`fa47e73`](brianc/node-postgres@fa47e73) fix: `Client#end` callback being called multiple times when first is no-op (#...
* [`88a7e60`](brianc/node-postgres@88a7e60) cleanup: Move declaration to more natural place
* [`2095247`](brianc/node-postgres@2095247) cleanup: Combine duplicated code in `Client#query` and avoid unneeded early n...
* [`0ac3edd`](brianc/node-postgres@0ac3edd) fix: apply SASLprep (RFC 4013) to passwords before SCRAM-SHA-256 PBKDF2 ([ArcadeData#3669](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg/issues/3669))
* [`be880d4`](brianc/node-postgres@be880d4) Assorted test fixes and cleanup ([ArcadeData#3672](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg/issues/3672))
* Additional commits viewable in [compare view](https://github.com/brianc/node-postgres/commits/pg@8.21.0/packages/pg)
  
[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility\_score?dependency-name=pg&package-manager=npm\_and\_yarn&previous-version=8.20.0&new-version=8.21.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
Dependabot commands and options
  
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot show  ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
@lvca
lvca deleted the fix/failing-tests-on-main branch July 3, 2026 20:19
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.

1 participant