Skip to content

#4200 fix: [postgres] advertise Long scalar columns as INT8 to fix id() IN $array round-trip - #4201

Merged
robfrank merged 2 commits into
mainfrom
fix/e2e-python-failing-test
May 11, 2026
Merged

#4200 fix: [postgres] advertise Long scalar columns as INT8 to fix id() IN $array round-trip#4201
robfrank merged 2 commits into
mainfrom
fix/e2e-python-failing-test

Conversation

@robfrank

Copy link
Copy Markdown
Collaborator

Closes #4200

Summary

  • Cypher id() became Long-encoded in id()` may return record-id strings and break numeric predicates #4183, but the Postgres wire announced every non-array scalar column as VARCHAR. Postgres clients (psycopg, JDBC, SQLAlchemy, …) therefore deserialized id() values as strings, and when a client resent those strings as the IN $ids array parameter the Cypher engine compared Long(id(n)) against String("<decimal>") and silently returned 0 rows.
  • Fix at the wire layer in PostgresNetworkExecutor.getColumns(): advertise Long-valued scalar columns as INT8 so the round-trip preserves the numeric type. Other scalars stay VARCHAR for backward compatibility with existing clients.
  • The narrower comparator-side coercion (Long ↔ numeric string in InExpression / ComparisonExpression) is deliberately avoided - it would violate the Cypher TCK invariant that 5 IN ["5"] returns false (verified: 5 TCK regressions when attempted).

Test plan

  • Engine Issue4183IdInArrayParameterTest — 3 cases: Long list matches, RID-string list matches (legacy coercion), numeric-string list deliberately doesn't (TCK invariant)
  • OpenCypherWhereClauseTest$IdFunctionWithInOperatorRegression — 4 existing tests still pass
  • Issue4183IdFunctionNumericTest — 8 tests from id()` may return record-id strings and break numeric predicates #4183 still pass
  • OpenCypherTCKSuite — full 3944 tests, zero regressions
  • postgresw IT suite — all 100 tests pass, including the re-enabled PostgresWJdbcIT#cypherWithArrayParameterInClause (asserts both the INT8 column-type announcement and the parameter round-trip)
  • e2e-python test_psycopg2_cypher_with_array_parameter_in_clause — CI

Files

  • postgresw/src/main/java/com/arcadedb/postgres/PostgresNetworkExecutor.java — Long → INT8 column type
  • postgresw/src/test/java/com/arcadedb/postgres/PostgresWJdbcIT.java — re-enabled and rewritten reproducer
  • engine/src/test/java/com/arcadedb/query/opencypher/Issue4183IdInArrayParameterTest.java — new engine-level reproducer
  • engine/src/main/java/com/arcadedb/query/opencypher/ast/InExpression.java, .../ComparisonExpression.java — comment-only clarification of the TCK boundary

…$array round-trip

Cypher id() became Long-encoded in #4183, but PostgresNetworkExecutor.getColumns()
still announced every non-array scalar as VARCHAR. Postgres clients (psycopg, JDBC,
SQLAlchemy, ...) therefore deserialized id() values as strings. When a client then
resent those strings as the array parameter of WHERE id(n) IN $ids the Cypher engine
compared Long(id(n)) against String("<decimal>"), no coercion matched, and the IN
clause silently returned zero rows.

Fix at the wire layer: advertise Long-valued scalar columns as INT8 so the round-trip
preserves the numeric type. The narrower comparator-side coercion (Long <-> numeric
string) is deliberately avoided because it would violate the Cypher TCK invariant
that 5 IN ["5"] returns false.

Regression tests:
- engine Issue4183IdInArrayParameterTest pins the engine-level contract for both the
  Long list and the legacy RID-string list, and asserts the negative TCK invariant
  for numeric-string lists.
- postgresw PostgresWJdbcIT.cypherWithArrayParameterInClause is re-enabled and now
  asserts both the INT8 column-type announcement and the parameter round-trip.

Closes #4200
@claude

claude Bot commented May 11, 2026

Copy link
Copy Markdown

Code Review - PR #4201

Fix: advertise Long scalar columns as INT8 in Postgres wire protocol

Overview

