mirror of https://github.com/apache/cassandra
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
This commit is contained in:
parent
944baa08da
commit
4e2e5f3c57
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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"))));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue