This is an automated email from the ASF dual-hosted git repository.

samt pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 7fe30fc313 Expand DDL statements on coordinator before submission to 
the CMS
7fe30fc313 is described below

commit 7fe30fc313ac35b1156f5a37d2069e29cded710b
Author: Alex Petrov <[email protected]>
AuthorDate: Wed Apr 24 15:54:23 2024 +0200

    Expand DDL statements on coordinator before submission to the CMS
    
    Patch by Alex Petrov; reviewed by Stefan Miklosovic and Sam Tunnicliffe for 
CASSANDRA-19592
---
 CHANGES.txt                                        |   1 +
 .../org/apache/cassandra/cql3/SchemaElement.java   |   7 +-
 .../cassandra/cql3/functions/UDAggregate.java      |   2 +-
 .../cassandra/cql3/functions/UDFunction.java       |   2 +-
 .../cql3/statements/DescribeStatement.java         |   6 +-
 .../statements/schema/CreateIndexStatement.java    |  11 ++
 .../statements/schema/CreateKeyspaceStatement.java |  25 ++-
 .../statements/schema/CreateTableStatement.java    |  16 +-
 .../org/apache/cassandra/db/SchemaCQLHelper.java   |   6 +-
 .../org/apache/cassandra/db/marshal/UserType.java  |   2 +-
 .../org/apache/cassandra/schema/IndexMetadata.java |   4 +
 .../apache/cassandra/schema/KeyspaceMetadata.java  |   4 +-
 src/java/org/apache/cassandra/schema/TableId.java  |   8 +-
 .../org/apache/cassandra/schema/TableMetadata.java |  88 ++++++++---
 .../org/apache/cassandra/schema/ViewMetadata.java  |   2 +-
 .../test/log/IndexParamsRecreateTest.java          | 164 ++++++++++++++++++++
 .../test/log/KeyspaceParamsRecreateTest.java       |  94 ++++++++++++
 .../test/log/TableParamsRecreateTest.java          | 168 +++++++++++++++++++++
 .../apache/cassandra/cql3/RandomSchemaTest.java    |   4 +-
 .../cql3/statements/DescribeStatementTest.java     |   5 +-
 .../cql3/validation/entities/UFJavaTest.java       |  16 +-
 .../apache/cassandra/db/SchemaCQLHelperTest.java   |   8 +-
 .../org/apache/cassandra/repair/FuzzTestBase.java  |   6 +-
 23 files changed, 580 insertions(+), 69 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index 9cc67faead..3fbae06ee6 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 5.1
+ * Expand DDL statements on coordinator before submission to the CMS 
(CASSANDRA-19592)
  * Fix number of arguments of String.format() in various classes 
(CASSANDRA-19645)
  * Remove unused fields from config (CASSANDRA-19599)
  * Refactor Relation and Restriction hierarchies (CASSANDRA-19341)
diff --git a/src/java/org/apache/cassandra/cql3/SchemaElement.java 
b/src/java/org/apache/cassandra/cql3/SchemaElement.java
index d99de7c054..2520ecb529 100644
--- a/src/java/org/apache/cassandra/cql3/SchemaElement.java
+++ b/src/java/org/apache/cassandra/cql3/SchemaElement.java
@@ -89,9 +89,10 @@ public interface SchemaElement
     /**
      * Returns a CQL representation of this element
      *
-     * @param withInternals if the internals part of the CQL should be exposed.
-     * @param ifNotExists if "IF NOT EXISTS" should be included.
+     * @param withWarnings if commented warnings should be included
+     * @param withInternals if the internals part of the CQL should be exposed
+     * @param ifNotExists if "IF NOT EXISTS" should be included
      * @return a CQL representation of this element
      */
-    String toCqlString(boolean withInternals, boolean ifNotExists);
+    String toCqlString(boolean withWarnings, boolean withInternals, boolean 
ifNotExists);
 }
diff --git a/src/java/org/apache/cassandra/cql3/functions/UDAggregate.java 
b/src/java/org/apache/cassandra/cql3/functions/UDAggregate.java
index 161ac8e353..6a9419efd4 100644
--- a/src/java/org/apache/cassandra/cql3/functions/UDAggregate.java
+++ b/src/java/org/apache/cassandra/cql3/functions/UDAggregate.java
@@ -350,7 +350,7 @@ public class UDAggregate extends UserFunction implements 
AggregateFunction
     }
 
     @Override
-    public String toCqlString(boolean withInternals, boolean ifNotExists)
+    public String toCqlString(boolean withWarnings, boolean withInternals, 
boolean ifNotExists)
     {
         CqlBuilder builder = new CqlBuilder();
         builder.append("CREATE AGGREGATE ");
diff --git a/src/java/org/apache/cassandra/cql3/functions/UDFunction.java 
b/src/java/org/apache/cassandra/cql3/functions/UDFunction.java
index ce660acdef..39f8f9b7fa 100644
--- a/src/java/org/apache/cassandra/cql3/functions/UDFunction.java
+++ b/src/java/org/apache/cassandra/cql3/functions/UDFunction.java
@@ -324,7 +324,7 @@ public abstract class UDFunction extends UserFunction 
implements ScalarFunction
     }
 
     @Override
-    public String toCqlString(boolean withInternals, boolean ifNotExists)
+    public String toCqlString(boolean withWarnings, boolean withInternals, 
boolean ifNotExists)
     {
         CqlBuilder builder = new CqlBuilder();
         builder.append("CREATE FUNCTION ");
diff --git 
a/src/java/org/apache/cassandra/cql3/statements/DescribeStatement.java 
b/src/java/org/apache/cassandra/cql3/statements/DescribeStatement.java
index 30e039e6b4..eff03f8cab 100644
--- a/src/java/org/apache/cassandra/cql3/statements/DescribeStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/DescribeStatement.java
@@ -370,7 +370,7 @@ public abstract class DescribeStatement<T> extends 
CQLStatement.Raw implements C
                 return 
ImmutableList.of(bytes(element.elementKeyspaceQuotedIfNeeded()),
                                         
bytes(element.elementType().toString()),
                                         
bytes(element.elementNameQuotedIfNeeded()),
-                                        
bytes(element.toCqlString(withInternals, false)));
+                                        bytes(element.toCqlString(true, 
withInternals, false)));
             }
         };
     }
@@ -420,7 +420,7 @@ public abstract class DescribeStatement<T> extends 
CQLStatement.Raw implements C
             return 
ImmutableList.of(bytes(element.elementKeyspaceQuotedIfNeeded()),
                                     bytes(element.elementType().toString()),
                                     bytes(element.elementNameQuotedIfNeeded()),
-                                    bytes(element.toCqlString(withInternals, 
false)));
+                                    bytes(element.toCqlString(true, 
withInternals, false)));
         }
     }
 
@@ -570,7 +570,7 @@ public abstract class DescribeStatement<T> extends 
CQLStatement.Raw implements C
                     }
 
                     @Override
-                    public String toCqlString(boolean withInternals, boolean 
ifNotExists)
+                    public String toCqlString(boolean withWarnings, boolean 
withInternals, boolean ifNotExists)
                     {
                         return index.toCqlString(table, ifNotExists);
                     }
diff --git 
a/src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java
 
b/src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java
index bf00c581c2..92466bf5b3 100644
--- 
a/src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java
+++ 
b/src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java
@@ -85,6 +85,7 @@ public final class CreateIndexStatement extends 
AlterSchemaStatement
     private final List<IndexTarget.Raw> rawIndexTargets;
     private final IndexAttributes attrs;
     private final boolean ifNotExists;
+    private String expandedCql;
 
     private ClientState state;
 
@@ -103,6 +104,14 @@ public final class CreateIndexStatement extends 
AlterSchemaStatement
         this.ifNotExists = ifNotExists;
     }
 
+    @Override
+    public String cql()
+    {
+        if (expandedCql != null)
+            return expandedCql;
+        return super.cql();
+    }
+
     @Override
     public void validate(ClientState state)
     {
@@ -192,6 +201,8 @@ public final class CreateIndexStatement extends 
AlterSchemaStatement
             throw ire(INDEX_DUPLICATE_OF_EXISTING, index.name, 
equalIndex.name);
         }
 
+        this.expandedCql = index.toCqlString(table, ifNotExists);
+
         TableMetadata newTable = table.withSwapped(table.indexes.with(index));
         newTable.validate();
 
diff --git 
a/src/java/org/apache/cassandra/cql3/statements/schema/CreateKeyspaceStatement.java
 
b/src/java/org/apache/cassandra/cql3/statements/schema/CreateKeyspaceStatement.java
index 16a117c890..533d48bd09 100644
--- 
a/src/java/org/apache/cassandra/cql3/statements/schema/CreateKeyspaceStatement.java
+++ 
b/src/java/org/apache/cassandra/cql3/statements/schema/CreateKeyspaceStatement.java
@@ -49,6 +49,7 @@ public final class CreateKeyspaceStatement extends 
AlterSchemaStatement
 
     private final KeyspaceAttributes attrs;
     private final boolean ifNotExists;
+    private String expandedCql;
 
     public CreateKeyspaceStatement(String keyspaceName, KeyspaceAttributes 
attrs, boolean ifNotExists)
     {
@@ -57,6 +58,15 @@ public final class CreateKeyspaceStatement extends 
AlterSchemaStatement
         this.ifNotExists = ifNotExists;
     }
 
+    @Override
+    public String cql()
+    {
+        if (expandedCql != null)
+            return expandedCql;
+        return super.cql();
+    }
+
+    @Override
     public Keyspaces apply(ClusterMetadata metadata)
     {
         attrs.validate();
@@ -76,17 +86,20 @@ public final class CreateKeyspaceStatement extends 
AlterSchemaStatement
             throw new AlreadyExistsException(keyspaceName);
         }
 
-        KeyspaceMetadata keyspace = KeyspaceMetadata.create(keyspaceName, 
attrs.asNewKeyspaceParams());
+        KeyspaceMetadata keyspaceMetadata = 
KeyspaceMetadata.create(keyspaceName, attrs.asNewKeyspaceParams());
 
-        if (keyspace.params.replication.klass.equals(LocalStrategy.class))
+        if 
(keyspaceMetadata.params.replication.klass.equals(LocalStrategy.class))
             throw ire("Unable to use given strategy class: LocalStrategy is 
reserved for internal use.");
 
-        if (keyspace.params.replication.isMeta())
+        if (keyspaceMetadata.params.replication.isMeta())
             throw ire("Can not create a keyspace with 
MetaReplicationStrategy");
 
-        keyspace.params.validate(keyspaceName, state, metadata);
-        keyspace.replicationStrategy.validateExpectedOptions(metadata);
-        return schema.withAddedOrUpdated(keyspace);
+        keyspaceMetadata.params.validate(keyspaceName, state, metadata);
+        keyspaceMetadata.replicationStrategy.validateExpectedOptions(metadata);
+
+        this.expandedCql = keyspaceMetadata.toCqlString(false, true, 
ifNotExists);
+
+        return schema.withAddedOrUpdated(keyspaceMetadata);
     }
 
     SchemaChange schemaChangeEvent(KeyspacesDiff diff)
diff --git 
a/src/java/org/apache/cassandra/cql3/statements/schema/CreateTableStatement.java
 
b/src/java/org/apache/cassandra/cql3/statements/schema/CreateTableStatement.java
index 264877db7c..59c7046223 100644
--- 
a/src/java/org/apache/cassandra/cql3/statements/schema/CreateTableStatement.java
+++ 
b/src/java/org/apache/cassandra/cql3/statements/schema/CreateTableStatement.java
@@ -65,6 +65,8 @@ public final class CreateTableStatement extends 
AlterSchemaStatement
     private final boolean ifNotExists;
     private final boolean useCompactStorage;
 
+    private String expandedCql;
+
     public CreateTableStatement(String keyspaceName,
                                 String tableName,
                                 Map<ColumnIdentifier, ColumnProperties.Raw> 
rawColumns,
@@ -91,6 +93,14 @@ public final class CreateTableStatement extends 
AlterSchemaStatement
         this.useCompactStorage = useCompactStorage;
     }
 
+    @Override
+    public String cql()
+    {
+        if (expandedCql != null)
+            return expandedCql;
+        return super.cql();
+    }
+
     public Keyspaces apply(ClusterMetadata metadata)
     {
         Keyspaces schema = metadata.schema.getKeyspaces();
@@ -113,7 +123,11 @@ public final class CreateTableStatement extends 
AlterSchemaStatement
             ufBuilder.add(ksm.userFunctions);
 
         TableMetadata.Builder builder = builder(keyspace.types, 
ufBuilder.build()).epoch(metadata.nextEpoch());
-        if (!builder.hasId() && !DatabaseDescriptor.useDeterministicTableID())
+
+        // We do not want to set table ID here just yet, since we are using 
CQL for serialising a fully expanded CREATE TABLE statement.
+        this.expandedCql = builder.build().toCqlString(false, 
attrs.hasProperty(TableAttributes.ID), ifNotExists);
+
+        if (!attrs.hasProperty(TableAttributes.ID) && 
!DatabaseDescriptor.useDeterministicTableID())
             builder.id(TableId.get(metadata));
         TableMetadata table = builder.build();
         table.validate();
diff --git a/src/java/org/apache/cassandra/db/SchemaCQLHelper.java 
b/src/java/org/apache/cassandra/db/SchemaCQLHelper.java
index b959ebcece..5e5f53c314 100644
--- a/src/java/org/apache/cassandra/db/SchemaCQLHelper.java
+++ b/src/java/org/apache/cassandra/db/SchemaCQLHelper.java
@@ -70,14 +70,14 @@ public class SchemaCQLHelper
              * first argument(withInternals) indicates to include table 
metadata id and clustering columns order,
              * second argument(ifNotExists) instructs to include IF NOT EXISTS 
statement within creation statements.
              */
-            return viewMetadata.toCqlString(true, true);
+            return viewMetadata.toCqlString(true, true, true);
         }
 
         /*
          * With addition to withInternals and ifNotExists arguments, 
includeDroppedColumns will include dropped
          * columns as ALTER TABLE statements appended into the snapshot.
          */
-        return metadata.toCqlString(true, true, true);
+        return metadata.toCqlString(true, true, true, true);
     }
 
     /**
@@ -122,7 +122,7 @@ public class SchemaCQLHelper
          */
         return metadata.getReferencedUserTypes()
                        .stream()
