From 3960260472fcd4e0243f62cc813992f1365197c6 Mon Sep 17 00:00:00 2001 From: Zhao Yang Date: Wed, 2 Aug 2017 11:58:38 +0800 Subject: [PATCH] Fix ColumnMetadata.cellValueType() return type and change sstabledump tool to use type.toJsonString() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit patch by Zhao Yang, reviewed by Andres de la Peña for CASSANDRA-13573 --- CHANGES.txt | 1 + .../cassandra/config/ColumnDefinition.java | 19 ++++++++--- .../apache/cassandra/db/rows/BTreeRow.java | 2 +- .../apache/cassandra/db/rows/BufferCell.java | 2 +- .../cassandra/tools/JsonTransformer.java | 6 ++-- .../org/apache/cassandra/cql3/ViewTest.java | 33 +++++++++++++++++++ 6 files changed, 55 insertions(+), 8 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 905a436865..1525289125 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 3.0.15 + * Fix ColumnDefinition.cellValueType() for non-frozen collection and change SSTabledump to use type.toJSONString() (CASSANDRA-13573) * Skip materialized view addition if the base table doesn't exist (CASSANDRA-13737) * Drop table should remove corresponding entries in dropped_columns table (CASSANDRA-13730) * Log warn message until legacy auth tables have been migrated (CASSANDRA-13371) diff --git a/src/java/org/apache/cassandra/config/ColumnDefinition.java b/src/java/org/apache/cassandra/config/ColumnDefinition.java index 34840e34bf..6a0f530f7d 100644 --- a/src/java/org/apache/cassandra/config/ColumnDefinition.java +++ b/src/java/org/apache/cassandra/config/ColumnDefinition.java @@ -391,13 +391,24 @@ public class ColumnDefinition extends ColumnSpecification implements Comparable< /** * The type of the cell values for cell belonging to this column. * - * This is the same than the column type, except for collections where it's the 'valueComparator' + * This is the same than the column type, except for non-frozen collections where it's the 'valueComparator' * of the collection. + * + * This method should not be used to get value type of non-frozon UDT. */ public AbstractType cellValueType() { - return type instanceof CollectionType - ? ((CollectionType)type).valueComparator() - : type; + assert !(type instanceof UserType && type.isMultiCell()); + return type instanceof CollectionType && type.isMultiCell() + ? ((CollectionType)type).valueComparator() + : type; + } + + + public boolean isCounterColumn() + { + if (type instanceof CollectionType) // for thrift + return ((CollectionType) type).valueComparator().isCounter(); + return type.isCounter(); } } diff --git a/src/java/org/apache/cassandra/db/rows/BTreeRow.java b/src/java/org/apache/cassandra/db/rows/BTreeRow.java index fda33d6418..41dad0ad9a 100644 --- a/src/java/org/apache/cassandra/db/rows/BTreeRow.java +++ b/src/java/org/apache/cassandra/db/rows/BTreeRow.java @@ -294,7 +294,7 @@ public class BTreeRow extends AbstractRow public Row markCounterLocalToBeCleared() { - return transformAndFilter(primaryKeyLivenessInfo, deletion, (cd) -> cd.column().cellValueType().isCounter() + return transformAndFilter(primaryKeyLivenessInfo, deletion, (cd) -> cd.column().isCounterColumn() ? cd.markCounterLocalToBeCleared() : cd); } diff --git a/src/java/org/apache/cassandra/db/rows/BufferCell.java b/src/java/org/apache/cassandra/db/rows/BufferCell.java index e4ad7e62e8..82ae02ca68 100644 --- a/src/java/org/apache/cassandra/db/rows/BufferCell.java +++ b/src/java/org/apache/cassandra/db/rows/BufferCell.java @@ -89,7 +89,7 @@ public class BufferCell extends AbstractCell public boolean isCounterCell() { - return !isTombstone() && column.cellValueType().isCounter(); + return !isTombstone() && column.isCounterColumn(); } public boolean isLive(int nowInSec) diff --git a/src/java/org/apache/cassandra/tools/JsonTransformer.java b/src/java/org/apache/cassandra/tools/JsonTransformer.java index 0a7258347c..5c3203506e 100644 --- a/src/java/org/apache/cassandra/tools/JsonTransformer.java +++ b/src/java/org/apache/cassandra/tools/JsonTransformer.java @@ -39,6 +39,7 @@ import org.apache.cassandra.db.RangeTombstone; import org.apache.cassandra.db.marshal.AbstractType; import org.apache.cassandra.db.marshal.CollectionType; import org.apache.cassandra.db.marshal.CompositeType; +import org.apache.cassandra.db.marshal.UserType; import org.apache.cassandra.db.rows.Cell; import org.apache.cassandra.db.rows.ColumnData; import org.apache.cassandra.db.rows.ComplexColumnData; @@ -49,6 +50,7 @@ import org.apache.cassandra.db.rows.Row; import org.apache.cassandra.db.rows.Unfiltered; import org.apache.cassandra.db.rows.UnfilteredRowIterator; import org.apache.cassandra.io.sstable.ISSTableScanner; +import org.apache.cassandra.transport.Server; import org.apache.cassandra.utils.ByteBufferUtil; import org.codehaus.jackson.JsonFactory; import org.codehaus.jackson.JsonGenerator; @@ -411,7 +413,7 @@ public final class JsonTransformer AbstractType type = cell.column().type; json.writeString(cell.column().name.toCQLString()); - if (cell.path() != null && cell.path().size() > 0) + if (type.isCollection() && type.isMultiCell()) // non-frozen collection { CollectionType ct = (CollectionType) type; json.writeFieldName("path"); @@ -437,7 +439,7 @@ public final class JsonTransformer else { json.writeFieldName("value"); - json.writeString(cell.column().cellValueType().getString(cell.value())); + json.writeRawValue(cell.column().cellValueType().toJSONString(cell.value(), Server.CURRENT_VERSION)); } if (liveInfo.isEmpty() || cell.timestamp() != liveInfo.timestamp()) { diff --git a/test/unit/org/apache/cassandra/cql3/ViewTest.java b/test/unit/org/apache/cassandra/cql3/ViewTest.java index e595ebd34a..f8f8c9f3e6 100644 --- a/test/unit/org/apache/cassandra/cql3/ViewTest.java +++ b/test/unit/org/apache/cassandra/cql3/ViewTest.java @@ -1262,4 +1262,37 @@ public class ViewTest extends CQLTester assertRows(execute("SELECT count(*) FROM mv_test"), row(1024L)); } + + @Test + public void testFrozenCollectionsWithComplicatedInnerType() throws Throwable + { + createTable("CREATE TABLE %s (k int, intval int, listval frozen>>, PRIMARY KEY (k))"); + + execute("USE " + keyspace()); + executeNet(protocolVersion, "USE " + keyspace()); + + createView("mv", + "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE k IS NOT NULL AND listval IS NOT NULL PRIMARY KEY (k, listval)"); + + updateView("INSERT INTO %s (k, intval, listval) VALUES (?, ?, fromJson(?))", + 0, + 0, + "[[\"a\", \"1\"], [\"b\", \"2\"], [\"c\", \"3\"]]"); + + // verify input + assertRows(execute("SELECT k, toJson(listval) FROM %s WHERE k = ?", 0), + row(0, "[[\"a\", \"1\"], [\"b\", \"2\"], [\"c\", \"3\"]]")); + assertRows(execute("SELECT k, toJson(listval) from mv"), + row(0, "[[\"a\", \"1\"], [\"b\", \"2\"], [\"c\", \"3\"]]")); + + // update listval with the same value and it will be compared in view generator + updateView("INSERT INTO %s (k, listval) VALUES (?, fromJson(?))", + 0, + "[[\"a\", \"1\"], [\"b\", \"2\"], [\"c\", \"3\"]]"); + // verify result + assertRows(execute("SELECT k, toJson(listval) FROM %s WHERE k = ?", 0), + row(0, "[[\"a\", \"1\"], [\"b\", \"2\"], [\"c\", \"3\"]]")); + assertRows(execute("SELECT k, toJson(listval) from mv"), + row(0, "[[\"a\", \"1\"], [\"b\", \"2\"], [\"c\", \"3\"]]")); + } }