Merge branch 'cassandra-3.9' into trunk

Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/e22170e9
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/e22170e9
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/e22170e9

Branch: refs/heads/trunk
Commit: e22170e990fb3b3cbafc2c7d747531981918714c
Parents: 9df02b9 de2c449
Author: Aleksey Yeschenko <[email protected]>
Authored: Mon Aug 15 18:33:14 2016 +0100
Committer: Aleksey Yeschenko <[email protected]>
Committed: Mon Aug 15 18:34:27 2016 +0100

----------------------------------------------------------------------
 CHANGES.txt                                               |  3 ++-
 src/java/org/apache/cassandra/db/ColumnFamilyStore.java   |  3 ++-
 .../cassandra/db/ColumnFamilyStoreCQLHelperTest.java      | 10 ++++++++++
 3 files changed, 14 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/e22170e9/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 9d80f94,05d09dc..a281b47
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,45 -1,5 +1,46 @@@
 +3.10
 + * Make decommission operation resumable (CASSANDRA-12008)
 + * Add support to one-way targeted repair (CASSANDRA-9876)
 + * Remove clientutil jar (CASSANDRA-11635)
 + * Fix compaction throughput throttle (CASSANDRA-12366)
 + * Delay releasing Memtable memory on flush until PostFlush has finished 
running (CASSANDRA-12358)
 + * Cassandra stress should dump all setting on startup (CASSANDRA-11914)
 + * Make it possible to compact a given token range (CASSANDRA-10643)
 + * Allow updating DynamicEndpointSnitch properties via JMX (CASSANDRA-12179)
 + * Collect metrics on queries by consistency level (CASSANDRA-7384)
 + * Add support for GROUP BY to SELECT statement (CASSANDRA-10707)
 + * Deprecate memtable_cleanup_threshold and update default for 
memtable_flush_writers (CASSANDRA-12228)
 + * Upgrade to OHC 0.4.4 (CASSANDRA-12133)
 + * Add version command to cassandra-stress (CASSANDRA-12258)
 + * Create compaction-stress tool (CASSANDRA-11844)
 + * Garbage-collecting compaction operation and schema option (CASSANDRA-7019)
-  * Add schema to snapshot manifest, add USING TIMESTAMP clause to ALTER TABLE 
statements (CASSANDRA-7190)
 + * Add beta protocol flag for v5 native protocol (CASSANDRA-12142)
 + * Support filtering on non-PRIMARY KEY columns in the CREATE
 +   MATERIALIZED VIEW statement's WHERE clause (CASSANDRA-10368)
 + * Unify STDOUT and SYSTEMLOG logback format (CASSANDRA-12004)
 + * COPY FROM should raise error for non-existing input files (CASSANDRA-12174)
 + * Faster write path (CASSANDRA-12269)
 + * Option to leave omitted columns in INSERT JSON unset (CASSANDRA-11424)
 + * Support json/yaml output in nodetool tpstats (CASSANDRA-12035)
 + * Expose metrics for successful/failed authentication attempts 
(CASSANDRA-10635)
 + * Prepend snapshot name with "truncated" or "dropped" when a snapshot
 +   is taken before truncating or dropping a table (CASSANDRA-12178)
 + * Optimize RestrictionSet (CASSANDRA-12153)
 + * cqlsh does not automatically downgrade CQL version (CASSANDRA-12150)
 + * Omit (de)serialization of state variable in UDAs (CASSANDRA-9613)
 + * Create a system table to expose prepared statements (CASSANDRA-8831)
 + * Reuse DataOutputBuffer from ColumnIndex (CASSANDRA-11970)
 + * Remove DatabaseDescriptor dependency from SegmentedFile (CASSANDRA-11580)
 + * Add supplied username to authentication error messages (CASSANDRA-12076)
 + * Remove pre-startup check for open JMX port (CASSANDRA-12074)
 + * Remove compaction Severity from DynamicEndpointSnitch (CASSANDRA-11738)
++Merged from 3.0:
++ * Add schema to snapshot manifest, add USING TIMESTAMP clause to ALTER TABLE 
statements (CASSANDRA-7190)
 +
 +
  3.9
   * Fix value skipping with counter columns (CASSANDRA-11726)
 + * Restore resumable hints delivery (CASSANDRA-11960)
   * Fix nodetool tablestats miss SSTable count (CASSANDRA-12205)
   * Fixed flacky SSTablesIteratedTest (CASSANDRA-12282)
   * Fixed flacky SSTableRewriterTest: check file counts before calling 
validateCFS (CASSANDRA-12348)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e22170e9/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/ColumnFamilyStore.java
index b92aedb,aa79e90..06dff0f
--- a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
+++ b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
@@@ -1775,7 -1754,6 +1775,8 @@@ public class ColumnFamilyStore implemen
                  }
  
                  writeSnapshotManifest(filesJSONArr, snapshotName);
-                 writeSnapshotSchema(snapshotName);
++                if (!Schema.SYSTEM_KEYSPACE_NAMES.contains(metadata.ksName) 
&& !Schema.REPLICATED_SYSTEM_KEYSPACE_NAMES.contains(metadata.ksName))
++                    writeSnapshotSchema(snapshotName);
              }
          }
          if (ephemeral)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e22170e9/test/unit/org/apache/cassandra/db/ColumnFamilyStoreCQLHelperTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/db/ColumnFamilyStoreCQLHelperTest.java
