Skip to content

Commit 4a4d176

Browse files
KodaiDfeeblefakie
andauthored
Add alter column type tests for imported tables (#3058)
Co-authored-by: Hiroyuki Yamada <mogwaing@gmail.com>
1 parent d15013f commit 4a4d176

File tree

4 files changed

+410
-1
lines changed

4 files changed

+410
-1
lines changed

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

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
package com.scalar.db.storage.jdbc;
22

3+
import static org.assertj.core.api.Assertions.assertThat;
4+
35
import com.scalar.db.api.DistributedStorageAdminImportTableIntegrationTestBase;
6+
import com.scalar.db.api.TableMetadata;
47
import com.scalar.db.exception.storage.ExecutionException;
8+
import com.scalar.db.io.DataType;
59
import java.sql.SQLException;
10+
import java.util.Collections;
611
import java.util.List;
12+
import java.util.Objects;
713
import java.util.Properties;
814
import org.junit.jupiter.api.Test;
915
import org.junit.jupiter.api.condition.DisabledIf;
@@ -47,16 +53,51 @@ protected List<TestData> createExistingDatabaseWithAllDataTypes() throws SQLExce
4753
return testUtils.createExistingDatabaseWithAllDataTypes(getNamespace());
4854
}
4955

56+
@Override
57+
protected List<String> getIntCompatibleColumnNamesOnExistingDatabase(String table) {
58+
return testUtils.getIntCompatibleColumnNamesOnExistingDatabase(table);
59+
}
60+
61+
@Override
62+
protected List<String> getFloatCompatibleColumnNamesOnExistingDatabase(String table) {
63+
return testUtils.getFloatCompatibleColumnNamesOnExistingDatabase(table);
64+
}
65+
5066
@Override
5167
protected void dropNonImportableTable(String table) throws SQLException {
5268
testUtils.dropTable(getNamespace(), table);
5369
}
5470

71+
@SuppressWarnings("unused")
72+
private boolean isOracle() {
73+
return JdbcEnv.isOracle();
74+
}
75+
76+
@SuppressWarnings("unused")
77+
private boolean isSqlServer() {
78+
return JdbcEnv.isSqlServer();
79+
}
80+
81+
@SuppressWarnings("unused")
82+
private boolean isDb2() {
83+
return JdbcEnv.isDb2();
84+
}
85+
5586
@SuppressWarnings("unused")
5687
private boolean isSqlite() {
5788
return JdbcEnv.isSqlite();
5889
}
5990

