Skip to content

fix(#4278): lockFilesInOrder silently continues on compaction-induced file migration - #4279

Merged
robfrank merged 5 commits into
mainfrom
fix/4278-lockfilesinorder-silent-migration
May 21, 2026
Merged

fix(#4278): lockFilesInOrder silently continues on compaction-induced file migration#4279
robfrank merged 5 commits into
mainfrom
fix/4278-lockfilesinorder-silent-migration

Conversation

@robfrank

Copy link
Copy Markdown
Collaborator

Closes #4278

Summary

TransactionContext.lockFilesInOrder() silently fell through when getMigratedFileId() returned a non-null value (i.e., when a file had been migrated by LSM index compaction). This left the new mutable file unlocked during the commit, allowing concurrent transactions to race on the same index file without proper serialization.

The sibling path checkExplicitLocks() already handled this correctly by throwing ConcurrentModificationException. This PR makes lockFilesInOrder() mirror that behavior: unlock all files, rollback the transaction, emit a FINE log identifying the old and new file IDs, and throw with a migration-specific message so callers can retry.

The fix is a minimal three-line structural change: always unlock+rollback first when any file is missing, then distinguish "migrated" from "simply removed" to produce the right exception message.

Test plan

  • New regression test LockFilesInOrderFileMigrationTest: creates a type with a small-page LSM index, inserts 1000 records to fill multiple mutable pages, begins a transaction that injects the pre-compaction mutable file ID into modifiedPages, runs compaction from a background thread to trigger file migration, then commits and asserts ConcurrentModificationException is thrown with a message containing "migrated".
  • ConcurrentCompactionTest (3 tests) - all pass
  • ExplicitLockingTransactionTest (5 tests) - all pass
  • LSMTreeIndexCompactionTest (5 tests) - all pass
  • Test fails on the pre-fix code (throws from checkPageVersion with "does not exist anymore", not from lockFilesInOrder with "migrated") and passes with the fix applied.

… file migration

TransactionContext.lockFilesInOrder() now mirrors checkExplicitLocks() behavior
when a locked file has been migrated by LSM index compaction: unlock, rollback,
emit a FINE log identifying the old and new file IDs, and throw
ConcurrentModificationException with a migration-specific message so callers can
retry the transaction.

Previously the method silently fell through when getMigratedFileId() returned
non-null, leaving the new mutable file unlocked during the commit and allowing
concurrent writes to race on the same index file.

Includes a regression test that injects the pre-compaction mutable file ID into
a transaction's modifiedPages, runs compaction from a background thread, then
asserts the commit throws the migration-specific ConcurrentModificationException.
@codacy-production

codacy-production Bot commented May 21, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Coverage 85.71% diff coverage · -7.84% coverage variation

Metric Results
Coverage variation -7.84% coverage variation
Diff coverage 85.71% diff coverage

View coverage diff in Codacy

Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (26eeb40) 127474 93959 73.71%
Head commit (473fef5) 159154 (+31680) 104830 (+10871) 65.87% (-7.84%)

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 (#4279) 7 6 85.71%

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%

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@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 addresses issue #4278, where TransactionContext.lockFilesInOrder() would silently continue if a locked file was migrated during LSM index compaction, potentially leading to data loss. The fix ensures that a ConcurrentModificationException is thrown when a migration is detected, providing a descriptive error message and ensuring proper rollback. The changes include the fix in TransactionContext.java, a new regression test, and documentation. Review feedback suggests using getEmbedded() instead of an explicit cast to LocalSchema for consistency.

throw new ConcurrentModificationException("File with id '" + f + "' has been removed");
database.getTransactionManager().unlockFilesInOrder(locked, getRequester());
rollback();
final Integer migrated = ((LocalSchema) database.getSchema()).getMigratedFileId(f);

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

For consistency with other parts of this class (e.g., lines 143 and 665) and to avoid an explicit cast, it is preferred to use the getEmbedded() method on the schema to access LocalSchema specific methods.

Suggested change
final Integer migrated = ((LocalSchema) database.getSchema()).getMigratedFileId(f);
final Integer migrated = database.getSchema().getEmbedded().getMigratedFileId(f);

@claude

claude Bot commented May 21, 2026

Copy link
Copy Markdown

Code Review

Overview

This PR fixes a genuine bug in TransactionContext.lockFilesInOrder(): when a locked file was missing due to LSM compaction-induced file migration, the original code fell through silently (leaving the new mutable file unlocked during commit). The fix restructures the block so unlock+rollback always runs first, then distinguishes the migration vs. plain-removal cases to produce the right exception. This mirrors the behavior of the sibling checkExplicitLocks() path.

The fix is correct, minimal, and well-targeted.


The Fix (TransactionContext.java)

Correct. Moving unlockFilesInOrder + rollback before the null-check eliminates the silent fallthrough. Both exception paths now properly release locks and roll back before throwing - callers using database.transaction() will retry automatically on ConcurrentModificationException, and direct begin()/commit() callers now receive the retryable exception they were previously denied.

Pre-existing double-rollback - the outer catch at line 709-710 also calls rollback() after catching ConcurrentModificationException. This was already the case for the "file removed without migration" branch before this PR, so it is not introduced here, and rollback() must be safe to call twice (idempotent). Still worth noting to future readers.

Minor style inconsistency - the new log call uses an explicit null Throwable:

LogManager.instance().log(this, Level.FINE, "Found upgraded file '%d' to '%d' during transaction commit", null, f, migrated);

The sibling checkExplicitLocks() call skips the Throwable parameter entirely and uses the non-Throwable overload:

LogManager.instance().log(this, Level.FINE, "Found upgraded file '%d' to '%d' during transaction lock", f, newFileId);

Both are correct (different overloads, same result), but the inconsistency is distracting. Consider dropping the explicit null to match the sibling style.


Test (LockFilesInOrderFileMigrationTest.java)

Good test. The approach is sound - inject a stale file ID via getPageToModify, compact from a background thread with a CountDownLatch barrier, commit on the main thread, assert the exception. This reliably exercises the exact race without depending on real concurrency timing.

Suggestion: use assertThatThrownBy for the exception assertion. Per project style (CLAUDE.md prefers AssertJ assertions), the idiomatic form is:

assertThatThrownBy(() -> database.commit())
    .isInstanceOf(ConcurrentModificationException.class)
    .hasMessageContaining("migrated");

This replaces the try/catch + null-variable pattern and is more readable.


Docs file (docs/4278-lockfilesinorder-silent-migration.md)

The analysis document is thorough and useful for understanding the root cause, but the project convention says documentation files should not be created unless explicitly requested. The content is already well-covered by the PR description - consider dropping this file or merging its content into the commit message instead.


Summary

Bug fix correctness Correct - silent fallthrough eliminated
Behavior parity with sibling Achieved
Test coverage Good regression test, reliably reproducible
Minor issues Log style inconsistency; exception assertion style; docs file convention

The core change is solid. The two small suggestions (log style + assertThatThrownBy) are optional polish. Ready to merge after addressing (or knowingly skipping) those points.

@claude

claude Bot commented May 21, 2026

Copy link
Copy Markdown

Code Review - PR #4279: lockFilesInOrder silently continues on compaction-induced file migration

Summary

This PR fixes a real correctness bug in TransactionContext.lockFilesInOrder(). Before the fix, when getMigratedFileId() returned a non-null value (meaning a file had been migrated by LSM index compaction), the method fell through silently without locking the new mutable file, potentially allowing concurrent transactions to race on the same index file without proper serialization. The fix makes lockFilesInOrder() mirror the behavior of checkExplicitLocks(): unlock all files, rollback the transaction, log at FINE, and throw ConcurrentModificationException with a descriptive message.

Positive aspects

  • The fix is minimal and precisely targeted.
  • The unlock+rollback happens unconditionally before the migration check, which is correct. Previously the "no migration" branch did unlock+rollback+throw while the "has migration" branch fell through silently. The reordering is clean.
  • The exception message is descriptive and actionable, naming both the old and new file IDs.
  • The new test correctly exercises the actual code path by injecting the old mutable file ID into modifiedPages using the real getPageToModify API, rather than mocking.
  • Using a CountDownLatch and AtomicReference<Throwable> for the background compaction thread is idiomatic and correct.
  • The pre/post compaction state assertions (migration entry present, old file gone) serve as useful intermediate checkpoints.
  • TestHelper.afterTest() safely handles the rolled-back transaction: since lockFilesInOrder calls rollback() before throwing, the database.commit() guard in afterTest() is not triggered.
  • License header is present and correct. Follows final keyword conventions on parameters and local variables.

Issues found

1. Em dash in an error message (test). The project style guide says not to use the em dash character (-). The test uses it in an AssertionError message:

compactionError.set(new AssertionError("compact() returned false — mutable must have >= 2 pages"));

Use a regular dash or a comma instead.

2. Inconsistent LocalSchema access style. The fix in lockFilesInOrder uses:

database.getSchema().getEmbedded().getMigratedFileId(f)

The sibling method checkExplicitLocks uses:

((LocalSchema) database.getSchema()).getMigratedFileId(f)

Since getMigratedFileId is not on the Schema interface, both styles ultimately reach LocalSchema. The getEmbedded() approach avoids the explicit cast and is cleaner - consider normalising checkExplicitLocks to use getEmbedded() as well for consistency.

3. Inconsistent LogManager.log call signature. The new log line passes null explicitly as the Throwable argument:

LogManager.instance().log(this, Level.FINE, "...", null, f, migrated);

The existing sibling log at line 936 uses the two-arg overload without a throwable:

LogManager.instance().log(this, Level.FINE, "...", f, newFileId);

The new line should use the same overload as the existing one to remain consistent.

4. Exception capture pattern in the test. The test uses a manual try/catch to capture the exception:

ConcurrentModificationException thrown = null;
try {
  database.commit();
} catch (final ConcurrentModificationException e) {
  thrown = e;
}
assertThat(thrown).as("...").isNotNull();
assertThat(thrown.getMessage()).contains("migrated");

The idiomatic AssertJ pattern used elsewhere in this codebase is assertThatThrownBy:

assertThatThrownBy(() -> database.commit())
    .isInstanceOf(ConcurrentModificationException.class)
    .hasMessageContaining("migrated");

This is cleaner, avoids the mutable thrown variable, and gives a better failure message when no exception is thrown.

5. Documentation file in the tree. The docs/4278-lockfilesinorder-silent-migration.md file appears to be an internal design note added to document reasoning. The project guidelines say not to proactively create documentation files. Consider removing it - the relevant context belongs in the PR description or the linked issue rather than the repository tree.

Correctness assessment

The core fix is correct and safe. The unlock-before-check reordering eliminates the window where the new mutable file was unlocked during commit. The ConcurrentModificationException thrown is already handled by the retry machinery in database.transaction() lambdas, so callers using that API are unaffected. Direct begin()/commit() callers now receive a clear, retryable exception rather than silent continuation.

The test reliably exercises the fixed code path. The 30-second timeout on compactionDone.await is generous and appropriate.

Overall assessment

The fix is correct, well-scoped, and includes a solid regression test. The items above are polish/style concerns - the em dash, the assertThatThrownBy pattern, and the documentation file are the items most worth addressing before merge.

@claude

claude Bot commented May 21, 2026

Copy link
Copy Markdown

Code Review

Overview

This PR fixes a real correctness bug in TransactionContext.lockFilesInOrder(): when a locked file was missing because LSM compaction had migrated it to a new file ID, the original code fell through silently, leaving the new mutable file unlocked during commit. The fix restructures the guard block so unlock+rollback always runs first, then distinguishes migration from plain removal to produce the right exception. This correctly mirrors the sibling checkExplicitLocks() path.

The fix is correct and minimal.


TransactionContext.java

Structurally correct. Moving unlockFilesInOrder + rollback before the null-check means both exception paths now clean up properly before throwing. Callers using database.transaction() will retry automatically on ConcurrentModificationException; direct begin()/commit() callers now receive the retryable exception they were silently denied before.

Minor: drop the explicit null Throwable argument. The new log call (line 909) uses:

LogManager.instance().log(this, Level.FINE, "Found upgraded file '%d' to '%d' during transaction commit", null, f, migrated);

The sibling call in checkExplicitLocks() (line 936) uses the two-arg overload without a Throwable:

LogManager.instance().log(this, Level.FINE, "Found upgraded file '%d' to '%d' during transaction lock", f, newFileId);

Both overloads work, but passing an explicit null Throwable is inconsistent with the rest of the file. Prefer dropping the null to match the sibling style.

Pre-existing inconsistency (not introduced here): checkExplicitLocks() at line 933 still uses the old cast style ((LocalSchema) database.getSchema()).getMigratedFileId(f) while the new code at line 907 correctly uses database.getSchema().getEmbedded(). Since this pre-dates the PR it does not block merge, but that line is worth cleaning up in a follow-on.

Pre-existing double-rollback (not introduced here): The outer catch at line 709-710 calls rollback() again after catching ConcurrentModificationException. This was already true for the plain-removal branch before this PR, so rollback() is evidently idempotent; no action needed.


LockFilesInOrderFileMigrationTest.java

Sound test design. The approach - inject a stale file ID via getPageToModify, compact from a background thread behind a CountDownLatch, then commit on the main thread - exercises the exact race without relying on real timing. The precondition assertions (>= 2 pages, migration entry present, old file gone) make setup failures obvious rather than silent.

Suggestion: use assertThatThrownBy for the exception assertion. The test uses a manual try/catch + null check, which is valid but not the idiomatic AssertJ style the project prefers. The idiomatic form:

assertThatThrownBy(database::commit)
    .isInstanceOf(ConcurrentModificationException.class)
    .hasMessageContaining("migrated");

This is shorter, avoids the thrown == null trap, and matches the style encouraged by the project.

Consider @Tag("slow") if compaction plus a 1000-record insert takes noticeably long on CI. Probably fine, but worth validating on a slow machine.


docs/4278-lockfilesinorder-silent-migration.md

The "Review cycles" section documents bot response times and loop timeouts - this is ephemeral workflow metadata, not reference documentation. It will be stale immediately after merge. The technical root-cause analysis and fix description are genuinely useful, but the review-cycle tracking belongs in the PR description rather than the repo's docs/ folder. Consider trimming that section before merging.


Summary

Area Assessment
Bug fix correctness Correct - the silent fallthrough is eliminated
Exception message quality Good - includes both old and new file IDs, actionable hint
Test reliability Good - deterministic injection, no timing dependency
Style Minor: drop null Throwable arg; use assertThatThrownBy in test
Docs file Trim the review-cycle metadata before merge

No blocking issues. The fix is safe to merge after addressing the minor style points.

…rim doc

- TransactionContext: drop explicit null Throwable arg to match the
  no-Throwable LogManager.log overload used by sibling checkExplicitLocks
- LockFilesInOrderFileMigrationTest: use assertThatThrownBy idiom instead
  of manual try/catch + null check
- docs/4278: drop ephemeral review-cycle metadata, keep technical
  description and PR cross-reference
@claude

claude Bot commented May 21, 2026

Copy link
Copy Markdown

Code Review

The fix is correct and well-motivated. The bug is real: the original lockFilesInOrder silently fell through when getMigratedFileId() returned non-null, leaving the new mutable file unlocked and open to concurrent writes. The restructuring (always unlock+rollback first, then distinguish migration from removal) mirrors checkExplicitLocks correctly.

Issues to address

1. License header typo in LockFilesInOrderFileMigrationTest.java (line 18)

STML-License-Identifier: Apache-2.0

should be:

SPDX-License-Identifier: Apache-2.0

2. Inconsistency in getMigratedFileId call style

The new code in lockFilesInOrder uses:

database.getSchema().getEmbedded().getMigratedFileId(f)

while the sibling method checkExplicitLocks still uses:

((LocalSchema) database.getSchema()).getMigratedFileId(f)

Both call sites should use the same pattern. Since getEmbedded() is the cleaner approach (no cast), checkExplicitLocks should be updated to match, or a note should explain the intentional difference.

3. docs file belongs elsewhere

docs/4278-lockfilesinorder-silent-migration.md contains issue-specific analysis that is better captured in the GitHub issue/PR description (where it already lives in full). Adding per-issue design docs to the source tree creates clutter that doesn't age well. The high-level rationale from this file should live in the issue/PR, not as a committed file.

4. Multi-line class-level Javadoc on the test

The test class carries a 7-line Javadoc block. The project style is one short line max (or none). The method name already conveys the scenario - the existing comment would be better reduced to a single short sentence or removed entirely.

Minor observations

  • The for loop in lockFilesInOrder always throws on the first missing file, so calling unlockFilesInOrder(locked, ...) from inside the same iteration is safe (execution never continues). The logic is correct.
  • The getPageToModify(..., false) followed by writeByte(0, readByte(0)) to force a dirty page is a reasonable injection point for a regression test, but it is inherently coupled to internal commit mechanics. A comment explaining why the read-modify-write is needed (to pass the range[1] > 0 gate in commit1stPhase) would help future readers - the existing inline comment partially covers this but could be tightened.
  • The isGreaterThanOrEqualTo(2) pre-condition assertion is good defensive test design.

Summary

The core fix is sound and minimal (3 lines changed, matching existing conventions). Address the license typo and the getMigratedFileId call-style inconsistency before merging; the docs-file concern is lower priority but worth discussing.

…le migration

putDuplicates wraps database.commit() inside assertThatThrownBy(...), so the
outer transaction's NeedRetryException handling never engages. The test was
passing on main only because the (now-fixed) silent fallthrough in
lockFilesInOrder swallowed file migrations and let the duplicate check still
run inside indexChanges.commit().

With #4278's fix, lockFilesInOrder correctly throws ConcurrentModificationException
when a file is migrated by an async compaction mid-test, so the duplicate check
never executes and the assertion fails.

Disable auto-compaction for the duration of the test: drain queued async
compactions, force a sync compaction (so the post-split mutable reads the
disabled config), then run the duplicate-detection loop. The test now exercises
the same behavior it always intended without depending on the old silent
fallthrough.
@claude

claude Bot commented May 21, 2026

Copy link
Copy Markdown

Code Review

Overview

This PR fixes a real concurrency bug: lockFilesInOrder() silently fell through when a file had been migrated by LSM compaction, leaving the new mutable index file unguarded during commit. The fix is structurally correct - always unlock and rollback first, then distinguish migration from plain removal. The accompanying regression test and putDuplicates stabilisation are both well-reasoned.


Issues

1. API inconsistency in getMigratedFileId call style

lockFilesInOrder() (line 907) now uses:

database.getSchema().getEmbedded().getMigratedFileId(f);

But checkExplicitLocks() (line 933) still uses the old cast form:

((LocalSchema) database.getSchema()).getMigratedFileId(f);

These two sibling methods should use the same pattern. Since getEmbedded() already avoids the cast and is used elsewhere in TransactionContext (lines 143-144, 665, 907), checkExplicitLocks() should be updated to match.

2. Docs file should not be committed

docs/4278-lockfilesinorder-silent-migration.md is a planning/decision document that duplicates the PR description and the in-code comments. Per project guidelines, such artifacts do not belong in the repository - the information is already preserved in git history and the PR body. This file will become stale as soon as the code evolves.

3. Multi-paragraph comment block in putDuplicates

The block comment added at the top of the try block in LSMTreeIndexTest.putDuplicates is a multi-paragraph explanation. Project guidelines say to keep comments to one short line when the why is non-obvious. The key point - "disable auto-compaction to prevent ConcurrentModificationException from interfering with DuplicatedKeyException assertion" - can fit in one line. The rest describes the mechanism rather than the constraint.


Positive aspects

  • Fix is minimal and correct. The 3-line restructuring in lockFilesInOrder() is the right shape: unlock + rollback always come first (preventing any window where files are left locked after detecting a bad state), then the exception message distinguishes migration from removal.
  • No double-unlock risk. rollback() calls reset() which only unlocks this.lockedFiles and this.explicitLockedFiles. Since the throw happens before lockFilesInOrder() returns, this.lockedFiles is never set to the (already-unlocked) locked list - the paths don't conflict.
  • Regression test is well-structured. CountDownLatch + AtomicReference<Throwable> is the right pattern for asserting background thread outcomes. The test correctly verifies that migration state exists and the old file is gone before committing, then asserts the exception message contains "migrated" rather than just the exception type.
  • putDuplicates config restore is correct. The finally block guarantees the original INDEX_COMPACTION_MIN_PAGES_SCHEDULE value is always restored, even on test failure.
  • Exception message is actionable. "file 'X' has been migrated to 'Y' (likely by an index compaction). Please retry the operation." gives callers the old and new IDs and explicitly signals retryability - better than the previous generic "file has been removed".

Summary

The fix and test are sound. Three things to address before merging:

  1. Update checkExplicitLocks() line 933 to use database.getSchema().getEmbedded().getMigratedFileId(f) for consistency with lockFilesInOrder().
  2. Delete docs/4278-lockfilesinorder-silent-migration.md.
  3. Collapse the multi-paragraph comment in putDuplicates to a single line.

@codecov

codecov Bot commented May 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 71.42857% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.17%. Comparing base (26eeb40) to head (473fef5).

Files with missing lines Patch % Lines
...java/com/arcadedb/database/TransactionContext.java 71.42% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #4279      +/-   ##
============================================
- Coverage     64.54%   64.17%   -0.38%     
- Complexity      445      453       +8     
============================================
  Files          1645     1645              
  Lines        127474   127476       +2     
  Branches      27324    27324              
============================================
- Hits          82280    81803     -477     
- Misses        33546    34146     +600     
+ Partials      11648    11527     -121     

☔ 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
robfrank merged commit 6e4de2c into main May 21, 2026
34 of 43 checks passed
@robfrank
robfrank deleted the fix/4278-lockfilesinorder-silent-migration branch May 21, 2026 21:29
tae898 pushed a commit to humemai/arcadedb-embedded-python that referenced this pull request Jun 28, 2026
mergify Bot added a commit that referenced this pull request Jul 8, 2026
…skip ci]

Bumps [org.postgresql:postgresql](https://github.com/pgjdbc/pgjdbc) from 42.7.12 to 42.7.13.
Release notes

*Sourced from [org.postgresql:postgresql's releases](https://github.com/pgjdbc/pgjdbc/releases).*

> v42.7.13
> --------
>
> Changes
> -------
>
> * docs: add 42.7.13 release changelog [`@​davecramer`](https://github.com/davecramer) ([#4270](https://redirect.github.com/pgjdbc/pgjdbc/issues/4270))
> * Adjust EditorConfig für Makefile [`@​BaumiCoder`](https://github.com/BaumiCoder) ([#4279](https://redirect.github.com/pgjdbc/pgjdbc/issues/4279))
> * fix(scram): fail closed on channel-binding downgrade (no scram bump) [`@​vlsi`](https://github.com/vlsi) ([#4272](https://redirect.github.com/pgjdbc/pgjdbc/issues/4272))
> * Bump pgjdbc version from 42.7.12 to 42.7.13 [`@​davecramer`](https://github.com/davecramer) ([#4269](https://redirect.github.com/pgjdbc/pgjdbc/issues/4269))
> * chore: remove test-anorm-sbt module and its disabled CI wiring [`@​vlsi`](https://github.com/vlsi) ([#4261](https://redirect.github.com/pgjdbc/pgjdbc/issues/4261))
> * refactor(test-gss): convert to Java/JUnit 5 submodule of the main build [`@​vlsi`](https://github.com/vlsi) ([#4166](https://redirect.github.com/pgjdbc/pgjdbc/issues/4166))
> * ci: derive PG test versions from a Renovate-managed maxPgVersion [`@​vlsi`](https://github.com/vlsi) ([#4218](https://redirect.github.com/pgjdbc/pgjdbc/issues/4218))
> * feat(insert): cap reWriteBatchedInserts by the protocol limit, not 128 [`@​vlsi`](https://github.com/vlsi) ([#4207](https://redirect.github.com/pgjdbc/pgjdbc/issues/4207))
> * refactor(metadata): derive getPrimaryKeys from pg\_constraint.conkey [`@​vlsi`](https://github.com/vlsi) ([#4202](https://redirect.github.com/pgjdbc/pgjdbc/issues/4202))
> * fix(protocol): defer flushes until response processing [`@​vlsi`](https://github.com/vlsi) ([#4196](https://redirect.github.com/pgjdbc/pgjdbc/issues/4196))
> * fix(build): resolve the Temurin 8 test toolchain by vendor [`@​vlsi`](https://github.com/vlsi) ([#4257](https://redirect.github.com/pgjdbc/pgjdbc/issues/4257))
> * build: include multi-release source sets in the JaCoCo coverage report [`@​vlsi`](https://github.com/vlsi) ([#4256](https://redirect.github.com/pgjdbc/pgjdbc/issues/4256))
> * fix(ci): read java\_vendor before overwriting java\_distribution [`@​vlsi`](https://github.com/vlsi) ([#4255](https://redirect.github.com/pgjdbc/pgjdbc/issues/4255))
> * ci: generate the whole matrix in one batch, coverage job included [`@​vlsi`](https://github.com/vlsi) ([#4253](https://redirect.github.com/pgjdbc/pgjdbc/issues/4253))
> * ci: pass CODECOV\_TOKEN so protected-branch coverage uploads succeed [`@​vlsi`](https://github.com/vlsi) ([#4254](https://redirect.github.com/pgjdbc/pgjdbc/issues/4254))
> * ci: collect coverage on one pinned job [`@​vlsi`](https://github.com/vlsi) ([#4245](https://redirect.github.com/pgjdbc/pgjdbc/issues/4245))
> * ci: apply -DqueryTimeout from the matrix query\_timeout axis [`@​vlsi`](https://github.com/vlsi) ([#4246](https://redirect.github.com/pgjdbc/pgjdbc/issues/4246))
> * ci: make Codecov project and patch statuses informational [`@​vlsi`](https://github.com/vlsi) ([#4244](https://redirect.github.com/pgjdbc/pgjdbc/issues/4244))
> * fix(build): restore JaCoCo XML report so Codecov receives coverage [`@​vlsi`](https://github.com/vlsi) ([#4240](https://redirect.github.com/pgjdbc/pgjdbc/issues/4240))
> * test(replication): shrink big-transaction inserts to avoid CI timeouts [`@​vlsi`](https://github.com/vlsi) ([#4243](https://redirect.github.com/pgjdbc/pgjdbc/issues/4243))
> * update maintainers [`@​davecramer`](https://github.com/davecramer) ([#4222](https://redirect.github.com/pgjdbc/pgjdbc/issues/4222))
> * test: add hermetic test for localSocketAddress [`@​vlsi`](https://github.com/vlsi) ([#4224](https://redirect.github.com/pgjdbc/pgjdbc/issues/4224))
> * docs(translation): clean up leftover German header in ja.po [`@​vlsi`](https://github.com/vlsi) ([#4206](https://redirect.github.com/pgjdbc/pgjdbc/issues/4206))
> * Update ja.po [`@​davecramer`](https://github.com/davecramer) ([#2004](https://redirect.github.com/pgjdbc/pgjdbc/issues/2004))
> * test: add PostgreSQL 18 to the CI test matrix [`@​vlsi`](https://github.com/vlsi) ([#4198](https://redirect.github.com/pgjdbc/pgjdbc/issues/4198))
> * test: silence expected SSPI warning stack trace in SSPIClientWaffleTest [`@​vlsi`](https://github.com/vlsi) ([#4197](https://redirect.github.com/pgjdbc/pgjdbc/issues/4197))
> * fix(ssl): build PKIX trust anchors without a KeyStore so FIPS-mode JVMs can load sslrootcert [`@​vlsi`](https://github.com/vlsi) ([#4193](https://redirect.github.com/pgjdbc/pgjdbc/issues/4193))
> * test: fix flaky sentLocationEqualToLastReceiveLSN replication test [`@​vlsi`](https://github.com/vlsi) ([#4175](https://redirect.github.com/pgjdbc/pgjdbc/issues/4175))
> * build: promote MethodCanBeStatic to error level [`@​vlsi`](https://github.com/vlsi) ([#4172](https://redirect.github.com/pgjdbc/pgjdbc/issues/4172))
> * Fix PGInterval.setSeconds to reject out of range and NaN values [`@​sehrope`](https://github.com/sehrope) ([#4194](https://redirect.github.com/pgjdbc/pgjdbc/issues/4194))
> * Replace connectThreadFactory with connectExecutor [`@​sehrope`](https://github.com/sehrope) ([#4165](https://redirect.github.com/pgjdbc/pgjdbc/issues/4165))
> * Fix deleting temp file when spooling large stream to disk in StreamWrapper [`@​sehrope`](https://github.com/sehrope) ([#4190](https://redirect.github.com/pgjdbc/pgjdbc/issues/4190))
> * chore: Add top level /scratch to gitignore [`@​sehrope`](https://github.com/sehrope) ([#4164](https://redirect.github.com/pgjdbc/pgjdbc/issues/4164))
> * refactor: favour composition over inheritance for Driver.ConnectTask [`@​vlsi`](https://github.com/vlsi) ([#4160](https://redirect.github.com/pgjdbc/pgjdbc/issues/4160))
> * Fix NumberParser.getFastLong(...) handling of overlong values [`@​sehrope`](https://github.com/sehrope) ([#4163](https://redirect.github.com/pgjdbc/pgjdbc/issues/4163))
> * build: produce a multi-release jar from reduced-pom.xml on Java 11+ [`@​vlsi`](https://github.com/vlsi) ([#4157](https://redirect.github.com/pgjdbc/pgjdbc/issues/4157))
> * Add connectThreadFactory and refactor Driver to use FutureTask for loginTimeout connection attempts [`@​sehrope`](https://github.com/sehrope) ([#4120](https://redirect.github.com/pgjdbc/pgjdbc/issues/4120))
> * test: verify custom properties reach socket factory [`@​vlsi`](https://github.com/vlsi) ([#4125](https://redirect.github.com/pgjdbc/pgjdbc/issues/4125))
> * test: fix LazyCleanerTest timeouts for the lingering Java 8 cleanup thread [`@​vlsi`](https://github.com/vlsi) ([#4122](https://redirect.github.com/pgjdbc/pgjdbc/issues/4122))
> * test: stabilise StatementTest.fastCloses on Windows [`@​vlsi`](https://github.com/vlsi) ([#4121](https://redirect.github.com/pgjdbc/pgjdbc/issues/4121))
> * fix: append default non-proxy hosts when socksNonProxyHosts is set [`@​davecramer`](https://github.com/davecramer) ([#4045](https://redirect.github.com/pgjdbc/pgjdbc/issues/4045))
> * test: budget terminating Sync in BatchDeadlockTest small-RETURNING branch [`@​vlsi`](https://github.com/vlsi) ([#4116](https://redirect.github.com/pgjdbc/pgjdbc/issues/4116))
> * test: make message assertions locale-independent [`@​vlsi`](https://github.com/vlsi) ([#4113](https://redirect.github.com/pgjdbc/pgjdbc/issues/4113))
> * build: drop xgettext default keywords; regenerate translations [`@​vlsi`](https://github.com/vlsi) ([#4100](https://redirect.github.com/pgjdbc/pgjdbc/issues/4100))
> * ci: opt-in scheduled workflows via ENABLE\_SCHEDULED\_JOBS repo variable [`@​vlsi`](https://github.com/vlsi) ([#4085](https://redirect.github.com/pgjdbc/pgjdbc/issues/4085))
> * Avoid direct java.lang.management dependency in maxResultBuffer parser [`@​mblakley-casana`](https://github.com/mblakley-casana) ([#4069](https://redirect.github.com/pgjdbc/pgjdbc/issues/4069))
> * fix: restore pre-describe for generated-key batches [`@​bilalshehata`](https://github.com/bilalshehata) ([#4014](https://redirect.github.com/pgjdbc/pgjdbc/issues/4014))

... (truncated)


Changelog

*Sourced from [org.postgresql:postgresql's changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md).*

> [42.7.13] (2026-07-06)
> ----------------------
>
> ### Added
>
> * feat: invalidate the prepared-statement cache when the server reports a `search_path` change via GUC\_REPORT (PostgreSQL 18+), so cached plans are no longer used against the wrong schema [PR [#4259](https://redirect.github.com/pgjdbc/pgjdbc/issues/4259)]([pgjdbc/pgjdbc#4259](https://redirect.github.com/pgjdbc/pgjdbc/pull/4259))
> * feat: `reWriteBatchedInserts` now merges up to 32768 rows into one multi-values `INSERT` (bounded by the 65535 bind-parameter limit on the extended protocol) instead of capping at 128, which speeds up batches of few-column rows. The new `reWriteBatchedInsertsSize` connection property lowers that cap when set; the default of `0` uses that maximum. [PR [#4207](https://redirect.github.com/pgjdbc/pgjdbc/issues/4207)]([pgjdbc/pgjdbc#4207](https://redirect.github.com/pgjdbc/pgjdbc/pull/4207))
> * feat: invalidate the prepared-statement cache after CREATE/DROP/ALTER so callers no longer trip on "cached plan must not change result type" without opting into `autosave=ALWAYS`. Controlled by the new `flushCacheOnDdl` connection property (default `true`); set to `false` for the prior behaviour. [PR [#4067](https://redirect.github.com/pgjdbc/pgjdbc/issues/4067)]([pgjdbc/pgjdbc#4067](https://redirect.github.com/pgjdbc/pgjdbc/pull/4067))
> * feat: add `connectExecutor` connection property to customize the `Executor` used to run the worker task that performs the connection attempt when `loginTimeout` is in effect. The value is the fully qualified name of a class implementing `java.util.concurrent.Executor`. With a null value, the default, the driver retains the prior behavior of running the connection attempt on a daemon thread named `"PostgreSQL JDBC driver connection thread"`. The executor must run the task on a thread other than the caller's. Running the attempt on a named thread lets applications that monitor driver-created threads identify it. [PR [#4165](https://redirect.github.com/pgjdbc/pgjdbc/issues/4165)]([pgjdbc/pgjdbc#4165](https://redirect.github.com/pgjdbc/pgjdbc/pull/4165))
> * feat: add `classLoaderStrategy` connection property to control which classloaders the driver searches when loading a class named by a connection property, for example `socketFactory`. The default `driver-first` now falls back to the thread context classloader when the driver's classloader cannot resolve the class, which fixes class loading in non-flat class paths such as Quarkus and OSGi. Set `driver` to keep the previous driver-classloader-only behaviour, or `context-first` to prefer the thread context classloader [Issue [#2112](https://redirect.github.com/pgjdbc/pgjdbc/issues/2112)]([pgjdbc/pgjdbc#2112](https://redirect.github.com/pgjdbc/pgjdbc/issues/2112)) [PR [#4167](https://redirect.github.com/pgjdbc/pgjdbc/issues/4167)]([pgjdbc/pgjdbc#4167](https://redirect.github.com/pgjdbc/pgjdbc/pull/4167))
> * feat: add OID constants for geometric arrays, `RECORD`, and `refcursor` [PR [#4220](https://redirect.github.com/pgjdbc/pgjdbc/issues/4220)]([pgjdbc/pgjdbc#4220](https://redirect.github.com/pgjdbc/pgjdbc/pull/4220))
> * feat: `LargeObject` `BlobInputStream` now skips by seeking instead of reading, and the driver exposes the server version so it can select the 64-bit large-object API where available [PR [#4204](https://redirect.github.com/pgjdbc/pgjdbc/issues/4204)]([pgjdbc/pgjdbc#4204](https://redirect.github.com/pgjdbc/pgjdbc/pull/4204))
>
> ### Changed
>
> * refactor: the worker that runs the connection attempt under `loginTimeout` is now a `FutureTask` (`ConnectTask`) instead of the hand-rolled `ConnectThread`. When the caller hits the timeout, the task is now cancelled with `cancel(true)`, which interrupts the worker thread rather than letting it run to completion. This makes the connection attempt interruptible, so `loginTimeout` can stop a slow connection attempt instead of leaking a thread. As before, a connection that the worker still manages to establish after the caller gives up is closed by the worker so that it does not leak. There are no public API changes and this should only lead to faster background resource cleanup for connections that time out. [PR [#4120](https://redirect.github.com/pgjdbc/pgjdbc/issues/4120)]([pgjdbc/pgjdbc#4120](https://redirect.github.com/pgjdbc/pgjdbc/pull/4120))
> * chore: `PGXAConnection.ConnectionHandler` now rejects `setAutoCommit(false)` and `setSavepoint(...)` during an active XA branch, in addition to the long-rejected `setAutoCommit(true)` / `commit()` / `rollback()`. The `setSavepoint` rejection was already meant to be in place but the guard misspelled the method name as `setSavePoint`, so savepoints silently went through. Both changes bring the proxy in line with JTA 1.2 §3.4. [PR [#4114](https://redirect.github.com/pgjdbc/pgjdbc/issues/4114)]([pgjdbc/pgjdbc#4114](https://redirect.github.com/pgjdbc/pgjdbc/pull/4114))
> * chore: `commitPrepared` / `rollback`-of-prepared now return `XAER_RMFAIL` instead of `XAER_RMERR` when the underlying connection is left in a non-idle `TransactionState`. Transaction managers (Geronimo, Narayana, Atomikos) treat `XAER_RMFAIL` as retryable on a fresh `XAResource`; the prepared transaction is no longer abandoned. [PR [#4114](https://redirect.github.com/pgjdbc/pgjdbc/issues/4114)]([pgjdbc/pgjdbc#4114](https://redirect.github.com/pgjdbc/pgjdbc/pull/4114))
> * refactor: derive `getPrimaryKeys` from `pg_constraint.conkey` [PR [#4202](https://redirect.github.com/pgjdbc/pgjdbc/issues/4202)]([pgjdbc/pgjdbc#4202](https://redirect.github.com/pgjdbc/pgjdbc/pull/4202))
>
> ### Fixed
>
> * fix: the published GitHub release now ships the released `postgresql-<version>.jar` and its detached PGP signature, taken from the same signed build that is uploaded to Maven Central, instead of a leftover SNAPSHOT jar [Issue [#3812](https://redirect.github.com/pgjdbc/pgjdbc/issues/3812)]([pgjdbc/pgjdbc#3812](https://redirect.github.com/pgjdbc/pgjdbc/issues/3812)) [PR [#3814](https://redirect.github.com/pgjdbc/pgjdbc/issues/3814)]([pgjdbc/pgjdbc#3814](https://redirect.github.com/pgjdbc/pgjdbc/pull/3814))
> * fix: simplify the `Statement#cancel` state machine by dropping the redundant `CANCELLED` state. `killTimerTask` now waits for the state to return to `IDLE` directly, which removes a spin-forever case when more than one thread observes the cancel completing [PR [#1827](https://redirect.github.com/pgjdbc/pgjdbc/issues/1827)]([pgjdbc/pgjdbc#1827](https://redirect.github.com/pgjdbc/pgjdbc/pull/1827)).
> * perf: defer simple-query flushes until the driver reads the response, allowing `BEGIN` and the following query to share a network flush [Issue [#3894](https://redirect.github.com/pgjdbc/pgjdbc/issues/3894)]([pgjdbc/pgjdbc#3894](https://redirect.github.com/pgjdbc/pgjdbc/issues/3894)) [PR [#4196](https://redirect.github.com/pgjdbc/pgjdbc/issues/4196)]([pgjdbc/pgjdbc#4196](https://redirect.github.com/pgjdbc/pgjdbc/pull/4196))
> * fix: `reWriteBatchedInserts` no longer throws `IllegalArgumentException` when batching a parameterless `INSERT` (for example `INSERT INTO t VALUES (1, 2)`) of 256 rows or more [PR [#4207](https://redirect.github.com/pgjdbc/pgjdbc/issues/4207)]([pgjdbc/pgjdbc#4207](https://redirect.github.com/pgjdbc/pgjdbc/pull/4207))
> * fix: a comment before `CALL` in a `CallableStatement` no longer hides the native call, so OUT parameter registration works for `/* comment */ call proc(?, ?)` and similar. `Parser.modifyJdbcCall` now skips leading whitespace and SQL comments (both `--` and `/* */`) before the call, tolerates a trailing comment after a `{ ... }` escape, and no longer adds a spurious comma when moving an OUT parameter into a call whose arguments are only a comment [Issue [#2538](https://redirect.github.com/pgjdbc/pgjdbc/issues/2538)]([pgjdbc/pgjdbc#2538](https://redirect.github.com/pgjdbc/pgjdbc/issues/2538)) [PR [#4209](https://redirect.github.com/pgjdbc/pgjdbc/issues/4209)]([pgjdbc/pgjdbc#4209](https://redirect.github.com/pgjdbc/pgjdbc/pull/4209))
> * fix: `PreparedStatement.toString()` no longer throws for a `bytea` value supplied as text via `PGobject`. Hex-format values (`\x...`) are validated and rendered as a `bytea` literal, and escape-format values are quoted and cast like any other literal [Issue [#3757](https://redirect.github.com/pgjdbc/pgjdbc/issues/3757)]([pgjdbc/pgjdbc#3757](https://redirect.github.com/pgjdbc/pgjdbc/issues/3757)) [PR [#4201](https://redirect.github.com/pgjdbc/pgjdbc/issues/4201)]([pgjdbc/pgjdbc#4201](https://redirect.github.com/pgjdbc/pgjdbc/pull/4201))
> * fix: the driver no longer nulls the `contextClassLoader` of shared `ForkJoinPool.commonPool()` worker threads, which previously left unrelated tasks on those threads running with a `null` classloader [Issue [#4155](https://redirect.github.com/pgjdbc/pgjdbc/issues/4155)]([pgjdbc/pgjdbc#4155](https://redirect.github.com/pgjdbc/pgjdbc/issues/4155)) [PR [#4156](https://redirect.github.com/pgjdbc/pgjdbc/issues/4156)]([pgjdbc/pgjdbc#4156](https://redirect.github.com/pgjdbc/pgjdbc/pull/4156))
> * fix: `PgResultSet#getCharacterStream` wraps `String` in a `StringReader` [PR [#4063](https://redirect.github.com/pgjdbc/pgjdbc/issues/4063)]([pgjdbc/pgjdbc#4063](https://redirect.github.com/pgjdbc/pgjdbc/pull/4063))
> * fix: `PGXAConnection` no longer saves and restores the underlying connection's JDBC `autoCommit` flag. All XA-protocol SQL (`BEGIN`, `PREPARE TRANSACTION`, `COMMIT`, `ROLLBACK`, `COMMIT PREPARED`, `ROLLBACK PREPARED`, the `recover()` SELECT) is sent through `QUERY_SUPPRESS_BEGIN`, so the caller's `autoCommit` value is invariant across every `XAResource` call. Fixes the "2nd phase commit must be issued using an idle connection" failure during recovery on managed datasources that pool connections with `autoCommit=false` (TomEE, WildFly, WebSphere Liberty) [PR [#4114](https://redirect.github.com/pgjdbc/pgjdbc/issues/4114)]([pgjdbc/pgjdbc#4114](https://redirect.github.com/pgjdbc/pgjdbc/pull/4114))
> * fix: `PGXAConnection.prepare()` now mutates XA state only after `PREPARE TRANSACTION` succeeds. A failed `PREPARE` previously left the driver thinking the branch was already prepared, so the follow-up `rollback(xid)` tried `ROLLBACK PREPARED` against a non-existent gid and returned `XAER_RMERR`. Transaction managers (Narayana) escalated this to `HeuristicMixedException`. With the fix, `rollback(xid)` takes the active-branch path and issues a plain `ROLLBACK`, which the server accepts cleanly. Fixes [Issue [#3153](https://redirect.github.com/pgjdbc/pgjdbc/issues/3153)]([pgjdbc/pgjdbc#3153](https://redirect.github.com/pgjdbc/pgjdbc/issues/3153)), [Issue [#3123](https://redirect.github.com/pgjdbc/pgjdbc/issues/3123)]([pgjdbc/pgjdbc#3123](https://redirect.github.com/pgjdbc/pgjdbc/issues/3123)). [PR [#4114](https://redirect.github.com/pgjdbc/pgjdbc/issues/4114)]([pgjdbc/pgjdbc#4114](https://redirect.github.com/pgjdbc/pgjdbc/pull/4114))
> * fix: an updatable result set over an unqualified table name is now classified using only the table visible through `search_path`. When two schemas held a table with the same name and the same primary or unique index name but a different set of key columns, the driver took the union of both schemas' columns, so the result set could be wrongly rejected as not updatable [PR [#4214](https://redirect.github.com/pgjdbc/pgjdbc/issues/4214)]([pgjdbc/pgjdbc#4214](https://redirect.github.com/pgjdbc/pgjdbc/pull/4214)). Supersedes [PR [#3400](https://redirect.github.com/pgjdbc/pgjdbc/issues/3400)]([pgjdbc/pgjdbc#3400](https://redirect.github.com/pgjdbc/pgjdbc/pull/3400)).
> * fix: `LargeObject.close()` now flushes a buffered output stream before marking the object closed, so closing a large object without an explicit `flush()` no longer drops buffered writes. The flush runs while the object is still open (it calls back into `LargeObject.write()`), and `lo_close` always runs afterward; a failure from `lo_close` no longer masks an earlier flush error, and the transaction is not committed when the flush failed [Issue [#4247](https://redirect.github.com/pgjdbc/pgjdbc/issues/4247)]([pgjdbc/pgjdbc#4247](https://redirect.github.com/pgjdbc/pgjdbc/issues/4247)) [PR [#4248](https://redirect.github.com/pgjdbc/pgjdbc/issues/4248)]([pgjdbc/pgjdbc#4248](https://redirect.github.com/pgjdbc/pgjdbc/pull/4248)).
> * fix: reject empty `timestamp`, `timestamptz`, and `date` text with a clear `SQLException` (SQLState `22007`) instead of an `ArrayIndexOutOfBoundsException` [PR [#4278](https://redirect.github.com/pgjdbc/pgjdbc/issues/4278)]([pgjdbc/pgjdbc#4278](https://redirect.github.com/pgjdbc/pgjdbc/pull/4278))
> * fix: return null `CHAR_OCTET_LENGTH` for non-character columns [PR [#4231](https://redirect.github.com/pgjdbc/pgjdbc/issues/4231)]([pgjdbc/pgjdbc#4231](https://redirect.github.com/pgjdbc/pgjdbc/pull/4231))
> * fix: honor scale in `ResultSet.getBigDecimal(int, int)` [PR [#4211](https://redirect.github.com/pgjdbc/pgjdbc/issues/4211)]([pgjdbc/pgjdbc#4211](https://redirect.github.com/pgjdbc/pgjdbc/pull/4211))
> * fix: support `java.time` values in an updatable `ResultSet` `updateRow()` / `insertRow()` [PR [#3848](https://redirect.github.com/pgjdbc/pgjdbc/issues/3848)]([pgjdbc/pgjdbc#3848](https://redirect.github.com/pgjdbc/pgjdbc/pull/3848))
> * fix: improve batching when the `RETURNING` clause contains `varchar` or `numeric` types [PR [#4014](https://redirect.github.com/pgjdbc/pgjdbc/issues/4014)]([pgjdbc/pgjdbc#4014](https://redirect.github.com/pgjdbc/pgjdbc/pull/4014))
> * fix: correct `estimatedReceiveBufferBytes` accounting after a forced `Sync` [PR [#4014](https://redirect.github.com/pgjdbc/pgjdbc/issues/4014)]([pgjdbc/pgjdbc#4014](https://redirect.github.com/pgjdbc/pgjdbc/pull/4014))
> * fix: avoid creating a transient `ResultSet` for describe-statement purposes, and restore the pre-describe path for generated-key batches [PR [#4014](https://redirect.github.com/pgjdbc/pgjdbc/issues/4014)]([pgjdbc/pgjdbc#4014](https://redirect.github.com/pgjdbc/pgjdbc/pull/4014))
> * fix: add an explicit failure message when a multi-statement command executes in a batch [PR [#4014](https://redirect.github.com/pgjdbc/pgjdbc/issues/4014)]([pgjdbc/pgjdbc#4014](https://redirect.github.com/pgjdbc/pgjdbc/pull/4014))
> * fix: detect `search_path` changes case-insensitively [PR [#4216](https://redirect.github.com/pgjdbc/pgjdbc/issues/4216)]([pgjdbc/pgjdbc#4216](https://redirect.github.com/pgjdbc/pgjdbc/pull/4216))
> * fix: auto-detect the SSL key format instead of relying on the `.key` extension [PR [#3946](https://redirect.github.com/pgjdbc/pgjdbc/issues/3946)]([pgjdbc/pgjdbc#3946](https://redirect.github.com/pgjdbc/pgjdbc/pull/3946))
> * fix: build PKIX trust anchors without a `KeyStore` so FIPS JVMs work [PR [#4193](https://redirect.github.com/pgjdbc/pgjdbc/issues/4193)]([pgjdbc/pgjdbc#4193](https://redirect.github.com/pgjdbc/pgjdbc/pull/4193))
> * fix: use `gssResponseTimeout` rather than `sslResponseTimeout` for GSS connections [PR [#4076](https://redirect.github.com/pgjdbc/pgjdbc/issues/4076)]([pgjdbc/pgjdbc#4076](https://redirect.github.com/pgjdbc/pgjdbc/pull/4076))
> * fix: skip the autosave savepoint for `SET LOCAL` / `SET SESSION TRANSACTION` [PR [#4203](https://redirect.github.com/pgjdbc/pgjdbc/issues/4203)]([pgjdbc/pgjdbc#4203](https://redirect.github.com/pgjdbc/pgjdbc/pull/4203))
> * fix: do not throw `AssertionError` from `BatchResultHandler` on a closed connection [PR [#4187](https://redirect.github.com/pgjdbc/pgjdbc/issues/4187)]([pgjdbc/pgjdbc#4187](https://redirect.github.com/pgjdbc/pgjdbc/pull/4187))
> * fix: reject `SQL_TSI_FRAC_SECOND` with an explicit, explained error [PR [#4229](https://redirect.github.com/pgjdbc/pgjdbc/issues/4229)]([pgjdbc/pgjdbc#4229](https://redirect.github.com/pgjdbc/pgjdbc/pull/4229))
> * fix: reject a null URL in `Driver.acceptsURL` with a clear `NullPointerException` [PR [#4205](https://redirect.github.com/pgjdbc/pgjdbc/issues/4205)]([pgjdbc/pgjdbc#4205](https://redirect.github.com/pgjdbc/pgjdbc/pull/4205))
> * fix: reject overlong inputs in `NumberParser.getFastLong` instead of silently wrapping [PR [#4163](https://redirect.github.com/pgjdbc/pgjdbc/issues/4163)]([pgjdbc/pgjdbc#4163](https://redirect.github.com/pgjdbc/pgjdbc/pull/4163))
> * fix: reject out-of-range and NaN values in `PGInterval.setSeconds` [PR [#4194](https://redirect.github.com/pgjdbc/pgjdbc/issues/4194)]([pgjdbc/pgjdbc#4194](https://redirect.github.com/pgjdbc/pgjdbc/pull/4194))
> * fix: close the socket when `PgConnection` setup fails after connect [PR [#4161](https://redirect.github.com/pgjdbc/pgjdbc/issues/4161)]([pgjdbc/pgjdbc#4161](https://redirect.github.com/pgjdbc/pgjdbc/pull/4161))
> * fix: keep the `LazyCleanerImpl` cleanup task alive across a transient empty queue [PR [#4038](https://redirect.github.com/pgjdbc/pgjdbc/issues/4038)]([pgjdbc/pgjdbc#4038](https://redirect.github.com/pgjdbc/pgjdbc/pull/4038))

... (truncated)


Commits

* [`3297557`](pgjdbc/pgjdbc@3297557) docs: add 42.7.13 release changelog ([#4270](https://redirect.github.com/pgjdbc/pgjdbc/issues/4270))
* [`d93d370`](pgjdbc/pgjdbc@d93d370) style: apply Autostyle to docs/ and .github/
* [`2e05ff9`](pgjdbc/pgjdbc@2e05ff9) build: check docs/ and .github/ formatting with Autostyle
* [`b4a6087`](pgjdbc/pgjdbc@b4a6087) Adjust EditorConfig für Makefiles
* [`725cebb`](pgjdbc/pgjdbc@725cebb) fix(jdbc): reject empty timestamp/timestamptz text with a clear error
* [`23a1b0d`](pgjdbc/pgjdbc@23a1b0d) fix(scram): fail closed on channel-binding downgrade (no scram bump)
* [`0b4077a`](pgjdbc/pgjdbc@0b4077a) Bump pgjdbc version from 42.7.12 to 42.7.13 ([#4269](https://redirect.github.com/pgjdbc/pgjdbc/issues/4269))
* [`394800a`](pgjdbc/pgjdbc@394800a) fix: flush LargeObject output stream before marking closed ([#4248](https://redirect.github.com/pgjdbc/pgjdbc/issues/4248))
* [`83780f1`](pgjdbc/pgjdbc@83780f1) Maintain consistency with the use of the word maintainer vs comitter ([#4234](https://redirect.github.com/pgjdbc/pgjdbc/issues/4234))
* [`d42cad5`](pgjdbc/pgjdbc@d42cad5) fix(jdbc): classify updatable result set by search\_path visibility
* Additional commits viewable in [compare view](pgjdbc/pgjdbc@REL42.7.12...REL42.7.13)
  
[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility\_score?dependency-name=org.postgresql:postgresql&package-manager=maven&previous-version=42.7.12&new-version=42.7.13)](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)
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.

TransactionContext.lockFilesInOrder silently continues on compaction-induced file migration, while checkExplicitLocks (correctly) throws

1 participant