pgjdbc/pgjdbc GitHub issues and pull requests (mirror)  
help / color / mirror / Atom feed
From: vlsi (@vlsi) <[email protected]>
To: pgjdbc/pgjdbc <[email protected]>
Subject: [pgjdbc/pgjdbc] PR #4067: feat: flushCacheOnDdl — transparent re-prepare after CREATE/DROP/ALTER
Date: Wed, 13 May 2026 13:17:25 +0000
Message-ID: <[email protected]> (raw)

## Summary

When a server-prepared statement references a table that is later modified via `ALTER TABLE` (or affected by `CREATE`/`DROP` of a referenced object), PostgreSQL raises `cached plan must not change result type` (SQLSTATE `0A000`) on the next `EXECUTE`. pgjdbc surfaces that error verbatim today, and transparent recovery requires opting into `autosave=ALWAYS`.

This PR adds a new connection property, **`flushCacheOnDdl` (default `true`)**, that makes the driver invalidate its prepared-statement cache when it sees a `CREATE`/`DROP`/`ALTER` `CommandComplete` in the same session. The next time the affected statement is executed, the driver re-PARSEs it server-side, so callers never see the cached-plan error.

The bump piggybacks on the existing `deallocateEpoch` mechanism used for `DEALLOCATE ALL` / `DISCARD ALL`. Setting `flushCacheOnDdl=false` preserves the pre-existing behaviour for users who rely on it.

### Why default to `true`?

The only observable user-facing change is that an opaque `0A000` after `ALTER` no longer reaches the caller. The alternative — `autosave=ALWAYS` — is more expensive (a `SAVEPOINT`/`RELEASE` around every statement) and not the default. For installations that depend on the legacy contract, the new property gives a clean opt-out.

## Wiring

- New `PGProperty.FLUSH_CACHE_ON_DDL` and matching `BaseDataSource get/setFlushCacheOnDdl` (`PGPropertyTest` enforces both).
- `QueryExecutor.{is,set}FlushCacheOnDdl` + `QueryExecutorBase` implementation, defaulting to `true` so non-`PgConnection` callers (e.g. `ReplicationProtocol`) inherit the improved behaviour.
- `PgConnection` reads the property in its constructor and forwards it.
- `QueryExecutorImpl` bumps `deallocateEpoch` on `CREATE`/`DROP`/`ALTER` `CommandComplete` when `flushCacheOnDdl` is enabled.

## Test plan

- [x] `AutoRollbackTest` now ties its existing `flushCacheOnDeallocate` parameterization to `flushCacheOnDdl` 1:1, and the `FailMode.ALTER` iteration no longer skips `flushCacheOnDeallocate=false`. Both legacy (`cached plan must not change result type` → `IN_FAILED_SQL_TRANSACTION`) and new (transparent re-prepare) paths get coverage. **1056 parameterizations, 0 failures**.
- [x] `PGPropertyTest` validates getter/setter wiring and alphabetic enum ordering. **All green**.
- [x] Full test suite runs clean locally (only `ConnectTimeoutTest#timeout` flakes on my network — environmental, unrelated to this PR).

## Backwards compatibility

- Default behaviour changes: callers that previously observed `0A000` after `ALTER` no longer do. To opt out, set `flushCacheOnDdl=false` in the JDBC URL or `Properties`.
- API additions only — `QueryExecutor` gains two methods (`isFlushCacheOnDdl` / `setFlushCacheOnDdl`), and `BaseDataSource` gains the corresponding bean accessors. No method signatures are changed or removed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: github://pgjdbc/pgjdbc
  Cc: [email protected], [email protected]
  Subject: Re: [pgjdbc/pgjdbc] PR #4067: feat: flushCacheOnDdl — transparent re-prepare after CREATE/DROP/ALTER
  In-Reply-To: <<[email protected]>>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox