diff --git a/CHANGES.txt b/CHANGES.txt index 2500043528..baf0e1e2e7 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -107,6 +107,7 @@ * Duplicate the buffer before passing it to analyser in SASI operation (CASSANDRA-13512) * Properly evict pstmts from prepared statements cache (CASSANDRA-13641) Merged from 3.0: + * Fix ALTER TABLE statement to atomically propagate changes to the table and its MVs (CASSANDRA-12952) * Fixed ambiguous output of nodetool tablestats command (CASSANDRA-13722) * Fix Digest mismatch Exception if hints file has UnknownColumnFamily (CASSANDRA-13696) * Purge tombstones created by expired cells (CASSANDRA-13643) diff --git a/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java b/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java index 35459dec56..0c45647530 100644 --- a/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java @@ -304,11 +304,7 @@ public class AlterTableStatement extends SchemaAlteringStatement break; } - // FIXME: Should really be a single announce for the table and views. - MigrationManager.announceTableUpdate(builder.build(), isLocalOnly); - for (ViewMetadata viewUpdate : viewUpdates) - MigrationManager.announceViewUpdate(viewUpdate, isLocalOnly); - + MigrationManager.announceTableUpdate(builder.build(), viewUpdates, isLocalOnly); return new Event.SchemaChange(Event.SchemaChange.Change.UPDATED, Event.SchemaChange.Target.TABLE, keyspace(), columnFamily()); } diff --git a/src/java/org/apache/cassandra/schema/MigrationManager.java b/src/java/org/apache/cassandra/schema/MigrationManager.java index 7ad8cad1ff..d8a3b72475 100644 --- a/src/java/org/apache/cassandra/schema/MigrationManager.java +++ b/src/java/org/apache/cassandra/schema/MigrationManager.java @@ -278,6 +278,11 @@ public class MigrationManager } public static void announceTableUpdate(TableMetadata updated, boolean announceLocally) throws ConfigurationException + { + announceTableUpdate(updated, null, announceLocally); + } + + public static void announceTableUpdate(TableMetadata updated, Collection views, boolean announceLocally) throws ConfigurationException { updated.validate(); @@ -288,23 +293,38 @@ public class MigrationManager current.validateCompatibility(updated); + long timestamp = FBUtilities.timestampMicros(); + logger.info("Update table '{}/{}' From {} To {}", current.keyspace, current.name, current, updated); - announce(SchemaKeyspace.makeUpdateTableMutation(ksm, current, updated, FBUtilities.timestampMicros()), announceLocally); + Mutation.SimpleBuilder builder = SchemaKeyspace.makeUpdateTableMutation(ksm, current, updated, timestamp); + + if (views != null) + views.forEach(view -> addViewUpdateToMutationBuilder(view, builder)); + + announce(builder, announceLocally); } public static void announceViewUpdate(ViewMetadata view, boolean announceLocally) throws ConfigurationException + { + KeyspaceMetadata ksm = Schema.instance.getKeyspaceMetadata(view.keyspace); + long timestamp = FBUtilities.timestampMicros(); + Mutation.SimpleBuilder builder = SchemaKeyspace.makeCreateKeyspaceMutation(ksm.name, ksm.params, timestamp); + addViewUpdateToMutationBuilder(view, builder); + announce(builder, announceLocally); + } + + private static void addViewUpdateToMutationBuilder(ViewMetadata view, Mutation.SimpleBuilder builder) { view.metadata.validate(); ViewMetadata oldView = Schema.instance.getView(view.keyspace, view.name); if (oldView == null) throw new ConfigurationException(String.format("Cannot update non existing materialized view '%s' in keyspace '%s'.", view.name, view.keyspace)); - KeyspaceMetadata ksm = Schema.instance.getKeyspaceMetadata(view.keyspace); oldView.metadata.validateCompatibility(view.metadata); logger.info("Update view '{}/{}' From {} To {}", view.keyspace, view.name, oldView, view); - announce(SchemaKeyspace.makeUpdateViewMutation(ksm, oldView, view, FBUtilities.timestampMicros()), announceLocally); + SchemaKeyspace.makeUpdateViewMutation(builder, oldView, view); } public static void announceTypeUpdate(UserType updatedType, boolean announceLocally) diff --git a/src/java/org/apache/cassandra/schema/SchemaKeyspace.java b/src/java/org/apache/cassandra/schema/SchemaKeyspace.java index d2aa7e14cf..69bdf8d49a 100644 --- a/src/java/org/apache/cassandra/schema/SchemaKeyspace.java +++ b/src/java/org/apache/cassandra/schema/SchemaKeyspace.java @@ -744,13 +744,10 @@ public final class SchemaKeyspace return builder; } - static Mutation.SimpleBuilder makeUpdateViewMutation(KeyspaceMetadata keyspace, + public static Mutation.SimpleBuilder makeUpdateViewMutation(Mutation.SimpleBuilder builder, ViewMetadata oldView, - ViewMetadata newView, - long timestamp) + ViewMetadata newView) { - Mutation.SimpleBuilder builder = makeCreateKeyspaceMutation(keyspace.name, keyspace.params, timestamp); - addViewToSchemaMutation(newView, false, builder); MapDifference columnDiff = Maps.difference(oldView.metadata.columns,