This PR fixes a silent data-loss bug introduced by #4183 (where id() started returning Long-encoded RIDs): the Postgres wire layer was advertising every scalar column as VARCHAR, so clients deserialized id() values as strings, then re-sent them as a List<String> parameter — which the engine silently mismatched against Long(id(n)). The fix is applied at the correct layer (wire type advertisement in getColumns()) rather than the engine comparator, preserving Cypher TCK compliance (5 IN ["5"] = false).

The overall approach is sound and well-reasoned. Comments follow below.


PostgresNetworkExecutor.java

Simplification opportunity. The new else if branch puts pgType (already LONG) into the map - identical to what the array branch does. The three cases could be collapsed to:

if (pgType.isArrayType() || pgType == PostgresType.LONG)
  columns.put(p, pgType);
else
  columns.put(p, PostgresType.VARCHAR);

This is more concise and makes it trivially easy to extend to INT4, FLOAT8, etc. later without adding more branches.

Scope of the change is narrow. Only Long gets the native-type treatment; Integer-, Double-, and Boolean-valued properties still advertise as VARCHAR. That is a reasonable "do-no-harm" scope for this bug, but it may mean a follow-up is needed if clients round-trip those types through Cypher parameters too. Worth a comment or issue tracking this.

Wire-level serialization. Advertising INT8 only works correctly if the actual bytes written for that column are in the format the client requested (text vs. binary). If the executor always writes text format, this works fine — the decimal representation of a Long is valid text-format INT8. If binary format can be requested and the code falls through to a generic text serializer, there is a latent failure. Worth confirming that PostgresNetworkExecutor handles the INT8 type in all transfer formats it supports.


Issue4183IdInArrayParameterTest.java

The three-case structure (Long list, RID-string list, numeric-string negative case) is excellent coverage of the exact TCK boundary the PR is protecting.

One nit: {@code ...} and {@link ...} appear inside regular // block comments (not /** */ Javadoc), so they render as raw text in IDEs/docs. They do no harm, but switching either to plain text or to /** */ Javadoc would be cleaner.

The @AfterEach null-guard on database is correct defensive coding.


PostgresWJdbcIT.java

Test approach changed from PreparedStatement to inline literal. The original disabled test used conn.prepareStatement(... IN ?) with setArray(1, conn.createArrayOf("text", rids)). The new test inlines the ids as a Cypher list literal. The PR comment says this mirrors the failing Python test scenario, which makes sense — but the PreparedStatement/setArray path is now untested. If a JDBC client actually does use setArray, the path may still silently fail (or behave differently). Consider either re-adding the parameterized variant as a second assertion block, or leaving a // TODO tracking that case.

Hardcoded index access ids[0], ids[1], ids[2]. Fine for a 3-element test, but tying the array-build to a fixed size is fragile if the test data count ever changes. A String.join or stream would be more robust:

final String inList = "[" + Arrays.stream(ids).mapToObj(Long::toString).collect(Collectors.joining(",")) + "]";

assertThat(rs.getMetaData().getColumnTypeName(1)).isEqualToIgnoringCase("int8") - This is exactly the right assertion to lock in the wire-level contract. Good call.


InExpression.java / ComparisonExpression.java

Comment-only changes are clear and accurately describe the TCK boundary. The {@link ...} cross-reference between the two classes is helpful for future readers.


Summary

Area Assessment
Root-cause fix (wire type advertisement) Correct and well-placed
TCK compliance preservation Verified end-to-end
Engine-level test coverage Solid (3 cases)
JDBC IT coverage Good, but PreparedStatement/setArray path no longer tested
Code simplification Minor: else if (pgType == LONG) can fold into isArrayType() check
Other numeric types (Integer, Double) Intentionally out of scope — worth tracking as follow-up

No blocking concerns. The simplification in getColumns() and re-adding the parameterized JDBC variant (or a tracking comment) would be nice-to-have before 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 addresses issue #4183 by ensuring that Long-encoded RIDs are correctly advertised as INT8 in the Postgres wire protocol, preventing type mismatches when clients use these values in subsequent queries. The changes include updates to the Postgres network executor, enhanced documentation regarding Cypher TCK invariants in comparison expressions, and new integration tests. Review feedback suggests simplifying the type-mapping logic and identifies a potential consistency issue where property retrieval during column metadata discovery might not align with the actual data serialization logic.