-                       .map(name -> getType(metadata, types, 
name).toCqlString(false, ifNotExists));
+                       .map(name -> getType(metadata, types, 
name).toCqlString(true, false, ifNotExists));
     }
 
     /**
diff --git a/src/java/org/apache/cassandra/db/marshal/UserType.java 
b/src/java/org/apache/cassandra/db/marshal/UserType.java
index 81ef9b00bf..816b019dcf 100644
--- a/src/java/org/apache/cassandra/db/marshal/UserType.java
+++ b/src/java/org/apache/cassandra/db/marshal/UserType.java
@@ -500,7 +500,7 @@ public class UserType extends TupleType implements 
SchemaElement
     }
 
     @Override
-    public String toCqlString(boolean withInternals, boolean ifNotExists)
+    public String toCqlString(boolean withWarnings, boolean withInternals, 
boolean ifNotExists)
     {
         CqlBuilder builder = new CqlBuilder();
         builder.append("CREATE TYPE ");
diff --git a/src/java/org/apache/cassandra/schema/IndexMetadata.java 
b/src/java/org/apache/cassandra/schema/IndexMetadata.java
index 6667846e85..fb94c56f01 100644
--- a/src/java/org/apache/cassandra/schema/IndexMetadata.java
+++ b/src/java/org/apache/cassandra/schema/IndexMetadata.java
@@ -314,6 +314,10 @@ public final class IndexMetadata
                    .append(" (")
                    .append(options.get(IndexTarget.TARGET_OPTION_NAME))
                    .append(')');
+
+            builder.append(" USING '")
+                   .append(CassandraIndex.NAME)
+                   .append("'");
         }
         builder.append(';');
     }
diff --git a/src/java/org/apache/cassandra/schema/KeyspaceMetadata.java 
b/src/java/org/apache/cassandra/schema/KeyspaceMetadata.java
index 14ca49f53a..fff222334d 100644
--- a/src/java/org/apache/cassandra/schema/KeyspaceMetadata.java
+++ b/src/java/org/apache/cassandra/schema/KeyspaceMetadata.java
@@ -290,10 +290,10 @@ public final class KeyspaceMetadata implements 
SchemaElement
     }
 
     @Override
-    public String toCqlString(boolean withInternals, boolean ifNotExists)
+    public String toCqlString(boolean withWarnings, boolean withInternals, 
boolean ifNotExists)
     {
         CqlBuilder builder = new CqlBuilder();
-        if (isVirtual())
+        if (isVirtual() && withWarnings)
         {
             builder.append("/*")
                    .newLine()
diff --git a/src/java/org/apache/cassandra/schema/TableId.java 
b/src/java/org/apache/cassandra/schema/TableId.java
index 69a853d45a..d6b7b141a9 100644
--- a/src/java/org/apache/cassandra/schema/TableId.java
+++ b/src/java/org/apache/cassandra/schema/TableId.java
@@ -67,13 +67,13 @@ public class TableId implements Comparable<TableId>
         return new TableId(UUID.fromString(idString));
     }
 
-    public static TableId get(ClusterMetadata metadata)
+    public static TableId get(ClusterMetadata prev)
     {
         int i = 0;
         while (true)
         {
-            TableId tableId = TableId.fromLong(metadata.epoch.getEpoch() + i);
-            if (!tableIdExists(metadata, tableId))
+            TableId tableId = TableId.fromLong(prev.epoch.getEpoch() + i);
+            if (!tableIdExists(prev, tableId))
                 return tableId;
             i++;
         }
@@ -105,7 +105,7 @@ public class TableId implements Comparable<TableId>
         return fromUUID(new UUID(msb, lsb));
     }
 
-    private static TableId fromLong(long start)
+    public static TableId fromLong(long start)
     {
         return TableId.fromUUID(new UUID(MAGIC, start));
     }
diff --git a/src/java/org/apache/cassandra/schema/TableMetadata.java 
b/src/java/org/apache/cassandra/schema/TableMetadata.java
index 5f60250649..3a5cbd3f60 100644
--- a/src/java/org/apache/cassandra/schema/TableMetadata.java
+++ b/src/java/org/apache/cassandra/schema/TableMetadata.java
@@ -1320,23 +1320,25 @@ public class TableMetadata implements SchemaElement
     }
 
     @Override
-    public String toCqlString(boolean withInternals, boolean ifNotExists)
+    public String toCqlString(boolean withWarnings, boolean withInternals, 
boolean ifNotExists)
     {
         CqlBuilder builder = new CqlBuilder(2048);
-        appendCqlTo(builder, withInternals, withInternals, ifNotExists);
+        appendCqlTo(builder, withWarnings, withInternals, withInternals, 
ifNotExists);
         return builder.toString();
     }
 
-    public String toCqlString(boolean includeDroppedColumns,
+    public String toCqlString(boolean withWarnings,
+                              boolean withDroppedColumns,
                               boolean withInternals,
                               boolean ifNotExists)
     {
         CqlBuilder builder = new CqlBuilder(2048);
-        appendCqlTo(builder, includeDroppedColumns, withInternals, 
ifNotExists);
+        appendCqlTo(builder, withWarnings, withDroppedColumns, withInternals, 
ifNotExists);
         return builder.toString();
     }
 
     public void appendCqlTo(CqlBuilder builder,
+                            boolean withWarnings,
                             boolean includeDroppedColumns,
                             boolean withInternals,
                             boolean ifNotExists)
@@ -1344,12 +1346,12 @@ public class TableMetadata implements SchemaElement
         assert !isView();
 
         String createKeyword = "CREATE";
-        if (isVirtual())
+        if (isVirtual() && withWarnings)
         {
             builder.append(String.format("/*\n" +
                     "Warning: Table %s is a virtual table and cannot be 
recreated with CQL.\n" +
                     "Structure, for reference:\n",
-                                         toString()));
+                                         this));
             createKeyword = "VIRTUAL";
         }
 
@@ -1468,7 +1470,6 @@ public class TableMetadata implements SchemaElement
                    .newLine()
                    .append("AND ");
 
-        List<ColumnMetadata> clusteringColumns = clusteringColumns();
         if (!clusteringColumns.isEmpty())
         {
             builder.append("CLUSTERING ORDER BY (")
@@ -1590,6 +1591,7 @@ public class TableMetadata implements SchemaElement
         public final ColumnMetadata compactValueColumn;
 
         private final Set<ColumnMetadata> hiddenColumns;
+
         protected CompactTableMetadata(Builder builder)
         {
             super(builder);
@@ -1605,7 +1607,6 @@ public class TableMetadata implements SchemaElement
                 hiddenColumns = 
Sets.newHashSetWithExpectedSize(clusteringColumns.size() + 1);
                 hiddenColumns.add(compactValueColumn);
                 hiddenColumns.addAll(clusteringColumns);
-
             }
             else
             {
@@ -1717,36 +1718,75 @@ public class TableMetadata implements SchemaElement
             return !Flag.isSuper(flags) && !Flag.isDense(flags) && 
!Flag.isCompound(flags);
         }
 
+        @Override
         public void appendCqlTo(CqlBuilder builder,
+                                boolean withWarnings,
                                 boolean includeDroppedColumns,
                                 boolean internals,
                                 boolean ifNotExists)
         {
-            builder.append("/*")
-                   .newLine()
-                   .append("Warning: Table ")
-                   .append(toString())
-                   .append(" omitted because it has constructs not compatible 
with CQL (was created via legacy API).")
-                   .newLine()
-                   .append("Approximate structure, for reference:")
-                   .newLine()
-                   .append("(this should not be used to reproduce this 
schema)")
-                   .newLine()
-                   .newLine();
+            if (withWarnings)
+            {
+                builder.append("/*")
+                       .newLine()
+                       .append("Warning: Table ")
+                       .append(toString())
+                       .append(" omitted because it has constructs not 
compatible with CQL (was created via legacy API).")
+                       .newLine()
+                       .append("Approximate structure, for reference:")
+                       .newLine()
+                       .append("(this should not be used to reproduce this 
schema)")
+                       .newLine()
+                       .newLine();
+            }
 
-            super.appendCqlTo(builder, includeDroppedColumns, internals, 
ifNotExists);
+            super.appendCqlTo(builder, withWarnings, includeDroppedColumns, 
internals, ifNotExists);
 
-            builder.newLine()
-                   .append("*/");
+            if (withWarnings)
+            {
+                builder.newLine()
+                       .append("*/");
+            }
         }
 
-        void appendTableOptions(CqlBuilder builder, boolean internals)
+        @Override
+        void appendTableOptions(CqlBuilder builder, boolean withInternals)
         {
             builder.append("COMPACT STORAGE")
                    .newLine()
                    .append("AND ");
 
-            super.appendTableOptions(builder, internals);
+            if (withInternals)
+                builder.append("ID = ")
+                       .append(id.toString())
+                       .newLine()
+                       .append("AND ");
+
+            List<ColumnMetadata> visibleClusteringColumns = new ArrayList<>();
+            for (ColumnMetadata column : clusteringColumns)
+            {
+                if (!isHiddenColumn(column))
+                    visibleClusteringColumns.add(column);
+            }
+
+            if (!visibleClusteringColumns.isEmpty())
+            {
+                builder.append("CLUSTERING ORDER BY (")
+                       .appendWithSeparators(visibleClusteringColumns, (b, c) 
-> c.appendNameAndOrderTo(b), ", ")
+                       .append(')')
+                       .newLine()
+                       .append("AND ");
+            }
+
+            if (isVirtual())
+            {
+                builder.append("comment = 
").appendWithSingleQuotes(params.comment);
+            }
+            else
+            {
+                params.appendCqlTo(builder, isView());
+            }
+            builder.append(";");
         }
 
         public static ColumnMetadata 
getCompactValueColumn(RegularAndStaticColumns columns)
diff --git a/src/java/org/apache/cassandra/schema/ViewMetadata.java 
b/src/java/org/apache/cassandra/schema/ViewMetadata.java
index db8b802f78..e20ae25ea0 100644
--- a/src/java/org/apache/cassandra/schema/ViewMetadata.java
+++ b/src/java/org/apache/cassandra/schema/ViewMetadata.java
@@ -241,7 +241,7 @@ public final class ViewMetadata implements SchemaElement
     }
 
     @Override
