You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by jz...@apache.org on 2018/05/02 19:21:55 UTC

[1/6] cassandra git commit: Better handle missing partition columns in system_schema.columns

Repository: cassandra
Updated Branches:
  refs/heads/cassandra-3.0 733f6b0cf -> eb68c3126
  refs/heads/cassandra-3.11 783bbb3c8 -> 2d19de1cf
  refs/heads/trunk 01439740b -> 60ed982d5


Better handle missing partition columns in system_schema.columns

Provide the user workaround if schema table is corrupted.

patch by Jay Zhuang; reviewed by Aleksey Yeschenko for CASSANDRA-14379


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

Branch: refs/heads/cassandra-3.0
Commit: eb68c3126270e27fd9c88ef867bbcb8c7942a8e8
Parents: 733f6b0
Author: Jay Zhuang <zj...@uber.com>
Authored: Wed Apr 4 13:49:08 2018 -0700
Committer: Jay Zhuang <ja...@yahoo.com>
Committed: Wed May 2 10:59:47 2018 -0700

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../apache/cassandra/schema/SchemaKeyspace.java | 32 +++++++++++++++-----
 .../cassandra/schema/SchemaKeyspaceTest.java    | 29 ++++++++++++++++++
 3 files changed, 54 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/eb68c312/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 9992802..39edeb1 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 3.0.17
+ * Better handle missing partition columns in system_schema.columns (CASSANDRA-14379)
  * Delay hints store excise by write timeout to avoid race with decommission (CASSANDRA-13740)
  * Deprecate background repair and probablistic read_repair_chance table options
    (CASSANDRA-13910)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/eb68c312/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/schema/SchemaKeyspace.java b/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
index 578f501..81cc2e1 100644
--- a/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
+++ b/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
@@ -25,6 +25,7 @@ import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.*;
 import com.google.common.collect.Maps;
 import org.slf4j.Logger;
@@ -960,14 +961,24 @@ public final class SchemaKeyspace
             }
             catch (MissingColumns exc)
             {
-                if (!IGNORE_CORRUPTED_SCHEMA_TABLES)
+                String errorMsg = String.format("No partition columns found for table %s.%s in %s.%s.  This may be due to " +
+                                                "corruption or concurrent dropping and altering of a table. If this table is supposed " +
+                                                "to be dropped, {}run the following query to cleanup: " +
+                                                "\"DELETE FROM %s.%s WHERE keyspace_name = '%s' AND table_name = '%s'; " +
+                                                "DELETE FROM %s.%s WHERE keyspace_name = '%s' AND table_name = '%s';\" " +
+                                                "If the table is not supposed to be dropped, restore %s.%s sstables from backups.",
+                                                keyspaceName, tableName, NAME, COLUMNS,
+                                                NAME, TABLES, keyspaceName, tableName,
+                                                NAME, COLUMNS, keyspaceName, tableName,
+                                                NAME, COLUMNS);
+
+                if (IGNORE_CORRUPTED_SCHEMA_TABLES)
                 {
-                    logger.error("No columns found for table {}.{} in {}.{}.  This may be due to " +
-                                 "corruption or concurrent dropping and altering of a table.  If this table " +
-                                 "is supposed to be dropped, restart cassandra with -Dcassandra.ignore_corrupted_schema_tables=true " +
-                                 "and run the following query: \"DELETE FROM {}.{} WHERE keyspace_name = '{}' AND table_name = '{}';\"." +
-                                 "If the table is not supposed to be dropped, restore {}.{} sstables from backups.",
-                                 keyspaceName, tableName, NAME, COLUMNS, NAME, TABLES, keyspaceName, tableName, NAME, COLUMNS);
+                    logger.error(errorMsg, "", exc);
+                }
+                else
+                {
+                    logger.error(errorMsg, "restart cassandra with -Dcassandra.ignore_corrupted_schema_tables=true and ");
                     throw exc;
                 }
             }
@@ -1043,6 +1054,10 @@ public final class SchemaKeyspace
 
         List<ColumnDefinition> columns = new ArrayList<>();
         columnRows.forEach(row -> columns.add(createColumnFromRow(row, types)));
+
+        if (columns.stream().noneMatch(ColumnDefinition::isPartitionKey))
+            throw new MissingColumns("No partition key columns found in schema table for " + keyspace + "." + table);
+
         return columns;
     }
 
@@ -1466,7 +1481,8 @@ public final class SchemaKeyspace
                     .collect(toList());
     }
 
