diff --git a/spring-cql/src/main/java/org/springframework/cassandra/core/cql/generator/AddColumnCqlGenerator.java b/spring-cql/src/main/java/org/springframework/cassandra/core/cql/generator/AddColumnCqlGenerator.java index cf0705956..c4f9c7b46 100644 --- a/spring-cql/src/main/java/org/springframework/cassandra/core/cql/generator/AddColumnCqlGenerator.java +++ b/spring-cql/src/main/java/org/springframework/cassandra/core/cql/generator/AddColumnCqlGenerator.java @@ -15,15 +15,17 @@ */ package org.springframework.cassandra.core.cql.generator; -import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull; +import static org.springframework.cassandra.core.cql.CqlStringUtils.*; import org.springframework.cassandra.core.keyspace.AddColumnSpecification; /** - * CQL generator for generating an ADD clause of an ALTER TABLE statement. + * CQL generator for generating an {@code ADD} clause of an {@code ALTER TABLE} statement. * * @author Matthew T. Adams * @author Mark Paluch + * @see AddColumnSpecification + * @see org.springframework.cassandra.core.keyspace.AlterTableSpecification */ public class AddColumnCqlGenerator extends ColumnChangeCqlGenerator { @@ -31,8 +33,12 @@ public class AddColumnCqlGenerator extends ColumnChangeCqlGeneratorALTER TABLE statements. + * CQL generator for generating {@code ALTER TABLE} statements. * * @author Matthew T. Adams + * @author Mark Paluch + * @see AlterTableSpecification */ public class AlterTableCqlGenerator extends TableOptionsCqlGenerator { + /** + * Generates a CQL statement from the given {@code specification}. + * + * @param specification must not be {@literal null}. + * @return the generated CQL statement. + */ public static String toCql(AlterTableSpecification specification) { return new AlterTableCqlGenerator(specification).toCql(); } + /** + * Creates a new {@literal {@link AlterTableCqlGenerator}. + * + * @param specification must not be {@literal null}. + */ public AlterTableCqlGenerator(AlterTableSpecification specification) { super(specification); } @@ -47,8 +61,16 @@ public class AlterTableCqlGenerator extends TableOptionsCqlGenerator getCqlGeneratorFor(ColumnChangeSpecification change) { + if (change instanceof AddColumnSpecification) { return new AddColumnCqlGenerator((AddColumnSpecification) change); } + if (change instanceof DropColumnSpecification) { return new DropColumnCqlGenerator((DropColumnSpecification) change); } + if (change instanceof AlterColumnSpecification) { return new AlterColumnCqlGenerator((AlterColumnSpecification) change); } + + if (change instanceof RenameColumnSpecification) { + return new RenameColumnCqlGenerator((RenameColumnSpecification) change); + } + throw new IllegalArgumentException("unknown ColumnChangeSpecification type: " + change.getClass().getName()); } @SuppressWarnings("unchecked") protected StringBuilder optionsCql(StringBuilder cql) { + cql = noNull(cql); Map options = spec().getOptions(); @@ -97,7 +128,7 @@ public class AlterTableCqlGenerator extends TableOptionsCqlGeneratorDROP column clause of an ALTER TABLE statement. + * CQL generator for generating a {@code DROP} column clause of an {@code ALTER TABLE} statement. * * @author Matthew T. Adams + * @see DropColumnSpecification + * @see org.springframework.cassandra.core.keyspace.AlterTableSpecification */ public class DropColumnCqlGenerator extends ColumnChangeCqlGenerator { diff --git a/spring-cql/src/main/java/org/springframework/cassandra/core/cql/generator/RenameColumnCqlGenerator.java b/spring-cql/src/main/java/org/springframework/cassandra/core/cql/generator/RenameColumnCqlGenerator.java new file mode 100644 index 000000000..2c4fd8806 --- /dev/null +++ b/spring-cql/src/main/java/org/springframework/cassandra/core/cql/generator/RenameColumnCqlGenerator.java @@ -0,0 +1,42 @@ +/* + * Copyright 2016 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 + * + * http://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.cassandra.core.cql.generator; + +import static org.springframework.cassandra.core.cql.CqlStringUtils.*; + +import org.springframework.cassandra.core.keyspace.RenameColumnSpecification; + +/** + * CQL generator for generating an {@code RENAME} column clause of an {@code ALTER TABLE} statement. + * + * @author Mark Paluch + * @since 1.5 + * @see RenameColumnSpecification + * @see org.springframework.cassandra.core.keyspace.AlterTableSpecification + */ +public class RenameColumnCqlGenerator extends ColumnChangeCqlGenerator { + + RenameColumnCqlGenerator(RenameColumnSpecification specification) { + super(specification); + } + + /* (non-Javadoc) + * @see org.springframework.cassandra.core.cql.generator.ColumnChangeCqlGenerator#toCql(java.lang.StringBuilder) + */ + public StringBuilder toCql(StringBuilder cql) { + return noNull(cql).append("RENAME ").append(spec().getName()).append(" TO ").append(spec().getTargetName()); + } +} diff --git a/spring-cql/src/main/java/org/springframework/cassandra/core/keyspace/AlterTableSpecification.java b/spring-cql/src/main/java/org/springframework/cassandra/core/keyspace/AlterTableSpecification.java index f88b6c3dc..01d63a867 100644 --- a/spring-cql/src/main/java/org/springframework/cassandra/core/keyspace/AlterTableSpecification.java +++ b/spring-cql/src/main/java/org/springframework/cassandra/core/keyspace/AlterTableSpecification.java @@ -24,9 +24,17 @@ import org.springframework.cassandra.core.cql.CqlIdentifier; import com.datastax.driver.core.DataType; /** - * Builder class to construct an ALTER TABLE specification. + * Builder class to construct an {@code ALTER TABLE} specification. * * @author Matthew T. Adams + * @author Mark Paluch + * @see AddColumnSpecification + * @see AlterColumnSpecification + * @see DropColumnSpecification + * @see RenameColumnSpecification + * @see CreateTableSpecification + * @see DropTableSpecification + * @see org.springframework.cassandra.core.cql.generator.AlterTableCqlGenerator */ public class AlterTableSpecification extends TableOptionsSpecification { @@ -60,17 +68,22 @@ public class AlterTableSpecification extends TableOptionsSpecification changes = new ArrayList(); /* - * Adds a DROP to the list of column changes. + * Adds a {@code DROP} to the list of column changes. * - * DW Removed as this only works in C* 2.0 + * @param column must not be empty or {@literal null} + * @return {@literal this} {@link AlterTableSpecification} */ - // public AlterTableSpecification drop(String column) { - // changes.add(new DropColumnSpecification(column)); - // return this; - // } + public AlterTableSpecification drop(String column) { + changes.add(new DropColumnSpecification(column)); + return this; + } /** - * Adds an ADD to the list of column changes. + * Adds an {@code ADD} to the list of column changes. + * + * @param column must not be empty or {@literal null} + * @param type must not be {@literal null} + * @return {@literal this} {@link AlterTableSpecification} */ public AlterTableSpecification add(String column, DataType type) { changes.add(new AddColumnSpecification(column, type)); @@ -78,7 +91,23 @@ public class AlterTableSpecification extends TableOptionsSpecificationALTER to the list of column changes. + * Adds a {@code RENAME} to the list of column changes. + * + * @param from must not be empty or {@literal null} + * @param to must not be empty or {@literal null} + * @return {@literal this} {@link AlterTableSpecification} + */ + public AlterTableSpecification rename(String from, String to) { + changes.add(new RenameColumnSpecification(from, to)); + return this; + } + + /** + * Adds an {@literal ALTER} to the list of column changes. + * + * @param column must not be empty or {@literal null} + * @param type must not be {@literal null} + * @return {@literal this} {@link AlterTableSpecification} */ public AlterTableSpecification alter(String column, DataType type) { changes.add(new AlterColumnSpecification(column, type)); @@ -91,4 +120,5 @@ public class AlterTableSpecification extends TableOptionsSpecification getChanges() { return Collections.unmodifiableList(changes); } + } diff --git a/spring-cql/src/main/java/org/springframework/cassandra/core/keyspace/RenameColumnSpecification.java b/spring-cql/src/main/java/org/springframework/cassandra/core/keyspace/RenameColumnSpecification.java new file mode 100644 index 000000000..d1797552c --- /dev/null +++ b/spring-cql/src/main/java/org/springframework/cassandra/core/keyspace/RenameColumnSpecification.java @@ -0,0 +1,63 @@ +/* + * Copyright 2016 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 + * + * http://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.cassandra.core.keyspace; + +import static org.springframework.cassandra.core.cql.CqlIdentifier.*; + +import org.springframework.cassandra.core.cql.CqlIdentifier; +import org.springframework.util.Assert; + +/** + * {@link ColumnChangeSpecification} to rename a column. + * + * @author Mark Paluch + * @since 1.5 + * @see ColumnChangeSpecification + */ +public class RenameColumnSpecification extends ColumnChangeSpecification { + + private final CqlIdentifier targetName; + + /** + * Creates a new {@link ColumnChangeSpecification}. + * + * @param from must not be empty or {@literal null}. + * @param to must not be empty or {@literal null}. + */ + RenameColumnSpecification(String from, String to) { + this(cqlId(from), cqlId(to)); + } + + /** + * Creates a new {@link ColumnChangeSpecification}. + * + * @param from must not be {@literal null}. + * @param to must not be {@literal null}. + */ + RenameColumnSpecification(CqlIdentifier from, CqlIdentifier to) { + super(from); + + Assert.notNull(to, "Target name must not be null"); + this.targetName = to; + } + + /** + * @return the column name. + */ + public CqlIdentifier getTargetName() { + return targetName; + } +} diff --git a/spring-cql/src/test/java/org/springframework/cassandra/core/cql/generator/AlterTableCqlGeneratorIntegrationTests.java b/spring-cql/src/test/java/org/springframework/cassandra/core/cql/generator/AlterTableCqlGeneratorIntegrationTests.java index d526f38f7..a439a59c7 100644 --- a/spring-cql/src/test/java/org/springframework/cassandra/core/cql/generator/AlterTableCqlGeneratorIntegrationTests.java +++ b/spring-cql/src/test/java/org/springframework/cassandra/core/cql/generator/AlterTableCqlGeneratorIntegrationTests.java @@ -18,9 +18,15 @@ package org.springframework.cassandra.core.cql.generator; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; +import java.util.LinkedHashMap; +import java.util.Map; + import org.junit.Before; import org.junit.Test; import org.springframework.cassandra.core.keyspace.AlterTableSpecification; +import org.springframework.cassandra.core.keyspace.TableOption; +import org.springframework.cassandra.core.keyspace.TableOption.CachingOption; +import org.springframework.cassandra.core.keyspace.TableOption.KeyCachingOption; import org.springframework.cassandra.test.integration.AbstractKeyspaceCreatingIntegrationTest; import com.datastax.driver.core.ColumnMetadata; @@ -32,6 +38,7 @@ import com.datastax.driver.core.TableMetadata; * Integration tests tests for {@link AlterTableCqlGenerator}. * * @author Mark Paluch + * @see DATACASS-192 */ public class AlterTableCqlGeneratorIntegrationTests extends AbstractKeyspaceCreatingIntegrationTest { @@ -48,8 +55,8 @@ public class AlterTableCqlGeneratorIntegrationTests extends AbstractKeyspaceCrea @Test public void alterTableAlterColumnType() { - session.execute("CREATE TABLE addamsFamily (name varchar PRIMARY KEY, gender varchar,\n" - + " lastknownlocation bigint);"); + session.execute( + "CREATE TABLE addamsFamily (name varchar PRIMARY KEY, gender varchar,\n" + " lastknownlocation bigint);"); AlterTableSpecification spec = AlterTableSpecification.alterTable("addamsFamily").alter("lastKnownLocation", DataType.varint()); @@ -66,8 +73,8 @@ public class AlterTableCqlGeneratorIntegrationTests extends AbstractKeyspaceCrea @Test public void alterTableAlterListColumnType() { - session.execute("CREATE TABLE addamsFamily (name varchar PRIMARY KEY, gender varchar,\n" - + " lastknownlocation list);"); + session.execute( + "CREATE TABLE addamsFamily (name varchar PRIMARY KEY, gender varchar,\n" + " lastknownlocation list);"); AlterTableSpecification spec = AlterTableSpecification.alterTable("addamsFamily").alter("lastKnownLocation", DataType.list(DataType.varchar())); @@ -84,8 +91,8 @@ public class AlterTableCqlGeneratorIntegrationTests extends AbstractKeyspaceCrea @Test public void alterTableAddColumn() { - session.execute("CREATE TABLE addamsFamily (name varchar PRIMARY KEY, gender varchar,\n" - + " lastknownlocation varchar);"); + session.execute( + "CREATE TABLE addamsFamily (name varchar PRIMARY KEY, gender varchar,\n" + " lastknownlocation varchar);"); AlterTableSpecification spec = AlterTableSpecification.alterTable("addamsFamily").add("gravesite", DataType.varchar()); @@ -113,6 +120,58 @@ public class AlterTableCqlGeneratorIntegrationTests extends AbstractKeyspaceCrea assertThat(column.getType(), is(equalTo((DataType) DataType.list(DataType.ascii())))); } + /** + * @see DATACASS-192 + */ + @Test + public void alterTableDropColumn() { + + session.execute("CREATE TABLE addamsFamily (name varchar PRIMARY KEY, gender varchar);"); + + AlterTableSpecification spec = AlterTableSpecification.alterTable("addamsFamily").drop("gender"); + + execute(spec); + + assertThat(getTableMetadata("addamsfamily").getColumn("gender"), is(nullValue())); + } + + /** + * @see DATACASS-192 + */ + @Test + public void alterTableRenameColumn() { + + session.execute("CREATE TABLE addamsFamily (name varchar PRIMARY KEY, firstname varchar);"); + + AlterTableSpecification spec = AlterTableSpecification.alterTable("addamsFamily").rename("name", "newname"); + + execute(spec); + + assertThat(getTableMetadata("addamsfamily").getColumn("name"), is(nullValue())); + assertThat(getTableMetadata("addamsfamily").getColumn("newname"), is(notNullValue())); + } + + /** + * @see DATACASS-192 + */ + @Test + public void alterTableAddCaching() { + + session.execute("CREATE TABLE users (user_name varchar PRIMARY KEY);"); + + Map cachingMap = new LinkedHashMap(); + cachingMap.put(CachingOption.KEYS, KeyCachingOption.NONE); + cachingMap.put(CachingOption.ROWS_PER_PARTITION, "15"); + + AlterTableSpecification spec = AlterTableSpecification.alterTable("users").with(TableOption.CACHING, cachingMap); + + execute(spec); + + assertThat(getTableMetadata("users").getOptions().getCaching().get("keys"), is(equalTo("NONE"))); + assertThat(getTableMetadata("users").getOptions().getCaching().get("rows_per_partition"), is(equalTo("15"))); + + } + private void execute(AlterTableSpecification spec) { session.execute(new AlterTableCqlGenerator(spec).toCql()); } diff --git a/spring-cql/src/test/java/org/springframework/cassandra/core/cql/generator/AlterTableCqlGeneratorUnitTests.java b/spring-cql/src/test/java/org/springframework/cassandra/core/cql/generator/AlterTableCqlGeneratorUnitTests.java index bc63c710f..98a41e36a 100644 --- a/spring-cql/src/test/java/org/springframework/cassandra/core/cql/generator/AlterTableCqlGeneratorUnitTests.java +++ b/spring-cql/src/test/java/org/springframework/cassandra/core/cql/generator/AlterTableCqlGeneratorUnitTests.java @@ -18,8 +18,14 @@ package org.springframework.cassandra.core.cql.generator; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; +import java.util.LinkedHashMap; +import java.util.Map; + import org.junit.Test; import org.springframework.cassandra.core.keyspace.AlterTableSpecification; +import org.springframework.cassandra.core.keyspace.TableOption; +import org.springframework.cassandra.core.keyspace.TableOption.CachingOption; +import org.springframework.cassandra.core.keyspace.TableOption.KeyCachingOption; import com.datastax.driver.core.DataType; @@ -80,6 +86,71 @@ public class AlterTableCqlGeneratorUnitTests { assertThat(toCql(spec), is(equalTo("ALTER TABLE users ADD top_places list;"))); } + /** + * @see DATACASS-192 + */ + @Test + public void alterTableDropColumn() { + + AlterTableSpecification spec = AlterTableSpecification.alterTable("addamsFamily").drop("gender"); + + assertThat(toCql(spec), is(equalTo("ALTER TABLE addamsfamily DROP gender;"))); + } + + /** + * @see DATACASS-192 + */ + @Test + public void alterTableRenameColumn() { + + AlterTableSpecification spec = AlterTableSpecification.alterTable("addamsFamily").rename("firstname", "lastname"); + + assertThat(toCql(spec), is(equalTo("ALTER TABLE addamsfamily RENAME firstname TO lastname;"))); + } + + /** + * @see DATACASS-192 + */ + @Test + public void alterTableAddCommentAndTableOption() { + + AlterTableSpecification spec = AlterTableSpecification.alterTable("addamsFamily") + .with(TableOption.READ_REPAIR_CHANCE, 0.2f).with(TableOption.COMMENT, "A most excellent and useful table"); + + assertThat(toCql(spec), is(equalTo( + "ALTER TABLE addamsfamily WITH read_repair_chance = 0.2 AND comment = 'A most excellent and useful table';"))); + } + + /** + * @see DATACASS-192 + */ + @Test + public void alterTableAddColumnAndComment() { + + AlterTableSpecification spec = AlterTableSpecification.alterTable("addamsFamily") + .add("top_places", DataType.list(DataType.ascii())).add("other", DataType.list(DataType.ascii())) + .with(TableOption.COMMENT, "A most excellent and useful table"); + + assertThat(toCql(spec), is(equalTo( + "ALTER TABLE addamsfamily ADD top_places list ADD other list WITH comment = 'A most excellent and useful table';"))); + } + + /** + * @see DATACASS-192 + */ + @Test + public void alterTableAddCaching() { + + Map cachingMap = new LinkedHashMap(); + cachingMap.put(CachingOption.KEYS, KeyCachingOption.NONE); + cachingMap.put(CachingOption.ROWS_PER_PARTITION, "15"); + + AlterTableSpecification spec = AlterTableSpecification.alterTable("users").with(TableOption.CACHING, cachingMap); + + assertThat(toCql(spec), + is(equalTo("ALTER TABLE users WITH caching = { 'keys' : 'none', 'rows_per_partition' : '15' };"))); + } + private String toCql(AlterTableSpecification spec) { return new AlterTableCqlGenerator(spec).toCql(); }