now have create/alter/drop table builders

This commit is contained in:
Matthew Adams
2013-11-19 16:03:27 -06:00
parent 08c89c37b0
commit 8fcdadbc88
17 changed files with 563 additions and 159 deletions

View File

@@ -9,29 +9,28 @@ public class CqlStringUtils {
protected static final String DOUBLE_QUOTE = "\"";
protected static final String DOUBLE_DOUBLE_QUOTE = "\"\"";
/**
* Helper {@link StringBuilder} factory method. If given a non-<code>null</code> argument, returns that, else returns
* a new {@link StringBuilder}. Intended to be imported statically by other classes in the builder's fluent API
* implementation.
*
* @param sb
* @return The given {@link StringBuilder} if not null, else a new one.
*
* @author Matthew T. Adams
*/
public static StringBuilder ensureNotNull(StringBuilder sb) {
public static StringBuilder noNull(StringBuilder sb) {
return sb == null ? new StringBuilder() : sb;
}
public static final String IDENTIFIER_REGEX = "[a-zA-Z0-9_]*";
public static final Pattern IDENTIFIER_PATTERN = Pattern.compile(IDENTIFIER_REGEX);
public static final String UNESCAPED_DOUBLE_QUOTE_REGEX = "TODO";
public static final Pattern UNESCAPED_DOUBLE_QUOTE_PATTERN = Pattern.compile(UNESCAPED_DOUBLE_QUOTE_REGEX);
public static boolean isIdentifier(CharSequence chars) {
return IDENTIFIER_PATTERN.matcher(chars).matches();
public static final String UNQUOTED_IDENTIFIER_REGEX = "[a-zA-Z_][a-zA-Z0-9_]*";
public static final Pattern UNQUOTED_IDENTIFIER_PATTERN = Pattern.compile(UNQUOTED_IDENTIFIER_REGEX);
public static boolean isUnquotedIdentifier(CharSequence chars) {
return UNQUOTED_IDENTIFIER_PATTERN.matcher(chars).matches();
}
public static final String QUOTED_IDENTIFIER_REGEX = "([a-zA-Z0-9_]|'{2}+|\"{2}+)*";
public static final Pattern QUOTED_IDENTIFIER_PATTERN = Pattern.compile(IDENTIFIER_REGEX);
public static void checkUnquotedIdentifier(CharSequence chars) {
if (!CqlStringUtils.isUnquotedIdentifier(chars)) {
throw new IllegalArgumentException("[" + chars + "] is not a valid CQL identifier");
}
}
public static final String QUOTED_IDENTIFIER_REGEX = "[a-zA-Z_]([a-zA-Z0-9_]|\"{2}+)*";
public static final Pattern QUOTED_IDENTIFIER_PATTERN = Pattern.compile(QUOTED_IDENTIFIER_REGEX);
public static boolean isQuotedIdentifier(CharSequence chars) {
return QUOTED_IDENTIFIER_PATTERN.matcher(chars).matches();
@@ -43,19 +42,45 @@ public class CqlStringUtils {
}
}
/**
* Trims then escapes the given {@link CharSequence}. Given <code>null</code>, returns <code>null</code>.
*/
public static String scrub(Object thing) {
return thing == null ? (String) null : escape(thing.toString().trim());
public static boolean isIdentifier(CharSequence chars) {
return isUnquotedIdentifier(chars) || isQuotedIdentifier(chars);
}
public static void checkIdentifier(CharSequence chars) {
if (!CqlStringUtils.isIdentifier(chars)) {
throw new IllegalArgumentException("[" + chars + "] is not a valid CQL quoted or unquoted identifier");
}
}
/**
* Doubles single quote characters and doubles double quote characters (' -&gt; '' and " -&gt; ""). Given
* <code>null</code>, returns <code>null</code>.
* Renders the given string as a legal Cassandra identifier.
* <ul>
* <li>If the given identifier is a legal unquoted identifier, it is returned unchanged.</li>
* <li>If the given identifier is a legal quoted identifier, it is returned encased in double quotes.</li>
* <li>If the given identifier is illegal, an {@link IllegalArgumentException} is thrown.</li>
* </ul>
*/
public static String escape(Object thing) {
return escapeDouble(escapeSingle(thing));
public static String identifize(String candidate) {
checkIdentifier(candidate);
if (isUnquotedIdentifier(candidate)) {
return candidate;
}
// else it must be quoted
return doubleQuote(candidate);
}
/**
* Renders the given string as a legal Cassandra string column or table option value, by escaping single quotes and
* encasing the result in single quotes. Given <code>null</code>, returns <code>null</code>.
*/
public static String valuize(String candidate) {
if (candidate == null) {
return null;
}
return singleQuote(escapeSingle(candidate));
}
/**
@@ -69,7 +94,7 @@ public class CqlStringUtils {
* Doubles double quote characters (" -&gt; ""). Given <code>null</code>, returns <code>null</code>.
*/
public static String escapeDouble(Object things) {
return things == null ? (String) null : things.toString().replace(DOUBLE_QUOTE, DOUBLE_SINGLE_QUOTE);
return things == null ? (String) null : things.toString().replace(DOUBLE_QUOTE, DOUBLE_DOUBLE_QUOTE);
}
/**

View File

@@ -0,0 +1,149 @@
package org.springframework.data.cassandra.cql.builder;
import static org.springframework.data.cassandra.cql.CqlStringUtils.noNull;
import static org.springframework.data.cassandra.cql.CqlStringUtils.escapeSingle;
import static org.springframework.data.cassandra.cql.CqlStringUtils.identifize;
import static org.springframework.data.cassandra.cql.CqlStringUtils.singleQuote;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.data.cassandra.cql.CqlStringUtils;
/**
* Base class that contains behavior common to table operations.
*
* @author Matthew T. Adams
* @param T The subtype of AbstractTableBuilder.
*/
public abstract class AbstractTableBuilder<T extends AbstractTableBuilder<T>> {
protected abstract StringBuilder toCql(StringBuilder cql);
private String name;
protected Map<String, Object> options = new LinkedHashMap<String, Object>();
/**
* Sets the table name.
*
* @return this
*/
@SuppressWarnings("unchecked")
public T name(String name) {
CqlStringUtils.checkIdentifier(name);
this.name = name;
return (T) this;
}
public String getName() {
return name;
}
public String getNameAsIdentifier() {
return identifize(name);
}
/**
* Convenience method that calls <code>with(option, null)</code>.
*
* @return this
*/
public T with(TableOption option) {
return with(option, null);
}
/**
* Sets the given table option. This is a convenience method that calls
* {@link #with(String, Object, boolean, boolean)} appropriately from the given {@link TableOption} and value for that
* option.
*
* @param option The option to set.
* @param value The value of the option. Must be type-compatible with the {@link TableOption}.
* @return this
* @see #with(String, Object, boolean, boolean)
*/
public T with(TableOption option, Object value) {
option.checkValue(value);
return (T) with(option.getName(), value, option.escapesValue(), option.quotesValue());
}
/**
* Adds the given option by name to this table's options.
* <p/>
* Options that have <code>null</code> values are considered single string options where the name of the option is the
* string to be used. Otherwise, the result of {@link Object#toString()} is considered to be the value of the option
* with the given name. The value, after conversion to string, may have embedded single quotes escaped according to
* parameter <code>escape</code> and may be single-quoted according to parameter <code>quote</code>.
*
* @param name The name of the option
* @param value The value of the option. If <code>null</code>, the value is ignored and the option is considered to be
* composed of only the name, otherwise the value's {@link Object#toString()} value is used.
* @param escape Whether to escape the value via {@link CqlStringUtils#escapeSingle(Object)}. Ignored if given value
* is an instance of a {@link Map}.
* @param quote Whether to quote the value via {@link CqlStringUtils#singleQuote(Object)}. Ignored if given value is
* an instance of a {@link Map}.
* @return this
*/
@SuppressWarnings("unchecked")
public T with(String name, Object value, boolean escape, boolean quote) {
if (!(value instanceof Map)) {
if (escape) {
value = escapeSingle(value);
}
if (quote) {
value = singleQuote(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();
}
}

View File

@@ -0,0 +1,17 @@
package org.springframework.data.cassandra.cql.builder;
import static org.springframework.data.cassandra.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,17 @@
package org.springframework.data.cassandra.cql.builder;
import static org.springframework.data.cassandra.cql.CqlStringUtils.noNull;
import com.datastax.driver.core.DataType;
public class AlterColumn extends ColumnTypeChange {
public AlterColumn(String name, DataType type) {
super(name, type);
}
public StringBuilder toCql(StringBuilder cql) {
return noNull(cql).append("ALTER ").append(getNameAsIdentifier()).append(" TYPE ")
.append(getType().getName());
}
}

View File

@@ -0,0 +1,103 @@
package org.springframework.data.cassandra.cql.builder;
import static org.springframework.data.cassandra.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

@@ -1,12 +1,12 @@
package org.springframework.data.cassandra.cql.builder;
import static org.springframework.data.cassandra.cql.CqlStringUtils.checkQuotedIdentifier;
import static org.springframework.data.cassandra.cql.CqlStringUtils.ensureNotNull;
import static org.springframework.data.cassandra.cql.CqlStringUtils.checkIdentifier;
import static org.springframework.data.cassandra.cql.CqlStringUtils.identifize;
import static org.springframework.data.cassandra.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 org.springframework.data.cassandra.cql.CqlStringUtils;
import org.springframework.data.cassandra.mapping.KeyType;
import org.springframework.data.cassandra.mapping.Ordering;
@@ -35,15 +35,12 @@ public class ColumnBuilder {
private Ordering ordering;
/**
* Sets the column's name. Quotes are not escaped.
*
* @see CqlStringUtils#escape(CharSequence)
* @see CqlStringUtils#scrub(CharSequence)
* Sets the column's name.
*
* @return this
*/
public ColumnBuilder name(String name) {
checkQuotedIdentifier(name);
checkIdentifier(name);
this.name = name;
return this;
}
@@ -138,6 +135,10 @@ public class ColumnBuilder {
return name;
}
public String getNameAsIdentifier() {
return identifize(name);
}
public DataType getType() {
return type;
}
@@ -155,7 +156,7 @@ public class ColumnBuilder {
}
public StringBuilder toCql(StringBuilder cql) {
return (cql = ensureNotNull(cql)).append(name).append(" ").append(type);
return (cql = noNull(cql)).append(name).append(" ").append(type);
}
@Override

View File

@@ -0,0 +1,32 @@
package org.springframework.data.cassandra.cql.builder;
import static org.springframework.data.cassandra.cql.CqlStringUtils.checkIdentifier;
import static org.springframework.data.cassandra.cql.CqlStringUtils.identifize;
public abstract class ColumnChange {
public abstract StringBuilder toCql(StringBuilder cql);
private String name;
public ColumnChange(String name) {
setName(name);
}
public String toString() {
return toCql(null).toString();
}
private void setName(String name) {
checkIdentifier(name);
this.name = name;
}
public String getName() {
return name;
}
public String getNameAsIdentifier() {
return identifize(name);
}
}

View File

@@ -0,0 +1,24 @@
package org.springframework.data.cassandra.cql.builder;
import org.springframework.util.Assert;
import com.datastax.driver.core.DataType;
public abstract class ColumnTypeChange extends ColumnChange {
private DataType type;
public ColumnTypeChange(String name, DataType type) {
super(name);
setType(type);
}
private void setType(DataType type) {
Assert.notNull(type);
this.type = type;
}
public DataType getType() {
return type;
}
}

View File

@@ -8,4 +8,39 @@ public class CqlBuilder {
public static CreateTableBuilder createTable() {
return new CreateTableBuilder();
}
/**
* 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);
}
/**
* Entry point into the {@link CqlBuilder}'s fluent API to alter a table. Convenient if imported statically.
*/
public static AlterTableBuilder alterTable() {
return new AlterTableBuilder();
}
/**
* 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);
}
/**
* Entry point into the {@link CqlBuilder}'s fluent API to drop a table. Convenient if imported statically.
*/
public static DropTableBuilder dropTable() {
return new DropTableBuilder();
}
/**
* 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);
}
}

View File

@@ -1,19 +1,14 @@
package org.springframework.data.cassandra.cql.builder;
import static org.springframework.data.cassandra.cql.CqlStringUtils.checkQuotedIdentifier;
import static org.springframework.data.cassandra.cql.CqlStringUtils.ensureNotNull;
import static org.springframework.data.cassandra.cql.CqlStringUtils.escapeSingle;
import static org.springframework.data.cassandra.cql.CqlStringUtils.singleQuote;
import static org.springframework.data.cassandra.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.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.data.cassandra.cql.CqlStringUtils;
import org.springframework.data.cassandra.mapping.KeyType;
import org.springframework.data.cassandra.mapping.Ordering;
@@ -24,12 +19,10 @@ import com.datastax.driver.core.DataType;
*
* @author Matthew T. Adams
*/
public class CreateTableBuilder {
public class CreateTableBuilder extends AbstractTableBuilder<CreateTableBuilder> {
private boolean ifNotExists = false;
private String name;
private List<ColumnBuilder> columns = new ArrayList<ColumnBuilder>();
private Map<String, Object> options = new LinkedHashMap<String, Object>();
/**
* Causes the inclusion of an <code>IF NOT EXISTS</code> clause.
@@ -50,74 +43,6 @@ public class CreateTableBuilder {
return this;
}
/**
* Sets the table name. Quotes are not escaped.
*
* @see CqlStringUtils#escape(CharSequence)
* @see CqlStringUtils#scrub(CharSequence)
*
* @return this
*/
public CreateTableBuilder name(String name) {
checkQuotedIdentifier(name);
this.name = name;
return this;
}
/**
* Convenience method that calls <code>with(option, null)</code>.
*
* @return this
*/
public CreateTableBuilder with(TableOption option) {
return with(option, null);
}
/**
* Sets the given table option. This is a convenience method that calls
* {@link #with(String, Object, boolean, boolean)} appropriately from the given {@link TableOption} and value for that
* option.
*
* @param option The option to set.
* @param value The value of the option. Must be type-compatible with the {@link TableOption}.
* @return this
* @see #with(String, Object, boolean, boolean)
*/
public CreateTableBuilder with(TableOption option, Object value) {
option.checkValue(value);
return with(option.getName(), value, option.escapesValue(), option.quotesValue());
}
/**
* Adds the given option by name to this table's options.
* <p/>
* Options that have <code>null</code> values are considered single string options where the name of the option is the
* string to be used. Otherwise, the result of {@link Object#toString()} is considered to be the value of the option
* with the given name. The value, after conversion to string, may have embedded single quotes escaped according to
* parameter <code>escape</code> and may be single-quoted according to parameter <code>quote</code>.
*
* @param name The name of the option
* @param value The value of the option. If <code>null</code>, the value is ignored and the option is considered to be
* composed of only the name, otherwise the value's {@link Object#toString()} value is used.
* @param escape Whether to escape the value via {@link CqlStringUtils#escapeSingle(Object)}. Ignored if given value
* is an instance of a {@link Map}.
* @param quote Whether to quote the value via {@link CqlStringUtils#singleQuote(Object)}. Ignored if given value is
* an instance of a {@link Map}.
* @return this
*/
public CreateTableBuilder with(String name, Object value, boolean escape, boolean quote) {
if (!(value instanceof Map)) {
if (escape) {
value = escapeSingle(value);
}
if (quote) {
value = singleQuote(value);
}
}
options().put(name, value);
return this;
}
public CreateTableBuilder column(String name, DataType type) {
return column(name, type, null, null);
}
@@ -143,30 +68,27 @@ public class CreateTableBuilder {
return columns == null ? columns = new ArrayList<ColumnBuilder>() : columns;
}
protected Map<String, Object> options() {
return options == null ? options = new LinkedHashMap<String, Object>() : options;
}
public StringBuilder toCql(StringBuilder cql) {
public String toCql() {
StringBuilder cql = new StringBuilder();
cql = noNull(cql);
preambleCql(cql);
columnsAndOptionsCql(cql);
cql.append(";");
return cql.toString();
return cql;
}
protected StringBuilder preambleCql(StringBuilder cql) {
return (cql = ensureNotNull(cql)).append("CREATE TABLE ").append(ifNotExists ? "IF NOT EXISTS " : "").append(name);
return noNull(cql).append("CREATE TABLE ").append(ifNotExists ? "IF NOT EXISTS " : "")
.append(getNameAsIdentifier());
}
@SuppressWarnings("unchecked")
protected StringBuilder columnsAndOptionsCql(StringBuilder cql) {
cql = ensureNotNull(cql);
cql = noNull(cql);
// begin columns
cql.append(" (");
@@ -275,35 +197,8 @@ public class CreateTableBuilder {
cql.append(" = ");
Map<Option, Object> valueMap = null;
if ((value instanceof Map) && !(valueMap = (Map<Option, Object>) value).isEmpty()) {
// then 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(value);
}
if (option.quotesValue()) {
entryValue = singleQuote(value);
}
cql.append(entryValue);
}
cql.append(" }");
if (value instanceof Map) {
optionValueMap((Map<Option, Object>) value, cql);
continue; // end non-empty value map
}
@@ -316,9 +211,4 @@ public class CreateTableBuilder {
return cql;
}
@Override
public String toString() {
return toCql();
}
}

View File

@@ -0,0 +1,15 @@
package org.springframework.data.cassandra.cql.builder;
import static org.springframework.data.cassandra.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,38 @@
package org.springframework.data.cassandra.cql.builder;
import static org.springframework.data.cassandra.cql.CqlStringUtils.checkIdentifier;
import static org.springframework.data.cassandra.cql.CqlStringUtils.noNull;
import static org.springframework.data.cassandra.cql.CqlStringUtils.identifize;
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

@@ -7,7 +7,7 @@ import java.util.Set;
/**
* Builder for maps, which also conveniently implements {@link Map} via delegation for convenience so you don't have to
* actually {@link #build()} it if you don't want to (or forget).
* actually {@link #build()} it (or forget to).
*
* @author Matthew T. Adams
* @param <K> The key type of the map.

View File

@@ -0,0 +1,19 @@
package org.springframework.data.cassandra.cql;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.springframework.data.cassandra.cql.CqlStringUtils.isQuotedIdentifier;
import static org.springframework.data.cassandra.cql.CqlStringUtils.isUnquotedIdentifier;
import org.junit.Test;
public class CqlStringUtilsTest {
@Test
public void testIsQuotedIdentifier() throws Exception {
assertFalse(isQuotedIdentifier("my\"id"));
assertTrue(isQuotedIdentifier("my\"\"id"));
assertFalse(isUnquotedIdentifier("my\"id"));
assertTrue(isUnquotedIdentifier("myid"));
}
}

View File

@@ -0,0 +1,24 @@
package org.springframework.data.cassandra.cql.builder;
import static org.springframework.data.cassandra.cql.builder.CqlBuilder.alterTable;
import org.junit.Test;
import com.datastax.driver.core.DataType;
public class AlterTableBuilderTest {
@Test
public void testAlterTableBuilder() throws Exception {
String name = "mytable";
DataType addedType = DataType.timeuuid();
String addedName = "added_column";
DataType alteredType = DataType.text();
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);
}
}

View File

@@ -18,7 +18,7 @@ public class CreateTableBuilderTest {
@Test
public void createTableTest() {
String name = "mytable";
String name = "my\"\"table";
DataType type0 = DataType.text();
String partKey0 = "partitionKey0";
String partition1 = "partitionKey1";
@@ -38,7 +38,7 @@ public class CreateTableBuilderTest {
String cql = builder.toCql();
assertEquals(
"CREATE TABLE IF NOT EXISTS mytable (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;",
"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

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