-    private static class MissingColumns extends RuntimeException
+    @VisibleForTesting
+    static class MissingColumns extends RuntimeException
     {
         MissingColumns(String message)
         {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/eb68c312/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java b/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
index b2e3535..f76fc4f 100644
--- a/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
+++ b/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
@@ -52,6 +52,7 @@ import org.apache.cassandra.thrift.ThriftConversion;
 import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.FBUtilities;
 
+import static org.apache.cassandra.cql3.QueryProcessor.executeOnceInternal;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -205,4 +206,32 @@ public class SchemaKeyspaceTest
         assertEquals(cfm.params, params);
         assertEquals(new HashSet<>(cfm.allColumns()), columns);
     }
+
+    @Test(expected = SchemaKeyspace.MissingColumns.class)
+    public void testSchemaNoPartition()
+    {
+        String testKS = "test_schema_no_partition";
+        String testTable = "invalid_table";
+        SchemaLoader.createKeyspace(testKS,
+                                    KeyspaceParams.simple(1),
+                                    SchemaLoader.standardCFMD(testKS, testTable));
+        // Delete partition column in the schema
+        String query = String.format("DELETE FROM %s.%s WHERE keyspace_name=? and table_name=? and column_name=?", SchemaKeyspace.NAME, SchemaKeyspace.COLUMNS);
+        executeOnceInternal(query, testKS, testTable, "key");
+        SchemaKeyspace.fetchNonSystemKeyspaces();
+    }
+
+    @Test(expected = SchemaKeyspace.MissingColumns.class)
+    public void testSchemaNoColumn()
+    {
+        String testKS = "test_schema_no_Column";
+        String testTable = "invalid_table";
+        SchemaLoader.createKeyspace(testKS,
+                                    KeyspaceParams.simple(1),
+                                    SchemaLoader.standardCFMD(testKS, testTable));
+        // Delete all colmns in the schema
+        String query = String.format("DELETE FROM %s.%s WHERE keyspace_name=? and table_name=?", SchemaKeyspace.NAME, SchemaKeyspace.COLUMNS);
+        executeOnceInternal(query, testKS, testTable);
+        SchemaKeyspace.fetchNonSystemKeyspaces();
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[4/6] cassandra git commit: Merge branch 'cassandra-3.0' into cassandra-3.11

Posted by jz...@apache.org.
Merge branch 'cassandra-3.0' into cassandra-3.11


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

Branch: refs/heads/trunk
Commit: 2d19de1cfabdc848477b33ba922c63013a7a9a1a
Parents: 783bbb3 eb68c31
Author: Jay Zhuang <ja...@yahoo.com>
Authored: Wed May 2 11:02:03 2018 -0700
Committer: Jay Zhuang <ja...@yahoo.com>
Committed: Wed May 2 11:03:34 2018 -0700

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../apache/cassandra/schema/SchemaKeyspace.java | 35 +++++++++++++-------
 .../cassandra/schema/SchemaKeyspaceTest.java    | 29 ++++++++++++++++
 3 files changed, 53 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/2d19de1c/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 443c298,39edeb1..837b891
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,15 -1,5 +1,16 @@@
 -3.0.17
 +3.11.3
 + * Allow existing nodes to use all peers in shadow round (CASSANDRA-13851)
 + * Fix cqlsh to read connection.ssl cqlshrc option again (CASSANDRA-14299)
 + * Downgrade log level to trace for CommitLogSegmentManager (CASSANDRA-14370)
 + * CQL fromJson(null) throws NullPointerException (CASSANDRA-13891)
 + * Serialize empty buffer as empty string for json output format (CASSANDRA-14245)
 + * Allow logging implementation to be interchanged for embedded testing (CASSANDRA-13396)
 + * SASI tokenizer for simple delimiter based entries (CASSANDRA-14247)
 + * Fix Loss of digits when doing CAST from varint/bigint to decimal (CASSANDRA-14170)
 + * RateBasedBackPressure unnecessarily invokes a lock on the Guava RateLimiter (CASSANDRA-14163)
 + * Fix wildcard GROUP BY queries (CASSANDRA-14209)
 +Merged from 3.0:
+  * Better handle missing partition columns in system_schema.columns (CASSANDRA-14379)
   * Delay hints store excise by write timeout to avoid race with decommission (CASSANDRA-13740)
   * Deprecate background repair and probablistic read_repair_chance table options
     (CASSANDRA-13910)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/2d19de1c/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/schema/SchemaKeyspace.java
index 164e32d,81cc2e1..027b7cf
--- a/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
+++ b/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
@@@ -999,18 -961,24 +999,24 @@@ public final class SchemaKeyspac
              }
              catch (MissingColumns exc)
              {
-                 if (!IGNORE_CORRUPTED_SCHEMA_TABLES)
+                 String errorMsg = String.format("No partition columns found for table %s.%s in %s.%s.  This may be due to " +
+                                                 "corruption or concurrent dropping and altering of a table. If this table is supposed " +
+                                                 "to be dropped, {}run the following query to cleanup: " +
+                                                 "\"DELETE FROM %s.%s WHERE keyspace_name = '%s' AND table_name = '%s'; " +
+                                                 "DELETE FROM %s.%s WHERE keyspace_name = '%s' AND table_name = '%s';\" " +
+                                                 "If the table is not supposed to be dropped, restore %s.%s sstables from backups.",
 -                                                keyspaceName, tableName, NAME, COLUMNS,
 -                                                NAME, TABLES, keyspaceName, tableName,
 -                                                NAME, COLUMNS, keyspaceName, tableName,
 -                                                NAME, COLUMNS);
++                                                keyspaceName, tableName, SchemaConstants.SCHEMA_KEYSPACE_NAME, COLUMNS,
++                                                SchemaConstants.SCHEMA_KEYSPACE_NAME, TABLES, keyspaceName, tableName,
++                                                SchemaConstants.SCHEMA_KEYSPACE_NAME, COLUMNS, keyspaceName, tableName,
++                                                SchemaConstants.SCHEMA_KEYSPACE_NAME, COLUMNS);
+ 
+                 if (IGNORE_CORRUPTED_SCHEMA_TABLES)
                  {
-                     logger.error("No columns found for table {}.{} in {}.{}.  This may be due to " +
-                                  "corruption or concurrent dropping and altering of a table.  If this table " +
-                                  "is supposed to be dropped, restart cassandra with -Dcassandra.ignore_corrupted_schema_tables=true " +
-                                  "and run the following query: \"DELETE FROM {}.{} WHERE keyspace_name = '{}' AND table_name = '{}';\"." +
-                                  "If the table is not supposed to be dropped, restore {}.{} sstables from backups.",
-                                  keyspaceName, tableName,
-                                  SchemaConstants.SCHEMA_KEYSPACE_NAME, COLUMNS,
-                                  SchemaConstants.SCHEMA_KEYSPACE_NAME, TABLES,
-                                  keyspaceName, tableName,
-                                  SchemaConstants.SCHEMA_KEYSPACE_NAME, COLUMNS);
+                     logger.error(errorMsg, "", exc);
+                 }
+                 else
+                 {
+                     logger.error(errorMsg, "restart cassandra with -Dcassandra.ignore_corrupted_schema_tables=true and ");
                      throw exc;
                  }
              }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/2d19de1c/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
index 550deed,f76fc4f..f3ee85d
--- a/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
+++ b/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
@@@ -58,10 -51,9 +58,11 @@@ import org.apache.cassandra.thrift.Inde
  import org.apache.cassandra.thrift.ThriftConversion;
  import org.apache.cassandra.utils.ByteBufferUtil;
  import org.apache.cassandra.utils.FBUtilities;
 +import org.apache.cassandra.utils.Pair;
  
+ import static org.apache.cassandra.cql3.QueryProcessor.executeOnceInternal;
  import static org.junit.Assert.assertEquals;
 +import static org.junit.Assert.assertFalse;
  import static org.junit.Assert.assertTrue;
  
  public class SchemaKeyspaceTest
