Completed more of the CQL generators.

This commit is contained in:
john-mcpeek
2013-12-16 07:49:13 -05:00
parent 3d51fc150f
commit 8cfd144149
11 changed files with 123 additions and 345 deletions

View File

@@ -428,6 +428,7 @@ public class CassandraTemplate extends CassandraAccessor implements CassandraOpe
* @see org.springframework.cassandra.core.CassandraOperations#processList(com.datastax.driver.core.ResultSet, java.lang.Class)
*/
@Override
@SuppressWarnings( "unchecked" )
public <T> List<T> processList(ResultSet resultSet, Class<T> elementType) throws DataAccessException {
List<Row> rows = resultSet.all();
List<T> list = new ArrayList<T>(rows.size());

View File

@@ -19,11 +19,7 @@ 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.AlterKeyspaceSpecification;
import org.springframework.cassandra.core.keyspace.ColumnChangeSpecification;
import org.springframework.cassandra.core.keyspace.DropColumnSpecification;
import org.springframework.cassandra.core.keyspace.Option;
/**
@@ -41,8 +37,7 @@ public class AlterKeyspaceCqlGenerator extends KeyspaceOptionsCqlGenerator<Alter
cql = noNull(cql);
preambleCql(cql);
// changesCql(cql);
// optionsCql(cql);
optionsCql(cql);
cql.append(";");
@@ -53,69 +48,51 @@ public class AlterKeyspaceCqlGenerator extends KeyspaceOptionsCqlGenerator<Alter
return noNull(cql).append("ALTER KEYSPACE ").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 IllegalArgumentException("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;
// }
@SuppressWarnings( "unchecked" )
protected StringBuilder optionsCql(StringBuilder cql) {
cql = noNull(cql);
// begin options clause
Map<String, Object> options = spec().getOptions();
if (!options.isEmpty()) {
// option preamble
boolean first = true;
cql.append(" WITH ");
// end option preamble
if (!options.isEmpty()) {
for (String name : options.keySet()) {
// append AND if we're not on first option
if (first) {
first = false;
} else {
cql.append(" AND ");
}
// append <name> = <value>
cql.append(name);
Object value = options.get(name);
if (value == null) { // then assume string-only, valueless option like "COMPACT STORAGE"
continue;
}
cql.append(" = ");
if (value instanceof Map) {
optionValueMap((Map<Option, Object>) value, cql);
continue; // end non-empty value map
}
// else just use value as string
cql.append(value.toString());
}
}
}
// end options
return cql;
}
}

View File

@@ -15,15 +15,10 @@
*/
package org.springframework.cassandra.core.cql.generator;
import static org.springframework.cassandra.core.PrimaryKeyType.CLUSTERED;
import static org.springframework.cassandra.core.PrimaryKeyType.PARTITIONED;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.springframework.cassandra.core.keyspace.ColumnSpecification;
import org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification;
import org.springframework.cassandra.core.keyspace.Option;
@@ -56,146 +51,53 @@ public class CreateKeyspaceCqlGenerator extends KeyspaceCqlGenerator<CreateKeysp
.append(spec().getNameAsIdentifier());
}
protected void optionsCql(StringBuilder cql) {
@SuppressWarnings( "unchecked" )
protected StringBuilder optionsCql(StringBuilder cql) {
cql = noNull(cql);
cql.append("WITH REPLICATION =");
cql.append( " " );
// begin options clause
Map<String, Object> options = spec().getOptions();
if (!options.isEmpty()) {
// option preamble
boolean first = true;
cql.append(" WITH ");
// end option preamble
if (!options.isEmpty()) {
for (String name : options.keySet()) {
// append AND if we're not on first option
if (first) {
first = false;
} else {
cql.append(" AND ");
}
// append <name> = <value>
cql.append(name);
Object value = options.get(name);
if (value == null) { // then assume string-only, valueless option like "COMPACT STORAGE"
continue;
}
cql.append(" = ");
if (value instanceof Map) {
optionValueMap((Map<Option, Object>) value, cql);
continue; // end non-empty value map
}
// else just use value as string
cql.append(value.toString());
}
}
}
// end options
return cql;
}
// @SuppressWarnings("unchecked")
// protected StringBuilder columnsAndOptionsCql(StringBuilder cql) {
//
// cql = noNull(cql);
//
// // begin columns
// cql.append(" (");
//
// List<ColumnSpecification> partitionKeys = new ArrayList<ColumnSpecification>();
// List<ColumnSpecification> clusterKeys = new ArrayList<ColumnSpecification>();
// for (ColumnSpecification col : spec().getColumns()) {
// col.toCql(cql).append(", ");
//
// if (col.getKeyType() == PARTITIONED) {
// partitionKeys.add(col);
// } else if (col.getKeyType() == CLUSTERED) {
// clusterKeys.add(col);
// }
// }
//
// // begin primary key clause
// cql.append("PRIMARY KEY (");
//
// if (partitionKeys.size() > 1) {
// // begin partition key clause
// cql.append("(");
// }
//
// appendColumnNames(cql, partitionKeys);
//
// if (partitionKeys.size() > 1) {
// cql.append(")");
// // end partition key clause
// }
//
// if (!clusterKeys.isEmpty()) {
// cql.append(", ");
// }
//
// appendColumnNames(cql, clusterKeys);
//
// cql.append(")");
// // end primary key clause
//
// cql.append(")");
// // end columns
//
// StringBuilder ordering = createOrderingClause(clusterKeys);
// // begin options
// // begin option clause
// Map<String, Object> options = spec().getOptions();
//
// if (ordering != null || !options.isEmpty()) {
//
// // option preamble
// boolean first = true;
// cql.append(" WITH ");
// // end option preamble
//
// if (ordering != null) {
// cql.append(ordering);
// first = false;
// }
// if (!options.isEmpty()) {
// for (String name : options.keySet()) {
// // append AND if we're not on first option
// if (first) {
// first = false;
// } else {
// cql.append(" AND ");
// }
//
// // append <name> = <value>
// cql.append(name);
//
// Object value = options.get(name);
// if (value == null) { // then assume string-only, valueless option like "COMPACT STORAGE"
// continue;
// }
//
// cql.append(" = ");
//
// if (value instanceof Map) {
// optionValueMap((Map<Option, Object>) value, cql);
// continue; // end non-empty value map
// }
//
// // else just use value as string
// cql.append(value.toString());
// }
// }
// }
// // end options
//
// return cql;
// }
// private static StringBuilder createOrderingClause(List<ColumnSpecification> columns) {
// StringBuilder ordering = null;
// boolean first = true;
// for (ColumnSpecification col : columns) {
//
// if (col.getOrdering() != null) { // then ordering specified
// if (ordering == null) { // then initialize ordering clause
// ordering = new StringBuilder().append("CLUSTERING ORDER BY (");
// }
// if (first) {
// first = false;
// } else {
// ordering.append(", ");
// }
// ordering.append(col.getName()).append(" ").append(col.getOrdering().cql());
// }
// }
// if (ordering != null) { // then end ordering option
// ordering.append(")");
// }
// return ordering;
// }
//
// private static void appendColumnNames(StringBuilder str, List<ColumnSpecification> columns) {
//
// boolean first = true;
// for (ColumnSpecification col : columns) {
// if (first) {
// first = false;
// } else {
// str.append(", ");
// }
// str.append(col.getName());
//
// }
//
// }
}

