Repository navigation
fix(largeobject): correct BlobInputStream mark/reset position and add efficient skip - #4204
Merged
Merged
Conversation
9 tasks done
lo_tell64 and lo_lseek64 require PostgreSQL 9.3+. Expose the cached server version through Fastpath#getServerVersionNum and add LargeObject#supports64BitOffsets so callers can pick the 64-bit fastpath functions by version instead of calling them and recovering from the failure on older servers. The version is negotiated at connection startup, so the check costs no extra round-trip.
…osition BlobInputStream assumed the underlying LargeObject was positioned at the start, so mark() and reset() computed offsets from the wrong origin when the stream was created from a LargeObject that had already been seeked. reset() then repositioned to the wrong byte. Initialise the stream position from the LargeObject's current position (lo_tell64, or lo_tell on servers older than 9.3) on first use, and make the read limit relative to that position. The initialisation is deferred out of the constructor so the failure surfaces as a checked IOException. Also invalidate the read buffer before seeking in reset(), so a failed seek cannot leave stale buffered data behind. Closes pgjdbc#3149 Co-authored-by: James Howe <[email protected]>
InputStream.skip on a BlobInputStream used the default implementation, which reads and discards the bytes, so skipping a large distance cost a full read. Override skip(long) to seek with lo_lseek/lo_lseek64, making the cost independent of the distance. Large objects are sparse, so skipping past the current end is allowed: later reads return -1 and the returned count still reflects the requested distance, as the InputStream.skip contract permits. Skips that stay within the current buffer advance the buffer pointer without a round-trip. Closes pgjdbc#3144 Co-authored-by: James Howe <[email protected]>
vlsi
force-pushed
the
feat/blobinputstream-skip-reset
branch
from
June 26, 2026 06:43
83c4afe to
070636d
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #4204 +/- ##
============================================
+ Coverage 70.86% 70.88% +0.02%
- Complexity 5323 5333 +10
============================================
Files 244 244
Lines 21932 21973 +41
Branches 3685 3692 +7
============================================
+ Hits 15542 15576 +34
- Misses 4741 4742 +1
- Partials 1649 1655 +6 🚀 New features to boost your workflow:
|
davecramer
added a commit
to davecramer/pgjdbc
that referenced
this pull request
Jul 6, 2026
Rename the release notes to 2026-07-06 to reflect the release date, and add the remaining PR links (flushCacheOnDdl pgjdbc#4067, connectExecutor pgjdbc#4165, reWriteBatchedInserts cap pgjdbc#4207, OID constants pgjdbc#4220, 64-bit LO pgjdbc#4204, and the refactor entries pgjdbc#4160/pgjdbc#4166/pgjdbc#4215).
davecramer
added a commit
that referenced
this pull request
Jul 6, 2026
* docs: add 42.7.12 release changelog Covers all changes since REL42.7.11: search_path GUC_REPORT cache invalidation (PG 18+), flushCacheOnDdl, connectExecutor, classLoaderStrategy, reWriteBatchedInserts protocol-limit cap, large object 64-bit API, updatable ResultSet search_path fix, XA autoCommit fix, FIPS trust anchors, SSL key-format auto-detection, batching improvements, and numerous other bug fixes. docs: prepare 42.7.13 release notes after 42.7.12 security release 42.7.12 shipped as a security-only release for the silent channel-binding downgrade (CVE-2026-54291), so the feature and bug-fix notes that had been drafted for 42.7.12 now belong to 42.7.13. - bump pgjdbc.version to 42.7.13 - add a published 42.7.12 changelog entry covering CVE-2026-54291 - retitle the drafted maintenance notes from 42.7.12 to 42.7.13 (CHANGELOG.md and the website changelog) - record PR #4248 (LargeObject.close() flushes before marking closed, and lo_close no longer masks a flush failure) under 42.7.13 docs: fix PR links and add missing entries in 42.7.13 release notes Point each changelog entry at the PR that merged the change rather than at the issue or at the superseded #3400. Add two entries that were missing: the reWriteBatchedInserts parameterless-INSERT fix (#4207) and the GitHub release jar/signature fix (#3814). Drop the stray connectThreadFactory entry from CHANGELOG.md, which connectExecutor replaced before release. Co-Authored-By: Claude Opus 4.8 <[email protected]> docs: credit translators and attribute large-object commits to James Howe Move the BlobInputStream skip and reset commits to James Howe, who co-authored them, and add a short contributors note crediting the Italian, Simplified Chinese, and Russian-review translators. Co-Authored-By: Claude Opus 4.8 <[email protected]> docs: add the empty-timestamp fix (#4278) to the 42.7.13 release notes Reflect PR #4278, merged after the release-notes branch was opened: an empty timestamp/timestamptz/date value now yields a clear SQLException instead of ArrayIndexOutOfBoundsException. Co-Authored-By: Claude Opus 4.8 <[email protected]> * docs: diarize all 42.7.13 changes in CHANGELOG.md The root CHANGELOG.md [42.7.13] section listed only 20 entries while about 50 user-facing changes have landed since the 42.7.12 baseline. Bring it in line with the reviewed website changelog: add the missing feat/fix/refactor entries and correct PR references. Newly diarized items include getSchemas() on a hot standby (#4274), getColumnPrivileges()/CHAR_OCTET_LENGTH (#4231), FIPS PKIX trust anchors (#4193), SSL key-format auto-detection (#3946), GSS response timeout, autosave savepoints for SET LOCAL (#4203), BatchResultHandler on a closed connection (#4187), SQL_TSI_FRAC_SECOND (#4229), the batching/describe fixes, NumberParser/PGInterval validation, connectThreadFactory, OID constants, and getPrimaryKeys derivation. Docs, i18n, build, ci, test, and dependency-bump commits are omitted, consistent with the file's existing "Notable changes" scope. * docs: date the 42.7.13 website changelog to its release date Rename the release notes to 2026-07-06 to reflect the release date, and add the remaining PR links (flushCacheOnDdl #4067, connectExecutor #4165, reWriteBatchedInserts cap #4207, OID constants #4220, 64-bit LO #4204, and the refactor entries #4160/#4166/#4215). * docs: correct the 42.7.13 commits-by-author counts Reconcile the "Commits by author" section with git history: - Vladimir Sitnikov: 100 -> 104 (stale count carried from the 42.7.12 draft) - Dave Cramer: 4 -> 5, add the missing "maintainer vs committer" (#4234) entry - add Michael Baumgartner (1 commit), previously omitted James Howe remains credited for the two co-authored large-object commits. * remove connectThread as it was replaced by connectExecutor --------- Co-authored-by: Vladimir Sitnikov <[email protected]>
vlsi
added a commit
to vlsi/pgjdbc
that referenced
this pull request
Jul 8, 2026
* docs: add 42.7.12 release changelog Covers all changes since REL42.7.11: search_path GUC_REPORT cache invalidation (PG 18+), flushCacheOnDdl, connectExecutor, classLoaderStrategy, reWriteBatchedInserts protocol-limit cap, large object 64-bit API, updatable ResultSet search_path fix, XA autoCommit fix, FIPS trust anchors, SSL key-format auto-detection, batching improvements, and numerous other bug fixes. docs: prepare 42.7.13 release notes after 42.7.12 security release 42.7.12 shipped as a security-only release for the silent channel-binding downgrade (CVE-2026-54291), so the feature and bug-fix notes that had been drafted for 42.7.12 now belong to 42.7.13. - bump pgjdbc.version to 42.7.13 - add a published 42.7.12 changelog entry covering CVE-2026-54291 - retitle the drafted maintenance notes from 42.7.12 to 42.7.13 (CHANGELOG.md and the website changelog) - record PR pgjdbc#4248 (LargeObject.close() flushes before marking closed, and lo_close no longer masks a flush failure) under 42.7.13 docs: fix PR links and add missing entries in 42.7.13 release notes Point each changelog entry at the PR that merged the change rather than at the issue or at the superseded pgjdbc#3400. Add two entries that were missing: the reWriteBatchedInserts parameterless-INSERT fix (pgjdbc#4207) and the GitHub release jar/signature fix (pgjdbc#3814). Drop the stray connectThreadFactory entry from CHANGELOG.md, which connectExecutor replaced before release. Co-Authored-By: Claude Opus 4.8 <[email protected]> docs: credit translators and attribute large-object commits to James Howe Move the BlobInputStream skip and reset commits to James Howe, who co-authored them, and add a short contributors note crediting the Italian, Simplified Chinese, and Russian-review translators. Co-Authored-By: Claude Opus 4.8 <[email protected]> docs: add the empty-timestamp fix (pgjdbc#4278) to the 42.7.13 release notes Reflect PR pgjdbc#4278, merged after the release-notes branch was opened: an empty timestamp/timestamptz/date value now yields a clear SQLException instead of ArrayIndexOutOfBoundsException. Co-Authored-By: Claude Opus 4.8 <[email protected]> * docs: diarize all 42.7.13 changes in CHANGELOG.md The root CHANGELOG.md [42.7.13] section listed only 20 entries while about 50 user-facing changes have landed since the 42.7.12 baseline. Bring it in line with the reviewed website changelog: add the missing feat/fix/refactor entries and correct PR references. Newly diarized items include getSchemas() on a hot standby (pgjdbc#4274), getColumnPrivileges()/CHAR_OCTET_LENGTH (pgjdbc#4231), FIPS PKIX trust anchors (pgjdbc#4193), SSL key-format auto-detection (pgjdbc#3946), GSS response timeout, autosave savepoints for SET LOCAL (pgjdbc#4203), BatchResultHandler on a closed connection (pgjdbc#4187), SQL_TSI_FRAC_SECOND (pgjdbc#4229), the batching/describe fixes, NumberParser/PGInterval validation, connectThreadFactory, OID constants, and getPrimaryKeys derivation. Docs, i18n, build, ci, test, and dependency-bump commits are omitted, consistent with the file's existing "Notable changes" scope. * docs: date the 42.7.13 website changelog to its release date Rename the release notes to 2026-07-06 to reflect the release date, and add the remaining PR links (flushCacheOnDdl pgjdbc#4067, connectExecutor pgjdbc#4165, reWriteBatchedInserts cap pgjdbc#4207, OID constants pgjdbc#4220, 64-bit LO pgjdbc#4204, and the refactor entries pgjdbc#4160/pgjdbc#4166/pgjdbc#4215). * docs: correct the 42.7.13 commits-by-author counts Reconcile the "Commits by author" section with git history: - Vladimir Sitnikov: 100 -> 104 (stale count carried from the 42.7.12 draft) - Dave Cramer: 4 -> 5, add the missing "maintainer vs committer" (pgjdbc#4234) entry - add Michael Baumgartner (1 commit), previously omitted James Howe remains credited for the two co-authored large-object commits. * remove connectThread as it was replaced by connectExecutor --------- Co-authored-by: Vladimir Sitnikov <[email protected]>
vlsi
added a commit
to vlsi/pgjdbc
that referenced
this pull request
Jul 8, 2026
* docs: add 42.7.12 release changelog Covers all changes since REL42.7.11: search_path GUC_REPORT cache invalidation (PG 18+), flushCacheOnDdl, connectExecutor, classLoaderStrategy, reWriteBatchedInserts protocol-limit cap, large object 64-bit API, updatable ResultSet search_path fix, XA autoCommit fix, FIPS trust anchors, SSL key-format auto-detection, batching improvements, and numerous other bug fixes. docs: prepare 42.7.13 release notes after 42.7.12 security release 42.7.12 shipped as a security-only release for the silent channel-binding downgrade (CVE-2026-54291), so the feature and bug-fix notes that had been drafted for 42.7.12 now belong to 42.7.13. - bump pgjdbc.version to 42.7.13 - add a published 42.7.12 changelog entry covering CVE-2026-54291 - retitle the drafted maintenance notes from 42.7.12 to 42.7.13 (CHANGELOG.md and the website changelog) - record PR pgjdbc#4248 (LargeObject.close() flushes before marking closed, and lo_close no longer masks a flush failure) under 42.7.13 docs: fix PR links and add missing entries in 42.7.13 release notes Point each changelog entry at the PR that merged the change rather than at the issue or at the superseded pgjdbc#3400. Add two entries that were missing: the reWriteBatchedInserts parameterless-INSERT fix (pgjdbc#4207) and the GitHub release jar/signature fix (pgjdbc#3814). Drop the stray connectThreadFactory entry from CHANGELOG.md, which connectExecutor replaced before release. Co-Authored-By: Claude Opus 4.8 <[email protected]> docs: credit translators and attribute large-object commits to James Howe Move the BlobInputStream skip and reset commits to James Howe, who co-authored them, and add a short contributors note crediting the Italian, Simplified Chinese, and Russian-review translators. Co-Authored-By: Claude Opus 4.8 <[email protected]> docs: add the empty-timestamp fix (pgjdbc#4278) to the 42.7.13 release notes Reflect PR pgjdbc#4278, merged after the release-notes branch was opened: an empty timestamp/timestamptz/date value now yields a clear SQLException instead of ArrayIndexOutOfBoundsException. Co-Authored-By: Claude Opus 4.8 <[email protected]> * docs: diarize all 42.7.13 changes in CHANGELOG.md The root CHANGELOG.md [42.7.13] section listed only 20 entries while about 50 user-facing changes have landed since the 42.7.12 baseline. Bring it in line with the reviewed website changelog: add the missing feat/fix/refactor entries and correct PR references. Newly diarized items include getSchemas() on a hot standby (pgjdbc#4274), getColumnPrivileges()/CHAR_OCTET_LENGTH (pgjdbc#4231), FIPS PKIX trust anchors (pgjdbc#4193), SSL key-format auto-detection (pgjdbc#3946), GSS response timeout, autosave savepoints for SET LOCAL (pgjdbc#4203), BatchResultHandler on a closed connection (pgjdbc#4187), SQL_TSI_FRAC_SECOND (pgjdbc#4229), the batching/describe fixes, NumberParser/PGInterval validation, connectThreadFactory, OID constants, and getPrimaryKeys derivation. Docs, i18n, build, ci, test, and dependency-bump commits are omitted, consistent with the file's existing "Notable changes" scope. * docs: date the 42.7.13 website changelog to its release date Rename the release notes to 2026-07-06 to reflect the release date, and add the remaining PR links (flushCacheOnDdl pgjdbc#4067, connectExecutor pgjdbc#4165, reWriteBatchedInserts cap pgjdbc#4207, OID constants pgjdbc#4220, 64-bit LO pgjdbc#4204, and the refactor entries pgjdbc#4160/pgjdbc#4166/pgjdbc#4215). * docs: correct the 42.7.13 commits-by-author counts Reconcile the "Commits by author" section with git history: - Vladimir Sitnikov: 100 -> 104 (stale count carried from the 42.7.12 draft) - Dave Cramer: 4 -> 5, add the missing "maintainer vs committer" (pgjdbc#4234) entry - add Michael Baumgartner (1 commit), previously omitted James Howe remains credited for the two co-authored large-object commits. * remove connectThread as it was replaced by connectExecutor --------- Co-authored-by: Vladimir Sitnikov <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
BlobInputStreamcomputedmark/resetoffsets from position 0, soreset()returned to the wrong byte when the stream was created from aLargeObjectthat had already been seeked (BlobInputStream does not reset() to correct position if LargeObject was not at position 0. #3149).skip(long)used the defaultInputStreamimplementation, which reads and discards the bytes, so skipping a large distance cost a full read (BlobInputStream should implement skip #3144).What
LargeObject's current position (lo_tell64, orlo_tellbelow 9.3) and make the read limit relative to that position.skip(long)to seek withlo_lseek/lo_lseek64; skips that stay within the current buffer advance the buffer pointer without a round-trip. Large objects are sparse, so skipping past the end is allowed and later reads return-1, as theInputStream.skipcontract permits.Fastpath#getServerVersionNumandLargeObject#supports64BitOffsets, rather than callinglo_tell64and recovering from the failure. Older servers pay no extra round-trip, and the publictell64semantics are unchanged.This takes over and reworks #3148 by @OrangeDog, whose commits are credited via
Co-authored-by. Differences from that PR:try { tell64 } catch { tell }, which removes the extra round-trip on pre-9.3 servers that the original review flagged;castNonNullcalls — assigning the field to a local satisfies the nullness checker;close()throws, butLargeObject.close()is idempotent, so the assertion could not hold.Closes #3144
Closes #3149
How to verify
All 27
BlobTestcases pass locally against PostgreSQL 18;autostyleCheck,checkstyleMain, andcheckstyleTestare clean.