[
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)