Repository: cassandra Updated Branches: refs/heads/trunk 81ba56163 -> 7d6c876ec
http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/src/java/org/apache/cassandra/service/StorageService.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java index 93f69a9..596e463 100644 --- a/src/java/org/apache/cassandra/service/StorageService.java +++ b/src/java/org/apache/cassandra/service/StorageService.java @@ -2471,7 +2471,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE public int forceKeyspaceCleanup(String keyspaceName, String... columnFamilies) throws IOException, ExecutionException, InterruptedException { - if (keyspaceName.equals(SystemKeyspace.NAME)) + if (Schema.isSystemKeyspace(keyspaceName)) throw new RuntimeException("Cleanup of the system keyspace is neither necessary nor wise"); CompactionManager.AllSSTableOpStatus status = CompactionManager.AllSSTableOpStatus.SUCCESSFUL; @@ -2705,7 +2705,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE Map<String, TabularData> snapshotMap = new HashMap<>(); for (Keyspace keyspace : Keyspace.all()) { - if (SystemKeyspace.NAME.equals(keyspace.getName())) + if (Schema.isSystemKeyspace(keyspace.getName())) continue; for (ColumnFamilyStore cfStore : keyspace.getColumnFamilyStores()) @@ -2731,7 +2731,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE long total = 0; for (Keyspace keyspace : Keyspace.all()) { - if (SystemKeyspace.NAME.equals(keyspace.getName())) + if (Schema.isSystemKeyspace(keyspace.getName())) continue; for (ColumnFamilyStore cfStore : keyspace.getColumnFamilyStores()) http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/src/java/org/apache/cassandra/thrift/ThriftConversion.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/thrift/ThriftConversion.java b/src/java/org/apache/cassandra/thrift/ThriftConversion.java index f60ea48..3e0c8f4 100644 --- a/src/java/org/apache/cassandra/thrift/ThriftConversion.java +++ b/src/java/org/apache/cassandra/thrift/ThriftConversion.java @@ -40,9 +40,9 @@ import org.apache.cassandra.locator.AbstractReplicationStrategy; import org.apache.cassandra.locator.LocalStrategy; import org.apache.cassandra.schema.KeyspaceMetadata; import org.apache.cassandra.schema.KeyspaceParams; +import org.apache.cassandra.schema.SchemaKeyspace; import org.apache.cassandra.schema.Tables; import org.apache.cassandra.serializers.MarshalException; -import org.apache.cassandra.schema.LegacySchemaTables; import org.apache.cassandra.utils.ByteBufferUtil; import org.apache.cassandra.utils.UUIDGen; @@ -414,7 +414,7 @@ public class ThriftConversion cols.add(convertThriftCqlRow(row)); UntypedResultSet colsRows = UntypedResultSet.create(cols); - return LegacySchemaTables.createTableFromTableRowAndColumnRows(cfRow, colsRows); + return SchemaKeyspace.createTableFromTableRowAndColumnRows(cfRow, colsRows); } private static Map<String, ByteBuffer> convertThriftCqlRow(CqlRow row) http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/src/java/org/apache/cassandra/thrift/ThriftValidation.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/thrift/ThriftValidation.java b/src/java/org/apache/cassandra/thrift/ThriftValidation.java index dd5bf98..13c55aa 100644 --- a/src/java/org/apache/cassandra/thrift/ThriftValidation.java +++ b/src/java/org/apache/cassandra/thrift/ThriftValidation.java @@ -632,8 +632,8 @@ public class ThriftValidation public static void validateKeyspaceNotSystem(String modifiedKeyspace) throws org.apache.cassandra.exceptions.InvalidRequestException { - if (modifiedKeyspace.equalsIgnoreCase(SystemKeyspace.NAME)) - throw new org.apache.cassandra.exceptions.InvalidRequestException("system keyspace is not user-modifiable"); + if (Schema.isSystemKeyspace(modifiedKeyspace)) + throw new org.apache.cassandra.exceptions.InvalidRequestException(String.format("%s keyspace is not user-modifiable", modifiedKeyspace)); } //public static IDiskAtomFilter asIFilter(SlicePredicate sp, CFMetaData metadata, ByteBuffer superColumn) http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/src/java/org/apache/cassandra/tools/nodetool/Cleanup.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/tools/nodetool/Cleanup.java b/src/java/org/apache/cassandra/tools/nodetool/Cleanup.java index aa415b3..d5c505e 100644 --- a/src/java/org/apache/cassandra/tools/nodetool/Cleanup.java +++ b/src/java/org/apache/cassandra/tools/nodetool/Cleanup.java @@ -23,6 +23,7 @@ import io.airlift.command.Command; import java.util.ArrayList; import java.util.List; +import org.apache.cassandra.config.Schema; import org.apache.cassandra.db.SystemKeyspace; import org.apache.cassandra.tools.NodeProbe; import org.apache.cassandra.tools.NodeTool.NodeToolCmd; @@ -41,13 +42,14 @@ public class Cleanup extends NodeToolCmd for (String keyspace : keyspaces) { - if (SystemKeyspace.NAME.equals(keyspace)) + if (Schema.isSystemKeyspace(keyspace)) continue; try { probe.forceKeyspaceCleanup(System.out, keyspace, cfnames); - } catch (Exception e) + } + catch (Exception e) { throw new RuntimeException("Error occurred during cleanup", e); } http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/src/java/org/apache/cassandra/utils/NativeSSTableLoaderClient.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/utils/NativeSSTableLoaderClient.java b/src/java/org/apache/cassandra/utils/NativeSSTableLoaderClient.java index f2663bf..fa415ae 100644 --- a/src/java/org/apache/cassandra/utils/NativeSSTableLoaderClient.java +++ b/src/java/org/apache/cassandra/utils/NativeSSTableLoaderClient.java @@ -26,12 +26,11 @@ import org.apache.cassandra.config.ColumnDefinition; import org.apache.cassandra.config.CFMetaData; import org.apache.cassandra.cql3.ColumnIdentifier; import org.apache.cassandra.db.CompactTables; -import org.apache.cassandra.db.SystemKeyspace; import org.apache.cassandra.db.marshal.*; import org.apache.cassandra.dht.*; import org.apache.cassandra.dht.Token; import org.apache.cassandra.io.sstable.SSTableLoader; -import org.apache.cassandra.schema.LegacySchemaTables; +import org.apache.cassandra.schema.SchemaKeyspace; public class NativeSSTableLoaderClient extends SSTableLoader.Client { @@ -100,9 +99,9 @@ public class NativeSSTableLoaderClient extends SSTableLoader.Client { Map<String, CFMetaData> tables = new HashMap<>(); - String query = String.format("SELECT columnfamily_name, cf_id, type, comparator, subcomparator, is_dense, default_validator FROM %s.%s WHERE keyspace_name = '%s'", - SystemKeyspace.NAME, - LegacySchemaTables.COLUMNFAMILIES, + String query = String.format("SELECT table_name, cf_id, type, comparator, subcomparator, is_dense, default_validator FROM %s.%s WHERE keyspace_name = '%s'", + SchemaKeyspace.NAME, + SchemaKeyspace.TABLES, keyspace); @@ -110,7 +109,7 @@ public class NativeSSTableLoaderClient extends SSTableLoader.Client // be safer to have a simple wrapper of the driver ResultSet/Row implementing UntypedResultSet/UntypedResultSet.Row and reuse the original method. for (Row row : session.execute(query)) { - String name = row.getString("columnfamily_name"); + String name = row.getString("table_name"); UUID id = row.getUUID("cf_id"); boolean isSuper = row.getString("type").toLowerCase().equals("super"); AbstractType rawComparator = TypeParser.parse(row.getString("comparator")); @@ -124,9 +123,9 @@ public class NativeSSTableLoaderClient extends SSTableLoader.Client boolean isCounter = defaultValidator instanceof CounterColumnType; boolean isCQLTable = !isSuper && !isDense && isCompound; - String columnsQuery = String.format("SELECT column_name, component_index, type, validator FROM %s.%s WHERE keyspace_name='%s' AND columnfamily_name='%s'", - SystemKeyspace.NAME, - LegacySchemaTables.COLUMNS, + String columnsQuery = String.format("SELECT column_name, component_index, type, validator FROM %s.%s WHERE keyspace_name='%s' AND table_name='%s'", + SchemaKeyspace.NAME, + SchemaKeyspace.COLUMNS, keyspace, name); @@ -149,7 +148,7 @@ public class NativeSSTableLoaderClient extends SSTableLoader.Client boolean isSuper, boolean isCQLTable) { - ColumnDefinition.Kind kind = LegacySchemaTables.deserializeKind(row.getString("type")); + ColumnDefinition.Kind kind = SchemaKeyspace.deserializeKind(row.getString("type")); Integer componentIndex = null; if (!row.isNull("component_index")) http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/test/unit/org/apache/cassandra/SchemaLoader.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/SchemaLoader.java b/test/unit/org/apache/cassandra/SchemaLoader.java index bd213a5..86e4762 100644 --- a/test/unit/org/apache/cassandra/SchemaLoader.java +++ b/test/unit/org/apache/cassandra/SchemaLoader.java @@ -143,7 +143,7 @@ public class SchemaLoader //CFMetaData.Builder.create(ks1, "Counter1", false, false, true).build(), //CFMetaData.Builder.create(ks1, "SuperCounter1", false, false, true, true).build(), superCFMD(ks1, "SuperDirectGC", BytesType.instance).gcGraceSeconds(0), - jdbcCFMD(ks1, "JdbcInteger", IntegerType.instance).addColumnDefinition(integerColumn(ks1, "JdbcInteger")), +// jdbcCFMD(ks1, "JdbcInteger", IntegerType.instance).addColumnDefinition(integerColumn(ks1, "JdbcInteger")), jdbcCFMD(ks1, "JdbcUtf8", UTF8Type.instance).addColumnDefinition(utf8Column(ks1, "JdbcUtf8")), jdbcCFMD(ks1, "JdbcLong", LongType.instance), jdbcCFMD(ks1, "JdbcBytes", bytes), @@ -296,7 +296,7 @@ public class SchemaLoader ColumnDefinition.Kind.REGULAR); } - private static ColumnDefinition utf8Column(String ksName, String cfName) + public static ColumnDefinition utf8Column(String ksName, String cfName) { return new ColumnDefinition(ksName, cfName, http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/test/unit/org/apache/cassandra/config/CFMetaDataTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/config/CFMetaDataTest.java b/test/unit/org/apache/cassandra/config/CFMetaDataTest.java index 1238464..c0808d2 100644 --- a/test/unit/org/apache/cassandra/config/CFMetaDataTest.java +++ b/test/unit/org/apache/cassandra/config/CFMetaDataTest.java @@ -33,7 +33,7 @@ import org.apache.cassandra.exceptions.ConfigurationException; import org.apache.cassandra.io.compress.*; import org.apache.cassandra.schema.KeyspaceMetadata; import org.apache.cassandra.schema.KeyspaceParams; -import org.apache.cassandra.schema.LegacySchemaTables; +import org.apache.cassandra.schema.SchemaKeyspace; import org.apache.cassandra.service.StorageService; import org.apache.cassandra.thrift.CfDef; import org.apache.cassandra.thrift.ColumnDef; @@ -143,10 +143,10 @@ public class CFMetaDataTest assert before.equals(after) : String.format("%n%s%n!=%n%s", before, after); // Test schema conversion - Mutation rm = LegacySchemaTables.makeCreateTableMutation(keyspace, cfm, FBUtilities.timestampMicros()); - PartitionUpdate cfU = rm.getPartitionUpdate(Schema.instance.getId(SystemKeyspace.NAME, LegacySchemaTables.COLUMNFAMILIES)); - PartitionUpdate cdU = rm.getPartitionUpdate(Schema.instance.getId(SystemKeyspace.NAME, LegacySchemaTables.COLUMNS)); - CFMetaData newCfm = LegacySchemaTables.createTableFromTablePartitionAndColumnsPartition( + Mutation rm = SchemaKeyspace.makeCreateTableMutation(keyspace, cfm, FBUtilities.timestampMicros()); + PartitionUpdate cfU = rm.getPartitionUpdate(Schema.instance.getId(SchemaKeyspace.NAME, SchemaKeyspace.TABLES)); + PartitionUpdate cdU = rm.getPartitionUpdate(Schema.instance.getId(SchemaKeyspace.NAME, SchemaKeyspace.COLUMNS)); + CFMetaData newCfm = SchemaKeyspace.createTableFromTablePartitionAndColumnsPartition( UnfilteredRowIterators.filter(cfU.unfilteredIterator(), FBUtilities.nowInSeconds()), UnfilteredRowIterators.filter(cdU.unfilteredIterator(), FBUtilities.nowInSeconds()) ); http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/test/unit/org/apache/cassandra/config/LegacySchemaTablesTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/config/LegacySchemaTablesTest.java b/test/unit/org/apache/cassandra/config/LegacySchemaTablesTest.java deleted file mode 100644 index aabc392..0000000 --- a/test/unit/org/apache/cassandra/config/LegacySchemaTablesTest.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * 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.config; - -import java.util.ArrayList; -import java.util.List; -import java.util.HashMap; -import java.util.HashSet; - -import org.apache.cassandra.SchemaLoader; -import org.apache.cassandra.db.*; -import org.apache.cassandra.db.rows.UnfilteredRowIterators; -import org.apache.cassandra.db.partitions.PartitionUpdate; -import org.apache.cassandra.db.marshal.AsciiType; -import org.apache.cassandra.db.marshal.UTF8Type; -import org.apache.cassandra.exceptions.ConfigurationException; -import org.apache.cassandra.io.compress.*; -import org.apache.cassandra.schema.KeyspaceMetadata; -import org.apache.cassandra.schema.KeyspaceParams; -import org.apache.cassandra.schema.LegacySchemaTables; -import org.apache.cassandra.service.StorageService; -import org.apache.cassandra.thrift.CfDef; -import org.apache.cassandra.thrift.ColumnDef; -import org.apache.cassandra.thrift.IndexType; -import org.apache.cassandra.thrift.ThriftConversion; -import org.apache.cassandra.utils.ByteBufferUtil; -import org.apache.cassandra.utils.FBUtilities; - -import org.junit.BeforeClass; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class LegacySchemaTablesTest -{ - private static final String KEYSPACE1 = "CFMetaDataTest1"; - private static final String CF_STANDARD1 = "Standard1"; - - private static List<ColumnDef> columnDefs = new ArrayList<ColumnDef>(); - - static - { - columnDefs.add(new ColumnDef(ByteBufferUtil.bytes("col1"), AsciiType.class.getCanonicalName()) - .setIndex_name("col1Index") - .setIndex_type(IndexType.KEYS)); - - columnDefs.add(new ColumnDef(ByteBufferUtil.bytes("col2"), UTF8Type.class.getCanonicalName()) - .setIndex_name("col2Index") - .setIndex_type(IndexType.KEYS)); - } - - @BeforeClass - public static void defineSchema() throws ConfigurationException - { - SchemaLoader.prepareServer(); - SchemaLoader.createKeyspace(KEYSPACE1, - KeyspaceParams.simple(1), - SchemaLoader.standardCFMD(KEYSPACE1, CF_STANDARD1)); - } - - @Test - public void testThriftConversion() throws Exception - { - CfDef cfDef = new CfDef().setDefault_validation_class(AsciiType.class.getCanonicalName()) - .setComment("Test comment") - .setColumn_metadata(columnDefs) - .setKeyspace(KEYSPACE1) - .setName(CF_STANDARD1); - - // convert Thrift to CFMetaData - CFMetaData cfMetaData = ThriftConversion.fromThrift(cfDef); - - CfDef thriftCfDef = new CfDef(); - thriftCfDef.keyspace = KEYSPACE1; - thriftCfDef.name = CF_STANDARD1; - thriftCfDef.default_validation_class = cfDef.default_validation_class; - thriftCfDef.comment = cfDef.comment; - thriftCfDef.column_metadata = new ArrayList<>(); - for (ColumnDef columnDef : columnDefs) - { - ColumnDef c = new ColumnDef(); - c.name = ByteBufferUtil.clone(columnDef.name); - c.validation_class = columnDef.getValidation_class(); - c.index_name = columnDef.getIndex_name(); - c.index_type = IndexType.KEYS; - thriftCfDef.column_metadata.add(c); - } - - CfDef converted = ThriftConversion.toThrift(cfMetaData); - - assertEquals(thriftCfDef.keyspace, converted.keyspace); - assertEquals(thriftCfDef.name, converted.name); - assertEquals(thriftCfDef.default_validation_class, converted.default_validation_class); - assertEquals(thriftCfDef.comment, converted.comment); - assertEquals(new HashSet<>(thriftCfDef.column_metadata), new HashSet<>(converted.column_metadata)); - } - - @Test - public void testConversionsInverses() throws Exception - { - for (String keyspaceName : Schema.instance.getNonSystemKeyspaces()) - { - for (ColumnFamilyStore cfs : Keyspace.open(keyspaceName).getColumnFamilyStores()) - { - CFMetaData cfm = cfs.metadata; - if (!cfm.isThriftCompatible()) - continue; - - checkInverses(cfm); - - // Testing with compression to catch #3558 - CFMetaData withCompression = cfm.copy(); - withCompression.compressionParameters(new CompressionParameters(SnappyCompressor.instance, 32768, new HashMap<String, String>())); - checkInverses(withCompression); - } - } - } - - private void checkInverses(CFMetaData cfm) throws Exception - { - DecoratedKey k = StorageService.getPartitioner().decorateKey(ByteBufferUtil.bytes(cfm.ksName)); - KeyspaceMetadata keyspace = Schema.instance.getKSMetaData(cfm.ksName); - - // Test thrift conversion - CFMetaData before = cfm; - CFMetaData after = ThriftConversion.fromThriftForUpdate(ThriftConversion.toThrift(before), before); - assert before.equals(after) : String.format("%n%s%n!=%n%s", before, after); - - // Test schema conversion - Mutation rm = LegacySchemaTables.makeCreateTableMutation(keyspace, cfm, FBUtilities.timestampMicros()); - PartitionUpdate serializedCf = rm.getPartitionUpdate(Schema.instance.getId(SystemKeyspace.NAME, LegacySchemaTables.COLUMNFAMILIES)); - PartitionUpdate serializedCD = rm.getPartitionUpdate(Schema.instance.getId(SystemKeyspace.NAME, LegacySchemaTables.COLUMNS)); - CFMetaData newCfm = LegacySchemaTables.createTableFromTablePartitionAndColumnsPartition(UnfilteredRowIterators.filter(serializedCf.unfilteredIterator(), FBUtilities.nowInSeconds()), - UnfilteredRowIterators.filter(serializedCD.unfilteredIterator(), FBUtilities.nowInSeconds())); - assert cfm.equals(newCfm) : String.format("%n%s%n!=%n%s", cfm, newCfm); - } -} http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java index 4cf5abf..8c24cc5 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java @@ -115,12 +115,12 @@ public class UFTest extends CQLTester Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fSin)).size()); - assertRows(execute("SELECT function_name, language FROM system.schema_functions WHERE keyspace_name=?", KEYSPACE_PER_TEST), + assertRows(execute("SELECT function_name, language FROM system_schema.functions WHERE keyspace_name=?", KEYSPACE_PER_TEST), row(fSinName.name, "java")); dropPerTestKeyspace(); - assertRows(execute("SELECT function_name, language FROM system.schema_functions WHERE keyspace_name=?", KEYSPACE_PER_TEST)); + assertRows(execute("SELECT function_name, language FROM system_schema.functions WHERE keyspace_name=?", KEYSPACE_PER_TEST)); Assert.assertEquals(0, Schema.instance.getFunctions(fSinName).size()); } @@ -558,7 +558,7 @@ public class UFTest extends CQLTester "LANGUAGE JAVA\n" + "AS '" +functionBody + "';"); - assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?", + assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?", KEYSPACE, parseFunctionName(fName).name), row("java", functionBody)); @@ -662,7 +662,7 @@ public class UFTest extends CQLTester FunctionName fNameName = parseFunctionName(fName); - assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?", + assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?", fNameName.keyspace, fNameName.name), row("java", functionBody)); @@ -825,7 +825,7 @@ public class UFTest extends CQLTester FunctionName fNameName = parseFunctionName(fName); - assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?", + assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?", fNameName.keyspace, fNameName.name), row("java", functionBody)); @@ -856,7 +856,7 @@ public class UFTest extends CQLTester FunctionName fNameName = parseFunctionName(fName); - assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?", + assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?", fNameName.keyspace, fNameName.name), row("java", functionBody)); @@ -889,7 +889,7 @@ public class UFTest extends CQLTester FunctionName fNameName = parseFunctionName(fName); - assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?", + assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?", fNameName.keyspace, fNameName.name), row("java", functionBody)); } @@ -1792,7 +1792,7 @@ public class UFTest extends CQLTester FunctionName fNameName = parseFunctionName(fName); - assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?", + assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?", fNameName.keyspace, fNameName.name), row("javascript", functionBody)); http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/test/unit/org/apache/cassandra/cql3/validation/operations/AlterTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/AlterTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/AlterTest.java index 05f6c35..66b6b33 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/operations/AlterTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/operations/AlterTest.java @@ -17,6 +17,8 @@ */ package org.apache.cassandra.cql3.validation.operations; +import com.google.common.collect.ImmutableMap; + import org.apache.cassandra.cql3.CQLTester; import org.apache.cassandra.db.ColumnFamilyStore; import org.apache.cassandra.db.Keyspace; @@ -129,7 +131,7 @@ public class AlterTest extends CQLTester execute("CREATE KEYSPACE ks1 WITH replication={ 'class' : 'SimpleStrategy', 'replication_factor' : 1 }"); execute("CREATE KEYSPACE ks2 WITH replication={ 'class' : 'SimpleStrategy', 'replication_factor' : 1 } AND durable_writes=false"); - assertRows(execute("SELECT keyspace_name, durable_writes FROM system.schema_keyspaces"), + assertRows(execute("SELECT keyspace_name, durable_writes FROM system_schema.keyspaces"), row("ks1", true), row(KEYSPACE, true), row(KEYSPACE_PER_TEST, true), @@ -138,18 +140,22 @@ public class AlterTest extends CQLTester execute("ALTER KEYSPACE ks1 WITH replication = { 'class' : 'NetworkTopologyStrategy', 'dc1' : 1 } AND durable_writes=False"); execute("ALTER KEYSPACE ks2 WITH durable_writes=true"); - assertRows(execute("SELECT keyspace_name, durable_writes, strategy_class FROM system.schema_keyspaces"), - row("ks1", false, "org.apache.cassandra.locator.NetworkTopologyStrategy"), - row(KEYSPACE, true, "org.apache.cassandra.locator.SimpleStrategy"), - row(KEYSPACE_PER_TEST, true, "org.apache.cassandra.locator.SimpleStrategy"), - row("ks2", true, "org.apache.cassandra.locator.SimpleStrategy")); + assertRows(execute("SELECT keyspace_name, durable_writes, replication FROM system_schema.keyspaces"), + row("ks1", false, ImmutableMap.of("class", "org.apache.cassandra.locator.NetworkTopologyStrategy", + "dc1", "1")), + row(KEYSPACE, true, ImmutableMap.of("class", "org.apache.cassandra.locator.SimpleStrategy", + "replication_factor", "1")), + row(KEYSPACE_PER_TEST, true, ImmutableMap.of("class", "org.apache.cassandra.locator.SimpleStrategy", + "replication_factor", "1")), + row("ks2", true, ImmutableMap.of("class", "org.apache.cassandra.locator.SimpleStrategy", + "replication_factor", "1"))); execute("USE ks1"); assertInvalidThrow(ConfigurationException.class, "CREATE TABLE cf1 (a int PRIMARY KEY, b int) WITH compaction = { 'min_threshold' : 4 }"); execute("CREATE TABLE cf1 (a int PRIMARY KEY, b int) WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'min_threshold' : 7 }"); - assertRows(execute("SELECT columnfamily_name, min_compaction_threshold FROM system.schema_columnfamilies WHERE keyspace_name='ks1'"), + assertRows(execute("SELECT table_name, min_compaction_threshold FROM system_schema.tables WHERE keyspace_name='ks1'"), row("cf1", 7)); // clean-up @@ -195,8 +201,8 @@ public class AlterTest extends CQLTester // tests CASSANDRA-9565 public void testDoubleWith() throws Throwable { - String[] stmts = new String[] { "ALTER KEYSPACE WITH WITH DURABLE_WRITES = true", - "ALTER KEYSPACE ks WITH WITH DURABLE_WRITES = true" }; + String[] stmts = { "ALTER KEYSPACE WITH WITH DURABLE_WRITES = true", + "ALTER KEYSPACE ks WITH WITH DURABLE_WRITES = true" }; for (String stmt : stmts) { assertInvalidSyntaxMessage("no viable alternative at input 'WITH'", stmt); http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java index 055c9d9..19f85bf 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java @@ -798,19 +798,19 @@ public class InsertUpdateIfConditionTest extends CQLTester // create and confirm schemaChange("CREATE TABLE IF NOT EXISTS " + fullTableName + " (id text PRIMARY KEY, value1 blob) with comment = 'foo'"); - assertRows(execute("select comment from system.schema_columnfamilies where keyspace_name = ? and columnfamily_name = ?", KEYSPACE, tableName), + assertRows(execute("select comment from system_schema.tables where keyspace_name = ? and table_name = ?", KEYSPACE, tableName), row("foo")); // unsuccessful create since it's already there, confirm settings don't change schemaChange("CREATE TABLE IF NOT EXISTS " + fullTableName + " (id text PRIMARY KEY, value2 blob)with comment = 'bar'"); - assertRows(execute("select comment from system.schema_columnfamilies where keyspace_name = ? and columnfamily_name = ?", KEYSPACE, tableName), + assertRows(execute("select comment from system_schema.tables where keyspace_name = ? and table_name = ?", KEYSPACE, tableName), row("foo")); // drop and confirm schemaChange("DROP TABLE IF EXISTS " + fullTableName); - assertEmpty(execute("select * from system.schema_columnfamilies where keyspace_name = ? and columnfamily_name = ?", KEYSPACE, tableName)); + assertEmpty(execute("select * from system_schema.tables where keyspace_name = ? and table_name = ?", KEYSPACE, tableName)); } /** http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/test/unit/org/apache/cassandra/schema/DefsTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/schema/DefsTest.java b/test/unit/org/apache/cassandra/schema/DefsTest.java index dcc4c51..cf49253 100644 --- a/test/unit/org/apache/cassandra/schema/DefsTest.java +++ b/test/unit/org/apache/cassandra/schema/DefsTest.java @@ -515,7 +515,7 @@ public class DefsTest public void testDropIndex() throws ConfigurationException { // persist keyspace definition in the system keyspace - LegacySchemaTables.makeCreateKeyspaceMutation(Schema.instance.getKSMetaData(KEYSPACE6), FBUtilities.timestampMicros()).applyUnsafe(); + SchemaKeyspace.makeCreateKeyspaceMutation(Schema.instance.getKSMetaData(KEYSPACE6), FBUtilities.timestampMicros()).applyUnsafe(); ColumnFamilyStore cfs = Keyspace.open(KEYSPACE6).getColumnFamilyStore(TABLE1i); // insert some data. save the sstable descriptor so we can make sure it's marked for delete after the drop http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java b/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java new file mode 100644 index 0000000..b4149a0 --- /dev/null +++ b/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java @@ -0,0 +1,549 @@ +/* + * 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.schema; + +import java.nio.ByteBuffer; +import java.util.*; +import java.util.stream.Collectors; + +import com.google.common.collect.ImmutableList; +import org.junit.Test; + +import org.apache.cassandra.SchemaLoader; +import org.apache.cassandra.cache.CachingOptions; +import org.apache.cassandra.config.*; +import org.apache.cassandra.cql3.ColumnIdentifier; +import org.apache.cassandra.cql3.functions.*; +import org.apache.cassandra.db.*; +import org.apache.cassandra.db.compaction.LeveledCompactionStrategy; +import org.apache.cassandra.db.marshal.*; + +import static java.lang.String.format; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; +import static org.apache.cassandra.cql3.QueryProcessor.executeOnceInternal; +import static org.apache.cassandra.utils.ByteBufferUtil.bytes; +import static org.apache.cassandra.utils.FBUtilities.json; + +@SuppressWarnings("deprecation") +public class LegacySchemaMigratorTest +{ + private static final long TIMESTAMP = 1435908994000000L; + + private static final String KEYSPACE_PREFIX = "LegacySchemaMigratorTest"; + + /* + * 1. Write a variety of different keyspaces/tables/types/function in the legacy manner, using legacy schema tables + * 2. Run the migrator + * 3. Read all the keyspaces from the new schema tables + * 4. Make sure that we've read *exactly* the same set of keyspaces/tables/types/functions + * 5. Validate that the legacy schema tables are now empty + */ + @Test + public void testMigrate() + { + List<KeyspaceMetadata> expected = keyspaceToMigrate(); + expected.sort((k1, k2) -> k1.name.compareTo(k2.name)); + + // write the keyspaces into the legacy tables + expected.forEach(LegacySchemaMigratorTest::legacySerializeKeyspace); + + // run the migration + LegacySchemaMigrator.migrate(); + + // read back all the metadata from the new schema tables + List<KeyspaceMetadata> actual = SchemaKeyspace.readSchemaFromSystemTables(); + actual.sort((k1, k2) -> k1.name.compareTo(k2.name)); + + // make sure that we've read *exactly* the same set of keyspaces/tables/types/functions + assertEquals(expected, actual); + + // need to load back CFMetaData of those tables (CFS instances will still be loaded) + loadLegacySchemaTables(); + + // verify that nothing's left in the old schema tables + for (CFMetaData table : LegacySchemaMigrator.LegacySchemaTables) + { + String query = format("SELECT * FROM %s.%s", SystemKeyspace.NAME, table.cfName); + //noinspection ConstantConditions + assertTrue(executeOnceInternal(query).isEmpty()); + } + } + + private static void loadLegacySchemaTables() + { + KeyspaceMetadata systemKeyspace = Schema.instance.getKSMetaData(SystemKeyspace.NAME); + + Tables systemTables = systemKeyspace.tables; + for (CFMetaData table : LegacySchemaMigrator.LegacySchemaTables) + systemTables = systemTables.with(table); + + LegacySchemaMigrator.LegacySchemaTables.forEach(Schema.instance::load); + + Schema.instance.setKeyspaceMetadata(systemKeyspace.withSwapped(systemTables)); + } + + private static List<KeyspaceMetadata> keyspaceToMigrate() + { + List<KeyspaceMetadata> keyspaces = new ArrayList<>(); + + // A whole bucket of shorthand + String ks1 = KEYSPACE_PREFIX + "Keyspace1"; + String ks2 = KEYSPACE_PREFIX + "Keyspace2"; + String ks3 = KEYSPACE_PREFIX + "Keyspace3"; + String ks4 = KEYSPACE_PREFIX + "Keyspace4"; + String ks5 = KEYSPACE_PREFIX + "Keyspace5"; + String ks6 = KEYSPACE_PREFIX + "Keyspace6"; + String ks_rcs = KEYSPACE_PREFIX + "RowCacheSpace"; + String ks_nocommit = KEYSPACE_PREFIX + "NoCommitlogSpace"; + String ks_prsi = KEYSPACE_PREFIX + "PerRowSecondaryIndex"; + String ks_cql = KEYSPACE_PREFIX + "cql_keyspace"; + + // Make it easy to test compaction + Map<String, String> compactionOptions = new HashMap<>(); + compactionOptions.put("tombstone_compaction_interval", "1"); + Map<String, String> leveledOptions = new HashMap<>(); + leveledOptions.put("sstable_size_in_mb", "1"); + + keyspaces.add(KeyspaceMetadata.create(ks1, + KeyspaceParams.simple(1), + Tables.of(SchemaLoader.standardCFMD(ks1, "Standard1") + .compactionStrategyOptions(compactionOptions), + SchemaLoader.standardCFMD(ks1, "StandardGCGS0").gcGraceSeconds(0), + SchemaLoader.standardCFMD(ks1, "StandardLong1"), + SchemaLoader.superCFMD(ks1, "Super1", LongType.instance), + SchemaLoader.superCFMD(ks1, "Super2", UTF8Type.instance), + SchemaLoader.superCFMD(ks1, "Super5", BytesType.instance), + SchemaLoader.superCFMD(ks1, "Super6", LexicalUUIDType.instance, UTF8Type.instance), + SchemaLoader.keysIndexCFMD(ks1, "Indexed1", true), + SchemaLoader.keysIndexCFMD(ks1, "Indexed2", false), + SchemaLoader.superCFMD(ks1, "SuperDirectGC", BytesType.instance) + .gcGraceSeconds(0), + SchemaLoader.jdbcCFMD(ks1, "JdbcUtf8", UTF8Type.instance) + .addColumnDefinition(SchemaLoader.utf8Column(ks1, "JdbcUtf8")), + SchemaLoader.jdbcCFMD(ks1, "JdbcLong", LongType.instance), + SchemaLoader.jdbcCFMD(ks1, "JdbcBytes", BytesType.instance), + SchemaLoader.jdbcCFMD(ks1, "JdbcAscii", AsciiType.instance), + SchemaLoader.standardCFMD(ks1, "StandardLeveled") + .compactionStrategyClass(LeveledCompactionStrategy.class) + .compactionStrategyOptions(leveledOptions), + SchemaLoader.standardCFMD(ks1, "legacyleveled") + .compactionStrategyClass(LeveledCompactionStrategy.class) + .compactionStrategyOptions(leveledOptions), + SchemaLoader.standardCFMD(ks1, "StandardLowIndexInterval") + .minIndexInterval(8) + .maxIndexInterval(256) + .caching(CachingOptions.NONE)))); + + // Keyspace 2 + keyspaces.add(KeyspaceMetadata.create(ks2, + KeyspaceParams.simple(1), + Tables.of(SchemaLoader.standardCFMD(ks2, "Standard1"), + SchemaLoader.superCFMD(ks2, "Super3", BytesType.instance), + SchemaLoader.superCFMD(ks2, "Super4", TimeUUIDType.instance), + SchemaLoader.keysIndexCFMD(ks2, "Indexed1", true), + SchemaLoader.compositeIndexCFMD(ks2, "Indexed2", true), + SchemaLoader.compositeIndexCFMD(ks2, "Indexed3", true) + .gcGraceSeconds(0)))); + + // Keyspace 3 + keyspaces.add(KeyspaceMetadata.create(ks3, + KeyspaceParams.simple(5), + Tables.of(SchemaLoader.standardCFMD(ks3, "Standard1"), + SchemaLoader.keysIndexCFMD(ks3, "Indexed1", true)))); + + // Keyspace 4 + keyspaces.add(KeyspaceMetadata.create(ks4, + KeyspaceParams.simple(3), + Tables.of(SchemaLoader.standardCFMD(ks4, "Standard1"), + SchemaLoader.superCFMD(ks4, "Super3", BytesType.instance), + SchemaLoader.superCFMD(ks4, "Super4", TimeUUIDType.instance), + SchemaLoader.superCFMD(ks4, "Super5", TimeUUIDType.instance, BytesType.instance)))); + + // Keyspace 5 + keyspaces.add(KeyspaceMetadata.create(ks5, + KeyspaceParams.simple(2), + Tables.of(SchemaLoader.standardCFMD(ks5, "Standard1")))); + // Keyspace 6 + keyspaces.add(KeyspaceMetadata.create(ks6, + KeyspaceParams.simple(1), + Tables.of(SchemaLoader.keysIndexCFMD(ks6, "Indexed1", true)))); + + // RowCacheSpace + keyspaces.add(KeyspaceMetadata.create(ks_rcs, + KeyspaceParams.simple(1), + Tables.of(SchemaLoader.standardCFMD(ks_rcs, "CFWithoutCache") + .caching(CachingOptions.NONE), + SchemaLoader.standardCFMD(ks_rcs, "CachedCF") + .caching(CachingOptions.ALL), + SchemaLoader.standardCFMD(ks_rcs, "CachedIntCF") + .caching(new CachingOptions(new CachingOptions.KeyCache(CachingOptions.KeyCache.Type.ALL), + new CachingOptions.RowCache(CachingOptions.RowCache.Type.HEAD, 100)))))); + + + keyspaces.add(KeyspaceMetadata.create(ks_nocommit, + KeyspaceParams.simpleTransient(1), + Tables.of(SchemaLoader.standardCFMD(ks_nocommit, "Standard1")))); + + // PerRowSecondaryIndexTest + keyspaces.add(KeyspaceMetadata.create(ks_prsi, + KeyspaceParams.simple(1), + Tables.of(SchemaLoader.perRowIndexedCFMD(ks_prsi, "Indexed1")))); + + // CQLKeyspace + keyspaces.add(KeyspaceMetadata.create(ks_cql, + KeyspaceParams.simple(1), + Tables.of(CFMetaData.compile("CREATE TABLE table1 (" + + "k int PRIMARY KEY," + + "v1 text," + + "v2 int" + + ')', ks_cql), + + CFMetaData.compile("CREATE TABLE table2 (" + + "k text," + + "c text," + + "v text," + + "PRIMARY KEY (k, c))", ks_cql), + + CFMetaData.compile("CREATE TABLE foo (" + + "bar text, " + + "baz text, " + + "qux text, " + + "PRIMARY KEY(bar, baz) ) " + + "WITH COMPACT STORAGE", ks_cql), + + CFMetaData.compile("CREATE TABLE foofoo (" + + "bar text, " + + "baz text, " + + "qux text, " + + "quz text, " + + "foo text, " + + "PRIMARY KEY((bar, baz), qux, quz) ) " + + "WITH COMPACT STORAGE", ks_cql)))); + + keyspaces.add(keyspaceWithTriggers()); + keyspaces.add(keyspaceWithUDTs()); + keyspaces.add(keyspaceWithUDFs()); + keyspaces.add(keyspaceWithUDAs()); + + return keyspaces; + } + + private static KeyspaceMetadata keyspaceWithTriggers() + { + String keyspace = KEYSPACE_PREFIX + "Triggers"; + + CFMetaData table = SchemaLoader.standardCFMD(keyspace, "WithTriggers"); + for (int i = 0; i < 10; i++) + table.addTriggerDefinition(new TriggerDefinition("trigger" + i, "DummyTrigger" + i)); + + return KeyspaceMetadata.create(keyspace, KeyspaceParams.simple(1), Tables.of(table)); + } + + private static KeyspaceMetadata keyspaceWithUDTs() + { + String keyspace = KEYSPACE_PREFIX + "UDTs"; + + UserType udt1 = new UserType(keyspace, + bytes("udt1"), + new ArrayList<ByteBuffer>() {{ add(bytes("col1")); add(bytes("col2")); }}, + new ArrayList<AbstractType<?>>() {{ add(UTF8Type.instance); add(Int32Type.instance); }}); + + UserType udt2 = new UserType(keyspace, + bytes("udt2"), + new ArrayList<ByteBuffer>() {{ add(bytes("col3")); add(bytes("col4")); }}, + new ArrayList<AbstractType<?>>() {{ add(BytesType.instance); add(BooleanType.instance); }}); + + UserType udt3 = new UserType(keyspace, + bytes("udt3"), + new ArrayList<ByteBuffer>() {{ add(bytes("col5")); }}, + new ArrayList<AbstractType<?>>() {{ add(AsciiType.instance); }}); + + return KeyspaceMetadata.create(keyspace, + KeyspaceParams.simple(1), + Tables.none(), + Types.of(udt1, udt2, udt3), + Functions.none()); + } + + private static KeyspaceMetadata keyspaceWithUDFs() + { + String keyspace = KEYSPACE_PREFIX + "UDFs"; + + + UDFunction udf1 = UDFunction.create(new FunctionName(keyspace, "udf"), + ImmutableList.of(new ColumnIdentifier("col1", false), new ColumnIdentifier("col2", false)), + ImmutableList.of(BytesType.instance, Int32Type.instance), + LongType.instance, + false, + "java", + "return 42L;"); + + // an overload with the same name, not a typo + UDFunction udf2 = UDFunction.create(new FunctionName(keyspace, "udf"), + ImmutableList.of(new ColumnIdentifier("col3", false), new ColumnIdentifier("col4", false)), + ImmutableList.of(AsciiType.instance, LongType.instance), + Int32Type.instance, + true, + "java", + "return 42;"); + + UDFunction udf3 = UDFunction.create(new FunctionName(keyspace, "udf3"), + ImmutableList.of(new ColumnIdentifier("col4", false)), + ImmutableList.of(UTF8Type.instance), + BooleanType.instance, + false, + "java", + "return true;"); + + return KeyspaceMetadata.create(keyspace, + KeyspaceParams.simple(1), + Tables.none(), + Types.none(), + Functions.of(udf1, udf2, udf3)); + } + + // TODO: add representative UDAs set + private static KeyspaceMetadata keyspaceWithUDAs() + { + String keyspace = KEYSPACE_PREFIX + "UDAs"; + + return KeyspaceMetadata.create(keyspace, + KeyspaceParams.simple(1), + Tables.none(), + Types.none(), + Functions.of()); + } + + /* + * Serializing keyspaces + */ + + private static void legacySerializeKeyspace(KeyspaceMetadata keyspace) + { + makeLegacyCreateKeyspaceMutation(keyspace, TIMESTAMP).apply(); + } + + private static Mutation makeLegacyCreateKeyspaceMutation(KeyspaceMetadata keyspace, long timestamp) + { + // Note that because Keyspaces is a COMPACT TABLE, we're really only setting static columns internally and shouldn't set any clustering. + RowUpdateBuilder adder = new RowUpdateBuilder(SystemKeyspace.LegacyKeyspaces, timestamp, keyspace.name); + + adder.add("durable_writes", keyspace.params.durableWrites) + .add("strategy_class", keyspace.params.replication.klass.getName()) + .add("strategy_options", json(keyspace.params.replication.options)); + + Mutation mutation = adder.build(); + + keyspace.tables.forEach(table -> addTableToSchemaMutation(table, timestamp, true, mutation)); + keyspace.types.forEach(type -> addTypeToSchemaMutation(type, timestamp, mutation)); + keyspace.functions.udfs().forEach(udf -> addFunctionToSchemaMutation(udf, timestamp, mutation)); + keyspace.functions.udas().forEach(uda -> addAggregateToSchemaMutation(uda, timestamp, mutation)); + + return mutation; + } + + /* + * Serializing tables + */ + + private static void addTableToSchemaMutation(CFMetaData table, long timestamp, boolean withColumnsAndTriggers, Mutation mutation) + { + // For property that can be null (and can be changed), we insert tombstones, to make sure + // we don't keep a property the user has removed + RowUpdateBuilder adder = new RowUpdateBuilder(SystemKeyspace.LegacyColumnfamilies, timestamp, mutation) + .clustering(table.cfName); + + adder.add("cf_id", table.cfId) + .add("type", table.isSuper() ? "Super" : "Standard"); + + if (table.isSuper()) + { + adder.add("comparator", table.comparator.subtype(0).toString()) + .add("subcomparator", ((MapType)table.compactValueColumn().type).getKeysType().toString()); + } + else + { + adder.add("comparator", LegacyLayout.makeLegacyComparator(table).toString()); + } + + adder.add("bloom_filter_fp_chance", table.getBloomFilterFpChance()) + .add("caching", table.getCaching().toString()) + .add("comment", table.getComment()) + .add("compaction_strategy_class", table.compactionStrategyClass.getName()) + .add("compaction_strategy_options", json(table.compactionStrategyOptions)) + .add("compression_parameters", json(table.compressionParameters.asThriftOptions())) + .add("default_time_to_live", table.getDefaultTimeToLive()) + .add("gc_grace_seconds", table.getGcGraceSeconds()) + .add("key_validator", table.getKeyValidator().toString()) + .add("local_read_repair_chance", table.getDcLocalReadRepairChance()) + .add("max_compaction_threshold", table.getMaxCompactionThreshold()) + .add("max_index_interval", table.getMaxIndexInterval()) + .add("memtable_flush_period_in_ms", table.getMemtableFlushPeriod()) + .add("min_compaction_threshold", table.getMinCompactionThreshold()) + .add("min_index_interval", table.getMinIndexInterval()) + .add("read_repair_chance", table.getReadRepairChance()) + .add("speculative_retry", table.getSpeculativeRetry().toString()); + + for (Map.Entry<ColumnIdentifier, CFMetaData.DroppedColumn> entry : table.getDroppedColumns().entrySet()) + { + String name = entry.getKey().toString(); + CFMetaData.DroppedColumn column = entry.getValue(); + adder.addMapEntry("dropped_columns", name, column.droppedTime); + if (column.type != null) + adder.addMapEntry("dropped_columns_types", name, column.type.toString()); + } + + adder.add("is_dense", table.isDense()); + + adder.add("default_validator", table.makeLegacyDefaultValidator().toString()); + + if (withColumnsAndTriggers) + { + for (ColumnDefinition column : table.allColumns()) + addColumnToSchemaMutation(table, column, timestamp, mutation); + + for (TriggerDefinition trigger : table.getTriggers().values()) + addTriggerToSchemaMutation(table, trigger, timestamp, mutation); + } + + adder.build(); + } + + private static void addColumnToSchemaMutation(CFMetaData table, ColumnDefinition column, long timestamp, Mutation mutation) + { + RowUpdateBuilder adder = new RowUpdateBuilder(SystemKeyspace.LegacyColumns, timestamp, mutation) + .clustering(table.cfName, column.name.toString()); + + adder.add("validator", column.type.toString()) + .add("type", serializeKind(column.kind, table.isDense())) + .add("component_index", column.isOnAllComponents() ? null : column.position()) + .add("index_name", column.getIndexName()) + .add("index_type", column.getIndexType() == null ? null : column.getIndexType().toString()) + .add("index_options", json(column.getIndexOptions())) + .build(); + } + + private static String serializeKind(ColumnDefinition.Kind kind, boolean isDense) + { + // For backward compatibility, we special case CLUSTERING_COLUMN and the case where the table is dense. + if (kind == ColumnDefinition.Kind.CLUSTERING_COLUMN) + return "clustering_key"; + + if (kind == ColumnDefinition.Kind.REGULAR && isDense) + return "compact_value"; + + return kind.toString().toLowerCase(); + } + + private static void addTriggerToSchemaMutation(CFMetaData table, TriggerDefinition trigger, long timestamp, Mutation mutation) + { + new RowUpdateBuilder(SystemKeyspace.LegacyTriggers, timestamp, mutation) + .clustering(table.cfName, trigger.name) + .addMapEntry("trigger_options", "class", trigger.classOption) + .build(); + } + + /* + * Serializing types + */ + + private static void addTypeToSchemaMutation(UserType type, long timestamp, Mutation mutation) + { + RowUpdateBuilder adder = new RowUpdateBuilder(SystemKeyspace.LegacyUsertypes, timestamp, mutation) + .clustering(type.getNameAsString()); + + adder.resetCollection("field_names") + .resetCollection("field_types"); + + for (int i = 0; i < type.size(); i++) + { + adder.addListEntry("field_names", type.fieldName(i)) + .addListEntry("field_types", type.fieldType(i).toString()); + } + + adder.build(); + } + + /* + * Serializing functions + */ + + private static void addFunctionToSchemaMutation(UDFunction function, long timestamp, Mutation mutation) + { + RowUpdateBuilder adder = new RowUpdateBuilder(SystemKeyspace.LegacyFunctions, timestamp, mutation) + .clustering(function.name().name, functionSignatureWithTypes(function)); + + adder.add("body", function.body()) + .add("language", function.language()) + .add("return_type", function.returnType().toString()) + .add("called_on_null_input", function.isCalledOnNullInput()); + + adder.resetCollection("argument_names") + .resetCollection("argument_types"); + + for (int i = 0; i < function.argNames().size(); i++) + { + adder.addListEntry("argument_names", function.argNames().get(i).bytes) + .addListEntry("argument_types", function.argTypes().get(i).toString()); + } + + adder.build(); + } + + /* + * Serializing aggregates + */ + + private static void addAggregateToSchemaMutation(UDAggregate aggregate, long timestamp, Mutation mutation) + { + RowUpdateBuilder adder = new RowUpdateBuilder(SystemKeyspace.LegacyAggregates, timestamp, mutation) + .clustering(aggregate.name().name, functionSignatureWithTypes(aggregate)); + + adder.resetCollection("argument_types"); + + adder.add("return_type", aggregate.returnType().toString()) + .add("state_func", aggregate.stateFunction().name().toString()); + + if (aggregate.stateType() != null) + adder.add("state_type", aggregate.stateType().toString()); + if (aggregate.finalFunction() != null) + adder.add("final_func", aggregate.finalFunction().name().toString()); + if (aggregate.initialCondition() != null) + adder.add("initcond", aggregate.initialCondition()); + + for (AbstractType<?> argType : aggregate.argTypes()) + adder.addListEntry("argument_types", argType.toString()); + + adder.build(); + } + + // We allow method overloads, so a function is not uniquely identified by its name only, but + // also by its argument types. To distinguish overloads of given function name in the schema + // we use a "signature" which is just a list of it's CQL argument types. + public static ByteBuffer functionSignatureWithTypes(AbstractFunction fun) + { + List<String> arguments = + fun.argTypes() + .stream() + .map(argType -> argType.asCQL3Type().toString()) + .collect(Collectors.toList()); + + return ListType.getInstance(UTF8Type.instance, false).decompose(arguments); + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java b/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java new file mode 100644 index 0000000..715799b --- /dev/null +++ b/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java @@ -0,0 +1,153 @@ +/* + * 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.schema; + +import java.util.ArrayList; +import java.util.List; +import java.util.HashMap; +import java.util.HashSet; + +import org.apache.cassandra.SchemaLoader; +import org.apache.cassandra.config.CFMetaData; +import org.apache.cassandra.config.Schema; +import org.apache.cassandra.db.*; +import org.apache.cassandra.db.rows.UnfilteredRowIterators; +import org.apache.cassandra.db.partitions.PartitionUpdate; +import org.apache.cassandra.db.marshal.AsciiType; +import org.apache.cassandra.db.marshal.UTF8Type; +import org.apache.cassandra.exceptions.ConfigurationException; +import org.apache.cassandra.io.compress.*; +import org.apache.cassandra.schema.KeyspaceMetadata; +import org.apache.cassandra.schema.KeyspaceParams; +import org.apache.cassandra.schema.SchemaKeyspace; +import org.apache.cassandra.thrift.CfDef; +import org.apache.cassandra.thrift.ColumnDef; +import org.apache.cassandra.thrift.IndexType; +import org.apache.cassandra.thrift.ThriftConversion; +import org.apache.cassandra.utils.ByteBufferUtil; +import org.apache.cassandra.utils.FBUtilities; + +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class SchemaKeyspaceTest +{ + private static final String KEYSPACE1 = "CFMetaDataTest1"; + private static final String CF_STANDARD1 = "Standard1"; + + private static final List<ColumnDef> columnDefs = new ArrayList<>(); + + static + { + columnDefs.add(new ColumnDef(ByteBufferUtil.bytes("col1"), AsciiType.class.getCanonicalName()) + .setIndex_name("col1Index") + .setIndex_type(IndexType.KEYS)); + + columnDefs.add(new ColumnDef(ByteBufferUtil.bytes("col2"), UTF8Type.class.getCanonicalName()) + .setIndex_name("col2Index") + .setIndex_type(IndexType.KEYS)); + } + + @BeforeClass + public static void defineSchema() throws ConfigurationException + { + SchemaLoader.prepareServer(); + SchemaLoader.createKeyspace(KEYSPACE1, + KeyspaceParams.simple(1), + SchemaLoader.standardCFMD(KEYSPACE1, CF_STANDARD1)); + } + + @Test + public void testThriftConversion() throws Exception + { + CfDef cfDef = new CfDef().setDefault_validation_class(AsciiType.class.getCanonicalName()) + .setComment("Test comment") + .setColumn_metadata(columnDefs) + .setKeyspace(KEYSPACE1) + .setName(CF_STANDARD1); + + // convert Thrift to CFMetaData + CFMetaData cfMetaData = ThriftConversion.fromThrift(cfDef); + + CfDef thriftCfDef = new CfDef(); + thriftCfDef.keyspace = KEYSPACE1; + thriftCfDef.name = CF_STANDARD1; + thriftCfDef.default_validation_class = cfDef.default_validation_class; + thriftCfDef.comment = cfDef.comment; + thriftCfDef.column_metadata = new ArrayList<>(); + for (ColumnDef columnDef : columnDefs) + { + ColumnDef c = new ColumnDef(); + c.name = ByteBufferUtil.clone(columnDef.name); + c.validation_class = columnDef.getValidation_class(); + c.index_name = columnDef.getIndex_name(); + c.index_type = IndexType.KEYS; + thriftCfDef.column_metadata.add(c); + } + + CfDef converted = ThriftConversion.toThrift(cfMetaData); + + assertEquals(thriftCfDef.keyspace, converted.keyspace); + assertEquals(thriftCfDef.name, converted.name); + assertEquals(thriftCfDef.default_validation_class, converted.default_validation_class); + assertEquals(thriftCfDef.comment, converted.comment); + assertEquals(new HashSet<>(thriftCfDef.column_metadata), new HashSet<>(converted.column_metadata)); + } + + @Test + public void testConversionsInverses() throws Exception + { + for (String keyspaceName : Schema.instance.getNonSystemKeyspaces()) + { + for (ColumnFamilyStore cfs : Keyspace.open(keyspaceName).getColumnFamilyStores()) + { + CFMetaData cfm = cfs.metadata; + if (!cfm.isThriftCompatible()) + continue; + + checkInverses(cfm); + + // Testing with compression to catch #3558 + CFMetaData withCompression = cfm.copy(); + withCompression.compressionParameters(new CompressionParameters(SnappyCompressor.instance, 32768, new HashMap<>())); + checkInverses(withCompression); + } + } + } + + private static void checkInverses(CFMetaData cfm) throws Exception + { + KeyspaceMetadata keyspace = Schema.instance.getKSMetaData(cfm.ksName); + + // Test thrift conversion + CFMetaData before = cfm; + CFMetaData after = ThriftConversion.fromThriftForUpdate(ThriftConversion.toThrift(before), before); + assert before.equals(after) : String.format("%n%s%n!=%n%s", before, after); + + // Test schema conversion + Mutation rm = SchemaKeyspace.makeCreateTableMutation(keyspace, cfm, FBUtilities.timestampMicros()); + PartitionUpdate serializedCf = rm.getPartitionUpdate(Schema.instance.getId(SystemKeyspace.NAME, SchemaKeyspace.TABLES)); + PartitionUpdate serializedCD = rm.getPartitionUpdate(Schema.instance.getId(SystemKeyspace.NAME, SchemaKeyspace.COLUMNS)); + CFMetaData newCfm = SchemaKeyspace.createTableFromTablePartitionAndColumnsPartition(UnfilteredRowIterators.filter(serializedCf.unfilteredIterator(), FBUtilities.nowInSeconds()), + UnfilteredRowIterators.filter(serializedCD.unfilteredIterator(), FBUtilities.nowInSeconds())); + assert cfm.equals(newCfm) : String.format("%n%s%n!=%n%s", cfm, newCfm); + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java b/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java index 0819097..e716eda 100644 --- a/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java +++ b/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java @@ -38,7 +38,6 @@ import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.schema.KeyspaceMetadata; import org.apache.cassandra.config.Schema; import org.apache.cassandra.db.Keyspace; -import org.apache.cassandra.db.SystemKeyspace; import org.apache.cassandra.db.WindowsFailedSnapshotTracker; import org.apache.cassandra.dht.Murmur3Partitioner; import org.apache.cassandra.dht.Murmur3Partitioner.LongToken; @@ -50,7 +49,7 @@ import org.apache.cassandra.locator.IEndpointSnitch; import org.apache.cassandra.locator.PropertyFileSnitch; import org.apache.cassandra.locator.TokenMetadata; import org.apache.cassandra.schema.KeyspaceParams; -import org.apache.cassandra.schema.LegacySchemaTables; +import org.apache.cassandra.schema.SchemaKeyspace; import org.apache.cassandra.utils.FBUtilities; import static org.junit.Assert.assertEquals; @@ -173,7 +172,7 @@ public class StorageServiceServerTest public void testColumnFamilySnapshot() throws IOException { // no need to insert extra data, even an "empty" database will have a little information in the system keyspace - StorageService.instance.takeColumnFamilySnapshot(SystemKeyspace.NAME, LegacySchemaTables.KEYSPACES, "cf_snapshot"); + StorageService.instance.takeColumnFamilySnapshot(SchemaKeyspace.NAME, SchemaKeyspace.KEYSPACES, "cf_snapshot"); } @Test