index df8fe49,0000000..0b04bb3
mode 100644,000000..100644
--- a/test/unit/org/apache/cassandra/db/ColumnFamilyStoreCQLHelperTest.java
+++ b/test/unit/org/apache/cassandra/db/ColumnFamilyStoreCQLHelperTest.java
@@@ -1,683 -1,0 +1,693 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you 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.apache.cassandra.db;
 +
 +import java.io.FileReader;
 +import java.nio.ByteBuffer;
 +import java.nio.charset.Charset;
 +import java.util.*;
 +
 +import com.google.common.collect.ImmutableList;
 +import com.google.common.collect.ImmutableMap;
 +import com.google.common.io.Files;
 +import org.junit.Assert;
 +import org.junit.Before;
 +import org.junit.Test;
 +
 +import org.apache.cassandra.*;
 +import org.apache.cassandra.config.*;
 +import org.apache.cassandra.cql3.*;
 +import org.apache.cassandra.cql3.statements.*;
 +import org.apache.cassandra.db.marshal.*;
 +import org.apache.cassandra.exceptions.*;
 +import org.apache.cassandra.index.sasi.*;
 +import org.apache.cassandra.schema.*;
 +import org.apache.cassandra.utils.*;
 +import org.json.simple.JSONArray;
 +import org.json.simple.JSONObject;
 +import org.json.simple.parser.JSONParser;
 +
 +import static org.junit.Assert.assertEquals;
 +import static org.junit.Assert.assertTrue;
 +
 +public class ColumnFamilyStoreCQLHelperTest extends CQLTester
 +{
 +    @Before
 +    public void defineSchema() throws ConfigurationException
 +    {
 +        SchemaLoader.prepareServer();
 +    }
 +
 +    @Test
 +    public void testUserTypesCQL()
 +    {
 +        String keyspace = "cql_test_keyspace_user_types";
 +        String table = "test_table_user_types";
 +
 +        UserType typeA = new UserType(keyspace, ByteBufferUtil.bytes("a"),
 +                                      
Arrays.asList(FieldIdentifier.forUnquoted("a1"),
 +                                                    
FieldIdentifier.forUnquoted("a2"),
 +                                                    
FieldIdentifier.forUnquoted("a3")),
 +                                      Arrays.asList(IntegerType.instance,
 +                                                    IntegerType.instance,
 +                                                    IntegerType.instance),
 +                                      true);
 +
 +        UserType typeB = new UserType(keyspace, ByteBufferUtil.bytes("b"),
 +                                      
Arrays.asList(FieldIdentifier.forUnquoted("b1"),
 +                                                    
FieldIdentifier.forUnquoted("b2"),
 +                                                    
FieldIdentifier.forUnquoted("b3")),
 +                                      Arrays.asList(typeA,
 +                                                    typeA,
 +                                                    typeA),
 +                                      true);
 +
 +        UserType typeC = new UserType(keyspace, ByteBufferUtil.bytes("c"),
 +                                      
Arrays.asList(FieldIdentifier.forUnquoted("c1"),
 +                                                    
FieldIdentifier.forUnquoted("c2"),
 +                                                    
FieldIdentifier.forUnquoted("c3")),
 +                                      Arrays.asList(typeB,
 +                                                    typeB,
 +                                                    typeB),
 +                                      true);
 +
 +        CFMetaData cfm = CFMetaData.Builder.create(keyspace, table)
 +                                           .addPartitionKey("pk1", 
IntegerType.instance)
 +                                           .addClusteringColumn("ck1", 
IntegerType.instance)
 +                                           .addRegularColumn("reg1", typeC)
 +                                           .addRegularColumn("reg2", 
ListType.getInstance(IntegerType.instance, false))
 +                                           .addRegularColumn("reg3", 
MapType.getInstance(AsciiType.instance, IntegerType.instance, true))
 +                                           .build();
 +
 +        SchemaLoader.createKeyspace(keyspace,
 +                                    KeyspaceParams.simple(1),
 +                                    Tables.of(cfm),
 +                                    Types.of(typeA, typeB, typeC));
 +
 +        ColumnFamilyStore cfs = 
Keyspace.open(keyspace).getColumnFamilyStore(table);
 +
 +        assertEquals(ImmutableList.of("CREATE TYPE 
cql_test_keyspace_user_types.a(a1 varint, a2 varint, a3 varint);",
 +                                      "CREATE TYPE 
cql_test_keyspace_user_types.b(b1 a, b2 a, b3 a);",
 +                                      "CREATE TYPE 
cql_test_keyspace_user_types.c(c1 b, c2 b, c3 b);"),
 +                     
ColumnFamilyStoreCQLHelper.getUserTypesAsCQL(cfs.metadata));
 +    }
 +
 +    @Test
 +    public void testDroppedColumnsCQL()
 +    {
 +        String keyspace = "cql_test_keyspace_dropped_columns";
 +        String table = "test_table_dropped_columns";
 +
 +        CFMetaData cfm = CFMetaData.Builder.create(keyspace, table)
 +                                           .addPartitionKey("pk1", 
IntegerType.instance)
 +                                           .addClusteringColumn("ck1", 
IntegerType.instance)
 +                                           .addRegularColumn("reg1", 
IntegerType.instance)
 +                                           .addRegularColumn("reg2", 
IntegerType.instance)
 +                                           .addRegularColumn("reg3", 
IntegerType.instance)
 +                                           .build();
 +
 +
 +        ColumnDefinition reg1 = 
cfm.getColumnDefinition(ByteBufferUtil.bytes("reg1"));
 +        ColumnDefinition reg2 = 
cfm.getColumnDefinition(ByteBufferUtil.bytes("reg2"));
 +        ColumnDefinition reg3 = 
cfm.getColumnDefinition(ByteBufferUtil.bytes("reg3"));
 +
 +        cfm.removeColumnDefinition(reg1);
 +        cfm.removeColumnDefinition(reg2);
 +        cfm.removeColumnDefinition(reg3);
 +
 +        cfm.recordColumnDrop(reg1, 10000);
 +        cfm.recordColumnDrop(reg2, 20000);
 +        cfm.recordColumnDrop(reg3, 30000);
 +
 +        SchemaLoader.createKeyspace(keyspace,
 +                                    KeyspaceParams.simple(1),
 +                                    cfm);
 +
 +        ColumnFamilyStore cfs = 
Keyspace.open(keyspace).getColumnFamilyStore(table);
 +
 +        assertEquals(ImmutableList.of("ALTER TABLE 
cql_test_keyspace_dropped_columns.test_table_dropped_columns DROP reg1 USING 
TIMESTAMP 10000;",
 +                                      "ALTER TABLE 
cql_test_keyspace_dropped_columns.test_table_dropped_columns DROP reg3 USING 
TIMESTAMP 30000;",
 +                                      "ALTER TABLE 
cql_test_keyspace_dropped_columns.test_table_dropped_columns DROP reg2 USING 
TIMESTAMP 20000;"),
 +                     
ColumnFamilyStoreCQLHelper.getDroppedColumnsAsCQL(cfs.metadata));
 +
 +        
assertTrue(ColumnFamilyStoreCQLHelper.getCFMetadataAsCQL(cfs.metadata, 
true).startsWith(
 +        "CREATE TABLE IF NOT EXISTS 
cql_test_keyspace_dropped_columns.test_table_dropped_columns (\n" +
 +        "\tpk1 varint,\n" +
 +        "\tck1 varint,\n" +
 +        "\treg1 varint,\n" +
 +        "\treg3 varint,\n" +
 +        "\treg2 varint,\n" +
 +        "\tPRIMARY KEY (pk1, ck1))"));
 +    }
 +
 +    @Test
 +    public void testReaddedColumns()
 +    {
 +        String keyspace = "cql_test_keyspace_readded_columns";
 +        String table = "test_table_readded_columns";
 +
 +        CFMetaData cfm = CFMetaData.Builder.create(keyspace, table)
 +                                           .addPartitionKey("pk1", 
IntegerType.instance)
 +                                           .addClusteringColumn("ck1", 
IntegerType.instance)
 +                                           .addRegularColumn("reg1", 
IntegerType.instance)
 +                                           .addStaticColumn("reg2", 
IntegerType.instance)
 +                                           .addRegularColumn("reg3", 
IntegerType.instance)
 +                                           .build();
 +
 +        ColumnDefinition reg1 = 
cfm.getColumnDefinition(ByteBufferUtil.bytes("reg1"));
 +        ColumnDefinition reg2 = 
cfm.getColumnDefinition(ByteBufferUtil.bytes("reg2"));
 +
 +        cfm.removeColumnDefinition(reg1);
 +        cfm.removeColumnDefinition(reg2);
 +
 +        cfm.recordColumnDrop(reg1, 10000);
 +        cfm.recordColumnDrop(reg2, 20000);
 +
 +        cfm.addColumnDefinition(reg1);
 +        cfm.addColumnDefinition(reg2);
 +
 +        SchemaLoader.createKeyspace(keyspace,
 +                                    KeyspaceParams.simple(1),
 +                                    cfm);
 +
 +        ColumnFamilyStore cfs = 
Keyspace.open(keyspace).getColumnFamilyStore(table);
 +
 +        // when re-adding, column is present in CREATE, then in DROP and then 
in ADD again, to record DROP with a proper timestamp
 +        
assertTrue(ColumnFamilyStoreCQLHelper.getCFMetadataAsCQL(cfs.metadata, 
true).startsWith(
 +        "CREATE TABLE IF NOT EXISTS 
cql_test_keyspace_readded_columns.test_table_readded_columns (\n" +
 +        "\tpk1 varint,\n" +
 +        "\tck1 varint,\n" +
 +        "\treg2 varint static,\n" +
 +        "\treg1 varint,\n" +
 +        "\treg3 varint,\n" +
 +        "\tPRIMARY KEY (pk1, ck1))"));
 +
 +        assertEquals(ImmutableList.of("ALTER TABLE 
cql_test_keyspace_readded_columns.test_table_readded_columns DROP reg1 USING 
TIMESTAMP 10000;",
 +                                      "ALTER TABLE 
cql_test_keyspace_readded_columns.test_table_readded_columns ADD reg1 varint;",
 +                                      "ALTER TABLE 
cql_test_keyspace_readded_columns.test_table_readded_columns DROP reg2 USING 
TIMESTAMP 20000;",
 +                                      "ALTER TABLE 
cql_test_keyspace_readded_columns.test_table_readded_columns ADD reg2 varint 
static;"),
 +                     
ColumnFamilyStoreCQLHelper.getDroppedColumnsAsCQL(cfs.metadata));
 +    }
 +
 +    @Test
 +    public void testCfmColumnsCQL()
 +    {
 +        String keyspace = "cql_test_keyspace_create_table";
 +        String table = "test_table_create_table";
 +
 +        CFMetaData cfm = CFMetaData.Builder.create(keyspace, table)
 +                                           .addPartitionKey("pk1", 
IntegerType.instance)
 +                                           .addPartitionKey("pk2", 
AsciiType.instance)
 +                                           .addClusteringColumn("ck1", 
ReversedType.getInstance(IntegerType.instance))
 +                                           .addClusteringColumn("ck2", 
IntegerType.instance)
 +                                           .addStaticColumn("st1", 
AsciiType.instance)
 +                                           .addRegularColumn("reg1", 
AsciiType.instance)
 +                                           .addRegularColumn("reg2", 
ListType.getInstance(IntegerType.instance, false))
 +                                           .addRegularColumn("reg3", 
MapType.getInstance(AsciiType.instance, IntegerType.instance, true))
 +                                           .build();
 +
 +        SchemaLoader.createKeyspace(keyspace,
 +                                    KeyspaceParams.simple(1),
 +                                    cfm);
 +
 +        ColumnFamilyStore cfs = 
Keyspace.open(keyspace).getColumnFamilyStore(table);
 +
 +        
assertTrue(ColumnFamilyStoreCQLHelper.getCFMetadataAsCQL(cfs.metadata, 
true).startsWith(
 +        "CREATE TABLE IF NOT EXISTS 
cql_test_keyspace_create_table.test_table_create_table (\n" +
 +        "\tpk1 varint,\n" +
 +        "\tpk2 ascii,\n" +
 +        "\tck1 varint,\n" +
 +        "\tck2 varint,\n" +
 +        "\tst1 ascii static,\n" +
 +        "\treg1 ascii,\n" +
 +        "\treg2 frozen<list<varint>>,\n" +
 +        "\treg3 map<ascii, varint>,\n" +
 +        "\tPRIMARY KEY ((pk1, pk2), ck1, ck2))\n" +
 +        "\tWITH ID = " + cfs.metadata.cfId + "\n" +
 +        "\tAND CLUSTERING ORDER BY (ck1 DESC, ck2 ASC)"));
 +    }
 +
 +    @Test
 +    public void testCfmCompactStorageCQL()
 +    {
 +        String keyspace = "cql_test_keyspace_compact";
 +        String table = "test_table_compact";
 +
 +        CFMetaData cfm = CFMetaData.Builder.createDense(keyspace, table, 
true, false)
 +                                           .addPartitionKey("pk1", 
IntegerType.instance)
 +                                           .addPartitionKey("pk2", 
AsciiType.instance)
 +                                           .addClusteringColumn("ck1", 
ReversedType.getInstance(IntegerType.instance))
 +                                           .addClusteringColumn("ck2", 
IntegerType.instance)
 +                                           .addRegularColumn("reg", 
IntegerType.instance)
 +                                           .build();
 +
 +        SchemaLoader.createKeyspace(keyspace,
 +                                    KeyspaceParams.simple(1),
 +                                    cfm);
 +
 +        ColumnFamilyStore cfs = 
Keyspace.open(keyspace).getColumnFamilyStore(table);
 +
 +        
assertTrue(ColumnFamilyStoreCQLHelper.getCFMetadataAsCQL(cfs.metadata, 
true).startsWith(
 +        "CREATE TABLE IF NOT EXISTS 
cql_test_keyspace_compact.test_table_compact (\n" +
 +        "\tpk1 varint,\n" +
 +        "\tpk2 ascii,\n" +
 +        "\tck1 varint,\n" +
 +        "\tck2 varint,\n" +
 +        "\treg varint,\n" +
 +        "\tPRIMARY KEY ((pk1, pk2), ck1, ck2))\n" +
 +        "\tWITH ID = " + cfm.cfId + "\n" +
 +        "\tAND COMPACT STORAGE\n" +
 +        "\tAND CLUSTERING ORDER BY (ck1 DESC, ck2 ASC)"));
 +    }
 +
 +    @Test
 +    public void testCfmCounterCQL()
 +    {
 +        String keyspace = "cql_test_keyspace_counter";
 +        String table = "test_table_counter";
 +
 +        CFMetaData cfm = CFMetaData.Builder.createDense(keyspace, table, 
true, true)
 +                                           .addPartitionKey("pk1", 
IntegerType.instance)
 +                                           .addPartitionKey("pk2", 
AsciiType.instance)
 +                                           .addClusteringColumn("ck1", 
ReversedType.getInstance(IntegerType.instance))
 +                                           .addClusteringColumn("ck2", 
IntegerType.instance)
 +                                           .addRegularColumn("cnt", 
CounterColumnType.instance)
 +                                           .build();
 +
 +        SchemaLoader.createKeyspace(keyspace,
 +                                    KeyspaceParams.simple(1),
 +                                    cfm);
 +
 +        ColumnFamilyStore cfs = 
Keyspace.open(keyspace).getColumnFamilyStore(table);
 +
 +        
assertTrue(ColumnFamilyStoreCQLHelper.getCFMetadataAsCQL(cfs.metadata, 
true).startsWith(
 +        "CREATE TABLE IF NOT EXISTS 
cql_test_keyspace_counter.test_table_counter (\n" +
 +        "\tpk1 varint,\n" +
 +        "\tpk2 ascii,\n" +
 +        "\tck1 varint,\n" +
 +        "\tck2 varint,\n" +
 +        "\tcnt counter,\n" +
 +        "\tPRIMARY KEY ((pk1, pk2), ck1, ck2))\n" +
 +        "\tWITH ID = " + cfm.cfId + "\n" +
 +        "\tAND COMPACT STORAGE\n" +
 +        "\tAND CLUSTERING ORDER BY (ck1 DESC, ck2 ASC)"));
 +    }
 +
 +    @Test
 +    public void testCfmOptionsCQL()
 +    {
 +        String keyspace = "cql_test_keyspace_options";
 +        String table = "test_table_options";
 +
 +        CFMetaData cfm = CFMetaData.Builder.create(keyspace, table)
 +                                           .addPartitionKey("pk1", 
IntegerType.instance)
 +                                           .addClusteringColumn("cl1", 
IntegerType.instance)
 +                                           .addRegularColumn("reg1", 
AsciiType.instance)
 +                                           .build();
 +
 +        
cfm.recordColumnDrop(cfm.getColumnDefinition(ByteBuffer.wrap("reg1".getBytes())),
 FBUtilities.timestampMicros());
 +        cfm.bloomFilterFpChance(1.0);
 +        cfm.comment("comment");
 +        
cfm.compaction(CompactionParams.lcs(Collections.singletonMap("sstable_size_in_mb",
 "1")));
 +        cfm.compression(CompressionParams.lz4(1 << 16));
 +        cfm.dcLocalReadRepairChance(0.2);
 +        cfm.crcCheckChance(0.3);
 +        cfm.defaultTimeToLive(4);
 +        cfm.gcGraceSeconds(5);
 +        cfm.minIndexInterval(6);
 +        cfm.maxIndexInterval(7);
 +        cfm.memtableFlushPeriod(8);
 +        cfm.readRepairChance(0.9);
 +        cfm.speculativeRetry(SpeculativeRetryParam.always());
 +        cfm.extensions(ImmutableMap.of("ext1",
 +                                       ByteBuffer.wrap("val1".getBytes())));
 +
 +        SchemaLoader.createKeyspace(keyspace,
 +                                    KeyspaceParams.simple(1),
 +                                    cfm);
 +        ColumnFamilyStore cfs = 
Keyspace.open(keyspace).getColumnFamilyStore(table);
 +
 +        
assertTrue(ColumnFamilyStoreCQLHelper.getCFMetadataAsCQL(cfs.metadata, 
true).endsWith(
 +        "AND bloom_filter_fp_chance = 1.0\n" +
 +        "\tAND dclocal_read_repair_chance = 0.2\n" +
 +        "\tAND crc_check_chance = 0.3\n" +
 +        "\tAND default_time_to_live = 4\n" +
 +        "\tAND gc_grace_seconds = 5\n" +
 +        "\tAND min_index_interval = 6\n" +
 +        "\tAND max_index_interval = 7\n" +
 +        "\tAND memtable_flush_period_in_ms = 8\n" +
 +        "\tAND read_repair_chance = 0.9\n" +
 +        "\tAND speculative_retry = 'ALWAYS'\n" +
 +        "\tAND comment = 'comment'\n" +
 +        "\tAND caching = { 'keys': 'ALL', 'rows_per_partition': 'NONE' }\n" +
 +        "\tAND compaction = { 'class': 
'org.apache.cassandra.db.compaction.LeveledCompactionStrategy', 
'sstable_size_in_mb': '1' }\n" +
 +        "\tAND compression = { 'chunk_length_in_kb': '64', 'class': 
'org.apache.cassandra.io.compress.LZ4Compressor' }\n" +
 +        "\tAND cdc = false\n" +
 +        "\tAND extensions = { 'ext1': 0x76616c31 };"
 +        ));
 +    }
 +
 +    @Test
 +    public void testCfmIndexJson()
 +    {
 +        String keyspace = "cql_test_keyspace_3";
 +        String table = "test_table_3";
 +
 +        CFMetaData cfm = CFMetaData.Builder.create(keyspace, table)
 +                                           .addPartitionKey("pk1", 
IntegerType.instance)
 +                                           .addClusteringColumn("cl1", 
IntegerType.instance)
 +                                           .addRegularColumn("reg1", 
AsciiType.instance)
 +                                           .build();
 +
 +        cfm.indexes(cfm.getIndexes()
 +                       .with(IndexMetadata.fromIndexTargets(cfm,
 +                                                            
Collections.singletonList(new 
IndexTarget(cfm.getColumnDefinition(ByteBufferUtil.bytes("reg1")).name,
 +                                                                              
                        IndexTarget.Type.VALUES)),
 +                                                            "indexName",
 +                                                            
IndexMetadata.Kind.COMPOSITES,
 +                                                            
Collections.emptyMap()))
 +                       .with(IndexMetadata.fromIndexTargets(cfm,
 +                                                            
Collections.singletonList(new 
IndexTarget(cfm.getColumnDefinition(ByteBufferUtil.bytes("reg1")).name,
 +                                                                              
                        IndexTarget.Type.KEYS)),
 +                                                            "indexName2",
 +                                                            
IndexMetadata.Kind.COMPOSITES,
 +                                                            
Collections.emptyMap()))
 +                       .with(IndexMetadata.fromIndexTargets(cfm,
 +                                                            
Collections.singletonList(new 
IndexTarget(cfm.getColumnDefinition(ByteBufferUtil.bytes("reg1")).name,
 +                                                                              
                        IndexTarget.Type.KEYS_AND_VALUES)),
 +                                                            "indexName3",
 +                                                            
IndexMetadata.Kind.COMPOSITES,
 +                                                            
Collections.emptyMap()))
 +                       .with(IndexMetadata.fromIndexTargets(cfm,
 +                                                            
Collections.singletonList(new 
IndexTarget(cfm.getColumnDefinition(ByteBufferUtil.bytes("reg1")).name,
 +                                                                              
                        IndexTarget.Type.KEYS_AND_VALUES)),
 +                                                            "indexName4",
 +                                                            
IndexMetadata.Kind.CUSTOM,
 +                                                            
Collections.singletonMap(IndexTarget.CUSTOM_INDEX_OPTION_NAME,
 +                                                                              
       SASIIndex.class.getName()))
 +                       ));
 +
 +
 +        SchemaLoader.createKeyspace(keyspace,
 +                                    KeyspaceParams.simple(1),
 +                                    cfm);
 +
 +        ColumnFamilyStore cfs = 
Keyspace.open(keyspace).getColumnFamilyStore(table);
 +
 +        assertEquals(ImmutableList.of("CREATE INDEX \"indexName\" ON 
cql_test_keyspace_3.test_table_3 (reg1);",
 +                                      "CREATE INDEX \"indexName2\" ON 
cql_test_keyspace_3.test_table_3 (reg1);",
 +                                      "CREATE INDEX \"indexName3\" ON 
cql_test_keyspace_3.test_table_3 (reg1);",
 +                                      "CREATE CUSTOM INDEX \"indexName4\" ON 
cql_test_keyspace_3.test_table_3 (reg1) USING 
'org.apache.cassandra.index.sasi.SASIIndex';"),
 +                     
ColumnFamilyStoreCQLHelper.getIndexesAsCQL(cfs.metadata));
 +    }
 +
 +    private final static String SNAPSHOT = "testsnapshot";
 +
 +    @Test
 +    public void testSnapshot() throws Throwable
 +    {
 +        String typeA = createType("CREATE TYPE %s (a1 varint, a2 varint, a3 
varint);");
 +        String typeB = createType("CREATE TYPE %s (b1 frozen<" + typeA + ">, 
b2 frozen<" + typeA + ">, b3 frozen<" + typeA + ">);");
 +        String typeC = createType("CREATE TYPE %s (c1 frozen<" + typeB + ">, 
c2 frozen<" + typeB + ">, c3 frozen<" + typeB + ">);");
 +
 +        String tableName = createTable("CREATE TABLE IF NOT EXISTS %s (" +
 +                                       "pk1 varint," +
 +                                       "pk2 ascii," +
 +                                       "ck1 varint," +
 +                                       "ck2 varint," +
 +                                       "reg1 " + typeC + "," +
 +                                       "reg2 int," +
 +                                       "reg3 int," +
 +                                       "PRIMARY KEY ((pk1, pk2), ck1, ck2)) 
WITH " +
 +                                       "CLUSTERING ORDER BY (ck1 ASC, ck2 
DESC);");
 +
 +        alterTable("ALTER TABLE %s DROP reg3 USING TIMESTAMP 10000;");
 +        alterTable("ALTER TABLE %s ADD reg3 int;");
 +
 +        for (int i = 0; i < 10; i++)
 +            execute("INSERT INTO %s (pk1, pk2, ck1, ck2, reg1, reg2) VALUES 
(?, ?, ?, ?, ?, ?)", i, i + 1, i + 2, i + 3, null, i + 5);
 +
 +        ColumnFamilyStore cfs = 
Keyspace.open(keyspace()).getColumnFamilyStore(tableName);
 +        cfs.snapshot(SNAPSHOT);
 +
 +        String schema = 
Files.toString(cfs.getDirectories().getSnapshotSchemaFile(SNAPSHOT), 
Charset.defaultCharset());
 +        assertTrue(schema.contains(String.format("CREATE TYPE %s.%s(a1 
varint, a2 varint, a3 varint);", keyspace(), typeA)));
 +        assertTrue(schema.contains(String.format("CREATE TYPE %s.%s(a1 
varint, a2 varint, a3 varint);", keyspace(), typeA)));
 +        assertTrue(schema.contains(String.format("CREATE TYPE %s.%s(b1 
frozen<%s>, b2 frozen<%s>, b3 frozen<%s>);", keyspace(), typeB, typeA, typeA, 
typeA)));
 +        assertTrue(schema.contains(String.format("CREATE TYPE %s.%s(c1 
frozen<%s>, c2 frozen<%s>, c3 frozen<%s>);", keyspace(), typeC, typeB, typeB, 
typeB)));
 +
 +        schema = schema.substring(schema.indexOf("CREATE TABLE")); // trim to 
ensure order
 +
 +        assertTrue(schema.startsWith("CREATE TABLE IF NOT EXISTS " + 
keyspace() + "." + tableName + " (\n" +
 +                                     "\tpk1 varint,\n" +
 +                                     "\tpk2 ascii,\n" +
 +                                     "\tck1 varint,\n" +
 +                                     "\tck2 varint,\n" +
 +                                     "\treg2 int,\n" +
 +                                     "\treg3 int,\n" +
 +                                     "\treg1 " + typeC + ",\n" +
 +                                     "\tPRIMARY KEY ((pk1, pk2), ck1, 
ck2))\n" +
 +                                     "\tWITH ID = " + cfs.metadata.cfId + 
"\n" +
 +                                     "\tAND CLUSTERING ORDER BY (ck1 ASC, ck2 
DESC)"));
 +
 +        schema = schema.substring(schema.indexOf("ALTER"));
 +        assertTrue(schema.startsWith(String.format("ALTER TABLE %s.%s DROP 
reg3 USING TIMESTAMP 10000;", keyspace(), tableName)));
 +        assertTrue(schema.contains(String.format("ALTER TABLE %s.%s ADD reg3 
int;", keyspace(), tableName)));
 +
 +        JSONObject manifest = (JSONObject) new JSONParser().parse(new 
FileReader(cfs.getDirectories().getSnapshotManifestFile(SNAPSHOT)));
 +        JSONArray files = (JSONArray) manifest.get("files");
 +        Assert.assertEquals(1, files.size());
 +    }
 +
 +    @Test
++    public void testSystemKsSnapshot() throws Throwable
++    {
++        ColumnFamilyStore cfs = 
Keyspace.open("system").getColumnFamilyStore("peers");
++        cfs.snapshot(SNAPSHOT);
++
++        
Assert.assertTrue(cfs.getDirectories().getSnapshotManifestFile(SNAPSHOT).exists());
++        
Assert.assertFalse(cfs.getDirectories().getSnapshotSchemaFile(SNAPSHOT).exists());
++    }
++
++    @Test
 +    public void testDroppedType() throws Throwable
 +    {
 +        String typeA = createType("CREATE TYPE %s (a1 varint, a2 varint, a3 
varint);");
 +        String typeB = createType("CREATE TYPE %s (b1 frozen<" + typeA + ">, 
b2 frozen<" + typeA + ">, b3 frozen<" + typeA + ">);");
 +
 +        String tableName = createTable("CREATE TABLE IF NOT EXISTS %s (" +
 +                                       "pk1 varint," +
 +                                       "ck1 varint," +
 +                                       "reg1 " + typeB + "," +
 +                                       "reg2 varint," +
 +                                       "PRIMARY KEY (pk1, ck1));");
 +
 +        alterTable("ALTER TABLE %s DROP reg1 USING TIMESTAMP 10000;");
 +
 +        Runnable validate = () -> {
 +            try
 +            {
 +                ColumnFamilyStore cfs = 
Keyspace.open(keyspace()).getColumnFamilyStore(tableName);
 +                cfs.snapshot(SNAPSHOT);
 +                String schema = 
Files.toString(cfs.getDirectories().getSnapshotSchemaFile(SNAPSHOT), 
Charset.defaultCharset());
 +
 +                // When both column and it's type are dropped, the type in 
column definition gets substituted with a tuple
 +                assertTrue(schema.startsWith("CREATE TABLE IF NOT EXISTS " + 
keyspace() + "." + tableName + " (\n" +
 +                                             "\tpk1 varint,\n" +
 +                                             "\tck1 varint,\n" +
 +                                             "\treg2 varint,\n" +
 +                                             "\treg1 
frozen<tuple<frozen<tuple<varint, varint, varint>>, frozen<tuple<varint, 
varint, varint>>, frozen<tuple<varint, varint, varint>>>>,\n" +
 +                                             "\tPRIMARY KEY (pk1, ck1))"));
 +                assertTrue(schema.contains("ALTER TABLE " + keyspace() + "." 
+ tableName + " DROP reg1 USING TIMESTAMP 10000;"));
 +            }
 +            catch (Exception e)
 +            {
 +                throw new RuntimeException(e);
 +            }
 +        };
 +
 +        // Validate before and after the type drop
 +        validate.run();
 +        schemaChange("DROP TYPE " + keyspace() + "." + typeB);
 +        schemaChange("DROP TYPE " + keyspace() + "." + typeA);
 +        validate.run();
 +    }
 +
 +    @Test
 +    public void testDenseTable() throws Throwable
 +    {
 +        String tableName = createTable("CREATE TABLE IF NOT EXISTS %s (" +
 +                                       "pk1 varint PRIMARY KEY," +
 +                                       "reg1 int)" +
 +                                       " WITH COMPACT STORAGE");
 +
 +        ColumnFamilyStore cfs = 
Keyspace.open(keyspace()).getColumnFamilyStore(tableName);
 +
 +        
assertTrue(ColumnFamilyStoreCQLHelper.getCFMetadataAsCQL(cfs.metadata, 
true).startsWith(
 +        "CREATE TABLE IF NOT EXISTS " + keyspace() + "." + tableName + " (\n" 
+
 +        "\tpk1 varint PRIMARY KEY,\n" +
 +        "\treg1 int)\n" +
 +        "\tWITH ID = " + cfs.metadata.cfId + "\n" +
 +        "\tAND COMPACT STORAGE"));
 +    }
 +
 +    @Test
 +    public void testStaticCompactTable() throws Throwable
 +    {
 +        String tableName = createTable("CREATE TABLE IF NOT EXISTS %s (" +
 +                                       "pk1 varint PRIMARY KEY," +
 +                                       "reg1 int," +
 +                                       "reg2 int)" +
 +                                       " WITH COMPACT STORAGE");
 +
 +        ColumnFamilyStore cfs = 
Keyspace.open(keyspace()).getColumnFamilyStore(tableName);
 +
 +        
assertTrue(ColumnFamilyStoreCQLHelper.getCFMetadataAsCQL(cfs.metadata, 
true).startsWith(
 +        "CREATE TABLE IF NOT EXISTS " + keyspace() + "." + tableName + " (\n" 
+
 +        "\tpk1 varint PRIMARY KEY,\n" +
 +        "\treg1 int,\n" +
 +        "\treg2 int)\n" +
 +        "\tWITH ID = " + cfs.metadata.cfId + "\n" +
 +        "\tAND COMPACT STORAGE"));
 +    }
 +
 +    @Test
 +    public void testStaticCompactWithCounters() throws Throwable
 +    {
 +        String tableName = createTable("CREATE TABLE IF NOT EXISTS %s (" +
 +                                       "pk1 varint PRIMARY KEY," +
 +                                       "reg1 counter," +
 +                                       "reg2 counter)" +
 +                                       " WITH COMPACT STORAGE");
 +
 +
 +        ColumnFamilyStore cfs = 
Keyspace.open(keyspace()).getColumnFamilyStore(tableName);
 +
 +        
assertTrue(ColumnFamilyStoreCQLHelper.getCFMetadataAsCQL(cfs.metadata, 
true).startsWith(
 +        "CREATE TABLE IF NOT EXISTS " + keyspace() + "." + tableName + " (\n" 
+
 +        "\tpk1 varint PRIMARY KEY,\n" +
 +        "\treg1 counter,\n" +
 +        "\treg2 counter)\n" +
 +        "\tWITH ID = " + cfs.metadata.cfId + "\n" +
 +        "\tAND COMPACT STORAGE"));
 +    }
 +
 +    @Test
 +    public void testDenseCompactTableWithoutRegulars() throws Throwable
 +    {
 +        String tableName = createTable("CREATE TABLE IF NOT EXISTS %s (" +
 +                                       "pk1 varint," +
 +                                       "ck1 int," +
 +                                       "PRIMARY KEY (pk1, ck1))" +
 +                                       " WITH COMPACT STORAGE");
 +
 +        ColumnFamilyStore cfs = 
Keyspace.open(keyspace()).getColumnFamilyStore(tableName);
 +
 +        
assertTrue(ColumnFamilyStoreCQLHelper.getCFMetadataAsCQL(cfs.metadata, 
true).startsWith(
 +        "CREATE TABLE IF NOT EXISTS " + keyspace() + "." + tableName + " (\n" 
+
 +        "\tpk1 varint,\n" +
 +        "\tck1 int,\n" +
 +        "\tPRIMARY KEY (pk1, ck1))\n" +
 +        "\tWITH ID = " + cfs.metadata.cfId + "\n" +
 +        "\tAND COMPACT STORAGE"));
 +    }
 +
 +    @Test
 +    public void testCompactDynamic() throws Throwable
 +    {
 +        String tableName = createTable("CREATE TABLE IF NOT EXISTS %s (" +
 +                                       "pk1 varint," +
 +                                       "ck1 int," +
 +                                       "reg int," +
 +                                       "PRIMARY KEY (pk1, ck1))" +
 +                                       " WITH COMPACT STORAGE");
 +
 +        ColumnFamilyStore cfs = 
Keyspace.open(keyspace()).getColumnFamilyStore(tableName);
 +
 +        
assertTrue(ColumnFamilyStoreCQLHelper.getCFMetadataAsCQL(cfs.metadata, 
true).startsWith(
 +        "CREATE TABLE IF NOT EXISTS " + keyspace() + "." + tableName + " (\n" 
+
 +        "\tpk1 varint,\n" +
 +        "\tck1 int,\n" +
 +        "\treg int,\n" +
 +        "\tPRIMARY KEY (pk1, ck1))\n" +
 +        "\tWITH ID = " + cfs.metadata.cfId + "\n" +
 +        "\tAND COMPACT STORAGE"));
 +    }
 +
 +    @Test
 +    public void testDynamicComposite() throws Throwable
 +    {
 +        Map<Byte, AbstractType<?>> aliases = new HashMap<>();
 +        aliases.put((byte)'a', BytesType.instance);
 +        aliases.put((byte)'b', BytesType.instance);
 +        aliases.put((byte)'c', BytesType.instance);
 +
 +        String DYNAMIC_COMPOSITE = "dynamic_composite";
 +        AbstractType<?> dynamicComposite = 
DynamicCompositeType.getInstance(aliases);
 +
 +        SchemaLoader.createKeyspace(DYNAMIC_COMPOSITE,
 +                                    KeyspaceParams.simple(1),
 +                                    SchemaLoader.denseCFMD(DYNAMIC_COMPOSITE, 
DYNAMIC_COMPOSITE, dynamicComposite));
 +
 +        ColumnFamilyStore cfs = 
Keyspace.open(DYNAMIC_COMPOSITE).getColumnFamilyStore(DYNAMIC_COMPOSITE);
 +
 +        
assertTrue(ColumnFamilyStoreCQLHelper.getCFMetadataAsCQL(cfs.metadata, 
true).startsWith(
 +        "CREATE TABLE IF NOT EXISTS " + DYNAMIC_COMPOSITE + "." + 
DYNAMIC_COMPOSITE + " (\n" +
 +        "\tkey ascii,\n" +
 +        "\tcols 
'org.apache.cassandra.db.marshal.DynamicCompositeType(a=>org.apache.cassandra.db.marshal.BytesType,b=>org.apache.cassandra.db.marshal.BytesType,c=>org.apache.cassandra.db.marshal.BytesType)',\n"
 +
 +        "\tval ascii,\n" +
 +        "\tPRIMARY KEY (key, cols))\n" +
 +        "\tWITH ID = " + cfs.metadata.cfId + "\n" +
 +        "\tAND COMPACT STORAGE"));
 +    }
 +
 +    @Test
 +    public void superColumnFamilyTest() throws Throwable
 +    {
 +        final String KEYSPACE = "thrift_compact_table_with_supercolumns_test";
 +        final String TABLE = "test_table_1";
 +
 +        CFMetaData cfm = CFMetaData.Builder.createSuper(KEYSPACE, TABLE, 
false)
 +                                           .addPartitionKey("pk", 
BytesType.instance)
 +                                           .addClusteringColumn("c1", 
AsciiType.instance)
 +                                           .addClusteringColumn("c2", 
AsciiType.instance)
 +                                           .addRegularColumn("", 
MapType.getInstance(Int32Type.instance, AsciiType.instance, true))
 +                                           .build();
 +
 +        SchemaLoader.createKeyspace(KEYSPACE,
 +                                    KeyspaceParams.simple(1),
 +                                    cfm);
 +
 +        ColumnFamilyStore cfs = 
Keyspace.open(KEYSPACE).getColumnFamilyStore(TABLE);
 +
 +        
assertTrue(ColumnFamilyStoreCQLHelper.getCFMetadataAsCQL(cfs.metadata, 
true).startsWith(
 +        "/*\n" +
 +        "Warning: Table " + KEYSPACE + "." + TABLE + " omitted because it has 
constructs not compatible with CQL (was created via legacy API).\n\n" +
 +        "Approximate structure, for reference:\n" +
 +        "(this should not be used to reproduce this schema)\n\n" +
 +        "CREATE TABLE IF NOT EXISTS " + KEYSPACE + "." + TABLE + " (\n" +
 +        "\tpk blob,\n" +
 +        "\tc1 ascii,\n" +
 +        "\tc2 ascii,\n" +
 +        "\t\"\" map<int, ascii>,\n" +
 +        "\tPRIMARY KEY (pk, c1, c2))\n" +
 +        "\tWITH ID = " + cfs.metadata.cfId + "\n" +
 +        "\tAND COMPACT STORAGE"));
 +    }
 +}

Reply via email to