View File

@@ -15,14 +15,7 @@
*/
package org.springframework.cassandra.core.cql.generator;
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.KeyspaceSpecification;
import org.springframework.cassandra.core.keyspace.Option;
/**
* Base class that contains behavior common to CQL generation for table operations.
@@ -41,40 +34,4 @@ public abstract class KeyspaceCqlGenerator<T extends KeyspaceSpecification<T>> e
protected T spec() {
return (T) 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;
}
}

View File

@@ -15,13 +15,6 @@
*/
package org.springframework.cassandra.core.cql.generator;
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.Option;
import org.springframework.cassandra.core.keyspace.TableSpecification;
/**
@@ -41,40 +34,4 @@ public abstract class TableCqlGenerator<T extends TableSpecification<T>> extends
protected T spec() {
return (T) 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;
}
}

View File

@@ -88,7 +88,6 @@ public class CreateIndexSpecification extends IndexNameSpecification<CreateIndex
*
* @return this
*/
@SuppressWarnings("unchecked")
public CreateIndexSpecification tableName(String tableName) {
checkIdentifier(tableName);
this.tableName = tableName;

View File

@@ -27,4 +27,12 @@ public class CreateKeyspaceSpecification extends KeyspaceSpecification<CreateKey
return ifNotExists;
}
/**
* Entry point into the {@link CreateTableSpecification}'s fluent API to create a table. Convenient if imported
* statically.
*/
public static CreateKeyspaceSpecification createKeyspace() {
return new CreateKeyspaceSpecification();
}
}

