cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From alek...@apache.org
Subject [2/6] cassandra git commit: Fix rare NPE on schema upgrade from 2.x to 3.x
Date Fri, 01 Apr 2016 18:22:08 GMT
Fix rare NPE on schema upgrade from 2.x to 3.x

patch by Aleksey Yeschenko; reviewed by Sylvain Lebresne for
CASSANDRA-10943


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

Branch: refs/heads/cassandra-3.5
Commit: 1a1f836f20ba4bf1c263d4fd3c32338e55abbcbc
Parents: 1513139
Author: Aleksey Yeschenko <aleksey@apache.org>
Authored: Wed Mar 23 21:21:29 2016 +0000
Committer: Aleksey Yeschenko <aleksey@apache.org>
Committed: Fri Apr 1 19:19:51 2016 +0100

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../cassandra/schema/LegacySchemaMigrator.java  | 63 +++++++++++++++++++-
 2 files changed, 63 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/1a1f836f/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index d8d4834..0ce75a8 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 3.0.5
+ * Fix rare NPE on schema upgrade from 2.x to 3.x (CASSANDRA-10943)
  * Improve backoff policy for cqlsh COPY FROM (CASSANDRA-11320)
  * Improve IF NOT EXISTS check in CREATE INDEX (CASSANDRA-11131)
  * Upgrade ohc to 0.4.3

http://git-wip-us.apache.org/repos/asf/cassandra/blob/1a1f836f/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java b/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java
index afa0f38..7411b93 100644
--- a/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java
+++ b/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java
@@ -284,7 +284,9 @@ public final class LegacySchemaMigrator
         AbstractType<?> subComparator = tableRow.has("subcomparator") ? TypeParser.parse(tableRow.getString("subcomparator"))
: null;
 
         boolean isSuper = "super".equals(tableRow.getString("type").toLowerCase());
-        boolean isDense = tableRow.getBoolean("is_dense");
+        boolean isDense = tableRow.has("is_dense")
+                        ? tableRow.getBoolean("is_dense")
+                        : calculateIsDense(rawComparator, columnRows);
         boolean isCompound = rawComparator instanceof CompositeType;
 
         // We don't really use the default validator but as we have it for backward compatibility,
we use it to know if it's a counter table
@@ -364,6 +366,65 @@ public final class LegacySchemaMigrator
                   .triggers(createTriggersFromTriggerRows(triggerRows));
     }
 
+    /*
+     * We call dense a CF for which each component of the comparator is a clustering column,
i.e. no
+     * component is used to store a regular column names. In other words, non-composite static
"thrift"
+     * and CQL3 CF are *not* dense.
+     * We save whether the table is dense or not during table creation through CQL, but we
don't have this
+     * information for table just created through thrift, nor for table prior to CASSANDRA-7744,
so this
+     * method does its best to infer whether the table is dense or not based on other elements.
+     */
+    public static boolean calculateIsDense(AbstractType<?> comparator, UntypedResultSet
columnRows)
+    {
+        /*
+         * As said above, this method is only here because we need to deal with thrift upgrades.
+         * Once a CF has been "upgraded", i.e. we've rebuilt and save its CQL3 metadata at
least once,
+         * then we'll have saved the "is_dense" value and will be good to go.
+         *
+         * But non-upgraded thrift CF (and pre-7744 CF) will have no value for "is_dense",
so we need
+         * to infer that information without relying on it in that case. And for the most
part this is
+         * easy, a CF that has at least one REGULAR definition is not dense. But the subtlety
is that not
+         * having a REGULAR definition may not mean dense because of CQL3 definitions that
have only the
+         * PRIMARY KEY defined.
+         *
+         * So we need to recognize those special case CQL3 table with only a primary key.
If we have some
+         * clustering columns, we're fine as said above. So the only problem is that we cannot
decide for
+         * sure if a CF without REGULAR columns nor CLUSTERING_COLUMN definition is meant
to be dense, or if it
+         * has been created in CQL3 by say:
+         *    CREATE TABLE test (k int PRIMARY KEY)
+         * in which case it should not be dense. However, we can limit our margin of error
by assuming we are
+         * in the latter case only if the comparator is exactly CompositeType(UTF8Type).
+         */
+        boolean hasRegular = false;
+        int maxClusteringIdx = -1;
+
+        for (UntypedResultSet.Row columnRow : columnRows)
+        {
+            switch (columnRow.getString("type"))
+            {
+                case "clustering_key":
+                    maxClusteringIdx = Math.max(maxClusteringIdx, columnRow.has("component_index")
? columnRow.getInt("component_index") : 0);
+                    break;
+                case "regular":
+                    hasRegular = true;
+                    break;
+            }
+        }
+
+        return maxClusteringIdx >= 0
+               ? maxClusteringIdx == comparator.componentsCount() - 1
+               : !hasRegular && !isCQL3OnlyPKComparator(comparator);
+    }
+
+    private static boolean isCQL3OnlyPKComparator(AbstractType<?> comparator)
+    {
+        if (!(comparator instanceof CompositeType))
+            return false;
+
+        CompositeType ct = (CompositeType)comparator;
+        return ct.types.size() == 1 && ct.types.get(0) instanceof UTF8Type;
+    }
+
     private static TableParams decodeTableParams(UntypedResultSet.Row row)
     {
         TableParams.Builder params = TableParams.builder();


Mime
View raw message