Skip to content

Commit f8e5f4c

Browse files
committed
JAVA-2263 validate missing ClusteringColumns before doing validation for rest of the columns
1 parent 453b5fd commit f8e5f4c

3 files changed

Lines changed: 87 additions & 2 deletions

File tree

integration-tests/src/test/java/com/datastax/oss/driver/mapper/SchemaValidationIT.java

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.datastax.oss.driver.api.core.CqlSession;
2424
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
2525
import com.datastax.oss.driver.api.core.servererrors.InvalidQueryException;
26+
import com.datastax.oss.driver.api.mapper.annotations.ClusteringColumn;
2627
import com.datastax.oss.driver.api.mapper.annotations.Dao;
2728
import com.datastax.oss.driver.api.mapper.annotations.DaoFactory;
2829
import com.datastax.oss.driver.api.mapper.annotations.DaoKeyspace;
@@ -68,6 +69,7 @@ public static void setup() {
6869
Arrays.asList(
6970
"CREATE TABLE product_simple(id uuid PRIMARY KEY, description text, unmapped text)",
7071
"CREATE TABLE product_simple_missing_p_k(id uuid PRIMARY KEY, description text, unmapped text)",
72+
"CREATE TABLE product_simple_missing_clustering_column(id uuid PRIMARY KEY, description text, unmapped text)",
7173
"CREATE TYPE dimensions_with_incorrect_name(length int, width int, height int)",
7274
"CREATE TYPE dimensions_with_incorrect_name_schema_hint_udt(length int, width int, height int)",
7375
"CREATE TYPE dimensions_with_incorrect_name_schema_hint_table(length int, width int, height int)",
@@ -203,6 +205,16 @@ public void should_throw_when_table_is_missing_PKs() {
203205
sessionRule.keyspace()));
204206
}
205207

208+
@Test
209+
public void should_throw_when_table_is_missing_clustering_column() {
210+
assertThatThrownBy(() -> mapper.productSimpleMissingClusteringColumn(sessionRule.keyspace()))
211+
.isInstanceOf(IllegalArgumentException.class)
212+
.hasMessageContaining(
213+
String.format(
214+
"The CQL ks.table: %s.product_simple_missing_clustering_column has missing Clustering columns: [not_existing_clustering_column] that are defined in the entity class: com.datastax.oss.driver.mapper.SchemaValidationIT.ProductSimpleMissingClusteringColumn",
215+
sessionRule.keyspace()));
216+
}
217+
206218
@Mapper
207219
public interface InventoryMapper {
208220
@DaoFactory
@@ -231,6 +243,10 @@ ProductWithIncorrectUdtSchemaHintTableDao productWithIncorrectUdtSchemaHintTable
231243

232244
@DaoFactory
233245
ProductSimpleMissingPKDao productSimpleMissingPKDao(@DaoKeyspace CqlIdentifier keyspace);
246+
247+
@DaoFactory
248+
ProductSimpleMissingClusteringColumnDao productSimpleMissingClusteringColumn(
249+
@DaoKeyspace CqlIdentifier keyspace);
234250
}
235251

236252
@Dao
@@ -268,7 +284,7 @@ public interface ProductSimpleDao {
268284
ProductSimple findById(UUID productId);
269285
}
270286

