Skip to content

Commit e15da2e

Browse files
Backport to branch(3) : Add isConsistentVirtualTableReadGuaranteed() to StorageInfo (#3208)
Co-authored-by: Toshihiro Suzuki <[email protected]>
1 parent f49ac40 commit e15da2e

24 files changed

+241
-35
lines changed

core/src/main/java/com/scalar/db/api/DistributedStorageAdmin.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ public interface DistributedStorageAdmin extends Admin, AutoCloseable {
4747
/**
4848
* Returns the storage information.
4949
*
50+
* <p>Note: This feature is primarily for internal use. Breaking changes can and will be
51+
* introduced to it. Users should not depend on it.
52+
*
5053
* @param namespace the namespace to get the storage information for
5154
* @return the storage information
5255
* @throws ExecutionException if the operation fails

core/src/main/java/com/scalar/db/api/StorageInfo.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ public interface StorageInfo {
2222
*/
2323
int getMaxAtomicMutationsCount();
2424

25+
/**
26+
* Returns whether the storage guarantees consistent reads for virtual tables.
27+
*
28+
* @return true if the storage guarantees consistent reads for virtual tables, false otherwise
29+
*/
30+
boolean isConsistentVirtualTableReadGuaranteed();
31+
2532
/**
2633
* The mutation atomicity unit of the storage.
2734
*

core/src/main/java/com/scalar/db/common/StorageInfoImpl.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,17 @@ public class StorageInfoImpl implements StorageInfo {
1111
private final String storageName;
1212
private final MutationAtomicityUnit mutationAtomicityUnit;
1313
private final int maxAtomicMutationsCount;
14+
private final boolean consistentVirtualTableReadGuaranteed;
1415

1516
public StorageInfoImpl(
1617
String storageName,
1718
MutationAtomicityUnit mutationAtomicityUnit,
18-
int maxAtomicMutationsCount) {
19+
int maxAtomicMutationsCount,
20+
boolean consistentVirtualTableReadGuaranteed) {
1921
this.storageName = storageName;
2022
this.mutationAtomicityUnit = mutationAtomicityUnit;
2123
this.maxAtomicMutationsCount = maxAtomicMutationsCount;
24+
this.consistentVirtualTableReadGuaranteed = consistentVirtualTableReadGuaranteed;
2225
}
2326

2427
@Override
@@ -36,6 +39,11 @@ public int getMaxAtomicMutationsCount() {
3639
return maxAtomicMutationsCount;
3740
}
3841

42+
@Override
43+
public boolean isConsistentVirtualTableReadGuaranteed() {
44+
return consistentVirtualTableReadGuaranteed;
45+
}
46+
3947
@Override
4048
public boolean equals(Object o) {
4149
if (this == o) {
@@ -47,12 +55,18 @@ public boolean equals(Object o) {
4755
StorageInfoImpl that = (StorageInfoImpl) o;
4856
return getMaxAtomicMutationsCount() == that.getMaxAtomicMutationsCount()
4957
&& Objects.equals(getStorageName(), that.getStorageName())
50-
&& getMutationAtomicityUnit() == that.getMutationAtomicityUnit();
58+
&& getMutationAtomicityUnit() == that.getMutationAtomicityUnit()
59+
&& isConsistentVirtualTableReadGuaranteed()
60+
== that.isConsistentVirtualTableReadGuaranteed();
5161
}
5262

5363
@Override
5464
public int hashCode() {
55-
return Objects.hash(getStorageName(), getMutationAtomicityUnit(), getMaxAtomicMutationsCount());
65+
return Objects.hash(
66+
getStorageName(),
67+
getMutationAtomicityUnit(),
68+
getMaxAtomicMutationsCount(),
69+
isConsistentVirtualTableReadGuaranteed());
5670
}
5771

5872
@Override
@@ -61,6 +75,7 @@ public String toString() {
6175
.add("storageName", storageName)
6276
.add("mutationAtomicityUnit", mutationAtomicityUnit)
6377
.add("maxAtomicMutationsCount", maxAtomicMutationsCount)
78+
.add("consistentVirtualTableReadGuaranteed", consistentVirtualTableReadGuaranteed)
6479
.toString();
6580
}
6681
}

core/src/main/java/com/scalar/db/storage/cassandra/CassandraAdmin.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ public class CassandraAdmin implements DistributedStorageAdmin {
4949
"cassandra",
5050
StorageInfo.MutationAtomicityUnit.PARTITION,
5151
// No limit on the number of mutations
52-
Integer.MAX_VALUE);
52+
Integer.MAX_VALUE,
53+
false);
5354

5455
private final ClusterManager clusterManager;
5556
private final String systemNamespace;

core/src/main/java/com/scalar/db/storage/cosmos/CosmosAdmin.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ public class CosmosAdmin implements DistributedStorageAdmin {
7171
"cosmos",
7272
StorageInfo.MutationAtomicityUnit.PARTITION,
7373
// No limit on the number of mutations
74-
Integer.MAX_VALUE);
74+
Integer.MAX_VALUE,
75+
false);
7576

7677
private final CosmosClient client;
7778
private final String metadataDatabase;

core/src/main/java/com/scalar/db/storage/dynamo/DynamoAdmin.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ public class DynamoAdmin implements DistributedStorageAdmin {
162162
"dynamo",
163163
StorageInfo.MutationAtomicityUnit.STORAGE,
164164
// DynamoDB has a limit of 100 items per transactional batch write operation
165-
100);
165+
100,
166+
false);
166167

167168
private final DynamoDbClient client;
168169
private final ApplicationAutoScalingClient applicationAutoScalingClient;

core/src/main/java/com/scalar/db/storage/jdbc/JdbcAdmin.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,6 @@ public class JdbcAdmin implements DistributedStorageAdmin {
5353
@VisibleForTesting static final String JDBC_COL_DECIMAL_DIGITS = "DECIMAL_DIGITS";
5454

5555
private static final String INDEX_NAME_PREFIX = "index";
56-
private static final StorageInfo STORAGE_INFO =
57-
new StorageInfoImpl(
58-
"jdbc",
59-
StorageInfo.MutationAtomicityUnit.STORAGE,
60-
// No limit on the number of mutations
61-
Integer.MAX_VALUE);
6256

6357
private final RdbEngineStrategy rdbEngine;
6458
private final BasicDataSource dataSource;
@@ -984,8 +978,22 @@ public Set<String> getNamespaceNames() throws ExecutionException {
984978
}
985979

986980
@Override
987-
public StorageInfo getStorageInfo(String namespace) {
988-
return STORAGE_INFO;
981+
public StorageInfo getStorageInfo(String namespace) throws ExecutionException {
982+
boolean consistentVirtualTableReadGuaranteed;
983+
try (Connection connection = dataSource.getConnection()) {
984+
int isolationLevel = connection.getTransactionIsolation();
985+
consistentVirtualTableReadGuaranteed =
986+
isolationLevel >= rdbEngine.getMinimumIsolationLevelForConsistentVirtualTableRead();
987+
} catch (SQLException e) {
988+
throw new ExecutionException("Getting the transaction isolation level failed", e);
989+
}
990+
991+
return new StorageInfoImpl(
992+
"jdbc",
993+
StorageInfo.MutationAtomicityUnit.STORAGE,
994+
// No limit on the number of mutations
995+
Integer.MAX_VALUE,
996+
consistentVirtualTableReadGuaranteed);
989997
}
990998

991999
@Override

core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineDb2.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.scalar.db.storage.jdbc.query.SelectQuery;
2121
import com.scalar.db.storage.jdbc.query.SelectWithLimitQuery;
2222
import com.scalar.db.storage.jdbc.query.UpsertQuery;
23+
import java.sql.Connection;
2324
import java.sql.Driver;
2425
import java.sql.JDBCType;
2526
import java.sql.ResultSet;
@@ -588,4 +589,10 @@ public void throwIfCrossPartitionScanOrderingOnBlobColumnNotSupported(
588589
public String getTableNamesInNamespaceSql() {
589590
return "SELECT TABNAME FROM SYSCAT.TABLES WHERE TABSCHEMA = ? AND TYPE = 'T'";
590591
}
592+
593+
@Override
594+
public int getMinimumIsolationLevelForConsistentVirtualTableRead() {
595+
// In Db2, REPEATABLE READ and SERIALIZABLE isolation levels guarantee consistent reads
596+
return Connection.TRANSACTION_REPEATABLE_READ;
597+
}
591598
}

core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineMysql.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,4 +513,10 @@ public void setConnectionToReadOnly(Connection connection, boolean readOnly) thr
513513
public String getTableNamesInNamespaceSql() {
514514
return "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ?";
515515
}
516+
517+
@Override
518+
public int getMinimumIsolationLevelForConsistentVirtualTableRead() {
519+
// In MySQL, REPEATABLE READ and SERIALIZABLE isolation levels guarantee consistent reads
520+
return Connection.TRANSACTION_REPEATABLE_READ;
521+
}
516522
}

core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineOracle.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.scalar.db.storage.jdbc.query.UpsertQuery;
1919
import java.io.ByteArrayInputStream;
2020
import java.io.InputStream;
21+
import java.sql.Connection;
2122
import java.sql.Driver;
2223
import java.sql.JDBCType;
2324
import java.sql.PreparedStatement;
@@ -540,4 +541,10 @@ public void bindBlobColumnToPreparedStatement(
540541
public String getTableNamesInNamespaceSql() {
541542
return "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = ?";
542543
}
544+
545+
@Override
546+
public int getMinimumIsolationLevelForConsistentVirtualTableRead() {
547+
// In Oracle, only the SERIALIZABLE isolation level guarantees consistent reads
548+
return Connection.TRANSACTION_SERIALIZABLE;
549+
}
543550
}

0 commit comments

Comments
 (0)