Merge branch 'cassandra-2.2' into cassandra-3.0

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

Branch: refs/heads/cassandra-3.0
Commit: 3079ae60d29baec262a4b05d7082e88091299d26
Parents: 8bfe09f e5c4027
Author: Aleksey Yeschenko <alek...@apache.org>
Authored: Wed Apr 27 17:55:27 2016 +0100
Committer: Aleksey Yeschenko <alek...@apache.org>
Committed: Wed Apr 27 17:57:59 2016 +0100

----------------------------------------------------------------------
 CHANGES.txt                                           |  3 ++-
 .../cql3/statements/AlterTableStatement.java          |  2 +-
 .../cassandra/cql3/statements/AlterTypeStatement.java |  2 +-
 .../cql3/statements/CreateIndexStatement.java         |  2 +-
 .../cql3/statements/CreateTriggerStatement.java       |  2 +-
 .../cassandra/cql3/statements/DropIndexStatement.java |  2 +-
 .../cql3/statements/DropTriggerStatement.java         |  2 +-
 .../org/apache/cassandra/schema/SchemaKeyspace.java   | 14 ++------------
 .../apache/cassandra/service/MigrationManager.java    |  8 ++++----
 .../org/apache/cassandra/thrift/CassandraServer.java  |  2 +-
 test/unit/org/apache/cassandra/schema/DefsTest.java   | 14 +++++++-------
 .../apache/cassandra/schema/SchemaKeyspaceTest.java   |  2 +-
 .../apache/cassandra/triggers/TriggersSchemaTest.java |  4 ++--
 13 files changed, 25 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/3079ae60/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index bc15d32,3641816..6b6bc1f
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,27 -1,11 +1,28 @@@
 -2.2.7
 +3.0.6
 + * Fix sstabledump not showing cells after tombstone marker (CASSANDRA-11654)
 + * Ignore all LocalStrategy keyspaces for streaming and other related
 +   operations (CASSANDRA-11627)
 + * Ensure columnfilter covers indexed columns for thrift 2i queries 
(CASSANDRA-11523)
 + * Only open one sstable scanner per sstable (CASSANDRA-11412)
 + * Option to specify ProtocolVersion in cassandra-stress (CASSANDRA-11410)
 + * ArithmeticException in avgFunctionForDecimal (CASSANDRA-11485)
 + * LogAwareFileLister should only use OLD sstable files in current folder to 
determine disk consistency (CASSANDRA-11470)
 + * Notify indexers of expired rows during compaction (CASSANDRA-11329)
 + * Properly respond with ProtocolError when a v1/v2 native protocol
 +   header is received (CASSANDRA-11464)
 + * Validate that num_tokens and initial_token are consistent with one another 
(CASSANDRA-10120)
 +Merged from 2.2:
+  * Fix is_dense recalculation for Thrift-updated tables (CASSANDRA-11502)
   * Remove unnescessary file existence check during anticompaction 
(CASSANDRA-11660)
   * Add missing files to debian packages (CASSANDRA-11642)
   * Avoid calling Iterables::concat in loops during 
ModificationStatement::getFunctions (CASSANDRA-11621)
   * cqlsh: COPY FROM should use regular inserts for single statement batches 
and
-           report errors correctly if workers processes crash on 
initialization (CASSANDRA-11474)
+    report errors correctly if workers processes crash on initialization 
(CASSANDRA-11474)
   * Always close cluster with connection in CqlRecordWriter (CASSANDRA-11553)
 + * Allow only DISTINCT queries with partition keys restrictions 
(CASSANDRA-11339)
 + * CqlConfigHelper no longer requires both a keystore and truststore to work 
(CASSANDRA-11532)
 + * Make deprecated repair methods backward-compatible with previous 
notification service (CASSANDRA-11430)
 + * IncomingStreamingConnection version check message wrong (CASSANDRA-11462)
  Merged from 2.1:
   * cqlsh COPY FROM fails for null values with non-prepared statements 
