separated buildes from specifications

This commit is contained in:
Matthew Adams
2013-11-20 14:42:36 -06:00
parent 37de816c2d
commit 515f55c4f7
31 changed files with 549 additions and 349 deletions

View File

@@ -0,0 +1,85 @@
package org.springframework.cassandra.core.cql.builder;
import static org.springframework.cassandra.core.cql.CqlStringUtils.escapeSingle;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import static org.springframework.cassandra.core.cql.CqlStringUtils.singleQuote;
import java.util.Map;
import org.springframework.cassandra.core.keyspace.AbstractTableSpecification;
import org.springframework.cassandra.core.keyspace.Option;
import org.springframework.util.Assert;
/**
* Base class that contains behavior common to table operations.
*
* @author Matthew T. Adams
* @param T The subtype of AbstractTableSpecification for which this is a CQL generator.
*/
public abstract class AbstractTableOperationCqlGenerator<T extends AbstractTableSpecification<T>> {
protected abstract StringBuilder toCql(StringBuilder cql);
private AbstractTableSpecification<T> specification;
public AbstractTableOperationCqlGenerator(AbstractTableSpecification<T> specification) {
setSpecification(specification);
}
protected void setSpecification(AbstractTableSpecification<T> specification) {
Assert.notNull(specification);
this.specification = specification;
}
@SuppressWarnings("unchecked")
public T getSpecification() {
return (T) specification;
}
/**
* Convenient synonymous method of {@link #getSpecification()}.
*/
protected T spec() {
return getSpecification();
}
protected StringBuilder optionValueMap(Map<Option, Object> valueMap, StringBuilder cql) {
cql = noNull(cql);
if (valueMap == null || valueMap.isEmpty()) {
return cql;
}
// else option value is a non-empty map
// append { 'name' : 'value', ... }
cql.append("{ ");
boolean mapFirst = true;
for (Map.Entry<Option, Object> entry : valueMap.entrySet()) {
if (mapFirst) {
mapFirst = false;
} else {
cql.append(", ");
}
Option option = entry.getKey();
cql.append(singleQuote(option.getName())); // entries in map keys are always quoted
cql.append(" : ");
Object entryValue = entry.getValue();
entryValue = entryValue == null ? "" : entryValue.toString();
if (option.escapesValue()) {
entryValue = escapeSingle(entryValue);
}
if (option.quotesValue()) {
entryValue = singleQuote(entryValue);
}
cql.append(entryValue);
}
cql.append(" }");
return cql;
}
public String toCql() {
return toCql(null).toString();
}
}

View File

@@ -1,17 +0,0 @@
package org.springframework.cassandra.core.cql.builder;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import com.datastax.driver.core.DataType;
public class AddColumn extends ColumnTypeChange {
public AddColumn(String name, DataType type) {
super(name, type);
}
@Override
public StringBuilder toCql(StringBuilder cql) {
return noNull(cql).append("ADD ").append(getNameAsIdentifier()).append(" TYPE ").append(getType().getName());
}
}

View File

@@ -0,0 +1,18 @@
package org.springframework.cassandra.core.cql.builder;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import org.springframework.cassandra.core.keyspace.AddColumnSpecification;
public class AddColumnCqlGenerator extends ColumnChangeCqlGenerator<AddColumnSpecification> {
public AddColumnCqlGenerator(AddColumnSpecification specification) {
super(specification);
}
@Override
public StringBuilder toCql(StringBuilder cql) {
return noNull(cql).append("ADD ").append(spec().getNameAsIdentifier()).append(" TYPE ")
.append(spec().getType().getName());
}
}

View File

@@ -0,0 +1,17 @@
package org.springframework.cassandra.core.cql.builder;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import org.springframework.cassandra.core.keyspace.AlterColumnSpecification;
public class AlterColumnCqlGenerator extends ColumnChangeCqlGenerator<AlterColumnSpecification> {
public AlterColumnCqlGenerator(AlterColumnSpecification specification) {
super(specification);
}
public StringBuilder toCql(StringBuilder cql) {
return noNull(cql).append("ALTER ").append(spec().getNameAsIdentifier()).append(" TYPE ")
.append(spec().getType().getName());
}
}

View File

