Skip to content

Commit

Permalink
Refine API to create and render CQL object specifications.
Browse files Browse the repository at this point in the history
We now expose specification entrypoints at SpecificationBuilder and a generic generator at CqlGenerator.toCql(…).

Closes #1506
  • Loading branch information
mp911de committed Jul 25, 2024
1 parent e154ef6 commit 41805cc
Show file tree
Hide file tree
Showing 43 changed files with 1,010 additions and 202 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,9 @@
import org.springframework.data.cassandra.core.convert.SchemaFactory;
import org.springframework.data.cassandra.core.cql.CqlOperations;
import org.springframework.data.cassandra.core.cql.SessionCallback;
import org.springframework.data.cassandra.core.cql.generator.CreateTableCqlGenerator;
import org.springframework.data.cassandra.core.cql.generator.DropTableCqlGenerator;
import org.springframework.data.cassandra.core.cql.generator.DropUserTypeCqlGenerator;
import org.springframework.data.cassandra.core.cql.generator.CqlGenerator;
import org.springframework.data.cassandra.core.cql.keyspace.CreateTableSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.DropTableSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.DropUserTypeSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.SpecificationBuilder;
import org.springframework.data.cassandra.core.cql.keyspace.TableOption;
import org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity;
import org.springframework.util.Assert;
Expand Down Expand Up @@ -127,7 +124,7 @@ public void createTable(boolean ifNotExists, CqlIdentifier tableName, Class<?> e
});
}

getCqlOperations().execute(CreateTableCqlGenerator.toCql(createTableSpecification));
getCqlOperations().execute(CqlGenerator.toCql(createTableSpecification));
}

