Skip to content

Commit 26d8bce

Browse files
committed
Update AdminTestUtils
1 parent 604120e commit 26d8bce

File tree

7 files changed

+250
-39
lines changed

7 files changed

+250
-39
lines changed

core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminTestUtils.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package com.scalar.db.storage.cassandra;
22

3+
import com.scalar.db.config.DatabaseConfig;
34
import com.scalar.db.util.AdminTestUtils;
45
import java.util.Properties;
56

67
public class CassandraAdminTestUtils extends AdminTestUtils {
8+
private final ClusterManager clusterManager;
79

810
public CassandraAdminTestUtils(Properties properties) {
911
super(properties);
12+
DatabaseConfig databaseConfig = new DatabaseConfig(properties);
13+
clusterManager = new ClusterManager(databaseConfig);
1014
}
1115

1216
@Override
@@ -23,4 +27,19 @@ public void truncateMetadataTable() {
2327
public void corruptMetadata(String namespace, String table) {
2428
// Do nothing
2529
}
30+
31+
@Override
32+
public boolean namespaceExists(String namespace) {
33+
return clusterManager.getSession().getCluster().getMetadata().getKeyspace(namespace) != null;
34+
}
35+
36+
@Override
37+
public boolean tableExists(String namespace, String table) {
38+
return clusterManager.getMetadata(namespace, table) != null;
39+
}
40+
41+
@Override
42+
public void close() {
43+
clusterManager.close();
44+
}
2645
}

core/src/integration-test/java/com/scalar/db/storage/cosmos/CosmosAdminTestUtils.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,35 @@ public CosmosStoredProcedure getTableStoredProcedure(String namespace, String ta
9090
.getScripts()
9191
.getStoredProcedure(CosmosAdmin.STORED_PROCEDURE_FILE_NAME);
9292
}
93+
94+
@Override
95+
public boolean namespaceExists(String namespace) {
96+
try {
97+
client.getDatabase(namespace).read();
98+
} catch (CosmosException e) {
99+
if (e.getStatusCode() == CosmosErrorCode.NOT_FOUND.get()) {
100+
return false;
101+
}
102+
throw e;
103+
}
104+
return true;
105+
}
106+
107+
@Override
108+
public boolean tableExists(String namespace, String table) {
109+
try {
110+
client.getDatabase(namespace).getContainer(table).read();
111+
} catch (CosmosException e) {
112+
if (e.getStatusCode() == CosmosErrorCode.NOT_FOUND.get()) {
113+
return false;
114+
}
115+
throw e;
116+
}
117+
return true;
118+
}
119+
120+
@Override
121+
public void close() {
122+
client.close();
123+
}
93124
}

core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminTestUtils.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ private boolean waitForTableDeletion(String namespace, String table) {
7878
return false;
7979
}
8080