@@ -1,103 +0,0 @@
package org.springframework.cassandra.core.cql.builder;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.datastax.driver.core.DataType;
public class AlterTableBuilder extends AbstractTableBuilder<AlterTableBuilder> {
private List<ColumnChange> changes = new ArrayList<ColumnChange>();
public AlterTableBuilder drop(String column) {
changes.add(new DropColumn(column));
return this;
}
public AlterTableBuilder add(String column, DataType type) {
changes.add(new AddColumn(column, type));
return this;
}
public AlterTableBuilder alter(String column, DataType type) {
changes.add(new AlterColumn(column, type));
return this;
}
public AlterTableBuilder name(String name) {
return (AlterTableBuilder) super.name(name);
}
@Override
public StringBuilder toCql(StringBuilder cql) {
cql = noNull(cql);
preambleCql(cql);
changesCql(cql);
optionsCql(cql);
cql.append(";");
return cql;
}
protected StringBuilder preambleCql(StringBuilder cql) {
return noNull(cql).append("ALTER TABLE ").append(getNameAsIdentifier()).append(" ");
}
protected StringBuilder changesCql(StringBuilder cql) {
cql = noNull(cql);
boolean first = true;
for (ColumnChange change : changes) {
if (first) {
first = false;
} else {
cql.append(" ");
}
change.toCql(cql);
}
return cql;
}
@SuppressWarnings("unchecked")
protected StringBuilder optionsCql(StringBuilder cql) {
cql = noNull(cql);
Map<String, Object> options = options();
if (options == null || options.isEmpty()) {
return cql;
}
cql.append(" WITH ");
boolean first = true;
for (String key : options.keySet()) {
if (first) {
first = false;
} else {
cql.append(" AND ");
}
cql.append(key);
Object value = options.get(key);
if (value == null) {
continue;
}
cql.append(" = ");
if (value instanceof Map) {
optionValueMap((Map<Option, Object>) value, cql);
continue;
}
// else just use value as string
cql.append(value.toString());
}
return cql;
}
}

View File

@@ -0,0 +1,102 @@
package org.springframework.cassandra.core.cql.builder;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import java.util.Map;
import org.springframework.cassandra.core.keyspace.AddColumnSpecification;
import org.springframework.cassandra.core.keyspace.AlterColumnSpecification;
import org.springframework.cassandra.core.keyspace.AlterTableSpecification;
import org.springframework.cassandra.core.keyspace.ColumnChangeSpecification;
import org.springframework.cassandra.core.keyspace.DropColumnSpecification;
import org.springframework.cassandra.core.keyspace.Option;
public class AlterTableCqlGenerator extends AbstractTableOperationCqlGenerator<AlterTableSpecification> {
public AlterTableCqlGenerator(AlterTableSpecification specification) {
super(specification);
}
@Override
public StringBuilder toCql(StringBuilder cql) {
cql = noNull(cql);
preambleCql(cql);
changesCql(cql);
optionsCql(cql);
cql.append(";");
return cql;
}
protected StringBuilder preambleCql(StringBuilder cql) {
return noNull(cql).append("ALTER TABLE ").append(spec().getNameAsIdentifier()).append(" ");
}
protected StringBuilder changesCql(StringBuilder cql) {
cql = noNull(cql);
boolean first = true;
for (ColumnChangeSpecification change : spec().getChanges()) {
if (first) {
first = false;
} else {
cql.append(" ");
}
getCqlGeneratorFor(change).toCql(cql);
}
return cql;
}
protected ColumnChangeCqlGenerator<?> 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);
}
throw new Error("unknown ColumnChangeSpecification type: " + change.getClass().getName());
}
@SuppressWarnings("unchecked")
protected StringBuilder optionsCql(StringBuilder cql) {
cql = noNull(cql);
Map<String, Object> options = spec().getOptions();
if (options == null || options.isEmpty()) {
return cql;
}
cql.append(" WITH ");
boolean first = true;
for (String key : options.keySet()) {
if (first) {
first = false;
} else {
cql.append(" AND ");
}
cql.append(key);
Object value = options.get(key);
if (value == null) {
continue;
}
cql.append(" = ");
if (value instanceof Map) {
optionValueMap((Map<Option, Object>) value, cql);
continue;
}
// else just use value as string
cql.append(value.toString());
}
return cql;
}
}

View File

@@ -0,0 +1,29 @@
package org.springframework.cassandra.core.cql.builder;
import org.springframework.cassandra.core.keyspace.ColumnChangeSpecification;
import org.springframework.util.Assert;
public abstract class ColumnChangeCqlGenerator<T extends ColumnChangeSpecification> {
public abstract StringBuilder toCql(StringBuilder cql);
private ColumnChangeSpecification specification;
public ColumnChangeCqlGenerator(ColumnChangeSpecification specification) {
setSpecification(specification);
}
protected void setSpecification(ColumnChangeSpecification specification) {
Assert.notNull(specification);
this.specification = specification;
}
@SuppressWarnings("unchecked")
public T getSpecification() {
return (T) specification;
}
protected T spec() {
return getSpecification();
}
}

