Message-ID: From: "vlsi (@vlsi)" To: "pgjdbc/pgjdbc" Date: Fri, 22 May 2026 09:27:32 +0000 Subject: Re: [pgjdbc/pgjdbc] PR #4075: docs: restructure site, compatibility page, changelog-driven releases In-Reply-To: References: List-Id: X-GitHub-Author-Login: vlsi X-GitHub-Comment-Id: 4517416988 X-GitHub-Comment-Type: issue_comment X-GitHub-Issue: 4075 X-GitHub-Repo: pgjdbc/pgjdbc X-GitHub-Type: comment X-GitHub-Url: https://github.com/pgjdbc/pgjdbc/pull/4075#issuecomment-4517416988 Content-Type: text/plain; charset=utf-8 Twenty-eight documentation pages went through a two-agent fact-check pass with manual approval gates. The workflow is documented in the commit message and is intended to be repeatable: https://github.com/pgjdbc/pgjdbc/pull/4075/commits/6bc673af7264388ad915416ace717a1361b95160 **Workflow per page** 1. **GPT** proposes edits: read the page, verify each claim against the source tree on this branch, add `{{< review >}}` shortcodes pointing at the backing code, and surface any doubtful claims for me to decide on. 2. **Manual gate**: I read each diff, approve or push back on doubtful claims. 3. **Claude** does an independent review of the resulting diff (without seeing GPT's reasoning) and asks one question: does each edit make the page truer and clearer, or does it convert a true statement into a false one, leak implementation details where a high-level guarantee belongs, or make the page harder to reason about? 4. **Manual gate**: I read Claude's review, accept the proposed corrections, override when I disagree. The pass is not editorial polish. Below are the substantive factual bugs found and fixed, one per affected page. Some had been misleading readers for years. ### How to review If you want to spot-check the pass without reading 28 diffs, the highest-signal files are `ssl-errors.md`, `date-time.md`, `unix-sockets.md`, and `connection-pooling.md`. Those carry the largest factual fixes. The rest are mostly review-shortcode additions plus narrow corrections. Each `{{< review >}}` block is a hand-verifiable claim ledger: open the cited file at the cited line range and confirm the surrounding prose still matches the code. If anything reads as "implementation detail leaking into a user-facing guarantee", flag it. That was the explicit failure mode the Claude pass was looking for, but it is the easiest kind of mistake to leave in. ### Sample factual bugs fixed - **`docs/content/documentation/troubleshooting/ssl-errors.md`**: the default `sslkey` filename was documented as `postgresql.p12`; the actual default is `postgresql.pk8` (`LibPQFactory.java` falls back to `defaultdir + "postgresql.pk8"`). The description of which key loader runs for which file extension was also wrong: the page implied "modern pgJDBC expects PKCS-12", whereas the driver dispatches on the filename suffix and the PKCS-8 DER loader is the *fallback* for anything that is not `.p12`/`.pfx`/`.key`/`.pem`. - **`docs/content/documentation/data-types/date-time.md`**: the page listed `OffsetTime` / `TIME WITH TIME ZONE` as unsupported. Support has been in the driver for a long time. `PgResultSet.getOffsetTime` handles `Oid.TIMETZ`, `PgPreparedStatement.setObject` dispatches `OffsetTime`, and `GetObject310Test#testGetOffsetTime` covers the round trip. Table 5.1 now lists the mapping and the note no longer claims unsupported. - **`docs/content/documentation/connect/unix-sockets.md`**: the page rendered a literal AI-generation artifact (``) at the end of its body. The Maven snippet for `junixsocket-core` was missing `pom`, which means the snippet did not resolve as written (the artifact is an aggregator POM). The junixsocket version was bumped from 2.5.1 (2022) to a current 2.10.x, a full example URL was added, and the page now clarifies that `unix_socket_directories` defaults to `/tmp` upstream and gets relocated to `/var/run/postgresql` by some packagers. - **`docs/content/documentation/connect/connection-pooling.md`**: the page claimed that without an explicit `ApplicationName`, `pg_stat_activity.application_name` is the empty string. In reality `PGProperty.APPLICATION_NAME` defaults to `DriverInfo.DRIVER_NAME` (`"PostgreSQL JDBC Driver"`), which is what the DBA actually sees. An out-of-date claim that c3p0 cannot use `Connection.isValid()` (it can since 0.9.5) was also corrected. - **`docs/content/documentation/troubleshooting/class-not-found.md`**: `PGSimpleDataSource` was described as bypassing `DriverManager`. It does not: `BaseDataSource#getConnection` calls `DriverManager.getConnection(getUrl(), user, password)`. The static initializer does force-load `org.postgresql.Driver` to handle classloader-visibility cases, which is a different guarantee. - **`docs/content/documentation/query/stored-procedures.md`**: the page said that a `ResultSet` obtained from a refcursor materializes all rows on the client and ignores the `Statement` fetch size. The current behavior is the opposite of "all on the client": the inner `FETCH ALL IN ` runs through a statement that inherits `defaultRowFetchSize`, so the result streams. Two knobs are still not propagated: `Statement.setFetchSize()` and `ResultSet.setFetchSize()` set on the outer `CallableStatement` do not reach the inner fetch (tracked by a `TODO` in `RefCursorFetchTest`). The same diff fixed a broken backtick (`to a ResultSet\``) and a swapped class name (`getString` of `ResultSet` → `getString` of `CallableStatement`, which is what the example below the prose actually uses). - **`docs/content/documentation/postgresql-features/listen-notify.md`**: the NOTE claimed pgJDBC "cannot receive asynchronous notifications and must poll the backend". The PostgreSQL wire protocol *does* push `NotificationResponse` ('A') asynchronously; the actual driver-side limitation is that there is no background reader thread, so application code has to call `getNotifications()` itself to drain what the socket already has. Additional cleanups: clarified that `getNotifications(0)` blocks forever (per `PGConnection` javadoc), and that the blocking variant only blocks other threads on the same connection. Dropped the legacy `Class.forName("org.postgresql.Driver")` line from the sample. Added a note on `getParameter()` (the `NOTIFY channel, 'payload'` value, since PostgreSQL 9.0) and `getPID()` on `PGNotification`. Promoted the orphan `##### Example 9.2.` heading to a real `##`.