91+
@SuppressWarnings("unused")
92+
private boolean isColumnTypeConversionToTextNotFullySupported() {
93+
return JdbcEnv.isDb2() || JdbcEnv.isSqlServer() || JdbcEnv.isOracle() || JdbcEnv.isSqlite();
94+
}
95+
96+
@SuppressWarnings("unused")
97+
private boolean isWideningColumnTypeConversionNotFullySupported() {
98+
return JdbcEnv.isOracle() || JdbcEnv.isSqlite();
99+
}
100+
60101
@Test
61102
@Override
62103
@DisabledIf("isSqlite")
@@ -71,4 +112,155 @@ public void importTable_ForUnsupportedDatabase_ShouldThrowUnsupportedOperationEx
71112
throws ExecutionException {
72113
super.importTable_ForUnsupportedDatabase_ShouldThrowUnsupportedOperationException();
73114
}
115+
116+
@Test
117+
@Override
118+
@DisabledIf("isColumnTypeConversionToTextNotFullySupported")
119+
public void
120+
alterColumnType_AlterColumnTypeFromEachExistingDataTypeToText_ForImportedTable_ShouldAlterColumnTypesCorrectly()
121+
throws Exception {
122+
super
123+
.alterColumnType_AlterColumnTypeFromEachExistingDataTypeToText_ForImportedTable_ShouldAlterColumnTypesCorrectly();
124+
}
125+
126+
@Test
127+
@EnabledIf("isSqlServer")
128+
public void
129+
alterColumnType_SqlServer_AlterColumnTypeFromEachExistingDataTypeToText_ForImportedTable_ShouldAlterColumnTypesCorrectly()
130+
throws Exception {
131+
// Arrange
132+
testDataList.addAll(createExistingDatabaseWithAllDataTypes());
133+
for (TestData testData : testDataList) {
134+
if (testData.isImportableTable()) {
135+
admin.importTable(
136+
getNamespace(),
137+
testData.getTableName(),
138+
Collections.emptyMap(),
139+
testData.getOverrideColumnsType());
140+
}
141+
}
142+
143+
for (TestData testData : testDataList) {
144+
if (testData.isImportableTable()) {
145+
// Act
146+
TableMetadata metadata = testData.getTableMetadata();
147+
for (String column : metadata.getColumnNames()) {
148+
if (!metadata.getPartitionKeyNames().contains(column)
149+
&& !metadata.getClusteringKeyNames().contains(column)) {
150+
if (Objects.equals(column, "col16")) {
151+
// Conversion from IMAGE to VARCHAR(8000) is not supported in SQL Server engine
152+
continue;
153+
}
154+
admin.alterColumnType(getNamespace(), testData.getTableName(), column, DataType.TEXT);
155+
}
156+
}
157+
158+
// Assert
159+
TableMetadata newMetadata = admin.getTableMetadata(getNamespace(), testData.getTableName());
160+
assertThat(newMetadata).isNotNull();
161+
for (String column : metadata.getColumnNames()) {
162+
if (!metadata.getPartitionKeyNames().contains(column)
163+
&& !metadata.getClusteringKeyNames().contains(column)) {
164+
if (Objects.equals(column, "col16")) {
165+
continue;
166+
}
167+
assertThat(newMetadata.getColumnDataType(column)).isEqualTo(DataType.TEXT);
168+
}
169+
}
170+
}
171+
}
172+
}
173+
174+
@Test
175+
@EnabledIf("isDb2")
176+
public void
177+
alterColumnType_Db2_AlterColumnTypeFromEachExistingDataTypeToText_ForImportedTable_ShouldAlterColumnTypesCorrectly()
178+
throws Exception {
179+
// Arrange
180+
testDataList.addAll(createExistingDatabaseWithAllDataTypes());
181+
for (TestData testData : testDataList) {
182+
if (testData.isImportableTable()) {
183+
admin.importTable(
184+
getNamespace(),
185+
testData.getTableName(),
186+
Collections.emptyMap(),
187+
testData.getOverrideColumnsType());
188+
}
189+
}
190+
191+
for (TestData testData : testDataList) {
192+
if (testData.isImportableTable()) {
193+
// Act
194+
TableMetadata metadata = testData.getTableMetadata();
195+
for (String column : metadata.getColumnNames()) {
196+
if (!metadata.getPartitionKeyNames().contains(column)
197+
&& !metadata.getClusteringKeyNames().contains(column)) {
198+
if (metadata.getColumnDataType(column).equals(DataType.BLOB)) {
199+
// Conversion from BLOB to TEXT is not supported in Db2 engine
200+
continue;
201+
}
202+
admin.alterColumnType(getNamespace(), testData.getTableName(), column, DataType.TEXT);
203+
}
204+
}
205+
206+
// Assert
207+
TableMetadata newMetadata = admin.getTableMetadata(getNamespace(), testData.getTableName());
208+
assertThat(newMetadata).isNotNull();
209+
for (String column : metadata.getColumnNames()) {
210+
if (!metadata.getPartitionKeyNames().contains(column)
211+
&& !metadata.getClusteringKeyNames().contains(column)) {
212+
if (metadata.getColumnDataType(column).equals(DataType.BLOB)) {
213+
continue;
214+
}
215+
assertThat(newMetadata.getColumnDataType(column)).isEqualTo(DataType.TEXT);
216+
}
217+
}
218+
}
219+
}
220+
}
221+
222+
@Test
223+
@Override
224+
@DisabledIf("isWideningColumnTypeConversionNotFullySupported")
225+
public void alterColumnType_WideningConversion_ForImportedTable_ShouldAlterProperly()
226+
throws Exception {
227+
super.alterColumnType_WideningConversion_ForImportedTable_ShouldAlterProperly();
228+
}
229+
230+
@Test
231+
@EnabledIf("isOracle")
232+
public void alterColumnType_Oracle_WideningConversion_ForImportedTable_ShouldAlterProperly()
233+
throws Exception {
234+
// Arrange
235+
testDataList.addAll(createExistingDatabaseWithAllDataTypes());
236+
for (TestData testData : testDataList) {
237+
if (testData.isImportableTable()) {
238+
admin.importTable(
239+
getNamespace(),
240+
testData.getTableName(),
241+
Collections.emptyMap(),
242+
testData.getOverrideColumnsType());
243+
}
244+
}
245+
246+
for (TestData testData : testDataList) {
247+
if (testData.isImportableTable()) {
248+
// Act
249+
for (String intCompatibleColumn :
250+
getIntCompatibleColumnNamesOnExistingDatabase(testData.getTableName())) {
251+
admin.alterColumnType(
252+
getNamespace(), testData.getTableName(), intCompatibleColumn, DataType.BIGINT);
253+
}
254+
// Conversion from FLOAT TO DOUBLE is not supported in Oracle engine
255+
256+
// Assert
257+
TableMetadata metadata = admin.getTableMetadata(getNamespace(), testData.getTableName());
258+
assertThat(metadata).isNotNull();
259+
for (String intCompatibleColumn :
260+
getIntCompatibleColumnNamesOnExistingDatabase(testData.getTableName())) {
261+
assertThat(metadata.getColumnDataType(intCompatibleColumn)).isEqualTo(DataType.BIGINT);
262+
}
263+
}
264+
}
265+
}
74266
}

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

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,38 @@ public List<TestData> createExistingDatabaseWithAllDataTypes(String namespace)
146146
}
147147
}
148148