@@@ -215,97 -207,31 +216,125 @@@
          assertEquals(new HashSet<>(cfm.allColumns()), columns);
      }
  
 +    private static boolean hasCDC(Mutation m)
 +    {
 +        for (PartitionUpdate p : m.getPartitionUpdates())
 +        {
 +            for (ColumnDefinition cd : p.columns())
 +            {
 +                if (cd.name.toString().equals("cdc"))
 +                    return true;
 +            }
 +        }
 +        return false;
 +    }
 +
 +    private static boolean hasSchemaTables(Mutation m)
 +    {
 +        for (PartitionUpdate p : m.getPartitionUpdates())
 +        {
 +            if (p.metadata().cfName.equals(SchemaKeyspace.TABLES))
 +                return true;
 +        }
 +        return false;
 +    }
 +
 +    @Test
 +    public void testConvertSchemaToMutationsWithoutCDC() throws IOException
 +    {
 +        boolean oldCDCOption = DatabaseDescriptor.isCDCEnabled();
 +        try
 +        {
 +            DatabaseDescriptor.setCDCEnabled(false);
 +            Collection<Mutation> mutations = SchemaKeyspace.convertSchemaToMutations();
 +            boolean foundTables = false;
 +            for (Mutation m : mutations)
 +            {
 +                if (hasSchemaTables(m))
 +                {
 +                    foundTables = true;
 +                    assertFalse(hasCDC(m));
 +                    try (DataOutputBuffer output = new DataOutputBuffer())
 +                    {
 +                        Mutation.serializer.serialize(m, output, MessagingService.current_version);
 +                        try (DataInputBuffer input = new DataInputBuffer(output.getData()))
 +                        {
 +                            Mutation out = Mutation.serializer.deserialize(input, MessagingService.current_version);
 +                            assertFalse(hasCDC(out));
 +                        }
 +                    }
 +                }
 +            }
 +            assertTrue(foundTables);
 +        }
 +        finally
 +        {
 +            DatabaseDescriptor.setCDCEnabled(oldCDCOption);
 +        }
 +    }
 +
 +    @Test
 +    public void testConvertSchemaToMutationsWithCDC()
 +    {
 +        boolean oldCDCOption = DatabaseDescriptor.isCDCEnabled();
 +        try
 +        {
 +            DatabaseDescriptor.setCDCEnabled(true);
 +            Collection<Mutation> mutations = SchemaKeyspace.convertSchemaToMutations();
 +            boolean foundTables = false;
 +            for (Mutation m : mutations)
 +            {
 +                if (hasSchemaTables(m))
 +                {
 +                    foundTables = true;
 +                    assertTrue(hasCDC(m));
 +                }
 +            }
 +            assertTrue(foundTables);
 +        }
 +        finally
 +        {
 +            DatabaseDescriptor.setCDCEnabled(oldCDCOption);
 +        }
 +    }
 +
 +    @Test
 +    public void testSchemaDigest()
 +    {
 +        Set<ByteBuffer> abc = Collections.singleton(ByteBufferUtil.bytes("abc"));
 +        Pair<UUID, UUID> versions = SchemaKeyspace.calculateSchemaDigest(abc);
 +        assertTrue(versions.left.equals(versions.right));
 +
 +        Set<ByteBuffer> cdc = Collections.singleton(ByteBufferUtil.bytes("cdc"));
 +        versions = SchemaKeyspace.calculateSchemaDigest(cdc);
 +        assertFalse(versions.left.equals(versions.right));
 +    }
++
+     @Test(expected = SchemaKeyspace.MissingColumns.class)
+     public void testSchemaNoPartition()
+     {
+         String testKS = "test_schema_no_partition";
+         String testTable = "invalid_table";
+         SchemaLoader.createKeyspace(testKS,
+                                     KeyspaceParams.simple(1),
+                                     SchemaLoader.standardCFMD(testKS, testTable));
+         // Delete partition column in the schema
 -        String query = String.format("DELETE FROM %s.%s WHERE keyspace_name=? and table_name=? and column_name=?", SchemaKeyspace.NAME, SchemaKeyspace.COLUMNS);
++        String query = String.format("DELETE FROM %s.%s WHERE keyspace_name=? and table_name=? and column_name=?", SchemaConstants.SCHEMA_KEYSPACE_NAME, SchemaKeyspace.COLUMNS);
+         executeOnceInternal(query, testKS, testTable, "key");
+         SchemaKeyspace.fetchNonSystemKeyspaces();
+     }
+ 
+     @Test(expected = SchemaKeyspace.MissingColumns.class)
+     public void testSchemaNoColumn()
+     {
+         String testKS = "test_schema_no_Column";
+         String testTable = "invalid_table";
+         SchemaLoader.createKeyspace(testKS,
+                                     KeyspaceParams.simple(1),
+                                     SchemaLoader.standardCFMD(testKS, testTable));
+         // Delete all colmns in the schema
 -        String query = String.format("DELETE FROM %s.%s WHERE keyspace_name=? and table_name=?", SchemaKeyspace.NAME, SchemaKeyspace.COLUMNS);
++        String query = String.format("DELETE FROM %s.%s WHERE keyspace_name=? and table_name=?", SchemaConstants.SCHEMA_KEYSPACE_NAME, SchemaKeyspace.COLUMNS);
+         executeOnceInternal(query, testKS, testTable);
+         SchemaKeyspace.fetchNonSystemKeyspaces();
+     }
  }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[2/6] cassandra git commit: Better handle missing partition columns in system_schema.columns

Posted by jz...@apache.org.
Better handle missing partition columns in system_schema.columns

Provide the user workaround if schema table is corrupted.

patch by Jay Zhuang; reviewed by Aleksey Yeschenko for CASSANDRA-14379


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

Branch: refs/heads/cassandra-3.11
Commit: eb68c3126270e27fd9c88ef867bbcb8c7942a8e8
Parents: 733f6b0
Author: Jay Zhuang <zj...@uber.com>
Authored: Wed Apr 4 13:49:08 2018 -0700
Committer: Jay Zhuang <ja...@yahoo.com>
Committed: Wed May 2 10:59:47 2018 -0700

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../apache/cassandra/schema/SchemaKeyspace.java | 32 +++++++++++++++-----
 .../cassandra/schema/SchemaKeyspaceTest.java    | 29 ++++++++++++++++++
 3 files changed, 54 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/eb68c312/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 9992802..39edeb1 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 3.0.17
+ * Better handle missing partition columns in system_schema.columns (CASSANDRA-14379)
  * Delay hints store excise by write timeout to avoid race with decommission (CASSANDRA-13740)
  * Deprecate background repair and probablistic read_repair_chance table options
    (CASSANDRA-13910)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/eb68c312/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/schema/SchemaKeyspace.java b/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
