Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backpatch PR#2247 fix: handle ParameterStatus messages in QueryExecutorImpl.receiveFastpathResult #2249

Merged
merged 2 commits into from Sep 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions pgjdbc/src/main/java/org/postgresql/core/v3/QueryExecutorImpl.java
Expand Up @@ -847,6 +847,19 @@ private void setSocketTimeout(int millis) throws PSQLException {

break;

case 'S': // Parameter Status
try {
receiveParameterStatus();
} catch (SQLException e) {
if (error == null) {
error = e;
} else {
error.setNextException(e);
}
endQuery = true;
}
break;

default:
throw new PSQLException(GT.tr("Unknown Response Type {0}.", (char) c),
PSQLState.CONNECTION_FAILURE);
Expand Down
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2021, PostgreSQL Global Development Group
* See the LICENSE file in the project root for more information.
*/

package org.postgresql.jdbc;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;

import org.postgresql.largeobject.LargeObjectManager;
import org.postgresql.test.TestUtil;
import org.postgresql.util.PSQLException;
import org.postgresql.util.PSQLState;

import org.junit.jupiter.api.Test;

import java.sql.Statement;

class LargeObjectManagerTest {

/*
* It is possible for PostgreSQL to send a ParameterStatus message after an ErrorResponse
* Receiving such a message should not lead to an invalid connection state
* See https://github.com/pgjdbc/pgjdbc/issues/2237
*/
@Test
public void testOpenWithErrorAndSubsequentParameterStatusMessageShouldLeaveConnectionInUsableStateAndUpdateParameterStatus() throws Exception {
try (PgConnection con = (PgConnection) TestUtil.openDB()) {
con.setAutoCommit(false);
String originalApplicationName = con.getParameterStatus("application_name");
try (Statement statement = con.createStatement()) {
statement.execute("begin;");
// Set transaction application_name to trigger ParameterStatus message after error
// https://www.postgresql.org/docs/14/protocol-flow.html#PROTOCOL-ASYNC
String updatedApplicationName = "LargeObjectManagerTest-application-name";
statement.execute("set application_name to '" + updatedApplicationName + "'");

LargeObjectManager loManager = con.getLargeObjectAPI();
try {
loManager.open(0, false);
fail("Succeeded in opening a non-existent large object");
} catch (PSQLException e) {
assertEquals(PSQLState.UNDEFINED_OBJECT.getState(), e.getSQLState());
}

// Should be reset to original application name
assertEquals(originalApplicationName, con.getParameterStatus("application_name"));
}
}
}
}