149+
public List<String> getIntCompatibleColumnNamesOnExistingDatabase(String table) {
150+
if (JdbcTestUtils.isMysql(rdbEngine)) {
151+
return getIntCompatibleColumnNamesOnExistingMysqlDatabase(table);
152+
} else if (JdbcTestUtils.isPostgresql(rdbEngine)) {
153+
return getIntCompatibleColumnNamesOnExistingPostgresDatabase(table);
154+
} else if (JdbcTestUtils.isOracle(rdbEngine)) {
155+
return getIntCompatibleColumnNamesOnExistingOracleDatabase(table);
156+
} else if (JdbcTestUtils.isSqlServer(rdbEngine)) {
157+
return getIntCompatibleColumnNamesOnExistingSqlServerDatabase(table);
158+
} else if (JdbcTestUtils.isDb2(rdbEngine)) {
159+
return getIntCompatibleColumnNamesOnExistingDb2Database(table);
160+
} else {
161+
throw new AssertionError("Unsupported database engine: " + rdbEngine);
162+
}
163+
}
164+
165+
public List<String> getFloatCompatibleColumnNamesOnExistingDatabase(String table) {
166+
if (JdbcTestUtils.isMysql(rdbEngine)) {
167+
return getFloatCompatibleColumnNamesOnExistingMysqlDatabase(table);
168+
} else if (JdbcTestUtils.isPostgresql(rdbEngine)) {
169+
return getFloatCompatibleColumnNamesOnExistingPostgresDatabase(table);
170+
} else if (JdbcTestUtils.isOracle(rdbEngine)) {
171+
return getFloatCompatibleColumnNamesOnExistingOracleDatabase(table);
172+
} else if (JdbcTestUtils.isSqlServer(rdbEngine)) {
173+
return getFloatCompatibleColumnNamesOnExistingSqlServerDatabase(table);
174+
} else if (JdbcTestUtils.isDb2(rdbEngine)) {
175+
return getFloatCompatibleColumnNamesOnExistingDb2Database(table);
176+
} else {
177+
throw new AssertionError("Unsupported database engine: " + rdbEngine);
178+
}
179+
}
180+
149181
public void dropTable(String namespace, String table) throws SQLException {
150182
String dropTable = "DROP TABLE " + rdbEngine.encloseFullTableName(namespace, table);
151183
execute(dropTable);
@@ -612,6 +644,22 @@ private List<TestData> createExistingMysqlDatabaseWithAllDataTypes(String namesp
612644
return ImmutableList.copyOf(data);
613645
}
614646

647+
private ImmutableList<String> getIntCompatibleColumnNamesOnExistingMysqlDatabase(String table) {
648+
if (table.equals(SUPPORTED_TABLE_NAME)) {
649+
return ImmutableList.of("col02", "col04", "col05", "col06");
650+
} else {
651+
throw new IllegalArgumentException("Table does not exist: " + table);
652+
}
653+
}
654+
655+
private ImmutableList<String> getFloatCompatibleColumnNamesOnExistingMysqlDatabase(String table) {
656+
if (table.equals(SUPPORTED_TABLE_NAME)) {
657+
return ImmutableList.of("col08");
658+
} else {
659+
throw new IllegalArgumentException("Table does not exist: " + table);
660+
}
661+
}
662+
615663
private List<TestData> createExistingPostgresDatabaseWithAllDataTypes(String namespace)
616664
throws SQLException {
617665
List<JdbcTestData> data = new ArrayList<>();
@@ -646,6 +694,24 @@ private List<TestData> createExistingPostgresDatabaseWithAllDataTypes(String nam
646694
return ImmutableList.copyOf(data);
647695
}
648696

697+
private ImmutableList<String> getIntCompatibleColumnNamesOnExistingPostgresDatabase(
698+
String table) {
699+
if (table.equals(SUPPORTED_TABLE_NAME)) {
700+
return ImmutableList.of("col02", "col03");
701+
} else {
702+
throw new IllegalArgumentException("Table does not exist: " + table);
703+
}
704+
}
705+
706+
private ImmutableList<String> getFloatCompatibleColumnNamesOnExistingPostgresDatabase(
707+
String table) {
708+
if (table.equals(SUPPORTED_TABLE_NAME)) {
709+
return ImmutableList.of("col05");
710+
} else {
711+
throw new IllegalArgumentException("Table does not exist: " + table);
712+
}
713+
}
714+
649715
private List<TestData> createExistingOracleDatabaseWithAllDataTypes(String namespace)
650716
throws SQLException {
651717
List<JdbcTestData> data = new ArrayList<>();
@@ -697,6 +763,27 @@ private List<TestData> createExistingOracleDatabaseWithAllDataTypes(String names
697763
return ImmutableList.copyOf(data);
698764
}
699765

766+
private ImmutableList<String> getIntCompatibleColumnNamesOnExistingOracleDatabase(String table) {
767+
if (table.equals(SUPPORTED_TABLE_NAME)) {
768+
return ImmutableList.of();
769+
} else if (table.equals(SUPPORTED_TABLE_NAME + "_long_raw")) {
770+
return ImmutableList.of();
771+
} else {
772+
throw new IllegalArgumentException("Table does not exist: " + table);
773+
}
774+
}
775+
776+
private ImmutableList<String> getFloatCompatibleColumnNamesOnExistingOracleDatabase(
777+
String table) {
778+
if (table.equals(SUPPORTED_TABLE_NAME)) {
779+
return ImmutableList.of("col04");
780+
} else if (table.equals(SUPPORTED_TABLE_NAME + "_long_raw")) {
781+
return ImmutableList.of();
782+
} else {
783+
throw new IllegalArgumentException("Table does not exist: " + table);
784+
}
785+
}
786+
700787
private List<TestData> createExistingSqlServerDatabaseWithAllDataTypes(String namespace)
701788
throws SQLException {
702789
List<JdbcTestData> data = new ArrayList<>();
@@ -723,6 +810,24 @@ private List<TestData> createExistingSqlServerDatabaseWithAllDataTypes(String na
723810
return ImmutableList.copyOf(data);
724811
}
725812

813+
private ImmutableList<String> getIntCompatibleColumnNamesOnExistingSqlServerDatabase(
814+
String table) {
815+
if (table.equals(SUPPORTED_TABLE_NAME)) {
816+
return ImmutableList.of("col02", "col03", "col04");
817+
} else {
818+
throw new IllegalArgumentException("Table does not exist: " + table);
819+
}
820+
}
821+
822+
private ImmutableList<String> getFloatCompatibleColumnNamesOnExistingSqlServerDatabase(
823+
String table) {
824+
if (table.equals(SUPPORTED_TABLE_NAME)) {
825+
return ImmutableList.of("col06");
826+
} else {
827+
throw new IllegalArgumentException("Table does not exist: " + table);
828+
}
829+
}
830+
726831
private List<TestData> createExistingDb2DatabaseWithAllDataTypes(String namespace)
727832
throws SQLException {
728833
List<JdbcTestData> data = new ArrayList<>();
@@ -749,6 +854,22 @@ private List<TestData> createExistingDb2DatabaseWithAllDataTypes(String namespac
749854
return ImmutableList.copyOf(data);
750855
}
751856

857+
private ImmutableList<String> getIntCompatibleColumnNamesOnExistingDb2Database(String table) {
858+
if (table.equals(SUPPORTED_TABLE_NAME)) {
859+
return ImmutableList.of("col01", "col02");
860+
} else {
861+
throw new IllegalArgumentException("Table does not exist: " + table);
862+
}
863+
}
864+
865+
private ImmutableList<String> getFloatCompatibleColumnNamesOnExistingDb2Database(String table) {
866+
if (table.equals(SUPPORTED_TABLE_NAME)) {
867+
return ImmutableList.of("col04", "col05");
868+
} else {
869+
throw new IllegalArgumentException("Table does not exist: " + table);
870+
}
871+
}
872+
752873
private void executeCreateTableSql(List<JdbcTestData> data) throws SQLException {
753874
String[] sqls = data.stream().map(JdbcTestData::getCreateTableSql).toArray(String[]::new);
754875
execute(sqls);

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ public static boolean isOracle() {
5858
return System.getProperty(PROP_JDBC_URL, DEFAULT_JDBC_URL).startsWith("jdbc:oracle:");
5959
}
6060

61+
public static boolean isSqlServer() {
62+
return System.getProperty(PROP_JDBC_URL, DEFAULT_JDBC_URL).startsWith("jdbc:sqlserver:");
63+
}
64+
6165
public static boolean isSqlite() {
6266
return System.getProperty(PROP_JDBC_URL, DEFAULT_JDBC_URL).startsWith("jdbc:sqlite:");
6367
}

0 commit comments

Comments
 (0)