/* * * 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.cql; import org.apache.cassandra.config.CFMetaData; import org.apache.cassandra.config.ColumnDefinition; import org.apache.cassandra.config.ConfigurationException; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.db.marshal.TypeParser; import org.apache.cassandra.db.migration.avro.CfDef; import org.apache.cassandra.db.migration.avro.ColumnDef; import org.apache.cassandra.thrift.InvalidRequestException; import java.nio.ByteBuffer; public class AlterTableStatement { public static enum OperationType { ADD, ALTER, DROP } public final OperationType oType; public final String columnFamily, columnName, validator; public AlterTableStatement(String columnFamily, OperationType type, String columnName) { this(columnFamily, type, columnName, null); } public AlterTableStatement(String columnFamily, OperationType type, String columnName, String validator) { this.columnFamily = columnFamily; this.oType = type; this.columnName = columnName; this.validator = CreateColumnFamilyStatement.comparators.get(validator); // used only for ADD/ALTER commands } public CfDef getCfDef(String keyspace) throws ConfigurationException, InvalidRequestException { CFMetaData meta = DatabaseDescriptor.getCFMetaData(keyspace, columnFamily); CfDef cfDef = CFMetaData.convertToAvro(meta); ByteBuffer columnName = meta.comparator.fromString(this.columnName); switch (oType) { case ADD: if (cfDef.key_alias != null && cfDef.key_alias.equals(columnName)) throw new InvalidRequestException("Invalid column name: " + this.columnName + ", because it equals to key_alias."); cfDef.column_metadata.add(new ColumnDefinition(columnName, TypeParser.parse(validator), null, null).deflate()); break; case ALTER: ColumnDefinition column = meta.getColumnDefinition(columnName); if (column == null) throw new InvalidRequestException(String.format("Column '%s' was not found in CF '%s'", this.columnName, columnFamily)); column.setValidator(TypeParser.parse(validator)); cfDef.column_metadata.add(column.deflate()); break; case DROP: ColumnDef toDelete = null; for (ColumnDef columnDef : cfDef.column_metadata) { if (columnDef.name.equals(columnName)) { toDelete = columnDef; } } if (toDelete == null) throw new InvalidRequestException(String.format("Column '%s' was not found in CF '%s'", this.columnName, columnFamily)); // it is impossible to use ColumnDefinition.deflate() in remove() method // it will throw java.lang.ClassCastException: java.lang.String cannot be cast to org.apache.avro.util.Utf8 // some where deep inside of Avro cfDef.column_metadata.remove(toDelete); break; } return cfDef; } public String toString() { return String.format("AlterTableStatement(cf=%s, type=%s, column=%s, validator=%s)", columnFamily, oType, columnName, validator); } }