http://git-wip-us.apache.org/repos/asf/cassandra/blob/207c80c1/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java 
b/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
deleted file mode 100644
index 260c8fd..0000000
--- a/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
+++ /dev/null
@@ -1,317 +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.cql3.statements;
-
-import java.util.*;
-import java.util.stream.Collectors;
-
-import com.google.common.collect.Iterables;
-
-import org.apache.cassandra.audit.AuditLogEntryType;
-import org.apache.cassandra.auth.Permission;
-import org.apache.cassandra.cql3.*;
-import org.apache.cassandra.db.ColumnFamilyStore;
-import org.apache.cassandra.db.Keyspace;
-import org.apache.cassandra.db.marshal.AbstractType;
-import org.apache.cassandra.db.marshal.CollectionType;
-import org.apache.cassandra.db.view.View;
-import org.apache.cassandra.exceptions.*;
-import org.apache.cassandra.schema.ColumnMetadata;
-import org.apache.cassandra.schema.DroppedColumn;
-import org.apache.cassandra.schema.IndexMetadata;
-import org.apache.cassandra.schema.Indexes;
-import org.apache.cassandra.schema.MigrationManager;
-import org.apache.cassandra.schema.Schema;
-import org.apache.cassandra.schema.TableMetadata;
-import org.apache.cassandra.schema.TableParams;
-import org.apache.cassandra.schema.ViewMetadata;
-import org.apache.cassandra.service.ClientState;
-import org.apache.cassandra.service.QueryState;
-import org.apache.cassandra.transport.Event;
-
-public class AlterTableStatement extends SchemaAlteringStatement
-{
-    public enum Type
-    {
-        ADD, ALTER, DROP, OPTS, RENAME
-    }
-
-    public final Type oType;
-    private final TableAttributes attrs;
-    private final Map<ColumnMetadata.Raw, ColumnMetadata.Raw> renames;
-    private final List<AlterTableStatementColumn> colNameList;
-    private final Long deleteTimestamp;
-
-    public AlterTableStatement(CFName name,
-                               Type type,
-                               List<AlterTableStatementColumn> colDataList,
-                               TableAttributes attrs,
-                               Map<ColumnMetadata.Raw, ColumnMetadata.Raw> 
renames,
-                               Long deleteTimestamp)
-    {
-        super(name);
-        this.oType = type;
-        this.colNameList = colDataList;
-        this.attrs = attrs;
-        this.renames = renames;
-        this.deleteTimestamp = deleteTimestamp;
-    }
-
-    public void checkAccess(ClientState state) throws UnauthorizedException, 
InvalidRequestException
-    {
-        state.hasColumnFamilyAccess(keyspace(), columnFamily(), 
Permission.ALTER);
-    }
-
-    public void validate(ClientState state)
-    {
-        // validated in announceMigration()
-    }
-
-    public Event.SchemaChange announceMigration(QueryState queryState, boolean 
isLocalOnly) throws RequestValidationException
-    {
-        TableMetadata current = Schema.instance.validateTable(keyspace(), 
columnFamily());
-        if (current.isView())
-            throw new InvalidRequestException("Cannot use ALTER TABLE on 
Materialized View");
-
-        if (current.isVirtual())
-            throw new InvalidRequestException("Cannot alter virtual tables");
-
-        TableMetadata.Builder builder = current.unbuild();
-
-        ColumnIdentifier columnName = null;
-        ColumnMetadata def = null;
-        CQL3Type.Raw dataType = null;
-        boolean isStatic = false;
-        CQL3Type validator = null;
-
-        List<ViewMetadata> viewUpdates = new ArrayList<>();
-        Iterable<ViewMetadata> views = View.findAll(keyspace(), 
columnFamily());
-
-        switch (oType)
-        {
-            case ALTER:
-                throw new InvalidRequestException("Altering of types is not 
allowed");
-            case ADD:
-                if (current.isDense())
-                    throw new InvalidRequestException("Cannot add new column 
to a COMPACT STORAGE table");
-
-                for (AlterTableStatementColumn colData : colNameList)
-                {
-                    columnName = 
colData.getColumnName().getIdentifier(current);
-                    def = builder.getColumn(columnName);
-                    dataType = colData.getColumnType();
-                    assert dataType != null;
-                    isStatic = colData.getStaticType();
-                    validator = dataType.prepare(keyspace());
-
-
-                    if (isStatic)
-                    {
-                        if (!current.isCompound())
-                            throw new InvalidRequestException("Static columns 
are not allowed in COMPACT STORAGE tables");
-                        if (current.clusteringColumns().isEmpty())
-                            throw new InvalidRequestException("Static columns 
are only useful (and thus allowed) if the table has at least one clustering 
column");
-                    }
-
-                    if (def != null)
-                    {
-                        switch (def.kind)
-                        {
-                            case PARTITION_KEY:
-                            case CLUSTERING:
-                                throw new 
InvalidRequestException(String.format("Invalid column name %s because it 
conflicts with a PRIMARY KEY part", columnName));
-                            default:
-                                throw new 
InvalidRequestException(String.format("Invalid column name %s because it 
conflicts with an existing column", columnName));
-                        }
-                    }
-
-                    // Cannot re-add a dropped counter column. See #7831.
-                    if (current.isCounter() && 
current.getDroppedColumn(columnName.bytes) != null)
-                        throw new 
InvalidRequestException(String.format("Cannot re-add previously dropped counter 
column %s", columnName));
-
-                    AbstractType<?> type = validator.getType();
-                    if (type.isCollection() && type.isMultiCell())
-                    {
-                        if (!current.isCompound())
-                            throw new InvalidRequestException("Cannot use 
non-frozen collections in COMPACT STORAGE tables");
-                        if (current.isSuper())
-                            throw new InvalidRequestException("Cannot use 
non-frozen collections with super column families");
-
-                        // If there used to be a non-frozen collection column 
with the same name (that has been dropped),
-                        // we could still have some data using the old type, 
and so we can't allow adding a collection
-                        // with the same name unless the types are compatible 
(see #6276).
-                        DroppedColumn dropped = 
current.droppedColumns.get(columnName.bytes);
-                        if (dropped != null && dropped.column.type instanceof 
CollectionType
-                            && dropped.column.type.isMultiCell() && 
!type.isCompatibleWith(dropped.column.type))
-                        {
-                            String message =
-                                String.format("Cannot add a collection with 
the name %s because a collection with the same name"
-                                              + " and a different type (%s) 
has already been used in the past",
-                                              columnName,
-                                              
dropped.column.type.asCQL3Type());
-                            throw new InvalidRequestException(message);
-                        }
-                    }
-
-                    builder.addColumn(isStatic
-                                    ? ColumnMetadata.staticColumn(current, 
columnName.bytes, type)
-                                    : ColumnMetadata.regularColumn(current, 
columnName.bytes, type));
-
-                    // Adding a column to a table which has an include all 
view requires the column to be added to the view
-                    // as well
-                    if (!isStatic)
-                        for (ViewMetadata view : views)
-                            if (view.includeAllColumns)
-                                
viewUpdates.add(view.withAddedRegularColumn(ColumnMetadata.regularColumn(view.metadata,
 columnName.bytes, type)));
-
-                }
-                break;
-            case DROP:
-                if (!current.isCQLTable())
-                    throw new InvalidRequestException("Cannot drop columns 
from a non-CQL3 table");
-
-                for (AlterTableStatementColumn colData : colNameList)
-                {
-                    columnName = 
colData.getColumnName().getIdentifier(current);
-                    def = builder.getColumn(columnName);
-
-                    if (def == null)
-                        throw new 
InvalidRequestException(String.format("Column %s was not found in table %s", 
columnName, columnFamily()));
-
-                    switch (def.kind)
-                    {
-                         case PARTITION_KEY:
-                         case CLUSTERING:
-                              throw new 
InvalidRequestException(String.format("Cannot drop PRIMARY KEY part %s", 
columnName));
-                         case REGULAR:
-                         case STATIC:
-                             builder.removeRegularOrStaticColumn(def.name);
-                             builder.recordColumnDrop(def, deleteTimestamp  == 
null ? queryState.getTimestamp() : deleteTimestamp);
-                             break;
-                    }
-
-                    // If the dropped column is required by any secondary 
indexes
-                    // we reject the operation, as the indexes must be dropped 
first
-                    Indexes allIndexes = current.indexes;
-                    if (!allIndexes.isEmpty())
-                    {
-                        ColumnFamilyStore store = 
Keyspace.openAndGetStore(current);
-                        Set<IndexMetadata> dependentIndexes = 
store.indexManager.getDependentIndexes(def);
-                        if (!dependentIndexes.isEmpty())
-                        {
-                            throw new 
InvalidRequestException(String.format("Cannot drop column %s because it has " +
-                                                                            
"dependent secondary indexes (%s)",
-                                                                            
def,
-                                                                            
dependentIndexes.stream()
-                                                                               
             .map(i -> i.name)
-                                                                               
             .collect(Collectors.joining(","))));
-                        }
-                    }
-
-
-                    if (!Iterables.isEmpty(views))
-                    throw new InvalidRequestException(String.format("Cannot 
drop column %s on base table %s with materialized views.",
-                                                                        
columnName.toString(),
-                                                                        
columnFamily()));
-                }
-                break;
-            case OPTS:
-                if (attrs == null)
-                    throw new InvalidRequestException("ALTER TABLE WITH 
invoked, but no parameters found");
-                attrs.validate();
-
-                TableParams params = 
attrs.asAlteredTableParams(current.params);
-
-                if (!Iterables.isEmpty(views) && params.gcGraceSeconds == 0)
-                {
-                    throw new InvalidRequestException("Cannot alter 
gc_grace_seconds of the base table of a " +
-                                                      "materialized view to 0, 
since this value is used to TTL " +
-                                                      "undelivered updates. 
Setting gc_grace_seconds too low might " +
-                                                      "cause undelivered 
updates to expire " +
-                                                      "before being 
replayed.");
-                }
-
-                if (current.isCounter() && params.defaultTimeToLive > 0)
-                    throw new InvalidRequestException("Cannot set 
default_time_to_live on a table with counters");
-
-                builder.params(params);
-
-                break;
-            case RENAME:
-                for (Map.Entry<ColumnMetadata.Raw, ColumnMetadata.Raw> entry : 
renames.entrySet())
-                {
-                    ColumnIdentifier from = 
entry.getKey().getIdentifier(current);
-                    ColumnIdentifier to = 
entry.getValue().getIdentifier(current);
-
-                    def = current.getColumn(from);
-                    if (def == null)
-                        throw new 
InvalidRequestException(String.format("Cannot rename unknown column %s in table 
%s", from, current.name));
-
-                    if (current.getColumn(to) != null)
-                        throw new 
InvalidRequestException(String.format("Cannot rename column %s to %s in table 
%s; another column of that name already exist", from, to, current.name));
-
-                    if (!def.isPrimaryKeyColumn())
-                        throw new 
InvalidRequestException(String.format("Cannot rename non PRIMARY KEY part %s", 
from));
-
-                    if (!current.indexes.isEmpty())
-                    {
-                        ColumnFamilyStore store = 
Keyspace.openAndGetStore(current);
-                        Set<IndexMetadata> dependentIndexes = 
store.indexManager.getDependentIndexes(def);
-                        if (!dependentIndexes.isEmpty())
-                            throw new 
InvalidRequestException(String.format("Cannot rename column %s because it has " 
+
-                                                                            
"dependent secondary indexes (%s)",
-                                                                            
from,
-                                                                            
dependentIndexes.stream()
-                                                                               
             .map(i -> i.name)
-                                                                               
             .collect(Collectors.joining(","))));
-                    }
-
-                    builder.renamePrimaryKeyColumn(from, to);
-
-                    // If the view includes a renamed column, it must be 
renamed in the view table and the definition.
-                    for (ViewMetadata view : views)
-                    {
-                        if (!view.includes(from))
-                            continue;
-
-                        ColumnIdentifier viewFrom = 
entry.getKey().getIdentifier(view.metadata);
-                        ColumnIdentifier viewTo = 
entry.getValue().getIdentifier(view.metadata);
-                        viewUpdates.add(view.renamePrimaryKeyColumn(viewFrom, 
viewTo));
-                    }
-                }
-                break;
-        }
-
-        MigrationManager.announceTableUpdate(builder.build(), viewUpdates, 
isLocalOnly);
-        return new Event.SchemaChange(Event.SchemaChange.Change.UPDATED, 
Event.SchemaChange.Target.TABLE, keyspace(), columnFamily());
-    }
-
-    @Override
-    public String toString()
-    {
-        return String.format("AlterTableStatement(name=%s, type=%s)",
-                             cfName,
-                             oType);
-    }
-
-    @Override
-    public AuditLogContext getAuditLogContext()
-    {
-        return new AuditLogContext(AuditLogEntryType.ALTER_TABLE, keyspace(), 
cfName.getColumnFamily());
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/207c80c1/src/java/org/apache/cassandra/cql3/statements/AlterTableStatementColumn.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/cql3/statements/AlterTableStatementColumn.java 
b/src/java/org/apache/cassandra/cql3/statements/AlterTableStatementColumn.java
deleted file mode 100644
index 97bf024..0000000
--- 
a/src/java/org/apache/cassandra/cql3/statements/AlterTableStatementColumn.java
+++ /dev/null
@@ -1,74 +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.cql3.statements;
-
-import org.apache.cassandra.schema.ColumnMetadata;
-import org.apache.cassandra.cql3.CQL3Type;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
-
-/**
- * Stores a column name and optionally type for an Alter Table statement 
definition.
- *
- * This is used by AlterTableStatement to store the added, altered or dropped 
columns.
- */
-public class AlterTableStatementColumn
-{
-    private final CQL3Type.Raw dataType;
-    private final ColumnMetadata.Raw colName;
-    private final Boolean isStatic;
-
-    public AlterTableStatementColumn(ColumnMetadata.Raw colName, CQL3Type.Raw 
dataType, boolean isStatic)
-    {
-        assert colName != null;
-        this.dataType = dataType; // will be null when dropping columns, and 
never null otherwise (for ADD and ALTER).
-        this.colName = colName;
-        this.isStatic = isStatic;
-    }
-
-    public AlterTableStatementColumn(ColumnMetadata.Raw colName, CQL3Type.Raw 
dataType)
-    {
-        this(colName, dataType, false);
-    }
-
-    public AlterTableStatementColumn(ColumnMetadata.Raw colName)
-    {
-        this(colName, null, false);
-    }
-
-    public CQL3Type.Raw getColumnType()
-    {
-        return dataType;
-    }
-
-    public ColumnMetadata.Raw getColumnName()
-    {
-        return colName;
-    }
-
-    public Boolean getStaticType()
-    {
-        return isStatic;
-    }
-    
-    @Override
-    public String toString()
-    {
-        return ToStringBuilder.reflectionToString(this, 
ToStringStyle.SHORT_PREFIX_STYLE);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/207c80c1/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java 
b/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java
deleted file mode 100644
index 3249af2..0000000
--- a/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java
+++ /dev/null
@@ -1,195 +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.cql3.statements;
-
-import java.util.*;
-
-import org.apache.cassandra.audit.AuditLogEntryType;
-import org.apache.cassandra.auth.Permission;
-import org.apache.cassandra.cql3.*;
-import org.apache.cassandra.db.marshal.*;
-import org.apache.cassandra.exceptions.*;
-import org.apache.cassandra.schema.KeyspaceMetadata;
-import org.apache.cassandra.schema.MigrationManager;
-import org.apache.cassandra.schema.Schema;
-import org.apache.cassandra.service.ClientState;
-import org.apache.cassandra.service.QueryState;
-import org.apache.cassandra.transport.Event;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
-
-public abstract class AlterTypeStatement extends SchemaAlteringStatement
-{
-    protected final UTName name;
-
-    protected AlterTypeStatement(UTName name)
-    {
-        this.name = name;
-    }
-
-    @Override
-    public void prepareKeyspace(ClientState state) throws 
InvalidRequestException
-    {
-        if (!name.hasKeyspace())
-            name.setKeyspace(state.getKeyspace());
-
-        if (name.getKeyspace() == null)
-            throw new InvalidRequestException("You need to be logged in a 
keyspace or use a fully qualified user type name");
-    }
-
-    protected abstract UserType makeUpdatedType(UserType toUpdate, 
KeyspaceMetadata ksm) throws InvalidRequestException;
-
-    public static AlterTypeStatement addition(UTName name, FieldIdentifier 
fieldName, CQL3Type.Raw type)
-    {
-        return new Add(name, fieldName, type);
-    }
-
-    public static AlterTypeStatement alter(UTName name, FieldIdentifier 
fieldName, CQL3Type.Raw type)
-    {
-        throw new InvalidRequestException("Altering of types is not allowed");
-    }
-
-    public static AlterTypeStatement renames(UTName name, Map<FieldIdentifier, 
FieldIdentifier> renames)
-    {
-        return new Renames(name, renames);
-    }
-
-    public void checkAccess(ClientState state) throws UnauthorizedException, 
InvalidRequestException
-    {
-        state.hasKeyspaceAccess(keyspace(), Permission.ALTER);
-    }
-
-    public void validate(ClientState state) throws RequestValidationException
-    {
-        // Validation is left to announceMigration as it's easier to do it 
while constructing the updated type.
-        // It doesn't really change anything anyway.
-    }
-
-    @Override
-    public String keyspace()
-    {
-        return name.getKeyspace();
-    }
-
-    public Event.SchemaChange announceMigration(QueryState queryState, boolean 
isLocalOnly) throws InvalidRequestException, ConfigurationException
-    {
-        KeyspaceMetadata ksm = 
Schema.instance.getKeyspaceMetadata(name.getKeyspace());
-        if (ksm == null)
-            throw new InvalidRequestException(String.format("Cannot alter type 
in unknown keyspace %s", name.getKeyspace()));
-
-        UserType toUpdate =
-            ksm.types.get(name.getUserTypeName())
-                     .orElseThrow(() -> new 
InvalidRequestException(String.format("No user type named %s exists.", name)));
-
-        UserType updated = makeUpdatedType(toUpdate, ksm);
-
-        // Now, we need to announce the type update to basically change it for 
new tables using this type,
-        // but we also need to find all existing user types and CF using it 
and change them.
-        MigrationManager.announceTypeUpdate(updated, isLocalOnly);
-
-        return new Event.SchemaChange(Event.SchemaChange.Change.UPDATED, 
Event.SchemaChange.Target.TYPE, keyspace(), name.getStringTypeName());
-    }
-
-    protected void checkTypeNotUsedByAggregate(KeyspaceMetadata ksm)
-    {
-        ksm.functions.udas().filter(aggregate -> aggregate.initialCondition() 
!= null && aggregate.stateType().referencesUserType(name.getStringTypeName()))
-                     .findAny()
-                     .ifPresent((aggregate) -> {
-                         throw new 
InvalidRequestException(String.format("Cannot alter user type %s as it is still 
used as an INITCOND by aggregate %s", name, aggregate));
-                     });
-    }
-
-    private static class Add extends AlterTypeStatement
-    {
-        private final FieldIdentifier fieldName;
-        private final CQL3Type.Raw type;
-
-        public Add(UTName name, FieldIdentifier fieldName, CQL3Type.Raw type)
-        {
-            super(name);
-            this.fieldName = fieldName;
-            this.type = type;
-        }
-
-        protected UserType makeUpdatedType(UserType toUpdate, KeyspaceMetadata 
ksm) throws InvalidRequestException
-        {
-            if (toUpdate.fieldPosition(fieldName) >= 0)
-                throw new InvalidRequestException(String.format("Cannot add 
new field %s to type %s: a field of the same name already exists", fieldName, 
name));
-
-            List<FieldIdentifier> newNames = new ArrayList<>(toUpdate.size() + 
1);
-            newNames.addAll(toUpdate.fieldNames());
-            newNames.add(fieldName);
-
-            AbstractType<?> addType = type.prepare(keyspace()).getType();
-            if (addType.referencesUserType(toUpdate.getNameAsString()))
-                throw new InvalidRequestException(String.format("Cannot add 
new field %s of type %s to type %s as this would create a circular reference", 
fieldName, type, name));
-
-            List<AbstractType<?>> newTypes = new ArrayList<>(toUpdate.size() + 
1);
-            newTypes.addAll(toUpdate.fieldTypes());
-            newTypes.add(addType);
-
-            return new UserType(toUpdate.keyspace, toUpdate.name, newNames, 
newTypes, toUpdate.isMultiCell());
-        }
-    }
-
-    private static class Renames extends AlterTypeStatement
-    {
-        private final Map<FieldIdentifier, FieldIdentifier> renames;
-
-        public Renames(UTName name, Map<FieldIdentifier, FieldIdentifier> 
renames)
-        {
-            super(name);
-            this.renames = renames;
-        }
-
-        protected UserType makeUpdatedType(UserType toUpdate, KeyspaceMetadata 
ksm) throws InvalidRequestException
-        {
-            checkTypeNotUsedByAggregate(ksm);
-
-            List<FieldIdentifier> newNames = new 
ArrayList<>(toUpdate.fieldNames());
-            List<AbstractType<?>> newTypes = new 
ArrayList<>(toUpdate.fieldTypes());
-
-            for (Map.Entry<FieldIdentifier, FieldIdentifier> entry : 
renames.entrySet())
-            {
-                FieldIdentifier from = entry.getKey();
-                FieldIdentifier to = entry.getValue();
-                int idx = toUpdate.fieldPosition(from);
-                if (idx < 0)
-                    throw new InvalidRequestException(String.format("Unknown 
field %s in type %s", from, name));
-                newNames.set(idx, to);
-            }
-
-            UserType updated = new UserType(toUpdate.keyspace, toUpdate.name, 
newNames, newTypes, toUpdate.isMultiCell());
-            CreateTypeStatement.checkForDuplicateNames(updated);
-            return updated;
-        }
-
-    }
-    
-    @Override
-    public String toString()
-    {
-        return ToStringBuilder.reflectionToString(this, 
ToStringStyle.SHORT_PREFIX_STYLE);
-    }
-
-    @Override
-    public AuditLogContext getAuditLogContext()
-    {
-        return new AuditLogContext(AuditLogEntryType.ALTER_TYPE, keyspace(), 
name.getStringTypeName());
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/207c80c1/src/java/org/apache/cassandra/cql3/statements/AlterViewStatement.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/cql3/statements/AlterViewStatement.java 
b/src/java/org/apache/cassandra/cql3/statements/AlterViewStatement.java
deleted file mode 100644
index 938908c..0000000
--- a/src/java/org/apache/cassandra/cql3/statements/AlterViewStatement.java
+++ /dev/null
@@ -1,103 +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.cql3.statements;
-
-import org.apache.cassandra.audit.AuditLogEntryType;
-import org.apache.cassandra.auth.Permission;
-import org.apache.cassandra.cql3.CFName;
-import org.apache.cassandra.db.view.View;
-import org.apache.cassandra.exceptions.InvalidRequestException;
-import org.apache.cassandra.exceptions.RequestValidationException;
-import org.apache.cassandra.exceptions.UnauthorizedException;
-import org.apache.cassandra.schema.MigrationManager;
-import org.apache.cassandra.schema.Schema;
-import org.apache.cassandra.schema.TableMetadata;
-import org.apache.cassandra.schema.TableMetadataRef;
-import org.apache.cassandra.schema.TableParams;
-import org.apache.cassandra.schema.ViewMetadata;
-import org.apache.cassandra.service.ClientState;
-import org.apache.cassandra.service.QueryState;
-import org.apache.cassandra.transport.Event;
-
-public class AlterViewStatement extends SchemaAlteringStatement
-{
-    private final TableAttributes attrs;
-
-    public AlterViewStatement(CFName name, TableAttributes attrs)
-    {
-        super(name);
-        this.attrs = attrs;
-    }
-
-    public void checkAccess(ClientState state) throws UnauthorizedException, 
InvalidRequestException
-    {
-        TableMetadataRef baseTable = View.findBaseTable(keyspace(), 
columnFamily());
-        if (baseTable != null)
-            state.hasColumnFamilyAccess(keyspace(), baseTable.name, 
Permission.ALTER);
-    }
-
-    public void validate(ClientState state)
-    {
-        // validated in announceMigration()
-    }
-
-    public Event.SchemaChange announceMigration(QueryState queryState, boolean 
isLocalOnly) throws RequestValidationException
-    {
-        TableMetadata meta = Schema.instance.validateTable(keyspace(), 
columnFamily());
-        if (!meta.isView())
-            throw new InvalidRequestException("Cannot use ALTER MATERIALIZED 
VIEW on Table");
-
-        ViewMetadata current = Schema.instance.getView(keyspace(), 
columnFamily());
-
-        if (attrs == null)
-            throw new InvalidRequestException("ALTER MATERIALIZED VIEW WITH 
invoked, but no parameters found");
-
-        attrs.validate();
-
-        TableParams params = 
attrs.asAlteredTableParams(current.metadata.params);
-        if (params.gcGraceSeconds == 0)
-        {
-            throw new InvalidRequestException("Cannot alter gc_grace_seconds 
of a materialized view to 0, since this " +
-                                              "value is used to TTL 
undelivered updates. Setting gc_grace_seconds too " +
-                                              "low might cause undelivered 
updates to expire before being replayed.");
-        }
-
-        if (params.defaultTimeToLive > 0)
-        {
-            throw new InvalidRequestException("Cannot set or alter 
default_time_to_live for a materialized view. " +
-                                              "Data in a materialized view 
always expire at the same time than " +
-                                              "the corresponding data in the 
parent table.");
-        }
-
-        ViewMetadata updated = 
current.copy(current.metadata.unbuild().params(params).build());
-
-        MigrationManager.announceViewUpdate(updated, isLocalOnly);
-        return new Event.SchemaChange(Event.SchemaChange.Change.UPDATED, 
Event.SchemaChange.Target.TABLE, keyspace(), columnFamily());
-    }
-
-    public String toString()
-    {
-        return String.format("AlterViewStatement(name=%s)", cfName);
-    }
-
-    @Override
-    public AuditLogContext getAuditLogContext()
-    {
-        return new AuditLogContext(AuditLogEntryType.ALTER_VIEW, keyspace(), 
cfName.getColumnFamily());
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/207c80c1/src/java/org/apache/cassandra/cql3/statements/AuthenticationStatement.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/cql3/statements/AuthenticationStatement.java 
b/src/java/org/apache/cassandra/cql3/statements/AuthenticationStatement.java
index 0283009..a8cbaa7 100644
--- a/src/java/org/apache/cassandra/cql3/statements/AuthenticationStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/AuthenticationStatement.java
@@ -28,17 +28,11 @@ import org.apache.cassandra.service.ClientState;
 import org.apache.cassandra.service.QueryState;
 import org.apache.cassandra.transport.messages.ResultMessage;
 
-public abstract class AuthenticationStatement extends ParsedStatement 
implements CQLStatement
+public abstract class AuthenticationStatement extends CQLStatement.Raw 
implements CQLStatement
 {
-    @Override
-    public Prepared prepare()
+    public AuthenticationStatement prepare(ClientState state)
     {
-        return new Prepared(this);
-    }
-
-    public int getBoundTerms()
-    {
-        return 0;
+        return this;
     }
 
     public ResultMessage execute(QueryState state, QueryOptions options, long 
queryStartNanoTime)
@@ -49,9 +43,9 @@ public abstract class AuthenticationStatement extends 
ParsedStatement implements
 
     public abstract ResultMessage execute(ClientState state) throws 
RequestExecutionException, RequestValidationException;
 
-    public ResultMessage executeInternal(QueryState state, QueryOptions 
options)
+    public ResultMessage executeLocally(QueryState state, QueryOptions options)
     {
-        // executeInternal is for local query only, thus altering users 
doesn't make sense and is not supported
+        // executeLocally is for local query only, thus altering users doesn't 
make sense and is not supported
         throw new UnsupportedOperationException();
     }
 
@@ -59,7 +53,7 @@ public abstract class AuthenticationStatement extends 
ParsedStatement implements
     {
         try
         {
-            state.ensureHasPermission(required, resource);
+            state.ensurePermission(required, resource);
         }
         catch (UnauthorizedException e)
         {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/207c80c1/src/java/org/apache/cassandra/cql3/statements/AuthorizationStatement.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/cql3/statements/AuthorizationStatement.java 
b/src/java/org/apache/cassandra/cql3/statements/AuthorizationStatement.java
index 8c6f93b..46285c6 100644
--- a/src/java/org/apache/cassandra/cql3/statements/AuthorizationStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/AuthorizationStatement.java
@@ -17,7 +17,6 @@
  */
 package org.apache.cassandra.cql3.statements;
 
-
 import org.apache.cassandra.auth.DataResource;
 import org.apache.cassandra.auth.IResource;
 import org.apache.cassandra.cql3.CQLStatement;
@@ -31,17 +30,11 @@ import 
org.apache.cassandra.transport.messages.ResultMessage;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 
-public abstract class AuthorizationStatement extends ParsedStatement 
implements CQLStatement
+public abstract class AuthorizationStatement extends CQLStatement.Raw 
implements CQLStatement
 {
-    @Override
-    public Prepared prepare()
-    {
-        return new Prepared(this);
-    }
-
-    public int getBoundTerms()
+    public AuthorizationStatement prepare(ClientState state)
     {
-        return 0;
+        return this;
     }
 
     public ResultMessage execute(QueryState state, QueryOptions options, long 
queryStartNanoTime)
@@ -52,9 +45,9 @@ public abstract class AuthorizationStatement extends 
ParsedStatement implements
 
     public abstract ResultMessage execute(ClientState state) throws 
RequestValidationException, RequestExecutionException;
 
-    public ResultMessage executeInternal(QueryState state, QueryOptions 
options)
+    public ResultMessage executeLocally(QueryState state, QueryOptions options)
     {
-        // executeInternal is for local query only, thus altering permission 
doesn't make sense and is not supported
+        // executeLocally is for local query only, thus altering permission 
doesn't make sense and is not supported
         throw new UnsupportedOperationException();
     }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/207c80c1/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java 
b/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java
index a71c799..9ed150c 100644
--- a/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java
@@ -27,6 +27,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.helpers.MessageFormatter;
 
+import org.apache.cassandra.audit.AuditLogContext;
 import org.apache.cassandra.audit.AuditLogEntryType;
 import org.apache.cassandra.schema.TableId;
 import org.apache.cassandra.schema.TableMetadata;
@@ -45,6 +46,8 @@ import org.apache.cassandra.utils.FBUtilities;
 import org.apache.cassandra.utils.NoSpamLogger;
 import org.apache.cassandra.utils.Pair;
 
+import static java.util.function.Predicate.isEqual;
+
 import static 
org.apache.cassandra.cql3.statements.RequestValidations.checkFalse;
 
 /**
@@ -57,8 +60,8 @@ public class BatchStatement implements CQLStatement
         LOGGED, UNLOGGED, COUNTER
     }
 
-    private final int boundTerms;
     public final Type type;
+    private final VariableSpecifications bindVariables;
     private final List<ModificationStatement> statements;
 
     // Columns modified for each table (keyed by the table ID)
@@ -93,10 +96,10 @@ public class BatchStatement implements CQLStatement
      * @param statements the list of statements in the batch
      * @param attrs      additional attributes for statement (CL, timestamp, 
timeToLive)
      */
-    public BatchStatement(int boundTerms, Type type, 
List<ModificationStatement> statements, Attributes attrs)
+    public BatchStatement(Type type, VariableSpecifications bindVariables, 
List<ModificationStatement> statements, Attributes attrs)
     {
-        this.boundTerms = boundTerms;
         this.type = type;
+        this.bindVariables = bindVariables;
         this.statements = statements;
         this.attrs = attrs;
 
@@ -128,6 +131,26 @@ public class BatchStatement implements CQLStatement
         this.updatesVirtualTables = updatesVirtualTables;
     }
 
+    @Override
+    public List<ColumnSpecification> getBindVariables()
+    {
+        return bindVariables.getBindVariables();
+    }
+
+    @Override
+    public short[] getPartitionKeyBindVariableIndexes()
+    {
+        boolean affectsMultipleTables =
+            !statements.isEmpty() && statements.stream().map(s -> 
s.metadata().id).allMatch(isEqual(statements.get(0).metadata().id));
+
+        // Use the TableMetadata of the first statement for partition key bind 
indexes.  If the statements affect
+        // multiple tables, we won't send partition key bind indexes.
+        return (affectsMultipleTables || statements.isEmpty())
+             ? null
+             : 
bindVariables.getPartitionKeyBindVariableIndexes(statements.get(0).metadata());
+    }
+
+    @Override
     public Iterable<org.apache.cassandra.cql3.functions.Function> 
getFunctions()
     {
         List<org.apache.cassandra.cql3.functions.Function> functions = new 
ArrayList<>();
@@ -136,15 +159,10 @@ public class BatchStatement implements CQLStatement
         return functions;
     }
 
-    public int getBoundTerms()
-    {
-        return boundTerms;
-    }
-
-    public void checkAccess(ClientState state) throws InvalidRequestException, 
UnauthorizedException
+    public void authorize(ClientState state) throws InvalidRequestException, 
UnauthorizedException
     {
         for (ModificationStatement statement : statements)
-            statement.checkAccess(state);
+            statement.authorize(state);
     }
 
     // Validates a prepared batch statement without validating its nested 
statements.
@@ -506,7 +524,7 @@ public class BatchStatement implements CQLStatement
         return hasConditions;
     }
 
-    public ResultMessage executeInternal(QueryState queryState, QueryOptions 
options) throws RequestValidationException, RequestExecutionException
+    public ResultMessage executeLocally(QueryState queryState, QueryOptions 
options) throws RequestValidationException, RequestExecutionException
     {
         BatchQueryOptions batchOptions = 
BatchQueryOptions.withoutPerStatementVariables(options);
 
@@ -544,7 +562,7 @@ public class BatchStatement implements CQLStatement
         return String.format("BatchStatement(type=%s, statements=%s)", type, 
statements);
     }
 
-    public static class Parsed extends CFStatement
+    public static class Parsed extends QualifiedStatement
     {
         private final Type type;
         private final Attributes.Raw attrs;
@@ -559,48 +577,24 @@ public class BatchStatement implements CQLStatement
         }
 
         @Override
-        public void prepareKeyspace(ClientState state) throws 
InvalidRequestException
+        public void setKeyspace(ClientState state) throws 
InvalidRequestException
         {
             for (ModificationStatement.Parsed statement : parsedStatements)
-                statement.prepareKeyspace(state);
+                statement.setKeyspace(state);
         }
 
-        public ParsedStatement.Prepared prepare() throws 
InvalidRequestException
+        public BatchStatement prepare(ClientState state)
         {
-            VariableSpecifications boundNames = getBoundVariables();
-
-            String firstKS = null;
-            String firstCF = null;
-            boolean haveMultipleCFs = false;
-
             List<ModificationStatement> statements = new 
ArrayList<>(parsedStatements.size());
-            for (ModificationStatement.Parsed parsed : parsedStatements)
-            {
-                if (firstKS == null)
-                {
-                    firstKS = parsed.keyspace();
-                    firstCF = parsed.columnFamily();
-                }
-                else if (!haveMultipleCFs)
-                {
-                    haveMultipleCFs = !firstKS.equals(parsed.keyspace()) || 
!firstCF.equals(parsed.columnFamily());
-                }
-
-                statements.add(parsed.prepare(boundNames));
-            }
+            parsedStatements.forEach(s -> 
statements.add(s.prepare(bindVariables)));
 
             Attributes prepAttrs = attrs.prepare("[batch]", "[batch]");
-            prepAttrs.collectMarkerSpecification(boundNames);
+            prepAttrs.collectMarkerSpecification(bindVariables);
 
-            BatchStatement batchStatement = new 
BatchStatement(boundNames.size(), type, statements, prepAttrs);
+            BatchStatement batchStatement = new BatchStatement(type, 
bindVariables, statements, prepAttrs);
             batchStatement.validate();
 
-            // Use the TableMetadata of the first statement for partition key 
bind indexes.  If the statements affect
-            // multiple tables, we won't send partition key bind indexes.
-            short[] partitionKeyBindIndexes = (haveMultipleCFs || 
batchStatement.statements.isEmpty())? null
-                                                              : 
boundNames.getPartitionKeyBindIndexes(batchStatement.statements.get(0).metadata());
-
-            return new ParsedStatement.Prepared(batchStatement, boundNames, 
partitionKeyBindIndexes);
+            return batchStatement;
         }
     }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/207c80c1/src/java/org/apache/cassandra/cql3/statements/CFProperties.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/CFProperties.java 
b/src/java/org/apache/cassandra/cql3/statements/CFProperties.java
deleted file mode 100644
index 3f40c0d..0000000
--- a/src/java/org/apache/cassandra/cql3/statements/CFProperties.java
+++ /dev/null
@@ -1,64 +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.cql3.statements;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import org.apache.cassandra.cql3.ColumnIdentifier;
-import org.apache.cassandra.db.marshal.AbstractType;
-import org.apache.cassandra.db.marshal.ReversedType;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
-
-public class CFProperties
-{
-    public final TableAttributes properties = new TableAttributes();
-    final Map<ColumnIdentifier, Boolean> definedOrdering = new 
LinkedHashMap<>(); // Insertion ordering is important
-    boolean useCompactStorage = false;
-
-    public void validate()
-    {
-        properties.validate();
-    }
-
-    public void setOrdering(ColumnIdentifier alias, boolean reversed)
-    {
-        definedOrdering.put(alias, reversed);
-    }
-
-    public void setCompactStorage()
-    {
-        useCompactStorage = true;
-    }
-
-    public AbstractType getReversableType(ColumnIdentifier targetIdentifier, 
AbstractType<?> type)
-    {
-        if (!definedOrdering.containsKey(targetIdentifier))
-        {
-            return type;
-        }
-        return definedOrdering.get(targetIdentifier) ? 
ReversedType.getInstance(type) : type;
-    }
-    
-    @Override
-    public String toString()
-    {
-        return ToStringBuilder.reflectionToString(this, 
ToStringStyle.SHORT_PREFIX_STYLE);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/207c80c1/src/java/org/apache/cassandra/cql3/statements/CFStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/CFStatement.java 
b/src/java/org/apache/cassandra/cql3/statements/CFStatement.java
deleted file mode 100644
index 7cc8a99..0000000
--- a/src/java/org/apache/cassandra/cql3/statements/CFStatement.java
+++ /dev/null
@@ -1,74 +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.cql3.statements;
-
-import org.apache.cassandra.cql3.CFName;
-import org.apache.cassandra.service.ClientState;
-import org.apache.cassandra.exceptions.InvalidRequestException;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
-
-/**
- * Abstract class for statements that apply on a given column family.
- */
-public abstract class CFStatement extends ParsedStatement
-{
-    protected final CFName cfName;
-
-    protected CFStatement(CFName cfName)
-    {
-        this.cfName = cfName;
-    }
-
-    public void prepareKeyspace(ClientState state) throws 
InvalidRequestException
-    {
-        if (!cfName.hasKeyspace())
-        {
-            // XXX: We explicitly only want to call state.getKeyspace() in 
this case, as we don't want to throw
-            // if not logged in any keyspace but a keyspace is explicitly set 
on the statement. So don't move
-            // the call outside the 'if' or replace the method by 
'prepareKeyspace(state.getKeyspace())'
-            cfName.setKeyspace(state.getKeyspace(), true);
-        }
-    }
-
-    // Only for internal calls, use the version with ClientState for user 
queries. In particular, the
-    // version with ClientState throws an exception if the statement does not 
have keyspace set *and*
-    // ClientState has no keyspace.
-    public void prepareKeyspace(String keyspace)
-    {
-        if (!cfName.hasKeyspace())
-            cfName.setKeyspace(keyspace, true);
-    }
-
-    public String keyspace()
-    {
-        assert cfName.hasKeyspace() : "The statement hasn't been prepared 
correctly";
-        return cfName.getKeyspace();
-    }
-
-    public String columnFamily()
-    {
-        return cfName.getColumnFamily();
-    }
-    
-    @Override
-    public String toString()
-    {
-        return ToStringBuilder.reflectionToString(this, 
ToStringStyle.SHORT_PREFIX_STYLE);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/207c80c1/src/java/org/apache/cassandra/cql3/statements/CreateAggregateStatement.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/cql3/statements/CreateAggregateStatement.java 
b/src/java/org/apache/cassandra/cql3/statements/CreateAggregateStatement.java
deleted file mode 100644
index e428087..0000000
--- 
a/src/java/org/apache/cassandra/cql3/statements/CreateAggregateStatement.java
+++ /dev/null
@@ -1,281 +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.cql3.statements;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Objects;
-import java.util.List;
-
-import org.apache.cassandra.audit.AuditLogEntryType;
-import org.apache.cassandra.auth.*;
-import org.apache.cassandra.config.DatabaseDescriptor;
-import org.apache.cassandra.schema.KeyspaceMetadata;
-import org.apache.cassandra.schema.Schema;
-import org.apache.cassandra.cql3.*;
-import org.apache.cassandra.cql3.functions.*;
-import org.apache.cassandra.db.marshal.AbstractType;
-import org.apache.cassandra.exceptions.*;
-import org.apache.cassandra.serializers.MarshalException;
-import org.apache.cassandra.service.ClientState;
-import org.apache.cassandra.schema.MigrationManager;
-import org.apache.cassandra.service.QueryState;
-import org.apache.cassandra.transport.Event;
-import org.apache.cassandra.transport.ProtocolVersion;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
-
-/**
- * A {@code CREATE AGGREGATE} statement parsed from a CQL query.
- */
-public final class CreateAggregateStatement extends SchemaAlteringStatement
-{
-    private final boolean orReplace;
-    private final boolean ifNotExists;
-    private FunctionName functionName;
-    private FunctionName stateFunc;
-    private FunctionName finalFunc;
-    private final CQL3Type.Raw stateTypeRaw;
-
-    private final List<CQL3Type.Raw> argRawTypes;
-    private final Term.Raw ival;
-
-    private List<AbstractType<?>> argTypes;
-    private AbstractType<?> returnType;
-    private ScalarFunction stateFunction;
-    private ScalarFunction finalFunction;
-    private ByteBuffer initcond;
-
-    public CreateAggregateStatement(FunctionName functionName,
-                                    List<CQL3Type.Raw> argRawTypes,
-                                    String stateFunc,
-                                    CQL3Type.Raw stateType,
-                                    String finalFunc,
-                                    Term.Raw ival,
-                                    boolean orReplace,
-                                    boolean ifNotExists)
-    {
-        this.functionName = functionName;
-        this.argRawTypes = argRawTypes;
-        this.stateFunc = new FunctionName(functionName.keyspace, stateFunc);
-        this.finalFunc = finalFunc != null ? new 
FunctionName(functionName.keyspace, finalFunc) : null;
-        this.stateTypeRaw = stateType;
-        this.ival = ival;
-        this.orReplace = orReplace;
-        this.ifNotExists = ifNotExists;
-    }
-
-    public Prepared prepare()
-    {
-        argTypes = new ArrayList<>(argRawTypes.size());
-        for (CQL3Type.Raw rawType : argRawTypes)
-            argTypes.add(prepareType("arguments", rawType));
-
-        AbstractType<?> stateType = prepareType("state type", stateTypeRaw);
-
-        List<AbstractType<?>> stateArgs = stateArguments(stateType, argTypes);
-
-        Function f = Schema.instance.findFunction(stateFunc, 
stateArgs).orElse(null);
-        if (!(f instanceof ScalarFunction))
-            throw new InvalidRequestException("State function " + 
stateFuncSig(stateFunc, stateTypeRaw, argRawTypes) + " does not exist or is not 
a scalar function");
-        stateFunction = (ScalarFunction)f;
-
-        AbstractType<?> stateReturnType = stateFunction.returnType();
-        if (!stateReturnType.equals(stateType))
-            throw new InvalidRequestException("State function " + 
stateFuncSig(stateFunction.name(), stateTypeRaw, argRawTypes) + " return type 
must be the same as the first argument type - check STYPE, argument and return 
types");
-
-        if (finalFunc != null)
-        {
-            List<AbstractType<?>> finalArgs = 
Collections.<AbstractType<?>>singletonList(stateType);
-            f = Schema.instance.findFunction(finalFunc, 
finalArgs).orElse(null);
-            if (!(f instanceof ScalarFunction))
-                throw new InvalidRequestException("Final function " + 
finalFunc + '(' + stateTypeRaw + ") does not exist or is not a scalar 
function");
-            finalFunction = (ScalarFunction) f;
-            returnType = finalFunction.returnType();
-        }
-        else
-        {
-            returnType = stateReturnType;
-        }
-
-        if (ival != null)
-        {
-            initcond = Terms.asBytes(functionName.keyspace, ival.toString(), 
stateType);
-
-            if (initcond != null)
-            {
-                try
-                {
-                    stateType.validate(initcond);
-                }
-                catch (MarshalException e)
-                {
-                    throw new InvalidRequestException(String.format("Invalid 
value for INITCOND of type %s%s", stateType.asCQL3Type(),
-                                                                    
e.getMessage() == null ? "" : String.format(" (%s)", e.getMessage())));
-                }
-            }
-
-            // Sanity check that converts the initcond to a CQL literal and 
parse it back to avoid getting in CASSANDRA-11064.
-            String initcondAsCql = 
stateType.asCQL3Type().toCQLLiteral(initcond, ProtocolVersion.CURRENT);
-            assert Objects.equals(initcond, 
Terms.asBytes(functionName.keyspace, initcondAsCql, stateType));
-
-            if (Constants.NULL_LITERAL != ival && 
UDHelper.isNullOrEmpty(stateType, initcond))
-                throw new InvalidRequestException("INITCOND must not be empty 
for all types except TEXT, ASCII, BLOB");
-        }
-
-        return super.prepare();
-    }
-
-    private AbstractType<?> prepareType(String typeName, CQL3Type.Raw rawType)
-    {
-        if (rawType.isFrozen())
-            throw new InvalidRequestException(String.format("The function %s 
should not be frozen; remove the frozen<> modifier", typeName));
-
-        // UDT are not supported non frozen but we do not allow the frozen 
keyword for argument. So for the moment we
-        // freeze them here
-        if (!rawType.canBeNonFrozen())
-            rawType.freeze();
-
-        AbstractType<?> type = 
rawType.prepare(functionName.keyspace).getType();
-        return type;
-    }
-
-    public void prepareKeyspace(ClientState state) throws 
InvalidRequestException
-    {
-        if (!functionName.hasKeyspace() && state.getRawKeyspace() != null)
-            functionName = new FunctionName(state.getKeyspace(), 
functionName.name);
-
-        if (!functionName.hasKeyspace())
-            throw new InvalidRequestException("Functions must be fully 
qualified with a keyspace name if a keyspace is not set for the session");
-
-        Schema.validateKeyspaceNotSystem(functionName.keyspace);
-
-        stateFunc = new FunctionName(functionName.keyspace, stateFunc.name);
-        if (finalFunc != null)
-            finalFunc = new FunctionName(functionName.keyspace, 
finalFunc.name);
-    }
-
-    protected void grantPermissionsToCreator(QueryState state)
-    {
-        try
-        {
-            IResource resource = 
FunctionResource.function(functionName.keyspace, functionName.name, argTypes);
-            
DatabaseDescriptor.getAuthorizer().grant(AuthenticatedUser.SYSTEM_USER,
-                                                     
resource.applicablePermissions(),
-                                                     resource,
-                                                     
RoleResource.role(state.getClientState().getUser().getName()));
-        }
-        catch (RequestExecutionException e)
-        {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public void checkAccess(ClientState state) throws UnauthorizedException, 
InvalidRequestException
-    {
-        if (Schema.instance.findFunction(functionName, argTypes).isPresent() 
&& orReplace)
-            state.ensureHasPermission(Permission.ALTER, 
FunctionResource.function(functionName.keyspace,
-                                                                               
   functionName.name,
-                                                                               
   argTypes));
-        else
-            state.ensureHasPermission(Permission.CREATE, 
FunctionResource.keyspace(functionName.keyspace));
-
-        state.ensureHasPermission(Permission.EXECUTE, stateFunction);
-
-        if (finalFunction != null)
-            state.ensureHasPermission(Permission.EXECUTE, finalFunction);
-    }
-
-    public void validate(ClientState state) throws InvalidRequestException
-    {
-        if (ifNotExists && orReplace)
-            throw new InvalidRequestException("Cannot use both 'OR REPLACE' 
and 'IF NOT EXISTS' directives");
-
-
-        KeyspaceMetadata ksm = 
Schema.instance.getKeyspaceMetadata(functionName.keyspace);
-        if (null == ksm)
-            throw new InvalidRequestException(String.format("Cannot add 
aggregate '%s' to non existing keyspace '%s'.", functionName.name, 
functionName.keyspace));
-        if (ksm.isVirtual())
-            throw new InvalidRequestException("Cannot create aggregates in 
virtual keyspaces");
-    }
-
-    public Event.SchemaChange announceMigration(QueryState queryState, boolean 
isLocalOnly) throws RequestValidationException
-    {
-        Function old = Schema.instance.findFunction(functionName, 
argTypes).orElse(null);
-        boolean replaced = old != null;
-        if (replaced)
-        {
-            if (ifNotExists)
-                return null;
-            if (!orReplace)
-                throw new InvalidRequestException(String.format("Function %s 
already exists", old));
-            if (!(old instanceof AggregateFunction))
-                throw new InvalidRequestException(String.format("Aggregate %s 
can only replace an aggregate", old));
-
-            // Means we're replacing the function. We still need to validate 
that 1) it's not a native function and 2) that the return type
-            // matches (or that could break existing code badly)
-            if (old.isNative())
-                throw new InvalidRequestException(String.format("Cannot 
replace native aggregate %s", old));
-            if (!old.returnType().isValueCompatibleWith(returnType))
-                throw new InvalidRequestException(String.format("Cannot 
replace aggregate %s, the new return type %s is not compatible with the return 
type %s of existing function",
-                                                                functionName, 
returnType.asCQL3Type(), old.returnType().asCQL3Type()));
-        }
-
-        if (!stateFunction.isCalledOnNullInput() && initcond == null)
-            throw new InvalidRequestException(String.format("Cannot create 
aggregate %s without INITCOND because state function %s does not accept 'null' 
arguments", functionName, stateFunc));
-
-        UDAggregate udAggregate = new UDAggregate(functionName, argTypes, 
returnType, stateFunction, finalFunction, initcond);
-
-        MigrationManager.announceNewAggregate(udAggregate, isLocalOnly);
-
-        return new Event.SchemaChange(replaced ? 
Event.SchemaChange.Change.UPDATED : Event.SchemaChange.Change.CREATED,
-                                      Event.SchemaChange.Target.AGGREGATE,
-                                      udAggregate.name().keyspace, 
udAggregate.name().name, 
AbstractType.asCQLTypeStringList(udAggregate.argTypes()));
-    }
-
-    private static String stateFuncSig(FunctionName stateFuncName, 
CQL3Type.Raw stateTypeRaw, List<CQL3Type.Raw> argRawTypes)
-    {
-        StringBuilder sb = new StringBuilder();
-        sb.append(stateFuncName.toString()).append('(').append(stateTypeRaw);
-        for (CQL3Type.Raw argRawType : argRawTypes)
-            sb.append(", ").append(argRawType);
-        sb.append(')');
-        return sb.toString();
-    }
-
-    private static List<AbstractType<?>> stateArguments(AbstractType<?> 
stateType, List<AbstractType<?>> argTypes)
-    {
-        List<AbstractType<?>> r = new ArrayList<>(argTypes.size() + 1);
-        r.add(stateType);
-        r.addAll(argTypes);
-        return r;
-    }
-    
-    @Override
-    public String toString()
-    {
-        return ToStringBuilder.reflectionToString(this, 
ToStringStyle.SHORT_PREFIX_STYLE);
-    }
-
-    @Override
-    public AuditLogContext getAuditLogContext()
-    {
-        return new AuditLogContext(AuditLogEntryType.CREATE_AGGREGATE, 
keyspace(), functionName.name);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/207c80c1/src/java/org/apache/cassandra/cql3/statements/CreateFunctionStatement.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/cql3/statements/CreateFunctionStatement.java 
b/src/java/org/apache/cassandra/cql3/statements/CreateFunctionStatement.java
deleted file mode 100644
index c380991..0000000
--- a/src/java/org/apache/cassandra/cql3/statements/CreateFunctionStatement.java
+++ /dev/null
@@ -1,202 +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.cql3.statements;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-
-import org.apache.cassandra.audit.AuditLogEntryType;
-import org.apache.cassandra.auth.*;
-import org.apache.cassandra.config.DatabaseDescriptor;
-import org.apache.cassandra.schema.KeyspaceMetadata;
-import org.apache.cassandra.schema.Schema;
-import org.apache.cassandra.cql3.CQL3Type;
-import org.apache.cassandra.cql3.ColumnIdentifier;
-import org.apache.cassandra.cql3.functions.*;
-import org.apache.cassandra.db.marshal.AbstractType;
-import org.apache.cassandra.exceptions.*;
-import org.apache.cassandra.schema.Functions;
-import org.apache.cassandra.service.ClientState;
-import org.apache.cassandra.schema.MigrationManager;
-import org.apache.cassandra.service.QueryState;
-import org.apache.cassandra.transport.Event;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
-
-/**
- * A {@code CREATE FUNCTION} statement parsed from a CQL query.
- */
-public final class CreateFunctionStatement extends SchemaAlteringStatement
-{
-    private final boolean orReplace;
-    private final boolean ifNotExists;
-    private FunctionName functionName;
-    private final String language;
-    private final String body;
-
-    private final List<ColumnIdentifier> argNames;
-    private final List<CQL3Type.Raw> argRawTypes;
-    private final CQL3Type.Raw rawReturnType;
-    private final boolean calledOnNullInput;
-
-    private List<AbstractType<?>> argTypes;
-    private AbstractType<?> returnType;
-
-    public CreateFunctionStatement(FunctionName functionName,
-                                   String language,
-                                   String body,
-                                   List<ColumnIdentifier> argNames,
-                                   List<CQL3Type.Raw> argRawTypes,
-                                   CQL3Type.Raw rawReturnType,
-                                   boolean calledOnNullInput,
-                                   boolean orReplace,
-                                   boolean ifNotExists)
-    {
-        this.functionName = functionName;
-        this.language = language;
-        this.body = body;
-        this.argNames = argNames;
-        this.argRawTypes = argRawTypes;
-        this.rawReturnType = rawReturnType;
-        this.calledOnNullInput = calledOnNullInput;
-        this.orReplace = orReplace;
-        this.ifNotExists = ifNotExists;
-    }
-
-    public Prepared prepare() throws InvalidRequestException
-    {
-        if (new HashSet<>(argNames).size() != argNames.size())
-            throw new InvalidRequestException(String.format("duplicate 
argument names for given function %s with argument names %s",
-                                                            functionName, 
argNames));
-
-        argTypes = new ArrayList<>(argRawTypes.size());
-        for (CQL3Type.Raw rawType : argRawTypes)
-            argTypes.add(prepareType("arguments", rawType));
-
-        returnType = prepareType("return type", rawReturnType);
-        return super.prepare();
-    }
-
-    public void prepareKeyspace(ClientState state) throws 
InvalidRequestException
-    {
-        if (!functionName.hasKeyspace() && state.getRawKeyspace() != null)
-            functionName = new FunctionName(state.getRawKeyspace(), 
functionName.name);
-
-        if (!functionName.hasKeyspace())
-            throw new InvalidRequestException("Functions must be fully 
qualified with a keyspace name if a keyspace is not set for the session");
-
-        Schema.validateKeyspaceNotSystem(functionName.keyspace);
-    }
-
-    protected void grantPermissionsToCreator(QueryState state)
-    {
-        try
-        {
-            IResource resource = 
FunctionResource.function(functionName.keyspace, functionName.name, argTypes);
-            
DatabaseDescriptor.getAuthorizer().grant(AuthenticatedUser.SYSTEM_USER,
-                                                     
resource.applicablePermissions(),
-                                                     resource,
-                                                     
RoleResource.role(state.getClientState().getUser().getName()));
-        }
-        catch (RequestExecutionException e)
-        {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public void checkAccess(ClientState state) throws UnauthorizedException, 
InvalidRequestException
-    {
-        if (Schema.instance.findFunction(functionName, argTypes).isPresent() 
&& orReplace)
-            state.ensureHasPermission(Permission.ALTER, 
FunctionResource.function(functionName.keyspace,
-                                                                               
   functionName.name,
-                                                                               
   argTypes));
-        else
-            state.ensureHasPermission(Permission.CREATE, 
FunctionResource.keyspace(functionName.keyspace));
-    }
-
-    public void validate(ClientState state) throws InvalidRequestException
-    {
-        UDFunction.assertUdfsEnabled(language);
-
-        if (ifNotExists && orReplace)
-            throw new InvalidRequestException("Cannot use both 'OR REPLACE' 
and 'IF NOT EXISTS' directives");
-
-        KeyspaceMetadata ksm = 
Schema.instance.getKeyspaceMetadata(functionName.keyspace);
-        if (null == ksm)
-            throw new InvalidRequestException(String.format("Cannot add 
function '%s' to non existing keyspace '%s'.", functionName.name, 
functionName.keyspace));
-        if (ksm.isVirtual())
-            throw new InvalidRequestException("Cannot create functions in 
virtual keyspaces");
-    }
-
-    public Event.SchemaChange announceMigration(QueryState queryState, boolean 
isLocalOnly) throws RequestValidationException
-    {
-        Function old = Schema.instance.findFunction(functionName, 
argTypes).orElse(null);
-        boolean replaced = old != null;
-        if (replaced)
-        {
-            if (ifNotExists)
-                return null;
-            if (!orReplace)
-                throw new InvalidRequestException(String.format("Function %s 
already exists", old));
-            if (!(old instanceof ScalarFunction))
-                throw new InvalidRequestException(String.format("Function %s 
can only replace a function", old));
-            if (calledOnNullInput != ((ScalarFunction) 
old).isCalledOnNullInput())
-                throw new InvalidRequestException(String.format("Function %s 
can only be replaced with %s", old,
-                                                                
calledOnNullInput ? "CALLED ON NULL INPUT" : "RETURNS NULL ON NULL INPUT"));
-
-            if (!Functions.typesMatch(old.returnType(), returnType))
-                throw new InvalidRequestException(String.format("Cannot 
replace function %s, the new return type %s is not compatible with the return 
type %s of existing function",
-                                                                functionName, 
returnType.asCQL3Type(), old.returnType().asCQL3Type()));
-        }
-
-        UDFunction udFunction = UDFunction.create(functionName, argNames, 
argTypes, returnType, calledOnNullInput, language, body);
-
-        MigrationManager.announceNewFunction(udFunction, isLocalOnly);
-
-        return new Event.SchemaChange(replaced ? 
Event.SchemaChange.Change.UPDATED : Event.SchemaChange.Change.CREATED,
-                                      Event.SchemaChange.Target.FUNCTION,
-                                      udFunction.name().keyspace, 
udFunction.name().name, 
AbstractType.asCQLTypeStringList(udFunction.argTypes()));
-    }
-
-    private AbstractType<?> prepareType(String typeName, CQL3Type.Raw rawType)
-    {
-        if (rawType.isFrozen())
-            throw new InvalidRequestException(String.format("The function %s 
should not be frozen; remove the frozen<> modifier", typeName));
-
-        // UDT are not supported non frozen but we do not allow the frozen 
keyword for argument. So for the moment we
-        // freeze them here
-        if (!rawType.canBeNonFrozen())
-            rawType.freeze();
-
-        AbstractType<?> type = 
rawType.prepare(functionName.keyspace).getType();
-        return type;
-    }
-    
-    @Override
-    public String toString()
-    {
-        return ToStringBuilder.reflectionToString(this, 
ToStringStyle.SHORT_PREFIX_STYLE);
-    }
-
-    @Override
-    public AuditLogContext getAuditLogContext()
-    {
-        return new AuditLogContext(AuditLogEntryType.CREATE_FUNCTION, 
functionName.keyspace, functionName.name);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/207c80c1/src/java/org/apache/cassandra/cql3/statements/CreateIndexStatement.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/cql3/statements/CreateIndexStatement.java 
b/src/java/org/apache/cassandra/cql3/statements/CreateIndexStatement.java
deleted file mode 100644
index 778c4a3..0000000
--- a/src/java/org/apache/cassandra/cql3/statements/CreateIndexStatement.java
+++ /dev/null
@@ -1,275 +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.cql3.statements;
-
-import java.util.*;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Strings;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Sets;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.cassandra.audit.AuditLogEntryType;
-import org.apache.cassandra.auth.Permission;
-import org.apache.cassandra.cql3.CFName;
-import org.apache.cassandra.cql3.ColumnIdentifier;
-import org.apache.cassandra.cql3.IndexName;
-import org.apache.cassandra.db.marshal.MapType;
-import org.apache.cassandra.exceptions.InvalidRequestException;
-import org.apache.cassandra.exceptions.RequestValidationException;
-import org.apache.cassandra.exceptions.UnauthorizedException;
-import org.apache.cassandra.schema.ColumnMetadata;
-import org.apache.cassandra.schema.IndexMetadata;
-import org.apache.cassandra.schema.Indexes;
-import org.apache.cassandra.schema.MigrationManager;
-import org.apache.cassandra.schema.Schema;
-import org.apache.cassandra.schema.TableMetadata;
-import org.apache.cassandra.service.ClientState;
-import org.apache.cassandra.service.QueryState;
-import org.apache.cassandra.transport.Event;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
-
-import static 
org.apache.cassandra.cql3.statements.RequestValidations.checkFalse;
-import static 
org.apache.cassandra.cql3.statements.RequestValidations.invalidRequest;
-
-/** A <code>CREATE INDEX</code> statement parsed from a CQL query. */
-public class CreateIndexStatement extends SchemaAlteringStatement
-{
-    private static final Logger logger = 
LoggerFactory.getLogger(CreateIndexStatement.class);
-
-    private final String indexName;
-    private final List<IndexTarget.Raw> rawTargets;
-    private final IndexPropDefs properties;
-    private final boolean ifNotExists;
-
-    public CreateIndexStatement(CFName name,
-                                IndexName indexName,
-                                List<IndexTarget.Raw> targets,
-                                IndexPropDefs properties,
-                                boolean ifNotExists)
-    {
-        super(name);
-        this.indexName = indexName.getIdx();
-        this.rawTargets = targets;
-        this.properties = properties;
-        this.ifNotExists = ifNotExists;
-    }
-
-    public void checkAccess(ClientState state) throws UnauthorizedException, 
InvalidRequestException
-    {
-        state.hasColumnFamilyAccess(keyspace(), columnFamily(), 
Permission.ALTER);
-    }
-
-    public void validate(ClientState state) throws RequestValidationException
-    {
-        TableMetadata table = Schema.instance.validateTable(keyspace(), 
columnFamily());
-
-        if (table.isVirtual())
-            throw new InvalidRequestException("Secondary indexes are not 
supported on virtual tables");
-
-        if (table.isCounter())
-            throw new InvalidRequestException("Secondary indexes are not 
supported on counter tables");
-
-        if (table.isView())
-            throw new InvalidRequestException("Secondary indexes are not 
supported on materialized views");
-
-        if (table.isCompactTable() && !table.isStaticCompactTable())
-            throw new InvalidRequestException("Secondary indexes are not 
supported on COMPACT STORAGE tables that have clustering columns");
-
-        List<IndexTarget> targets = new ArrayList<>(rawTargets.size());
-        for (IndexTarget.Raw rawTarget : rawTargets)
-            targets.add(rawTarget.prepare(table));
-
-        if (targets.isEmpty() && !properties.isCustom)
-            throw new InvalidRequestException("Only CUSTOM indexes can be 
created without specifying a target column");
-
-        if (targets.size() > 1)
-            validateTargetsForMultiColumnIndex(targets);
-
-        for (IndexTarget target : targets)
-        {
-            ColumnMetadata cd = table.getColumn(target.column);
-
-            if (cd == null)
-                throw new InvalidRequestException("No column definition found 
for column " + target.column);
-
-            if (cd.type.referencesDuration())
-            {
-                checkFalse(cd.type.isCollection(), "Secondary indexes are not 
supported on collections containing durations");
-                checkFalse(cd.type.isTuple(), "Secondary indexes are not 
supported on tuples containing durations");
-                checkFalse(cd.type.isUDT(), "Secondary indexes are not 
supported on UDTs containing durations");
-                throw invalidRequest("Secondary indexes are not supported on 
duration columns");
-            }
-
-            // TODO: we could lift that limitation
-            if (table.isCompactTable() && cd.isPrimaryKeyColumn())
-                throw new InvalidRequestException("Secondary indexes are not 
supported on PRIMARY KEY columns in COMPACT STORAGE tables");
-
-            if (cd.kind == ColumnMetadata.Kind.PARTITION_KEY && 
table.partitionKeyColumns().size() == 1)
-                throw new InvalidRequestException(String.format("Cannot create 
secondary index on partition key column %s", target.column));
-
-            boolean isMap = cd.type instanceof MapType;
-            boolean isFrozenCollection = cd.type.isCollection() && 
!cd.type.isMultiCell();
-            if (isFrozenCollection)
-            {
-                validateForFrozenCollection(target);
-            }
-            else
-            {
-                validateNotFullIndex(target);
-                validateIsSimpleIndexIfTargetColumnNotCollection(cd, target);
-                validateTargetColumnIsMapIfIndexInvolvesKeys(isMap, target);
-            }
-
-            checkFalse(cd.type.isUDT() && cd.type.isMultiCell(), "Secondary 
indexes are not supported on non-frozen UDTs");
-        }
-
-        if (!Strings.isNullOrEmpty(indexName))
-        {
-            if 
(Schema.instance.getKeyspaceMetadata(keyspace()).existingIndexNames(null).contains(indexName))
-            {
-                if (ifNotExists)
-                    return;
-                else
-                    throw new InvalidRequestException(String.format("Index %s 
already exists", indexName));
-            }
-        }
-
-        properties.validate();
-    }
-
-    private void validateForFrozenCollection(IndexTarget target) throws 
InvalidRequestException
-    {
-        if (target.type != IndexTarget.Type.FULL)
-            throw new InvalidRequestException(String.format("Cannot create 
%s() index on frozen column %s. " +
-                                                            "Frozen 
collections only support full() indexes",
-                                                            target.type, 
target.column));
-    }
-
-    private void validateNotFullIndex(IndexTarget target) throws 
InvalidRequestException
-    {
-        if (target.type == IndexTarget.Type.FULL)
-            throw new InvalidRequestException("full() indexes can only be 
created on frozen collections");
-    }
-
-    private void 
validateIsSimpleIndexIfTargetColumnNotCollection(ColumnMetadata cd, IndexTarget 
target) throws InvalidRequestException
-    {
-        if (!cd.type.isCollection() && target.type != IndexTarget.Type.SIMPLE)
-            throw new InvalidRequestException(String.format("Cannot create 
%s() index on %s. " +
-                                                            "Non-collection 
columns support only simple indexes",
-                                                            
target.type.toString(), target.column));
-    }
-
-    private void validateTargetColumnIsMapIfIndexInvolvesKeys(boolean isMap, 
IndexTarget target) throws InvalidRequestException
-    {
-        if (target.type == IndexTarget.Type.KEYS || target.type == 
IndexTarget.Type.KEYS_AND_VALUES)
-        {
-            if (!isMap)
-                throw new InvalidRequestException(String.format("Cannot create 
index on %s of column %s with non-map type",
-                                                                target.type, 
target.column));
-        }
-    }
-
-    private void validateTargetsForMultiColumnIndex(List<IndexTarget> targets)
-    {
-        if (!properties.isCustom)
-            throw new InvalidRequestException("Only CUSTOM indexes support 
multiple columns");
-
-        Set<ColumnIdentifier> columns = 
Sets.newHashSetWithExpectedSize(targets.size());
-        for (IndexTarget target : targets)
-            if (!columns.add(target.column))
-                throw new InvalidRequestException("Duplicate column " + 
target.column + " in index target list");
-    }
-
-    public Event.SchemaChange announceMigration(QueryState queryState, boolean 
isLocalOnly) throws RequestValidationException
-    {
-        TableMetadata current = Schema.instance.getTableMetadata(keyspace(), 
columnFamily());
-        List<IndexTarget> targets = new ArrayList<>(rawTargets.size());
-        for (IndexTarget.Raw rawTarget : rawTargets)
-            targets.add(rawTarget.prepare(current));
-
-        String acceptedName = indexName;
-        if (Strings.isNullOrEmpty(acceptedName))
-        {
-            acceptedName = Indexes.getAvailableIndexName(keyspace(),
-                                                         columnFamily(),
-                                                         targets.size() == 1 ? 
targets.get(0).column.toString() : null);
-        }
-
-        if 
(Schema.instance.getKeyspaceMetadata(keyspace()).existingIndexNames(null).contains(acceptedName))
-        {
-            if (ifNotExists)
-                return null;
-            else
-                throw new InvalidRequestException(String.format("Index %s 
already exists", acceptedName));
-        }
-
-        IndexMetadata.Kind kind;
-        Map<String, String> indexOptions;
-        if (properties.isCustom)
-        {
-            kind = IndexMetadata.Kind.CUSTOM;
-            indexOptions = properties.getOptions();
-        }
-        else
-        {
-            indexOptions = Collections.emptyMap();
-            kind = current.isCompound() ? IndexMetadata.Kind.COMPOSITES : 
IndexMetadata.Kind.KEYS;
-        }
-
-        IndexMetadata index = IndexMetadata.fromIndexTargets(targets, 
acceptedName, kind, indexOptions);
-
-        // check to disallow creation of an index which duplicates an existing 
one in all but name
-        Optional<IndexMetadata> existingIndex = 
Iterables.tryFind(current.indexes, existing -> 
existing.equalsWithoutName(index));
-        if (existingIndex.isPresent())
-        {
-            if (ifNotExists)
-                return null;
-            else
-                throw new InvalidRequestException(String.format("Index %s is a 
duplicate of existing index %s",
-                                                                index.name,
-                                                                
existingIndex.get().name));
-        }
-
-        TableMetadata updated =
-            current.unbuild()
-                   .indexes(current.indexes.with(index))
-                   .build();
-
-        logger.trace("Updating index definition for {}", indexName);
-
-        MigrationManager.announceTableUpdate(updated, isLocalOnly);
-
-        // Creating an index is akin to updating the CF
-        return new Event.SchemaChange(Event.SchemaChange.Change.UPDATED, 
Event.SchemaChange.Target.TABLE, keyspace(), columnFamily());
-    }
-    
-    @Override
-    public String toString()
-    {
-        return ToStringBuilder.reflectionToString(this, 
ToStringStyle.SHORT_PREFIX_STYLE);
-    }
-    @Override
-    public AuditLogContext getAuditLogContext()
-    {
-        return new AuditLogContext(AuditLogEntryType.CREATE_INDEX, keyspace(), 
indexName);
-    }
-}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to