Skip to content

Commit

Permalink
fix: inconsistent behaviour of BlobInputStream.reset()
Browse files Browse the repository at this point in the history
A BlobInputStream will start reading from the current position of the LargeObject used to create it, but the current/marked position does not account for this.
Initialising current position correctly will fix this.

Closes pgjdbc#3149
  • Loading branch information
OrangeDog committed Mar 5, 2024
1 parent b591b9f commit e417dd6
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 13 deletions.
Expand Up @@ -76,7 +76,7 @@ public BlobInputStream(LargeObject lo) {
*/

public BlobInputStream(LargeObject lo, int bsize) {
this(lo, bsize, Long.MAX_VALUE);
this(lo, bsize, -1);
}

/**
Expand All @@ -90,8 +90,24 @@ public BlobInputStream(LargeObject lo, int bsize, long limit) {
// The very first read multiplies the last buffer size by two, so we divide by two to get
// the first read to be exactly the initial buffer size
this.lastBufferSize = INITIAL_BUFFER_SIZE / 2;

try {
// initialise current position for mark/reset
this.absolutePosition = lo.tell64();
} catch (SQLException e1) {
try {
// the tell64 function does not exist before PostgreSQL 9.3
this.absolutePosition = lo.tell();
} catch (SQLException e2) {
RuntimeException e3 = new RuntimeException("Failed to create BlobInputStream", e1);
e3.addSuppressed(e2);
throw e3;
}
}

// Treat -1 as no limit for backward compatibility
this.limit = limit == -1 ? Long.MAX_VALUE : limit;
this.limit = limit == -1 ? Long.MAX_VALUE : limit + this.absolutePosition;
this.markPosition = this.absolutePosition;
}

/**
Expand Down
52 changes: 41 additions & 11 deletions pgjdbc/src/test/java/org/postgresql/test/jdbc2/BlobTest.java
Expand Up @@ -207,17 +207,47 @@ void markResetStream() throws Exception {
LargeObjectManager lom = ((PGConnection) con).getLargeObjectAPI();

long oid = rs.getLong(1);
LargeObject blob = lom.open(oid);
InputStream bis = blob.getInputStream();

assertEquals('<', bis.read());
bis.mark(4);
assertEquals('?', bis.read());
assertEquals('x', bis.read());
assertEquals('m', bis.read());
assertEquals('l', bis.read());
bis.reset();
assertEquals('?', bis.read());
try (LargeObject blob = lom.open(oid)) {
InputStream bis = blob.getInputStream();

assertEquals('<', bis.read());
bis.mark(4);
assertEquals('?', bis.read());
assertEquals('x', bis.read());
assertEquals('m', bis.read());
assertEquals('l', bis.read());
bis.reset();
assertEquals('?', bis.read());
}
}
}
}

@Test
void markResetWithInitialOffset() throws Exception {
assertTrue(uploadFile(TEST_FILE, NATIVE_STREAM) > 0);

try (Statement stmt = con.createStatement()) {
try (ResultSet rs = stmt.executeQuery("SELECT lo FROM testblob where id = '/test-file.xml'")) {
assertTrue(rs.next());

LargeObjectManager lom = ((PGConnection) con).getLargeObjectAPI();

long oid = rs.getLong(1);
try (LargeObject blob = lom.open(oid)) {
blob.seek(4);
InputStream bis = blob.getInputStream();

assertEquals('l', bis.read());
bis.reset();
assertEquals('l', bis.read());
assertEquals(' ', bis.read());
bis.mark(4);
assertEquals('v', bis.read());
assertEquals('e', bis.read());
bis.reset();
assertEquals('v', bis.read());
}
}
}
}
Expand Down

0 comments on commit e417dd6

Please sign in to comment.