From f362b92866d292f94f0406876b25ae247795b21b Mon Sep 17 00:00:00 2001 From: Vincent Guilpain Date: Wed, 24 Sep 2025 05:35:14 +0000 Subject: [PATCH 1/2] Empty commit [skip ci] From 12ca026550c9eac8573a450b45c9725b03abc2b2 Mon Sep 17 00:00:00 2001 From: Vincent Guilpain Date: Wed, 24 Sep 2025 14:34:17 +0900 Subject: [PATCH 2/2] For IBM Db2, change the data type for BLOB column to support storing up to 2GB (#3000) # Conflicts: # core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTestBase.java --- ...tAdminIntegrationTestWithJdbcDatabase.java | 9 +- ...bcAdminCaseSensitivityIntegrationTest.java | 9 +- .../jdbc/JdbcAdminIntegrationTest.java | 9 +- ...baseCrossPartitionScanIntegrationTest.java | 5 + ...tipleClusteringKeyScanIntegrationTest.java | 7 +- ...seMultiplePartitionKeyIntegrationTest.java | 5 +- ...DatabaseSecondaryIndexIntegrationTest.java | 15 ++ ...ingleClusteringKeyScanIntegrationTest.java | 7 +- ...baseSinglePartitionKeyIntegrationTest.java | 5 +- ...nAdminIntegrationTestWithJdbcDatabase.java | 9 +- .../JdbcTransactionAdminIntegrationTest.java | 9 +- .../java/com/scalar/db/common/CoreError.java | 12 ++ .../db/common/checker/OperationChecker.java | 4 +- .../scalar/db/storage/jdbc/JdbcDatabase.java | 4 +- .../db/storage/jdbc/JdbcOperationChecker.java | 29 +++ .../scalar/db/storage/jdbc/RdbEngineDb2.java | 26 ++- .../db/storage/jdbc/RdbEngineStrategy.java | 13 ++ .../common/checker/OperationCheckerTest.java | 30 +++ .../db/storage/jdbc/JdbcAdminTestBase.java | 204 ++++++++++++------ .../jdbc/JdbcOperationCheckerTest.java | 65 ++++++ .../db/storage/jdbc/RdbEngineDb2Test.java | 102 +++++++++ ...ibutedStorageAdminIntegrationTestBase.java | 44 ++-- ...CrossPartitionScanIntegrationTestBase.java | 10 + ...edTransactionAdminIntegrationTestBase.java | 44 ++-- 24 files changed, 558 insertions(+), 118 deletions(-) create mode 100644 core/src/main/java/com/scalar/db/storage/jdbc/JdbcOperationChecker.java create mode 100644 core/src/test/java/com/scalar/db/storage/jdbc/JdbcOperationCheckerTest.java create mode 100644 core/src/test/java/com/scalar/db/storage/jdbc/RdbEngineDb2Test.java diff --git a/core/src/integration-test/java/com/scalar/db/storage/jdbc/ConsensusCommitAdminIntegrationTestWithJdbcDatabase.java b/core/src/integration-test/java/com/scalar/db/storage/jdbc/ConsensusCommitAdminIntegrationTestWithJdbcDatabase.java index 0dbd1ea3be..0b28e55d3b 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/jdbc/ConsensusCommitAdminIntegrationTestWithJdbcDatabase.java +++ b/core/src/integration-test/java/com/scalar/db/storage/jdbc/ConsensusCommitAdminIntegrationTestWithJdbcDatabase.java @@ -122,8 +122,8 @@ public void createTable_ForNonExistingNamespace_ShouldThrowIllegalArgumentExcept } @Override - protected boolean isCreateIndexOnTextAndBlobColumnsEnabled() { - // "admin.createIndex()" for TEXT and BLOB columns fails (the "create index" query runs + protected boolean isCreateIndexOnTextColumnEnabled() { + // "admin.createIndex()" for TEXT column fails (the "create index" query runs // indefinitely) on the Db2 community edition docker version which we use for the CI. // However, the index creation is successful on Db2 hosted on IBM Cloud. // So we disable these tests until the issue with the Db2 community edition is resolved. @@ -180,4 +180,9 @@ public void renameColumn_Db2_ForPrimaryOrIndexKeyColumn_ShouldThrowUnsupportedOp admin.dropTable(namespace1, TABLE4, true); } } + + @Override + protected boolean isIndexOnBlobColumnSupported() { + return !JdbcTestUtils.isDb2(rdbEngine); + } } diff --git a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcAdminCaseSensitivityIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcAdminCaseSensitivityIntegrationTest.java index 3f78e0da79..3460adcc92 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcAdminCaseSensitivityIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcAdminCaseSensitivityIntegrationTest.java @@ -106,8 +106,8 @@ public void createTable_ForNonExistingNamespace_ShouldThrowIllegalArgumentExcept } @Override - protected boolean isCreateIndexOnTextAndBlobColumnsEnabled() { - // "admin.createIndex()" for TEXT and BLOB columns fails (the "create index" query runs + protected boolean isCreateIndexOnTextColumnEnabled() { + // "admin.createIndex()" for TEXT column fails (the "create index" query runs // indefinitely) on Db2 community edition version but works on Db2 hosted on IBM Cloud. // So we disable these tests until the issue is resolved. return !JdbcTestUtils.isDb2(rdbEngine); @@ -172,4 +172,9 @@ public void renameColumn_Db2_ForPrimaryOrIndexKeyColumn_ShouldThrowUnsupportedOp admin.dropTable(getNamespace1(), getTable4(), true); } } + + @Override + protected boolean isIndexOnBlobColumnSupported() { + return !JdbcTestUtils.isDb2(rdbEngine); + } } diff --git a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcAdminIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcAdminIntegrationTest.java index 788e44a66c..f6e4eaf2e7 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcAdminIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcAdminIntegrationTest.java @@ -105,8 +105,8 @@ public void createTable_ForNonExistingNamespace_ShouldThrowIllegalArgumentExcept } @Override - protected boolean isCreateIndexOnTextAndBlobColumnsEnabled() { - // "admin.createIndex()" for TEXT and BLOB columns fails (the "create index" query runs + protected boolean isCreateIndexOnTextColumnEnabled() { + // "admin.createIndex()" for TEXT columns fails (the "create index" query runs // indefinitely) on Db2 community edition version but works on Db2 hosted on IBM Cloud. // So we disable these tests until the issue is resolved. return !JdbcTestUtils.isDb2(rdbEngine); @@ -171,4 +171,9 @@ public void renameColumn_Db2_ForPrimaryOrIndexKeyColumn_ShouldThrowUnsupportedOp admin.dropTable(getNamespace1(), getTable4(), true); } } + + @Override + protected boolean isIndexOnBlobColumnSupported() { + return !JdbcTestUtils.isDb2(rdbEngine); + } } diff --git a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseCrossPartitionScanIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseCrossPartitionScanIntegrationTest.java index 83ed7a4eb1..1e85cd44d5 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseCrossPartitionScanIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseCrossPartitionScanIntegrationTest.java @@ -80,4 +80,9 @@ protected Stream provideColumnsForCNFConditionsTest() { } return Stream.of(Arguments.of(allColumnNames)); } + + @Override + protected boolean isOrderingOnBlobColumnSupported() { + return !JdbcTestUtils.isDb2(rdbEngine); + } } diff --git a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseMultipleClusteringKeyScanIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseMultipleClusteringKeyScanIntegrationTest.java index 5dc47a8f7f..2247c67e0b 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseMultipleClusteringKeyScanIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseMultipleClusteringKeyScanIntegrationTest.java @@ -94,9 +94,14 @@ protected Column getColumnWithMaxValue(String columnName, DataType dataType) @Override protected List getDataTypes() { // TIMESTAMP WITH TIME ZONE type cannot be used as a primary key in Oracle + // BLOB type cannot be used as a clustering key in Db2 return JdbcTestUtils.filterDataTypes( super.getDataTypes(), rdbEngine, - ImmutableMap.of(RdbEngineOracle.class, ImmutableList.of(DataType.TIMESTAMPTZ))); + ImmutableMap.of( + RdbEngineOracle.class, + ImmutableList.of(DataType.TIMESTAMPTZ), + RdbEngineDb2.class, + ImmutableList.of(DataType.BLOB))); } } diff --git a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseMultiplePartitionKeyIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseMultiplePartitionKeyIntegrationTest.java index c4943d8478..82919a2f72 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseMultiplePartitionKeyIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseMultiplePartitionKeyIntegrationTest.java @@ -88,6 +88,7 @@ protected Column getColumnWithMaxValue(String columnName, DataType dataType) protected List getDataTypes() { // TIMESTAMP WITH TIME ZONE type cannot be used as a primary key in Oracle // FLOAT and DOUBLE types cannot be used as partition key in Yugabyte + // BLOB type cannot be used as a partition key in Db2 return JdbcTestUtils.filterDataTypes( super.getDataTypes(), rdbEngine, @@ -95,6 +96,8 @@ protected List getDataTypes() { RdbEngineOracle.class, ImmutableList.of(DataType.TIMESTAMPTZ), RdbEngineYugabyte.class, - ImmutableList.of(DataType.FLOAT, DataType.DOUBLE))); + ImmutableList.of(DataType.FLOAT, DataType.DOUBLE), + RdbEngineDb2.class, + ImmutableList.of(DataType.BLOB))); } } diff --git a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseSecondaryIndexIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseSecondaryIndexIntegrationTest.java index 4bff0bed6d..16fc9182c3 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseSecondaryIndexIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseSecondaryIndexIntegrationTest.java @@ -1,12 +1,17 @@ package com.scalar.db.storage.jdbc; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Sets; import com.scalar.db.api.DistributedStorageSecondaryIndexIntegrationTestBase; import com.scalar.db.config.DatabaseConfig; import com.scalar.db.io.Column; import com.scalar.db.io.DataType; import com.scalar.db.util.TestUtils; +import java.util.Arrays; import java.util.Properties; import java.util.Random; +import java.util.Set; public class JdbcDatabaseSecondaryIndexIntegrationTest extends DistributedStorageSecondaryIndexIntegrationTestBase { @@ -68,4 +73,14 @@ protected Column getColumnWithMaxValue(String columnName, DataType dataType) } return super.getColumnWithMaxValue(columnName, dataType); } + + @Override + protected Set getSecondaryIndexTypes() { + // BLOB type cannot be used as a secondary index in Db2 + return Sets.newHashSet( + JdbcTestUtils.filterDataTypes( + Arrays.asList(DataType.values()), + rdbEngine, + ImmutableMap.of(RdbEngineDb2.class, ImmutableList.of(DataType.BLOB)))); + } } diff --git a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseSingleClusteringKeyScanIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseSingleClusteringKeyScanIntegrationTest.java index d1f1f97bc9..4f77dafed1 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseSingleClusteringKeyScanIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseSingleClusteringKeyScanIntegrationTest.java @@ -70,9 +70,14 @@ protected Column getColumnWithMaxValue(String columnName, DataType dataType) @Override protected List getClusteringKeyTypes() { // TIMESTAMP WITH TIME ZONE type cannot be used as a primary key in Oracle + // BLOB type cannot be used as a clustering key in Db2 return JdbcTestUtils.filterDataTypes( super.getClusteringKeyTypes(), rdbEngine, - ImmutableMap.of(RdbEngineOracle.class, ImmutableList.of(DataType.TIMESTAMPTZ))); + ImmutableMap.of( + RdbEngineOracle.class, + ImmutableList.of(DataType.TIMESTAMPTZ), + RdbEngineDb2.class, + ImmutableList.of(DataType.BLOB))); } } diff --git a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseSinglePartitionKeyIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseSinglePartitionKeyIntegrationTest.java index 598936d760..480d384ec8 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseSinglePartitionKeyIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcDatabaseSinglePartitionKeyIntegrationTest.java @@ -71,6 +71,7 @@ protected Column getColumnWithMaxValue(String columnName, DataType dataType) protected List getPartitionKeyTypes() { // TIMESTAMP WITH TIME ZONE type cannot be used as a primary key in Oracle // FLOAT and DOUBLE types cannot be used as partition key in Yugabyte + // BLOB type cannot be used as a partition key in Db2 return JdbcTestUtils.filterDataTypes( super.getPartitionKeyTypes(), rdbEngine, @@ -78,6 +79,8 @@ protected List getPartitionKeyTypes() { RdbEngineOracle.class, ImmutableList.of(DataType.TIMESTAMPTZ), RdbEngineYugabyte.class, - ImmutableList.of(DataType.FLOAT, DataType.DOUBLE))); + ImmutableList.of(DataType.FLOAT, DataType.DOUBLE), + RdbEngineDb2.class, + ImmutableList.of(DataType.BLOB))); } } diff --git a/core/src/integration-test/java/com/scalar/db/storage/jdbc/SingleCrudOperationTransactionAdminIntegrationTestWithJdbcDatabase.java b/core/src/integration-test/java/com/scalar/db/storage/jdbc/SingleCrudOperationTransactionAdminIntegrationTestWithJdbcDatabase.java index be07149cff..ef8b61aacf 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/jdbc/SingleCrudOperationTransactionAdminIntegrationTestWithJdbcDatabase.java +++ b/core/src/integration-test/java/com/scalar/db/storage/jdbc/SingleCrudOperationTransactionAdminIntegrationTestWithJdbcDatabase.java @@ -106,8 +106,8 @@ public void createTable_ForNonExistingNamespace_ShouldThrowIllegalArgumentExcept } @Override - protected boolean isCreateIndexOnTextAndBlobColumnsEnabled() { - // "admin.createIndex()" for TEXT and BLOB columns fails (the "create index" query runs + protected boolean isCreateIndexOnTextColumnEnabled() { + // "admin.createIndex()" for TEXT column fails (the "create index" query runs // indefinitely) on the Db2 community edition docker version which we use for the CI. // However, the index creation is successful on Db2 hosted on IBM Cloud. // So we disable these tests until the issue with the Db2 community edition is resolved. @@ -164,4 +164,9 @@ public void renameColumn_Db2_ForPrimaryOrIndexKeyColumn_ShouldThrowUnsupportedOp admin.dropTable(namespace1, TABLE4, true); } } + + @Override + protected boolean isIndexOnBlobColumnSupported() { + return !JdbcTestUtils.isDb2(rdbEngine); + } } diff --git a/core/src/integration-test/java/com/scalar/db/transaction/jdbc/JdbcTransactionAdminIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/transaction/jdbc/JdbcTransactionAdminIntegrationTest.java index a40aaf5d4b..1cf04f3948 100644 --- a/core/src/integration-test/java/com/scalar/db/transaction/jdbc/JdbcTransactionAdminIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/transaction/jdbc/JdbcTransactionAdminIntegrationTest.java @@ -173,8 +173,8 @@ public void dropCoordinatorTables_IfExist_CoordinatorTablesDoNotExist_ShouldNotT } @Override - protected boolean isCreateIndexOnTextAndBlobColumnsEnabled() { - // "admin.createIndex()" for TEXT and BLOB columns fails (the "create index" query runs + protected boolean isCreateIndexOnTextColumnEnabled() { + // "admin.createIndex()" for TEXT column fails (the "create index" query runs // indefinitely) on the Db2 community edition docker version which we use for the CI. // However, the index creation is successful on Db2 hosted on IBM Cloud. // So we disable these tests until the issue with the Db2 community edition is resolved. @@ -231,4 +231,9 @@ public void renameColumn_Db2_ForPrimaryOrIndexKeyColumn_ShouldThrowUnsupportedOp admin.dropTable(namespace1, TABLE4, true); } } + + @Override + protected boolean isIndexOnBlobColumnSupported() { + return !JdbcTestUtils.isDb2(rdbEngine); + } } diff --git a/core/src/main/java/com/scalar/db/common/CoreError.java b/core/src/main/java/com/scalar/db/common/CoreError.java index f42c362717..0e1eca1b55 100644 --- a/core/src/main/java/com/scalar/db/common/CoreError.java +++ b/core/src/main/java/com/scalar/db/common/CoreError.java @@ -742,6 +742,18 @@ public enum CoreError implements ScalarDbError { "The TIMESTAMP type is not supported in Cassandra. Column: %s", "", ""), + JDBC_DB2_INDEX_OR_KEY_ON_BLOB_COLUMN_NOT_SUPPORTED( + Category.USER_ERROR, + "0228", + "With Db2, using a BLOB column as partition key, clustering key or secondary index is not supported.", + "", + ""), + JDBC_DB2_CROSS_PARTITION_SCAN_ORDERING_ON_BLOB_COLUMN_NOT_SUPPORTED( + Category.USER_ERROR, + "0229", + "With Db2, setting an ordering on a BLOB column when using a cross partition scan operation is not supported. Ordering: %s", + "", + ""), // // Errors for the concurrency error category diff --git a/core/src/main/java/com/scalar/db/common/checker/OperationChecker.java b/core/src/main/java/com/scalar/db/common/checker/OperationChecker.java index 2754f0e471..8a977be66f 100644 --- a/core/src/main/java/com/scalar/db/common/checker/OperationChecker.java +++ b/core/src/main/java/com/scalar/db/common/checker/OperationChecker.java @@ -159,7 +159,7 @@ private void check(ScanAll scanAll) throws ExecutionException { throw new IllegalArgumentException( CoreError.OPERATION_CHECK_ERROR_CROSS_PARTITION_SCAN_ORDERING.buildMessage(scanAll)); } - checkOrderings(scanAll, metadata); + checkOrderingsForScanAll(scanAll, metadata); if (!config.isCrossPartitionScanFilteringEnabled() && !scanAll.getConjunctions().isEmpty()) { throw new IllegalArgumentException( @@ -258,7 +258,7 @@ private void checkOrderings(Scan scan, TableMetadata metadata) { } } - private void checkOrderings(ScanAll scanAll, TableMetadata metadata) { + protected void checkOrderingsForScanAll(ScanAll scanAll, TableMetadata metadata) { for (Scan.Ordering ordering : scanAll.getOrderings()) { if (!metadata.getColumnNames().contains(ordering.getColumnName())) { throw new IllegalArgumentException( diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/JdbcDatabase.java b/core/src/main/java/com/scalar/db/storage/jdbc/JdbcDatabase.java index 5fca851925..75e7ab92c4 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/JdbcDatabase.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/JdbcDatabase.java @@ -59,8 +59,8 @@ public JdbcDatabase(DatabaseConfig databaseConfig) { TableMetadataManager tableMetadataManager = new TableMetadataManager(jdbcAdmin, databaseConfig.getMetadataCacheExpirationTimeSecs()); OperationChecker operationChecker = - new OperationChecker( - databaseConfig, tableMetadataManager, new StorageInfoProvider(jdbcAdmin)); + new JdbcOperationChecker( + databaseConfig, tableMetadataManager, new StorageInfoProvider(jdbcAdmin), rdbEngine); jdbcService = new JdbcService( diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/JdbcOperationChecker.java b/core/src/main/java/com/scalar/db/storage/jdbc/JdbcOperationChecker.java new file mode 100644 index 0000000000..8cf440d4a7 --- /dev/null +++ b/core/src/main/java/com/scalar/db/storage/jdbc/JdbcOperationChecker.java @@ -0,0 +1,29 @@ +package com.scalar.db.storage.jdbc; + +import com.scalar.db.api.ScanAll; +import com.scalar.db.api.TableMetadata; +import com.scalar.db.common.StorageInfoProvider; +import com.scalar.db.common.TableMetadataManager; +import com.scalar.db.common.checker.OperationChecker; +import com.scalar.db.config.DatabaseConfig; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +public class JdbcOperationChecker extends OperationChecker { + private final RdbEngineStrategy rdbEngine; + + @SuppressFBWarnings("EI_EXPOSE_REP2") + public JdbcOperationChecker( + DatabaseConfig config, + TableMetadataManager tableMetadataManager, + StorageInfoProvider storageInfoProvider, + RdbEngineStrategy rdbEngine) { + super(config, tableMetadataManager, storageInfoProvider); + this.rdbEngine = rdbEngine; + } + + @Override + protected void checkOrderingsForScanAll(ScanAll scanAll, TableMetadata metadata) { + super.checkOrderingsForScanAll(scanAll, metadata); + rdbEngine.throwIfCrossPartitionScanOrderingOnBlobColumnNotSupported(scanAll, metadata); + } +} diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineDb2.java b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineDb2.java index 7b3df1a78e..b050a6a63b 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineDb2.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineDb2.java @@ -6,6 +6,8 @@ import com.google.common.collect.ImmutableMap; import com.ibm.db2.jcc.DB2BaseDataSource; import com.scalar.db.api.LikeExpression; +import com.scalar.db.api.Scan.Ordering; +import com.scalar.db.api.ScanAll; import com.scalar.db.api.TableMetadata; import com.scalar.db.common.CoreError; import com.scalar.db.exception.storage.ExecutionException; @@ -31,6 +33,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.annotation.Nullable; @@ -64,7 +67,7 @@ public String getDataTypeForEngine(DataType scalarDbDataType) { case BIGINT: return "BIGINT"; case BLOB: - return "VARBINARY(32672)"; + return "BLOB(2G)"; case BOOLEAN: return "BOOLEAN"; case FLOAT: @@ -352,7 +355,8 @@ public String getDataTypeForKey(DataType dataType) { case TEXT: return "VARCHAR(" + keyColumnSize + ") NOT NULL"; case BLOB: - return "VARBINARY(" + keyColumnSize + ") NOT NULL"; + throw new UnsupportedOperationException( + CoreError.JDBC_DB2_INDEX_OR_KEY_ON_BLOB_COLUMN_NOT_SUPPORTED.buildMessage()); default: return getDataTypeForEngine(dataType) + " NOT NULL"; } @@ -365,7 +369,8 @@ public String getDataTypeForSecondaryIndex(DataType dataType) { case TEXT: return "VARCHAR(" + keyColumnSize + ")"; case BLOB: - return "VARBINARY(" + keyColumnSize + ")"; + throw new UnsupportedOperationException( + CoreError.JDBC_DB2_INDEX_OR_KEY_ON_BLOB_COLUMN_NOT_SUPPORTED.buildMessage()); default: return null; } @@ -518,4 +523,19 @@ private String getProjection(String columnName, DataType dataType) { } return enclose(columnName); } + + @Override + public void throwIfCrossPartitionScanOrderingOnBlobColumnNotSupported( + ScanAll scanAll, TableMetadata metadata) { + Optional orderingOnBlobColumn = + scanAll.getOrderings().stream() + .filter( + ordering -> metadata.getColumnDataType(ordering.getColumnName()) == DataType.BLOB) + .findFirst(); + if (orderingOnBlobColumn.isPresent()) { + throw new UnsupportedOperationException( + CoreError.JDBC_DB2_CROSS_PARTITION_SCAN_ORDERING_ON_BLOB_COLUMN_NOT_SUPPORTED + .buildMessage(orderingOnBlobColumn.get())); + } + } } diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineStrategy.java b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineStrategy.java index a5205a1ab6..490dd20f0e 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineStrategy.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineStrategy.java @@ -1,6 +1,7 @@ package com.scalar.db.storage.jdbc; import com.scalar.db.api.LikeExpression; +import com.scalar.db.api.ScanAll; import com.scalar.db.api.TableMetadata; import com.scalar.db.exception.storage.ExecutionException; import com.scalar.db.io.DataType; @@ -283,4 +284,16 @@ default void setConnectionToReadOnly(Connection connection, boolean readOnly) throws SQLException { connection.setReadOnly(readOnly); } + + /** + * Throws an exception if a cross-partition scan operation with ordering on a blob column is + * specified and is not supported in the underlying storage. + * + * @param scanAll the ScanAll operation + * @param metadata the table metadata + * @throws UnsupportedOperationException if the ScanAll operation contains an ordering on a blob + * column, and it is not supported in the underlying storage + */ + default void throwIfCrossPartitionScanOrderingOnBlobColumnNotSupported( + ScanAll scanAll, TableMetadata metadata) {} } diff --git a/core/src/test/java/com/scalar/db/common/checker/OperationCheckerTest.java b/core/src/test/java/com/scalar/db/common/checker/OperationCheckerTest.java index e2a6e0febf..e734368dca 100644 --- a/core/src/test/java/com/scalar/db/common/checker/OperationCheckerTest.java +++ b/core/src/test/java/com/scalar/db/common/checker/OperationCheckerTest.java @@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.catchException; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.mockito.Mockito.any; import static org.mockito.Mockito.when; @@ -416,6 +417,35 @@ public void whenCheckingScanOperationWithEmptyOrdering_shouldNotThrowAnyExceptio assertThatCode(() -> operationChecker.check(scan)).doesNotThrowAnyException(); } + @Test + public void whenCheckingScanAllOperationWithCrossPartitionScanEnabledWithOrdering_shouldNotThrow() + throws ExecutionException { + // Arrange + TableMetadata metadata = + TableMetadata.newBuilder() + .addColumn(PKEY1, DataType.BLOB) + .addColumn(COL1, DataType.INT) + .addColumn(COL2, DataType.BLOB) + .addPartitionKey(PKEY1) + .build(); + when(metadataManager.getTableMetadata(any())).thenReturn(metadata); + Scan scan = + Scan.newBuilder() + .namespace(NAMESPACE) + .table(TABLE_NAME) + .all() + .ordering(Scan.Ordering.asc(COL1)) + .ordering(Scan.Ordering.desc(COL2)) + .build(); + when(databaseConfig.isCrossPartitionScanEnabled()).thenReturn(true); + when(databaseConfig.isCrossPartitionScanOrderingEnabled()).thenReturn(true); + + operationChecker = new OperationChecker(databaseConfig, metadataManager, storageInfoProvider); + + // Act Assert + assertDoesNotThrow(() -> operationChecker.check(scan)); + } + @Test public void whenCheckingScanOperationWithInvalidProjections_shouldThrowIllegalArgumentException() { diff --git a/core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTestBase.java b/core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTestBase.java index 1fe0152de4..fb665084f5 100644 --- a/core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTestBase.java +++ b/core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTestBase.java @@ -443,8 +443,8 @@ public void createTable_forMysql_shouldExecuteCreateTableStatement() + "`indexed` BOOLEAN NOT NULL," + "`ordinal_position` INTEGER NOT NULL," + "PRIMARY KEY (`full_table_name`, `column_name`))", - "CREATE TABLE `my_ns`.`foo_table`(`c3` BOOLEAN,`c1` VARCHAR(128),`c4` VARBINARY(128),`c2` BIGINT,`c5` INT,`c6` DOUBLE,`c7` REAL, PRIMARY KEY (`c3`,`c1`,`c4`))", - "CREATE INDEX `index_my_ns_foo_table_c4` ON `my_ns`.`foo_table` (`c4`)", + "CREATE TABLE `my_ns`.`foo_table`(`c3` BOOLEAN,`c1` VARCHAR(128),`c5` INT,`c2` BIGINT,`c4` LONGBLOB,`c6` DOUBLE,`c7` REAL, PRIMARY KEY (`c3`,`c1`,`c5`))", + "CREATE INDEX `index_my_ns_foo_table_c5` ON `my_ns`.`foo_table` (`c5`)", "CREATE INDEX `index_my_ns_foo_table_c1` ON `my_ns`.`foo_table` (`c1`)", "INSERT INTO `" + tableMetadataSchemaName @@ -454,13 +454,13 @@ public void createTable_forMysql_shouldExecuteCreateTableStatement() + "`.`metadata` VALUES ('my_ns.foo_table','c1','TEXT','CLUSTERING','ASC',true,2)", "INSERT INTO `" + tableMetadataSchemaName - + "`.`metadata` VALUES ('my_ns.foo_table','c4','BLOB','CLUSTERING','ASC',true,3)", + + "`.`metadata` VALUES ('my_ns.foo_table','c5','INT','CLUSTERING','ASC',true,3)", "INSERT INTO `" + tableMetadataSchemaName + "`.`metadata` VALUES ('my_ns.foo_table','c2','BIGINT',NULL,NULL,false,4)", "INSERT INTO `" + tableMetadataSchemaName - + "`.`metadata` VALUES ('my_ns.foo_table','c5','INT',NULL,NULL,false,5)", + + "`.`metadata` VALUES ('my_ns.foo_table','c4','BLOB',NULL,NULL,false,5)", "INSERT INTO `" + tableMetadataSchemaName + "`.`metadata` VALUES ('my_ns.foo_table','c6','DOUBLE',NULL,NULL,false,6)", @@ -487,8 +487,8 @@ public void createTable_forMysqlWithModifiedKeyColumnSize_shouldExecuteCreateTab + "`indexed` BOOLEAN NOT NULL," + "`ordinal_position` INTEGER NOT NULL," + "PRIMARY KEY (`full_table_name`, `column_name`))", - "CREATE TABLE `my_ns`.`foo_table`(`c3` BOOLEAN,`c1` VARCHAR(64),`c4` VARBINARY(64),`c2` BIGINT,`c5` INT,`c6` DOUBLE,`c7` REAL, PRIMARY KEY (`c3`,`c1`,`c4`))", - "CREATE INDEX `index_my_ns_foo_table_c4` ON `my_ns`.`foo_table` (`c4`)", + "CREATE TABLE `my_ns`.`foo_table`(`c3` BOOLEAN,`c1` VARCHAR(64),`c5` INT,`c2` BIGINT,`c4` LONGBLOB,`c6` DOUBLE,`c7` REAL, PRIMARY KEY (`c3`,`c1`,`c5`))", + "CREATE INDEX `index_my_ns_foo_table_c5` ON `my_ns`.`foo_table` (`c5`)", "CREATE INDEX `index_my_ns_foo_table_c1` ON `my_ns`.`foo_table` (`c1`)", "INSERT INTO `" + tableMetadataSchemaName @@ -498,13 +498,13 @@ public void createTable_forMysqlWithModifiedKeyColumnSize_shouldExecuteCreateTab + "`.`metadata` VALUES ('my_ns.foo_table','c1','TEXT','CLUSTERING','ASC',true,2)", "INSERT INTO `" + tableMetadataSchemaName - + "`.`metadata` VALUES ('my_ns.foo_table','c4','BLOB','CLUSTERING','ASC',true,3)", + + "`.`metadata` VALUES ('my_ns.foo_table','c5','INT','CLUSTERING','ASC',true,3)", "INSERT INTO `" + tableMetadataSchemaName + "`.`metadata` VALUES ('my_ns.foo_table','c2','BIGINT',NULL,NULL,false,4)", "INSERT INTO `" + tableMetadataSchemaName - + "`.`metadata` VALUES ('my_ns.foo_table','c5','INT',NULL,NULL,false,5)", + + "`.`metadata` VALUES ('my_ns.foo_table','c4','BLOB',NULL,NULL,false,5)", "INSERT INTO `" + tableMetadataSchemaName + "`.`metadata` VALUES ('my_ns.foo_table','c6','DOUBLE',NULL,NULL,false,6)", @@ -530,8 +530,8 @@ public void createTable_forPostgresql_shouldExecuteCreateTableStatement() + "\"indexed\" BOOLEAN NOT NULL," + "\"ordinal_position\" INTEGER NOT NULL," + "PRIMARY KEY (\"full_table_name\", \"column_name\"))", - "CREATE TABLE \"my_ns\".\"foo_table\"(\"c3\" BOOLEAN,\"c1\" VARCHAR(10485760),\"c4\" BYTEA,\"c2\" BIGINT,\"c5\" INT,\"c6\" DOUBLE PRECISION,\"c7\" REAL, PRIMARY KEY (\"c3\",\"c1\",\"c4\"))", - "CREATE INDEX \"index_my_ns_foo_table_c4\" ON \"my_ns\".\"foo_table\" (\"c4\")", + "CREATE TABLE \"my_ns\".\"foo_table\"(\"c3\" BOOLEAN,\"c1\" VARCHAR(10485760),\"c5\" INT,\"c2\" BIGINT,\"c4\" BYTEA,\"c6\" DOUBLE PRECISION,\"c7\" REAL, PRIMARY KEY (\"c3\",\"c1\",\"c5\"))", + "CREATE INDEX \"index_my_ns_foo_table_c5\" ON \"my_ns\".\"foo_table\" (\"c5\")", "CREATE INDEX \"index_my_ns_foo_table_c1\" ON \"my_ns\".\"foo_table\" (\"c1\")", "INSERT INTO \"" + tableMetadataSchemaName @@ -541,13 +541,13 @@ public void createTable_forPostgresql_shouldExecuteCreateTableStatement() + "\".\"metadata\" VALUES ('my_ns.foo_table','c1','TEXT','CLUSTERING','ASC',true,2)", "INSERT INTO \"" + tableMetadataSchemaName - + "\".\"metadata\" VALUES ('my_ns.foo_table','c4','BLOB','CLUSTERING','ASC',true,3)", + + "\".\"metadata\" VALUES ('my_ns.foo_table','c5','INT','CLUSTERING','ASC',true,3)", "INSERT INTO \"" + tableMetadataSchemaName + "\".\"metadata\" VALUES ('my_ns.foo_table','c2','BIGINT',NULL,NULL,false,4)", "INSERT INTO \"" + tableMetadataSchemaName - + "\".\"metadata\" VALUES ('my_ns.foo_table','c5','INT',NULL,NULL,false,5)", + + "\".\"metadata\" VALUES ('my_ns.foo_table','c4','BLOB',NULL,NULL,false,5)", "INSERT INTO \"" + tableMetadataSchemaName + "\".\"metadata\" VALUES ('my_ns.foo_table','c6','DOUBLE',NULL,NULL,false,6)", @@ -573,9 +573,8 @@ public void createTable_forSqlServer_shouldExecuteCreateTableStatement() + "[indexed] BIT NOT NULL," + "[ordinal_position] INTEGER NOT NULL," + "PRIMARY KEY ([full_table_name], [column_name]))", - "CREATE TABLE [my_ns].[foo_table]([c3] BIT,[c1] VARCHAR(8000)," - + "[c4] VARBINARY(8000),[c2] BIGINT,[c5] INT,[c6] FLOAT,[c7] FLOAT(24), PRIMARY KEY ([c3],[c1],[c4]))", - "CREATE INDEX [index_my_ns_foo_table_c4] ON [my_ns].[foo_table] ([c4])", + "CREATE TABLE [my_ns].[foo_table]([c3] BIT,[c1] VARCHAR(8000),[c5] INT,[c2] BIGINT,[c4] VARBINARY(8000),[c6] FLOAT,[c7] FLOAT(24), PRIMARY KEY ([c3],[c1],[c5]))", + "CREATE INDEX [index_my_ns_foo_table_c5] ON [my_ns].[foo_table] ([c5])", "CREATE INDEX [index_my_ns_foo_table_c1] ON [my_ns].[foo_table] ([c1])", "INSERT INTO [" + tableMetadataSchemaName @@ -585,13 +584,13 @@ public void createTable_forSqlServer_shouldExecuteCreateTableStatement() + "].[metadata] VALUES ('my_ns.foo_table','c1','TEXT','CLUSTERING','ASC',1,2)", "INSERT INTO [" + tableMetadataSchemaName - + "].[metadata] VALUES ('my_ns.foo_table','c4','BLOB','CLUSTERING','ASC',1,3)", + + "].[metadata] VALUES ('my_ns.foo_table','c5','INT','CLUSTERING','ASC',1,3)", "INSERT INTO [" + tableMetadataSchemaName + "].[metadata] VALUES ('my_ns.foo_table','c2','BIGINT',NULL,NULL,0,4)", "INSERT INTO [" + tableMetadataSchemaName - + "].[metadata] VALUES ('my_ns.foo_table','c5','INT',NULL,NULL,0,5)", + + "].[metadata] VALUES ('my_ns.foo_table','c4','BLOB',NULL,NULL,0,5)", "INSERT INTO [" + tableMetadataSchemaName + "].[metadata] VALUES ('my_ns.foo_table','c6','DOUBLE',NULL,NULL,0,6)", @@ -610,9 +609,9 @@ public void createTable_forOracle_shouldExecuteCreateTableStatement() "CREATE TABLE \"" + tableMetadataSchemaName + "\".\"metadata\"(\"full_table_name\" VARCHAR2(128),\"column_name\" VARCHAR2(128),\"data_type\" VARCHAR2(20) NOT NULL,\"key_type\" VARCHAR2(20),\"clustering_order\" VARCHAR2(10),\"indexed\" NUMBER(1) NOT NULL,\"ordinal_position\" INTEGER NOT NULL,PRIMARY KEY (\"full_table_name\", \"column_name\"))", - "CREATE TABLE \"my_ns\".\"foo_table\"(\"c3\" NUMBER(1),\"c1\" VARCHAR2(128),\"c4\" RAW(128),\"c2\" NUMBER(16),\"c5\" NUMBER(10),\"c6\" BINARY_DOUBLE,\"c7\" BINARY_FLOAT, PRIMARY KEY (\"c3\",\"c1\",\"c4\")) ROWDEPENDENCIES", + "CREATE TABLE \"my_ns\".\"foo_table\"(\"c3\" NUMBER(1),\"c1\" VARCHAR2(128),\"c5\" NUMBER(10),\"c2\" NUMBER(16),\"c4\" RAW(2000),\"c6\" BINARY_DOUBLE,\"c7\" BINARY_FLOAT, PRIMARY KEY (\"c3\",\"c1\",\"c5\")) ROWDEPENDENCIES", "ALTER TABLE \"my_ns\".\"foo_table\" INITRANS 3 MAXTRANS 255", - "CREATE INDEX \"my_ns\".\"index_my_ns_foo_table_c4\" ON \"my_ns\".\"foo_table\" (\"c4\")", + "CREATE INDEX \"my_ns\".\"index_my_ns_foo_table_c5\" ON \"my_ns\".\"foo_table\" (\"c5\")", "CREATE INDEX \"my_ns\".\"index_my_ns_foo_table_c1\" ON \"my_ns\".\"foo_table\" (\"c1\")", "INSERT INTO \"" + tableMetadataSchemaName @@ -622,13 +621,13 @@ public void createTable_forOracle_shouldExecuteCreateTableStatement() + "\".\"metadata\" VALUES ('my_ns.foo_table','c1','TEXT','CLUSTERING','ASC',1,2)", "INSERT INTO \"" + tableMetadataSchemaName - + "\".\"metadata\" VALUES ('my_ns.foo_table','c4','BLOB','CLUSTERING','ASC',1,3)", + + "\".\"metadata\" VALUES ('my_ns.foo_table','c5','INT','CLUSTERING','ASC',1,3)", "INSERT INTO \"" + tableMetadataSchemaName + "\".\"metadata\" VALUES ('my_ns.foo_table','c2','BIGINT',NULL,NULL,0,4)", "INSERT INTO \"" + tableMetadataSchemaName - + "\".\"metadata\" VALUES ('my_ns.foo_table','c5','INT',NULL,NULL,0,5)", + + "\".\"metadata\" VALUES ('my_ns.foo_table','c4','BLOB',NULL,NULL,0,5)", "INSERT INTO \"" + tableMetadataSchemaName + "\".\"metadata\" VALUES ('my_ns.foo_table','c6','DOUBLE',NULL,NULL,0,6)", @@ -648,9 +647,9 @@ public void createTable_forOracleWithModifiedKeyColumnSize_shouldExecuteCreateTa "CREATE TABLE \"" + tableMetadataSchemaName + "\".\"metadata\"(\"full_table_name\" VARCHAR2(128),\"column_name\" VARCHAR2(128),\"data_type\" VARCHAR2(20) NOT NULL,\"key_type\" VARCHAR2(20),\"clustering_order\" VARCHAR2(10),\"indexed\" NUMBER(1) NOT NULL,\"ordinal_position\" INTEGER NOT NULL,PRIMARY KEY (\"full_table_name\", \"column_name\"))", - "CREATE TABLE \"my_ns\".\"foo_table\"(\"c3\" NUMBER(1),\"c1\" VARCHAR2(64),\"c4\" RAW(64),\"c2\" NUMBER(16),\"c5\" NUMBER(10),\"c6\" BINARY_DOUBLE,\"c7\" BINARY_FLOAT, PRIMARY KEY (\"c3\",\"c1\",\"c4\")) ROWDEPENDENCIES", + "CREATE TABLE \"my_ns\".\"foo_table\"(\"c3\" NUMBER(1),\"c1\" VARCHAR2(64),\"c5\" NUMBER(10),\"c2\" NUMBER(16),\"c4\" RAW(2000),\"c6\" BINARY_DOUBLE,\"c7\" BINARY_FLOAT, PRIMARY KEY (\"c3\",\"c1\",\"c5\")) ROWDEPENDENCIES", "ALTER TABLE \"my_ns\".\"foo_table\" INITRANS 3 MAXTRANS 255", - "CREATE INDEX \"my_ns\".\"index_my_ns_foo_table_c4\" ON \"my_ns\".\"foo_table\" (\"c4\")", + "CREATE INDEX \"my_ns\".\"index_my_ns_foo_table_c5\" ON \"my_ns\".\"foo_table\" (\"c5\")", "CREATE INDEX \"my_ns\".\"index_my_ns_foo_table_c1\" ON \"my_ns\".\"foo_table\" (\"c1\")", "INSERT INTO \"" + tableMetadataSchemaName @@ -660,13 +659,13 @@ public void createTable_forOracleWithModifiedKeyColumnSize_shouldExecuteCreateTa + "\".\"metadata\" VALUES ('my_ns.foo_table','c1','TEXT','CLUSTERING','ASC',1,2)", "INSERT INTO \"" + tableMetadataSchemaName - + "\".\"metadata\" VALUES ('my_ns.foo_table','c4','BLOB','CLUSTERING','ASC',1,3)", + + "\".\"metadata\" VALUES ('my_ns.foo_table','c5','INT','CLUSTERING','ASC',1,3)", "INSERT INTO \"" + tableMetadataSchemaName + "\".\"metadata\" VALUES ('my_ns.foo_table','c2','BIGINT',NULL,NULL,0,4)", "INSERT INTO \"" + tableMetadataSchemaName - + "\".\"metadata\" VALUES ('my_ns.foo_table','c5','INT',NULL,NULL,0,5)", + + "\".\"metadata\" VALUES ('my_ns.foo_table','c4','BLOB',NULL,NULL,0,5)", "INSERT INTO \"" + tableMetadataSchemaName + "\".\"metadata\" VALUES ('my_ns.foo_table','c6','DOUBLE',NULL,NULL,0,6)", @@ -691,8 +690,8 @@ public void createTable_forSqlite_shouldExecuteCreateTableStatement() + "\"indexed\" BOOLEAN NOT NULL," + "\"ordinal_position\" INTEGER NOT NULL," + "PRIMARY KEY (\"full_table_name\", \"column_name\"))", - "CREATE TABLE \"my_ns$foo_table\"(\"c3\" BOOLEAN,\"c1\" TEXT,\"c4\" BLOB,\"c2\" BIGINT,\"c5\" INT,\"c6\" DOUBLE,\"c7\" FLOAT, PRIMARY KEY (\"c3\",\"c1\",\"c4\"))", - "CREATE INDEX \"index_my_ns_foo_table_c4\" ON \"my_ns$foo_table\" (\"c4\")", + "CREATE TABLE \"my_ns$foo_table\"(\"c3\" BOOLEAN,\"c1\" TEXT,\"c5\" INT,\"c2\" BIGINT,\"c4\" BLOB,\"c6\" DOUBLE,\"c7\" FLOAT, PRIMARY KEY (\"c3\",\"c1\",\"c5\"))", + "CREATE INDEX \"index_my_ns_foo_table_c5\" ON \"my_ns$foo_table\" (\"c5\")", "CREATE INDEX \"index_my_ns_foo_table_c1\" ON \"my_ns$foo_table\" (\"c1\")", "INSERT INTO \"" + tableMetadataSchemaName @@ -702,13 +701,13 @@ public void createTable_forSqlite_shouldExecuteCreateTableStatement() + "$metadata\" VALUES ('my_ns.foo_table','c1','TEXT','CLUSTERING','ASC',TRUE,2)", "INSERT INTO \"" + tableMetadataSchemaName - + "$metadata\" VALUES ('my_ns.foo_table','c4','BLOB','CLUSTERING','ASC',TRUE,3)", + + "$metadata\" VALUES ('my_ns.foo_table','c5','INT','CLUSTERING','ASC',TRUE,3)", "INSERT INTO \"" + tableMetadataSchemaName + "$metadata\" VALUES ('my_ns.foo_table','c2','BIGINT',NULL,NULL,FALSE,4)", "INSERT INTO \"" + tableMetadataSchemaName - + "$metadata\" VALUES ('my_ns.foo_table','c5','INT',NULL,NULL,FALSE,5)", + + "$metadata\" VALUES ('my_ns.foo_table','c4','BLOB',NULL,NULL,FALSE,5)", "INSERT INTO \"" + tableMetadataSchemaName + "$metadata\" VALUES ('my_ns.foo_table','c6','DOUBLE',NULL,NULL,FALSE,6)", @@ -734,8 +733,8 @@ public void createTable_forDb2_shouldExecuteCreateTableStatement() + "\"indexed\" BOOLEAN NOT NULL," + "\"ordinal_position\" INTEGER NOT NULL," + "PRIMARY KEY (\"full_table_name\", \"column_name\"))", - "CREATE TABLE \"my_ns\".\"foo_table\"(\"c3\" BOOLEAN NOT NULL,\"c1\" VARCHAR(128) NOT NULL,\"c4\" VARBINARY(128) NOT NULL,\"c2\" BIGINT,\"c5\" INT,\"c6\" DOUBLE,\"c7\" REAL, PRIMARY KEY (\"c3\",\"c1\",\"c4\"))", - "CREATE INDEX \"my_ns\".\"index_my_ns_foo_table_c4\" ON \"my_ns\".\"foo_table\" (\"c4\")", + "CREATE TABLE \"my_ns\".\"foo_table\"(\"c3\" BOOLEAN NOT NULL,\"c1\" VARCHAR(128) NOT NULL,\"c5\" INT NOT NULL,\"c2\" BIGINT,\"c4\" BLOB(2G),\"c6\" DOUBLE,\"c7\" REAL, PRIMARY KEY (\"c3\",\"c1\",\"c5\"))", + "CREATE INDEX \"my_ns\".\"index_my_ns_foo_table_c5\" ON \"my_ns\".\"foo_table\" (\"c5\")", "CREATE INDEX \"my_ns\".\"index_my_ns_foo_table_c1\" ON \"my_ns\".\"foo_table\" (\"c1\")", "INSERT INTO \"" + tableMetadataSchemaName @@ -745,13 +744,13 @@ public void createTable_forDb2_shouldExecuteCreateTableStatement() + "\".\"metadata\" VALUES ('my_ns.foo_table','c1','TEXT','CLUSTERING','ASC',true,2)", "INSERT INTO \"" + tableMetadataSchemaName - + "\".\"metadata\" VALUES ('my_ns.foo_table','c4','BLOB','CLUSTERING','ASC',true,3)", + + "\".\"metadata\" VALUES ('my_ns.foo_table','c5','INT','CLUSTERING','ASC',true,3)", "INSERT INTO \"" + tableMetadataSchemaName + "\".\"metadata\" VALUES ('my_ns.foo_table','c2','BIGINT',NULL,NULL,false,4)", "INSERT INTO \"" + tableMetadataSchemaName - + "\".\"metadata\" VALUES ('my_ns.foo_table','c5','INT',NULL,NULL,false,5)", + + "\".\"metadata\" VALUES ('my_ns.foo_table','c4','BLOB',NULL,NULL,false,5)", "INSERT INTO \"" + tableMetadataSchemaName + "\".\"metadata\" VALUES ('my_ns.foo_table','c6','DOUBLE',NULL,NULL,false,6)", @@ -778,8 +777,8 @@ public void createTable_forDb2WithModifiedKeyColumnSize_shouldExecuteCreateTable + "\"indexed\" BOOLEAN NOT NULL," + "\"ordinal_position\" INTEGER NOT NULL," + "PRIMARY KEY (\"full_table_name\", \"column_name\"))", - "CREATE TABLE \"my_ns\".\"foo_table\"(\"c3\" BOOLEAN NOT NULL,\"c1\" VARCHAR(64) NOT NULL,\"c4\" VARBINARY(64) NOT NULL,\"c2\" BIGINT,\"c5\" INT,\"c6\" DOUBLE,\"c7\" REAL, PRIMARY KEY (\"c3\",\"c1\",\"c4\"))", - "CREATE INDEX \"my_ns\".\"index_my_ns_foo_table_c4\" ON \"my_ns\".\"foo_table\" (\"c4\")", + "CREATE TABLE \"my_ns\".\"foo_table\"(\"c3\" BOOLEAN NOT NULL,\"c1\" VARCHAR(64) NOT NULL,\"c5\" INT NOT NULL,\"c2\" BIGINT,\"c4\" BLOB(2G),\"c6\" DOUBLE,\"c7\" REAL, PRIMARY KEY (\"c3\",\"c1\",\"c5\"))", + "CREATE INDEX \"my_ns\".\"index_my_ns_foo_table_c5\" ON \"my_ns\".\"foo_table\" (\"c5\")", "CREATE INDEX \"my_ns\".\"index_my_ns_foo_table_c1\" ON \"my_ns\".\"foo_table\" (\"c1\")", "INSERT INTO \"" + tableMetadataSchemaName @@ -789,13 +788,13 @@ public void createTable_forDb2WithModifiedKeyColumnSize_shouldExecuteCreateTable + "\".\"metadata\" VALUES ('my_ns.foo_table','c1','TEXT','CLUSTERING','ASC',true,2)", "INSERT INTO \"" + tableMetadataSchemaName - + "\".\"metadata\" VALUES ('my_ns.foo_table','c4','BLOB','CLUSTERING','ASC',true,3)", + + "\".\"metadata\" VALUES ('my_ns.foo_table','c5','INT','CLUSTERING','ASC',true,3)", "INSERT INTO \"" + tableMetadataSchemaName + "\".\"metadata\" VALUES ('my_ns.foo_table','c2','BIGINT',NULL,NULL,false,4)", "INSERT INTO \"" + tableMetadataSchemaName - + "\".\"metadata\" VALUES ('my_ns.foo_table','c5','INT',NULL,NULL,false,5)", + + "\".\"metadata\" VALUES ('my_ns.foo_table','c4','BLOB',NULL,NULL,false,5)", "INSERT INTO \"" + tableMetadataSchemaName + "\".\"metadata\" VALUES ('my_ns.foo_table','c6','DOUBLE',NULL,NULL,false,6)", @@ -821,7 +820,7 @@ private void createTable_forX_shouldExecuteCreateTableStatement( TableMetadata.newBuilder() .addPartitionKey("c3") .addClusteringKey("c1") - .addClusteringKey("c4") + .addClusteringKey("c5") .addColumn("c1", DataType.TEXT) .addColumn("c2", DataType.BIGINT) .addColumn("c3", DataType.BOOLEAN) @@ -830,7 +829,7 @@ private void createTable_forX_shouldExecuteCreateTableStatement( .addColumn("c6", DataType.DOUBLE) .addColumn("c7", DataType.FLOAT) .addSecondaryIndex("c1") - .addSecondaryIndex("c4") + .addSecondaryIndex("c5") .build(); List mockedStatements = new ArrayList<>(); @@ -871,8 +870,8 @@ public void createTable_WithClusteringOrderForMysql_shouldExecuteCreateTableStat + "`indexed` BOOLEAN NOT NULL," + "`ordinal_position` INTEGER NOT NULL," + "PRIMARY KEY (`full_table_name`, `column_name`))", - "CREATE TABLE `my_ns`.`foo_table`(`c3` BOOLEAN,`c1` VARCHAR(128),`c4` VARBINARY(128),`c2` BIGINT,`c5` INT,`c6` DOUBLE,`c7` REAL,`c8` DATE,`c9` TIME(6),`c10` DATETIME(3),`c11` DATETIME(3), PRIMARY KEY (`c3` ASC,`c1` DESC,`c4` ASC))", - "CREATE INDEX `index_my_ns_foo_table_c4` ON `my_ns`.`foo_table` (`c4`)", + "CREATE TABLE `my_ns`.`foo_table`(`c3` BOOLEAN,`c1` VARCHAR(128),`c5` INT,`c2` BIGINT,`c4` LONGBLOB,`c6` DOUBLE,`c7` REAL,`c8` DATE,`c9` TIME(6),`c10` DATETIME(3),`c11` DATETIME(3), PRIMARY KEY (`c3` ASC,`c1` DESC,`c5` ASC))", + "CREATE INDEX `index_my_ns_foo_table_c5` ON `my_ns`.`foo_table` (`c5`)", "CREATE INDEX `index_my_ns_foo_table_c1` ON `my_ns`.`foo_table` (`c1`)", "INSERT INTO `" + tableMetadataSchemaName @@ -882,13 +881,13 @@ public void createTable_WithClusteringOrderForMysql_shouldExecuteCreateTableStat + "`.`metadata` VALUES ('my_ns.foo_table','c1','TEXT','CLUSTERING','DESC',true,2)", "INSERT INTO `" + tableMetadataSchemaName - + "`.`metadata` VALUES ('my_ns.foo_table','c4','BLOB','CLUSTERING','ASC',true,3)", + + "`.`metadata` VALUES ('my_ns.foo_table','c5','INT','CLUSTERING','ASC',true,3)", "INSERT INTO `" + tableMetadataSchemaName + "`.`metadata` VALUES ('my_ns.foo_table','c2','BIGINT',NULL,NULL,false,4)", "INSERT INTO `" + tableMetadataSchemaName - + "`.`metadata` VALUES ('my_ns.foo_table','c5','INT',NULL,NULL,false,5)", + + "`.`metadata` VALUES ('my_ns.foo_table','c4','BLOB',NULL,NULL,false,5)", "INSERT INTO `" + tableMetadataSchemaName + "`.`metadata` VALUES ('my_ns.foo_table','c6','DOUBLE',NULL,NULL,false,6)", @@ -926,9 +925,9 @@ public void createTable_WithClusteringOrderForPostgresql_shouldExecuteCreateTabl + "\"indexed\" BOOLEAN NOT NULL," + "\"ordinal_position\" INTEGER NOT NULL," + "PRIMARY KEY (\"full_table_name\", \"column_name\"))", - "CREATE TABLE \"my_ns\".\"foo_table\"(\"c3\" BOOLEAN,\"c1\" VARCHAR(10485760),\"c4\" BYTEA,\"c2\" BIGINT,\"c5\" INT,\"c6\" DOUBLE PRECISION,\"c7\" REAL,\"c8\" DATE,\"c9\" TIME,\"c10\" TIMESTAMP,\"c11\" TIMESTAMP WITH TIME ZONE, PRIMARY KEY (\"c3\",\"c1\",\"c4\"))", - "CREATE UNIQUE INDEX \"my_ns.foo_table_clustering_order_idx\" ON \"my_ns\".\"foo_table\" (\"c3\" ASC,\"c1\" DESC,\"c4\" ASC)", - "CREATE INDEX \"index_my_ns_foo_table_c4\" ON \"my_ns\".\"foo_table\" (\"c4\")", + "CREATE TABLE \"my_ns\".\"foo_table\"(\"c3\" BOOLEAN,\"c1\" VARCHAR(10485760),\"c5\" INT,\"c2\" BIGINT,\"c4\" BYTEA,\"c6\" DOUBLE PRECISION,\"c7\" REAL,\"c8\" DATE,\"c9\" TIME,\"c10\" TIMESTAMP,\"c11\" TIMESTAMP WITH TIME ZONE, PRIMARY KEY (\"c3\",\"c1\",\"c5\"))", + "CREATE UNIQUE INDEX \"my_ns.foo_table_clustering_order_idx\" ON \"my_ns\".\"foo_table\" (\"c3\" ASC,\"c1\" DESC,\"c5\" ASC)", + "CREATE INDEX \"index_my_ns_foo_table_c5\" ON \"my_ns\".\"foo_table\" (\"c5\")", "CREATE INDEX \"index_my_ns_foo_table_c1\" ON \"my_ns\".\"foo_table\" (\"c1\")", "INSERT INTO \"" + tableMetadataSchemaName @@ -938,13 +937,13 @@ public void createTable_WithClusteringOrderForPostgresql_shouldExecuteCreateTabl + "\".\"metadata\" VALUES ('my_ns.foo_table','c1','TEXT','CLUSTERING','DESC',true,2)", "INSERT INTO \"" + tableMetadataSchemaName - + "\".\"metadata\" VALUES ('my_ns.foo_table','c4','BLOB','CLUSTERING','ASC',true,3)", + + "\".\"metadata\" VALUES ('my_ns.foo_table','c5','INT','CLUSTERING','ASC',true,3)", "INSERT INTO \"" + tableMetadataSchemaName + "\".\"metadata\" VALUES ('my_ns.foo_table','c2','BIGINT',NULL,NULL,false,4)", "INSERT INTO \"" + tableMetadataSchemaName - + "\".\"metadata\" VALUES ('my_ns.foo_table','c5','INT',NULL,NULL,false,5)", + + "\".\"metadata\" VALUES ('my_ns.foo_table','c4','BLOB',NULL,NULL,false,5)", "INSERT INTO \"" + tableMetadataSchemaName + "\".\"metadata\" VALUES ('my_ns.foo_table','c6','DOUBLE',NULL,NULL,false,6)", @@ -982,9 +981,8 @@ public void createTable_WithClusteringOrderForSqlServer_shouldExecuteCreateTable + "[indexed] BIT NOT NULL," + "[ordinal_position] INTEGER NOT NULL," + "PRIMARY KEY ([full_table_name], [column_name]))", - "CREATE TABLE [my_ns].[foo_table]([c3] BIT,[c1] VARCHAR(8000)," - + "[c4] VARBINARY(8000),[c2] BIGINT,[c5] INT,[c6] FLOAT,[c7] FLOAT(24),[c8] DATE,[c9] TIME(6),[c10] DATETIME2(3),[c11] DATETIMEOFFSET(3), PRIMARY KEY ([c3] ASC,[c1] DESC,[c4] ASC))", - "CREATE INDEX [index_my_ns_foo_table_c4] ON [my_ns].[foo_table] ([c4])", + "CREATE TABLE [my_ns].[foo_table]([c3] BIT,[c1] VARCHAR(8000),[c5] INT,[c2] BIGINT,[c4] VARBINARY(8000),[c6] FLOAT,[c7] FLOAT(24),[c8] DATE,[c9] TIME(6),[c10] DATETIME2(3),[c11] DATETIMEOFFSET(3), PRIMARY KEY ([c3] ASC,[c1] DESC,[c5] ASC))", + "CREATE INDEX [index_my_ns_foo_table_c5] ON [my_ns].[foo_table] ([c5])", "CREATE INDEX [index_my_ns_foo_table_c1] ON [my_ns].[foo_table] ([c1])", "INSERT INTO [" + tableMetadataSchemaName @@ -994,13 +992,13 @@ public void createTable_WithClusteringOrderForSqlServer_shouldExecuteCreateTable + "].[metadata] VALUES ('my_ns.foo_table','c1','TEXT','CLUSTERING','DESC',1,2)", "INSERT INTO [" + tableMetadataSchemaName - + "].[metadata] VALUES ('my_ns.foo_table','c4','BLOB','CLUSTERING','ASC',1,3)", + + "].[metadata] VALUES ('my_ns.foo_table','c5','INT','CLUSTERING','ASC',1,3)", "INSERT INTO [" + tableMetadataSchemaName + "].[metadata] VALUES ('my_ns.foo_table','c2','BIGINT',NULL,NULL,0,4)", "INSERT INTO [" + tableMetadataSchemaName - + "].[metadata] VALUES ('my_ns.foo_table','c5','INT',NULL,NULL,0,5)", + + "].[metadata] VALUES ('my_ns.foo_table','c4','BLOB',NULL,NULL,0,5)", "INSERT INTO [" + tableMetadataSchemaName + "].[metadata] VALUES ('my_ns.foo_table','c6','DOUBLE',NULL,NULL,0,6)", @@ -1031,10 +1029,10 @@ public void createTable_WithClusteringOrderForOracle_shouldExecuteCreateTableSta "CREATE TABLE \"" + tableMetadataSchemaName + "\".\"metadata\"(\"full_table_name\" VARCHAR2(128),\"column_name\" VARCHAR2(128),\"data_type\" VARCHAR2(20) NOT NULL,\"key_type\" VARCHAR2(20),\"clustering_order\" VARCHAR2(10),\"indexed\" NUMBER(1) NOT NULL,\"ordinal_position\" INTEGER NOT NULL,PRIMARY KEY (\"full_table_name\", \"column_name\"))", - "CREATE TABLE \"my_ns\".\"foo_table\"(\"c3\" NUMBER(1),\"c1\" VARCHAR2(128),\"c4\" RAW(128),\"c2\" NUMBER(16),\"c5\" NUMBER(10),\"c6\" BINARY_DOUBLE,\"c7\" BINARY_FLOAT,\"c8\" DATE,\"c9\" TIMESTAMP(6),\"c10\" TIMESTAMP(3),\"c11\" TIMESTAMP(3) WITH TIME ZONE, PRIMARY KEY (\"c3\",\"c1\",\"c4\")) ROWDEPENDENCIES", + "CREATE TABLE \"my_ns\".\"foo_table\"(\"c3\" NUMBER(1),\"c1\" VARCHAR2(128),\"c5\" NUMBER(10),\"c2\" NUMBER(16),\"c4\" RAW(2000),\"c6\" BINARY_DOUBLE,\"c7\" BINARY_FLOAT,\"c8\" DATE,\"c9\" TIMESTAMP(6),\"c10\" TIMESTAMP(3),\"c11\" TIMESTAMP(3) WITH TIME ZONE, PRIMARY KEY (\"c3\",\"c1\",\"c5\")) ROWDEPENDENCIES", "ALTER TABLE \"my_ns\".\"foo_table\" INITRANS 3 MAXTRANS 255", - "CREATE UNIQUE INDEX \"my_ns.foo_table_clustering_order_idx\" ON \"my_ns\".\"foo_table\" (\"c3\" ASC,\"c1\" DESC,\"c4\" ASC)", - "CREATE INDEX \"my_ns\".\"index_my_ns_foo_table_c4\" ON \"my_ns\".\"foo_table\" (\"c4\")", + "CREATE UNIQUE INDEX \"my_ns.foo_table_clustering_order_idx\" ON \"my_ns\".\"foo_table\" (\"c3\" ASC,\"c1\" DESC,\"c5\" ASC)", + "CREATE INDEX \"my_ns\".\"index_my_ns_foo_table_c5\" ON \"my_ns\".\"foo_table\" (\"c5\")", "CREATE INDEX \"my_ns\".\"index_my_ns_foo_table_c1\" ON \"my_ns\".\"foo_table\" (\"c1\")", "INSERT INTO \"" + tableMetadataSchemaName @@ -1044,13 +1042,13 @@ public void createTable_WithClusteringOrderForOracle_shouldExecuteCreateTableSta + "\".\"metadata\" VALUES ('my_ns.foo_table','c1','TEXT','CLUSTERING','DESC',1,2)", "INSERT INTO \"" + tableMetadataSchemaName - + "\".\"metadata\" VALUES ('my_ns.foo_table','c4','BLOB','CLUSTERING','ASC',1,3)", + + "\".\"metadata\" VALUES ('my_ns.foo_table','c5','INT','CLUSTERING','ASC',1,3)", "INSERT INTO \"" + tableMetadataSchemaName + "\".\"metadata\" VALUES ('my_ns.foo_table','c2','BIGINT',NULL,NULL,0,4)", "INSERT INTO \"" + tableMetadataSchemaName - + "\".\"metadata\" VALUES ('my_ns.foo_table','c5','INT',NULL,NULL,0,5)", + + "\".\"metadata\" VALUES ('my_ns.foo_table','c4','BLOB',NULL,NULL,0,5)", "INSERT INTO \"" + tableMetadataSchemaName + "\".\"metadata\" VALUES ('my_ns.foo_table','c6','DOUBLE',NULL,NULL,0,6)", @@ -1087,8 +1085,8 @@ public void createTable_WithClusteringOrderForSqlite_shouldExecuteCreateTableSta + "\"indexed\" BOOLEAN NOT NULL," + "\"ordinal_position\" INTEGER NOT NULL," + "PRIMARY KEY (\"full_table_name\", \"column_name\"))", - "CREATE TABLE \"my_ns$foo_table\"(\"c3\" BOOLEAN,\"c1\" TEXT,\"c4\" BLOB,\"c2\" BIGINT,\"c5\" INT,\"c6\" DOUBLE,\"c7\" FLOAT,\"c8\" INT,\"c9\" BIGINT,\"c10\" BIGINT,\"c11\" BIGINT, PRIMARY KEY (\"c3\",\"c1\",\"c4\"))", - "CREATE INDEX \"index_my_ns_foo_table_c4\" ON \"my_ns$foo_table\" (\"c4\")", + "CREATE TABLE \"my_ns$foo_table\"(\"c3\" BOOLEAN,\"c1\" TEXT,\"c5\" INT,\"c2\" BIGINT,\"c4\" BLOB,\"c6\" DOUBLE,\"c7\" FLOAT,\"c8\" INT,\"c9\" BIGINT,\"c10\" BIGINT,\"c11\" BIGINT, PRIMARY KEY (\"c3\",\"c1\",\"c5\"))", + "CREATE INDEX \"index_my_ns_foo_table_c5\" ON \"my_ns$foo_table\" (\"c5\")", "CREATE INDEX \"index_my_ns_foo_table_c1\" ON \"my_ns$foo_table\" (\"c1\")", "INSERT INTO \"" + tableMetadataSchemaName @@ -1098,13 +1096,13 @@ public void createTable_WithClusteringOrderForSqlite_shouldExecuteCreateTableSta + "$metadata\" VALUES ('my_ns.foo_table','c1','TEXT','CLUSTERING','DESC',TRUE,2)", "INSERT INTO \"" + tableMetadataSchemaName - + "$metadata\" VALUES ('my_ns.foo_table','c4','BLOB','CLUSTERING','ASC',TRUE,3)", + + "$metadata\" VALUES ('my_ns.foo_table','c5','INT','CLUSTERING','ASC',TRUE,3)", "INSERT INTO \"" + tableMetadataSchemaName + "$metadata\" VALUES ('my_ns.foo_table','c2','BIGINT',NULL,NULL,FALSE,4)", "INSERT INTO \"" + tableMetadataSchemaName - + "$metadata\" VALUES ('my_ns.foo_table','c5','INT',NULL,NULL,FALSE,5)", + + "$metadata\" VALUES ('my_ns.foo_table','c4','BLOB',NULL,NULL,FALSE,5)", "INSERT INTO \"" + tableMetadataSchemaName + "$metadata\" VALUES ('my_ns.foo_table','c6','DOUBLE',NULL,NULL,FALSE,6)", @@ -1142,9 +1140,9 @@ public void createTable_WithClusteringOrderForDb2_shouldExecuteCreateTableStatem + "\"indexed\" BOOLEAN NOT NULL," + "\"ordinal_position\" INTEGER NOT NULL," + "PRIMARY KEY (\"full_table_name\", \"column_name\"))", - "CREATE TABLE \"my_ns\".\"foo_table\"(\"c3\" BOOLEAN NOT NULL,\"c1\" VARCHAR(128) NOT NULL,\"c4\" VARBINARY(128) NOT NULL,\"c2\" BIGINT,\"c5\" INT,\"c6\" DOUBLE,\"c7\" REAL,\"c8\" DATE,\"c9\" TIMESTAMP(6),\"c10\" TIMESTAMP(3),\"c11\" TIMESTAMP(3), PRIMARY KEY (\"c3\",\"c1\",\"c4\"))", - "CREATE UNIQUE INDEX \"my_ns.foo_table_clustering_order_idx\" ON \"my_ns\".\"foo_table\" (\"c3\" ASC,\"c1\" DESC,\"c4\" ASC)", - "CREATE INDEX \"my_ns\".\"index_my_ns_foo_table_c4\" ON \"my_ns\".\"foo_table\" (\"c4\")", + "CREATE TABLE \"my_ns\".\"foo_table\"(\"c3\" BOOLEAN NOT NULL,\"c1\" VARCHAR(128) NOT NULL,\"c5\" INT NOT NULL,\"c2\" BIGINT,\"c4\" BLOB(2G),\"c6\" DOUBLE,\"c7\" REAL,\"c8\" DATE,\"c9\" TIMESTAMP(6),\"c10\" TIMESTAMP(3),\"c11\" TIMESTAMP(3), PRIMARY KEY (\"c3\",\"c1\",\"c5\"))", + "CREATE UNIQUE INDEX \"my_ns.foo_table_clustering_order_idx\" ON \"my_ns\".\"foo_table\" (\"c3\" ASC,\"c1\" DESC,\"c5\" ASC)", + "CREATE INDEX \"my_ns\".\"index_my_ns_foo_table_c5\" ON \"my_ns\".\"foo_table\" (\"c5\")", "CREATE INDEX \"my_ns\".\"index_my_ns_foo_table_c1\" ON \"my_ns\".\"foo_table\" (\"c1\")", "INSERT INTO \"" + tableMetadataSchemaName @@ -1154,13 +1152,13 @@ public void createTable_WithClusteringOrderForDb2_shouldExecuteCreateTableStatem + "\".\"metadata\" VALUES ('my_ns.foo_table','c1','TEXT','CLUSTERING','DESC',true,2)", "INSERT INTO \"" + tableMetadataSchemaName - + "\".\"metadata\" VALUES ('my_ns.foo_table','c4','BLOB','CLUSTERING','ASC',true,3)", + + "\".\"metadata\" VALUES ('my_ns.foo_table','c5','INT','CLUSTERING','ASC',true,3)", "INSERT INTO \"" + tableMetadataSchemaName + "\".\"metadata\" VALUES ('my_ns.foo_table','c2','BIGINT',NULL,NULL,false,4)", "INSERT INTO \"" + tableMetadataSchemaName - + "\".\"metadata\" VALUES ('my_ns.foo_table','c5','INT',NULL,NULL,false,5)", + + "\".\"metadata\" VALUES ('my_ns.foo_table','c4','BLOB',NULL,NULL,false,5)", "INSERT INTO \"" + tableMetadataSchemaName + "\".\"metadata\" VALUES ('my_ns.foo_table','c6','DOUBLE',NULL,NULL,false,6)", @@ -1191,7 +1189,7 @@ private void createTable_WithClusteringOrderForX_shouldExecuteCreateTableStateme TableMetadata.newBuilder() .addPartitionKey("c3") .addClusteringKey("c1", Order.DESC) - .addClusteringKey("c4", Order.ASC) + .addClusteringKey("c5", Order.ASC) .addColumn("c1", DataType.TEXT) .addColumn("c2", DataType.BIGINT) .addColumn("c3", DataType.BOOLEAN) @@ -1204,7 +1202,7 @@ private void createTable_WithClusteringOrderForX_shouldExecuteCreateTableStateme .addColumn("c10", DataType.TIMESTAMP) .addColumn("c11", DataType.TIMESTAMPTZ) .addSecondaryIndex("c1") - .addSecondaryIndex("c4") + .addSecondaryIndex("c5") .build(); List mockedStatements = new ArrayList<>(); @@ -3728,6 +3726,74 @@ private void getNamespaceNames_ForX_WithoutExistingTables_ShouldReturnMetadataSc assertThat(actual).containsOnly(tableMetadataSchemaName); } + @Test + void createTableInternal_Db2_WithBlobColumnAsKeyOrIndex_ShouldThrowUnsupportedOperationException() + throws SQLException { + // Arrange + TableMetadata metadata1 = + TableMetadata.newBuilder().addPartitionKey("pk").addColumn("pk", DataType.BLOB).build(); + TableMetadata metadata2 = + TableMetadata.newBuilder() + .addPartitionKey("pk") + .addClusteringKey("ck") + .addColumn("pk", DataType.INT) + .addColumn("ck", DataType.BLOB) + .build(); + TableMetadata metadata3 = + TableMetadata.newBuilder() + .addPartitionKey("pk") + .addColumn("pk", DataType.INT) + .addColumn("col", DataType.BLOB) + .addSecondaryIndex("col") + .build(); + JdbcAdmin admin = createJdbcAdminFor(RdbEngine.DB2); + when(connection.createStatement()).thenReturn(mock(Statement.class)); + when(dataSource.getConnection()).thenReturn(connection); + + // Act Assert + assertThatThrownBy(() -> admin.createTable("ns", "tbl", metadata1, false)) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessageContainingAll("BLOB", "key"); + assertThatThrownBy(() -> admin.createTable("ns", "tbl", metadata2, false)) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessageContainingAll("BLOB", "key"); + assertThatThrownBy(() -> admin.createTable("ns", "tbl", metadata3, false)) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessageContainingAll("BLOB", "index"); + } + + @Test + void createIndex_Db2_WithBlobColumnAsKeyOrIndex_ShouldThrowUnsupportedOperationException() + throws SQLException { + // Arrange + String namespace = "my_ns"; + String table = "my_tbl"; + String indexColumn = "index_col"; + JdbcAdmin admin = createJdbcAdminFor(RdbEngine.DB2); + + PreparedStatement checkStatement = prepareStatementForNamespaceCheck(); + PreparedStatement selectStatement = mock(PreparedStatement.class); + ResultSet resultSet = + mockResultSet( + Arrays.asList( + new GetColumnsResultSetMocker.Row( + "pk", DataType.BOOLEAN.toString(), "PARTITION", null, false), + new GetColumnsResultSetMocker.Row( + indexColumn, DataType.BLOB.toString(), null, null, false))); + when(selectStatement.executeQuery()).thenReturn(resultSet); + when(connection.prepareStatement(any())).thenReturn(checkStatement).thenReturn(selectStatement); + Statement statement = mock(Statement.class); + + when(dataSource.getConnection()).thenReturn(connection); + when(connection.createStatement()).thenReturn(statement); + + // Act Assert + assertThatThrownBy( + () -> admin.createIndex(namespace, table, indexColumn, Collections.emptyMap())) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessageContainingAll("BLOB", "index"); + } + private PreparedStatement prepareStatementForNamespaceCheck() throws SQLException { return prepareStatementForNamespaceCheck(true); } diff --git a/core/src/test/java/com/scalar/db/storage/jdbc/JdbcOperationCheckerTest.java b/core/src/test/java/com/scalar/db/storage/jdbc/JdbcOperationCheckerTest.java new file mode 100644 index 0000000000..0a0f8cdf6e --- /dev/null +++ b/core/src/test/java/com/scalar/db/storage/jdbc/JdbcOperationCheckerTest.java @@ -0,0 +1,65 @@ +package com.scalar.db.storage.jdbc; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.verify; + +import com.scalar.db.api.ScanAll; +import com.scalar.db.api.TableMetadata; +import com.scalar.db.common.StorageInfoProvider; +import com.scalar.db.common.TableMetadataManager; +import com.scalar.db.config.DatabaseConfig; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +public class JdbcOperationCheckerTest { + + @Mock private DatabaseConfig databaseConfig; + @Mock private TableMetadataManager tableMetadataManager; + @Mock private StorageInfoProvider storageInfoProvider; + @Mock private RdbEngineStrategy rdbEngine; + @Mock private ScanAll scanAll; + @Mock private TableMetadata tableMetadata; + private JdbcOperationChecker operationChecker; + + @BeforeEach + public void setUp() throws Exception { + MockitoAnnotations.openMocks(this).close(); + + operationChecker = + new JdbcOperationChecker( + databaseConfig, tableMetadataManager, storageInfoProvider, rdbEngine); + } + + @Test + public void checkOrderingsForScanAll_ShouldInvokeAdditionalCheckOnRdbEngine() { + // Arrange + // Act + operationChecker.checkOrderingsForScanAll(scanAll, tableMetadata); + + // Assert + verify(rdbEngine) + .throwIfCrossPartitionScanOrderingOnBlobColumnNotSupported(scanAll, tableMetadata); + } + + @Test + public void checkOrderingsForScanAll_WhenAdditionalCheckThrows_ShouldPropagateException() { + // Arrange + Exception exception = new RuntimeException(); + doThrow(exception) + .when(rdbEngine) + .throwIfCrossPartitionScanOrderingOnBlobColumnNotSupported(any(), any()); + + // Act + Assertions.assertThatThrownBy( + () -> operationChecker.checkOrderingsForScanAll(scanAll, tableMetadata)) + .isEqualTo(exception); + + // Assert + verify(rdbEngine) + .throwIfCrossPartitionScanOrderingOnBlobColumnNotSupported(scanAll, tableMetadata); + } +} diff --git a/core/src/test/java/com/scalar/db/storage/jdbc/RdbEngineDb2Test.java b/core/src/test/java/com/scalar/db/storage/jdbc/RdbEngineDb2Test.java new file mode 100644 index 0000000000..afc2295300 --- /dev/null +++ b/core/src/test/java/com/scalar/db/storage/jdbc/RdbEngineDb2Test.java @@ -0,0 +1,102 @@ +package com.scalar.db.storage.jdbc; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.when; + +import com.scalar.db.api.Scan; +import com.scalar.db.api.ScanAll; +import com.scalar.db.api.TableMetadata; +import com.scalar.db.io.DataType; +import java.util.Arrays; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +public class RdbEngineDb2Test { + + @Mock private ScanAll scanAll; + @Mock private TableMetadata metadata; + + private RdbEngineDb2 rdbEngineDb2; + + @BeforeEach + public void setUp() throws Exception { + MockitoAnnotations.openMocks(this).close(); + rdbEngineDb2 = new RdbEngineDb2(); + } + + @Test + public void + throwIfCrossPartitionScanOrderingOnBlobColumnNotSupported_WithBlobOrdering_ShouldThrowException() { + // Arrange + Scan.Ordering blobOrdering = Scan.Ordering.asc("blob_column"); + Scan.Ordering intOrdering = Scan.Ordering.desc("int_column"); + + when(scanAll.getOrderings()).thenReturn(Arrays.asList(intOrdering, blobOrdering)); + when(metadata.getColumnDataType("blob_column")).thenReturn(DataType.BLOB); + when(metadata.getColumnDataType("int_column")).thenReturn(DataType.INT); + + // Act & Assert + assertThatThrownBy( + () -> + rdbEngineDb2.throwIfCrossPartitionScanOrderingOnBlobColumnNotSupported( + scanAll, metadata)) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessageContaining("blob_column"); + } + + @Test + public void + throwIfCrossPartitionScanOrderingOnBlobColumnNotSupported_WithoutBlobOrdering_ShouldNotThrowException() { + // Arrange + Scan.Ordering intOrdering = Scan.Ordering.asc("int_column"); + Scan.Ordering textOrdering = Scan.Ordering.desc("text_column"); + + when(scanAll.getOrderings()).thenReturn(Arrays.asList(intOrdering, textOrdering)); + when(metadata.getColumnDataType("int_column")).thenReturn(DataType.INT); + when(metadata.getColumnDataType("text_column")).thenReturn(DataType.TEXT); + + // Act & Assert + assertThatCode( + () -> + rdbEngineDb2.throwIfCrossPartitionScanOrderingOnBlobColumnNotSupported( + scanAll, metadata)) + .doesNotThrowAnyException(); + } + + @Test + public void + throwIfCrossPartitionScanOrderingOnBlobColumnNotSupported_WithNoOrderings_ShouldNotThrowException() { + // Arrange + when(scanAll.getOrderings()).thenReturn(Arrays.asList()); + + // Act & Assert + assertThatCode( + () -> + rdbEngineDb2.throwIfCrossPartitionScanOrderingOnBlobColumnNotSupported( + scanAll, metadata)) + .doesNotThrowAnyException(); + } + + @Test + public void + throwIfCrossPartitionScanOrderingOnBlobColumnNotSupported_WithMultipleBlobOrderings_ShouldThrowForFirst() { + // Arrange + Scan.Ordering blobOrdering1 = Scan.Ordering.asc("blob_column1"); + Scan.Ordering blobOrdering2 = Scan.Ordering.desc("blob_column2"); + + when(scanAll.getOrderings()).thenReturn(Arrays.asList(blobOrdering1, blobOrdering2)); + when(metadata.getColumnDataType("blob_column1")).thenReturn(DataType.BLOB); + when(metadata.getColumnDataType("blob_column2")).thenReturn(DataType.BLOB); + + // Act & Assert + assertThatThrownBy( + () -> + rdbEngineDb2.throwIfCrossPartitionScanOrderingOnBlobColumnNotSupported( + scanAll, metadata)) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessageContaining("blob_column1"); + } +} diff --git a/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java b/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java index 6fa4fd8bb5..47cdb9477a 100644 --- a/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java +++ b/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java @@ -643,31 +643,39 @@ public void createIndex_ForAllDataTypesWithExistingData_ShouldCreateIndexesCorre // Act admin.createIndex(namespace1, getTable4(), getColumnName2(), options); + if (isCreateIndexOnTextColumnEnabled()) { + admin.createIndex(namespace1, getTable4(), getColumnName3(), options); + } admin.createIndex(namespace1, getTable4(), getColumnName4(), options); admin.createIndex(namespace1, getTable4(), getColumnName5(), options); admin.createIndex(namespace1, getTable4(), getColumnName6(), options); if (isIndexOnBooleanColumnSupported()) { admin.createIndex(namespace1, getTable4(), getColumnName7(), options); } + if (isIndexOnBlobColumnSupported()) { + admin.createIndex(namespace1, getTable4(), getColumnName8(), options); + } admin.createIndex(namespace1, getTable4(), getColumnName10(), options); admin.createIndex(namespace1, getTable4(), getColumnName11(), options); admin.createIndex(namespace1, getTable4(), getColumnName12(), options); if (isTimestampTypeSupported()) { admin.createIndex(namespace1, getTable4(), getColumnName13(), options); } - if (isCreateIndexOnTextAndBlobColumnsEnabled()) { - admin.createIndex(namespace1, getTable4(), getColumnName3(), options); - admin.createIndex(namespace1, getTable4(), getColumnName8(), options); - } // Assert assertThat(admin.indexExists(namespace1, getTable4(), getColumnName2())).isTrue(); + if (isCreateIndexOnTextColumnEnabled()) { + assertThat(admin.indexExists(namespace1, getTable4(), getColumnName3())).isTrue(); + } assertThat(admin.indexExists(namespace1, getTable4(), getColumnName4())).isTrue(); assertThat(admin.indexExists(namespace1, getTable4(), getColumnName5())).isTrue(); assertThat(admin.indexExists(namespace1, getTable4(), getColumnName6())).isTrue(); if (isIndexOnBooleanColumnSupported()) { assertThat(admin.indexExists(namespace1, getTable4(), getColumnName7())).isTrue(); } + if (isIndexOnBlobColumnSupported()) { + assertThat(admin.indexExists(namespace1, getTable4(), getColumnName8())).isTrue(); + } assertThat(admin.indexExists(namespace1, getTable4(), getColumnName9())).isTrue(); assertThat(admin.indexExists(namespace1, getTable4(), getColumnName10())).isTrue(); assertThat(admin.indexExists(namespace1, getTable4(), getColumnName11())).isTrue(); @@ -675,10 +683,6 @@ public void createIndex_ForAllDataTypesWithExistingData_ShouldCreateIndexesCorre if (isTimestampTypeSupported()) { assertThat(admin.indexExists(namespace1, getTable4(), getColumnName13())).isTrue(); } - if (isCreateIndexOnTextAndBlobColumnsEnabled()) { - assertThat(admin.indexExists(namespace1, getTable4(), getColumnName3())).isTrue(); - assertThat(admin.indexExists(namespace1, getTable4(), getColumnName8())).isTrue(); - } Set actualSecondaryIndexNames = admin.getTableMetadata(namespace1, getTable4()).getSecondaryIndexNames(); @@ -700,9 +704,13 @@ public void createIndex_ForAllDataTypesWithExistingData_ShouldCreateIndexesCorre assertThat(actualSecondaryIndexNames).contains(getColumnName13()); indexCount++; } - if (isCreateIndexOnTextAndBlobColumnsEnabled()) { - assertThat(actualSecondaryIndexNames).contains(getColumnName3(), getColumnName8()); - indexCount += 2; + if (isCreateIndexOnTextColumnEnabled()) { + assertThat(actualSecondaryIndexNames).contains(getColumnName3()); + indexCount++; + } + if (isIndexOnBlobColumnSupported()) { + assertThat(actualSecondaryIndexNames).contains(getColumnName8()); + indexCount++; } assertThat(actualSecondaryIndexNames).hasSize(indexCount); @@ -817,7 +825,6 @@ public void dropIndex_ForAllDataTypesWithExistingData_ShouldDropIndexCorrectly() .addSecondaryIndex(getColumnName4()) .addSecondaryIndex(getColumnName5()) .addSecondaryIndex(getColumnName6()) - .addSecondaryIndex(getColumnName8()) .addSecondaryIndex(getColumnName9()) .addSecondaryIndex(getColumnName10()) .addSecondaryIndex(getColumnName11()) @@ -829,6 +836,9 @@ public void dropIndex_ForAllDataTypesWithExistingData_ShouldDropIndexCorrectly() metadataBuilder.addColumn(getColumnName13(), DataType.TIMESTAMP); metadataBuilder.addSecondaryIndex(getColumnName13()); } + if (isIndexOnBlobColumnSupported()) { + metadataBuilder.addSecondaryIndex(getColumnName8()); + } admin.createTable(namespace1, getTable4(), metadataBuilder.build(), options); storage = storageFactory.getStorage(); PutBuilder.Buildable put = @@ -866,7 +876,9 @@ public void dropIndex_ForAllDataTypesWithExistingData_ShouldDropIndexCorrectly() if (isIndexOnBooleanColumnSupported()) { admin.dropIndex(namespace1, getTable4(), getColumnName7()); } - admin.dropIndex(namespace1, getTable4(), getColumnName8()); + if (isIndexOnBlobColumnSupported()) { + admin.dropIndex(namespace1, getTable4(), getColumnName8()); + } admin.dropIndex(namespace1, getTable4(), getColumnName10()); admin.dropIndex(namespace1, getTable4(), getColumnName11()); admin.dropIndex(namespace1, getTable4(), getColumnName12()); @@ -1289,11 +1301,15 @@ protected boolean isIndexOnBooleanColumnSupported() { return true; } + protected boolean isIndexOnBlobColumnSupported() { + return true; + } + protected boolean isTimestampTypeSupported() { return true; } - protected boolean isCreateIndexOnTextAndBlobColumnsEnabled() { + protected boolean isCreateIndexOnTextColumnEnabled() { return true; } } diff --git a/integration-test/src/main/java/com/scalar/db/api/DistributedStorageCrossPartitionScanIntegrationTestBase.java b/integration-test/src/main/java/com/scalar/db/api/DistributedStorageCrossPartitionScanIntegrationTestBase.java index af0746e41b..ab9787512c 100644 --- a/integration-test/src/main/java/com/scalar/db/api/DistributedStorageCrossPartitionScanIntegrationTestBase.java +++ b/integration-test/src/main/java/com/scalar/db/api/DistributedStorageCrossPartitionScanIntegrationTestBase.java @@ -924,7 +924,13 @@ public void scan_WithOrderingForNonPrimaryColumns_ShouldReturnProperResult() List> testCallables = new ArrayList<>(); for (DataType firstColumnType : columnTypes.keySet()) { + if (firstColumnType == DataType.BLOB && !isOrderingOnBlobColumnSupported()) { + continue; + } for (DataType secondColumnType : columnTypes.get(firstColumnType)) { + if (secondColumnType == DataType.BLOB && !isOrderingOnBlobColumnSupported()) { + continue; + } testCallables.add( () -> { random.get().setSeed(seed); @@ -1252,4 +1258,8 @@ public String toString() { protected boolean isTimestampTypeSupported() { return true; } + + protected boolean isOrderingOnBlobColumnSupported() { + return true; + } } diff --git a/integration-test/src/main/java/com/scalar/db/api/DistributedTransactionAdminIntegrationTestBase.java b/integration-test/src/main/java/com/scalar/db/api/DistributedTransactionAdminIntegrationTestBase.java index bef2513b2a..a057b615ae 100644 --- a/integration-test/src/main/java/com/scalar/db/api/DistributedTransactionAdminIntegrationTestBase.java +++ b/integration-test/src/main/java/com/scalar/db/api/DistributedTransactionAdminIntegrationTestBase.java @@ -563,31 +563,39 @@ public void createIndex_ForAllDataTypesWithExistingData_ShouldCreateIndexesCorre // Act admin.createIndex(namespace1, TABLE4, COL_NAME2, options); + if (isCreateIndexOnTextColumnEnabled()) { + admin.createIndex(namespace1, TABLE4, COL_NAME3, options); + } admin.createIndex(namespace1, TABLE4, COL_NAME4, options); admin.createIndex(namespace1, TABLE4, COL_NAME5, options); admin.createIndex(namespace1, TABLE4, COL_NAME6, options); if (isIndexOnBooleanColumnSupported()) { admin.createIndex(namespace1, TABLE4, COL_NAME7, options); } + if (isIndexOnBlobColumnSupported()) { + admin.createIndex(namespace1, TABLE4, COL_NAME8, options); + } admin.createIndex(namespace1, TABLE4, COL_NAME10, options); admin.createIndex(namespace1, TABLE4, COL_NAME11, options); admin.createIndex(namespace1, TABLE4, COL_NAME12, options); if (isTimestampTypeSupported()) { admin.createIndex(namespace1, TABLE4, COL_NAME13, options); } - if (isCreateIndexOnTextAndBlobColumnsEnabled()) { - admin.createIndex(namespace1, TABLE4, COL_NAME3, options); - admin.createIndex(namespace1, TABLE4, COL_NAME8, options); - } // Assert assertThat(admin.indexExists(namespace1, TABLE4, COL_NAME2)).isTrue(); + if (isCreateIndexOnTextColumnEnabled()) { + assertThat(admin.indexExists(namespace1, TABLE4, COL_NAME3)).isTrue(); + } assertThat(admin.indexExists(namespace1, TABLE4, COL_NAME4)).isTrue(); assertThat(admin.indexExists(namespace1, TABLE4, COL_NAME5)).isTrue(); assertThat(admin.indexExists(namespace1, TABLE4, COL_NAME6)).isTrue(); if (isIndexOnBooleanColumnSupported()) { assertThat(admin.indexExists(namespace1, TABLE4, COL_NAME7)).isTrue(); } + if (isIndexOnBlobColumnSupported()) { + assertThat(admin.indexExists(namespace1, TABLE4, COL_NAME8)).isTrue(); + } assertThat(admin.indexExists(namespace1, TABLE4, COL_NAME9)).isTrue(); assertThat(admin.indexExists(namespace1, TABLE4, COL_NAME10)).isTrue(); assertThat(admin.indexExists(namespace1, TABLE4, COL_NAME11)).isTrue(); @@ -595,10 +603,6 @@ public void createIndex_ForAllDataTypesWithExistingData_ShouldCreateIndexesCorre if (isTimestampTypeSupported()) { assertThat(admin.indexExists(namespace1, TABLE4, COL_NAME13)).isTrue(); } - if (isCreateIndexOnTextAndBlobColumnsEnabled()) { - assertThat(admin.indexExists(namespace1, TABLE4, COL_NAME3)).isTrue(); - assertThat(admin.indexExists(namespace1, TABLE4, COL_NAME8)).isTrue(); - } Set actualSecondaryIndexNames = admin.getTableMetadata(namespace1, TABLE4).getSecondaryIndexNames(); @@ -613,9 +617,13 @@ public void createIndex_ForAllDataTypesWithExistingData_ShouldCreateIndexesCorre assertThat(actualSecondaryIndexNames).contains(COL_NAME13); indexCount++; } - if (isCreateIndexOnTextAndBlobColumnsEnabled()) { - assertThat(actualSecondaryIndexNames).contains(COL_NAME3, COL_NAME8); - indexCount += 2; + if (isCreateIndexOnTextColumnEnabled()) { + assertThat(actualSecondaryIndexNames).contains(COL_NAME3); + indexCount += 1; + } + if (isIndexOnBlobColumnSupported()) { + assertThat(actualSecondaryIndexNames).contains(COL_NAME8); + indexCount += 1; } assertThat(actualSecondaryIndexNames).hasSize(indexCount); @@ -722,7 +730,6 @@ public void dropIndex_ForAllDataTypesWithExistingData_ShouldDropIndexCorrectly() .addSecondaryIndex(COL_NAME4) .addSecondaryIndex(COL_NAME5) .addSecondaryIndex(COL_NAME6) - .addSecondaryIndex(COL_NAME8) .addSecondaryIndex(COL_NAME9) .addSecondaryIndex(COL_NAME9) .addSecondaryIndex(COL_NAME10) @@ -731,6 +738,9 @@ public void dropIndex_ForAllDataTypesWithExistingData_ShouldDropIndexCorrectly() if (isIndexOnBooleanColumnSupported()) { metadataBuilder = metadataBuilder.addSecondaryIndex(COL_NAME7); } + if (isIndexOnBlobColumnSupported()) { + metadataBuilder = metadataBuilder.addSecondaryIndex(COL_NAME8); + } if (isTimestampTypeSupported()) { metadataBuilder.addColumn(COL_NAME13, DataType.TIMESTAMP); metadataBuilder.addSecondaryIndex(COL_NAME13); @@ -771,7 +781,9 @@ public void dropIndex_ForAllDataTypesWithExistingData_ShouldDropIndexCorrectly() if (isIndexOnBooleanColumnSupported()) { admin.dropIndex(namespace1, TABLE4, COL_NAME7); } - admin.dropIndex(namespace1, TABLE4, COL_NAME8); + if (isIndexOnBlobColumnSupported()) { + admin.dropIndex(namespace1, TABLE4, COL_NAME8); + } admin.dropIndex(namespace1, TABLE4, COL_NAME10); admin.dropIndex(namespace1, TABLE4, COL_NAME11); admin.dropIndex(namespace1, TABLE4, COL_NAME12); @@ -1277,11 +1289,15 @@ protected boolean isIndexOnBooleanColumnSupported() { return true; } + protected boolean isIndexOnBlobColumnSupported() { + return true; + } + protected boolean isTimestampTypeSupported() { return true; } - protected boolean isCreateIndexOnTextAndBlobColumnsEnabled() { + protected boolean isCreateIndexOnTextColumnEnabled() { return true; } }