-    public String toCqlString(boolean withInternals, boolean ifNotExists)
+    public String toCqlString(boolean withWarnings, boolean withInternals, 
boolean ifNotExists)
     {
         CqlBuilder builder = new CqlBuilder(2048);
         appendCqlTo(builder, withInternals, ifNotExists);
diff --git 
a/test/distributed/org/apache/cassandra/distributed/test/log/IndexParamsRecreateTest.java
 
b/test/distributed/org/apache/cassandra/distributed/test/log/IndexParamsRecreateTest.java
new file mode 100644
index 0000000000..7008fca797
--- /dev/null
+++ 
b/test/distributed/org/apache/cassandra/distributed/test/log/IndexParamsRecreateTest.java
@@ -0,0 +1,164 @@
+/*
+ * 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.distributed.test.log;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.cassandra.distributed.Cluster;
+import org.apache.cassandra.distributed.api.ConsistencyLevel;
+import org.apache.cassandra.distributed.api.IInstanceConfig;
+import org.apache.cassandra.distributed.api.IInvokableInstance;
+import org.apache.cassandra.distributed.api.TokenSupplier;
+import org.apache.cassandra.distributed.shared.ClusterUtils;
+import org.apache.cassandra.distributed.shared.NetworkTopology;
+import org.apache.cassandra.distributed.test.TestBaseImpl;
+import org.apache.cassandra.index.internal.CassandraIndex;
+import org.apache.cassandra.index.sai.StorageAttachedIndex;
+import org.apache.cassandra.schema.IndexMetadata;
+import org.apache.cassandra.schema.Indexes;
+import org.apache.cassandra.tcm.ClusterMetadata;
+
+public class IndexParamsRecreateTest extends TestBaseImpl
+{
+    protected static final String CREATE_TABLE_TEMPLATE = "CREATE TABLE %s 
(id1 TEXT PRIMARY KEY, v1 INT, v2 TEXT, v3 TEXT) WITH compaction = " +
+                                                          "{'class' : 
'SizeTieredCompactionStrategy', 'enabled' : false }";
+    protected static final String CREATE_DEFAULT_INDEX_TEMPLATE = "CREATE 
INDEX IF NOT EXISTS default_idx ON %s(%s)";
+    protected static final String CREATE_SAI_INDEX_TEMPLATE = "CREATE INDEX IF 
NOT EXISTS sai_idx ON %s(%s) USING 'sai'";
+    protected static final String CREATE_LEGACY_INDEX_TEMPLATE = "CREATE INDEX 
IF NOT EXISTS legacy_idx ON %s(%s) USING 'legacy_local_table'";
+
+    @Test
+    public void bounceTest() throws Exception
+    {
+        try (Cluster cluster = builder().withNodes(1)
+                                        .withConfig(config -> 
config.set("default_secondary_index", "legacy_local_table")
+                                                                    
.set("default_secondary_index_enabled", "true"))
+                                        .start())
+        {
+            cluster.coordinator(1).execute("CREATE KEYSPACE before_bounce WITH 
replication = {'class': 'SimpleStrategy'}", ConsistencyLevel.ALL);
+            
cluster.coordinator(1).execute(String.format(CREATE_TABLE_TEMPLATE, 
"before_bounce.tbl1"), ConsistencyLevel.ALL);
+            
cluster.coordinator(1).execute(String.format(CREATE_DEFAULT_INDEX_TEMPLATE, 
"before_bounce.tbl1", "v1"), ConsistencyLevel.ALL);
+            
cluster.coordinator(1).execute(String.format(CREATE_LEGACY_INDEX_TEMPLATE, 
"before_bounce.tbl1", "v2"), ConsistencyLevel.ALL);
+            
cluster.coordinator(1).execute(String.format(CREATE_SAI_INDEX_TEMPLATE, 
"before_bounce.tbl1", "v3"), ConsistencyLevel.ALL);
+
+            cluster.get(1).shutdown().get();
+            cluster.get(1).config()
+                   .set("default_secondary_index", "sai")
+                   .set("default_secondary_index_enabled", "true");
+
+            cluster.get(1).startup();
+            cluster.coordinator(1).execute("CREATE KEYSPACE after_bounce WITH 
replication = {'class': 'SimpleStrategy'}", ConsistencyLevel.ALL);
+            
cluster.coordinator(1).execute(String.format(CREATE_TABLE_TEMPLATE, 
"after_bounce.tbl1"), ConsistencyLevel.ALL);
+            
cluster.coordinator(1).execute(String.format(CREATE_DEFAULT_INDEX_TEMPLATE, 
"after_bounce.tbl1", "v1"), ConsistencyLevel.ALL);
+            
cluster.coordinator(1).execute(String.format(CREATE_LEGACY_INDEX_TEMPLATE, 
"after_bounce.tbl1", "v2"), ConsistencyLevel.ALL);
+            
cluster.coordinator(1).execute(String.format(CREATE_SAI_INDEX_TEMPLATE, 
"after_bounce.tbl1", "v3"), ConsistencyLevel.ALL);
+
+            // Where an index class was explicitly specified with USING, 
changing the default should have no effect.
+            // The index created using the default implementation before the 
bounce should preserve its original type
+            // while the one created after bounce should use the new default.
+            cluster.stream().forEach(i -> {
+                i.runOnInstance(() -> {
+                    Indexes before_bounce = 
ClusterMetadata.current().schema.getKeyspace("before_bounce")
+                                                                            
.getMetadata()
+                                                                            
.getTableNullable("tbl1")
+                                            .indexes;
+                    assertIndex(before_bounce.get("legacy_idx").get(), 
IndexMetadata.Kind.COMPOSITES, CassandraIndex.class);
+                    assertIndex(before_bounce.get("sai_idx").get(), 
IndexMetadata.Kind.CUSTOM, StorageAttachedIndex.class);
+                    // the original default was legacy 2i
+                    assertIndex(before_bounce.get("default_idx").get(), 
IndexMetadata.Kind.COMPOSITES, CassandraIndex.class);
+
+                    Indexes after_bounce = 
ClusterMetadata.current().schema.getKeyspace("after_bounce")
+                                                                           
.getMetadata()
+                                                                           
.getTableNullable("tbl1")
+                                           .indexes;
+                    assertIndex(after_bounce.get("legacy_idx").get(), 
IndexMetadata.Kind.COMPOSITES, CassandraIndex.class);
+                    assertIndex(after_bounce.get("sai_idx").get(), 
IndexMetadata.Kind.CUSTOM, StorageAttachedIndex.class);
+                    // the updated default is sai
+                    assertIndex(after_bounce.get("default_idx").get(), 
IndexMetadata.Kind.CUSTOM, StorageAttachedIndex.class);
+                });
+            });
+        }
+    }
+
+    @Test
+    public void differentConfigurationsTest() throws Exception
+    {
+        try (Cluster cluster = builder().withNodes(1)
+                                        
.withTokenSupplier(TokenSupplier.evenlyDistributedTokens(2))
+                                        
.withNodeIdTopology(NetworkTopology.singleDcNetworkTopology(2, "dc0", "rack0"))
+                                        .withConfig(config -> 
config.set("default_secondary_index", "legacy_local_table")
+                                                                    
.set("default_secondary_index_enabled", "true"))
+                                        .start())
+        {
+            IInstanceConfig config = cluster.newInstanceConfig()
+                                            .set("default_secondary_index", 
"sai")
+                                            
.set("default_secondary_index_enabled", "true");
+
+            IInvokableInstance newInstance = cluster.bootstrap(config);
+            newInstance.startup();
+
+            cluster.coordinator(1).execute("CREATE KEYSPACE from_1 WITH 
replication = {'class': 'SimpleStrategy'}", ConsistencyLevel.ALL);
+            
cluster.coordinator(1).execute(String.format(CREATE_TABLE_TEMPLATE, 
"from_1.tbl1"), ConsistencyLevel.ALL);
+            
cluster.coordinator(1).execute(String.format(CREATE_DEFAULT_INDEX_TEMPLATE, 
"from_1.tbl1", "v1"), ConsistencyLevel.ALL);
+            
cluster.coordinator(1).execute(String.format(CREATE_LEGACY_INDEX_TEMPLATE, 
"from_1.tbl1", "v2"), ConsistencyLevel.ALL);
+            
cluster.coordinator(1).execute(String.format(CREATE_SAI_INDEX_TEMPLATE, 
"from_1.tbl1", "v3"), ConsistencyLevel.ALL);
+
+            ClusterUtils.waitForCMSToQuiesce(cluster, cluster.get(1));
+            newInstance.coordinator().execute("CREATE KEYSPACE from_2 WITH 
replication = {'class': 'SimpleStrategy'}", ConsistencyLevel.ALL);
+            
newInstance.coordinator().execute(String.format(CREATE_TABLE_TEMPLATE, 
"from_2.tbl1"), ConsistencyLevel.ALL);
+            
newInstance.coordinator().execute(String.format(CREATE_DEFAULT_INDEX_TEMPLATE, 
"from_2.tbl1", "v1"), ConsistencyLevel.ALL);
+            
newInstance.coordinator().execute(String.format(CREATE_LEGACY_INDEX_TEMPLATE, 
"from_2.tbl1", "v2"), ConsistencyLevel.ALL);
+            
newInstance.coordinator().execute(String.format(CREATE_SAI_INDEX_TEMPLATE, 
"from_2.tbl1", "v3"), ConsistencyLevel.ALL);
+
+            ClusterUtils.waitForCMSToQuiesce(cluster, cluster.get(1));
+
+            // Just like in 5.0, both nodes should see identical index params 
(those of the coordinator).
+            cluster.stream().forEach(i -> {
+                i.runOnInstance(() -> {
+                    Indexes from_1 = 
ClusterMetadata.current().schema.getKeyspace("from_1")
+                                                                     
.getMetadata()
+                                                                     
.getTableNullable("tbl1")
+                                     .indexes;
+                    Assert.assertEquals(IndexMetadata.Kind.COMPOSITES, 
from_1.get("default_idx").get().kind);
+                    Assert.assertEquals(IndexMetadata.Kind.COMPOSITES, 
from_1.get("legacy_idx").get().kind);
+                    Assert.assertEquals(IndexMetadata.Kind.CUSTOM, 
from_1.get("sai_idx").get().kind);
+                    assertIndex(from_1.get("legacy_idx").get(), 
IndexMetadata.Kind.COMPOSITES, CassandraIndex.class);
+                    assertIndex(from_1.get("sai_idx").get(), 
IndexMetadata.Kind.CUSTOM, StorageAttachedIndex.class);
+                    // Node1's default is legacy 2i
+                    assertIndex(from_1.get("default_idx").get(), 
IndexMetadata.Kind.COMPOSITES, CassandraIndex.class);
+
+                    Indexes from_2 = 
ClusterMetadata.current().schema.getKeyspace("from_2")
+                                                                     
.getMetadata()
+                                                                     
.getTableNullable("tbl1")
+                                     .indexes;
+                    assertIndex(from_2.get("legacy_idx").get(), 
IndexMetadata.Kind.COMPOSITES, CassandraIndex.class);
+                    assertIndex(from_2.get("sai_idx").get(), 
IndexMetadata.Kind.CUSTOM, StorageAttachedIndex.class);
+                    // Node2's default is sai
+                    assertIndex(from_2.get("default_idx").get(), 
IndexMetadata.Kind.CUSTOM, StorageAttachedIndex.class);
+                });
+            });
+        }
+    }
+
+    private static void assertIndex(IndexMetadata index, IndexMetadata.Kind 
expectedKind, Class expectedClass)
+    {
+        Assert.assertEquals(expectedKind, index.kind);
+        Assert.assertEquals(expectedClass.getName(), 
index.getIndexClassName());
+    }
+}
\ No newline at end of file
diff --git 
a/test/distributed/org/apache/cassandra/distributed/test/log/KeyspaceParamsRecreateTest.java
 
b/test/distributed/org/apache/cassandra/distributed/test/log/KeyspaceParamsRecreateTest.java
new file mode 100644
index 0000000000..0d4b4cbd42
--- /dev/null
+++ 
b/test/distributed/org/apache/cassandra/distributed/test/log/KeyspaceParamsRecreateTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.distributed.test.log;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.cassandra.distributed.Cluster;
+import org.apache.cassandra.distributed.api.ConsistencyLevel;
+import org.apache.cassandra.distributed.api.IInstanceConfig;
+import org.apache.cassandra.distributed.api.IInvokableInstance;
+import org.apache.cassandra.distributed.api.TokenSupplier;
+import org.apache.cassandra.distributed.shared.ClusterUtils;
+import org.apache.cassandra.distributed.shared.NetworkTopology;
+import org.apache.cassandra.distributed.test.TestBaseImpl;
+import org.apache.cassandra.schema.KeyspaceMetadata;
+import org.apache.cassandra.tcm.ClusterMetadata;
+
+public class KeyspaceParamsRecreateTest extends TestBaseImpl
+{
+    @Test
+    public void bounceTest() throws Exception
+    {
+        try (Cluster cluster = builder().withNodes(1)
+                                        .withConfig(config -> 
config.set("default_keyspace_rf", "100"))
+                                        .start())
+        {
+            cluster.coordinator(1).execute("CREATE KEYSPACE before_bounce WITH 
replication = {'class': 'SimpleStrategy'}", ConsistencyLevel.ALL);
+            cluster.get(1).shutdown().get();
+            cluster.get(1).config().set("default_keyspace_rf", "200");
+
+            cluster.get(1).startup();
+            cluster.coordinator(1).execute("CREATE KEYSPACE after_bounce WITH 
replication = {'class': 'SimpleStrategy'}", ConsistencyLevel.ALL);
+
+            // The keyspace created before the bounce should preserve the 
initial default value. The one created after
+            // updating should take the new value from config.
+            cluster.stream().forEach(i -> {
+                i.runOnInstance(() -> {
+                    KeyspaceMetadata before_bounce = 
ClusterMetadata.current().schema.getKeyspace("before_bounce").getMetadata();
+                    Assert.assertEquals("100", 
before_bounce.params.replication.options.get("replication_factor"));
+                    KeyspaceMetadata after_bounce = 
ClusterMetadata.current().schema.getKeyspace("after_bounce").getMetadata();
+                    Assert.assertEquals("200", 
after_bounce.params.replication.options.get("replication_factor"));
+                });
+            });
+        }
+    }
+
+    @Test
+    public void differentConfigurationsTest() throws Exception
+    {
+        try (Cluster cluster = builder().withNodes(1)
+                                        
.withTokenSupplier(TokenSupplier.evenlyDistributedTokens(2))
+                                        
.withNodeIdTopology(NetworkTopology.singleDcNetworkTopology(2, "dc0", "rack0"))
+                                        .withConfig(config -> 
config.set("default_keyspace_rf", "100"))
+                                        .start())
+        {
+            IInstanceConfig config = 
cluster.newInstanceConfig().set("default_keyspace_rf", "200");
+
+            IInvokableInstance newInstance = cluster.bootstrap(config);
+            newInstance.startup();
+
+            cluster.coordinator(1).execute("CREATE KEYSPACE from_1 WITH 
replication = {'class': 'SimpleStrategy'}", ConsistencyLevel.ALL);
+            ClusterUtils.waitForCMSToQuiesce(cluster, cluster.get(1));
+            newInstance.coordinator().execute("CREATE KEYSPACE from_2 WITH 
replication = {'class': 'SimpleStrategy'}", ConsistencyLevel.ALL);
+            ClusterUtils.waitForCMSToQuiesce(cluster, cluster.get(1));
+
+            // Just like in 5.0, both nodes should see identical keyspace 
params (those of the coordinator).
+            cluster.stream().forEach(i -> {
+                i.runOnInstance(() -> {
+                    KeyspaceMetadata from_1 = 
ClusterMetadata.current().schema.getKeyspace("from_1").getMetadata();
+                    Assert.assertEquals("100", 
from_1.params.replication.options.get("replication_factor"));
+                    KeyspaceMetadata from_2 = 
ClusterMetadata.current().schema.getKeyspace("from_2").getMetadata();
+                    Assert.assertEquals("200", 
from_2.params.replication.options.get("replication_factor"));
+                });
+            });
+        }
+    }
+}
\ No newline at end of file
diff --git 
a/test/distributed/org/apache/cassandra/distributed/test/log/TableParamsRecreateTest.java
 
b/test/distributed/org/apache/cassandra/distributed/test/log/TableParamsRecreateTest.java
new file mode 100644
index 0000000000..bbc5ab6366
--- /dev/null
+++ 
b/test/distributed/org/apache/cassandra/distributed/test/log/TableParamsRecreateTest.java
@@ -0,0 +1,168 @@
+/*
+ * 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.distributed.test.log;
+
+import java.util.Map;
+import java.util.UUID;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.cassandra.distributed.Cluster;
+import org.apache.cassandra.distributed.api.ConsistencyLevel;
+import org.apache.cassandra.distributed.api.IInstanceConfig;
+import org.apache.cassandra.distributed.api.IInvokableInstance;
+import org.apache.cassandra.distributed.api.IMessageFilters;
+import org.apache.cassandra.distributed.api.TokenSupplier;
+import org.apache.cassandra.distributed.shared.ClusterUtils;
+import org.apache.cassandra.distributed.shared.NetworkTopology;
+import org.apache.cassandra.distributed.test.TestBaseImpl;
+import org.apache.cassandra.schema.CompactionParams;
+import org.apache.cassandra.schema.TableId;
+import org.apache.cassandra.tcm.ClusterMetadata;
+
+public class TableParamsRecreateTest extends TestBaseImpl
+{
+    @Test
+    public void bounceTest() throws Exception
+    {
+        try (Cluster cluster = init(builder().withNodes(1)
+                                             .withConfig(config -> 
config.set("default_compaction", Map.of(
+                                             "class_name", 
"SizeTieredCompactionStrategy",
+                                             "parameters", Map.of(
+                                             "min_threshold", "16",
+                                             "max_threshold", "64"))))
+                                             .start()))
+        {
+            cluster.coordinator(1).execute("CREATE TABLE " + KEYSPACE + 
".before_bounce (id int PRIMARY KEY, value text);", ConsistencyLevel.ALL);
+            cluster.get(1).shutdown().get();
+            cluster.get(1).config()
+                   .set("default_compaction", Map.of("class_name", 
"SizeTieredCompactionStrategy",
+                                                     "parameters", Map.of(
+                   "min_threshold", "32",
+                   "max_threshold", "128")));;
+
+            cluster.get(1).startup();
+            cluster.coordinator(1).execute("CREATE TABLE " + KEYSPACE + 
".after_bounce (id int PRIMARY KEY, value text);", ConsistencyLevel.ALL);
+
+            // Tables created before the bounce should preserve the initial 
default value. Those created after updating
+            // should take the new value from config.
+            cluster.stream().forEach(i -> {
+                i.runOnInstance(() -> {
+                    CompactionParams before_bounce = 
ClusterMetadata.current().schema.getKeyspace(KEYSPACE).getMetadata().tables.get("before_bounce").get().params.compaction;
+                    Assert.assertEquals("16", 
before_bounce.options().get("min_threshold"));
+                    Assert.assertEquals("64", 
before_bounce.options().get("max_threshold"));
+                    CompactionParams after_bounce = 
ClusterMetadata.current().schema.getKeyspace(KEYSPACE).getMetadata().tables.get("after_bounce").get().params.compaction;
+                    Assert.assertEquals("32", 
after_bounce.options().get("min_threshold"));
+                    Assert.assertEquals("128", 
after_bounce.options().get("max_threshold"));
+                });
+            });
+        }
+    }
+
+    @Test
+    public void differentConfigurationsTest() throws Exception
+    {
+        try (Cluster cluster = init(builder().withNodes(1)
+                                             
.withTokenSupplier(TokenSupplier.evenlyDistributedTokens(2))
+                                             
.withNodeIdTopology(NetworkTopology.singleDcNetworkTopology(2, "dc0", "rack0"))
+                                             .withConfig(config -> 
config.set("default_compaction", Map.of(
+                                             "class_name", 
"SizeTieredCompactionStrategy",
+                                             "parameters", Map.of(
+                                             "min_threshold", "16",
+                                             "max_threshold", "64"))))
+                                             .start(),
+                                    1))
+        {
+            IInstanceConfig config = cluster.newInstanceConfig()
+                                            .set("default_compaction", 
Map.of("class_name", "SizeTieredCompactionStrategy",
+                                                                              
"parameters", Map.of(
+                                            "min_threshold", "32",
+                                            "max_threshold", "128")));
+
+            IInvokableInstance newInstance = cluster.bootstrap(config);
+            newInstance.startup();
+
+            cluster.coordinator(1).execute("CREATE TABLE " + KEYSPACE + 
".from_1 (id int PRIMARY KEY, value text);", ConsistencyLevel.ALL);
+            ClusterUtils.waitForCMSToQuiesce(cluster, cluster.get(1));
+            newInstance.coordinator().execute("CREATE TABLE " + KEYSPACE + 
".from_2 (id int PRIMARY KEY, value text);", ConsistencyLevel.ALL);
+            ClusterUtils.waitForCMSToQuiesce(cluster, cluster.get(1));
+
+            // Just like in 5.0, both nodes should see identical table params 
(those from the coordinator)
+            cluster.stream().forEach(i -> {
+                i.runOnInstance(() -> {
+                    CompactionParams from_1 = 
ClusterMetadata.current().schema.getKeyspace(KEYSPACE).getMetadata().tables.get("from_1").get().params.compaction;
+                    Assert.assertEquals("16", 
from_1.options().get("min_threshold"));
+                    Assert.assertEquals("64", 
from_1.options().get("max_threshold"));
+                    CompactionParams from_2 = 
ClusterMetadata.current().schema.getKeyspace(KEYSPACE).getMetadata().tables.get("from_2").get().params.compaction;
+                    Assert.assertEquals("32", 
from_2.options().get("min_threshold"));
+                    Assert.assertEquals("128", 
from_2.options().get("max_threshold"));
+                });
+            });
+        }
+    }
+
+    @Test
+    public void laggingNodeTest() throws Exception
+    {
+        try (Cluster cluster = init(builder().withNodes(2).start(),1))
+        {
+            IMessageFilters.Filter filter = 
cluster.filters().allVerbs().from(1).to(2).drop();
+
+            for (int i = 0; i < 10; i++)
+            {
+                cluster.coordinator(1).execute(String.format("CREATE TABLE 
%s.tbl%d (id int PRIMARY KEY, value text);", KEYSPACE, i), 
ConsistencyLevel.ALL);
+                int finalI = i;
+                cluster.get(1).runOnInstance(() -> {
+                    ClusterMetadata metadata = ClusterMetadata.current();
+                    
Assert.assertEquals(TableId.fromLong(metadata.epoch.getEpoch() - 1),
+                                        
metadata.schema.getKeyspace(KEYSPACE).getMetadata().tables.get("tbl" + 
finalI).get().id);
+                });
+            }
+
+            int expectedEpoch = cluster.get(1).callOnInstance(() -> 
ClusterMetadata.current().epoch.getEpoch()).intValue();
+            int laggingEpoch = cluster.get(2).callOnInstance(() -> 
ClusterMetadata.current().epoch.getEpoch()).intValue();
+            Assert.assertTrue(String.format("%d should be less than %s", 
laggingEpoch, expectedEpoch), laggingEpoch < expectedEpoch);
+
+            filter.off();
+            cluster.coordinator(2).execute(String.format("CREATE TABLE 
%s.tbl%d (id int PRIMARY KEY, value text);", KEYSPACE, 10), 
ConsistencyLevel.ALL);
+
+            cluster.get(2).runOnInstance(() -> {
+                Assert.assertEquals(TableId.fromLong(expectedEpoch), 
ClusterMetadata.current().schema.getKeyspace(KEYSPACE).getMetadata().tables.get("tbl10").get().id);
+            });
+
+            cluster.coordinator(2).execute(String.format("CREATE TABLE 
%s.tbl%d (id int PRIMARY KEY, value text) WITH id = %s;", KEYSPACE, 11, new 
UUID(11, 11)),
+                                                         ConsistencyLevel.ALL);
+
+            cluster.get(2).runOnInstance(() -> {
+                Assert.assertEquals(TableId.fromUUID(new UUID(11, 11)),
+                                    
ClusterMetadata.current().schema.getKeyspace(KEYSPACE).getMetadata().tables.get("tbl11").get().id);
+            });
+        }
+    }
+
+    @Test
+    public void compactStorageTest() throws Exception
+    {
+        try (Cluster cluster = init(builder().withNodes(2).start(),1))
+        {
+            cluster.coordinator(1).execute(String.format("CREATE TABLE %s.tbl 
(id int PRIMARY KEY, value text) WITH COMPACT STORAGE;", KEYSPACE), 
ConsistencyLevel.ALL);
+        }
+    }
+}
\ No newline at end of file
diff --git a/test/unit/org/apache/cassandra/cql3/RandomSchemaTest.java 
b/test/unit/org/apache/cassandra/cql3/RandomSchemaTest.java
index aaffb7277e..1eff610c84 100644
--- a/test/unit/org/apache/cassandra/cql3/RandomSchemaTest.java
+++ b/test/unit/org/apache/cassandra/cql3/RandomSchemaTest.java
@@ -117,7 +117,7 @@ public class RandomSchemaTest extends CQLTester.InMemory
                                      .withStaticColumnsBetween(0, 2)
                                      .build(random);
             maybeCreateUDTs(metadata);
-            String createTable = metadata.toCqlString(false, false);
+            String createTable = metadata.toCqlString(true, false, false);
             // just to make the CREATE TABLE stmt easier to read for CUSTOM 
types
             createTable = 
createTable.replaceAll("org.apache.cassandra.db.marshal.", "");
             createTable(KEYSPACE, createTable);
@@ -203,7 +203,7 @@ public class RandomSchemaTest extends CQLTester.InMemory
                 subTypes.remove(next); // it includes self
                 if (subTypes.isEmpty() || subTypes.stream().allMatch(t -> 
created.contains(t.name)))
                 {
-                    String cql = next.toCqlString(false, false);
+                    String cql = next.toCqlString(true, false, false);
                     logger.warn("Creating UDT {}", cql);
                     schemaChange(cql);
                     created.add(next.name);
diff --git 
a/test/unit/org/apache/cassandra/cql3/statements/DescribeStatementTest.java 
b/test/unit/org/apache/cassandra/cql3/statements/DescribeStatementTest.java
index f605671ce8..1bef2d82cf 100644
--- a/test/unit/org/apache/cassandra/cql3/statements/DescribeStatementTest.java
+++ b/test/unit/org/apache/cassandra/cql3/statements/DescribeStatementTest.java
@@ -19,6 +19,7 @@ package org.apache.cassandra.cql3.statements;
 
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 
 import com.google.common.collect.ImmutableList;
@@ -1013,8 +1014,8 @@ public class DescribeStatementTest extends CQLTester
 
     private static String indexOutput(String index, String table, String col)
     {
-        if (DatabaseDescriptor.getDefaultSecondaryIndex() == 
CassandraIndex.NAME)
-            return format("CREATE INDEX %s ON %s.%s (%s);", index, "test", 
table, col);
+        if (Objects.equals(DatabaseDescriptor.getDefaultSecondaryIndex(), 
CassandraIndex.NAME))
+            return format("CREATE INDEX %s ON %s.%s (%s) USING '" + 
CassandraIndex.NAME + "';", index, "test", table, col);
         else
             return format("CREATE CUSTOM INDEX %s ON %s.%s (%s) USING '%s';",
                           index, "test", table, col, 
DatabaseDescriptor.getDefaultSecondaryIndex());
diff --git 
a/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java 
b/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
index ccb1513f19..4c9962afab 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
@@ -814,11 +814,11 @@ public class UFJavaTest extends CQLTester
                                                 "java",
                                                 "return 0;");
 
-        Assert.assertTrue(function.toCqlString(true, true).contains("CREATE 
FUNCTION IF NOT EXISTS"));
-        Assert.assertFalse(function.toCqlString(true, false).contains("CREATE 
FUNCTION IF NOT EXISTS"));
+        Assert.assertTrue(function.toCqlString(true, true, 
true).contains("CREATE FUNCTION IF NOT EXISTS"));
+        Assert.assertFalse(function.toCqlString(true, true, 
false).contains("CREATE FUNCTION IF NOT EXISTS"));
 
-        Assert.assertEquals(function.toCqlString(true, true), 
function.toCqlString(false, true));
-        Assert.assertEquals(function.toCqlString(true, false), 
function.toCqlString(false, false));
+        Assert.assertEquals(function.toCqlString(true, true, true), 
function.toCqlString(true, false, true));
+        Assert.assertEquals(function.toCqlString(true, true, false), 
function.toCqlString(true, false, false));
     }
 
     @Test
@@ -853,10 +853,10 @@ public class UFJavaTest extends CQLTester
                                                    Int32Type.instance,
                                                    null);
 
-        Assert.assertTrue(aggregate.toCqlString(true, true).contains("CREATE 
AGGREGATE IF NOT EXISTS"));
-        Assert.assertFalse(aggregate.toCqlString(true, false).contains("CREATE 
AGGREGATE IF NOT EXISTS"));
+        Assert.assertTrue(aggregate.toCqlString(true, true, 
true).contains("CREATE AGGREGATE IF NOT EXISTS"));
+        Assert.assertFalse(aggregate.toCqlString(true, true, 
false).contains("CREATE AGGREGATE IF NOT EXISTS"));
 
-        Assert.assertEquals(aggregate.toCqlString(true, true), 
aggregate.toCqlString(false, true));
-        Assert.assertEquals(aggregate.toCqlString(true, false), 
aggregate.toCqlString(false, false));
+        Assert.assertEquals(aggregate.toCqlString(true, true, true), 
aggregate.toCqlString(true, false, true));
+        Assert.assertEquals(aggregate.toCqlString(true, true, false), 
aggregate.toCqlString(true, false, false));
     }
 }
diff --git a/test/unit/org/apache/cassandra/db/SchemaCQLHelperTest.java 
b/test/unit/org/apache/cassandra/db/SchemaCQLHelperTest.java
index 2f966a217e..7880d17900 100644
--- a/test/unit/org/apache/cassandra/db/SchemaCQLHelperTest.java
+++ b/test/unit/org/apache/cassandra/db/SchemaCQLHelperTest.java
@@ -358,9 +358,9 @@ public class SchemaCQLHelperTest extends CQLTester
 
         ColumnFamilyStore cfs = 
Keyspace.open(keyspace).getColumnFamilyStore(table);
 
-        assertEquals(ImmutableList.of("CREATE INDEX \"indexName\" ON 
cql_test_keyspace_3.test_table_3 (values(reg1));",
-                                      "CREATE INDEX \"indexName2\" ON 
cql_test_keyspace_3.test_table_3 (keys(reg1));",
-                                      "CREATE INDEX \"indexName3\" ON 
cql_test_keyspace_3.test_table_3 (entries(reg1));",
+        assertEquals(ImmutableList.of("CREATE INDEX \"indexName\" ON 
cql_test_keyspace_3.test_table_3 (values(reg1)) USING 'legacy_local_table';",
+                                      "CREATE INDEX \"indexName2\" ON 
cql_test_keyspace_3.test_table_3 (keys(reg1)) USING 'legacy_local_table';",
+                                      "CREATE INDEX \"indexName3\" ON 
cql_test_keyspace_3.test_table_3 (entries(reg1)) USING 'legacy_local_table';",
                                       "CREATE CUSTOM INDEX \"indexName4\" ON 
cql_test_keyspace_3.test_table_3 (entries(reg1)) USING 
'org.apache.cassandra.index.sasi.SASIIndex';",
                                       "CREATE CUSTOM INDEX \"indexName5\" ON 
cql_test_keyspace_3.test_table_3 (entries(reg1)) USING 
'org.apache.cassandra.index.sasi.SASIIndex' WITH OPTIONS = {'is_literal': 
'false'};"),
                      SchemaCQLHelper.getIndexesAsCQL(cfs.metadata(), 
false).collect(Collectors.toList()));
@@ -442,7 +442,7 @@ public class SchemaCQLHelperTest extends CQLTester
         assertThat(schema, containsString(
             "CREATE " + (isIndexLegacy ? "" : "CUSTOM ") +
             "INDEX IF NOT EXISTS " + tableName + "_reg2_idx ON " + keyspace() 
+ '.' + tableName + " (reg2)" +
-            (isIndexLegacy ? "" : " USING '" + 
DatabaseDescriptor.getDefaultSecondaryIndex() + "'") + ";"));
+            (" USING '" + (isIndexLegacy ? CassandraIndex.NAME : 
DatabaseDescriptor.getDefaultSecondaryIndex()) + "'") + ";"));
 
         JsonNode manifest = 
JsonUtils.JSON_OBJECT_MAPPER.readTree(cfs.getDirectories().getSnapshotManifestFile(SNAPSHOT).toJavaIOFile());
         JsonNode files = manifest.get("files");
diff --git a/test/unit/org/apache/cassandra/repair/FuzzTestBase.java 
b/test/unit/org/apache/cassandra/repair/FuzzTestBase.java
index 40959a21e1..261cbd97f5 100644
--- a/test/unit/org/apache/cassandra/repair/FuzzTestBase.java
+++ b/test/unit/org/apache/cassandra/repair/FuzzTestBase.java
@@ -285,7 +285,7 @@ public abstract class FuzzTestBase extends 
CQLTester.InMemory
         // StorageService can not be mocked out, nor can ColumnFamilyStores, 
so make sure that the keyspace is a "local" keyspace to avoid replication as 
the peers don't actually exist for replication
         schemaChange(String.format("CREATE KEYSPACE %s WITH REPLICATION = 
{'class': '%s'}", SchemaConstants.DISTRIBUTED_KEYSPACE_NAME, 
HackStrat.class.getName()));
         for (TableMetadata table : SystemDistributedKeyspace.metadata().tables)
-            schemaChange(table.toCqlString(false, false));
+            schemaChange(table.toCqlString(true, false, false));
 
         createSchema();
     }
@@ -320,10 +320,10 @@ public abstract class FuzzTestBase extends 
CQLTester.InMemory
         KeyspaceMetadata metadata = KeyspaceMetadata.create(ks, params, 
tableBuilder.build());
 
         // create
-        schemaChange(metadata.toCqlString(false, false));
+        schemaChange(metadata.toCqlString(true, false, false));
         KEYSPACE = ks;
         for (TableMetadata table : metadata.tables)
-            schemaChange(table.toCqlString(false, false));
+            schemaChange(table.toCqlString(true, false, false));
         TABLES = tableNames;
     }
 


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

Reply via email to