(CASSANDRA-11631)
   * Make cython optional in pylib/setup.py (CASSANDRA-11630)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/3079ae60/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
index 3515c6b,f4a7b39..381971f
--- a/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
@@@ -322,61 -284,8 +322,61 @@@ public class AlterTableStatement extend
                  break;
          }
  
-         MigrationManager.announceColumnFamilyUpdate(cfm, false, isLocalOnly);
+         MigrationManager.announceColumnFamilyUpdate(cfm, isLocalOnly);
 -        return true;
 +
 +        if (viewUpdates != null)
 +        {
 +            for (ViewDefinition viewUpdate : viewUpdates)
 +                MigrationManager.announceViewUpdate(viewUpdate, isLocalOnly);
 +        }
 +        return new Event.SchemaChange(Event.SchemaChange.Change.UPDATED, 
Event.SchemaChange.Target.TABLE, keyspace(), columnFamily());
 +    }
 +
 +    private static void validateAlter(CFMetaData cfm, ColumnDefinition def, 
AbstractType<?> validatorType)
 +    {
 +        switch (def.kind)
 +        {
 +            case PARTITION_KEY:
 +                if (validatorType instanceof CounterColumnType)
 +                    throw new InvalidRequestException(String.format("counter 
type is not supported for PRIMARY KEY part %s", def.name));
 +
 +                AbstractType<?> currentType = 
cfm.getKeyValidatorAsClusteringComparator().subtype(def.position());
 +                if (!validatorType.isValueCompatibleWith(currentType))
 +                    throw new ConfigurationException(String.format("Cannot 
change %s from type %s to type %s: types are incompatible.",
 +                                                                   def.name,
 +                                                                   
currentType.asCQL3Type(),
 +                                                                   
validatorType.asCQL3Type()));
 +                break;
 +            case CLUSTERING:
 +                if (!cfm.isCQLTable())
 +                    throw new InvalidRequestException(String.format("Cannot 
alter clustering column %s in a non-CQL3 table", def.name));
 +
 +                AbstractType<?> oldType = 
cfm.comparator.subtype(def.position());
 +                // Note that CFMetaData.validateCompatibility already 
validate the change we're about to do. However, the error message it
 +                // sends is a bit cryptic for a CQL3 user, so validating here 
for a sake of returning a better error message
 +                // Do note that we need isCompatibleWith here, not just 
isValueCompatibleWith.
 +                if (!validatorType.isCompatibleWith(oldType))
 +                {
 +                    throw new ConfigurationException(String.format("Cannot 
change %s from type %s to type %s: types are not order-compatible.",
 +                                                                   def.name,
 +                                                                   
oldType.asCQL3Type(),
 +                                                                   
validatorType.asCQL3Type()));
 +                }
 +                break;
 +            case REGULAR:
 +            case STATIC:
 +                // Thrift allows to change a column validator so 
CFMetaData.validateCompatibility will let it slide
 +                // if we change to an incompatible type (contrarily to the 
comparator case). But we don't want to
 +                // allow it for CQL3 (see #5882) so validating it explicitly 
here. We only care about value compatibility
 +                // though since we won't compare values (except when there is 
an index, but that is validated by
 +                // ColumnDefinition already).
 +                if (!validatorType.isValueCompatibleWith(def.type))
 +                    throw new ConfigurationException(String.format("Cannot 
change %s from type %s to type %s: types are incompatible.",
 +                                                                   def.name,
 +                                                                   
def.type.asCQL3Type(),
 +                                                                   
validatorType.asCQL3Type()));
 +                break;
 +        }
      }
  
      public String toString()

http://git-wip-us.apache.org/repos/asf/cassandra/blob/3079ae60/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java
index 8e51c26,9203cf9..bd23971
--- a/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java
@@@ -106,21 -113,11 +106,21 @@@ public abstract class AlterTypeStatemen
              for (ColumnDefinition def : copy.allColumns())
                  modified |= updateDefinition(copy, def, toUpdate.keyspace, 
toUpdate.name, updated);
              if (modified)
-                 MigrationManager.announceColumnFamilyUpdate(copy, false, 
isLocalOnly);
+                 MigrationManager.announceColumnFamilyUpdate(copy, 
isLocalOnly);
          }
  
 +        for (ViewDefinition view : ksm.views)
 +        {
 +            ViewDefinition copy = view.copy();
 +            boolean modified = false;
 +            for (ColumnDefinition def : copy.metadata.allColumns())
 +                modified |= updateDefinition(copy.metadata, def, 
toUpdate.keyspace, toUpdate.name, updated);
 +            if (modified)
 +                MigrationManager.announceViewUpdate(copy, isLocalOnly);
 +        }
 +
          // Other user types potentially using the updated type
 -        for (UserType ut : ksm.userTypes.getAllTypes().values())
 +        for (UserType ut : ksm.types)
          {
              // Re-updating the type we've just updated would be harmless but 
useless so we avoid it.
              // Besides, we use the occasion to drop the old version of the 
type if it's a type rename

http://git-wip-us.apache.org/repos/asf/cassandra/blob/3079ae60/src/java/org/apache/cassandra/cql3/statements/CreateIndexStatement.java
----------------------------------------------------------------------
diff --cc 
src/java/org/apache/cassandra/cql3/statements/CreateIndexStatement.java
index df1965a,d93c0a7..2eebe0d
--- a/src/java/org/apache/cassandra/cql3/statements/CreateIndexStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/CreateIndexStatement.java
@@@ -220,29 -186,17 +220,29 @@@ public class CreateIndexStatement exten
          }
          else
          {
 -            cd.setIndexType(IndexType.KEYS, Collections.<String, 
String>emptyMap());
 +            indexOptions = Collections.emptyMap();
 +            kind = cfm.isCompound() ? IndexMetadata.Kind.COMPOSITES : 
IndexMetadata.Kind.KEYS;
          }
  
 -        cd.setIndexName(indexName);
 -        cfm.addDefaultIndexNames();
 +        IndexMetadata index = IndexMetadata.fromIndexTargets(cfm, 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(cfm.getIndexes(), 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));
 +        }
 +
 +        logger.trace("Updating index definition for {}", indexName);
 +        cfm.indexes(cfm.getIndexes().with(index));
 +
-         MigrationManager.announceColumnFamilyUpdate(cfm, false, isLocalOnly);
+         MigrationManager.announceColumnFamilyUpdate(cfm, isLocalOnly);
 -        return true;
 -    }
  
 -    public Event.SchemaChange changeEvent()
 -    {
          // Creating an index is akin to updating the CF
          return new Event.SchemaChange(Event.SchemaChange.Change.UPDATED, 
Event.SchemaChange.Target.TABLE, keyspace(), columnFamily());
      }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/3079ae60/src/java/org/apache/cassandra/cql3/statements/CreateTriggerStatement.java