View File

@@ -3,69 +3,24 @@ package org.springframework.cassandra.core.cql.builder;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import static org.springframework.data.cassandra.mapping.KeyType.PARTITION;
import static org.springframework.data.cassandra.mapping.KeyType.PRIMARY;
import static org.springframework.data.cassandra.mapping.Ordering.ASCENDING;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.springframework.data.cassandra.mapping.KeyType;
import org.springframework.data.cassandra.mapping.Ordering;
import com.datastax.driver.core.DataType;
import org.springframework.cassandra.core.keyspace.ColumnSpecification;
import org.springframework.cassandra.core.keyspace.CreateTableSpecification;
import org.springframework.cassandra.core.keyspace.Option;
/**
* Builder class to construct CQL for a <code>CREATE TABLE</code> statement. Not threadsafe.
*
* @author Matthew T. Adams
*/
public class CreateTableBuilder extends AbstractTableBuilder<CreateTableBuilder> {
public class CreateTableCqlGenerator extends AbstractTableOperationCqlGenerator<CreateTableSpecification> {
private boolean ifNotExists = false;
private List<ColumnBuilder> columns = new ArrayList<ColumnBuilder>();
/**
* Causes the inclusion of an <code>IF NOT EXISTS</code> clause.
*
* @return this
*/
public CreateTableBuilder ifNotExists() {
return ifNotExists(true);
}
/**
* Toggles the inclusion of an <code>IF NOT EXISTS</code> clause.
*
* @return this
*/
public CreateTableBuilder ifNotExists(boolean ifNotExists) {
this.ifNotExists = ifNotExists;
return this;
}
public CreateTableBuilder column(String name, DataType type) {
return column(name, type, null, null);
}
public CreateTableBuilder partitionKeyColumn(String name, DataType type) {
return column(name, type, PARTITION, null);
}
public CreateTableBuilder primaryKeyColumn(String name, DataType type) {
return primaryKeyColumn(name, type, ASCENDING);
}
public CreateTableBuilder primaryKeyColumn(String name, DataType type, Ordering order) {
return column(name, type, PRIMARY, order);
}
protected CreateTableBuilder column(String name, DataType type, KeyType keyType, Ordering ordering) {
columns().add(new ColumnBuilder().name(name).type(type).keyType(keyType).ordering(ordering));
return this;
}
protected List<ColumnBuilder> columns() {
return columns == null ? columns = new ArrayList<ColumnBuilder>() : columns;
public CreateTableCqlGenerator(CreateTableSpecification specification) {
super(specification);
}
public StringBuilder toCql(StringBuilder cql) {
@@ -81,8 +36,8 @@ public class CreateTableBuilder extends AbstractTableBuilder<CreateTableBuilder>
}
protected StringBuilder preambleCql(StringBuilder cql) {
return noNull(cql).append("CREATE TABLE ").append(ifNotExists ? "IF NOT EXISTS " : "")
.append(getNameAsIdentifier());
return noNull(cql).append("CREATE TABLE ").append(spec().getIfNotExists() ? "IF NOT EXISTS " : "")
.append(spec().getNameAsIdentifier());
}
@SuppressWarnings("unchecked")
@@ -93,9 +48,9 @@ public class CreateTableBuilder extends AbstractTableBuilder<CreateTableBuilder>
// begin columns
cql.append(" (");
List<ColumnBuilder> partitionKeys = new ArrayList<ColumnBuilder>();
List<ColumnBuilder> primaryKeys = new ArrayList<ColumnBuilder>();
for (ColumnBuilder col : columns) {
List<ColumnSpecification> partitionKeys = new ArrayList<ColumnSpecification>();
List<ColumnSpecification> primaryKeys = new ArrayList<ColumnSpecification>();
for (ColumnSpecification col : spec().getColumns()) {
col.toCql(cql).append(", ");
if (col.getKeyType() == PARTITION) {
@@ -115,7 +70,7 @@ public class CreateTableBuilder extends AbstractTableBuilder<CreateTableBuilder>
}
boolean first = true;
for (ColumnBuilder col : partitionKeys) {
for (ColumnSpecification col : partitionKeys) {
if (first) {
first = false;
} else {
@@ -131,7 +86,7 @@ public class CreateTableBuilder extends AbstractTableBuilder<CreateTableBuilder>
StringBuilder clustering = null;
boolean clusteringFirst = true;
first = true;
for (ColumnBuilder col : primaryKeys) {
for (ColumnSpecification col : primaryKeys) {
if (first) {
first = false;
} else {
@@ -167,6 +122,8 @@ public class CreateTableBuilder extends AbstractTableBuilder<CreateTableBuilder>
// begin options
// begin option clause
Map<String, Object> options = spec().getOptions();
if (clustering != null || !options.isEmpty()) {
// option preamble

View File

@@ -1,15 +0,0 @@
package org.springframework.cassandra.core.cql.builder;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
public class DropColumn extends ColumnChange {
public DropColumn(String name) {
super(name);
}
@Override
public StringBuilder toCql(StringBuilder cql) {
return noNull(cql).append("DROP ").append(getNameAsIdentifier());
}
}

View File

@@ -0,0 +1,16 @@
package org.springframework.cassandra.core.cql.builder;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import org.springframework.cassandra.core.keyspace.DropColumnSpecification;
public class DropColumnCqlGenerator extends ColumnChangeCqlGenerator<DropColumnSpecification> {
public DropColumnCqlGenerator(DropColumnSpecification specification) {
super(specification);
}
public StringBuilder toCql(StringBuilder cql) {
return noNull(cql).append("DROP ").append(spec().getNameAsIdentifier());
}
}

View File

@@ -1,38 +0,0 @@
package org.springframework.cassandra.core.cql.builder;
import static org.springframework.cassandra.core.cql.CqlStringUtils.checkIdentifier;
import static org.springframework.cassandra.core.cql.CqlStringUtils.identifize;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
public class DropTableBuilder {
private String name;
private boolean ifExists;
public DropTableBuilder name(String name) {
checkIdentifier(name);
this.name = name;
return this;
}
public DropTableBuilder ifExists() {
return ifExists(true);
}
public DropTableBuilder ifExists(boolean ifExists) {
this.ifExists = ifExists;
return this;
}
public StringBuilder toCql(StringBuilder cql) {
return noNull(cql).append("DROP TABLE ").append(ifExists ? "IF EXISTS " : "").append(identifize(name));
}
public String toCql() {
return toCql(null).toString();
}
public String toString() {
return toCql();
}
}

View File

@@ -0,0 +1,29 @@
package org.springframework.cassandra.core.cql.builder;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import org.springframework.cassandra.core.keyspace.DropTableSpecification;
import org.springframework.util.Assert;
public class DropTableCqlGenerator {
protected DropTableSpecification specification;
public DropTableCqlGenerator(DropTableSpecification specification) {
setSpecification(specification);
}
protected void setSpecification(DropTableSpecification specification) {
Assert.notNull(specification);
this.specification = specification;
}
public StringBuilder toCql(StringBuilder cql) {
return noNull(cql).append("DROP TABLE ").append(specification.getIfExists() ? "IF EXISTS " : "")
.append(specification.getNameAsIdentifier());
}
public String toCql() {
return toCql(null).toString();
}
}

View File

@@ -1,10 +1,11 @@
package org.springframework.cassandra.core.cql.builder;
package org.springframework.cassandra.core.keyspace;
import static org.springframework.cassandra.core.cql.CqlStringUtils.checkIdentifier;
import static org.springframework.cassandra.core.cql.CqlStringUtils.escapeSingle;
import static org.springframework.cassandra.core.cql.CqlStringUtils.identifize;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import static org.springframework.cassandra.core.cql.CqlStringUtils.singleQuote;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -16,9 +17,7 @@ import org.springframework.cassandra.core.cql.CqlStringUtils;
* @author Matthew T. Adams
* @param T The subtype of AbstractTableBuilder.
*/
public abstract class AbstractTableBuilder<T extends AbstractTableBuilder<T>> {
protected abstract StringBuilder toCql(StringBuilder cql);
public abstract class AbstractTableSpecification<T extends AbstractTableSpecification<T>> {
private String name;
@@ -31,11 +30,15 @@ public abstract class AbstractTableBuilder<T extends AbstractTableBuilder<T>> {
*/
@SuppressWarnings("unchecked")
public T name(String name) {
CqlStringUtils.checkIdentifier(name);
this.name = name;
setName(name);
return (T) this;
}
public void setName(String name) {
checkIdentifier(name);
this.name = name;
}
public String getName() {
return name;
}
@@ -95,55 +98,11 @@ public abstract class AbstractTableBuilder<T extends AbstractTableBuilder<T>> {
value = singleQuote(value);
}
}
options().put(name, value);
options.put(name, value);
return (T) this;
}
protected Map<String, Object> options() {
return options == null ? options = new LinkedHashMap<String, Object>() : options;
}
protected StringBuilder optionValueMap(Map<Option, Object> valueMap, StringBuilder cql) {
cql = noNull(cql);
if (valueMap == null || valueMap.isEmpty()) {
return cql;
}
// else option value is a non-empty map
// append { 'name' : 'value', ... }
cql.append("{ ");
boolean mapFirst = true;
for (Map.Entry<Option, Object> entry : valueMap.entrySet()) {
if (mapFirst) {
mapFirst = false;
} else {
cql.append(", ");
}
Option option = entry.getKey();
cql.append(singleQuote(option.getName())); // entries in map keys are always quoted
cql.append(" : ");
Object entryValue = entry.getValue();
entryValue = entryValue == null ? "" : entryValue.toString();
if (option.escapesValue()) {
entryValue = escapeSingle(entryValue);
}
if (option.quotesValue()) {
entryValue = singleQuote(entryValue);
}
cql.append(entryValue);
}
cql.append(" }");
return cql;
}
public String toCql() {
return toCql(null).toString();
}
public String toString() {
return toCql(null).toString();
public Map<String, Object> getOptions() {
return Collections.unmodifiableMap(options);
}
}

View File

@@ -0,0 +1,10 @@
package org.springframework.cassandra.core.keyspace;
import com.datastax.driver.core.DataType;
public class AddColumnSpecification extends ColumnTypeChangeSpecification {
public AddColumnSpecification(String name, DataType type) {
super(name, type);
}
}

View File

@@ -1,12 +1,12 @@
package org.springframework.cassandra.core.cql.builder;
package org.springframework.cassandra.core.keyspace;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import com.datastax.driver.core.DataType;
public class AlterColumn extends ColumnTypeChange {
public class AlterColumnSpecification extends ColumnTypeChangeSpecification {
public AlterColumn(String name, DataType type) {
public AlterColumnSpecification(String name, DataType type) {
super(name, type);
}

View File

@@ -0,0 +1,31 @@
package org.springframework.cassandra.core.keyspace;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.datastax.driver.core.DataType;
public class AlterTableSpecification extends AbstractTableSpecification<AlterTableSpecification> {
private List<ColumnChangeSpecification> changes = new ArrayList<ColumnChangeSpecification>();
public AlterTableSpecification drop(String column) {
changes.add(new DropColumnSpecification(column));
return this;
}
public AlterTableSpecification add(String column, DataType type) {
changes.add(new AddColumnSpecification(column, type));
return this;
}
public AlterTableSpecification alter(String column, DataType type) {
changes.add(new AlterColumnSpecification(column, type));
return this;
}
public List<ColumnChangeSpecification> getChanges() {
return Collections.unmodifiableList(changes);
}
}

View File

@@ -1,22 +1,16 @@
package org.springframework.cassandra.core.cql.builder;
package org.springframework.cassandra.core.keyspace;
import static org.springframework.cassandra.core.cql.CqlStringUtils.checkIdentifier;
import static org.springframework.cassandra.core.cql.CqlStringUtils.identifize;
public abstract class ColumnChange {
public abstract StringBuilder toCql(StringBuilder cql);
public abstract class ColumnChangeSpecification {
private String name;
public ColumnChange(String name) {
public ColumnChangeSpecification(String name) {
setName(name);
}
public String toString() {
return toCql(null).toString();
}
private void setName(String name) {
checkIdentifier(name);
this.name = name;

View File

@@ -1,4 +1,4 @@
package org.springframework.cassandra.core.cql.builder;
package org.springframework.cassandra.core.keyspace;
import static org.springframework.cassandra.core.cql.CqlStringUtils.checkIdentifier;
import static org.springframework.cassandra.core.cql.CqlStringUtils.identifize;
@@ -22,7 +22,7 @@ import com.datastax.driver.core.DataType;
*
* @author Matthew T. Adams
*/
public class ColumnBuilder {
public class ColumnSpecification {
/**
* Default ordering of primary key fields; value is {@link Ordering#ASCENDING}.
@@ -39,7 +39,7 @@ public class ColumnBuilder {
*
* @return this
*/
public ColumnBuilder name(String name) {
public ColumnSpecification name(String name) {
checkIdentifier(name);
this.name = name;
return this;
@@ -50,7 +50,7 @@ public class ColumnBuilder {
*
* @return this
*/
public ColumnBuilder type(DataType type) {
public ColumnSpecification type(DataType type) {
this.type = type;
return this;
}
@@ -61,7 +61,7 @@ public class ColumnBuilder {
*
* @return this
*/
public ColumnBuilder partition() {
public ColumnSpecification partition() {
return partition(true);
}
@@ -72,7 +72,7 @@ public class ColumnBuilder {
*
* @return this
*/
public ColumnBuilder partition(boolean partition) {
public ColumnSpecification partition(boolean partition) {
this.keyType = partition ? PARTITION : null;
this.ordering = null;
return this;
@@ -84,7 +84,7 @@ public class ColumnBuilder {
*
* @return this
*/
public ColumnBuilder primary() {
public ColumnSpecification primary() {
return primary(DFAULT_ORDERING);
}
@@ -94,7 +94,7 @@ public class ColumnBuilder {
*
* @return this
*/
public ColumnBuilder primary(Ordering order) {
public ColumnSpecification primary(Ordering order) {
return primary(order, true);
}
@@ -105,7 +105,7 @@ public class ColumnBuilder {
*
* @return this
*/
public ColumnBuilder primary(Ordering order, boolean primary) {
public ColumnSpecification primary(Ordering order, boolean primary) {
this.keyType = primary ? PRIMARY : null;
this.ordering = primary ? order : null;
return this;
@@ -116,7 +116,7 @@ public class ColumnBuilder {
*
* @return this
*/
/* package */ColumnBuilder keyType(KeyType keyType) {
/* package */ColumnSpecification keyType(KeyType keyType) {
this.keyType = keyType;
return this;
}
@@ -126,7 +126,7 @@ public class ColumnBuilder {
*
* @return this
*/
/* package */ColumnBuilder ordering(Ordering ordering) {
/* package */ColumnSpecification ordering(Ordering ordering) {
this.ordering = ordering;
return this;
}

View File

@@ -1,14 +1,14 @@
package org.springframework.cassandra.core.cql.builder;
package org.springframework.cassandra.core.keyspace;
import org.springframework.util.Assert;
import com.datastax.driver.core.DataType;
public abstract class ColumnTypeChange extends ColumnChange {
public abstract class ColumnTypeChangeSpecification extends ColumnChangeSpecification {
private DataType type;
public ColumnTypeChange(String name, DataType type) {
public ColumnTypeChangeSpecification(String name, DataType type) {
super(name);
setType(type);
}

View File

@@ -1,46 +1,46 @@
package org.springframework.cassandra.core.cql.builder;
package org.springframework.cassandra.core.keyspace;
public class CqlBuilder {
/**
* Entry point into the {@link CqlBuilder}'s fluent API to create a table. Convenient if imported statically.
*/
public static CreateTableBuilder createTable() {
return new CreateTableBuilder();
public static CreateTableSpecification createTable() {
return new CreateTableSpecification();
}
/**
* Entry point into the {@link CqlBuilder}'s fluent API to create a table. Convenient if imported statically.
*/
public static CreateTableBuilder createTable(String name) {
return new CreateTableBuilder().name(name);
public static CreateTableSpecification createTable(String name) {
return new CreateTableSpecification().name(name);
}
/**
* Entry point into the {@link CqlBuilder}'s fluent API to alter a table. Convenient if imported statically.
*/
public static AlterTableBuilder alterTable() {
return new AlterTableBuilder();
public static AlterTableSpecification alterTable() {
return new AlterTableSpecification();
}
/**
* Entry point into the {@link CqlBuilder}'s fluent API to alter a table. Convenient if imported statically.
*/
public static AlterTableBuilder alterTable(String name) {
return new AlterTableBuilder().name(name);
public static AlterTableSpecification alterTable(String name) {
return new AlterTableSpecification().name(name);
}
/**
* Entry point into the {@link CqlBuilder}'s fluent API to drop a table. Convenient if imported statically.
*/
public static DropTableBuilder dropTable() {
return new DropTableBuilder();
public static DropTableSpecification dropTable() {
return new DropTableSpecification();
}
/**
* Entry point into the {@link CqlBuilder}'s fluent API to drop a table. Convenient if imported statically.
*/
public static DropTableBuilder dropTable(String name) {
return new DropTableBuilder().name(name);
public static DropTableSpecification dropTable(String name) {
return new DropTableSpecification().name(name);
}
}

View File

@@ -0,0 +1,77 @@
package org.springframework.cassandra.core.keyspace;
import static org.springframework.data.cassandra.mapping.KeyType.PARTITION;
import static org.springframework.data.cassandra.mapping.KeyType.PRIMARY;
import static org.springframework.data.cassandra.mapping.Ordering.ASCENDING;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.springframework.data.cassandra.mapping.KeyType;
import org.springframework.data.cassandra.mapping.Ordering;
import com.datastax.driver.core.DataType;
/**
* Builder class to construct CQL for a <code>CREATE TABLE</code> statement. Not threadsafe.
*
* @author Matthew T. Adams
*/
public class CreateTableSpecification extends AbstractTableSpecification<CreateTableSpecification> {
private boolean ifNotExists = false;
private List<ColumnSpecification> columns = new ArrayList<ColumnSpecification>();
/**
* Causes the inclusion of an <code>IF NOT EXISTS</code> clause.
*
* @return this
*/
public CreateTableSpecification ifNotExists() {
return ifNotExists(true);
}
/**
* Toggles the inclusion of an <code>IF NOT EXISTS</code> clause.
*
* @return this
*/
public CreateTableSpecification ifNotExists(boolean ifNotExists) {
this.ifNotExists = ifNotExists;
return this;
}
public CreateTableSpecification column(String name, DataType type) {
return column(name, type, null, null);
}
public CreateTableSpecification partitionKeyColumn(String name, DataType type) {
return column(name, type, PARTITION, null);
}
public CreateTableSpecification primaryKeyColumn(String name, DataType type) {
return primaryKeyColumn(name, type, ASCENDING);
}
public CreateTableSpecification primaryKeyColumn(String name, DataType type, Ordering order) {
return column(name, type, PRIMARY, order);
}
protected CreateTableSpecification column(String name, DataType type, KeyType keyType, Ordering ordering) {
columns().add(new ColumnSpecification().name(name).type(type).keyType(keyType).ordering(ordering));
return this;
}
protected List<ColumnSpecification> columns() {
return columns == null ? columns = new ArrayList<ColumnSpecification>() : columns;
}
public boolean getIfNotExists() {
return ifNotExists;
}
public List<ColumnSpecification> getColumns() {
return Collections.unmodifiableList(columns);
}
}

View File

@@ -1,4 +1,4 @@
package org.springframework.cassandra.core.cql.builder;
package org.springframework.cassandra.core.keyspace;
import static org.springframework.cassandra.core.cql.CqlStringUtils.escapeSingle;
import static org.springframework.cassandra.core.cql.CqlStringUtils.singleQuote;

View File

@@ -0,0 +1,8 @@
package org.springframework.cassandra.core.keyspace;
public class DropColumnSpecification extends ColumnChangeSpecification {
public DropColumnSpecification(String name) {
super(name);
}
}

View File

@@ -0,0 +1,33 @@
package org.springframework.cassandra.core.keyspace;
import static org.springframework.cassandra.core.cql.CqlStringUtils.checkIdentifier;
import static org.springframework.cassandra.core.cql.CqlStringUtils.identifize;
public class DropTableSpecification {
private String name;
private boolean ifExists;
public DropTableSpecification name(String name) {
checkIdentifier(name);
this.name = name;
return this;
}
public DropTableSpecification ifExists() {
return ifExists(true);
}
public DropTableSpecification ifExists(boolean ifExists) {
this.ifExists = ifExists;
return this;
}
public boolean getIfExists() {
return ifExists;
}
public String getNameAsIdentifier() {
return identifize(name);
}
}

View File

@@ -1,4 +1,4 @@
package org.springframework.cassandra.core.cql.builder;
package org.springframework.cassandra.core.keyspace;
import java.util.Collection;
import java.util.LinkedHashMap;

View File

@@ -1,4 +1,4 @@
package org.springframework.cassandra.core.cql.builder;
package org.springframework.cassandra.core.keyspace;
/**
* Interface to represent option types.

View File

@@ -1,10 +1,10 @@
package org.springframework.cassandra.core.cql.builder;
package org.springframework.cassandra.core.keyspace;
import java.util.Map;
/**
* Enumeration that represents all known table options. If a table option is not listed here, but is supported by
* Cassandra, use the method {@link CreateTableBuilder#with(String, Object, boolean, boolean)} to write the raw value.
* Cassandra, use the method {@link CreateTableSpecification#with(String, Object, boolean, boolean)} to write the raw value.
*
* Implements {@link Option} via delegation, since {@link Enum}s can't extend anything.
*

View File

@@ -1,8 +1,10 @@
package org.springframework.cassandra.cql.builder;
import static org.springframework.cassandra.core.cql.builder.CqlBuilder.alterTable;
import static org.springframework.cassandra.core.keyspace.CqlBuilder.alterTable;
import org.junit.Test;
import org.springframework.cassandra.core.cql.builder.AlterTableCqlGenerator;
import org.springframework.cassandra.core.keyspace.AlterTableSpecification;
import com.datastax.driver.core.DataType;
@@ -17,8 +19,9 @@ public class AlterTableBuilderTest {
String alteredName = "altered_column";
String droppedName = "dropped";
String cql = alterTable().name(name).add(addedName, addedType).alter(alteredName, alteredType).drop(droppedName)
.toCql();
System.out.println(cql);
AlterTableSpecification alter = alterTable().name(name).add(addedName, addedType).alter(alteredName, alteredType)
.drop(droppedName);
AlterTableCqlGenerator generator = new AlterTableCqlGenerator(alter);
System.out.println(generator.toCql());
}
}

View File

@@ -1,17 +1,18 @@
package org.springframework.cassandra.cql.builder;
import static junit.framework.Assert.assertEquals;
import static org.springframework.cassandra.core.cql.builder.CqlBuilder.createTable;
import static org.springframework.cassandra.core.cql.builder.MapBuilder.map;
import static org.springframework.cassandra.core.cql.builder.TableOption.BLOOM_FILTER_FP_CHANCE;
import static org.springframework.cassandra.core.cql.builder.TableOption.CACHING;
import static org.springframework.cassandra.core.cql.builder.TableOption.COMMENT;
import static org.springframework.cassandra.core.cql.builder.TableOption.COMPACTION;
import static org.springframework.cassandra.core.cql.builder.TableOption.CompactionOption.TOMBSTONE_THRESHOLD;
import static org.springframework.cassandra.core.keyspace.CqlBuilder.createTable;
import static org.springframework.cassandra.core.keyspace.MapBuilder.map;
import static org.springframework.cassandra.core.keyspace.TableOption.BLOOM_FILTER_FP_CHANCE;
import static org.springframework.cassandra.core.keyspace.TableOption.CACHING;
import static org.springframework.cassandra.core.keyspace.TableOption.COMMENT;
import static org.springframework.cassandra.core.keyspace.TableOption.COMPACTION;
import static org.springframework.cassandra.core.keyspace.TableOption.CompactionOption.TOMBSTONE_THRESHOLD;
import org.junit.Test;
import org.springframework.cassandra.core.cql.builder.CreateTableBuilder;
import org.springframework.cassandra.core.cql.builder.TableOption.CachingOption;
import org.springframework.cassandra.core.cql.builder.CreateTableCqlGenerator;
import org.springframework.cassandra.core.keyspace.CreateTableSpecification;
import org.springframework.cassandra.core.keyspace.TableOption.CachingOption;
import com.datastax.driver.core.DataType;
@@ -32,12 +33,13 @@ public class CreateTableBuilderTest {
Object bloom = "0.00075";
Object caching = CachingOption.KEYS_ONLY;
CreateTableBuilder builder = createTable().ifNotExists().name(name).partitionKeyColumn(partKey0, type0)
CreateTableSpecification create = createTable().ifNotExists().name(name).partitionKeyColumn(partKey0, type0)
.partitionKeyColumn(partition1, type0).primaryKeyColumn(primary0, type0).column(column1, type1)
.column(column2, type2).with(COMMENT, comment).with(BLOOM_FILTER_FP_CHANCE, bloom)
.with(COMPACTION, map().entry(TOMBSTONE_THRESHOLD, "0.15")).with(CACHING, caching);
String cql = builder.toCql();
CreateTableCqlGenerator generator = new CreateTableCqlGenerator(create);
String cql = generator.toCql();
assertEquals(
"CREATE TABLE IF NOT EXISTS \"my\"\"table\" (partitionKey0 text, partitionKey1 text, primary0 text, column1 text, column2 bigint, PRIMARY KEY ((partitionKey0, partitionKey1), primary0) WITH CLUSTERING ORDER BY (primary0 ASC) AND comment = 'this is a comment' AND bloom_filter_fp_chance = 0.00075 AND compaction = { 'tombstone_threshold' : 0.15 } AND caching = keys_only;",
cql);

View File

@@ -1,15 +1,18 @@
package org.springframework.cassandra.cql.builder;
import static org.springframework.cassandra.core.cql.builder.CqlBuilder.dropTable;
import static org.springframework.cassandra.core.keyspace.CqlBuilder.dropTable;
import org.junit.Test;
import org.springframework.cassandra.core.cql.builder.DropTableCqlGenerator;
import org.springframework.cassandra.core.keyspace.DropTableSpecification;
public class DropTableBuilderTest {
@Test
public void testDropTableBuilder() throws Exception {
String cql = dropTable().name("mytable").ifExists().toCql();
DropTableSpecification drop = dropTable().name("mytable").ifExists();
System.out.println(cql);
DropTableCqlGenerator generator = new DropTableCqlGenerator(drop);
System.out.println(generator.toCql());
}
}

View File

@@ -7,8 +7,8 @@ import static junit.framework.Assert.assertTrue;
import java.lang.annotation.RetentionPolicy;
import org.junit.Test;
import org.springframework.cassandra.core.cql.builder.DefaultOption;
import org.springframework.cassandra.core.cql.builder.Option;
import org.springframework.cassandra.core.keyspace.DefaultOption;
import org.springframework.cassandra.core.keyspace.Option;
public class OptionTest {