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/8d98a992 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/8d98a992 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/8d98a992 Branch: refs/heads/trunk Commit: 8d98a99231f38102d0ef572ffe948d705169aae4 Parents: 000007f cf0b6d1 Author: Benjamin Lerer <b.le...@gmail.com> Authored: Thu Aug 24 18:21:08 2017 +0200 Committer: Benjamin Lerer <b.le...@gmail.com> Committed: Thu Aug 24 18:22:13 2017 +0200 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../cassandra/db/SerializationHeader.java | 13 +- .../db/rows/AbstractTypeVersionComparator.java | 121 ++++++++++++ src/java/org/apache/cassandra/db/rows/Row.java | 18 +- src/java/org/apache/cassandra/db/rows/Rows.java | 22 ++- .../io/sstable/format/SSTableReader.java | 20 +- .../org/apache/cassandra/cql3/CQLTester.java | 20 +- .../cql3/validation/entities/UserTypesTest.java | 151 +++++++++++++++ .../rows/AbstractTypeVersionComparatorTest.java | 188 +++++++++++++++++++ 9 files changed, 533 insertions(+), 21 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/8d98a992/CHANGES.txt ---------------------------------------------------------------------- diff --cc CHANGES.txt index d39f78c,ba35152..8fb8e2f --- a/CHANGES.txt +++ b/CHANGES.txt @@@ -1,11 -1,5 +1,12 @@@ -3.0.15 +3.11.1 + * Fix cassandra-stress hang issues when an error during cluster connection happens (CASSANDRA-12938) + * Better bootstrap failure message when blocked by (potential) range movement (CASSANDRA-13744) + * "ignore" option is ignored in sstableloader (CASSANDRA-13721) + * Deadlock in AbstractCommitLogSegmentManager (CASSANDRA-13652) + * Duplicate the buffer before passing it to analyser in SASI operation (CASSANDRA-13512) + * Properly evict pstmts from prepared statements cache (CASSANDRA-13641) +Merged from 3.0: + * Fix the merging of cells with different user type versions (CASSANDRA-13776) * Copy session properties on cqlsh.py do_login (CASSANDRA-13640) * Potential AssertionError during ReadRepair of range tombstone and partition deletions (CASSANDRA-13719) * Don't let stress write warmup data if n=0 (CASSANDRA-13773) http://git-wip-us.apache.org/repos/asf/cassandra/blob/8d98a992/src/java/org/apache/cassandra/db/SerializationHeader.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/8d98a992/src/java/org/apache/cassandra/db/rows/Row.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/8d98a992/src/java/org/apache/cassandra/db/rows/Rows.java ---------------------------------------------------------------------- diff --cc src/java/org/apache/cassandra/db/rows/Rows.java index a92bdac,09213a4..3331506 --- a/src/java/org/apache/cassandra/db/rows/Rows.java +++ b/src/java/org/apache/cassandra/db/rows/Rows.java @@@ -26,9 -25,7 +26,8 @@@ import org.apache.cassandra.config.CFMe import org.apache.cassandra.config.ColumnDefinition; import org.apache.cassandra.db.*; import org.apache.cassandra.db.partitions.PartitionStatisticsCollector; - import org.apache.cassandra.db.rows.Row.Deletion; import org.apache.cassandra.utils.MergeIterator; +import org.apache.cassandra.utils.WrappedInt; /** * Static utilities to work on Row objects. @@@ -330,78 -312,20 +330,96 @@@ public abstract class Row } /** + * Returns a row that is obtained from the given existing row by removing everything that is shadowed by data in + * the update row. In other words, produces the smallest result row such that + * {@code merge(result, update, nowInSec) == merge(existing, update, nowInSec)} after filtering by rangeDeletion. + * + * @param existing source row + * @param update shadowing row + * @param rangeDeletion extra {@code DeletionTime} from covering tombstone + * @param nowInSec the current time in seconds (which plays a role during reconciliation + * because deleted cells always have precedence on timestamp equality and deciding if a + * cell is a live or not depends on the current time due to expiring cells). + */ + public static Row removeShadowedCells(Row existing, Row update, DeletionTime rangeDeletion, int nowInSec) + { + Row.Builder builder = BTreeRow.sortedBuilder(); + Clustering clustering = existing.clustering(); + builder.newRow(clustering); + + DeletionTime deletion = update.deletion().time(); + if (rangeDeletion.supersedes(deletion)) + deletion = rangeDeletion; + + LivenessInfo existingInfo = existing.primaryKeyLivenessInfo(); + if (!deletion.deletes(existingInfo)) + builder.addPrimaryKeyLivenessInfo(existingInfo); + Row.Deletion rowDeletion = existing.deletion(); + if (!deletion.supersedes(rowDeletion.time())) + builder.addRowDeletion(rowDeletion); + + Iterator<ColumnData> a = existing.iterator(); + Iterator<ColumnData> b = update.iterator(); + ColumnData nexta = a.hasNext() ? a.next() : null, nextb = b.hasNext() ? b.next() : null; + while (nexta != null) + { + int comparison = nextb == null ? -1 : nexta.column.compareTo(nextb.column); + if (comparison <= 0) + { + ColumnData cura = nexta; + ColumnDefinition column = cura.column; + ColumnData curb = comparison == 0 ? nextb : null; + if (column.isSimple()) + { + Cells.addNonShadowed((Cell) cura, (Cell) curb, deletion, builder, nowInSec); + } + else + { + ComplexColumnData existingData = (ComplexColumnData) cura; + ComplexColumnData updateData = (ComplexColumnData) curb; + + DeletionTime existingDt = existingData.complexDeletion(); + DeletionTime updateDt = updateData == null ? DeletionTime.LIVE : updateData.complexDeletion(); + + DeletionTime maxDt = updateDt.supersedes(deletion) ? updateDt : deletion; + if (existingDt.supersedes(maxDt)) + { + builder.addComplexDeletion(column, existingDt); + maxDt = existingDt; + } + + Iterator<Cell> existingCells = existingData.iterator(); + Iterator<Cell> updateCells = updateData == null ? null : updateData.iterator(); + Cells.addNonShadowedComplex(column, existingCells, updateCells, maxDt, builder, nowInSec); + } + nexta = a.hasNext() ? a.next() : null; + if (curb != null) + nextb = b.hasNext() ? b.next() : null; + } + else + { + nextb = b.hasNext() ? b.next() : null; + } + } + Row row = builder.build(); + return row != null && !row.isEmpty() ? row : null; + } ++ ++ /** + * Returns the {@code ColumnDefinition} to use for merging the columns. + * If the 2 column definitions are different the latest one will be returned. + */ + private static ColumnDefinition getColumnDefinition(ColumnData cura, ColumnData curb) + { + if (cura == null) + return curb.column; + + if (curb == null) + return cura.column; + + if (AbstractTypeVersionComparator.INSTANCE.compare(cura.column.type, curb.column.type) >= 0) + return cura.column; + + return curb.column; + } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/8d98a992/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/8d98a992/test/unit/org/apache/cassandra/cql3/CQLTester.java ---------------------------------------------------------------------- diff --cc test/unit/org/apache/cassandra/cql3/CQLTester.java index 2542db0,40aec88..c0513ce --- a/test/unit/org/apache/cassandra/cql3/CQLTester.java +++ b/test/unit/org/apache/cassandra/cql3/CQLTester.java @@@ -425,9 -396,34 +425,10 @@@ public abstract class CQLTeste public void disableCompaction(String keyspace) { ColumnFamilyStore store = getCurrentColumnFamilyStore(keyspace); - store.disableAutoCompaction(); + if (store != null) + store.disableAutoCompaction(); } - public void flush(boolean forceFlush) - { - if (forceFlush) - flush(); - } - - @FunctionalInterface - public interface CheckedFunction { - void apply() throws Throwable; - } - - /** - * Runs the given function before and after a flush of sstables. This is useful for checking that behavior is - * the same whether data is in memtables or sstables. - * @param runnable - * @throws Throwable - */ - public void beforeAndAfterFlush(CheckedFunction runnable) throws Throwable - { - runnable.apply(); - flush(); - runnable.apply(); - } - public void compact() { try http://git-wip-us.apache.org/repos/asf/cassandra/blob/8d98a992/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java ---------------------------------------------------------------------- diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java index b78eb3e,dfc2e5e..9ea5572 --- a/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java @@@ -624,109 -563,156 +624,260 @@@ public class UserTypesTest extends CQLT } @Test + public void testInsertNonFrozenUDT() throws Throwable + { + String typeName = createType("CREATE TYPE %s (a int, b text)"); + createTable("CREATE TABLE %s (k int PRIMARY KEY, v " + typeName + ")"); + + execute("INSERT INTO %s (k, v) VALUES (?, {a: ?, b: ?})", 0, 0, "abc"); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", "abc"))); + + execute("INSERT INTO %s (k, v) VALUES (?, ?)", 0, userType("a", 0, "b", "abc")); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", "abc"))); + + execute("INSERT INTO %s (k, v) VALUES (?, {a: ?, b: ?})", 0, 0, null); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", null))); + + execute("INSERT INTO %s (k, v) VALUES (?, ?)", 0, userType("a", null, "b", "abc")); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", null, "b", "abc"))); + } + + @Test + public void testUpdateNonFrozenUDT() throws Throwable + { + String typeName = createType("CREATE TYPE %s (a int, b text)"); + createTable("CREATE TABLE %s (k int PRIMARY KEY, v " + typeName + ")"); + + execute("INSERT INTO %s (k, v) VALUES (?, ?)", 0, userType("a", 0, "b", "abc")); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", "abc"))); + + // overwrite the whole UDT + execute("UPDATE %s SET v = ? WHERE k = ?", userType("a", 1, "b", "def"), 0); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 1, "b", "def"))); + + execute("UPDATE %s SET v = ? WHERE k = ?", userType("a", 0, "b", null), 0); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", null))); + + execute("UPDATE %s SET v = ? WHERE k = ?", userType("a", null, "b", "abc"), 0); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", null, "b", "abc"))); + + // individually set fields to non-null values + execute("UPDATE %s SET v.a = ? WHERE k = ?", 1, 0); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 1, "b", "abc"))); + + execute("UPDATE %s SET v.b = ? WHERE k = ?", "def", 0); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 1, "b", "def"))); + + execute("UPDATE %s SET v.a = ?, v.b = ? WHERE k = ?", 0, "abc", 0); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", "abc"))); + + execute("UPDATE %s SET v.b = ?, v.a = ? WHERE k = ?", "abc", 0, 0); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", "abc"))); + + // individually set fields to null values + execute("UPDATE %s SET v.a = ? WHERE k = ?", null, 0); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", null, "b", "abc"))); + + execute("UPDATE %s SET v.a = ? WHERE k = ?", 0, 0); + execute("UPDATE %s SET v.b = ? WHERE k = ?", null, 0); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", null))); + + execute("UPDATE %s SET v.a = ? WHERE k = ?", null, 0); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, null)); + + assertInvalid("UPDATE %s SET v.bad = ? FROM %s WHERE k = ?", 0, 0); + assertInvalid("UPDATE %s SET v = ? FROM %s WHERE k = ?", 0, 0); + assertInvalid("UPDATE %s SET v = ? FROM %s WHERE k = ?", userType("a", 1, "b", "abc", "bad", 123), 0); + } + + @Test + public void testDeleteNonFrozenUDT() throws Throwable + { + String typeName = createType("CREATE TYPE %s (a int, b text)"); + createTable("CREATE TABLE %s (k int PRIMARY KEY, v " + typeName + ")"); + + execute("INSERT INTO %s (k, v) VALUES (?, ?)", 0, userType("a", 0, "b", "abc")); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", "abc"))); + + execute("DELETE v.b FROM %s WHERE k = ?", 0); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", null))); + + execute("INSERT INTO %s (k, v) VALUES (?, ?)", 0, userType("a", 0, "b", "abc")); + execute("DELETE v.a FROM %s WHERE k = ?", 0); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", null, "b", "abc"))); + + execute("DELETE v.b FROM %s WHERE k = ?", 0); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, null)); + + // delete both fields at once + execute("INSERT INTO %s (k, v) VALUES (?, ?)", 0, userType("a", 0, "b", "abc")); + execute("DELETE v.a, v.b FROM %s WHERE k = ?", 0); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, null)); + + // same, but reverse field order + execute("INSERT INTO %s (k, v) VALUES (?, ?)", 0, userType("a", 0, "b", "abc")); + execute("DELETE v.b, v.a FROM %s WHERE k = ?", 0); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, null)); + + // delete the whole thing at once + execute("INSERT INTO %s (k, v) VALUES (?, ?)", 0, userType("a", 0, "b", "abc")); + execute("DELETE v FROM %s WHERE k = ?", 0); + assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, null)); + + assertInvalid("DELETE v.bad FROM %s WHERE k = ?", 0); + } + ++ @Test + public void testReadAfterAlteringUserTypeNestedWithinSet() throws Throwable + { + String columnType = typeWithKs(createType("CREATE TYPE %s (a int)")); + + try + { + createTable("CREATE TABLE %s (x int PRIMARY KEY, y set<frozen<" + columnType + ">>)"); + disableCompaction(); + - execute("INSERT INTO %s (x, y) VALUES(1, ?)", set(userType(1), userType(2))); - assertRows(execute("SELECT * FROM %s"), row(1, set(userType(1), userType(2)))); ++ execute("INSERT INTO %s (x, y) VALUES(1, ?)", set(userType("a", 1), userType("a", 2))); ++ assertRows(execute("SELECT * FROM %s"), row(1, set(userType("a", 1), userType("a", 2)))); + flush(); + + assertRows(execute("SELECT * FROM %s WHERE x = 1"), - row(1, set(userType(1), userType(2)))); ++ row(1, set(userType("a", 1), userType("a", 2)))); + + execute("ALTER TYPE " + columnType + " ADD b int"); + execute("UPDATE %s SET y = y + ? WHERE x = 1", - set(userType(1, 1), userType(1, 2), userType(2, 1))); ++ set(userType("a", 1, "b", 1), userType("a", 1, "b", 2), userType("a", 2, "b", 1))); + + flush(); + assertRows(execute("SELECT * FROM %s WHERE x = 1"), - row(1, set(userType(1), - userType(1, 1), - userType(1, 2), - userType(2), - userType(2, 1)))); ++ row(1, set(userType("a", 1), ++ userType("a", 1, "b", 1), ++ userType("a", 1, "b", 2), ++ userType("a", 2), ++ userType("a", 2, "b", 1)))); + + compact(); + + assertRows(execute("SELECT * FROM %s WHERE x = 1"), - row(1, set(userType(1), - userType(1, 1), - userType(1, 2), - userType(2), - userType(2, 1)))); ++ row(1, set(userType("a", 1), ++ userType("a", 1, "b", 1), ++ userType("a", 1, "b", 2), ++ userType("a", 2), ++ userType("a", 2, "b", 1)))); + } + finally + { + enableCompaction(); + } + } + + @Test + public void testReadAfterAlteringUserTypeNestedWithinMap() throws Throwable + { + String columnType = typeWithKs(createType("CREATE TYPE %s (a int)")); + + try + { + createTable("CREATE TABLE %s (x int PRIMARY KEY, y map<frozen<" + columnType + ">, int>)"); + disableCompaction(); + - execute("INSERT INTO %s (x, y) VALUES(1, ?)", map(userType(1), 1, userType(2), 2)); - assertRows(execute("SELECT * FROM %s"), row(1, map(userType(1), 1, userType(2), 2))); ++ execute("INSERT INTO %s (x, y) VALUES(1, ?)", map(userType("a", 1), 1, userType("a", 2), 2)); ++ assertRows(execute("SELECT * FROM %s"), row(1, map(userType("a", 1), 1, userType("a", 2), 2))); + flush(); + + assertRows(execute("SELECT * FROM %s WHERE x = 1"), - row(1, map(userType(1), 1, userType(2), 2))); ++ row(1, map(userType("a", 1), 1, userType("a", 2), 2))); + + execute("ALTER TYPE " + columnType + " ADD b int"); + execute("UPDATE %s SET y = y + ? WHERE x = 1", - map(userType(1, 1), 1, userType(1, 2), 1, userType(2, 1), 2)); ++ map(userType("a", 1, "b", 1), 1, userType("a", 1, "b", 2), 1, userType("a", 2, "b", 1), 2)); + + flush(); + assertRows(execute("SELECT * FROM %s WHERE x = 1"), - row(1, map(userType(1), 1, - userType(1, 1), 1, - userType(1, 2), 1, - userType(2), 2, - userType(2, 1), 2))); ++ row(1, map(userType("a", 1), 1, ++ userType("a", 1, "b", 1), 1, ++ userType("a", 1, "b", 2), 1, ++ userType("a", 2), 2, ++ userType("a", 2, "b", 1), 2))); + + compact(); + + assertRows(execute("SELECT * FROM %s WHERE x = 1"), - row(1, map(userType(1), 1, - userType(1, 1), 1, - userType(1, 2), 1, - userType(2), 2, - userType(2, 1), 2))); ++ row(1, map(userType("a", 1), 1, ++ userType("a", 1, "b", 1), 1, ++ userType("a", 1, "b", 2), 1, ++ userType("a", 2), 2, ++ userType("a", 2, "b", 1), 2))); + } + finally + { + enableCompaction(); + } + } + + @Test + public void testReadAfterAlteringUserTypeNestedWithinList() throws Throwable + { + String columnType = typeWithKs(createType("CREATE TYPE %s (a int)")); + + try + { + createTable("CREATE TABLE %s (x int PRIMARY KEY, y list<frozen<" + columnType + ">>)"); + disableCompaction(); + - execute("INSERT INTO %s (x, y) VALUES(1, ?)", list(userType(1), userType(2))); - assertRows(execute("SELECT * FROM %s"), row(1, list(userType(1), userType(2)))); ++ execute("INSERT INTO %s (x, y) VALUES(1, ?)", list(userType("a", 1), userType("a", 2))); ++ assertRows(execute("SELECT * FROM %s"), row(1, list(userType("a", 1), userType("a", 2)))); + flush(); + + assertRows(execute("SELECT * FROM %s WHERE x = 1"), - row(1, list(userType(1), userType(2)))); ++ row(1, list(userType("a", 1), userType("a", 2)))); + + execute("ALTER TYPE " + columnType + " ADD b int"); + execute("UPDATE %s SET y = y + ? WHERE x = 1", - list(userType(1, 1), userType(1, 2), userType(2, 1))); ++ list(userType("a", 1, "b", 1), userType("a", 1, "b", 2), userType("a", 2, "b", 1))); + + flush(); + assertRows(execute("SELECT * FROM %s WHERE x = 1"), - row(1, list(userType(1), - userType(2), - userType(1, 1), - userType(1, 2), - userType(2, 1)))); ++ row(1, list(userType("a", 1), ++ userType("a", 2), ++ userType("a", 1, "b", 1), ++ userType("a", 1, "b", 2), ++ userType("a", 2, "b", 1)))); + + compact(); + + assertRows(execute("SELECT * FROM %s WHERE x = 1"), - row(1, list(userType(1), - userType(2), - userType(1, 1), - userType(1, 2), - userType(2, 1)))); ++ row(1, list(userType("a", 1), ++ userType("a", 2), ++ userType("a", 1, "b", 1), ++ userType("a", 1, "b", 2), ++ userType("a", 2, "b", 1)))); + } + finally + { + enableCompaction(); + } + } + + @Test + public void testAlteringUserTypeNestedWithinSetWithView() throws Throwable + { + String columnType = typeWithKs(createType("CREATE TYPE %s (a int)")); + + createTable("CREATE TABLE %s (pk int, c int, v int, s set<frozen<" + columnType + ">>, PRIMARY KEY (pk, c))"); + execute("CREATE MATERIALIZED VIEW " + keyspace() + ".view1 AS SELECT c, pk, v FROM %s WHERE pk IS NOT NULL AND c IS NOT NULL AND v IS NOT NULL PRIMARY KEY (c, pk)"); + - execute("INSERT INTO %s (pk, c, v, s) VALUES(?, ?, ?, ?)", 1, 1, 1, set(userType(1), userType(2))); ++ execute("INSERT INTO %s (pk, c, v, s) VALUES(?, ?, ?, ?)", 1, 1, 1, set(userType("a", 1), userType("a", 2))); + flush(); + + execute("ALTER TYPE " + columnType + " ADD b int"); + execute("UPDATE %s SET s = s + ?, v = ? WHERE pk = ? AND c = ?", - set(userType(1, 1), userType(1, 2), userType(2, 1)), 2, 1, 1); ++ set(userType("a", 1, "b", 1), userType("a", 1, "b", 2), userType("a", 2, "b", 1)), 2, 1, 1); + + assertRows(execute("SELECT * FROM %s WHERE pk = ? AND c = ?", 1, 1), - row(1, 1,set(userType(1), userType(1, 1), userType(1, 2), userType(2), userType(2, 1)), 2)); ++ row(1, 1,set(userType("a", 1), userType("a", 1, "b", 1), userType("a", 1, "b", 2), userType("a", 2), userType("a", 2, "b", 1)), 2)); + } + private String typeWithKs(String type1) { return keyspace() + '.' + type1; http://git-wip-us.apache.org/repos/asf/cassandra/blob/8d98a992/test/unit/org/apache/cassandra/db/rows/AbstractTypeVersionComparatorTest.java ---------------------------------------------------------------------- diff --cc test/unit/org/apache/cassandra/db/rows/AbstractTypeVersionComparatorTest.java index 0000000,ad0c05c..7170696 mode 000000,100644..100644 --- a/test/unit/org/apache/cassandra/db/rows/AbstractTypeVersionComparatorTest.java +++ b/test/unit/org/apache/cassandra/db/rows/AbstractTypeVersionComparatorTest.java @@@ -1,0 -1,184 +1,188 @@@ + /* + * 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.db.rows; + + import java.nio.ByteBuffer; + import java.util.Set; + + import org.junit.After; + import org.junit.Before; + import org.junit.Test; + + import org.apache.cassandra.db.marshal.*; + + import static java.util.Arrays.asList; ++import static org.apache.cassandra.cql3.FieldIdentifier.forUnquoted; + import static org.apache.cassandra.utils.ByteBufferUtil.bytes; + import static org.junit.Assert.assertEquals; + import static org.junit.Assert.fail; + + public class AbstractTypeVersionComparatorTest + { + private UserType udtWith2Fields; + private UserType udtWith3Fields; + + @Before + public void setUp() + { + udtWith2Fields = new UserType("ks", + bytes("myType"), - asList(bytes("a"), bytes("b")), - asList(Int32Type.instance, Int32Type.instance)); ++ asList(forUnquoted("a"), forUnquoted("b")), ++ asList(Int32Type.instance, Int32Type.instance), ++ false); + udtWith3Fields = new UserType("ks", + bytes("myType"), - asList(bytes("a"), bytes("b"), bytes("c")), - asList(Int32Type.instance, Int32Type.instance, Int32Type.instance)); ++ asList(forUnquoted("a"), forUnquoted("b"), forUnquoted("c")), ++ asList(Int32Type.instance, Int32Type.instance, Int32Type.instance), ++ false); + } + + @After + public void tearDown() + { + udtWith2Fields = null; + udtWith3Fields = null; + } + + @Test + public void testWithTuples() + { + checkComparisonResults(new TupleType(asList(Int32Type.instance, Int32Type.instance)), + new TupleType(asList(Int32Type.instance, Int32Type.instance, Int32Type.instance))); + } + + @Test + public void testWithUDTs() + { + checkComparisonResults(udtWith2Fields, udtWith3Fields); + } + + @Test + public void testWithUDTsNestedWithinSet() + { + for (boolean isMultiCell : new boolean[]{false, true}) + { + SetType<ByteBuffer> set1 = SetType.getInstance(udtWith2Fields, isMultiCell); + SetType<ByteBuffer> set2 = SetType.getInstance(udtWith3Fields, isMultiCell); + checkComparisonResults(set1, set2); + } + } + + @Test + public void testWithUDTsNestedWithinList() + { + for (boolean isMultiCell : new boolean[]{false, true}) + { + ListType<ByteBuffer> list1 = ListType.getInstance(udtWith2Fields, isMultiCell); + ListType<ByteBuffer> list2 = ListType.getInstance(udtWith3Fields, isMultiCell); + checkComparisonResults(list1, list2); + } + } + + @Test + public void testWithUDTsNestedWithinMap() + { + for (boolean isMultiCell : new boolean[]{false, true}) + { + MapType<ByteBuffer, Integer> map1 = MapType.getInstance(udtWith2Fields, Int32Type.instance, isMultiCell); + MapType<ByteBuffer, Integer> map2 = MapType.getInstance(udtWith3Fields, Int32Type.instance, isMultiCell); + checkComparisonResults(map1, map2); + } + + for (boolean isMultiCell : new boolean[]{false, true}) + { + MapType<Integer, ByteBuffer> map1 = MapType.getInstance(Int32Type.instance, udtWith2Fields, isMultiCell); + MapType<Integer, ByteBuffer> map2 = MapType.getInstance(Int32Type.instance, udtWith3Fields, isMultiCell); + checkComparisonResults(map1, map2); + } + } + + @Test + public void testWithUDTsNestedWithinTuple() + { + TupleType tuple1 = new TupleType(asList(udtWith2Fields, Int32Type.instance)); + TupleType tuple2 = new TupleType(asList(udtWith3Fields, Int32Type.instance)); + checkComparisonResults(tuple1, tuple2); + } + + @Test + public void testWithUDTsNestedWithinComposite() + { + CompositeType composite1 = CompositeType.getInstance(asList(udtWith2Fields, Int32Type.instance)); + CompositeType composite2 = CompositeType.getInstance(asList(udtWith3Fields, Int32Type.instance)); + checkComparisonResults(composite1, composite2); + } + + @Test + public void testWithDeeplyNestedUDT() + { + for (boolean isMultiCell : new boolean[]{false, true}) + { + ListType<Set<ByteBuffer>> list1 = ListType.getInstance(SetType.getInstance(new TupleType(asList(udtWith2Fields, Int32Type.instance)), isMultiCell), isMultiCell); + ListType<Set<ByteBuffer>> list2 = ListType.getInstance(SetType.getInstance(new TupleType(asList(udtWith3Fields, Int32Type.instance)), isMultiCell), isMultiCell); + checkComparisonResults(list1, list2); + } + } + + @Test + public void testInvalidComparison() + { - assertInvalidComparison("Trying to compare 2 different types: org.apache.cassandra.db.marshal.UserType(ks,6d7954797065,61:org.apache.cassandra.db.marshal.Int32Type,62:org.apache.cassandra.db.marshal.Int32Type) and org.apache.cassandra.db.marshal.Int32Type", ++ assertInvalidComparison("Trying to compare 2 different types: org.apache.cassandra.db.marshal.FrozenType(org.apache.cassandra.db.marshal.UserType(ks,6d7954797065,61:org.apache.cassandra.db.marshal.Int32Type,62:org.apache.cassandra.db.marshal.Int32Type)) and org.apache.cassandra.db.marshal.Int32Type", + udtWith2Fields, + Int32Type.instance); + assertInvalidComparison("Trying to compare 2 different types: org.apache.cassandra.db.marshal.UTF8Type and org.apache.cassandra.db.marshal.InetAddressType", + SetType.getInstance(UTF8Type.instance, true), + SetType.getInstance(InetAddressType.instance, true)); + assertInvalidComparison("Trying to compare 2 different types: org.apache.cassandra.db.marshal.UTF8Type and org.apache.cassandra.db.marshal.InetAddressType", + ListType.getInstance(UTF8Type.instance, true), + ListType.getInstance(InetAddressType.instance, true)); + assertInvalidComparison("Trying to compare 2 different types: org.apache.cassandra.db.marshal.UTF8Type and org.apache.cassandra.db.marshal.InetAddressType", + MapType.getInstance(UTF8Type.instance, IntegerType.instance, true), + MapType.getInstance(InetAddressType.instance, IntegerType.instance, true)); + assertInvalidComparison("Trying to compare 2 different types: org.apache.cassandra.db.marshal.UTF8Type and org.apache.cassandra.db.marshal.InetAddressType", + MapType.getInstance(IntegerType.instance, UTF8Type.instance, true), + MapType.getInstance(IntegerType.instance, InetAddressType.instance, true)); + } + + private void assertInvalidComparison(String expectedMessage, AbstractType<?> oldVersion, AbstractType<?> newVersion) + { + try + { + checkComparisonResults(oldVersion, newVersion); + fail("comparison doesn't throw expected IllegalArgumentException: " + expectedMessage); + } + catch (IllegalArgumentException e) + { ++ System.out.println(e.getMessage()); + assertEquals(e.getMessage(), expectedMessage); + } + } + + private void checkComparisonResults(AbstractType<?> oldVersion, AbstractType<?> newVersion) + { + assertEquals(0, compare(oldVersion, oldVersion)); + assertEquals(0, compare(newVersion, newVersion)); + assertEquals(-1, compare(oldVersion, newVersion)); + assertEquals(1, compare(newVersion, oldVersion)); + } + - private int compare(AbstractType<?> left, AbstractType<?> right) ++ private static int compare(AbstractType<?> left, AbstractType<?> right) + { + return AbstractTypeVersionComparator.INSTANCE.compare(left, right); + } + } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org