index 578f501..81cc2e1 100644
--- a/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
+++ b/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
@@ -25,6 +25,7 @@ import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.*;
 import com.google.common.collect.Maps;
 import org.slf4j.Logger;
@@ -960,14 +961,24 @@ public final class SchemaKeyspace
             }
             catch (MissingColumns exc)
             {
-                if (!IGNORE_CORRUPTED_SCHEMA_TABLES)
+                String errorMsg = String.format("No partition columns found for table %s.%s in %s.%s.  This may be due to " +
+                                                "corruption or concurrent dropping and altering of a table. If this table is supposed " +
+                                                "to be dropped, {}run the following query to cleanup: " +
+                                                "\"DELETE FROM %s.%s WHERE keyspace_name = '%s' AND table_name = '%s'; " +
+                                                "DELETE FROM %s.%s WHERE keyspace_name = '%s' AND table_name = '%s';\" " +
+                                                "If the table is not supposed to be dropped, restore %s.%s sstables from backups.",
+                                                keyspaceName, tableName, NAME, COLUMNS,
+                                                NAME, TABLES, keyspaceName, tableName,
+                                                NAME, COLUMNS, keyspaceName, tableName,
+                                                NAME, COLUMNS);
+
+                if (IGNORE_CORRUPTED_SCHEMA_TABLES)
                 {
-                    logger.error("No columns found for table {}.{} in {}.{}.  This may be due to " +
-                                 "corruption or concurrent dropping and altering of a table.  If this table " +
-                                 "is supposed to be dropped, restart cassandra with -Dcassandra.ignore_corrupted_schema_tables=true " +
-                                 "and run the following query: \"DELETE FROM {}.{} WHERE keyspace_name = '{}' AND table_name = '{}';\"." +
-                                 "If the table is not supposed to be dropped, restore {}.{} sstables from backups.",
-                                 keyspaceName, tableName, NAME, COLUMNS, NAME, TABLES, keyspaceName, tableName, NAME, COLUMNS);
+                    logger.error(errorMsg, "", exc);
+                }
+                else
+                {
+                    logger.error(errorMsg, "restart cassandra with -Dcassandra.ignore_corrupted_schema_tables=true and ");
                     throw exc;
                 }
             }
@@ -1043,6 +1054,10 @@ public final class SchemaKeyspace
 
         List<ColumnDefinition> columns = new ArrayList<>();
         columnRows.forEach(row -> columns.add(createColumnFromRow(row, types)));
+
+        if (columns.stream().noneMatch(ColumnDefinition::isPartitionKey))
+            throw new MissingColumns("No partition key columns found in schema table for " + keyspace + "." + table);
+
         return columns;
     }
 
@@ -1466,7 +1481,8 @@ public final class SchemaKeyspace
                     .collect(toList());
     }
 
-    private static class MissingColumns extends RuntimeException
+    @VisibleForTesting
+    static class MissingColumns extends RuntimeException
     {
         MissingColumns(String message)
         {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/eb68c312/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java b/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
index b2e3535..f76fc4f 100644
--- a/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
+++ b/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
@@ -52,6 +52,7 @@ import org.apache.cassandra.thrift.ThriftConversion;
 import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.FBUtilities;
 
+import static org.apache.cassandra.cql3.QueryProcessor.executeOnceInternal;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -205,4 +206,32 @@ public class SchemaKeyspaceTest
         assertEquals(cfm.params, params);
         assertEquals(new HashSet<>(cfm.allColumns()), columns);
     }
+
+    @Test(expected = SchemaKeyspace.MissingColumns.class)
+    public void testSchemaNoPartition()
+    {
+        String testKS = "test_schema_no_partition";
+        String testTable = "invalid_table";
+        SchemaLoader.createKeyspace(testKS,
+                                    KeyspaceParams.simple(1),
+                                    SchemaLoader.standardCFMD(testKS, testTable));
+        // Delete partition column in the schema
+        String query = String.format("DELETE FROM %s.%s WHERE keyspace_name=? and table_name=? and column_name=?", SchemaKeyspace.NAME, SchemaKeyspace.COLUMNS);
+        executeOnceInternal(query, testKS, testTable, "key");
+        SchemaKeyspace.fetchNonSystemKeyspaces();
+    }
+
+    @Test(expected = SchemaKeyspace.MissingColumns.class)
+    public void testSchemaNoColumn()
+    {
+        String testKS = "test_schema_no_Column";
+        String testTable = "invalid_table";
+        SchemaLoader.createKeyspace(testKS,
+                                    KeyspaceParams.simple(1),
+                                    SchemaLoader.standardCFMD(testKS, testTable));
+        // Delete all colmns in the schema
+        String query = String.format("DELETE FROM %s.%s WHERE keyspace_name=? and table_name=?", SchemaKeyspace.NAME, SchemaKeyspace.COLUMNS);
+        executeOnceInternal(query, testKS, testTable);
+        SchemaKeyspace.fetchNonSystemKeyspaces();
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[3/6] cassandra git commit: Better handle missing partition columns in system_schema.columns

Posted by jz...@apache.org.
Better handle missing partition columns in system_schema.columns

Provide the user workaround if schema table is corrupted.

patch by Jay Zhuang; reviewed by Aleksey Yeschenko for CASSANDRA-14379


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

Branch: refs/heads/trunk
Commit: eb68c3126270e27fd9c88ef867bbcb8c7942a8e8
Parents: 733f6b0
Author: Jay Zhuang <zj...@uber.com>
Authored: Wed Apr 4 13:49:08 2018 -0700
Committer: Jay Zhuang <ja...@yahoo.com>
Committed: Wed May 2 10:59:47 2018 -0700

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../apache/cassandra/schema/SchemaKeyspace.java | 32 +++++++++++++++-----
 .../cassandra/schema/SchemaKeyspaceTest.java    | 29 ++++++++++++++++++
 3 files changed, 54 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/eb68c312/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 9992802..39edeb1 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 3.0.17
+ * Better handle missing partition columns in system_schema.columns (CASSANDRA-14379)
  * Delay hints store excise by write timeout to avoid race with decommission (CASSANDRA-13740)
  * Deprecate background repair and probablistic read_repair_chance table options
    (CASSANDRA-13910)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/eb68c312/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/schema/SchemaKeyspace.java b/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
index 578f501..81cc2e1 100644
--- a/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
+++ b/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
@@ -25,6 +25,7 @@ import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.*;
 import com.google.common.collect.Maps;
 import org.slf4j.Logger;
@@ -960,14 +961,24 @@ public final class SchemaKeyspace
             }
             catch (MissingColumns exc)
             {
-                if (!IGNORE_CORRUPTED_SCHEMA_TABLES)
+                String errorMsg = String.format("No partition columns found for table %s.%s in %s.%s.  This may be due to " +
+                                                "corruption or concurrent dropping and altering of a table. If this table is supposed " +
+                                                "to be dropped, {}run the following query to cleanup: " +
+                                                "\"DELETE FROM %s.%s WHERE keyspace_name = '%s' AND table_name = '%s'; " +
+                                                "DELETE FROM %s.%s WHERE keyspace_name = '%s' AND table_name = '%s';\" " +
+                                                "If the table is not supposed to be dropped, restore %s.%s sstables from backups.",
+                                                keyspaceName, tableName, NAME, COLUMNS,
+                                                NAME, TABLES, keyspaceName, tableName,
+                                                NAME, COLUMNS, keyspaceName, tableName,
+                                                NAME, COLUMNS);
+
+                if (IGNORE_CORRUPTED_SCHEMA_TABLES)
                 {
-                    logger.error("No columns found for table {}.{} in {}.{}.  This may be due to " +
-                                 "corruption or concurrent dropping and altering of a table.  If this table " +
-                                 "is supposed to be dropped, restart cassandra with -Dcassandra.ignore_corrupted_schema_tables=true " +
-                                 "and run the following query: \"DELETE FROM {}.{} WHERE keyspace_name = '{}' AND table_name = '{}';\"." +
-                                 "If the table is not supposed to be dropped, restore {}.{} sstables from backups.",
-                                 keyspaceName, tableName, NAME, COLUMNS, NAME, TABLES, keyspaceName, tableName, NAME, COLUMNS);
+                    logger.error(errorMsg, "", exc);
+                }
+                else
+                {
+                    logger.error(errorMsg, "restart cassandra with -Dcassandra.ignore_corrupted_schema_tables=true and ");
                     throw exc;
                 }
             }
@@ -1043,6 +1054,10 @@ public final class SchemaKeyspace
 
         List<ColumnDefinition> columns = new ArrayList<>();
         columnRows.forEach(row -> columns.add(createColumnFromRow(row, types)));
+
+        if (columns.stream().noneMatch(ColumnDefinition::isPartitionKey))
+            throw new MissingColumns("No partition key columns found in schema table for " + keyspace + "." + table);
+
         return columns;
     }
 
