[ https://issues.apache.org/jira/browse/CASSANDRA-7525?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14063778#comment-14063778 ]
Sam Tunnicliffe commented on CASSANDRA-7525: -------------------------------------------- Pushed a branch here: https://github.com/beobal/cassandra/tree/7525 The first commit is Tyler's and fixes the reported problem with selecting from multiple candidate indexes. That uncovered a second issue whereby under certain conditions querying an collection value index would throw NPE The problem is in CompositesSearcher, when building the Composite prefixes to use for the slices to read from the index column family. If the values of the partition and clustering columns are restricted, the Composite built by {{CompositesIndexOnCollectionValues.makeIndexColumnPrefix}} incorrectly includes a null element as it mistakenly attempts to add the collection key to the Composite. This is necessary for indexing but not for searching, because we don't yet know the collection key, only the target value. So a query like {code} SELECT * FROM %s WHERE account = 'test' AND id = 5 AND categories CONTAINS 'foo' ALLOW FILTERING {code} where account is the partition key and id is a clustering column, results in an error such as: {code} [junit] Testcase: testQueryMultipleIndexTypes(org.apache.cassandra.cql3.ContainsRelationTest): Caused an ERROR [junit] null [junit] java.lang.NullPointerException [junit] at org.apache.cassandra.utils.FastByteOperations$UnsafeOperations.compare(FastByteOperations.java:225) [junit] at org.apache.cassandra.utils.FastByteOperations.compareUnsigned(FastByteOperations.java:62) [junit] at org.apache.cassandra.utils.ByteBufferUtil.compareUnsigned(ByteBufferUtil.java:83) [junit] at org.apache.cassandra.db.marshal.UTF8Type.compare(UTF8Type.java:35) [junit] at org.apache.cassandra.db.marshal.UTF8Type.compare(UTF8Type.java:27) [junit] at org.apache.cassandra.db.composites.AbstractCType.compare(AbstractCType.java:125) [junit] at org.apache.cassandra.db.composites.AbstractCType.compare(AbstractCType.java:40) [junit] at org.apache.cassandra.db.AtomicBTreeColumns$3.compare(AtomicBTreeColumns.java:234) [junit] at org.apache.cassandra.utils.btree.BTree.find(BTree.java:277) [junit] at org.apache.cassandra.utils.btree.Path.find(Path.java:122) [junit] at org.apache.cassandra.utils.btree.Cursor._reset(Cursor.java:107) [junit] at org.apache.cassandra.utils.btree.Cursor.reset(Cursor.java:91) [junit] at org.apache.cassandra.utils.btree.BTree.slice(BTree.java:238) [junit] at org.apache.cassandra.db.AtomicBTreeColumns.slice(AtomicBTreeColumns.java:453) [junit] at org.apache.cassandra.db.AtomicBTreeColumns.iterator(AtomicBTreeColumns.java:283) [junit] at org.apache.cassandra.db.filter.SliceQueryFilter.getColumnIterator(SliceQueryFilter.java:138) [junit] at org.apache.cassandra.db.filter.QueryFilter.getIterator(QueryFilter.java:57) [junit] at org.apache.cassandra.db.CollationController.collectAllData(CollationController.java:206) [junit] at org.apache.cassandra.db.CollationController.getTopLevelColumns(CollationController.java:59) [junit] at org.apache.cassandra.db.ColumnFamilyStore.getTopLevelColumns(ColumnFamilyStore.java:1873) [junit] at org.apache.cassandra.db.ColumnFamilyStore.getColumnFamily(ColumnFamilyStore.java:1681) [junit] at org.apache.cassandra.db.index.composites.CompositesSearcher$1.computeNext(CompositesSearcher.java:183) [junit] at org.apache.cassandra.db.index.composites.CompositesSearcher$1.computeNext(CompositesSearcher.java:121) [junit] at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:143) [junit] at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:138) [junit] at org.apache.cassandra.db.ColumnFamilyStore.filter(ColumnFamilyStore.java:2077) [junit] at org.apache.cassandra.db.index.composites.CompositesSearcher.search(CompositesSearcher.java:68) [junit] at org.apache.cassandra.db.index.SecondaryIndexManager.search(SecondaryIndexManager.java:591) [junit] at org.apache.cassandra.db.ColumnFamilyStore.search(ColumnFamilyStore.java:2065) [junit] at org.apache.cassandra.db.RangeSliceCommand.executeLocally(RangeSliceCommand.java:131) [junit] at org.apache.cassandra.cql3.statements.SelectStatement.executeInternal(SelectStatement.java:302) [junit] at org.apache.cassandra.cql3.statements.SelectStatement.executeInternal(SelectStatement.java:60) [junit] at org.apache.cassandra.cql3.QueryProcessor.executeOnceInternal(QueryProcessor.java:307) [junit] at org.apache.cassandra.cql3.CQLTester.execute(CQLTester.java:185) [junit] at org.apache.cassandra.cql3.ContainsRelationTest.testQueryMultipleIndexTypes(ContainsRelationTest.java:117) {code} Second commit in the branch fixes CIOCV so the slice filters are built correctly & adds tests which fail without that. > Querying by multiple secondary indexes gives > java.lang.IllegalArgumentException on some cases > --------------------------------------------------------------------------------------------- > > Key: CASSANDRA-7525 > URL: https://issues.apache.org/jira/browse/CASSANDRA-7525 > Project: Cassandra > Issue Type: Bug > Reporter: Tuukka Mustonen > Assignee: Sam Tunnicliffe > Fix For: 2.1.0 > > > Querying by: > * non-primary key column with secondary index + collection with secondary > index > * primary key column with secondary index + non-primary key column with > secondary index > gives {{<ErrorMessage code=0000 [Server error] > message="java.lang.IllegalArgumentException: expected one element but was: > <org.apache.cassandra.db.index.composites.CompositesSearcher@156b5576, > org.apache.cassandra.db.index.composites.CompositesSearcher@39b7c0f6>">}} > Steps to reproduce: > {code} > cqlsh:cs> CREATE TABLE test ( > ... id1 text, > ... id2 text, > ... column1 text, > ... column2 text, > ... collection set<text>, > ... PRIMARY KEY (id1, id2) > ... ); > cqlsh:cs> > {code} > Simple query by primary key works as should: > {code} > cqlsh:cs> SELECT * FROM test WHERE id1 = 'foo'; > (0 rows) > cqlsh:cs> SELECT * FROM test WHERE id1 = 'foo' AND id2 = 'bar'; > (0 rows) > {code} > Query by secondary index + non-indexed column: > {code} > cqlsh:cs> CREATE INDEX test_column1s ON test(column1); > cqlsh:cs> SELECT * FROM test WHERE column1 = 'foo'; > (0 rows) > cqlsh:cs> SELECT * FROM test WHERE column1 = 'foo' AND column2 = 'bar' ALLOW > FILTERING; > (0 rows) > {code} > Add secondary index also for the second column: > {code} > cqlsh:cs> CREATE INDEX test_column2s ON test(column2); > cqlsh:cs> SELECT * FROM test WHERE column1 = 'foo' AND column2 = 'bar' ALLOW > FILTERING; > (0 rows) > {code} > Doesn't matter if we bring primary key or the collection there as well: > {code} > cqlsh:cs> SELECT * FROM test WHERE id1 = 'blah' AND column1 = 'foo' AND > column2 = 'bar' ALLOW FILTERING; > (0 rows) > cqlsh:cs> SELECT * FROM test WHERE column1 = 'foo' AND collection CONTAINS > 'bar' ALLOW FILTERING; > (0 rows) > {code} > Let's add index for the collection: > {code} > cqlsh:cs> CREATE INDEX test_collections ON test(collection); > cqlsh:cs> SELECT * FROM test WHERE collection CONTAINS 'bar'; > (0 rows) > {code} > But then combine secondary index column and collection with secondary index: > {code} > cqlsh:cs> SELECT * FROM test WHERE column1 = 'foo' AND collection CONTAINS > 'bar' ALLOW FILTERING; > <ErrorMessage code=0000 [Server error] > message="java.lang.IllegalArgumentException: expected one element but was: > <org.apache.cassandra.db.index.composites.CompositesSearcher@68e37722, > org.apache.cassandra.db.index.composites.CompositesSearcher@2da28efa>"> > {code} > Furthermore, query by primary key field with secondary index + non-primary > key column with secondary index: > {code} > cqlsh:cs> CREATE INDEX test_id2s ON test(id2); > cqlsh:cs> SELECT * FROM test WHERE id2 = 'foo' AND column1 = 'bar' ALLOW > FILTERING; > <ErrorMessage code=0000 [Server error] > message="java.lang.IllegalArgumentException: expected one element but was: > <org.apache.cassandra.db.index.composites.CompositesSearcher@3ca899f1, > org.apache.cassandra.db.index.composites.CompositesSearcher@6112bc53>"> > {code} > I'm a cassandra noob so maybe I'm trying to do things the db is not meant to > do? -- This message was sent by Atlassian JIRA (v6.2#6252)