This is an automated email from the ASF dual-hosted git repository. maedhroz pushed a commit to branch cassandra-5.0 in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/cassandra-5.0 by this push: new 4e2e5f3c57 Fixed multiple single-node SAI query bugs relating to static columns - Ensure MemtableIndexWriter calculates min/max properly with indexes on partition key elements - Ensure only rows with live data are indexed - Ensure min cannot be greater than max in intersection statistics with static keys - Correct tracking of last key in the searcher in the presence of static keys 4e2e5f3c57 is described below commit 4e2e5f3c57cbd375e1ec112e25578a184618c4b5 Author: Caleb Rackliffe <calebrackli...@gmail.com> AuthorDate: Thu Feb 20 12:25:07 2025 -0600 Fixed multiple single-node SAI query bugs relating to static columns - Ensure MemtableIndexWriter calculates min/max properly with indexes on partition key elements - Ensure only rows with live data are indexed - Ensure min cannot be greater than max in intersection statistics with static keys - Correct tracking of last key in the searcher in the presence of static keys patch by Caleb Rackliffe; reviewed by David Capwell for CASSANDRA-20338 --- CHANGES.txt | 1 + .../index/sai/StorageAttachedIndexGroup.java | 8 +- .../index/sai/disk/StorageAttachedIndexWriter.java | 10 ++- .../index/sai/disk/v1/MemtableIndexWriter.java | 6 +- .../iterators/KeyRangeIntersectionIterator.java | 4 + .../sai/plan/StorageAttachedIndexSearcher.java | 4 +- .../cassandra/index/sai/utils/PrimaryKey.java | 18 ++++- .../sai/cql/CompositePartitionKeyIndexTest.java | 88 +++++++++++++++++++++- .../index/sai/cql/StaticColumnIndexTest.java | 44 +++++++++++ 9 files changed, 170 insertions(+), 13 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 4f8ae90366..f4b1be2002 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 5.0.4 + * Fixed multiple single-node SAI query bugs relating to static columns (CASSANDRA-20338) * Upgrade com.datastax.cassandra:cassandra-driver-core:3.11.5 to org.apache.cassandra:cassandra-driver-core:3.12.1 (CASSANDRA-17231) * Update netty to 4.1.119.Final and netty-tcnative to 2.0.70.Final (CASSANDRA-20314) * Serialization can lose complex deletions in a mutation with multiple collections in a row (CASSANDRA-20449) diff --git a/src/java/org/apache/cassandra/index/sai/StorageAttachedIndexGroup.java b/src/java/org/apache/cassandra/index/sai/StorageAttachedIndexGroup.java index bddeacecc7..02e7971814 100644 --- a/src/java/org/apache/cassandra/index/sai/StorageAttachedIndexGroup.java +++ b/src/java/org/apache/cassandra/index/sai/StorageAttachedIndexGroup.java @@ -177,7 +177,7 @@ public class StorageAttachedIndexGroup implements Index.Group, INotificationCons public void insertRow(Row row) { // SAI does not index deletions, as these are resolved during post-filtering. - if (row.deletion().isLive()) + if (row.hasLiveData(nowInSec, false)) for (Index.Indexer indexer : indexers) indexer.insertRow(row); } @@ -185,8 +185,10 @@ public class StorageAttachedIndexGroup implements Index.Group, INotificationCons @Override public void updateRow(Row oldRow, Row newRow) { - for (Index.Indexer indexer : indexers) - indexer.updateRow(oldRow, newRow); + // SAI does not index deletions, as these are resolved during post-filtering. + if (newRow.hasLiveData(nowInSec, false)) + for (Index.Indexer indexer : indexers) + indexer.updateRow(oldRow, newRow); } }; } diff --git a/src/java/org/apache/cassandra/index/sai/disk/StorageAttachedIndexWriter.java b/src/java/org/apache/cassandra/index/sai/disk/StorageAttachedIndexWriter.java index f35ae67f93..341bcaac5e 100644 --- a/src/java/org/apache/cassandra/index/sai/disk/StorageAttachedIndexWriter.java +++ b/src/java/org/apache/cassandra/index/sai/disk/StorageAttachedIndexWriter.java @@ -37,6 +37,7 @@ import org.apache.cassandra.index.sai.StorageAttachedIndex; import org.apache.cassandra.index.sai.disk.format.IndexDescriptor; import org.apache.cassandra.index.sai.utils.PrimaryKey; import org.apache.cassandra.io.sstable.SSTableFlushObserver; +import org.apache.cassandra.utils.FBUtilities; import org.apache.cassandra.utils.Throwables; /** @@ -52,6 +53,8 @@ public class StorageAttachedIndexWriter implements SSTableFlushObserver private final PerSSTableIndexWriter perSSTableWriter; private final Stopwatch stopwatch = Stopwatch.createUnstarted(); private final RowMapping rowMapping; + private final long nowInSeconds = FBUtilities.nowInSeconds(); + private DecoratedKey currentKey; private boolean tokenOffsetWriterCompleted = false; private boolean aborted = false; @@ -126,9 +129,14 @@ public class StorageAttachedIndexWriter implements SSTableFlushObserver if (!unfiltered.isRow()) return; + // Ignore rows with no live data... + Row row = (Row) unfiltered; + if (!row.hasLiveData(nowInSeconds, false)) + return; + try { - addRow((Row)unfiltered); + addRow(row); } catch (Throwable t) { diff --git a/src/java/org/apache/cassandra/index/sai/disk/v1/MemtableIndexWriter.java b/src/java/org/apache/cassandra/index/sai/disk/v1/MemtableIndexWriter.java index 0650e9b9d6..04d3185bfc 100644 --- a/src/java/org/apache/cassandra/index/sai/disk/v1/MemtableIndexWriter.java +++ b/src/java/org/apache/cassandra/index/sai/disk/v1/MemtableIndexWriter.java @@ -91,14 +91,16 @@ public class MemtableIndexWriter implements PerColumnIndexWriter // keys and row IDs in the flushing SSTable. This writer, therefore, does nothing in // response to the flushing of individual rows except for keeping index-specific statistics. boolean isStatic = indexTermType.columnMetadata().isStatic(); + boolean isPartitionKey = indexTermType.columnMetadata().isPartitionKey(); // Indexes on static columns should only track static rows, and indexes on non-static columns // should only track non-static rows. (Within a partition, the row ID for a static row will always - // come before any non-static row.) - if (key.kind() == PrimaryKey.Kind.STATIC && isStatic || key.kind() != PrimaryKey.Kind.STATIC && !isStatic) + // come before any non-static row.) The only exception to this is indexes on partition key elements. + if ((key.kind() == PrimaryKey.Kind.STATIC && (isStatic || isPartitionKey)) || key.kind() != PrimaryKey.Kind.STATIC && !isStatic) { if (minKey == null) minKey = key; + maxKey = key; rowCount++; maxSSTableRowId = Math.max(maxSSTableRowId, sstableRowId); diff --git a/src/java/org/apache/cassandra/index/sai/iterators/KeyRangeIntersectionIterator.java b/src/java/org/apache/cassandra/index/sai/iterators/KeyRangeIntersectionIterator.java index 6237aa0131..4909033bf8 100644 --- a/src/java/org/apache/cassandra/index/sai/iterators/KeyRangeIntersectionIterator.java +++ b/src/java/org/apache/cassandra/index/sai/iterators/KeyRangeIntersectionIterator.java @@ -375,6 +375,10 @@ public class KeyRangeIntersectionIterator extends KeyRangeIterator min = nullSafeMax(min, range.getMinimum()); // maximum of the intersection is the smallest maximum of individual iterators max = nullSafeMin(max, range.getMaximum()); + + // With STATIC keys, it is possible for the min to overtake the max, which must be corrected. + min = nullSafeMin(min, max); + if (empty) { empty = false; diff --git a/src/java/org/apache/cassandra/index/sai/plan/StorageAttachedIndexSearcher.java b/src/java/org/apache/cassandra/index/sai/plan/StorageAttachedIndexSearcher.java index 858242006a..9116db0d31 100644 --- a/src/java/org/apache/cassandra/index/sai/plan/StorageAttachedIndexSearcher.java +++ b/src/java/org/apache/cassandra/index/sai/plan/StorageAttachedIndexSearcher.java @@ -229,7 +229,7 @@ public class StorageAttachedIndexSearcher implements Index.Searcher if (firstKey == null) return Collections.emptyList(); } - while (queryController.doesNotSelect(firstKey) || firstKey.equals(lastKey)); + while (queryController.doesNotSelect(firstKey) || firstKey.equals(lastKey, false)); lastKey = firstKey; threadLocalNextKeys.add(firstKey); @@ -291,7 +291,7 @@ public class StorageAttachedIndexSearcher implements Index.Searcher if (key == null) break; - if (queryController.doesNotSelect(key) || key.equals(lastKey)) + if (queryController.doesNotSelect(key) || key.equals(lastKey, false)) continue; nextPrimaryKeys.add(key); diff --git a/src/java/org/apache/cassandra/index/sai/utils/PrimaryKey.java b/src/java/org/apache/cassandra/index/sai/utils/PrimaryKey.java index 3cc5033044..6de7a6c884 100644 --- a/src/java/org/apache/cassandra/index/sai/utils/PrimaryKey.java +++ b/src/java/org/apache/cassandra/index/sai/utils/PrimaryKey.java @@ -218,10 +218,20 @@ public interface PrimaryKey extends Comparable<PrimaryKey>, ByteComparable } @Override - public boolean equals(Object obj) + public boolean equals(Object o) { - if (obj instanceof PrimaryKey) - return compareTo((PrimaryKey) obj) == 0; + if (o instanceof PrimaryKey) + return compareTo((PrimaryKey) o) == 0; + return false; + } + + @Override + public boolean equals(Object o, boolean strict) + { + if (o == null) + return false; + if (o instanceof PrimaryKey) + return compareTo((PrimaryKey) o, strict) == 0; return false; } @@ -494,4 +504,6 @@ public interface PrimaryKey extends Comparable<PrimaryKey>, ByteComparable { return compareTo(key); } + + boolean equals(Object obj, boolean strict); } diff --git a/test/unit/org/apache/cassandra/index/sai/cql/CompositePartitionKeyIndexTest.java b/test/unit/org/apache/cassandra/index/sai/cql/CompositePartitionKeyIndexTest.java index 5d3c9e11d7..d7aa4e48ab 100644 --- a/test/unit/org/apache/cassandra/index/sai/cql/CompositePartitionKeyIndexTest.java +++ b/test/unit/org/apache/cassandra/index/sai/cql/CompositePartitionKeyIndexTest.java @@ -22,19 +22,99 @@ import java.math.BigInteger; import org.junit.Test; import org.apache.cassandra.cql3.restrictions.StatementRestrictions; +import org.apache.cassandra.db.marshal.ByteType; import org.apache.cassandra.db.marshal.FloatType; +import org.apache.cassandra.db.marshal.IntegerType; import org.apache.cassandra.db.marshal.SimpleDateType; import org.apache.cassandra.db.marshal.TimeType; import org.apache.cassandra.db.marshal.UUIDType; import org.apache.cassandra.index.sai.SAITester; +import org.apache.cassandra.utils.ByteBufferUtil; public class CompositePartitionKeyIndexTest extends SAITester { + @Test + public void testStaticAndNonStaticKeysOnFlush() throws Throwable + { + createTable("CREATE TABLE %s (pk0 tinyint, pk1 bigint, ck0 blob, s1 text static, s0 set<uuid> static, v0 smallint, PRIMARY KEY ((pk0, pk1), ck0)) WITH CLUSTERING ORDER BY (ck0 DESC)"); + disableCompaction(KEYSPACE); + createIndex("CREATE INDEX tbl_pk0 ON %s(pk0) USING 'sai'"); + createIndex("CREATE INDEX tbl_pk1 ON %s(pk1) USING 'sai'"); + createIndex("CREATE INDEX tbl_s1 ON %s(s1) USING 'sai'"); + createIndex("CREATE INDEX tbl_v0 ON %s(v0) USING 'sai'"); + + execute("INSERT INTO %s (pk0, pk1, ck0, s1, s0, v0) VALUES (-62, -5815950741950477880, 0x326f, '켅\uF6EB憓ᤃ\uEF32ꝃ窰ŷ', {00000000-0000-4700-aa00-000000000000}, 19310) USING TIMESTAMP 1"); + execute("DELETE FROM %s USING TIMESTAMP 2 WHERE pk0 = 45 AND pk1 = 6014418364385708772 AND ck0 = 0x7c10"); + execute("DELETE FROM %s USING TIMESTAMP 3 WHERE pk0 = -41 AND pk1 = -3934225888295599640"); + execute("INSERT INTO %s (pk0, pk1, ck0, s1, s0, v0) " + + "VALUES (-64, 7973592261481566341, 0x0d, '\uE11B摻', {00000000-0000-4800-8900-000000000000, 00000000-0000-4900-8600-000000000000}, -23873) USING TIMESTAMP 4"); + flush(KEYSPACE); + + execute("UPDATE %s USING TIMESTAMP 5 SET v0=-359, s1='ل≻Ⱆ喡䮠?' WHERE pk0 = -64 AND pk1 = 7973592261481566341 AND ck0 = 0x99d570024de738f37877"); + execute("INSERT INTO %s (pk0, pk1, ck0, v0, s1, s0) " + + "VALUES (-104, -4990846884898776392, 0xf7ac771298eaf1d4, -6977, '凘纖볭菮⏏↶?蜑', null) USING TIMESTAMP 6"); + execute("INSERT INTO %s (pk0, pk1, ck0, s1, s0, v0) " + + "VALUES (-62, -5815950741950477880, 0x9277e744212e1c4b50, '\uF6AD瀛⛕徳倬糽ᢷ' + '雴', {00000000-0000-4700-b100-000000000000, 00000000-0000-4800-9300-000000000000}, 5423) USING TIMESTAMP 7"); + execute("DELETE FROM %s USING TIMESTAMP 8 WHERE pk0 = -64 AND pk1 = 7973592261481566341"); + flush(KEYSPACE); + + execute("DELETE s0, s1, s0 FROM %s USING TIMESTAMP 9 WHERE pk0 = -62 AND pk1 = -5815950741950477880"); + execute("DELETE FROM %s USING TIMESTAMP 10 WHERE pk0 = -41 AND pk1 = -3934225888295599640 AND ck0 = 0xd753dc3a473acaf665"); + execute("INSERT INTO %s (pk0, pk1, ck0, s1, s0, v0) " + + "VALUES (-62, -5815950741950477880, 0xd1e07b568a7188, 'ᑿ鼾戆' + '篐뵡?䰫', {00000000-0000-4500-b000-000000000000}, 17933) USING TIMESTAMP 11"); + execute("UPDATE %s USING TIMESTAMP 12 SET v0=null, s0={00000000-0000-4600-a000-000000000000, 00000000-0000-4d00-8200-000000000000, 00000000-0000-4f00-9200-000000000000} " + + "WHERE pk0 = -41 AND pk1 = -3934225888295599640 AND ck0 = 0x0dab3b038131efa2"); + + assertRowCount(execute("SELECT * FROM %s WHERE pk0 >= ? LIMIT 81", (byte) -104), 5); + execute("DELETE FROM %s USING TIMESTAMP 13 WHERE pk0 = -64 AND pk1 = 7973592261481566341"); + flush(KEYSPACE); + + beforeAndAfterFlush(() -> + assertRows(execute("SELECT pk0, pk1, ck0 FROM %s WHERE pk0 >= ?", (byte) -104), + row((byte) -62, -5815950741950477880L, ByteBufferUtil.hexToBytes("d1e07b568a7188")), + row((byte) -62, -5815950741950477880L, ByteBufferUtil.hexToBytes("9277e744212e1c4b50")), + row((byte) -62, -5815950741950477880L, ByteBufferUtil.hexToBytes("326f")), + row((byte) -104, -4990846884898776392L, ByteBufferUtil.hexToBytes("f7ac771298eaf1d4")), + row((byte) -41, -3934225888295599640L, null))); + } + + @Test + public void testIgnoreCellDeletions() throws Throwable + { + createTable("CREATE TABLE %s (pk0 boolean, pk1 varint, ck0 tinyint, ck1 varint, s0 list<frozen<map<double, smallint>>> static, " + + " s1 map<frozen<set<uuid>>, frozen<map<inet, date>>> static, v0 frozen<map<frozen<set<text>>, uuid>>, " + + " PRIMARY KEY ((pk0, pk1), ck0, ck1)) WITH CLUSTERING ORDER BY (ck0 DESC, ck1 DESC)"); + disableCompaction(KEYSPACE); + createIndex("CREATE INDEX tbl_pk0 ON %s(pk0) USING 'sai'"); + + execute("INSERT INTO %s (pk0, pk1, ck0, ck1, s0, s1, v0) " + + "VALUES (true, 0, 109, 0, [{2.2352903520430565E260: -29214, 2.605618737869944E274: -13041}], " + + " {{00000000-0000-4400-9f00-000000000000, 00000000-0000-4500-9b00-000000000000, 00000000-0000-4b00-bf00-000000000000}: {'18.112.79.221': '-2306623-03-19', '227.58.183.116': '-3929454-04-25'}}, " + + " {{'⭎憢?', '黣偛紑'}: 00000000-0000-4900-8600-000000000000, {'㛽ꓗ', '剢ꮱ死䰀륬ਐ喑ퟚ', '竖䝏爐뷤曀'}: 00000000-0000-4900-bc00-000000000000}) USING TIMESTAMP 1"); + execute("INSERT INTO %s (pk0, pk1, ck0, ck1, s1, v0) " + + "VALUES (true, 0, 114, 742, {{00000000-0000-4000-9a00-000000000000, 00000000-0000-4700-ba00-000000000000}: {'96.31.70.25': '-912836-06-15', '185.90.18.173': '-5257542-01-31', '223.18.191.245': '-4633145-10-30'}}, " + + " {{'뫥㩎뎠ྭẒ'}: 00000000-0000-4800-8600-000000000000}) USING TIMESTAMP 2"); + + // This will result in the creation of erroneous postings if cell deletions are not accounted for: + execute("DELETE v0, s1, s0 FROM %s USING TIMESTAMP 6 WHERE pk0 = true AND pk1 = 0 AND ck0 = 121 AND ck1 = 1"); + + execute("UPDATE %s USING TIMESTAMP 8 SET s0 += [{4.3056056376102396E-169: 22551, 1.439623561042819E208: 20450}, {-2.7900719406964408E-242: 30147, 8.586565205109037E-211: 28721, 4.603864140847754E20: -12814}], " + + " s1 += {{00000000-0000-4200-b900-000000000000, 00000000-0000-4500-ab00-000000000000}: {'2.67.240.121': '-471656-04-17', '134.186.187.51': '-2056459-04-13'}}, " + + " v0={{'?', '蠥╩徰昰弳펠재', '됢簔Ὕ텇⢌យ稭澣'}: 00000000-0000-4d00-8d00-000000000000} " + + "WHERE pk0 = true AND pk1 = 0 AND ck0 = 37 AND ck1 = 0"); + + beforeAndAfterFlush(() -> + assertRows(execute("SELECT pk0, pk1, ck0, ck1 FROM %s WHERE pk0 = ? LIMIT 4", true), + row(true, IntegerType.instance.fromString("0"), ByteType.instance.fromString("114"), IntegerType.instance.fromString("742")), + row(true, IntegerType.instance.fromString("0"), ByteType.instance.fromString("109"), IntegerType.instance.fromString("0")), + row(true, IntegerType.instance.fromString("0"), ByteType.instance.fromString("37"), IntegerType.instance.fromString("0")))); + } + @Test public void testIntersectionOnMixedPostingsOnDelete() throws Throwable { createTable("CREATE TABLE %s (pk0 boolean, pk1 uuid, ck0 date, ck1 smallint, s0 timeuuid static, v0 bigint, v1 float, PRIMARY KEY ((pk0, pk1), ck0, ck1)) WITH CLUSTERING ORDER BY (ck0 DESC, ck1 ASC)"); - + disableCompaction(KEYSPACE); createIndex("CREATE INDEX tbl_pk0 ON %s(pk0) USING 'sai'"); createIndex("CREATE INDEX tbl_ck0 ON %s(ck0) USING 'sai'"); @@ -54,7 +134,7 @@ public class CompositePartitionKeyIndexTest extends SAITester public void testIntersectionOnMixedPostingsOnUpdate() throws Throwable { createTable("CREATE TABLE %s (pk0 boolean, pk1 uuid, ck0 date, ck1 smallint, s0 timeuuid static, v0 bigint, v1 float, PRIMARY KEY ((pk0, pk1), ck0, ck1)) WITH CLUSTERING ORDER BY (ck0 DESC, ck1 ASC)"); - + disableCompaction(KEYSPACE); createIndex("CREATE INDEX tbl_pk0 ON %s(pk0) USING 'sai'"); createIndex("CREATE INDEX tbl_ck0 ON %s(ck0) USING 'sai'"); @@ -74,6 +154,7 @@ public class CompositePartitionKeyIndexTest extends SAITester public void testIntersectionWithStaticOverlap() throws Throwable { createTable("CREATE TABLE %s (pk0 int, pk1 int, ck0 int, s1 int static, v0 int, PRIMARY KEY((pk0, pk1), ck0))"); + disableCompaction(KEYSPACE); createIndex("CREATE INDEX ON %s(pk0) USING 'sai'"); execute("UPDATE %s USING TIMESTAMP 1 SET s1 = 0, v0 = 0 WHERE pk0 = 0 AND pk1 = 1 AND ck0 = 0"); @@ -91,6 +172,7 @@ public class CompositePartitionKeyIndexTest extends SAITester public void testIntersectionWithStaticUpdate() throws Throwable { createTable("CREATE TABLE %s (pk0 time, pk1 varint, ck0 date, s0 boolean static, s1 text static, v0 boolean, PRIMARY KEY ((pk0, pk1), ck0))"); + disableCompaction(KEYSPACE); createIndex("CREATE INDEX tbl_pk0 ON %s(pk0) USING 'sai'"); createIndex("CREATE INDEX tbl_s0 ON %s(s0) USING 'sai'"); @@ -116,6 +198,7 @@ public class CompositePartitionKeyIndexTest extends SAITester public void testCompositePartitionIndex() throws Throwable { createTable("CREATE TABLE %s (pk1 int, pk2 text, val int, PRIMARY KEY((pk1, pk2)))"); + disableCompaction(KEYSPACE); createIndex("CREATE INDEX ON %s(pk1) USING 'sai'"); createIndex("CREATE INDEX ON %s(pk2) USING 'sai'"); @@ -168,6 +251,7 @@ public class CompositePartitionKeyIndexTest extends SAITester public void testFilterWithIndexForContains() throws Throwable { createTable("CREATE TABLE %s (k1 int, k2 int, v set<int>, PRIMARY KEY ((k1, k2)))"); + disableCompaction(KEYSPACE); createIndex("CREATE INDEX ON %s(k2) USING 'sai'"); execute("INSERT INTO %s (k1, k2, v) VALUES (?, ?, ?)", 0, 0, set(1, 2, 3)); diff --git a/test/unit/org/apache/cassandra/index/sai/cql/StaticColumnIndexTest.java b/test/unit/org/apache/cassandra/index/sai/cql/StaticColumnIndexTest.java index faaf74f5c6..d9dec8e3a7 100644 --- a/test/unit/org/apache/cassandra/index/sai/cql/StaticColumnIndexTest.java +++ b/test/unit/org/apache/cassandra/index/sai/cql/StaticColumnIndexTest.java @@ -20,6 +20,9 @@ package org.apache.cassandra.index.sai.cql; import org.junit.Test; +import org.apache.cassandra.db.marshal.BytesType; +import org.apache.cassandra.db.marshal.TimeType; +import org.apache.cassandra.db.marshal.UUIDType; import org.apache.cassandra.index.sai.SAITester; public class StaticColumnIndexTest extends SAITester @@ -28,6 +31,7 @@ public class StaticColumnIndexTest extends SAITester public void staticIndexReturnsAllRowsInPartition() throws Throwable { createTable("CREATE TABLE %s (pk int, ck int, val1 int static, val2 int, PRIMARY KEY(pk, ck))"); + disableCompaction(KEYSPACE); createIndex("CREATE INDEX ON %s(val1) USING 'sai'"); execute("INSERT INTO %s(pk, ck, val1, val2) VALUES(?, ?, ?, ?)", 1, 1, 2, 1); @@ -42,6 +46,7 @@ public class StaticColumnIndexTest extends SAITester public void staticIndexAndNonStaticIndex() throws Throwable { createTable("CREATE TABLE %s (pk int, ck int, val1 int static, val2 int, PRIMARY KEY(pk, ck))"); + disableCompaction(KEYSPACE); createIndex("CREATE INDEX ON %s(val1) USING 'sai'"); createIndex("CREATE INDEX ON %s(val2) USING 'sai'"); @@ -57,6 +62,7 @@ public class StaticColumnIndexTest extends SAITester public void staticAndNonStaticRangeIntersection() throws Throwable { createTable("CREATE TABLE %s (pk int, ck int, v1 int, s1 int static, PRIMARY KEY(pk, ck))"); + disableCompaction(KEYSPACE); createIndex("CREATE INDEX ON %s(v1) USING 'sai'"); createIndex("CREATE INDEX ON %s(s1) USING 'sai'"); @@ -71,4 +77,42 @@ public class StaticColumnIndexTest extends SAITester beforeAndAfterFlush(() -> assertRowCount(execute("SELECT * FROM %s WHERE pk = ? AND v1 > ? AND s1 = ?", 0, 2, 100), 3)); } + + @Test + public void testTupleAndBlobFiltering() throws Throwable + { + String blobTupleType = createType("CREATE TYPE IF NOT EXISTS %s (f0 blob)"); + String boolTinyTextType = createType("CREATE TYPE IF NOT EXISTS %s (f0 boolean, f1 tinyint, f2 text)"); + createTable("CREATE TABLE %s (pk0 time, pk1 uuid, ck0 uuid, ck1 blob, s0 frozen<tuple<smallint, frozen<set<float>>>> static, " + + " v0 vector<vector<int, 2>, 3>, v1 frozen<map<frozen<" + blobTupleType + ">, vector<bigint, 2>>>, " + + " v2 vector<frozen<" + boolTinyTextType + ">, 2>, v3 bigint, PRIMARY KEY ((pk0, pk1), ck0, ck1)) WITH CLUSTERING ORDER BY (ck0 DESC, ck1 DESC)"); + disableCompaction(KEYSPACE); + createIndex("CREATE INDEX tbl_pk1 ON %s(pk1) USING 'sai'"); + createIndex("CREATE INDEX tbl_s0 ON %s(s0) USING 'sai'"); + + execute("INSERT INTO %s (pk0, pk1, ck0, ck1, s0, v0, v1, v2, v3) " + + "VALUES ('02:43:47.716011275', 00000000-0000-4200-b200-000000000000, 00000000-0000-4e00-8400-000000000000, 0xf2791941aea8e469, " + + " (12129, {-2.58545975E14}), [[-1781797567, 330686172], [103364202, 2031130152], [-550709009, 492544493]], " + + " {{f0: 0x34839b8bae653b2bdee8}: [-8431172225521461427, 8894719445990427242]}, [{f0: false, f1: 53, f2: '嵆왛孷쏆䊖恣'}, {f0: true, f1: 21, f2: 'ᨚ?榥쯢?ɚ챛ퟡ'}], 9167463065336786821) USING TIMESTAMP 3"); + execute("UPDATE %s USING TIMESTAMP 4 " + + "SET s0=(23307, {-8.214548E-18}), v0=[[672139924, -1253475201], [353181149, -1829076723], [179355765, 379303855]], " + + " v1={{f0: 0x64850696464d}: [-7485547085069825418, 7795885370802556756], {f0: 0x67633db6f091}: [-8484578637223040646, 8216210044102487771]}, " + + " v2=[{f0: true, f1: 68, f2: '䝿ᝧ䶨푥펟겭매郂쀌'}, {f0: true, f1: 98, f2: '髃爫삿챥卛☓읂ີ?'}], v3=-4626482462417652499 * -7377486305688263453 " + + "WHERE pk0 = '03:36:30.876439626' AND pk1 = 00000000-0000-4000-ad00-000000000000 AND ck0 = 00000000-0000-4000-9f00-000000000000 AND ck1 = 0xa06bb301"); + execute("INSERT INTO %s (pk0, pk1, ck0, ck1, s0, v0, v1, v2, v3) " + + "VALUES ('07:08:47.775161332', 00000000-0000-4800-ad00-000000000000, 00000000-0000-4a00-a500-000000000000, 0xfef0d63ff7, (-15283, {-1.132058E24, 2.9319742E-31}), " + + " [[-335960956, 678086816], [-2139882146, 1011627708], [-55338955, -2094185756]], {{f0: 0xd9c3ab}: [-9002034104664383537, -8074261670215737032]}, " + + " [{f0: true, f1: -79, f2: '霠♘칳⦵ঋ幗䶐'}, {f0: true, f1: 7, f2: '䉻ݹ鞞텔㙠'}], 1885613374025825905) USING TIMESTAMP 5"); + execute("DELETE FROM %s USING TIMESTAMP 6 WHERE pk0 = '14:02:14.975449434' AND pk1 = 00000000-0000-4900-9900-000000000000"); + execute("DELETE FROM %s USING TIMESTAMP 7 WHERE pk0 = '12:15:35.151327231' AND pk1 = 00000000-0000-4500-ac00-000000000000"); + execute("DELETE FROM %s USING TIMESTAMP 8 WHERE pk0 = '07:08:47.775161332' AND pk1 = 00000000-0000-4800-ad00-000000000000 AND ck0 = 00000000-0000-4b00-b000-000000000000 AND ck1 = 0xa4121adb08"); + execute("INSERT INTO %s (pk0, pk1, ck0, ck1, s0, v0, v1, v2, v3) " + + "VALUES ('03:36:30.876439626', 00000000-0000-4000-ad00-000000000000, 00000000-0000-4600-b400-000000000000, 0x63f5, (28387, {-1.18764904E-20}), " + + " [[-441895935, 313114446], [-740629531, -678512740], [1429899934, -1259907921]], {{f0: 0x5df1}: [414225888834712632, -5730196176171247108], " + + " {f0: 0x92c1497d7072b81c91}: [-7587541014989351350, -2813091340484612608]}, [{f0: true, f1: 41, f2: '쎺╇⒀왶'}, {f0: true, f1: -84, f2: '턺䋏篷'}], -1473884563651667176 + 128345915915881356) USING TIMESTAMP 9"); + + beforeAndAfterFlush(() -> assertRows(execute("SELECT pk0, pk1, ck0, ck1 FROM %s WHERE s0 = (28387, {-1.18764904E-20}) AND pk1 = 00000000-0000-4000-ad00-000000000000 AND ck1 = 0xa06bb301 LIMIT 307 ALLOW FILTERING"), + row(TimeType.instance.fromString("03:36:30.876439626"), UUIDType.instance.fromString("00000000-0000-4000-ad00-000000000000"), + UUIDType.instance.fromString("00000000-0000-4000-9f00-000000000000"), BytesType.instance.fromString("a06bb301")))); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org