Comment on lines 758 to 763
if (pgType.isArrayType())
columns.put(p, pgType);
} else {
else if (pgType == PostgresType.LONG)
columns.put(p, PostgresType.LONG);
else
columns.put(p, PostgresType.VARCHAR);

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

The logic for determining the advertised column type can be simplified for better readability. Additionally, there is a potential consistency issue: the value used here (retrieved at line 756) does not use the fallback logic found in writeDataRows (lines 966-970). If a property is only available on the element itself and not in the top-level result map, it will be detected as null here (resulting in VARCHAR), but correctly retrieved as a Long during serialization, leading to a type mismatch in the RowDescription.

          if (pgType.isArrayType() || pgType == PostgresType.LONG)
            columns.put(p, pgType);
          else
            columns.put(p, PostgresType.VARCHAR);

@codacy-production

codacy-production Bot commented May 11, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 0 complexity

Metric Results
Complexity 0

View in Codacy

🟢 Coverage 100.00% diff coverage · -7.94% coverage variation

Metric Results
Coverage variation -7.94% coverage variation
Diff coverage 100.00% diff coverage

View coverage diff in Codacy

Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (8c65bd7) 126778 93937 74.10%
Head commit (8134d09) 158478 (+31700) 104841 (+10904) 66.15% (-7.94%)

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 (#4201) 1 1 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%

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.

- Fold the LONG check into the array-type branch in getColumns() so the
  next numeric type (INT4, FLOAT8, ...) is a one-line add.
- Build the inline Cypher IN list via a loop so the test data size is not
  hard-coded into the test body.
- Drop the {@code} wrappers from the appended sentence in InExpression /
  ComparisonExpression - they were inside // blocks and rendered as raw text.
@robfrank

Copy link
Copy Markdown
Collaborator Author

Iteration on the review (commit 8134d09):

Applied:

  • Simplification in getColumns() — folded the LONG case into the array-type branch as suggested:

    if (pgType.isArrayType() || pgType == PostgresType.LONG)
      columns.put(p, pgType);
    else
      columns.put(p, PostgresType.VARCHAR);
  • PostgresWJdbcIT IN-list construction — replaced the hardcoded ids[0],ids[1],ids[2] with a loop so the test is robust to data-size changes.

  • {@code} rendering nit — only applied to the appended sentences in InExpression / ComparisonExpression; my added text in Issue4183IdInArrayParameterTest was already inside /** */ Javadoc and renders correctly there.

Not changing in this PR (tracked as follow-ups):

Not applicable:

  • Binary format concern — verified: writeRowDescription hardcodes format code 0 (text) at line 907 and serializeAsText is the only DataRow serializer used. INT8 in text format is decimal digits, which Long.toString produces — no latent failure.

Verified after iteration:

  • 3900 engine + TCK tests pass (zero regressions).
  • PostgresWJdbcIT#cypherWithArrayParameterInClause passes.

@claude

claude Bot commented May 11, 2026

Copy link
Copy Markdown

Code Review - PR #4201

Fix: advertise Long scalar columns as INT8 in the Postgres wire protocol

Overview

This PR fixes a silent data-loss regression introduced by #4183, where id() started returning a Long-encoded RID. The Postgres wire layer was advertising every non-array scalar as VARCHAR, so clients deserialised id() values as strings; when they re-sent those strings as an IN $ids parameter the Cypher engine compared Long against String and returned 0 rows. The fix is applied at the correct layer (column type advertisement in getColumns()), preserving the Cypher TCK invariant that 5 IN ["5"] returns false.


PostgresNetworkExecutor.getColumns()

The change is minimal and correct:

if (pgType.isArrayType() || pgType == PostgresType.LONG)
  columns.put(p, pgType);
else
  columns.put(p, PostgresType.VARCHAR);

Serialization is safe. serializeAsText for LONG falls through to value.toString(), emitting the decimal string (e.g., "4294967296"). Postgres text-format INT8 accepts a decimal string, so no binary-format mismatch arises. The comment at line 904 confirms the format code is always 0 (text) in RowDescription.

Null-first-row edge case (pre-existing). getColumns() sets a column's type on the first row that contains it, and then skips it (!columns.containsKey(p)). If a column is null in every row that precedes the first non-null occurrence, getTypeForValue(null) returns VARCHAR and the column is locked in as VARCHAR for the whole result set. For id() this cannot happen since every matched vertex has a non-null id, but it is a latent issue for nullable user properties. Pre-existing, not introduced here.

Scope is intentionally narrow. Integer, Double, and Boolean scalars still advertise as VARCHAR. That is a reasonable "do-no-harm" boundary for this fix, but it means those types could regress in the same way if round-tripped through clients. Worth a follow-up issue.


PostgresWJdbcIT.cypherWithArrayParameterInClause

The @Disabled annotation is removed and the test is rewritten. Two concerns:

  1. The PreparedStatement/setArray path is no longer tested. The original (disabled) test used:

    conn.prepareStatement("... WHERE ID(n) IN ?")
    pst.setArray(1, conn.createArrayOf("text", rids))

    The new test inlines the ids as a Cypher list literal built with StringBuilder. Inline literals bypass Postgres parameter binding entirely, so the test does not exercise the client scenario that was actually breaking (client fetches ids, stores them in an array, re-sends via setArray). The assertThat(rs.getMetaData().getColumnTypeName(1)).isEqualToIgnoringCase("int8") assertion is excellent and validates the wire contract, but the parameter round-trip half of the original test is missing.

  2. Query built by string concatenation. Inlining ids into a Cypher query string via StringBuilder is fine for the Cypher literal list case (Long values only, no user input), but it is worth a comment noting why this is safe here, to prevent future copy-paste that concatenates untrusted input.


Issue4183IdInArrayParameterTest

The three-case structure is exactly right:

  • List<Long> matches all rows - verifies engine accepts the round-tripped type
  • List<String> of RID strings matches all rows - preserves legacy callers
  • List<String> of numeric strings matches nothing - pins the TCK boundary

The @AfterEach null-guard and database.drop() cleanup are correct.

Minor nit: {@code ...} and {@link ...} tags inside regular // block comments (not /** */ Javadoc) render as raw text in IDEs. Either switch to plain text or convert the enclosing comments to Javadoc.


InExpression.java / ComparisonExpression.java

Comment-only changes. The extended description accurately explains the TCK boundary and the {@link} cross-reference between the two classes is helpful for future readers.


Summary

Area Assessment
Root-cause fix (wire type advertisement) Correct, well-placed, and verified
Wire serialization safety Confirmed - text-format decimal is valid INT8
TCK compliance Preserved and tested with a negative case
Engine-level test coverage Solid (3 cases covering the full contract)
JDBC IT coverage Wire-type assertion is good; PreparedStatement/setArray path no longer tested
Other numeric types (Integer, Double, Boolean) Intentionally out of scope - worth a follow-up issue

No blocking concerns. The main suggestion before merge: either restore a PreparedStatement/setArray variant in PostgresWJdbcIT alongside the current literal test, or explicitly document why the inline-literal approach is sufficient to cover the real client scenario.

@codecov

codecov Bot commented May 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 64.58%. Comparing base (8c65bd7) to head (8134d09).
⚠️ Report is 7 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4201      +/-   ##
==========================================
- Coverage   64.95%   64.58%   -0.37%     
==========================================
  Files        1645     1645              
  Lines      126778   126800      +22     
  Branches    27123    27132       +9     
==========================================
- Hits        82352    81900     -452     
- Misses      32870    33451     +581     
+ Partials    11556    11449     -107     

☔ 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 changed the title fix: [postgres] advertise Long scalar columns as INT8 to fix id() IN $array round-trip #4200 fix: [postgres] advertise Long scalar columns as INT8 to fix id() IN $array round-trip May 11, 2026
@robfrank
robfrank merged commit 750f2a6 into main May 11, 2026
25 of 29 checks passed
robfrank added a commit that referenced this pull request May 12, 2026
…() IN $array round-trip (#4201)

* fix: [postgres] advertise Long scalar columns as INT8 to fix id() IN $array round-trip

Cypher id() became Long-encoded in #4183, but PostgresNetworkExecutor.getColumns()
still announced every non-array scalar as VARCHAR. Postgres clients (psycopg, JDBC,
SQLAlchemy, ...) therefore deserialized id() values as strings. When a client then
resent those strings as the array parameter of WHERE id(n) IN $ids the Cypher engine
compared Long(id(n)) against String("<decimal>"), no coercion matched, and the IN
clause silently returned zero rows.

Fix at the wire layer: advertise Long-valued scalar columns as INT8 so the round-trip
preserves the numeric type. The narrower comparator-side coercion (Long <-> numeric
string) is deliberately avoided because it would violate the Cypher TCK invariant
that 5 IN ["5"] returns false.

Regression tests:
- engine Issue4183IdInArrayParameterTest pins the engine-level contract for both the
  Long list and the legacy RID-string list, and asserts the negative TCK invariant
  for numeric-string lists.
- postgresw PostgresWJdbcIT.cypherWithArrayParameterInClause is re-enabled and now
  asserts both the INT8 column-type announcement and the parameter round-trip.

Closes #4200

* fix: [postgres] code-review iteration (#4201)

- Fold the LONG check into the array-type branch in getColumns() so the
  next numeric type (INT4, FLOAT8, ...) is a one-line add.
- Build the inline Cypher IN list via a loop so the test data size is not
  hard-coded into the test body.
- Drop the {@code} wrappers from the appended sentence in InExpression /
  ComparisonExpression - they were inside // blocks and rendered as raw text.

(cherry picked from commit 750f2a6)
robfrank added a commit that referenced this pull request May 19, 2026
…, FLOAT8, FLOAT4, BOOL, TIMESTAMP)

Extends PR #4201 which limited the wire-level type fidelity fix to LONG/INT8. PostgresNetworkExecutor.getColumns()
now passes through all native scalar types (Integer, Short, Byte, Float, Double, Boolean, Character, Date,
LocalDateTime) with their proper Postgres OIDs instead of collapsing to VARCHAR. Clients (pgjdbc, psycopg) use the
announced OID to choose a deserializer; VARCHAR for typed columns caused values to round-trip as strings and
silently broke typed parameter comparisons.

- Added TIMESTAMP (OID 1114) entry for LocalDateTime with text + binary deserialization
- getTypeForValue(LocalDateTime) and getTypeFromArcade(DATETIME) now return TIMESTAMP
- serializeAsText emits canonical "t"/"f" for Boolean and "YYYY-MM-DD" for Date (was timestamp-format)
- DATE size corrected from 8 to 4 to match pg_type binary size
- New isNativeScalarType() drives the getColumns() condition

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
tae898 pushed a commit to humemai/arcadedb-embedded-python that referenced this pull request Jun 28, 2026
… to fix id() IN $array round-trip (ArcadeData#4201)

* fix: [postgres] advertise Long scalar columns as INT8 to fix id() IN $array round-trip

Cypher id() became Long-encoded in ArcadeData#4183, but PostgresNetworkExecutor.getColumns()
still announced every non-array scalar as VARCHAR. Postgres clients (psycopg, JDBC,
SQLAlchemy, ...) therefore deserialized id() values as strings. When a client then
resent those strings as the array parameter of WHERE id(n) IN $ids the Cypher engine
compared Long(id(n)) against String("<decimal>"), no coercion matched, and the IN
clause silently returned zero rows.

Fix at the wire layer: advertise Long-valued scalar columns as INT8 so the round-trip
preserves the numeric type. The narrower comparator-side coercion (Long <-> numeric
string) is deliberately avoided because it would violate the Cypher TCK invariant
that 5 IN ["5"] returns false.

Regression tests:
- engine Issue4183IdInArrayParameterTest pins the engine-level contract for both the
  Long list and the legacy RID-string list, and asserts the negative TCK invariant
  for numeric-string lists.
- postgresw PostgresWJdbcIT.cypherWithArrayParameterInClause is re-enabled and now
  asserts both the INT8 column-type announcement and the parameter round-trip.

Closes ArcadeData#4200

* fix: [postgres] code-review iteration (ArcadeData#4201)

- Fold the LONG check into the array-type branch in getColumns() so the
  next numeric type (INT4, FLOAT8, ...) is a one-line add.
- Build the inline Cypher IN list via a loop so the test data size is not
  hard-coded into the test body.
- Drop the {@code} wrappers from the appended sentence in InExpression /
  ComparisonExpression - they were inside // blocks and rendered as raw text.
@lvca
lvca deleted the fix/e2e-python-failing-test branch July 3, 2026 20:19
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.

[postgres] Cypher WHERE id(n) IN $array returns 0 rows over Postgres wire after id() became numeric (#4183)

2 participants