maedhroz commented on code in PR #4353:
URL: https://github.com/apache/cassandra/pull/4353#discussion_r2678347568


##########
src/java/org/apache/cassandra/index/sai/plan/StorageAttachedIndexSearcher.java:
##########
@@ -468,79 +501,321 @@ private UnfilteredRowIterator 
queryStorageAndFilter(List<PrimaryKey> keys)
             }
         }
 
-        private UnfilteredRowIterator filterPartition(List<PrimaryKey> keys, 
UnfilteredRowIterator partition, FilterTree tree)
+        @Override
+        public TableMetadata metadata()
         {
-            Row staticRow = partition.staticRow();
-            DecoratedKey partitionKey = partition.partitionKey();
-            List<Unfiltered> matches = new ArrayList<>();
-            boolean hasMatch = false;
-            Set<PrimaryKey> keysToShadow = topK ? new HashSet<>(keys) : 
Collections.emptySet();
+            return queryController.metadata();
+        }
 
-            while (partition.hasNext())
-            {
-                Unfiltered unfiltered = partition.next();
+        @Override
+        public void close()
+        {
+            FileUtils.closeQuietly(resultKeyIterator);
+            if (tableQueryMetrics != null) 
tableQueryMetrics.record(queryContext);
+        }
+    }
 
-                if (unfiltered.isRow())
-                {
-                    queryContext.rowsFiltered++;
+    private static UnfilteredRowIterator filterPartition(UnfilteredRowIterator 
partition, FilterTree tree, QueryContext context)
+    {
+        Row staticRow = partition.staticRow();
+        DecoratedKey partitionKey = partition.partitionKey();
+        List<Unfiltered> matches = new ArrayList<>();
+        boolean hasMatch = false;
 
-                    if (tree.isSatisfiedBy(partitionKey, (Row) unfiltered, 
staticRow))
-                    {
-                        matches.add(unfiltered);
-                        hasMatch = true;
+        // todo static keys??
+        while (partition.hasNext())
+        {
+            Unfiltered unfiltered = partition.next();
 
-                        if (topK)
-                        {
-                            PrimaryKey shadowed = 
keyFactory.hasClusteringColumns()
-                                                  ? 
keyFactory.create(partitionKey, ((Row) unfiltered).clustering())
-                                                  : 
keyFactory.create(partitionKey);
-                            keysToShadow.remove(shadowed);
-                        }
-                    }
+            if (unfiltered.isRow())
+            {
+                context.rowsFiltered++;
+
+                if (tree.isSatisfiedBy(partitionKey, (Row) unfiltered, 
staticRow))
+                {
+                    matches.add(unfiltered);
+                    hasMatch = true;
                 }
             }
+        }
 
-            // If any non-static rows match the filter, there should be no 
need to shadow the static primary key:
-            if (topK && hasMatch && keyFactory.hasClusteringColumns())
-                keysToShadow.remove(keyFactory.create(partitionKey, 
Clustering.STATIC_CLUSTERING));
+        // We may not have any non-static row data to filter...
+        if (!hasMatch)
+        {
+            context.rowsFiltered++;
 
-            // We may not have any non-static row data to filter...
-            if (!hasMatch)
+            if (tree.isSatisfiedBy(partitionKey, staticRow, staticRow))
             {
-                queryContext.rowsFiltered++;
+                hasMatch = true;
+            }
+        }
 
-                if (tree.isSatisfiedBy(partitionKey, staticRow, staticRow))
-                {
-                    hasMatch = true;
+        if (!hasMatch)
+        {
+            // If there are no matches, return an empty partition. If 
reconciliation is required at the
+            // coordinator, replica filtering protection may make a second 
round trip to complete its view
+            // of the partition.
+            return null;
+        }
 
-                    if (topK)
-                        keysToShadow.clear();
-                }
+        // Return all matches found, along with the static row...
+        return new SinglePartitionIterator(partition, staticRow, 
matches.iterator());
+    }
+
+    private static class SinglePartitionIterator extends 
AbstractUnfilteredRowIterator
+    {
+        private final Iterator<Unfiltered> rows;
+
+        public SinglePartitionIterator(UnfilteredRowIterator partition, Row 
staticRow, Iterator<Unfiltered> rows)
+        {
+            super(partition.metadata(),
+                  partition.partitionKey(),
+                  partition.partitionLevelDeletion(),
+                  partition.columns(),
+                  staticRow,
+                  partition.isReverseOrder(),
+                  partition.stats());
+
+            this.rows = rows;
+        }
+
+        @Override
+        protected Unfiltered computeNext()
+        {
+            return rows.hasNext() ? rows.next() : endOfData();
+        }
+    }
+
+    /**
+     * A result retriever that consumes an iterator primary keys sorted by 
some score, materializes the row for each
+     * primary key (currently, each primary key is required to be fully 
qualified and should only point to one row),
+     * apply the filter tree to the row to test that the real row satisfies 
the WHERE clause, and finally tests
+     * that the row is valid for the ORDER BY clause. The class performs some 
optimizations to avoid materializing
+     * rows unnecessarily. See the class for more details.
+     * <p>
+     * The resulting {@link UnfilteredRowIterator} objects are not guaranteed 
to be in any particular order. It is
+     * the responsibility of the caller to sort the results if necessary.
+     */
+    public static class ScoreOrderedResultRetriever extends 
AbstractIterator<UnfilteredRowIterator> implements UnfilteredPartitionIterator
+    {
+        private final ColumnFamilyStore.ViewFragment view;
+        private final List<AbstractBounds<PartitionPosition>> keyRanges;
+        private final boolean coversFullRing;
+        private final CloseableIterator<PrimaryKeyWithScore> 
scoredPrimaryKeyIterator;
+        private final FilterTree filterTree;
+        private final QueryController controller;
+        private final ReadExecutionController executionController;
+        private final QueryContext queryContext;

Review Comment:
   There are a few shared fields between the retrievers: `filterTree`, 
`queryContext`, `controller`, etc. I don't know if there's enough to factor 
something common out, given the only strict duplication looks like maybe the 
`metadata()` method.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to