271-
@Dao()
287+
@Dao
272288
public interface ProductSimpleDaoValidationDisabledDao {
273289

274290
@Select
@@ -288,6 +304,12 @@ public interface ProductSimpleMissingPKDao {
288304
ProductSimpleMissingPK findById(UUID productId);
289305
}
290306

307+
@Dao
308+
public interface ProductSimpleMissingClusteringColumnDao {
309+
@Select
310+
ProductSimpleMissingClusteringColumn findById(UUID productId);
311+
}
312+
291313
@Entity
292314
public static class ProductCqlTableMissing {
293315
@PartitionKey private UUID id;
@@ -318,6 +340,30 @@ public void setIdNotPresent(UUID idNotPresent) {
318340
}
319341
}
320342

343+
@Entity
344+
public static class ProductSimpleMissingClusteringColumn {
345+
@PartitionKey private UUID id;
346+
@ClusteringColumn private Integer notExistingClusteringColumn;
347+
348+
public ProductSimpleMissingClusteringColumn() {}
349+
350+
public UUID getId() {
351+
return id;
352+
}
353+
354+
public void setId(UUID id) {
355+
this.id = id;
356+
}
357+
358+
public Integer getNotExistingClusteringColumn() {
359+
return notExistingClusteringColumn;
360+
}
361+
362+
public void setNotExistingClusteringColumn(Integer notExistingClusteringColumn) {
363+
this.notExistingClusteringColumn = notExistingClusteringColumn;
364+
}
365+
}
366+
321367
@Entity
322368
public static class ProductSimple {
323369
@PartitionKey private UUID id;

mapper-processor/src/main/java/com/datastax/oss/driver/internal/mapper/processor/entity/EntityHelperSchemaValidationMethodGenerator.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ else if (targetElement.get().equals(TargetElement.UDT)) {
135135
// CQL table
136136
private void findMissingColumnsInTable(MethodSpec.Builder methodBuilder) {
137137
methodBuilder.beginControlFlow("if (tableMetadata.isPresent())");
138+
139+
// handle missing Clustering Columns
140+
generateMissingClusteringColumnsCheck(methodBuilder);
141+
138142
// handle missing PKs
139143
generateMissingPKsCheck(methodBuilder);
140144

@@ -203,6 +207,40 @@ private void generateMissingPKsCheck(MethodSpec.Builder methodBuilder) {
203207
methodBuilder.endControlFlow();
204208
}
205209

210+
private void generateMissingClusteringColumnsCheck(MethodSpec.Builder methodBuilder) {
211+
List<CodeBlock> expectedCqlClusteringColumns =
212+
entityDefinition.getClusteringColumns().stream()
213+
.map(PropertyDefinition::getCqlName)
214+
.collect(Collectors.toList());
215+
216+
methodBuilder.addStatement(
217+
"$1T<$2T> expectedCqlClusteringColumns = new $3T<>()",
218+
List.class,
219+
CqlIdentifier.class,
220+
ArrayList.class);
221+
for (CodeBlock expectedCqlName : expectedCqlClusteringColumns) {
222+
methodBuilder.addStatement(
223+
"expectedCqlClusteringColumns.add($1T.fromCql($2L))",
224+
CqlIdentifier.class,
225+
expectedCqlName);
226+
}
227+
228+
methodBuilder.addStatement(
229+
"$1T<$2T> missingTableClusteringColumnNames = findMissingColumns(expectedCqlClusteringColumns, tableMetadata.get().getClusteringColumns().keySet())",
230+
List.class,
231+
CqlIdentifier.class);
232+
233+
// throw if there are any missing Clustering Columns columns
234+
CodeBlock missingCqlColumnExceptionMessage =
235+
CodeBlock.of(
236+
"String.format(\"The CQL ks.table: %s.%s has missing Clustering columns: %s that are defined in the entity class: %s\", "
237+
+ "keyspaceId, tableId, missingTableClusteringColumnNames, entityClassName)");
238+
methodBuilder.beginControlFlow("if (!missingTableClusteringColumnNames.isEmpty())");
239+
methodBuilder.addStatement(
240+
"throw new $1T($2L)", IllegalArgumentException.class, missingCqlColumnExceptionMessage);
241+
methodBuilder.endControlFlow();
242+
}
243+
206244
// Finds out missingTableCqlNames - columns that are present in Entity Mapping but NOT present in
207245
// UDT table
208246
private void findMissingColumnsInUdt(MethodSpec.Builder methodBuilder, boolean generateElse) {

mapper-runtime/src/main/java/com/datastax/oss/driver/internal/mapper/entity/EntityHelperBase.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import edu.umd.cs.findbugs.annotations.NonNull;
2727
import edu.umd.cs.findbugs.annotations.Nullable;
2828
import java.util.ArrayList;
29+
import java.util.Collection;
2930
import java.util.List;
3031
import java.util.stream.Collectors;
3132

@@ -81,7 +82,7 @@ protected void throwIfKeyspaceMissing() {
8182
}
8283

8384
public List<CqlIdentifier> findMissingColumns(
84-
List<CqlIdentifier> expected, List<ColumnMetadata> actual) {
85+
List<CqlIdentifier> expected, Collection<ColumnMetadata> actual) {
8586
List<CqlIdentifier> missingColumns = new ArrayList<>();
8687
List<CqlIdentifier> actualCql =
8788
actual.stream().map(ColumnMetadata::getName).collect(Collectors.toList());

0 commit comments

Comments
 (0)