@Override
Expand All @@ -143,7 +140,7 @@ public void dropTable(CqlIdentifier tableName) {
@Override
public void dropTable(boolean ifExists, CqlIdentifier tableName) {

String dropTableCql = DropTableCqlGenerator.toCql(DropTableSpecification.dropTable(tableName).ifExists(ifExists));
String dropTableCql = CqlGenerator.toCql(SpecificationBuilder.dropTable(tableName).ifExists(ifExists));

getCqlOperations().execute(dropTableCql);
}
Expand All @@ -153,7 +150,7 @@ public void dropUserType(CqlIdentifier typeName) {

Assert.notNull(typeName, "Type name must not be null");

String dropUserTypeCql = DropUserTypeCqlGenerator.toCql(DropUserTypeSpecification.dropType(typeName));
String dropUserTypeCql = CqlGenerator.toCql(SpecificationBuilder.dropType(typeName));

getCqlOperations().execute(dropUserTypeCql);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@
import java.util.stream.Collectors;

import org.jetbrains.annotations.NotNull;
import org.springframework.data.cassandra.core.cql.generator.CreateIndexCqlGenerator;
import org.springframework.data.cassandra.core.cql.generator.CreateTableCqlGenerator;
import org.springframework.data.cassandra.core.cql.generator.CreateUserTypeCqlGenerator;

import org.springframework.data.cassandra.core.cql.generator.CqlGenerator;
import org.springframework.data.cassandra.core.cql.keyspace.CreateIndexSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.CreateTableSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.CreateUserTypeSpecification;
Expand Down Expand Up @@ -96,7 +95,7 @@ public CassandraPersistentEntitySchemaCreator(CassandraMappingContext mappingCon
public void createTables(boolean ifNotExists) {

createTableSpecifications(ifNotExists).stream() //
.map(CreateTableCqlGenerator::toCql) //
.map(CqlGenerator::toCql) //
.forEach(cql -> this.cassandraAdminOperations.getCqlOperations().execute(cql));
}

Expand All @@ -123,7 +122,7 @@ protected List<CreateTableSpecification> createTableSpecifications(boolean ifNot
public void createIndexes(boolean ifNotExists) {

createIndexSpecifications(ifNotExists).stream() //
.map(CreateIndexCqlGenerator::toCql) //
.map(CqlGenerator::toCql) //
.forEach(cql -> this.cassandraAdminOperations.getCqlOperations().execute(cql));
}

Expand All @@ -150,7 +149,7 @@ protected List<CreateIndexSpecification> createIndexSpecifications(boolean ifNot
public void createUserTypes(boolean ifNotExists) {

createUserTypeSpecifications(ifNotExists).stream() //
.map(CreateUserTypeCqlGenerator::toCql) //
.map(CqlGenerator::toCql) //
.forEach(cql -> this.cassandraAdminOperations.getCqlOperations().execute(cql));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.data.cassandra.core.cql.keyspace.CreateIndexSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.SpecificationBuilder;
import org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty;
import org.springframework.data.cassandra.core.mapping.Indexed;
import org.springframework.data.cassandra.core.mapping.SASI;
Expand Down Expand Up @@ -136,9 +137,9 @@ static CreateIndexSpecification createIndexSpecification(@Nullable CqlIdentifier
CreateIndexSpecification index;

if (StringUtils.hasText(annotation.value())) {
index = CreateIndexSpecification.createIndex(keyspace, CqlIdentifier.fromCql(annotation.value()));
index = SpecificationBuilder.createIndex(keyspace, CqlIdentifier.fromCql(annotation.value()));
} else {
index = CreateIndexSpecification.createIndex(keyspace, null);
index = SpecificationBuilder.createIndex(keyspace, null);
}

return index.columnName(property.getRequiredColumnName());
Expand All @@ -150,9 +151,9 @@ private static CreateIndexSpecification createIndexSpecification(@Nullable CqlId
CreateIndexSpecification index;

if (StringUtils.hasText(annotation.value())) {
index = CreateIndexSpecification.createIndex(keyspace, CqlIdentifier.fromCql(annotation.value()));
index = SpecificationBuilder.createIndex(keyspace, CqlIdentifier.fromCql(annotation.value()));
} else {
index = CreateIndexSpecification.createIndex(keyspace, null);
index = SpecificationBuilder.createIndex(keyspace, null);
}

index.using("org.apache.cassandra.index.sasi.SASIIndex") //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,14 @@
*/
package org.springframework.data.cassandra.core.convert;

import static org.springframework.data.cassandra.core.cql.keyspace.CreateTableSpecification.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import org.springframework.data.cassandra.core.cql.keyspace.CreateIndexSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.CreateTableSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.CreateUserTypeSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.SpecificationBuilder;
import org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity;
import org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty;
import org.springframework.data.cassandra.core.mapping.EmbeddedEntityOperations;
Expand Down Expand Up @@ -141,7 +140,7 @@ public CreateTableSpecification getCreateTableSpecificationFor(CassandraPersiste
Assert.notNull(tableName, "Table name must not be null");
Assert.notNull(entity, "CassandraPersistentEntity must not be null");

CreateTableSpecification specification = createTable(entity.getKeyspace(), tableName);
CreateTableSpecification specification = SpecificationBuilder.createTable(entity.getKeyspace(), tableName);

for (CassandraPersistentProperty property : entity) {

Expand Down Expand Up @@ -296,7 +295,7 @@ public CreateUserTypeSpecification getCreateUserTypeSpecificationFor(CassandraPe

Assert.notNull(entity, "CassandraPersistentEntity must not be null");

CreateUserTypeSpecification specification = CreateUserTypeSpecification.createType(entity.getKeyspace(),
CreateUserTypeSpecification specification = SpecificationBuilder.createType(entity.getKeyspace(),
entity.getTableName());

for (CassandraPersistentProperty property : entity) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.core.cql.generator;

import org.springframework.data.cassandra.core.cql.keyspace.*;

/**
* Entrypoint for CQL generation of {@link CqlSpecification} objects representing DML statements such as table creations
* or keyspace drops. For example:
*
* <pre class="code">
* DropUserTypeSpecification spec = SpecificationBuilder.dropType("address");
* String cql = CqlGenerator.toCql(spec);
* </pre>
*
* @author Mark Paluch
* @since 4.4
* @see SpecificationBuilder
*/
public final class CqlGenerator {

private CqlGenerator() {
// utility class, no instances
}

/**
* Entrypoint for CQL generation of {@link CqlSpecification} objects.
*
* @param specification the CQL specification to generate CQL for.
* @return the generated CQL from {@link CqlSpecification}.
*/
public static String toCql(CqlSpecification specification) {

if (specification instanceof CreateKeyspaceSpecification createKeyspace) {
return CreateKeyspaceCqlGenerator.toCql(createKeyspace);
}

if (specification instanceof AlterKeyspaceSpecification alterKeyspace) {
return AlterKeyspaceCqlGenerator.toCql(alterKeyspace);
}

if (specification instanceof DropKeyspaceSpecification dropKeyspace) {
return DropKeyspaceCqlGenerator.toCql(dropKeyspace);
}

if (specification instanceof CreateTableSpecification createTable) {
return CreateTableCqlGenerator.toCql(createTable);
}

if (specification instanceof AlterTableSpecification alterTable) {
return AlterTableCqlGenerator.toCql(alterTable);
}

if (specification instanceof DropTableSpecification dropTable) {
return DropTableCqlGenerator.toCql(dropTable);
}

if (specification instanceof CreateUserTypeSpecification createType) {
return CreateUserTypeCqlGenerator.toCql(createType);
}

if (specification instanceof AlterUserTypeSpecification alterType) {
return AlterUserTypeCqlGenerator.toCql(alterType);
}

if (specification instanceof DropUserTypeSpecification dropType) {
return DropUserTypeCqlGenerator.toCql(dropType);
}

if (specification instanceof CreateIndexSpecification createIndex) {
return CreateIndexCqlGenerator.toCql(createIndex);
}

if (specification instanceof DropIndexSpecification dropIndex) {
return DropIndexCqlGenerator.toCql(dropIndex);
}

throw new UnsupportedOperationException(String.format("CQL specification %s is not supported", specification));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
*
* @author Mark Paluch
*/
public class AlterKeyspaceSpecification extends KeyspaceOptionsSpecification<AlterKeyspaceSpecification> {
public class AlterKeyspaceSpecification extends KeyspaceOptionsSpecification<AlterKeyspaceSpecification>
implements CqlSpecification {

private AlterKeyspaceSpecification(CqlIdentifier name) {
super(name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
* @see TableOptionsSpecification
* @see org.springframework.data.cassandra.core.cql.generator.AlterTableCqlGenerator
*/
public class AlterTableSpecification extends TableOptionsSpecification<AlterTableSpecification> {
public class AlterTableSpecification extends TableOptionsSpecification<AlterTableSpecification>
implements CqlSpecification {

/**
* The list of column changes.
Expand Down Expand Up @@ -81,7 +82,7 @@ public static AlterTableSpecification alterTable(CqlIdentifier tableName) {
* @return a new {@link AlterTableSpecification}.
* @since 4.4
*/
public static AlterTableSpecification alterTable(CqlIdentifier keyspace, CqlIdentifier tableName) {
public static AlterTableSpecification alterTable(@Nullable CqlIdentifier keyspace, CqlIdentifier tableName) {
return new AlterTableSpecification(keyspace, tableName);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
* @since 1.5
* @see CqlIdentifier
*/
public class AlterUserTypeSpecification extends UserTypeNameSpecification {
public class AlterUserTypeSpecification extends UserTypeNameSpecification implements CqlSpecification {

private final List<ColumnChangeSpecification> changes = new ArrayList<>();

Expand All @@ -58,7 +58,7 @@ public static AlterUserTypeSpecification alterType(String typeName) {
* @param typeName must not be {@literal null}.
* @return a new {@link AlterUserTypeSpecification}.
*/
private static AlterUserTypeSpecification alterType(CqlIdentifier typeName) {
public static AlterUserTypeSpecification alterType(CqlIdentifier typeName) {
return new AlterUserTypeSpecification(null, typeName);
}

Expand All @@ -70,8 +70,9 @@ private static AlterUserTypeSpecification alterType(CqlIdentifier typeName) {
* @param keyspace can be {@literal null}.
* @param typeName must not be {@literal null}.
* @return a new {@link AlterUserTypeSpecification}.
* @since 4.4
*/
private static AlterUserTypeSpecification alterType(@Nullable CqlIdentifier keyspace, CqlIdentifier typeName) {
public static AlterUserTypeSpecification alterType(@Nullable CqlIdentifier keyspace, CqlIdentifier typeName) {
return new AlterUserTypeSpecification(keyspace, typeName);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.core.cql.keyspace;

/**
* Marker interface for CQL specification objects that describe CQL keyspace objects.
*
* @author Mark Paluch
* @since 4.4
*/
public interface CqlSpecification {}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
* @author Mark Paluch
*/
public class CreateIndexSpecification extends IndexNameSpecification<CreateIndexSpecification>
implements IndexDescriptor {
implements IndexDescriptor, CqlSpecification {

private @Nullable CqlIdentifier tableName;

Expand All @@ -57,15 +57,15 @@ private CreateIndexSpecification(@Nullable CqlIdentifier keyspace, @Nullable Cql
}

/**
* Entry point into the {@link CreateIndexSpecification}'s fluent API to create a index. Convenient if imported
* Entry point into the {@link CreateIndexSpecification}'s fluent API to create an index. Convenient if imported
* statically.
*/
public static CreateIndexSpecification createIndex() {
return new CreateIndexSpecification();
}

/**
* Entry point into the {@link CreateIndexSpecification}'s fluent API given {@code indexName} to create a index.
* Entry point into the {@link CreateIndexSpecification}'s fluent API given {@code indexName} to create an index.
* Convenient if imported statically.
*
* @param indexName must not be {@literal null} or empty.
Expand All @@ -76,7 +76,7 @@ public static CreateIndexSpecification createIndex(String indexName) {
}

/**
* Entry point into the {@link CreateIndexSpecification}'s fluent API given {@code indexName} to create a index.
* Entry point into the {@link CreateIndexSpecification}'s fluent API given {@code indexName} to create an index.
* Convenient if imported statically.
*
* @param indexName must not be {@literal null}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* @author Mark Paluch
*/
public class CreateKeyspaceSpecification extends KeyspaceOptionsSpecification<CreateKeyspaceSpecification>
implements KeyspaceDescriptor {
implements KeyspaceDescriptor, CqlSpecification {

private boolean ifNotExists = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* @author Matthew T. Adams
* @author Mark Paluch
*/
public class CreateTableSpecification extends TableSpecification<CreateTableSpecification> {
public class CreateTableSpecification extends TableSpecification<CreateTableSpecification> implements CqlSpecification {

private boolean ifNotExists = false;

Expand Down
Loading

0 comments on commit 41805cc

Please # to comment.