@@ -1466,7 +1481,8 @@ public final class SchemaKeyspace
                     .collect(toList());
     }
 
-    private static class MissingColumns extends RuntimeException
+    @VisibleForTesting
+    static class MissingColumns extends RuntimeException
     {
         MissingColumns(String message)
         {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/eb68c312/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java b/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
index b2e3535..f76fc4f 100644
--- a/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
+++ b/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
@@ -52,6 +52,7 @@ import org.apache.cassandra.thrift.ThriftConversion;
 import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.FBUtilities;
 
+import static org.apache.cassandra.cql3.QueryProcessor.executeOnceInternal;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -205,4 +206,32 @@ public class SchemaKeyspaceTest
         assertEquals(cfm.params, params);
         assertEquals(new HashSet<>(cfm.allColumns()), columns);
     }
+
+    @Test(expected = SchemaKeyspace.MissingColumns.class)
+    public void testSchemaNoPartition()
+    {
+        String testKS = "test_schema_no_partition";
+        String testTable = "invalid_table";
+        SchemaLoader.createKeyspace(testKS,
+                                    KeyspaceParams.simple(1),
+                                    SchemaLoader.standardCFMD(testKS, testTable));
+        // Delete partition column in the schema
+        String query = String.format("DELETE FROM %s.%s WHERE keyspace_name=? and table_name=? and column_name=?", SchemaKeyspace.NAME, SchemaKeyspace.COLUMNS);
+        executeOnceInternal(query, testKS, testTable, "key");
+        SchemaKeyspace.fetchNonSystemKeyspaces();
+    }
+
+    @Test(expected = SchemaKeyspace.MissingColumns.class)
+    public void testSchemaNoColumn()
+    {
+        String testKS = "test_schema_no_Column";
+        String testTable = "invalid_table";
+        SchemaLoader.createKeyspace(testKS,
+                                    KeyspaceParams.simple(1),
+                                    SchemaLoader.standardCFMD(testKS, testTable));
+        // Delete all colmns in the schema
+        String query = String.format("DELETE FROM %s.%s WHERE keyspace_name=? and table_name=?", SchemaKeyspace.NAME, SchemaKeyspace.COLUMNS);
+        executeOnceInternal(query, testKS, testTable);
+        SchemaKeyspace.fetchNonSystemKeyspaces();
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[6/6] cassandra git commit: Merge branch 'cassandra-3.11' into trunk

Posted by jz...@apache.org.
Merge branch 'cassandra-3.11' into trunk


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

Branch: refs/heads/trunk
Commit: 60ed982d5309b674abfb32584f75f676951c2668
Parents: 0143974 2d19de1
Author: Jay Zhuang <ja...@yahoo.com>
Authored: Wed May 2 11:05:25 2018 -0700
Committer: Jay Zhuang <ja...@yahoo.com>
Committed: Wed May 2 11:08:18 2018 -0700

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../apache/cassandra/schema/SchemaKeyspace.java | 36 +++++++++++++-------
 .../cassandra/schema/SchemaKeyspaceTest.java    | 29 ++++++++++++++++
 3 files changed, 54 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/60ed982d/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 27e69b8,837b891..5831978
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -246,7 -10,10 +246,8 @@@
   * RateBasedBackPressure unnecessarily invokes a lock on the Guava RateLimiter (CASSANDRA-14163)
   * Fix wildcard GROUP BY queries (CASSANDRA-14209)
  Merged from 3.0:
+  * Better handle missing partition columns in system_schema.columns (CASSANDRA-14379)
   * Delay hints store excise by write timeout to avoid race with decommission (CASSANDRA-13740)
 - * Deprecate background repair and probablistic read_repair_chance table options
 -   (CASSANDRA-13910)
   * Add missed CQL keywords to documentation (CASSANDRA-14359)
   * Fix unbounded validation compactions on repair / revert CASSANDRA-13797 (CASSANDRA-14332)
   * Avoid deadlock when running nodetool refresh before node is fully up (CASSANDRA-14310)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/60ed982d/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/schema/SchemaKeyspace.java
index ca3c69f,027b7cf..638e912
--- a/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
+++ b/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
@@@ -23,9 -25,9 +23,10 @@@ import java.util.*
  import java.util.concurrent.TimeUnit;
  import java.util.stream.Collectors;
  
+ import com.google.common.annotations.VisibleForTesting;
  import com.google.common.collect.*;
  import com.google.common.collect.Maps;
 +import com.google.common.hash.Hasher;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
@@@ -1012,8 -1097,12 +1019,12 @@@ public final class SchemaKeyspac
          if (columnRows.isEmpty())
              throw new MissingColumns("Columns not found in schema table for " + keyspace + "." + table);
  
 -        List<ColumnDefinition> columns = new ArrayList<>();
 +        List<ColumnMetadata> columns = new ArrayList<>();
          columnRows.forEach(row -> columns.add(createColumnFromRow(row, types)));
+ 
 -        if (columns.stream().noneMatch(ColumnDefinition::isPartitionKey))
++        if (columns.stream().noneMatch(ColumnMetadata::isPartitionKey))
+             throw new MissingColumns("No partition key columns found in schema table for " + keyspace + "." + table);
+ 
          return columns;
      }
  

http://git-wip-us.apache.org/repos/asf/cassandra/blob/60ed982d/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
index d4c4bb4,f3ee85d..b3a7047
--- a/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
+++ b/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
@@@ -39,9 -47,22 +39,10 @@@ import org.apache.cassandra.db.Mutation
  import org.apache.cassandra.db.partitions.PartitionUpdate;
  import org.apache.cassandra.db.rows.UnfilteredRowIterators;
  import org.apache.cassandra.exceptions.ConfigurationException;
 -import org.apache.cassandra.io.util.DataInputBuffer;
 -import org.apache.cassandra.io.util.DataOutputBuffer;
 -import org.apache.cassandra.net.MessagingService;
 -import org.apache.cassandra.thrift.CfDef;
 -import org.apache.cassandra.thrift.ColumnDef;
 -import org.apache.cassandra.thrift.IndexType;
 -import org.apache.cassandra.thrift.ThriftConversion;
 -import org.apache.cassandra.utils.ByteBufferUtil;
  import org.apache.cassandra.utils.FBUtilities;
 -import org.apache.cassandra.utils.Pair;
  
+ import static org.apache.cassandra.cql3.QueryProcessor.executeOnceInternal;
  import static org.junit.Assert.assertEquals;
 -import static org.junit.Assert.assertFalse;
  import static org.junit.Assert.assertTrue;
  
  public class SchemaKeyspaceTest
@@@ -131,7 -212,129 +132,35 @@@
          for (UntypedResultSet.Row row : columnsRows)
              columns.add(SchemaKeyspace.createColumnFromRow(row, Types.none()));
  
 -        assertEquals(cfm.params, params);
 -        assertEquals(new HashSet<>(cfm.allColumns()), columns);
 -    }
 -
 -    private static boolean hasCDC(Mutation m)
 -    {
 -        for (PartitionUpdate p : m.getPartitionUpdates())
 -        {
 -            for (ColumnDefinition cd : p.columns())
 -            {
 -                if (cd.name.toString().equals("cdc"))
 -                    return true;
 -            }
 -        }
 -        return false;
 -    }
 -
 -    private static boolean hasSchemaTables(Mutation m)
 -    {
 -        for (PartitionUpdate p : m.getPartitionUpdates())
 -        {
 -            if (p.metadata().cfName.equals(SchemaKeyspace.TABLES))
 -                return true;
 -        }
 -        return false;
 -    }
 -
 -    @Test
 -    public void testConvertSchemaToMutationsWithoutCDC() throws IOException
 -    {
 -        boolean oldCDCOption = DatabaseDescriptor.isCDCEnabled();
 -        try
 -        {
 -            DatabaseDescriptor.setCDCEnabled(false);
 -            Collection<Mutation> mutations = SchemaKeyspace.convertSchemaToMutations();
 -            boolean foundTables = false;
 -            for (Mutation m : mutations)
 -            {
 -                if (hasSchemaTables(m))
 -                {
 -                    foundTables = true;
 -                    assertFalse(hasCDC(m));
 -                    try (DataOutputBuffer output = new DataOutputBuffer())
 -                    {
 -                        Mutation.serializer.serialize(m, output, MessagingService.current_version);
 -                        try (DataInputBuffer input = new DataInputBuffer(output.getData()))
 -                        {
 -                            Mutation out = Mutation.serializer.deserialize(input, MessagingService.current_version);
 -                            assertFalse(hasCDC(out));
 -                        }
 -                    }
 -                }
 -            }
 -            assertTrue(foundTables);
 -        }
 -        finally
 -        {
 -            DatabaseDescriptor.setCDCEnabled(oldCDCOption);
 -        }
 -    }
 -
 -    @Test
 -    public void testConvertSchemaToMutationsWithCDC()
 -    {
 -        boolean oldCDCOption = DatabaseDescriptor.isCDCEnabled();
 -        try
 -        {
 -            DatabaseDescriptor.setCDCEnabled(true);
 -            Collection<Mutation> mutations = SchemaKeyspace.convertSchemaToMutations();
 -            boolean foundTables = false;
 -            for (Mutation m : mutations)
 -            {
 -                if (hasSchemaTables(m))
 -                {
 -                    foundTables = true;
 -                    assertTrue(hasCDC(m));
 -                }
 -            }
 -            assertTrue(foundTables);
 -        }
 -        finally
 -        {
 -            DatabaseDescriptor.setCDCEnabled(oldCDCOption);
 -        }
 -    }
 -
 -    @Test
 -    public void testSchemaDigest()
 -    {
 -        Set<ByteBuffer> abc = Collections.singleton(ByteBufferUtil.bytes("abc"));
 -        Pair<UUID, UUID> versions = SchemaKeyspace.calculateSchemaDigest(abc);
 -        assertTrue(versions.left.equals(versions.right));
 -
 -        Set<ByteBuffer> cdc = Collections.singleton(ByteBufferUtil.bytes("cdc"));
 -        versions = SchemaKeyspace.calculateSchemaDigest(cdc);
 -        assertFalse(versions.left.equals(versions.right));
 +        assertEquals(metadata.params, params);
 +        assertEquals(new HashSet<>(metadata.columns()), columns);
      }
