Repository: cassandra Updated Branches: refs/heads/cassandra-2.2 8556a2b93 -> 3f4501077 refs/heads/cassandra-3.0 e2bdf9971 -> 0020e79f8 refs/heads/cassandra-3.11 3f89d2446 -> 87e8c6be7 refs/heads/trunk 1f7a1dde5 -> eaa594865
Fix ColumnCounter::countAll behaviour for reverse queries Patch by Sam Tunnicliffe; reviewed by Jason Brown for CASSANDRA-13222 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/3f450107 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/3f450107 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/3f450107 Branch: refs/heads/cassandra-2.2 Commit: 3f450107749c637ba133e479e7b6e5cd02e1153f Parents: 8556a2b Author: Sam Tunnicliffe <s...@beobal.com> Authored: Mon Feb 20 11:38:32 2017 +0000 Committer: Sam Tunnicliffe <s...@beobal.com> Committed: Mon Feb 20 11:43:52 2017 +0000 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../cassandra/db/filter/ColumnCounter.java | 19 ++++++- .../cassandra/service/QueryPagerTest.java | 52 +++++++++++++++++++- 3 files changed, 69 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f450107/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 1b83501..7073356 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 2.2.10 + * Fix ColumnCounter::countAll behaviour for reverse queries (CASSANDRA-13222) * Exceptions encountered calling getSeeds() breaks OTC thread (CASSANDRA-13018) 2.2.9 http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f450107/src/java/org/apache/cassandra/db/filter/ColumnCounter.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/filter/ColumnCounter.java b/src/java/org/apache/cassandra/db/filter/ColumnCounter.java index 0d5acd1..594fde8 100644 --- a/src/java/org/apache/cassandra/db/filter/ColumnCounter.java +++ b/src/java/org/apache/cassandra/db/filter/ColumnCounter.java @@ -20,6 +20,8 @@ */ package org.apache.cassandra.db.filter; +import java.util.Iterator; + import org.apache.cassandra.db.Cell; import org.apache.cassandra.db.composites.CellName; import org.apache.cassandra.db.composites.CellNameType; @@ -72,11 +74,18 @@ public class ColumnCounter return this; DeletionInfo.InOrderTester tester = container.inOrderDeletionTester(); - for (Cell c : container) - count(c, tester); + Iterator<Cell> cells = getCellIterator(container); + while (cells.hasNext()) + count(cells.next(), tester); return this; } + protected Iterator<Cell> getCellIterator(ColumnFamily container) + { + // overridden by GroupByPrefixReversed to return a reverse iterator + return container.iterator(); + } + public static class GroupByPrefix extends ColumnCounter { protected final CellNameType type; @@ -169,6 +178,12 @@ public class ColumnCounter } @Override + public Iterator<Cell> getCellIterator(ColumnFamily container) + { + return container.reverseIterator(); + } + + @Override public boolean count(Cell cell, DeletionInfo.InOrderTester tester) { if (tester.isDeleted(cell)) http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f450107/test/unit/org/apache/cassandra/service/QueryPagerTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/service/QueryPagerTest.java b/test/unit/org/apache/cassandra/service/QueryPagerTest.java index 961f080..33a7585 100644 --- a/test/unit/org/apache/cassandra/service/QueryPagerTest.java +++ b/test/unit/org/apache/cassandra/service/QueryPagerTest.java @@ -53,6 +53,7 @@ public class QueryPagerTest public static final String CF_STANDARD = "Standard1"; public static final String KEYSPACE_CQL = "cql_keyspace"; public static final String CF_CQL = "table2"; + public static final String CF_CQL_WITH_STATIC = "with_static"; @BeforeClass public static void defineSchema() throws ConfigurationException @@ -69,7 +70,14 @@ public class QueryPagerTest + "k text," + "c text," + "v text," - + "PRIMARY KEY (k, c))", KEYSPACE_CQL)); + + "PRIMARY KEY (k, c))", KEYSPACE_CQL), + CFMetaData.compile("CREATE TABLE " + CF_CQL_WITH_STATIC + " (" + + "pk text, " + + "ck int, " + + "st int static, " + + "v1 int, " + + "v2 int, " + + "PRIMARY KEY(pk, ck))", KEYSPACE_CQL)); addData(); } @@ -378,4 +386,46 @@ public class QueryPagerTest assertRow(page.get(0), "k0", ct.decompose("c" + i, "")); } } + + @Test + public void pagingReversedQueriesWithStaticColumnsTest() throws Exception + { + // insert some rows into a single partition + for (int i=0; i < 5; i++) + executeInternal(String.format("INSERT INTO %s.%s (pk, ck, st, v1, v2) VALUES ('k0', %3$s, %3$s, %3$s, %3$s)", + KEYSPACE_CQL, CF_CQL_WITH_STATIC, i)); + + // query the table in reverse with page size = 1 & check that the returned rows contain the correct cells + CFMetaData cfm = Keyspace.open(KEYSPACE_CQL).getColumnFamilyStore(CF_CQL_WITH_STATIC).metadata; + queryAndVerifyCells(cfm, true, "k0"); + } + + private void queryAndVerifyCells(CFMetaData cfm, boolean reversed, String key) throws Exception + { + SliceQueryFilter filter = new SliceQueryFilter(ColumnSlice.ALL_COLUMNS_ARRAY, reversed, 100, 1); + QueryPager pager = QueryPagers.localPager(new SliceFromReadCommand(cfm.ksName, bytes(key), cfm.cfName, 0, filter)); + CellName staticCellName = cfm.comparator.create(cfm.comparator.staticPrefix(), + cfm.staticColumns().iterator().next()); + for (int i=0; i<5; i++) + { + List<Row> page = pager.fetchPage(1); + assertEquals(1, page.size()); + Row row = page.get(0); + assertCell(row.cf, staticCellName, 4); + int cellIndex = !reversed ? i : 4 - i; + assertCell(row.cf, Util.cellname(ByteBufferUtil.bytes(cellIndex), ByteBufferUtil.bytes("v1")), cellIndex); + assertCell(row.cf, Util.cellname(ByteBufferUtil.bytes(cellIndex), ByteBufferUtil.bytes("v2")), cellIndex); + } + + // After processing the 5 rows there should be no more rows to return + List<Row> page = pager.fetchPage(1); + assertTrue(page.isEmpty()); + } + + private void assertCell(ColumnFamily cf, CellName cellName, int value) + { + Cell cell = cf.getColumn(cellName); + assertNotNull(cell); + assertEquals(value, ByteBufferUtil.toInt(cell.value())); + } }