Skip to content

Commit

Permalink
Return correct default from PgDatabaseMetaData.getDefaultTransactionI…
Browse files Browse the repository at this point in the history
…solation (#2992)

Fixes: #2991

This commit updates `PgDatabaseMetaData.getDefaultTransactionIsolation`
to query the database for the default transaction isolation level,
instead of assuming that the default isolation level is READ COMMITTED.
  • Loading branch information
nvanbenschoten committed Nov 15, 2023
1 parent a17f1a6 commit de74292
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 1 deletion.
37 changes: 36 additions & 1 deletion pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;

Expand All @@ -53,6 +54,7 @@ public PgDatabaseMetaData(PgConnection conn) {

private int nameDataLength = 0; // length for name datatype
private int indexMaxKeys = 0; // maximum number of keys in an index.
private int defaultTransactionIsolation = 0;

protected int getMaxIndexKeys() throws SQLException {
if (indexMaxKeys == 0) {
Expand Down Expand Up @@ -957,7 +959,40 @@ public int getMaxUserNameLength() throws SQLException {
}

public int getDefaultTransactionIsolation() throws SQLException {
return Connection.TRANSACTION_READ_COMMITTED;
if (defaultTransactionIsolation == 0) {
String sql;
sql = "SELECT setting FROM pg_catalog.pg_settings WHERE name='default_transaction_isolation'";

try (Statement stmt = connection.createStatement()) {
try (ResultSet rs = stmt.executeQuery(sql)) {
String level = null;
if (rs.next()) {
level = rs.getString(1);
}
if (level == null) {
throw new PSQLException(
GT.tr(
"Unable to determine a value for DefaultTransactionIsolation due to missing "
+ "system catalog data."),
PSQLState.UNEXPECTED_ERROR);
}

level = level.toUpperCase(Locale.US);
if (level.equals("READ COMMITTED")) {
defaultTransactionIsolation = Connection.TRANSACTION_READ_COMMITTED;
} else if (level.equals("READ UNCOMMITTED")) {
defaultTransactionIsolation = Connection.TRANSACTION_READ_UNCOMMITTED;
} else if (level.equals("REPEATABLE READ")) {
defaultTransactionIsolation = Connection.TRANSACTION_REPEATABLE_READ;
} else if (level.equals("SERIALIZABLE")) {
defaultTransactionIsolation = Connection.TRANSACTION_SERIALIZABLE;
} else {
defaultTransactionIsolation = Connection.TRANSACTION_READ_COMMITTED; // Best guess.
}
}
}
}
return defaultTransactionIsolation;
}

public boolean supportsTransactions() throws SQLException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,41 @@ public void testIdentifiers() throws SQLException {

}

@Test
public void testDefaultTransactionIsolation() throws SQLException {
DatabaseMetaData dbmd = con.getMetaData();
assertNotNull(dbmd);

int transactionIsolation = dbmd.getDefaultTransactionIsolation();
assertEquals(Connection.TRANSACTION_READ_COMMITTED, transactionIsolation);

String [] isolationLevels = {"\"read committed\"","\"read uncommitted\"", "\"repeatable read\"","serializable"};
try {
for (int i = 0; i < isolationLevels.length; i++) {
con.createStatement().execute("alter database test set default_transaction_isolation to " + isolationLevels[i]);
try (Connection con1 = TestUtil.openDB()) {
transactionIsolation = con1.getMetaData().getDefaultTransactionIsolation();
switch (i) {
case 0:
assertEquals(Connection.TRANSACTION_READ_COMMITTED, transactionIsolation);
break;
case 1:
assertEquals(Connection.TRANSACTION_READ_UNCOMMITTED, transactionIsolation);
break;
case 2:
assertEquals(Connection.TRANSACTION_REPEATABLE_READ, transactionIsolation);
break;
case 3:
assertEquals(Connection.TRANSACTION_SERIALIZABLE, transactionIsolation);
break;
}
}
}
} finally {
con.createStatement().execute("alter database test set default_transaction_isolation to DEFAULT");
}
}

@Test
public void testTables() throws SQLException {
DatabaseMetaData dbmd = con.getMetaData();
Expand Down

0 comments on commit de74292

Please sign in to comment.