----------------------------------------------------------------------
diff --cc 
src/java/org/apache/cassandra/cql3/statements/CreateTriggerStatement.java
index 2720749,ef2f263..94cfc15
--- a/src/java/org/apache/cassandra/cql3/statements/CreateTriggerStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/CreateTriggerStatement.java
@@@ -72,22 -68,24 +72,22 @@@ public class CreateTriggerStatement ext
          }
      }
  
 -    public boolean announceMigration(boolean isLocalOnly) throws 
ConfigurationException, InvalidRequestException
 +    public Event.SchemaChange announceMigration(boolean isLocalOnly) throws 
ConfigurationException, InvalidRequestException
      {
          CFMetaData cfm = Schema.instance.getCFMetaData(keyspace(), 
columnFamily()).copy();
 +        Triggers triggers = cfm.getTriggers();
  
 -        TriggerDefinition triggerDefinition = 
TriggerDefinition.create(triggerName, triggerClass);
 -
 -        if (!ifNotExists || !cfm.containsTriggerDefinition(triggerDefinition))
 +        if (triggers.get(triggerName).isPresent())
          {
 -            cfm.addTriggerDefinition(triggerDefinition);
 -            logger.info("Adding trigger with name {} and class {}", 
triggerName, triggerClass);
 -            MigrationManager.announceColumnFamilyUpdate(cfm, isLocalOnly);
 -            return true;
 +            if (ifNotExists)
 +                return null;
 +            else
 +                throw new InvalidRequestException(String.format("Trigger %s 
already exists", triggerName));
          }
 -        return false;
 -    }
  
 -    public Event.SchemaChange changeEvent()
 -    {
 +        cfm.triggers(triggers.with(TriggerMetadata.create(triggerName, 
triggerClass)));
 +        logger.info("Adding trigger with name {} and class {}", triggerName, 
triggerClass);
-         MigrationManager.announceColumnFamilyUpdate(cfm, false, isLocalOnly);
++        MigrationManager.announceColumnFamilyUpdate(cfm, isLocalOnly);
          return new Event.SchemaChange(Event.SchemaChange.Change.UPDATED, 
Event.SchemaChange.Target.TABLE, keyspace(), columnFamily());
      }
  }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/3079ae60/src/java/org/apache/cassandra/cql3/statements/DropIndexStatement.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/statements/DropIndexStatement.java
index eaf755f,0d33e57..85f5f0d
--- a/src/java/org/apache/cassandra/cql3/statements/DropIndexStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/DropIndexStatement.java
@@@ -66,48 -85,58 +66,48 @@@ public class DropIndexStatement extend
      @Override
      public ResultMessage execute(QueryState state, QueryOptions options) 
throws RequestValidationException
      {
 -        announceMigration(false);
 -        return indexedCF == null ? null : new 
ResultMessage.SchemaChange(changeEvent());
 +        Event.SchemaChange ce = announceMigration(false);
 +        return ce == null ? null : new ResultMessage.SchemaChange(ce);
      }
  
 -    public boolean announceMigration(boolean isLocalOnly) throws 
InvalidRequestException, ConfigurationException
 +    public Event.SchemaChange announceMigration(boolean isLocalOnly) throws 
InvalidRequestException, ConfigurationException
      {
 -        CFMetaData cfm = findIndexedCF();
 +        CFMetaData cfm = lookupIndexedTable();
          if (cfm == null)
 -            return false;
 +            return null;
  
 -        CFMetaData updatedCfm = updateCFMetadata(cfm);
 -        indexedCF = updatedCfm.cfName;
 +        CFMetaData updatedCfm = cfm.copy();
 +        updatedCfm.indexes(updatedCfm.getIndexes().without(indexName));
-         MigrationManager.announceColumnFamilyUpdate(updatedCfm, false, 
isLocalOnly);
+         MigrationManager.announceColumnFamilyUpdate(updatedCfm, isLocalOnly);
 -        return true;
 -    }
 -
 -    private CFMetaData updateCFMetadata(CFMetaData cfm)
 -    {
 -        ColumnDefinition column = findIndexedColumn(cfm);
 -        assert column != null;
 -        CFMetaData cloned = cfm.copy();
 -        ColumnDefinition toChange = cloned.getColumnDefinition(column.name);
 -        assert toChange.getIndexName() != null && 
toChange.getIndexName().equals(indexName);
 -        toChange.setIndexName(null);
 -        toChange.setIndexType(null, null);
 -        return cloned;
 +        // Dropping an index is akin to updating the CF
 +        // Note that we shouldn't call columnFamily() at this point because 
the index has been dropped and the call to lookupIndexedTable()
 +        // in that method would now throw.
 +        return new Event.SchemaChange(Event.SchemaChange.Change.UPDATED, 
Event.SchemaChange.Target.TABLE, cfm.ksName, cfm.cfName);
      }
  
 -    private CFMetaData findIndexedCF() throws InvalidRequestException
 +    /**
 +     * The table for which the index should be dropped, or null if the index 
doesn't exist
 +     *
 +     * @return the metadata for the table containing the dropped index, or 
{@code null}
 +     * if the index to drop cannot be found but "IF EXISTS" is set on the 
statement.
 +     *
 +     * @throws InvalidRequestException if the index cannot be found and "IF 
EXISTS" is not
 +     * set on the statement.
 +     */
 +    private CFMetaData lookupIndexedTable()
      {
 -        KSMetaData ksm = Schema.instance.getKSMetaData(keyspace());
 +        KeyspaceMetadata ksm = Schema.instance.getKSMetaData(keyspace());
          if (ksm == null)
              throw new KeyspaceNotDefinedException("Keyspace " + keyspace() + 
" does not exist");
 -        for (CFMetaData cfm : ksm.cfMetaData().values())
 -        {
 -            if (findIndexedColumn(cfm) != null)
 -                return cfm;
 -        }
  
 -        if (ifExists)
 -            return null;
 -        else
 -            throw new InvalidRequestException("Index '" + indexName + "' 
could not be found in any of the tables of keyspace '" + keyspace() + '\'');
 -    }
 -
 -    private ColumnDefinition findIndexedColumn(CFMetaData cfm)
 -    {
 -        for (ColumnDefinition column : cfm.allColumns())
 -        {
 -            if (column.getIndexType() != null && column.getIndexName() != 
null && column.getIndexName().equals(indexName))
 -                return column;
 -        }
 -        return null;
 +        return ksm.findIndexedTable(indexName)
 +                  .orElseGet(() -> {
 +                      if (ifExists)
 +                          return null;
 +                      else
 +                          throw new 
InvalidRequestException(String.format("Index '%s' could not be found in any " +
 +                                                                          "of 
the tables of keyspace '%s'",
 +                                                                          
indexName, keyspace()));
 +                  });
      }
  }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/3079ae60/src/java/org/apache/cassandra/cql3/statements/DropTriggerStatement.java
