diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/TableOption.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/TableOption.java index c76629056..bac1a0cf8 100644 --- a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/TableOption.java +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/TableOption.java @@ -53,13 +53,13 @@ public enum TableOption implements Option { /** * replicate_on_write */ - REPLICATE_ON_WRITE("replicate_on_write", Boolean.class, true, false, false), + REPLICATE_ON_WRITE("replicate_on_write", Boolean.class, true, false, true), /** * caching * * @see CachingOption */ - CACHING("caching", CachingOption.class, true, false, false), + CACHING("caching", CachingOption.class, true, false, true), /** * bloom_filter_fp_chance */ @@ -152,6 +152,10 @@ public enum TableOption implements Option { * @author Matthew T. Adams */ public enum CompactionOption implements Option { + /** + * tombstone_threshold + */ + CLASS("class", String.class, true, false, true), /** * tombstone_threshold */ @@ -242,7 +246,7 @@ public enum TableOption implements Option { /** * sstable_compression */ - STABLE_COMPRESSION("sstable_compression", String.class, true, false, false), + SSTABLE_COMPRESSION("sstable_compression", String.class, true, false, true), /** * chunk_length_kb */ diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CqlTableSpecificationAssertions.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CqlTableSpecificationAssertions.java index 1cce358e3..f6c262764 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CqlTableSpecificationAssertions.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CqlTableSpecificationAssertions.java @@ -20,6 +20,8 @@ import static org.junit.Assert.assertEquals; import java.util.List; import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.cassandra.core.keyspace.ColumnSpecification; import org.springframework.cassandra.core.keyspace.TableDescriptor; import org.springframework.cassandra.core.keyspace.TableOption; @@ -32,6 +34,8 @@ import com.datastax.driver.core.TableMetadata.Options; public class CqlTableSpecificationAssertions { + private final static Logger log = LoggerFactory.getLogger(CqlTableSpecificationAssertions.class); + public static double DELTA = 1e-6; // delta for comparisons of doubles public static void assertTable(TableDescriptor expected, String keyspace, Session session) { @@ -57,8 +61,10 @@ public class CqlTableSpecificationAssertions { for (String key : expected.keySet()) { + log.info(key + " -> " + expected.get(key)); + Object value = expected.get(key); - TableOption tableOption = getTableOptionFor(key); + TableOption tableOption = getTableOptionFor(key.toUpperCase()); if (tableOption == null && key.equalsIgnoreCase(TableOption.COMPACT_STORAGE.getName())) { // TODO: figure out how to tell if COMPACT STORAGE was used diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CreateTableCqlGeneratorIntegrationTests.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CreateTableCqlGeneratorIntegrationTests.java index 82872f163..232d73659 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CreateTableCqlGeneratorIntegrationTests.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CreateTableCqlGeneratorIntegrationTests.java @@ -4,6 +4,7 @@ import static org.springframework.cassandra.test.integration.core.cql.generator. import org.junit.Test; import org.springframework.cassandra.test.integration.AbstractEmbeddedCassandraIntegrationTest; +import org.springframework.cassandra.test.unit.core.cql.generator.CreateTableCqlGeneratorTests; import org.springframework.cassandra.test.unit.core.cql.generator.CreateTableCqlGeneratorTests.BasicTest; import org.springframework.cassandra.test.unit.core.cql.generator.CreateTableCqlGeneratorTests.CompositePartitionKeyTest; import org.springframework.cassandra.test.unit.core.cql.generator.CreateTableCqlGeneratorTests.CreateTableTest; @@ -53,4 +54,19 @@ public class CreateTableCqlGeneratorIntegrationTests { return new CompositePartitionKeyTest(); } } + + public static class TableOptionsIntegrationTest extends AbstractEmbeddedCassandraIntegrationTest { + + @Test + public void test() { + + CreateTableCqlGeneratorTests.MultipleOptionsTest optionsTest = new CreateTableCqlGeneratorTests.MultipleOptionsTest(); + + optionsTest.prepare(); + + session.execute(optionsTest.cql); + + // assertTable(optionsTest.specification, keyspace, session); + } + } } \ No newline at end of file diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/CreateTableCqlGeneratorTests.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/CreateTableCqlGeneratorTests.java index 0f3b37d1b..c0a413924 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/CreateTableCqlGeneratorTests.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/CreateTableCqlGeneratorTests.java @@ -1,15 +1,27 @@ package org.springframework.cassandra.test.unit.core.cql.generator; -import static org.junit.Assert.*; +import static org.junit.Assert.assertTrue; + +import java.util.LinkedHashMap; +import java.util.Map; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.cassandra.core.cql.generator.CreateTableCqlGenerator; import org.springframework.cassandra.core.keyspace.CreateTableSpecification; +import org.springframework.cassandra.core.keyspace.Option; +import org.springframework.cassandra.core.keyspace.TableOption; +import org.springframework.cassandra.core.keyspace.TableOption.CachingOption; +import org.springframework.cassandra.core.keyspace.TableOption.CompactionOption; +import org.springframework.cassandra.core.keyspace.TableOption.CompressionOption; import com.datastax.driver.core.DataType; public class CreateTableCqlGeneratorTests { + private static final Logger log = LoggerFactory.getLogger(CreateTableCqlGeneratorTests.class); + /** * Asserts that the preamble is first & correctly formatted in the given CQL string. */ @@ -35,6 +47,35 @@ public class CreateTableCqlGeneratorTests { assertTrue(cql.contains("(" + columnSpec + ",")); } + /** + * Asserts that the read repair change is set properly + */ + public static void assertStringOption(String name, String value, String cql) { + log.info(name + " -> " + value); + assertTrue(cql.contains(name + " = '" + value + "'")); + } + + /** + * Asserts that the option is set + */ + public static void assertDoubleOption(String name, Double value, String cql) { + log.info(name + " -> " + value); + assertTrue(cql.contains(name + " = " + value)); + } + + public static void assertLongOption(String name, Long value, String cql) { + log.info(name + " -> " + value); + assertTrue(cql.contains(name + " = " + value)); + } + + /** + * Asserts that the read repair change is set properly + */ + public static void assertNullOption(String name, String cql) { + log.info(name); + assertTrue(cql.contains(" " + name + " ")); + } + /** * Convenient base class that other test classes can use so as not to repeat the generics declarations or * {@link #generator()} method. @@ -56,7 +97,8 @@ public class CreateTableCqlGeneratorTests { public String column1 = "column1"; public CreateTableSpecification specification() { - return CreateTableSpecification.createTable().name(name).partitionKeyColumn(partitionKey0, partitionKeyType0).column(column1, columnType1); + return CreateTableSpecification.createTable().name(name).partitionKeyColumn(partitionKey0, partitionKeyType0) + .column(column1, columnType1); } @Test @@ -96,4 +138,109 @@ public class CreateTableCqlGeneratorTests { assertPrimaryKey(String.format("(%s, %s)", partKey0, partKey1), cql); } } + + /** + * Test just the Read Repair Chance + * + * @author David Webb + * + */ + public static class ReadRepairChanceTest extends CreateTableTest { + + public String name = "mytable"; + public DataType partitionKeyType0 = DataType.text(); + public String partitionKey0 = "partitionKey0"; + public DataType partitionKeyType1 = DataType.timestamp(); + public String partitionKey1 = "create_timestamp"; + public DataType columnType1 = DataType.text(); + public String column1 = "column1"; + public Double readRepairChance = 0.5; + + public CreateTableSpecification specification() { + return (CreateTableSpecification) CreateTableSpecification.createTable().name(name) + .partitionKeyColumn(partitionKey0, partitionKeyType0).partitionKeyColumn(partitionKey1, partitionKeyType1) + .column(column1, columnType1).with(TableOption.READ_REPAIR_CHANCE, readRepairChance); + } + + @Test + public void test() { + prepare(); + + assertPreamble(name, cql); + assertColumns(String.format("%s %s, %s %s, %s %s", partitionKey0, partitionKeyType0, partitionKey1, + partitionKeyType1, column1, columnType1), cql); + assertPrimaryKey(String.format("(%s, %s)", partitionKey0, partitionKey1), cql); + assertDoubleOption(TableOption.READ_REPAIR_CHANCE.getName(), readRepairChance, cql); + } + } + + /** + * Fully test all available create table options + * + * TODO - Determine how to assert the options with map values + * + * @author David Webb + * + */ + public static class MultipleOptionsTest extends CreateTableTest { + + public String name = "timeseries_table"; + public DataType partitionKeyType0 = DataType.timeuuid(); + public String partitionKey0 = "tid"; + public DataType partitionKeyType1 = DataType.timestamp(); + public String partitionKey1 = "create_timestamp"; + public DataType columnType1 = DataType.text(); + public String column1 = "data_point"; + public Double readRepairChance = 0.5; + public Double dcLocalReadRepairChance = 0.7; + public Double bloomFilterFpChance = 0.001; + public Boolean replcateOnWrite = Boolean.FALSE; + public Long gcGraceSeconds = 600l; + public String comment = "This is My Table"; + public Map compactionMap = new LinkedHashMap(); + public Map compressionMap = new LinkedHashMap(); + + public CreateTableSpecification specification() { + + // Compaction + compactionMap.put(CompactionOption.CLASS, "SizeTieredCompactionStrategy"); + compactionMap.put(CompactionOption.MIN_THRESHOLD, "4"); + // Compression + compressionMap.put(CompressionOption.SSTABLE_COMPRESSION, "SnappyCompressor"); + compressionMap.put(CompressionOption.CHUNK_LENGTH_KB, 128); + compressionMap.put(CompressionOption.CRC_CHECK_CHANCE, 0.75); + + return (CreateTableSpecification) CreateTableSpecification.createTable().name(name) + .partitionKeyColumn(partitionKey0, partitionKeyType0).partitionKeyColumn(partitionKey1, partitionKeyType1) + .column(column1, columnType1).with(TableOption.COMPACT_STORAGE) + .with(TableOption.READ_REPAIR_CHANCE, readRepairChance).with(TableOption.COMPACTION, compactionMap) + .with(TableOption.COMPRESSION, compressionMap).with(TableOption.BLOOM_FILTER_FP_CHANCE, bloomFilterFpChance) + .with(TableOption.CACHING, CachingOption.KEYS_ONLY).with(TableOption.REPLICATE_ON_WRITE, replcateOnWrite) + .with(TableOption.COMMENT, comment).with(TableOption.DCLOCAL_READ_REPAIR_CHANCE, dcLocalReadRepairChance) + .with(TableOption.GC_GRACE_SECONDS, gcGraceSeconds); + } + + @Test + public void test() { + + prepare(); + + log.info(cql); + + assertPreamble(name, cql); + assertColumns(String.format("%s %s, %s %s, %s %s", partitionKey0, partitionKeyType0, partitionKey1, + partitionKeyType1, column1, columnType1), cql); + assertPrimaryKey(String.format("(%s, %s)", partitionKey0, partitionKey1), cql); + assertNullOption(TableOption.COMPACT_STORAGE.getName(), cql); + assertDoubleOption(TableOption.READ_REPAIR_CHANCE.getName(), readRepairChance, cql); + assertDoubleOption(TableOption.DCLOCAL_READ_REPAIR_CHANCE.getName(), dcLocalReadRepairChance, cql); + assertDoubleOption(TableOption.BLOOM_FILTER_FP_CHANCE.getName(), bloomFilterFpChance, cql); + assertStringOption(TableOption.CACHING.getName(), CachingOption.KEYS_ONLY.getValue(), cql); + assertStringOption(TableOption.REPLICATE_ON_WRITE.getName(), replcateOnWrite.toString(), cql); + assertStringOption(TableOption.COMMENT.getName(), comment, cql); + assertLongOption(TableOption.GC_GRACE_SECONDS.getName(), gcGraceSeconds, cql); + + } + } + }