Repository navigation
fix(spanner): show database value for unknown isolation levels - #14981
rayudu3745 wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a new method getDatabaseDefaultIsolationLevelValue() to DatabaseClient and its implementations to retrieve the raw string value of the default transaction isolation level. This allows handling unrecognized isolation levels (such as "read committed" in PostgreSQL) without throwing an exception. The feedback recommends adding @Nullable annotations to the overridden implementations of getDatabaseDefaultIsolationLevelValue() in DatabaseClientImpl and MultiplexedSessionDatabaseClient to match the interface definition. Additionally, it suggests wrapping the call to getDatabaseDefaultIsolationLevelValue() in ConnectionStatementExecutorImpl with Objects.requireNonNull to prevent potential null-safety warnings or runtime exceptions since the enclosing method returns a non-nullable string.
e051207 to
57d2d56
Compare
|
|
||
| private final String dialect; | ||
| private final IsolationLevel defaultIsolationLevel; | ||
| private final @Nullable String defaultIsolationLevelValue; |
There was a problem hiding this comment.
Would it not be better to keep both these fields? That way, you do not need to reparse the string whenever the actual isolation level enum is needed. It would also make it possible to consider the string value more as a 'view' value, meaning that we could also format it in a more logical way. E.g. PostgreSQL normally returns isolation level names in lower case and without underscores.
There was a problem hiding this comment.
Done, the enum is parsed once and the string is kept as returned by Spanner.
| private TransactionOptions.IsolationLevel getEffectiveIsolationLevel( | ||
| TransactionOptions.IsolationLevel isolationLevel) { | ||
| /** Resolves an unspecified isolation level to the database default and formats it. */ | ||
| private String getEffectiveIsolationLevel(TransactionOptions.IsolationLevel isolationLevel) { |
There was a problem hiding this comment.
I think that you can simplify this method to something like this:
private String getEffectiveIsolationLevel(TransactionOptions.IsolationLevel isolationLevel) {
if (isolationLevel != TransactionOptions.IsolationLevel.ISOLATION_LEVEL_UNSPECIFIED) {
return formatIsolationLevel(isolationLevel);
}
String databaseDefault =
getConnection().getDatabaseClient().getDatabaseDefaultIsolationLevelValue();
if (databaseDefault != null) {
return getConnection().getDialect() == Dialect.POSTGRESQL
? databaseDefault.toLowerCase(Locale.ROOT)
: databaseDefault;
}
return formatIsolationLevel(TransactionOptions.IsolationLevel.SERIALIZABLE);
}(and maybe even further if we keep both the string and enum values in DatabaseMetadata)
There was a problem hiding this comment.
Simplified as suggested. Spanner already stores these values in lower case with spaces, so the value is returned as-is.
Fixes #14967.
If the database's
default_transaction_isolationholds a value that this client doesn't recognize, the PostgreSQL isolation levelSHOWstatements failed withFAILED_PRECONDITION. They now return the value that is stored in the database, so an older client keeps working with a database that uses a newer default isolation level.read committed)SHOW TRANSACTION ISOLATION LEVELFAILED_PRECONDITIONread committedSHOW transaction_isolationFAILED_PRECONDITIONread committedSHOW default_transaction_isolationFAILED_PRECONDITIONread committedChanges
DatabaseMetadatastores thedefault_transaction_isolationvalue as returned by Spanner, and derives the isolation level from it.@InternalApimethodDatabaseClient#getDatabaseDefaultIsolationLevelValue()returns that value.SHOWstatements return it when the isolation level isUNRECOGNIZED.