[ https://issues.apache.org/jira/browse/CASSANDRA-12149?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15369264#comment-15369264 ]
DOAN DuyHai commented on CASSANDRA-12149: ----------------------------------------- The query used = {{SELECT namespace, entity, timestamp, feature1, feature2 FROM mykeyspace.myrecordtable WHERE namespace = 'ns2' AND entity = 'entity2' AND feature1= 11 AND token(namespace, entity) <= 9223372036854775807;}} Ok, after successfully re-producing the NPE in debug mode, it is *not* a SASI bug but is rather related to how Cassandra optimises the *WHERE* clause in general. NPE root cause is {{slice.bound(b) == null}} in {{TokenRestriction.bounds(Bound b, QueryOptions options)}}: {code:java} public List<ByteBuffer> bounds(Bound b, QueryOptions options) throws InvalidRequestException { return Collections.singletonList(slice.bound(b).bindAndGet(options)); } {code} Going up the call stack, the culprit is at {{StatementRestrictions.getPartitionKeyBounds(IPartitioner p, QueryOptions options)}}: {code:java} private AbstractBounds<PartitionPosition> getPartitionKeyBounds(IPartitioner p, QueryOptions options) { ByteBuffer startKeyBytes = getPartitionKeyBound(Bound.START, options); ByteBuffer finishKeyBytes = getPartitionKeyBound(Bound.END, options); .... {code} Since we have no lower bound restriction on the {{token(namespace, entity)}}, the call to {{getPartitionKeyBound(Bound.START, options)}} generates the NPE. I try another query without using secondary index {{SELECT namespace, entity, timestamp, feature1, feature2 FROM mykeyspace.myrecordtable WHERE namespace = 'ns2' AND entity = 'entity2' AND token(namespace, entity) <= 9223372036854775807;}} and this time, no NPE. The place in the call stack where both queries diverge is at {{SelectStatements.getQuery(QueryOptions options, int nowInSec, int userLimit, int perPartitionLimit)}}: {code:java} public ReadQuery getQuery(QueryOptions options, int nowInSec, int userLimit, int perPartitionLimit) throws RequestValidationException { DataLimits limit = getDataLimits(userLimit, perPartitionLimit); if (restrictions.isKeyRange() || restrictions.usesSecondaryIndexing()) return getRangeCommand(options, limit, nowInSec); return getSliceCommands(options, limit, nowInSec); } {code} When using secondary index, we fall in the *if* condition obviously. When NOT using secondary index as per my 2nd SELECT statement, the *if* condition is not verified so the code path is {{return getSliceCommands(options, limit, nowInSec);}}. Strangely enough, even with the 2nd SELECT, {{restrictions.isKeyRange()}} should be *true*, why is it *false* ???? The culprit is at {{StatementRestrictions.processPartitionKeyRestrictions(boolean hasQueriableIndex)}} {code:java} ... if (partitionKeyRestrictions.isOnToken()) isKeyRange = true; if (hasUnrestrictedPartitionKeyComponents()) { if (!partitionKeyRestrictions.isEmpty()) { if (!hasQueriableIndex) throw invalidRequest("Partition key parts: %s must be restricted as other parts are", Joiner.on(", ").join(getPartitionKeyUnrestrictedComponents())); } isKeyRange = true; usesSecondaryIndexing = hasQueriableIndex; } } {code} Condition {{if (partitionKeyRestrictions.isOnToken())}} evaluates to *false* so variable _isKeyRange_ is never set to *true*. Condition {{if (partitionKeyRestrictions.isOnToken())}} evaluates to *false* because of {{TokenFilter.isOnToken()}}: {code:java} public boolean isOnToken() { // if all partition key columns have non-token restrictions, we can simply use the token range to filter // those restrictions and then ignore the token range return restrictions.size() < tokenRestriction.size(); } {code} Here, since there are *more* conditions on primary key than on token restriction, the SELECT is not considered to be a token restriction, which is sensible. By the way, if we look at the original WHERE clause {{WHERE namespace = 'ns2' AND entity = 'entity2' AND feature1= 11 AND token(namespace, entity) <= 9223372036854775807;}}, the restriction using *token* function is *useless* because we already provide the complete partition key restriction. And I tried the original query by removing {{token(namespace, entity) <= 9223372036854775807}} and it works like a charm. I would consider this JIRA to be *not an issue* cc [~xedin] [~beobal] and [~avkonst] > NullPointerException on SELECT with SASI index > ---------------------------------------------- > > Key: CASSANDRA-12149 > URL: https://issues.apache.org/jira/browse/CASSANDRA-12149 > Project: Cassandra > Issue Type: Bug > Components: sasi > Reporter: Andrey Konstantinov > Attachments: CASSANDRA-12149.txt > > > If I execute the sequence of queries (see the attached file), Cassandra > aborts a connection reporting NPE on server side. SELECT query without token > range filter works, but does not work when token range filter is specified. > My intent was to issue multiple SELECT queries targeting the same single > partition, filtered by a column indexed by SASI, partitioning results by > different token ranges. > Output from cqlsh on SELECT is the following: > cqlsh> SELECT namespace, entity, timestamp, feature1, feature2 FROM > mykeyspace.myrecordtable WHERE namespace = 'ns2' AND entity = 'entity2' AND > feature1 > 11 AND feature1 < 31 AND token(namespace, entity) <= > 9223372036854775807; > ServerError: <ErrorMessage code=0000 [Server error] > message="java.lang.NullPointerException"> -- This message was sent by Atlassian JIRA (v6.3.4#6332)