Provide user workaround for partially corrupt schema tables Patch by Tyler Hobbs; reviewed by Aleksey Yeschenko for CASSANDRA-13180
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/a70b0d4d Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/a70b0d4d Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/a70b0d4d Branch: refs/heads/cassandra-3.11 Commit: a70b0d4d37851891ec1c8af96063985a5122edda Parents: 6caf3c4 Author: Tyler Hobbs <tylerlho...@gmail.com> Authored: Fri Feb 3 11:25:27 2017 -0600 Committer: Tyler Hobbs <tylerlho...@gmail.com> Committed: Fri Feb 3 11:25:27 2017 -0600 ---------------------------------------------------------------------- CHANGES.txt | 2 ++ .../apache/cassandra/schema/SchemaKeyspace.java | 36 ++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/a70b0d4d/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index e3bda6c..ade3d5a 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,6 @@ 3.0.11 + * Provide user workaround when system_schema.columns does not contain entries + for a table that's in system_schema.tables (CASSANDRA-13180) * Dump threads when unit tests time out (CASSANDRA-13117) * Better error when modifying function permissions without explicit keyspace (CASSANDRA-12925) * Indexer is not correctly invoked when building indexes over sstables (CASSANDRA-13075) http://git-wip-us.apache.org/repos/asf/cassandra/blob/a70b0d4d/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 84a5e13..eee4fbb 100644 --- a/src/java/org/apache/cassandra/schema/SchemaKeyspace.java +++ b/src/java/org/apache/cassandra/schema/SchemaKeyspace.java @@ -67,6 +67,7 @@ public final class SchemaKeyspace private static final Logger logger = LoggerFactory.getLogger(SchemaKeyspace.class); private static final boolean FLUSH_SCHEMA_TABLES = Boolean.valueOf(System.getProperty("cassandra.test.flush_local_schema_changes", "true")); + private static final boolean IGNORE_CORRUPTED_SCHEMA_TABLES = Boolean.valueOf(System.getProperty("cassandra.ignore_corrupted_schema_tables", "false")); public static final String NAME = "system_schema"; @@ -925,7 +926,26 @@ public final class SchemaKeyspace Tables.Builder tables = org.apache.cassandra.schema.Tables.builder(); for (UntypedResultSet.Row row : query(query, keyspaceName)) - tables.add(fetchTable(keyspaceName, row.getString("table_name"), types)); + { + String tableName = row.getString("table_name"); + try + { + tables.add(fetchTable(keyspaceName, tableName, types)); + } + catch (MissingColumns exc) + { + 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); + throw exc; + } + } + } return tables.build(); } @@ -991,8 +1011,12 @@ public final class SchemaKeyspace private static List<ColumnDefinition> fetchColumns(String keyspace, String table, Types types) { String query = format("SELECT * FROM %s.%s WHERE keyspace_name = ? AND table_name = ?", NAME, COLUMNS); + UntypedResultSet columnRows = query(query, keyspace, table); + if (columnRows.isEmpty()) + throw new MissingColumns("Columns not found in schema table for " + keyspace + "." + table); + List<ColumnDefinition> columns = new ArrayList<>(); - query(query, keyspace, table).forEach(row -> columns.add(createColumnFromRow(row, types))); + columnRows.forEach(row -> columns.add(createColumnFromRow(row, types))); return columns; } @@ -1399,4 +1423,12 @@ public final class SchemaKeyspace .map(SchemaKeyspace::expandUserTypes) .collect(toList()); } + + private static class MissingColumns extends RuntimeException + { + MissingColumns(String message) + { + super(message); + } + } }