+ 
+     @Test(expected = SchemaKeyspace.MissingColumns.class)
+     public void testSchemaNoPartition()
+     {
+         String testKS = "test_schema_no_partition";
+         String testTable = "invalid_table";
+         SchemaLoader.createKeyspace(testKS,
+                                     KeyspaceParams.simple(1),
+                                     SchemaLoader.standardCFMD(testKS, testTable));
+         // Delete partition column in the schema
+         String query = String.format("DELETE FROM %s.%s WHERE keyspace_name=? and table_name=? and column_name=?", SchemaConstants.SCHEMA_KEYSPACE_NAME, SchemaKeyspace.COLUMNS);
+         executeOnceInternal(query, testKS, testTable, "key");
+         SchemaKeyspace.fetchNonSystemKeyspaces();
+     }
+ 
+     @Test(expected = SchemaKeyspace.MissingColumns.class)
+     public void testSchemaNoColumn()
+     {
+         String testKS = "test_schema_no_Column";
+         String testTable = "invalid_table";
+         SchemaLoader.createKeyspace(testKS,
+                                     KeyspaceParams.simple(1),
+                                     SchemaLoader.standardCFMD(testKS, testTable));
+         // Delete all colmns in the schema
+         String query = String.format("DELETE FROM %s.%s WHERE keyspace_name=? and table_name=?", SchemaConstants.SCHEMA_KEYSPACE_NAME, SchemaKeyspace.COLUMNS);
+         executeOnceInternal(query, testKS, testTable);
+         SchemaKeyspace.fetchNonSystemKeyspaces();
+     }
  }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[5/6] cassandra git commit: Merge branch 'cassandra-3.0' into cassandra-3.11

