@@ -680,6 +680,69 @@ public void testReadingWithRuntimeParameterizedFilter() throws Exception {
680680 defaultRead .withTableId (table ).withRowFilter (StaticValueProvider .of (filter )),
681681 Lists .newArrayList (filteredRows ));
682682 }
683+
684+ /** Tests reading rows using a text proto filter provided through ValueProvider. */
685+ @ Test
686+ public void testReadingWithRowFilterTextProto () throws Exception {
687+ final String table = "TEST-FILTER-TABLE" ;
688+ final int numRows = 1001 ;
689+ List <Row > testRows = makeTableData (table , numRows );
690+ String regex = ".*17.*" ;
691+ final KeyMatchesRegex keyPredicate = new KeyMatchesRegex (regex );
692+ Iterable <Row > filteredRows =
693+ testRows .stream ()
694+ .filter (
695+ input -> {
696+ verifyNotNull (input , "input" );
697+ return keyPredicate .apply (input .getKey ());
698+ })
699+ .collect (Collectors .toList ());
700+
701+ String filter = "row_key_regex_filter: \" .*17.*\" " ;
702+ service .setupSampleRowKeys (table , 5 , 10L );
703+
704+ runReadTest (
705+ defaultRead .withTableId (table ).withRowFilterTextProto (StaticValueProvider .of (filter )),
706+ Lists .newArrayList (filteredRows ));
707+ }
708+
709+ /** Tests reading rows using both filter providers. */
710+ @ Test
711+ public void testReadingWithBothTextFilterAndRowFilter () throws Exception {
712+ final String table = "TEST-FILTER-TABLE" ;
713+ final int numRows = 1001 ;
714+ List <Row > testRows = makeTableData (table , numRows );
715+ String regex1 = ".*17.*" ;
716+ String regex2 = ".*2.*" ;
717+ final KeyMatchesRegex keyPredicate1 = new KeyMatchesRegex (regex1 );
718+ final KeyMatchesRegex keyPredicate2 = new KeyMatchesRegex (regex2 );
719+ Iterable <Row > filteredRows =
720+ testRows .stream ()
721+ .filter (
722+ input -> {
723+ verifyNotNull (input , "input" );
724+ return keyPredicate1 .apply (input .getKey ());
725+ })
726+ .filter (
727+ input -> {
728+ verifyNotNull (input , "input" );
729+ return keyPredicate2 .apply (input .getKey ());
730+ })
731+ .collect (Collectors .toList ());
732+
733+ String filter = "row_key_regex_filter: \" .*17.*\" " ;
734+ RowFilter rowFilter =
735+ RowFilter .newBuilder ().setRowKeyRegexFilter (ByteString .copyFromUtf8 (regex2 )).build ();
736+ service .setupSampleRowKeys (table , 5 , 10L );
737+
738+ runReadTest (
739+ defaultRead
740+ .withTableId (table )
741+ .withRowFilterTextProto (StaticValueProvider .of (filter ))
742+ .withRowFilter (rowFilter ),
743+ Lists .newArrayList (filteredRows ));
744+ }
745+
683746 /** Tests dynamic work rebalancing exhaustively. */
684747 @ Test
685748 public void testReadingSplitAtFractionExhaustive () throws Exception {
@@ -1778,17 +1841,27 @@ private static class FakeBigtableReader implements BigtableService.Reader {
17781841 private final FakeBigtableService service ;
17791842 private Iterator <Map .Entry <ByteString , ByteString >> rows ;
17801843 private Row currentRow ;
1781- private final Predicate <ByteString > filter ;
1844+ private final List < Predicate <ByteString >> filters = new ArrayList <>() ;
17821845
17831846 public FakeBigtableReader (BigtableSource source , FakeBigtableService service ) {
17841847 this .source = source ;
17851848 this .service = service ;
17861849 if (source .getRowFilter () == null ) {
1787- filter = Predicates .alwaysTrue ();
1850+ filters . add ( Predicates .alwaysTrue () );
17881851 } else {
1789- ByteString keyRegex = source .getRowFilter ().getRowKeyRegexFilter ();
1790- checkArgument (!keyRegex .isEmpty (), "Only RowKeyRegexFilter is supported" );
1791- filter = new KeyMatchesRegex (keyRegex .toStringUtf8 ());
1852+ RowFilter rowFilter = source .getRowFilter ();
1853+ if (rowFilter .hasChain ()) {
1854+ RowFilter .Chain chain = rowFilter .getChain ();
1855+ for (RowFilter filter : chain .getFiltersList ()) {
1856+ ByteString keyRegex = filter .getRowKeyRegexFilter ();
1857+ checkArgument (!keyRegex .isEmpty (), "Only RowKeyRegexFilter is supported" );
1858+ filters .add (new KeyMatchesRegex (keyRegex .toStringUtf8 ()));
1859+ }
1860+ } else {
1861+ ByteString keyRegex = source .getRowFilter ().getRowKeyRegexFilter ();
1862+ checkArgument (!keyRegex .isEmpty (), "Only RowKeyRegexFilter is supported" );
1863+ filters .add (new KeyMatchesRegex (keyRegex .toStringUtf8 ()));
1864+ }
17921865 }
17931866 service .verifyTableExists (source .getTableId ().get ());
17941867 }
@@ -1809,7 +1882,13 @@ public boolean advance() throws IOException {
18091882 Map .Entry <ByteString , ByteString > entry = null ;
18101883 while (rows .hasNext ()) {
18111884 entry = rows .next ();
1812- if (!filter .apply (entry .getKey ())
1885+ boolean predicateMatched = true ;
1886+ for (Predicate <ByteString > predicate : filters ) {
1887+ if (!predicate .apply (entry .getKey ())) {
1888+ predicateMatched = false ;
1889+ }
1890+ }
1891+ if (!predicateMatched
18131892 || !rangesContainsKey (source .getRanges (), makeByteKey (entry .getKey ()))) {
18141893 // Does not match row filter or does not match source range. Skip.
18151894 entry = null ;
0 commit comments