-
Notifications
You must be signed in to change notification settings - Fork 819
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
Return correct default from PgDatabaseMetaData.getDefaultTransactionIsolation #2992
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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; | ||
|
||
|
@@ -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) { | ||
|
@@ -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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If it does a buest guess here, it should do one above as well instead of throwing an exception. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't agree. The error is being thrown on a relatively straightforward query. If that fails, something has gone wrong. |
||
} | ||
} | ||
} | ||
} | ||
return defaultTransactionIsolation; | ||
} | ||
|
||
public boolean supportsTransactions() throws SQLException { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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; | ||
Comment on lines
+165
to
+176
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Technically speaking, Java 8 supports There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. agreed |
||
} | ||
} | ||
} | ||
} finally { | ||
con.createStatement().execute("alter database test set default_transaction_isolation to DEFAULT"); | ||
} | ||
} | ||
|
||
@Test | ||
public void testTables() throws SQLException { | ||
DatabaseMetaData dbmd = con.getMetaData(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like the current PG implementation caches
default_transaction_isolation
, and it requires client to-reconnect to observe the changed value. I believe it sounds like a bug, and it is not documented: https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-ISOLATIONAt the same time, the javadoc for
getDefaultTransactionIsolation
saysRetrieves this database's default transaction isolation level
, so we should probably refrain from caching the isolation at the driver level unless we implement cache invalidation properly