View File

@@ -37,11 +37,7 @@ public interface KeyspaceDescriptor {
/**
* Returns the replication strategy.
*/
String getReplicationStrategy();
Long getReplicationFactor();
Map<String, Long> getDataCenters();
Boolean getDurableWrites();
/**
* Returns an unmodifiable {@link Map} of keyspace options.

View File

@@ -1,9 +1,11 @@
package org.springframework.cassandra.core.keyspace;
import java.util.Map;
public enum KeyspaceOption implements Option {
REPLICATION_STRATEGY("class", String.class, true, true, true),
REPLICATION("replication", Map.class, true, false, false),
REPLICATION_FACTOR("replication_factor", Long.class, false, false, false);
DURABLE_WRITES("durable_writes", Boolean.class, false, false, false);
private Option delegate;

View File

@@ -15,9 +15,6 @@
*/
package org.springframework.cassandra.core.keyspace;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
@@ -28,48 +25,27 @@ import java.util.Map;
*/
public class KeyspaceSpecification<T> extends KeyspaceOptionsSpecification<KeyspaceSpecification<T>> implements KeyspaceDescriptor {
private String replicationStrategy;
private Long replicationFactor;
private Map<String, Long> dataCenters = new HashMap<String, Long>();
@Override
public String getReplicationStrategy() {
return replicationStrategy;
}
private Boolean durableWrites;
/**
* @param replicationStrategy the replicationStrategy to set
* @param durableWrites the durableWrites to set
*/
public void setReplicationStrategy(String replicationStrategy) {
this.replicationStrategy = replicationStrategy;
}
/**
* @return the replicationFactor
*/
@Override
public Long getReplicationFactor() {
return replicationFactor;
}
/**
* @param replicationFactor the replicationFactor to set
*/
public void setReplicationFactor(Long replicationFactor) {
this.replicationFactor = replicationFactor;
@SuppressWarnings( "unchecked" )
public T durableWrites(Boolean durableWrites) {
this.durableWrites = durableWrites;
return (T) this;
}
@Override
public Map<String, Long> getDataCenters() {
return Collections.unmodifiableMap( dataCenters );
public Boolean getDurableWrites() {
return durableWrites;
}
/**
* @param dataCenters the dataCenters to set
* @param durableWrites the durableWrites to set
*/
public void setDataCenters(Map<String, Long> dataCenters) {
this.dataCenters = dataCenters;
public void setDurableWrites(Boolean durableWrites) {
this.durableWrites = durableWrites;
}
}

View File

@@ -140,6 +140,7 @@ public class CassandraOperationsTest extends AbstractEmbeddedCassandraIntegratio
}
@Test
@SuppressWarnings( "unchecked" )
public void ingestionTestListOfList() {
String cql = "insert into book (isbn, title, author, pages) values (?, ?, ?, ?)";
@@ -507,6 +508,7 @@ public class CassandraOperationsTest extends AbstractEmbeddedCassandraIntegratio
// Insert our 3 test books.
ingestionTestObjectArray();
@SuppressWarnings( "unused" )
Book book = cassandraTemplate.queryForObject("select * from book where isbn in ('1234','2345','3456')",
new RowMapper<Book>() {
@Override
@@ -561,6 +563,7 @@ public class CassandraOperationsTest extends AbstractEmbeddedCassandraIntegratio
@Test(expected = ClassCastException.class)
public void queryForObjectTestCqlStringRequiredTypeInvalid() {
@SuppressWarnings( "unused" )
Float title = cassandraTemplate.queryForObject("select title from book where isbn in ('" + ISBN_NINES + "')",
Float.class);