@@ -503,7 +503,10 @@ private UnfilteredRowIterator queryStorageAndFilter(List<PrimaryKey> keys)
503503 queryContext .partitionsRead ++;
504504 queryContext .checkpoint ();
505505
506- List <Row > filtered = filterPartition (partition , filterTree , queryContext );
506+ // If there is an unresolved static expression during RFP, completion reads to silent replicas will
507+ // fetch entire partitions. If we don't return range tombstones in this initial read, there may not be
508+ // enough information at the coordinator for RFP to shadow logically deleted rows from those replicas.
509+ List <Unfiltered > filtered = filterPartition (partition , filterTree , queryContext , command .rowFilter ().hasStaticExpression ());
507510
508511 // Note that we record the duration of the read after post-filtering, which actually
509512 // materializes the rows from disk.
@@ -523,11 +526,11 @@ public void close()
523526 }
524527 }
525528
526- private static List <Row > filterPartition (UnfilteredRowIterator partition , FilterTree tree , QueryContext context )
529+ private static List <Unfiltered > filterPartition (UnfilteredRowIterator partition , FilterTree tree , QueryContext context , boolean matchTombstones )
527530 {
528531 Row staticRow = partition .staticRow ();
529532 DecoratedKey partitionKey = partition .partitionKey ();
530- List <Row > matches = new ArrayList <>();
533+ List <Unfiltered > matches = new ArrayList <>();
531534 boolean hasMatch = false ;
532535
533536 while (partition .hasNext ())
@@ -540,10 +543,15 @@ private static List<Row> filterPartition(UnfilteredRowIterator partition, Filter
540543
541544 if (tree .isSatisfiedBy (partitionKey , (Row ) unfiltered , staticRow ))
542545 {
543- matches .add (( Row ) unfiltered );
546+ matches .add (unfiltered );
544547 hasMatch = true ;
545548 }
546549 }
550+ else if (matchTombstones && unfiltered .isRangeTombstoneMarker ())
551+ {
552+ // Note that range tombstones do not constitute matches, and will be discarded if no actual rows match.
553+ matches .add (unfiltered );
554+ }
547555 }
548556
549557 // We may not have any non-static row data to filter...
@@ -571,9 +579,9 @@ private static List<Row> filterPartition(UnfilteredRowIterator partition, Filter
571579
572580 private static class SinglePartitionIterator extends AbstractUnfilteredRowIterator
573581 {
574- private final Iterator <Row > rows ;
582+ private final Iterator <Unfiltered > rows ;
575583
576- public SinglePartitionIterator (UnfilteredRowIterator partition , Row staticRow , Iterator <Row > rows )
584+ public SinglePartitionIterator (UnfilteredRowIterator partition , Row staticRow , Iterator <Unfiltered > rows )
577585 {
578586 super (partition .metadata (),
579587 partition .partitionKey (),
@@ -766,7 +774,8 @@ public UnfilteredRowIterator readAndValidatePartition(PrimaryKey pk, List<Primar
766774 queryContext .partitionsRead ++;
767775 queryContext .checkpoint ();
768776
769- List <Row > clusters = filterPartition (partition , filterTree , queryContext );
777+ // Scored queries do not involve RFP, and therefore can ignore range tombstones.
778+ List <Unfiltered > clusters = filterPartition (partition , filterTree , queryContext , false );
770779
771780 if (clusters == null )
772781 {
@@ -794,7 +803,7 @@ public UnfilteredRowIterator readAndValidatePartition(PrimaryKey pk, List<Primar
794803 processedKeys .add (pk );
795804 return null ;
796805 }
797- representativeRow = clusters .get (0 );
806+ representativeRow = ( Row ) clusters .get (0 );
798807 assert clusters .size () == 1 : "Expect 1 result row, but got: " + clusters .size ();
799808 }
800809
0 commit comments