----------------------------------------------------------------------
diff --cc 
src/java/org/apache/cassandra/cql3/statements/DropTriggerStatement.java
index 562b4e8,8267b4e..3f61e01
--- a/src/java/org/apache/cassandra/cql3/statements/DropTriggerStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/DropTriggerStatement.java
@@@ -58,22 -57,22 +58,22 @@@ public class DropTriggerStatement exten
          ThriftValidation.validateColumnFamily(keyspace(), columnFamily());
      }
  
 -    public boolean announceMigration(boolean isLocalOnly) throws 
ConfigurationException, InvalidRequestException
 +    public Event.SchemaChange announceMigration(boolean isLocalOnly) throws 
ConfigurationException, InvalidRequestException
      {
          CFMetaData cfm = Schema.instance.getCFMetaData(keyspace(), 
columnFamily()).copy();
 -        if (cfm.removeTrigger(triggerName))
 +        Triggers triggers = cfm.getTriggers();
 +
 +        if (!triggers.get(triggerName).isPresent())
          {
 -            logger.info("Dropping trigger with name {}", triggerName);
 -            MigrationManager.announceColumnFamilyUpdate(cfm, isLocalOnly);
 -            return true;
 +            if (ifExists)
 +                return null;
 +            else
 +                throw new InvalidRequestException(String.format("Trigger %s 
was not found", triggerName));
          }
 -        if (!ifExists)
 -            throw new InvalidRequestException(String.format("Trigger %s was 
not found", triggerName));
 -        return false;
 -    }
  
 -    public Event.SchemaChange changeEvent()
 -    {
 +        logger.info("Dropping trigger with name {}", triggerName);
 +        cfm.triggers(triggers.without(triggerName));
-         MigrationManager.announceColumnFamilyUpdate(cfm, false, isLocalOnly);
++        MigrationManager.announceColumnFamilyUpdate(cfm, isLocalOnly);
          return new Event.SchemaChange(Event.SchemaChange.Change.UPDATED, 
Event.SchemaChange.Target.TABLE, keyspace(), columnFamily());
      }
  }

Reply via email to