Posted by jz...@apache.org.
Merge branch 'cassandra-3.0' into cassandra-3.11


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

Branch: refs/heads/cassandra-3.11
Commit: 2d19de1cfabdc848477b33ba922c63013a7a9a1a
Parents: 783bbb3 eb68c31
Author: Jay Zhuang <ja...@yahoo.com>
Authored: Wed May 2 11:02:03 2018 -0700
Committer: Jay Zhuang <ja...@yahoo.com>
Committed: Wed May 2 11:03:34 2018 -0700

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../apache/cassandra/schema/SchemaKeyspace.java | 35 +++++++++++++-------
 .../cassandra/schema/SchemaKeyspaceTest.java    | 29 ++++++++++++++++
 3 files changed, 53 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/2d19de1c/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 443c298,39edeb1..837b891
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,15 -1,5 +1,16 @@@
 -3.0.17
 +3.11.3
 + * Allow existing nodes to use all peers in shadow round (CASSANDRA-13851)
 + * Fix cqlsh to read connection.ssl cqlshrc option again (CASSANDRA-14299)
 + * Downgrade log level to trace for CommitLogSegmentManager (CASSANDRA-14370)
 + * CQL fromJson(null) throws NullPointerException (CASSANDRA-13891)
 + * Serialize empty buffer as empty string for json output format (CASSANDRA-14245)
 + * Allow logging implementation to be interchanged for embedded testing (CASSANDRA-13396)
 + * SASI tokenizer for simple delimiter based entries (CASSANDRA-14247)
 + * Fix Loss of digits when doing CAST from varint/bigint to decimal (CASSANDRA-14170)
 + * RateBasedBackPressure unnecessarily invokes a lock on the Guava RateLimiter (CASSANDRA-14163)
 + * Fix wildcard GROUP BY queries (CASSANDRA-14209)
 +Merged from 3.0:
+  * Better handle missing partition columns in system_schema.columns (CASSANDRA-14379)
   * Delay hints store excise by write timeout to avoid race with decommission (CASSANDRA-13740)
   * Deprecate background repair and probablistic read_repair_chance table options
     (CASSANDRA-13910)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/2d19de1c/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/schema/SchemaKeyspace.java
index 164e32d,81cc2e1..027b7cf
--- a/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
+++ b/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
@@@ -999,18 -961,24 +999,24 @@@ public final class SchemaKeyspac
              }
              catch (MissingColumns exc)
              {
-                 if (!IGNORE_CORRUPTED_SCHEMA_TABLES)
+                 String errorMsg = String.format("No partition columns found for table %s.%s in %s.%s.  This may be due to " +
+                                                 "corruption or concurrent dropping and altering of a table. If this table is supposed " +
+                                                 "to be dropped, {}run the following query to cleanup: " +
+                                                 "\"DELETE FROM %s.%s WHERE keyspace_name = '%s' AND table_name = '%s'; " +
+                                                 "DELETE FROM %s.%s WHERE keyspace_name = '%s' AND table_name = '%s';\" " +
+                                                 "If the table is not supposed to be dropped, restore %s.%s sstables from backups.",
 -                                                keyspaceName, tableName, NAME, COLUMNS,
 -                                                NAME, TABLES, keyspaceName, tableName,
 -                                                NAME, COLUMNS, keyspaceName, tableName,
 -                                                NAME, COLUMNS);
++                                                keyspaceName, tableName, SchemaConstants.SCHEMA_KEYSPACE_NAME, COLUMNS,
++                                                SchemaConstants.SCHEMA_KEYSPACE_NAME, TABLES, keyspaceName, tableName,
++                                                SchemaConstants.SCHEMA_KEYSPACE_NAME, COLUMNS, keyspaceName, tableName,
++                                                SchemaConstants.SCHEMA_KEYSPACE_NAME, COLUMNS);
+ 
+                 if (IGNORE_CORRUPTED_SCHEMA_TABLES)
                  {
-                     logger.error("No columns found for table {}.{} in {}.{}.  This may be due to " +
-                                  "corruption or concurrent dropping and altering of a table.  If this table " +
-                                  "is supposed to be dropped, restart cassandra with -Dcassandra.ignore_corrupted_schema_tables=true " +
-                                  "and run the following query: \"DELETE FROM {}.{} WHERE keyspace_name = '{}' AND table_name = '{}';\"." +
-                                  "If the table is not supposed to be dropped, restore {}.{} sstables from backups.",
-                                  keyspaceName, tableName,
-                                  SchemaConstants.SCHEMA_KEYSPACE_NAME, COLUMNS,
-                                  SchemaConstants.SCHEMA_KEYSPACE_NAME, TABLES,
-                                  keyspaceName, tableName,
-                                  SchemaConstants.SCHEMA_KEYSPACE_NAME, COLUMNS);
+                     logger.error(errorMsg, "", exc);
+                 }
+                 else
+                 {
+                     logger.error(errorMsg, "restart cassandra with -Dcassandra.ignore_corrupted_schema_tables=true and ");
                      throw exc;
                  }
              }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/2d19de1c/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
