Skip to content

Commit caddaf4

Browse files
feeblefakieKodaiD
andauthored
Backport to branch(3) : Add alter column type tests for imported tables (#3077)
Co-authored-by: Kodai Doki <[email protected]> Co-authored-by: Kodai Doki <[email protected]>
1 parent 04ea484 commit caddaf4

File tree

4 files changed

+415
-1
lines changed

4 files changed

+415
-1
lines changed

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

Lines changed: 195 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;
@@ -39,16 +45,51 @@ protected List<TestData> createExistingDatabaseWithAllDataTypes() throws SQLExce
3945
return testUtils.createExistingDatabaseWithAllDataTypes(getNamespace());
4046
}
4147

48+
@Override
49+
protected List<String> getIntCompatibleColumnNamesOnExistingDatabase(String table) {
50+
return testUtils.getIntCompatibleColumnNamesOnExistingDatabase(table);
51+
}
52+
53+
@Override
54+
protected List<String> getFloatCompatibleColumnNamesOnExistingDatabase(String table) {
55+
return testUtils.getFloatCompatibleColumnNamesOnExistingDatabase(table);
56+
}
57+
4258
@Override
4359
protected void dropNonImportableTable(String table) throws SQLException {
4460
testUtils.dropTable(getNamespace(), table);
4561
}
4662

63+
@SuppressWarnings("unused")
64+
private boolean isOracle() {
65+
return JdbcEnv.isOracle();
66+
}
67+
68+
@SuppressWarnings("unused")
69+
private boolean isSqlServer() {
70+
return JdbcEnv.isSqlServer();
71+
}
72+
73+
@SuppressWarnings("unused")
74+
private boolean isDb2() {
75+
return JdbcEnv.isDb2();
76+
}
77+
4778
@SuppressWarnings("unused")
4879
private boolean isSqlite() {
4980
return JdbcEnv.isSqlite();
5081
}
5182

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

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
@@ -148,6 +148,38 @@ public void createExistingDatabase(String namespace) throws SQLException {
148148
execute(rdbEngine.createNamespaceSqls(rdbEngine.enclose(namespace)));
149149
}
150150

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

651+
private ImmutableList<String> getIntCompatibleColumnNamesOnExistingMysqlDatabase(String table) {
652+
if (table.equals(SUPPORTED_TABLE_NAME)) {
653+
return ImmutableList.of("col02", "col04", "col05", "col06");
654+
} else {
655+
throw new IllegalArgumentException("Table does not exist: " + table);
656+
}
657+
}
658+
659+
private ImmutableList<String> getFloatCompatibleColumnNamesOnExistingMysqlDatabase(String table) {
660+
if (table.equals(SUPPORTED_TABLE_NAME)) {
661+
return ImmutableList.of("col08");
662+
} else {
663+
throw new IllegalArgumentException("Table does not exist: " + table);
664+
}
665+
}
666+
619667
private List<TestData> createExistingPostgresDatabaseWithAllDataTypes(String namespace)
620668
throws SQLException {
621669
List<JdbcTestData> data = new ArrayList<>();
@@ -650,6 +698,24 @@ private List<TestData> createExistingPostgresDatabaseWithAllDataTypes(String nam
650698
return ImmutableList.copyOf(data);
651699
}
652700

701+
private ImmutableList<String> getIntCompatibleColumnNamesOnExistingPostgresDatabase(
702+
String table) {
703+
if (table.equals(SUPPORTED_TABLE_NAME)) {
704+
return ImmutableList.of("col02", "col03");
705+
} else {
706+
throw new IllegalArgumentException("Table does not exist: " + table);
707+
}
708+
}
709+
710+
private ImmutableList<String> getFloatCompatibleColumnNamesOnExistingPostgresDatabase(
711+
String table) {
712+
if (table.equals(SUPPORTED_TABLE_NAME)) {
713+
return ImmutableList.of("col05");
714+
} else {
715+
throw new IllegalArgumentException("Table does not exist: " + table);
716+
}
717+
}
718+
653719
private List<TestData> createExistingOracleDatabaseWithAllDataTypes(String namespace)
654720
throws SQLException {
655721
List<JdbcTestData> data = new ArrayList<>();
@@ -701,6 +767,27 @@ private List<TestData> createExistingOracleDatabaseWithAllDataTypes(String names
701767
return ImmutableList.copyOf(data);
702768
}
703769

770+
private ImmutableList<String> getIntCompatibleColumnNamesOnExistingOracleDatabase(String table) {
771+
if (table.equals(SUPPORTED_TABLE_NAME)) {
772+
return ImmutableList.of();
773+
} else if (table.equals(SUPPORTED_TABLE_NAME + "_long_raw")) {
774+
return ImmutableList.of();
775+
} else {
776+
throw new IllegalArgumentException("Table does not exist: " + table);
777+
}
778+
}
779+
780+
private ImmutableList<String> getFloatCompatibleColumnNamesOnExistingOracleDatabase(
781+
String table) {
782+
if (table.equals(SUPPORTED_TABLE_NAME)) {
783+
return ImmutableList.of("col04");
784+
} else if (table.equals(SUPPORTED_TABLE_NAME + "_long_raw")) {
785+
return ImmutableList.of();
786+
} else {
787+
throw new IllegalArgumentException("Table does not exist: " + table);
788+
}
789+
}
790+
704791
private List<TestData> createExistingSqlServerDatabaseWithAllDataTypes(String namespace)
705792
throws SQLException {
706793
List<JdbcTestData> data = new ArrayList<>();
@@ -727,6 +814,24 @@ private List<TestData> createExistingSqlServerDatabaseWithAllDataTypes(String na
727814
return ImmutableList.copyOf(data);
728815
}
729816

817+
private ImmutableList<String> getIntCompatibleColumnNamesOnExistingSqlServerDatabase(
818+
String table) {
819+
if (table.equals(SUPPORTED_TABLE_NAME)) {
820+
return ImmutableList.of("col02", "col03", "col04");
821+
} else {
822+
throw new IllegalArgumentException("Table does not exist: " + table);
823+
}
824+
}
825+
826+
private ImmutableList<String> getFloatCompatibleColumnNamesOnExistingSqlServerDatabase(
827+
String table) {
828+
if (table.equals(SUPPORTED_TABLE_NAME)) {
829+
return ImmutableList.of("col06");
830+
} else {
831+
throw new IllegalArgumentException("Table does not exist: " + table);
832+
}
833+
}
834+
730835
private List<TestData> createExistingDb2DatabaseWithAllDataTypes(String namespace)
731836
throws SQLException {
732837
List<JdbcTestData> data = new ArrayList<>();
@@ -753,6 +858,22 @@ private List<TestData> createExistingDb2DatabaseWithAllDataTypes(String namespac
753858
return ImmutableList.copyOf(data);
754859
}
755860

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

0 commit comments

Comments
 (0)