81-
private boolean tableExists(String nonPrefixedNamespace, String table) {
81+
@Override
82+
public boolean tableExists(String nonPrefixedNamespace, String table) {
8283
try {
8384
client.describeTable(
8485
DescribeTableRequest.builder()
@@ -137,4 +138,15 @@ public void corruptMetadata(String namespace, String table) {
137138
.item(itemValues)
138139
.build());
139140
}
141+
142+
@Override
143+
public boolean namespaceExists(String namespace) throws Exception {
144+
// Dynamo has no concept of namespace
145+
return true;
146+
}
147+
148+
@Override
149+
public void close() {
150+
client.close();
151+
}
140152
}

core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcAdminTestUtils.java

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,26 @@
66
import com.scalar.db.util.AdminTestUtils;
77
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
88
import java.sql.Connection;
9+
import java.sql.PreparedStatement;
10+
import java.sql.ResultSet;
911
import java.sql.SQLException;
12+
import java.sql.Statement;
1013
import java.util.Properties;
1114
import org.apache.commons.dbcp2.BasicDataSource;
1215

1316
public class JdbcAdminTestUtils extends AdminTestUtils {
1417

15-
private final JdbcConfig config;
1618
private final String metadataSchema;
1719
private final RdbEngineStrategy rdbEngine;
20+
private final BasicDataSource dataSource;
1821

1922
public JdbcAdminTestUtils(Properties properties) {
2023
super(properties);
21-
config = new JdbcConfig(new DatabaseConfig(properties));
24+
JdbcConfig config = new JdbcConfig(new DatabaseConfig(properties));
2225
metadataSchema =
2326
config.getTableMetadataSchema().orElse(DatabaseConfig.DEFAULT_SYSTEM_NAMESPACE_NAME);
2427
rdbEngine = RdbEngineFactory.create(config);
28+
dataSource = JdbcUtils.initDataSourceForAdmin(config, rdbEngine);
2529
}
2630

2731
@Override
@@ -53,9 +57,63 @@ public void corruptMetadata(String namespace, String table) throws Exception {
5357
}
5458

5559
private void execute(String sql) throws SQLException {
56-
try (BasicDataSource dataSource = JdbcUtils.initDataSourceForAdmin(config, rdbEngine);
57-
Connection connection = dataSource.getConnection()) {
60+
try (Connection connection = dataSource.getConnection()) {
5861
JdbcAdmin.execute(connection, sql);
5962
}
6063
}
64+
65+
@Override
66+
public boolean namespaceExists(String namespace) throws SQLException {
67+
String sql;
68+
if (JdbcTestUtils.isMysql(rdbEngine)) {
69+
sql = "SELECT 1 FROM information_schema.schemata WHERE schema_name = ?";
70+
} else if (JdbcTestUtils.isOracle(rdbEngine)) {
71+
sql = "SELECT 1 FROM all_users WHERE username = ?";
72+
} else if (JdbcTestUtils.isPostgresql(rdbEngine)) {
73+
sql = "SELECT 1 FROM pg_namespace WHERE nspname = ?";
74+
} else if (JdbcTestUtils.isSqlite(rdbEngine)) {
75+
// SQLite has no concept of namespace
76+
return true;
77+
} else if (JdbcTestUtils.isSqlServer(rdbEngine)) {
78+
sql = "SELECT 1 FROM sys.schemas WHERE name = ?";
79+
} else if (JdbcTestUtils.isDb2(rdbEngine)) {
80+
sql = "SELECT 1 FROM syscat.schemata WHERE schemaname = ?";
81+
} else {
82+
throw new AssertionError("Unsupported engine : " + rdbEngine.getClass().getSimpleName());
83+
}
84+
85+
try (Connection connection = dataSource.getConnection();
86+
PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
87+
preparedStatement.setString(1, namespace);
88+
ResultSet resultSet = preparedStatement.executeQuery();
89+
90+
return resultSet.next();
91+
}
92+
}
93+
94+
@Override
95+
public boolean tableExists(String namespace, String table) throws Exception {
96+
String fullTableName = rdbEngine.encloseFullTableName(namespace, table);
97+
String sql = rdbEngine.tableExistsInternalTableCheckSql(fullTableName);
98+
try (Connection connection = dataSource.getConnection();
99+
Statement statement = connection.createStatement()) {
100+
statement.execute(sql);
101+
return true;
102+
} catch (SQLException e) {
103+
// An exception will be thrown if the table does not exist when executing the select
104+
// query
105+
if (rdbEngine.isUndefinedTableError(e)) {
106+
return false;
107+
}
108+
throw new Exception(
109+
String.format(
110+
"Checking if the %s table exists failed", getFullTableName(namespace, table)),
111+
e);
112+
}
113+
}
114+
115+
@Override
116+
public void close() throws SQLException {
117+
dataSource.close();
118+
}
61119
}

core/src/integration-test/java/com/scalar/db/storage/multistorage/MultiStorageAdminTestUtils.java

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,44 @@
33
import static com.scalar.db.util.ScalarDbUtils.getFullTableName;
44

55
import com.scalar.db.config.DatabaseConfig;
6+
import com.scalar.db.storage.cassandra.ClusterManager;
67
import com.scalar.db.storage.jdbc.JdbcAdmin;
78
import com.scalar.db.storage.jdbc.JdbcConfig;
9+
import com.scalar.db.storage.jdbc.JdbcTestUtils;
810
import com.scalar.db.storage.jdbc.JdbcUtils;
911
import com.scalar.db.storage.jdbc.RdbEngineFactory;
1012
import com.scalar.db.storage.jdbc.RdbEngineOracle;
1113
import com.scalar.db.storage.jdbc.RdbEngineStrategy;
1214
import com.scalar.db.util.AdminTestUtils;
1315
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
1416
import java.sql.Connection;
17+
import java.sql.PreparedStatement;
18+
import java.sql.ResultSet;
1519
import java.sql.SQLException;
1620
import java.sql.Statement;
1721
import java.util.Properties;
1822
import org.apache.commons.dbcp2.BasicDataSource;
1923

2024
public class MultiStorageAdminTestUtils extends AdminTestUtils {
21-
25+
// for Cassandra
26+
private final ClusterManager clusterManager;
27+
// for JDBC
2228
private final JdbcConfig jdbcConfig;
2329
private final String jdbcMetadataSchema;
2430
private final RdbEngineStrategy rdbEngine;
31+
private final BasicDataSource dataSource;
2532

2633
public MultiStorageAdminTestUtils(Properties cassandraProperties, Properties jdbcProperties) {
2734
// Cassandra has the coordinator tables
2835
super(cassandraProperties);
36+
clusterManager = new ClusterManager(new DatabaseConfig(cassandraProperties));
2937

38+
// for JDBC
3039
jdbcConfig = new JdbcConfig(new DatabaseConfig(jdbcProperties));
3140
jdbcMetadataSchema =
3241
jdbcConfig.getTableMetadataSchema().orElse(DatabaseConfig.DEFAULT_SYSTEM_NAMESPACE_NAME);
3342
rdbEngine = RdbEngineFactory.create(jdbcConfig);
43+
dataSource = JdbcUtils.initDataSourceForAdmin(jdbcConfig, rdbEngine);
3444
}
3545

3646
@Override
@@ -77,11 +87,97 @@ public void corruptMetadata(String namespace, String table) throws Exception {
7787
execute(insertCorruptedMetadataStatement);
7888
}
7989

90+
@Override
91+
public boolean namespaceExists(String namespace) throws SQLException {
92+
boolean existsOnCassandra = namespaceExistsOnCassandra(namespace);
93+
boolean existsOnJdbc = namespaceExistsOnJdbc(namespace);
94+
95+
if (existsOnCassandra && existsOnJdbc) {
96+
throw new IllegalStateException(
97+
"The " + namespace + " namespace should not exist on both storages");
98+
}
99+
return existsOnCassandra || existsOnJdbc;
100+
}
101+
102+
private boolean namespaceExistsOnCassandra(String namespace) {
103+
return clusterManager.getSession().getCluster().getMetadata().getKeyspace(namespace) != null;
104+
}
105+
106+
private boolean namespaceExistsOnJdbc(String namespace) throws SQLException {
107+
String sql;
108+
// RdbEngine classes are not publicly exposed, so we test the type using hard coded class name
109+
if (JdbcTestUtils.isMysql(rdbEngine)) {
110+
sql = "SELECT 1 FROM information_schema.schemata WHERE schema_name = ?";
111+
} else if (JdbcTestUtils.isPostgresql(rdbEngine)) {
112+
sql = "SELECT 1 FROM pg_namespace WHERE nspname = ?";
113+
} else if (JdbcTestUtils.isOracle(rdbEngine)) {
114+
sql = "SELECT 1 FROM all_users WHERE username = ?";
115+
} else if (JdbcTestUtils.isSqlServer(rdbEngine)) {
116+
sql = "SELECT 1 FROM sys.schemas WHERE name = ?";
117+
} else if (JdbcTestUtils.isSqlite(rdbEngine)) {
118+
// SQLite has no concept of namespace
119+
return true;
120+
} else {
121+
throw new AssertionError("Unsupported engine : " + rdbEngine.getClass().getSimpleName());
122+
}
123+
124+
try (Connection connection = dataSource.getConnection();
125+
PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
126+
preparedStatement.setString(1, namespace);
127+
ResultSet resultSet = preparedStatement.executeQuery();
128+
129+
return resultSet.next();
130+
}
131+
}
132+
133+
@Override
134+
public boolean tableExists(String namespace, String table) throws Exception {
135+
boolean existsOnCassandra = tableExistsOnCassandra(namespace, table);
136+
boolean existsOnJdbc = tableExistsOnJdbc(namespace, table);
137+
if (existsOnCassandra && existsOnJdbc) {
138+
throw new IllegalStateException(
139+
String.format(
140+
"The %s table should not exist on both storages",
141+
getFullTableName(namespace, table)));
142+
}
143+
return existsOnCassandra || existsOnJdbc;
144+
}
145+
146+
private boolean tableExistsOnCassandra(String namespace, String table) {
147+
return clusterManager.getMetadata(namespace, table) != null;
148+
}
149+
150+
private boolean tableExistsOnJdbc(String namespace, String table) throws Exception {
151+
String fullTableName = rdbEngine.encloseFullTableName(namespace, table);
152+
String sql = rdbEngine.tableExistsInternalTableCheckSql(fullTableName);
153+
try (Connection connection = dataSource.getConnection();
154+
Statement statement = connection.createStatement()) {
155+
statement.execute(sql);
156+
return true;
157+
} catch (SQLException e) {
158+
// An exception will be thrown if the table does not exist when executing the select
159+
// query
160+
if (rdbEngine.isUndefinedTableError(e)) {
161+
return false;
162+
}
163+
throw new Exception(
164+
String.format(
165+
"Checking if the %s table exists failed", getFullTableName(namespace, table)),
166+
e);
167+
}
168+
}
169+
80170
private void execute(String sql) throws SQLException {
81171
try (BasicDataSource dataSource = JdbcUtils.initDataSourceForAdmin(jdbcConfig, rdbEngine);
82172
Connection connection = dataSource.getConnection();
83173
Statement stmt = connection.createStatement()) {
84174
stmt.execute(sql);
85175
}
86176
}
177+
178+
@Override
179+
public void close() throws SQLException {
180+
clusterManager.close();
181+
dataSource.close();
182+
}
87183
}

integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminPermissionIntegrationTestBase.java

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -253,22 +253,6 @@ public void tableExists_WithSufficientPermission_ShouldSucceed() throws Executio
253253
.doesNotThrowAnyException();
254254
}
255255

256-
@Test
257-
public void repairNamespace_WithSufficientPermission_ShouldSucceed() throws Exception {
258-
// Arrange
259-
createNamespaceByRoot();
260-
// Drop the namespaces table to simulate a repair scenario
261-
AdminTestUtils adminTestUtils = getAdminTestUtils(TEST_NAME);
262-
try {
263-
adminTestUtils.dropNamespacesTable();
264-
} finally {
265-
adminTestUtils.close();
266-
}
267-
// Act Assert
268-
assertThatCode(() -> adminForNormalUser.repairNamespace(NAMESPACE, getCreationOptions()))
269-
.doesNotThrowAnyException();
270-
}
271-
272256
@Test
273257
public void repairTable_WithSufficientPermission_ShouldSucceed() throws Exception {
274258
// Arrange
@@ -310,7 +294,6 @@ public void importTable_WithSufficientPermission_ShouldSucceed() throws Exceptio
310294
createTableByRoot();
311295
AdminTestUtils adminTestUtils = getAdminTestUtils(TEST_NAME);
312296
try {
313-
adminTestUtils.dropNamespacesTable();
314297
adminTestUtils.dropMetadataTable();
315298
} finally {
316299
adminTestUtils.close();
@@ -328,22 +311,6 @@ public void getNamespaceNames_WithSufficientPermission_ShouldSucceed() throws Ex
328311
assertThatCode(() -> adminForNormalUser.getNamespaceNames()).doesNotThrowAnyException();
329312
}
330313

331-
@Test
332-
public void upgrade_WithSufficientPermission_ShouldSucceed() throws Exception {
333-
// Arrange
334-
createNamespaceByRoot();
335-
createTableByRoot();
336-
AdminTestUtils adminTestUtils = getAdminTestUtils(TEST_NAME);
337-
try {
338-
adminTestUtils.dropNamespacesTable();
339-
} finally {
340-
adminTestUtils.close();
341-
}
342-
// Act Assert
343-
assertThatCode(() -> adminForNormalUser.upgrade(getCreationOptions()))
344-
.doesNotThrowAnyException();
345-
}
346-
347314
protected abstract Properties getProperties(String testName);
348315

349316
protected abstract Properties getPropertiesForNormalUser(String testName);

0 commit comments

Comments
 (0)