pgjdbc/pgjdbc GitHub issues and pull requests (mirror)
help / color / mirror / Atom feedFrom: mjschwaiger (@mjschwaiger) <[email protected]>
To: pgjdbc/pgjdbc <[email protected]>
Subject: [pgjdbc/pgjdbc] issue #3910: Connection parameter cleanupSavepoints=true does not work with oid/blob column
Date: Fri, 16 Jan 2026 17:44:38 +0000
Message-ID: <[email protected]> (raw)
**Describe the issue**
PSQLException with message "Unknown Response Type C." occurs when a connection with parameter "cleanupSavepoints=true" (and "autosave=always") inserts or reads a record with an oid column (Blob object in Java).
PSQLException does not occur if just "autosave=always" is set.
https://jdbc.postgresql.org/documentation/use/
Related to #1407 / #1409.
**Driver Version?**
42.7.8
**Java Version?**
JDK 21
**OS Version?**
Windows Server 2025
**PostgreSQL Version?**
Postgres 18.2-1
**To Reproduce**
See description and example code.
**Expected behaviour**
Insert and read of oid columns should also work when parameter "cleanupSavepoints=true" is set.
**Logs**
*PostgreSQL logs*
log_line_prefix = '%m %x '
log_statement = all
```
2026-01-16 18:43:25.837 CET 0 LOG: database system is ready to accept connections
2026-01-16 18:43:42.172 CET 0 LOG: statement: SET application_name = 'PostgreSQL JDBC Driver'
2026-01-16 18:43:42.216 CET 0 LOG: statement: BEGIN
2026-01-16 18:43:42.218 CET 0 LOG: execute <unnamed>: DROP TABLE IF EXISTS test_blob
2026-01-16 18:43:42.221 CET 1197 LOG: execute <unnamed>: CREATE TABLE test_blob (id BIGINT, doc OID)
2026-01-16 18:43:42.233 CET 1197 LOG: execute <unnamed>: SELECT p.proname,p.oid FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n WHERE p.pronamespace=n.oid AND n.nspname='pg_catalog' AND ( proname = 'lo_open' or proname = 'lo_close' or proname = 'lo_creat' or proname = 'lo_unlink' or proname = 'lo_lseek' or proname = 'lo_lseek64' or proname = 'lo_tell' or proname = 'lo_tell64' or proname = 'loread' or proname = 'lowrite' or proname = 'lo_truncate' or proname = 'lo_truncate64')
2026-01-16 18:43:42.241 CET 1197 LOG: fastpath function call: "lo_creat" (OID 957)
2026-01-16 18:43:42.243 CET 1197 LOG: fastpath function call: "lo_open" (OID 952)
2026-01-16 18:43:42.244 CET 1197 LOG: fastpath function call: "lowrite" (OID 955)
2026-01-16 18:43:42.245 CET 1197 LOG: fastpath function call: "lo_close" (OID 953)
2026-01-16 18:43:42.248 CET 1197 LOG: execute <unnamed>: INSERT INTO test_blob (id, doc) VALUES ($1, $2)
2026-01-16 18:43:42.248 CET 1197 DETAIL: Parameters: $1 = '1', $2 = '16776'
2026-01-16 18:43:42.249 CET 1197 LOG: execute S_1: COMMIT
2026-01-16 18:43:42.257 CET 0 LOG: statement: BEGIN
2026-01-16 18:43:42.257 CET 0 LOG: execute <unnamed>: select id, doc from test_blob
2026-01-16 18:43:42.259 CET 0 LOG: fastpath function call: "lo_open" (OID 952)
2026-01-16 18:43:42.259 CET 0 LOG: fastpath function call: "lo_open" (OID 952)
2026-01-16 18:43:42.259 CET 0 LOG: fastpath function call: "lo_lseek" (OID 956)
2026-01-16 18:43:42.259 CET 0 LOG: fastpath function call: "loread" (OID 954)
2026-01-16 18:43:42.260 CET 0 LOG: fastpath function call: "loread" (OID 954)
2026-01-16 18:43:42.260 CET 0 LOG: execute <unnamed>: DROP TABLE IF EXISTS test_blob
2026-01-16 18:43:42.337 CET 0 LOG: statement: SET application_name = 'PostgreSQL JDBC Driver'
2026-01-16 18:43:42.338 CET 0 LOG: statement: BEGIN
2026-01-16 18:43:42.338 CET 0 LOG: statement: SAVEPOINT PGJDBC_AUTOSAVE
2026-01-16 18:43:42.338 CET 0 LOG: execute <unnamed>: DROP TABLE IF EXISTS test_blob
2026-01-16 18:43:42.340 CET 1199 LOG: statement: SAVEPOINT PGJDBC_AUTOSAVE
2026-01-16 18:43:42.340 CET 1199 LOG: execute <unnamed>: CREATE TABLE test_blob (id BIGINT, doc OID)
2026-01-16 18:43:42.342 CET 1199 LOG: statement: SAVEPOINT PGJDBC_AUTOSAVE
2026-01-16 18:43:42.345 CET 1199 LOG: execute <unnamed>: SELECT p.proname,p.oid FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n WHERE p.pronamespace=n.oid AND n.nspname='pg_catalog' AND ( proname = 'lo_open' or proname = 'lo_close' or proname = 'lo_creat' or proname = 'lo_unlink' or proname = 'lo_lseek' or proname = 'lo_lseek64' or proname = 'lo_tell' or proname = 'lo_tell64' or proname = 'loread' or proname = 'lowrite' or proname = 'lo_truncate' or proname = 'lo_truncate64')
2026-01-16 18:43:42.345 CET 1199 LOG: fastpath function call: "lo_creat" (OID 957)
2026-01-16 18:43:42.346 CET 1199 LOG: fastpath function call: "lo_open" (OID 952)
2026-01-16 18:43:42.346 CET 1199 LOG: fastpath function call: "lowrite" (OID 955)
2026-01-16 18:43:42.347 CET 1199 LOG: fastpath function call: "lo_close" (OID 953)
2026-01-16 18:43:42.347 CET 1199 LOG: statement: SAVEPOINT PGJDBC_AUTOSAVE
2026-01-16 18:43:42.348 CET 1199 LOG: execute <unnamed>: INSERT INTO test_blob (id, doc) VALUES ($1, $2)
2026-01-16 18:43:42.348 CET 1199 DETAIL: Parameters: $1 = '1', $2 = '16780'
2026-01-16 18:43:42.348 CET 1199 LOG: execute S_1: COMMIT
2026-01-16 18:43:42.351 CET 0 LOG: statement: BEGIN
2026-01-16 18:43:42.351 CET 0 LOG: statement: SAVEPOINT PGJDBC_AUTOSAVE
2026-01-16 18:43:42.351 CET 0 LOG: execute <unnamed>: select id, doc from test_blob
2026-01-16 18:43:42.352 CET 0 LOG: fastpath function call: "lo_open" (OID 952)
2026-01-16 18:43:42.352 CET 0 LOG: fastpath function call: "lo_open" (OID 952)
2026-01-16 18:43:42.352 CET 0 LOG: fastpath function call: "lo_lseek" (OID 956)
2026-01-16 18:43:42.352 CET 0 LOG: fastpath function call: "loread" (OID 954)
2026-01-16 18:43:42.353 CET 0 LOG: fastpath function call: "loread" (OID 954)
2026-01-16 18:43:42.353 CET 0 LOG: statement: SAVEPOINT PGJDBC_AUTOSAVE
2026-01-16 18:43:42.353 CET 0 LOG: execute <unnamed>: DROP TABLE IF EXISTS test_blob
2026-01-16 18:43:42.429 CET 0 LOG: statement: SET application_name = 'PostgreSQL JDBC Driver'
2026-01-16 18:43:42.430 CET 0 LOG: statement: BEGIN
2026-01-16 18:43:42.430 CET 0 LOG: statement: SAVEPOINT PGJDBC_AUTOSAVE
2026-01-16 18:43:42.433 CET 0 LOG: execute <unnamed>: SELECT p.proname,p.oid FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n WHERE p.pronamespace=n.oid AND n.nspname='pg_catalog' AND ( proname = 'lo_open' or proname = 'lo_close' or proname = 'lo_creat' or proname = 'lo_unlink' or proname = 'lo_lseek' or proname = 'lo_lseek64' or proname = 'lo_tell' or proname = 'lo_tell64' or proname = 'loread' or proname = 'lowrite' or proname = 'lo_truncate' or proname = 'lo_truncate64')
2026-01-16 18:43:42.433 CET 0 LOG: statement: RELEASE SAVEPOINT PGJDBC_AUTOSAVE
2026-01-16 18:43:42.434 CET 0 LOG: fastpath function call: "lo_creat" (OID 957)
2026-01-16 18:43:42.506 CET 0 LOG: statement: SET application_name = 'PostgreSQL JDBC Driver'
2026-01-16 18:43:42.507 CET 0 LOG: statement: BEGIN
2026-01-16 18:43:42.507 CET 0 LOG: statement: SAVEPOINT PGJDBC_AUTOSAVE
2026-01-16 18:43:42.508 CET 0 LOG: execute <unnamed>: select id, doc from test_blob
2026-01-16 18:43:42.508 CET 0 LOG: statement: RELEASE SAVEPOINT PGJDBC_AUTOSAVE
2026-01-16 18:43:42.508 CET 0 LOG: statement: SAVEPOINT PGJDBC_AUTOSAVE
2026-01-16 18:43:42.510 CET 0 LOG: execute <unnamed>: SELECT p.proname,p.oid FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n WHERE p.pronamespace=n.oid AND n.nspname='pg_catalog' AND ( proname = 'lo_open' or proname = 'lo_close' or proname = 'lo_creat' or proname = 'lo_unlink' or proname = 'lo_lseek' or proname = 'lo_lseek64' or proname = 'lo_tell' or proname = 'lo_tell64' or proname = 'loread' or proname = 'lowrite' or proname = 'lo_truncate' or proname = 'lo_truncate64')
2026-01-16 18:43:42.511 CET 0 LOG: statement: RELEASE SAVEPOINT PGJDBC_AUTOSAVE
2026-01-16 18:43:42.511 CET 0 LOG: fastpath function call: "lo_open" (OID 952)
2026-01-16 18:43:42.512 CET 0 LOG: could not receive data from client: An established connection was aborted by the software in your host machine.
2026-01-16 18:43:42.512 CET 0 LOG: unexpected EOF on client connection with an open transaction
```
*Stacktrace of exception when inserting oid column:*
```
org.postgresql.util.PSQLException: Unknown Response Type C.
at org.postgresql.core.v3.QueryExecutorImpl.receiveFastpathResult(QueryExecutorImpl.java:937)
at org.postgresql.core.v3.QueryExecutorImpl.fastpathCall(QueryExecutorImpl.java:669)
at org.postgresql.fastpath.Fastpath.fastpath(Fastpath.java:106)
at org.postgresql.fastpath.Fastpath.fastpath(Fastpath.java:149)
at org.postgresql.fastpath.Fastpath.getInteger(Fastpath.java:161)
at org.postgresql.fastpath.Fastpath.getOID(Fastpath.java:212)
at org.postgresql.largeobject.LargeObjectManager.createLO(LargeObjectManager.java:290)
at org.postgresql.largeobject.LargeObjectManager.createLO(LargeObjectManager.java:273)
at TestPgCleanupSavepointsWithBlob.testPgWithBlob(TestPgCleanupSavepointsWithBlob.java:54)
at TestPgCleanupSavepointsWithBlob.main(TestPgCleanupSavepointsWithBlob.java:22)
```
*Stacktrace of exception when reading oid column:*
```
org.postgresql.util.PSQLException: Unknown Response Type C.
at org.postgresql.core.v3.QueryExecutorImpl.receiveFastpathResult(QueryExecutorImpl.java:937)
at org.postgresql.core.v3.QueryExecutorImpl.fastpathCall(QueryExecutorImpl.java:669)
at org.postgresql.fastpath.Fastpath.fastpath(Fastpath.java:106)
at org.postgresql.fastpath.Fastpath.fastpath(Fastpath.java:149)
at org.postgresql.fastpath.Fastpath.getInteger(Fastpath.java:161)
at org.postgresql.largeobject.LargeObject.<init>(LargeObject.java:107)
at org.postgresql.largeobject.LargeObjectManager.open(LargeObjectManager.java:247)
at org.postgresql.largeobject.LargeObjectManager.open(LargeObjectManager.java:230)
at org.postgresql.jdbc.AbstractBlobClob.getLo(AbstractBlobClob.java:288)
at org.postgresql.jdbc.AbstractBlobClob.getBinaryStream(AbstractBlobClob.java:127)
at TestPgCleanupSavepointsWithBlob.testPgWithBlob(TestPgCleanupSavepointsWithBlob.java:75)
at TestPgCleanupSavepointsWithBlob.main(TestPgCleanupSavepointsWithBlob.java:24)
```
**Example code**
Code to replicate these errors:
```
import org.postgresql.PGConnection;
import org.postgresql.largeobject.LargeObject;
import org.postgresql.largeobject.LargeObjectManager;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Locale;
public class TestPgCleanupSavepointsWithBlob {
private static final String DB_URL = "jdbc:postgresql://localhost:5432/test";
private static final String DB_USER = "testuser";
private static final String DB_PASSWORD = "testuser";
public static void main(String[] args) {
testPgWithBlob("",
true, true, true, true, true);
testPgWithBlob("?autosave=always&cleanupSavepoints=false",
true, true, true, true, true);
testPgWithBlob("?autosave=always&cleanupSavepoints=true",
false, false, true, false, false); // insert record with blob (oid column)
testPgWithBlob("?autosave=always&cleanupSavepoints=true",
false, false, false, true, false); // query record with blob (oid column)
}
private static void testPgWithBlob(String dbUrlProperties, boolean dropTableStart,
boolean createTable, boolean insertData,
boolean executeQuery, boolean dropTableEnd) {
Locale.setDefault(Locale.ENGLISH);
try {
String dbUrlWithProp = DB_URL + dbUrlProperties;
System.out.println("Connecting to database [" + dbUrlWithProp + "] ...");
try (Connection connection = DriverManager.getConnection(dbUrlWithProp, DB_USER, DB_PASSWORD)) {
System.out.println("Connected successfully");
System.out.println("Set autocommit=false");
connection.setAutoCommit(false);
try (Statement statement = connection.createStatement()) {
if (dropTableStart) {
System.out.println("Drop table (start) ...");
statement.executeUpdate("DROP TABLE IF EXISTS test_blob");
}
if (createTable) {
System.out.println("Create table ...");
statement.executeUpdate("CREATE TABLE test_blob (id BIGINT, doc OID)");
}
if (insertData) {
System.out.println("Insert record ...");
LargeObjectManager lom = ((PGConnection) connection).getLargeObjectAPI();
long oid = lom.createLO();
LargeObject lobj = lom.open(oid, LargeObjectManager.WRITE);
byte[] bytes = {0x48, 0x65, 0x6C, 0x6C, 0x6F};
lobj.write(bytes);
lobj.close();
String sql = "INSERT INTO test_blob (id, doc) VALUES (?, ?)";
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
pstmt.setInt(1, 1);
pstmt.setLong(2, oid);
pstmt.executeUpdate();
}
connection.commit();
}
if (executeQuery) {
System.out.println("Executing query ...");
try (ResultSet resultSet = statement.executeQuery("select id, doc from test_blob")) {
while (resultSet.next()) {
System.out.println("[id] -> " + resultSet.getString(1));
Blob content = resultSet.getBlob(2);
InputStream contentInputStream = new BufferedInputStream(content.getBinaryStream());
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[1024];
while ((nRead = contentInputStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
byte[] contentArray = buffer.toByteArray();
System.out.println("[doc] -> contentArray.length=" + contentArray.length);
} catch (IOException e) {
System.err.println("I/O error occurred!");
e.printStackTrace();
}
}
}
}
if (dropTableEnd) {
System.out.println("Drop table (end) ...");
statement.executeUpdate("DROP TABLE IF EXISTS test_blob");
}
}
}
} catch (SQLException e) {
System.out.println("### Database error occurred - " + e.getMessage());
System.err.println("### Database error occurred - " + e.getMessage());
e.printStackTrace();
}
System.out.println(" - - - - - - - - - - - - - ");
}
}
```
*Output/result of execution of example code*
```
Connecting to database [jdbc:postgresql://localhost:5432/test] ...
Connected successfully
Set autocommit=false
Drop table (start) ...
Create table ...
Insert record ...
Executing query ...
[id] -> 1
[doc] -> contentArray.length=5
Drop table (end) ...
- - - - - - - - - - - - -
Connecting to database [jdbc:postgresql://localhost:5432/test?autosave=always&cleanupSavepoints=false] ...
Connected successfully
Set autocommit=false
Drop table (start) ...
Create table ...
Insert record ...
Executing query ...
[id] -> 1
[doc] -> contentArray.length=5
Drop table (end) ...
- - - - - - - - - - - - -
Connecting to database [jdbc:postgresql://localhost:5432/test?autosave=always&cleanupSavepoints=true] ...
Connected successfully
Set autocommit=false
Insert record ...
### Database error occurred: Unknown Response Type C.
- - - - - - - - - - - - -
Connecting to database [jdbc:postgresql://localhost:5432/test?autosave=always&cleanupSavepoints=true] ...
Connected successfully
Set autocommit=false
Executing query ...
[id] -> 1
### Database error occurred: Unknown Response Type C.
```
view thread (5+ messages) latest in thread
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] issue #3910: Connection parameter cleanupSavepoints=true does not work with oid/blob column
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