index 550deed,f76fc4f..f3ee85d
--- a/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
+++ b/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
@@@ -58,10 -51,9 +58,11 @@@ import org.apache.cassandra.thrift.Inde
  import org.apache.cassandra.thrift.ThriftConversion;
  import org.apache.cassandra.utils.ByteBufferUtil;
  import org.apache.cassandra.utils.FBUtilities;
 +import org.apache.cassandra.utils.Pair;
  
+ import static org.apache.cassandra.cql3.QueryProcessor.executeOnceInternal;
  import static org.junit.Assert.assertEquals;
 +import static org.junit.Assert.assertFalse;
  import static org.junit.Assert.assertTrue;
  
  public class SchemaKeyspaceTest
@@@ -215,97 -207,31 +216,125 @@@
          assertEquals(new HashSet<>(cfm.allColumns()), columns);
      }
  
 +    private static boolean hasCDC(Mutation m)
 +    {
 +        for (PartitionUpdate p : m.getPartitionUpdates())
 +        {
 +            for (ColumnDefinition cd : p.columns())
 +            {
 +                if (cd.name.toString().equals("cdc"))
 +                    return true;
 +            }
 +        }
 +        return false;
 +    }
 +
 +    private static boolean hasSchemaTables(Mutation m)
 +    {
 +        for (PartitionUpdate p : m.getPartitionUpdates())
 +        {
 +            if (p.metadata().cfName.equals(SchemaKeyspace.TABLES))
 +                return true;
 +        }
 +        return false;
 +    }
 +
 +    @Test
 +    public void testConvertSchemaToMutationsWithoutCDC() throws IOException
 +    {
 +        boolean oldCDCOption = DatabaseDescriptor.isCDCEnabled();
 +        try
 +        {
 +            DatabaseDescriptor.setCDCEnabled(false);
 +            Collection<Mutation> mutations = SchemaKeyspace.convertSchemaToMutations();
 +            boolean foundTables = false;
 +            for (Mutation m : mutations)
 +            {
 +                if (hasSchemaTables(m))
 +                {
 +                    foundTables = true;
 +                    assertFalse(hasCDC(m));
 +                    try (DataOutputBuffer output = new DataOutputBuffer())
 +                    {
 +                        Mutation.serializer.serialize(m, output, MessagingService.current_version);
 +                        try (DataInputBuffer input = new DataInputBuffer(output.getData()))
 +                        {
 +                            Mutation out = Mutation.serializer.deserialize(input, MessagingService.current_version);
 +                            assertFalse(hasCDC(out));
 +                        }
 +                    }
 +                }
 +            }
 +            assertTrue(foundTables);
 +        }
 +        finally
 +        {
 +            DatabaseDescriptor.setCDCEnabled(oldCDCOption);
 +        }
 +    }
 +
 +    @Test
 +    public void testConvertSchemaToMutationsWithCDC()
 +    {
 +        boolean oldCDCOption = DatabaseDescriptor.isCDCEnabled();
 +        try
 +        {
 +            DatabaseDescriptor.setCDCEnabled(true);
 +            Collection<Mutation> mutations = SchemaKeyspace.convertSchemaToMutations();
 +            boolean foundTables = false;
 +            for (Mutation m : mutations)
 +            {
 +                if (hasSchemaTables(m))
 +                {
 +                    foundTables = true;
 +                    assertTrue(hasCDC(m));
 +                }
 +            }
 +            assertTrue(foundTables);
 +        }
 +        finally
 +        {
 +            DatabaseDescriptor.setCDCEnabled(oldCDCOption);
 +        }
 +    }
 +
 +    @Test
 +    public void testSchemaDigest()
 +    {
 +        Set<ByteBuffer> abc = Collections.singleton(ByteBufferUtil.bytes("abc"));
 +        Pair<UUID, UUID> versions = SchemaKeyspace.calculateSchemaDigest(abc);
 +        assertTrue(versions.left.equals(versions.right));
 +
 +        Set<ByteBuffer> cdc = Collections.singleton(ByteBufferUtil.bytes("cdc"));
 +        versions = SchemaKeyspace.calculateSchemaDigest(cdc);
 +        assertFalse(versions.left.equals(versions.right));
 +    }
++
+     @Test(expected = SchemaKeyspace.MissingColumns.class)
+     public void testSchemaNoPartition()
+     {
+         String testKS = "test_schema_no_partition";
+         String testTable = "invalid_table";
+         SchemaLoader.createKeyspace(testKS,
+                                     KeyspaceParams.simple(1),
+                                     SchemaLoader.standardCFMD(testKS, testTable));
+         // Delete partition column in the schema
 -        String query = String.format("DELETE FROM %s.%s WHERE keyspace_name=? and table_name=? and column_name=?", SchemaKeyspace.NAME, SchemaKeyspace.COLUMNS);
++        String query = String.format("DELETE FROM %s.%s WHERE keyspace_name=? and table_name=? and column_name=?", SchemaConstants.SCHEMA_KEYSPACE_NAME, SchemaKeyspace.COLUMNS);
+         executeOnceInternal(query, testKS, testTable, "key");
+         SchemaKeyspace.fetchNonSystemKeyspaces();
+     }
+ 
+     @Test(expected = SchemaKeyspace.MissingColumns.class)
+     public void testSchemaNoColumn()
+     {
+         String testKS = "test_schema_no_Column";
+         String testTable = "invalid_table";
+         SchemaLoader.createKeyspace(testKS,
+                                     KeyspaceParams.simple(1),
+                                     SchemaLoader.standardCFMD(testKS, testTable));
+         // Delete all colmns in the schema
 -        String query = String.format("DELETE FROM %s.%s WHERE keyspace_name=? and table_name=?", SchemaKeyspace.NAME, SchemaKeyspace.COLUMNS);
++        String query = String.format("DELETE FROM %s.%s WHERE keyspace_name=? and table_name=?", SchemaConstants.SCHEMA_KEYSPACE_NAME, SchemaKeyspace.COLUMNS);
+         executeOnceInternal(query, testKS, testTable);
+         SchemaKeyspace.fetchNonSystemKeyspaces();
+     }
  }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org