Google Cloud Bigtable C++ Client  2.0.0
A C++ Client Library for Google Cloud Bigtable
filters.h
Go to the documentation of this file.
1 // Copyright 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_FILTERS_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_FILTERS_H
17 
18 #include "google/cloud/bigtable/version.h"
19 #include "absl/meta/type_traits.h"
20 #include <google/bigtable/v2/data.pb.h>
21 #include <chrono>
22 #include <string>
23 
24 namespace google {
25 namespace cloud {
26 namespace bigtable {
28 /**
29  * Define the interfaces to create filter expressions.
30  *
31  * Example:
32  * @code
33  * // Get only data from the "fam" column family, and only the latest value.
34  * auto filter = Filter::Chain(Filter::Family("fam"), Filter::Latest(1));
35  * table->ReadRow("foo", std::move(filter));
36  * @endcode
37  *
38  * Those filters that use regular expressions, expect the patterns to be in
39  * the [RE2](https://github.com/google/re2/wiki/Syntax) syntax.
40  *
41  * @note Special care need be used with the expression used. Some of the
42  * filtered values (column names, row keys, cell values) are byte sequences,
43  * and can contain arbitrary bytes, the `\C` escape sequence must be used
44  * if a true wildcard is desired. The `.` character will not match the new
45  * line character `\n`, because `.` means `[^\n]` in RE2. As new line
46  * characters may be present in a binary value, you may need to explicitly
47  * match it using "\\n". The double escape is necessary because RE2 needs
48  * to get the escape sequence.
49  */
50 class Filter {
51  public:
52  explicit Filter(::google::bigtable::v2::RowFilter rhs)
53  : filter_(std::move(rhs)) {}
54 
55  Filter(Filter&&) = default;
56  Filter& operator=(Filter&&) = default;
57  Filter(Filter const&) = default;
58  Filter& operator=(Filter const&) = default;
59 
60  /// Return a filter that passes on all data.
61  static Filter PassAllFilter() {
62  Filter tmp;
63  tmp.filter_.set_pass_all_filter(true);
64  return tmp;
65  }
66 
67  /// Return a filter that blocks all data.
69  Filter tmp;
70  tmp.filter_.set_block_all_filter(true);
71  return tmp;
72  }
73 
74  /**
75  * Return a filter that accepts only the last @p n values of each column.
76  *
77  * The server rejects filters where @p n <= 0, any ReadRows() request
78  * containing such a filter fails with `grpc::StatusCode::INVALID_ARGUMENT`.
79  * This function does not perform any local validation of @p n.
80  */
81  static Filter Latest(std::int32_t n) {
82  Filter result;
83  result.filter_.set_cells_per_column_limit_filter(n);
84  return result;
85  }
86 
87  /**
88  * Return a filter that matches column families matching the given regexp.
89  *
90  * @param pattern the regular expression. It must be a valid
91  * [RE2](https://github.com/google/re2/wiki/Syntax) pattern. For
92  * technical reasons, the regex must not contain the ':' character, even
93  * if it is not being used as a literal. The server rejects filters with
94  * invalid patterns, including patterns containing the ':' character.
95  * The server fails the ReadRows() request with a
96  * `grpc::StatusCode::INVALID_ARGUMENT` status code. This function makes
97  * no attempt to validate the pattern before sending it to the server.
98  */
99  static Filter FamilyRegex(std::string pattern) {
100  Filter tmp;
101  tmp.filter_.set_family_name_regex_filter(std::move(pattern));
102  return tmp;
103  }
104 
105  /**
106  * Return a filter that accepts only columns matching the given regexp.
107  *
108  * @param pattern the regular expression. It must be a valid
109  * [RE2](https://github.com/google/re2/wiki/Syntax) pattern. The server
110  * rejects filters with an invalid pattern with a
111  * `grpc::StatusCode::INVALID_ARGUMENT` status code. This function makes
112  * no attempt to validate the pattern before sending it to the server.
113  *
114  * @note Special care need be used with the expression used. A column name
115  * is a byte sequence, and can contain arbitrary bytes, the `\C` escape
116  * sequence must be used if a true wildcard is desired. The `.` character
117  * will not match the new line character `\n`, because `.` means `[^\n]`
118  * in RE2. As new line characters may be present in a binary value, you
119  * may need to explicitly match it using "\\n". The double escape is
120  * necessary because RE2 needs to get the escape sequence.
121  */
122  static Filter ColumnRegex(std::string pattern) {
123  Filter tmp;
124  tmp.filter_.set_column_qualifier_regex_filter(std::move(pattern));
125  return tmp;
126  }
127 
128  /**
129  * Return a filter that accepts columns in the range [@p start, @p end)
130  * within the @p family column family.
131  *
132  * The column range must be non-empty, i.e., @p start must be strictly
133  * smaller than @p end. The server will reject empty ranges with a
134  * `grpc::StatusCode::INVALID_ARGUMENT` status code. This function makes no
135  * attempt to validate the column family or column range before sending them
136  * to the server.
137  */
138  static Filter ColumnRange(std::string family, std::string start,
139  std::string end) {
140  return ColumnRangeRightOpen(std::move(family), std::move(start),
141  std::move(end));
142  }
143 
144  /**
145  * Return the filter that accepts the named @p column within the @p family
146  * column family.
147  *
148  * This function makes no attempt to validate the column family or column
149  * range before sending them to the server.
150  */
151  static Filter ColumnName(std::string family, std::string column) {
152  std::string end = column;
153  return ColumnRangeClosed(std::move(family), std::move(column),
154  std::move(end));
155  }
156 
157  /**
158  * Return a filter that accepts cells with timestamps in the range
159  * [@p start, @p end).
160  *
161  * The timestamp range must be non-empty, i.e. @p start must be strictly
162  * smaller than @p end. The server will reject empty ranges with a
163  * `grpc::StatusCode::INVALID_ARGUMENT` status code. This function makes no
164  * attempt to validate the timestamp range before sending it to the server.
165  */
166  static Filter TimestampRangeMicros(std::int64_t start, std::int64_t end) {
167  Filter tmp;
168  auto& range = *tmp.filter_.mutable_timestamp_range_filter();
169  range.set_start_timestamp_micros(start);
170  range.set_end_timestamp_micros(end);
171  return tmp;
172  }
173 
174  /**
175  * Return a filter that accepts cells with timestamps in the range
176  * [@p start, @p end).
177  *
178  * The function accepts any instantiation of `std::chrono::duration<>` for the
179  * @p start and @p end parameters. For example:
180  *
181  * @code
182  * using namespace std::chrono_literals; // C++14
183  * auto r1 = bigtable::Filter::TimestampRange(10ms, 500ms);
184  * auto r2 = bigtable::Filter::TimestampRange(10min, 10min + 2s);
185  * @endcode
186  *
187  * The timestamp range must be non-empty, i.e. @p start must be strictly
188  * smaller than @p end. The server will reject empty ranges with a
189  * `grpc::StatusCode::INVALID_ARGUMENT` error. This function makes no
190  * attempt to validate the timestamp range before sending it to the server.
191  *
192  * @tparam Rep1 a placeholder to match the Rep tparam for @p start type,
193  * the semantics of this template parameter are documented in
194  * `std::chrono::duration<>` (in brief, the underlying arithmetic type
195  * used to store the number of ticks), for our purposes it is simply a
196  * formal parameter.
197  * @tparam Rep2 similar formal parameter for the type of @p end.
198  * @tparam Period1 a placeholder to match the Period tparam for @p start
199  * type, the semantics of this template parameter are documented in
200  * `std::chrono::duration<>` (in brief, the length of the tick in seconds,
201  * expressed as a `std::ratio<>`), for our purposes it is simply a formal
202  * parameter.
203  * @tparam Period2 similar formal parameter for the type of @p end.
204  *
205  * @see
206  * [std::chrono::duration<>](http://en.cppreference.com/w/cpp/chrono/duration)
207  * for more details.
208  */
209  template <typename Rep1, typename Period1, typename Rep2, typename Period2>
210  static Filter TimestampRange(std::chrono::duration<Rep1, Period1> start,
211  std::chrono::duration<Rep2, Period2> end) {
212  return TimestampRangeMicros(
213  std::chrono::duration_cast<std::chrono::microseconds>(start).count(),
214  std::chrono::duration_cast<std::chrono::microseconds>(end).count());
215  }
216 
217  /**
218  * Return a filter that matches keys matching the given regexp.
219  *
220  * @param pattern the regular expression. It must be a valid RE2 pattern.
221  * More details at https://github.com/google/re2/wiki/Syntax
222  *
223  * @note Special care need be used with the expression used. A row key
224  * is a byte sequence, and can contain arbitrary bytes, the `\C` escape
225  * sequence must be used if a true wildcard is desired. The `.` character
226  * will not match the new line character `\n`, because `.` means `[^\n]`
227  * in RE2. As new line characters may be present in a binary value, you
228  * may need to explicitly match it using "\\n". The double escape is
229  * necessary because RE2 needs to get the escape sequence.
230  */
231  static Filter RowKeysRegex(std::string pattern) {
232  Filter tmp;
233  tmp.filter_.set_row_key_regex_filter(std::move(pattern));
234  return tmp;
235  }
236 
237  /**
238  * Return a filter that matches cells with values matching the given regexp.
239  *
240  * @param pattern the regular expression. It must be a valid
241  * [RE2](https://github.com/google/re2/wiki/Syntax) pattern. The server
242  * rejects filters with an invalid pattern with a
243  * `grpc::StatusCode::INVALID_ARGUMENT` status code. This function makes
244  * no attempt to validate the timestamp range before sending it to
245  * the server.
246  *
247  * @note Special care need be used with the expression used. A cell value
248  * is a byte sequence, and can contain arbitrary bytes, the `\C` escape
249  * sequence must be used if a true wildcard is desired. The `.` character
250  * will not match the new line character `\n`, because `.` means `[^\n]`
251  * in RE2. As new line characters may be present in a binary value, you
252  * may need to explicitly match it using "\\n". The double escape is
253  * necessary because RE2 needs to get the escape sequence.
254  */
255  static Filter ValueRegex(std::string pattern) {
256  Filter tmp;
257  tmp.filter_.set_value_regex_filter(std::move(pattern));
258  return tmp;
259  }
260 
261  /**
262  * Return filter matching values in the range [@p start, @p end).
263  *
264  * @see ValueRangeRightOpen() for more details.
265  */
266  static Filter ValueRange(std::string start, std::string end) {
267  return ValueRangeRightOpen(std::move(start), std::move(end));
268  }
269 
270  /**
271  * Return a filter that only accepts the first @p n cells in a row.
272  *
273  * Note that cells might be repeated, such as when interleaving the results
274  * of multiple filters via the `Interleave()` function. Furthermore, this
275  * filter apples to the cells within a row; if there are multiple column
276  * families and/or columns in a row, the order is:
277  * - All the cells for a column family appear together, but there is no
278  * guarantee on the order of the column families. Furthermore, column
279  * families may appear in different orders in different rows.
280  * - Within a column family, the cells are ordered by column name, where
281  * column names are sorted lexicographically.
282  * - Within a column, the cells appear in descending order by timestamp.
283  *
284  * The server rejects filters where @p n <= 0, any ReadRows() request
285  * containing such a filter fails with `grpc::StatusCode::INVALID_ARGUMENT`.
286  * This function does not perform any local validation of @p n.
287  */
288  static Filter CellsRowLimit(std::int32_t n) {
289  Filter tmp;
290  tmp.filter_.set_cells_per_row_limit_filter(n);
291  return tmp;
292  }
293 
294  /**
295  * Return a filter that skips the first @p n cells in a row.
296  *
297  * Note that cells might be repeated, such as when interleaving the results
298  * of multiple filters via the `Interleave()` function. Furthermore, this
299  * filter apples to the cells within a row; if there are multiple column
300  * families and/or columns in a row, the order is:
301  * - All the cells for a column family appear together, but there is no
302  * guarantee on the order of the column families. Furthermore, column
303  * families may appear in different orders in different rows.
304  * - Within a column family, the cells are ordered by column name, where
305  * column names are sorted lexicographically.
306  * - Within a column, the cells appear in descending order by timestamp.
307  *
308  * The server rejects filters where @p n <= 0, any ReadRows() request
309  * containing such a filter fails with `grpc::StatusCode::INVALID_ARGUMENT`.
310  * This function does not perform any local validation of @p n.
311  */
312  static Filter CellsRowOffset(std::int32_t n) {
313  Filter tmp;
314  tmp.filter_.set_cells_per_row_offset_filter(n);
315  return tmp;
316  }
317 
318  /**
319  * Return a filter that samples rows with a given probability.
320  *
321  * The server rejects filters where @p probability is outside the range
322  * (0.0, 1.0). Any ReadRows() request containing such a filter fails with
323  * `grpc::StatusCode::INVALID_ARGUMENT`. This function does not perform any
324  * local validation of @p probability.
325  *
326  * @param probability the probability that any row will be selected. It
327  * must be in the range (0.0, 1.0).
328  */
329  static Filter RowSample(double probability) {
330  Filter tmp;
331  tmp.filter_.set_row_sample_filter(probability);
332  return tmp;
333  }
334 
335  //@{
336  /**
337  * @name Less common range filters.
338  *
339  * Cloud Bigtable range filters can include or exclude the limits of the
340  * range. In most cases applications use [@p start, @p end) ranges, and the
341  * ValueRange() and ColumnRange() functions are offered to support the
342  * common case. For the less common cases where the application needs
343  * different ranges, the following functions are available.
344  */
345  /**
346  * Return a filter that accepts values in the range [@p start, @p end).
347  *
348  * The range must be non-empty. The server will reject empty ranges with a
349  * `grpc::StatusCode::INVALID_ARGUMENT` error. This function makes no
350  * attempt to validate the timestamp range before sending it to the server.
351  */
352  static Filter ValueRangeLeftOpen(std::string start, std::string end) {
353  Filter tmp;
354  auto& range = *tmp.filter_.mutable_value_range_filter();
355  range.set_start_value_open(std::move(start));
356  range.set_end_value_closed(std::move(end));
357  return tmp;
358  }
359 
360  /**
361  * Return a filter that accepts values in the range [@p start, @p end].
362  *
363  * The range must be non-empty. The server will reject empty ranges with a
364  * `grpc::StatusCode::INVALID_ARGUMENT` error. This function makes no
365  * attempt to validate the timestamp range before sending it to the server.
366  */
367  static Filter ValueRangeRightOpen(std::string start, std::string end) {
368  Filter tmp;
369  auto& range = *tmp.filter_.mutable_value_range_filter();
370  range.set_start_value_closed(std::move(start));
371  range.set_end_value_open(std::move(end));
372  return tmp;
373  }
374 
375  /**
376  * Return a filter that accepts values in the range [@p start, @p end].
377  *
378  * The range must be non-empty. The server will reject empty ranges with a
379  * `grpc::StatusCode::INVALID_ARGUMENT` error. This function makes no
380  * attempt to validate the timestamp range before sending it to the server.
381  */
382  static Filter ValueRangeClosed(std::string start, std::string end) {
383  Filter tmp;
384  auto& range = *tmp.filter_.mutable_value_range_filter();
385  range.set_start_value_closed(std::move(start));
386  range.set_end_value_closed(std::move(end));
387  return tmp;
388  }
389 
390  /**
391  * Return a filter that accepts values in the range (@p start, @p end).
392  *
393  * The range must be non-empty. The server will reject empty ranges with a
394  * `grpc::StatusCode::INVALID_ARGUMENT` error. This function makes no
395  * attempt to validate the timestamp range before sending it to the server.
396  */
397  static Filter ValueRangeOpen(std::string start, std::string end) {
398  Filter tmp;
399  auto& range = *tmp.filter_.mutable_value_range_filter();
400  range.set_start_value_open(std::move(start));
401  range.set_end_value_open(std::move(end));
402  return tmp;
403  }
404 
405  /**
406  * Return a filter that accepts columns in the range [@p start, @p end)
407  * within the @p column_family.
408  *
409  * The range must be non-empty. The server will reject empty ranges with a
410  * `grpc::StatusCode::INVALID_ARGUMENT` error. This function makes no
411  * attempt to validate the timestamp range before sending it to the server.
412  */
413  static Filter ColumnRangeRightOpen(std::string column_family,
414  std::string start, std::string end) {
415  Filter tmp;
416  auto& range = *tmp.filter_.mutable_column_range_filter();
417  range.set_family_name(std::move(column_family));
418  range.set_start_qualifier_closed(std::move(start));
419  range.set_end_qualifier_open(std::move(end));
420  return tmp;
421  }
422 
423  /**
424  * Return a filter that accepts columns in the range (@p start, @p end]
425  * within the @p column_family.
426  *
427  * The range must be non-empty. The server will reject empty ranges with a
428  * `grpc::StatusCode::INVALID_ARGUMENT` error. This function makes no
429  * attempt to validate the timestamp range before sending it to the server.
430  */
431  static Filter ColumnRangeLeftOpen(std::string column_family,
432  std::string start, std::string end) {
433  Filter tmp;
434  auto& range = *tmp.filter_.mutable_column_range_filter();
435  range.set_family_name(std::move(column_family));
436  range.set_start_qualifier_open(std::move(start));
437  range.set_end_qualifier_closed(std::move(end));
438  return tmp;
439  }
440 
441  /**
442  * Return a filter that accepts columns in the range [@p start, @p end]
443  * within the @p column_family.
444  *
445  * The range must be non-empty. The server will reject empty ranges with a
446  * `grpc::StatusCode::INVALID_ARGUMENT` error. This function makes no
447  * attempt to validate the timestamp range before sending it to the server.
448  */
449  static Filter ColumnRangeClosed(std::string column_family, std::string start,
450  std::string end) {
451  Filter tmp;
452  auto& range = *tmp.filter_.mutable_column_range_filter();
453  range.set_family_name(std::move(column_family));
454  range.set_start_qualifier_closed(std::move(start));
455  range.set_end_qualifier_closed(std::move(end));
456  return tmp;
457  }
458 
459  /**
460  * Return a filter that accepts columns in the range (@p start, @p end)
461  * within the @p column_family.
462  *
463  * The range must be non-empty. The server will reject empty ranges with a
464  * `grpc::StatusCode::INVALID_ARGUMENT` error. This function makes no
465  * attempt to validate the timestamp range before sending it to the server.
466  */
467  static Filter ColumnRangeOpen(std::string column_family, std::string start,
468  std::string end) {
469  Filter tmp;
470  auto& range = *tmp.filter_.mutable_column_range_filter();
471  range.set_family_name(std::move(column_family));
472  range.set_start_qualifier_open(std::move(start));
473  range.set_end_qualifier_open(std::move(end));
474  return tmp;
475  }
476  //@}
477 
478  /**
479  * Return a filter that transforms any values into the empty string.
480  *
481  * As the name indicates, this acts as a transformer on the data, replacing
482  * any values with the empty string.
483  */
485  Filter tmp;
486  tmp.filter_.set_strip_value_transformer(true);
487  return tmp;
488  }
489 
490  /**
491  * Returns a filter that applies a label to each value.
492  *
493  * Each value accepted by previous filters in modified to include the @p
494  * label.
495  *
496  * @note Currently, it is not possible to apply more than one label in a
497  * filter expression, that is, a chain can only contain a single
498  * ApplyLabelTransformer() filter. This limitation may be lifted in
499  * the future. It is possible to have multiple ApplyLabelTransformer
500  * filters in a Union() filter, though in this case, each copy of a cell
501  * gets a different label.
502  *
503  * @param label the label applied to each cell. The labels must be at most 15
504  * characters long, and must match the `[a-z0-9\\-]+` pattern. The server
505  * validates the filter and will return a
506  * `grpc::StatusCode::INVALID_ARGUMENT` if the label does not meet these
507  * requirements. This function makes no attempt to validate the @p label
508  * parameter before sending it to the server.
509  */
510  static Filter ApplyLabelTransformer(std::string label) {
511  Filter tmp;
512  tmp.filter_.set_apply_label_transformer(std::move(label));
513  return tmp;
514  }
515  //@}
516 
517  //@{
518  /**
519  * @name Compound filters.
520  *
521  * These filters compose several filters to build complex filter expressions.
522  */
523  /**
524  * Returns a per-row conditional filter expression.
525  *
526  * For each row the @p predicate filter is evaluated, if it returns any
527  * cells, then the cells returned by @p true_filter are returned, otherwise
528  * the cells from @p false_filter are returned.
529  *
530  * The server validates the tree of filters, and rejects them if any contain
531  * invalid values. The server may impose additional restrictions on the
532  * resulting collection of filters. This function makes no attempt to
533  * validate the input before sending it to the server.
534  */
535  static Filter Condition(Filter predicate, Filter true_filter,
536  Filter false_filter) {
537  Filter tmp;
538  auto& condition = *tmp.filter_.mutable_condition();
539  condition.mutable_predicate_filter()->Swap(&predicate.filter_);
540  condition.mutable_true_filter()->Swap(&true_filter.filter_);
541  condition.mutable_false_filter()->Swap(&false_filter.filter_);
542  return tmp;
543  }
544 
545  /**
546  * Return a chain filter.
547  *
548  * The filter returned by this function acts like a pipeline. The output
549  * row from each stage is passed on as input for the next stage.
550  *
551  * @tparam FilterTypes the type of the filter arguments. They must all be
552  * convertible to Filter.
553  * @param stages the filter stages. The filter must contain at least two
554  * stages. The server validates each stage, and will reject them as
555  * described in their corresponding function. The server may also impose
556  * additional restrictions on the composition of the Chain. This function
557  * makes no attempt at validating the stages locally, the Chain filter is
558  * sent as-is it to the server.
559  */
560  template <typename... FilterTypes>
561  static Filter Chain(FilterTypes&&... stages) {
562  // This ugly thing provides a better compile-time error message than
563  // just letting the compiler figure things out 3 levels deep
564  // as it recurses on append_types().
565  static_assert(
566  absl::conjunction<std::is_convertible<FilterTypes, Filter>...>::value,
567  "The arguments passed to Chain(...) must be convertible to Filter");
568  Filter tmp;
569  auto& chain = *tmp.filter_.mutable_chain();
570  std::initializer_list<Filter> list{std::forward<FilterTypes>(stages)...};
571  for (Filter const& f : list) {
572  *chain.add_filters() = f.as_proto();
573  }
574  return tmp;
575  }
576 
577  /**
578  * Return a chain filter.
579  *
580  * The filter returned by this function acts like a pipeline. The output
581  * row from each stage is passed on as input for the next stage.
582  *
583  * @tparam Iterator an InputIterator whose `value_type` is `Filter`.
584  * @param begin the start of the range.
585  * @param end the end of the range.
586  */
587  template <typename Iterator>
588  static Filter ChainFromRange(Iterator begin, Iterator end) {
589  static_assert(
590  std::is_convertible<typename std::iterator_traits<Iterator>::value_type,
591  Filter>::value,
592  "The value type of the Iterator arguments passed to"
593  " InterleaveFromRange(...) must be convertible to Filter");
594  Filter tmp;
595  auto& chain = *tmp.filter_.mutable_chain();
596  for (auto it = begin; it != end; ++it) {
597  *chain.add_filters() = it->as_proto();
598  }
599  return tmp;
600  }
601 
602  /**
603  * Return a filter that interleaves the results of many other filters.
604  *
605  * This filter executes each stream in parallel and then merges the results by
606  * interleaving the output from each stream. The
607  * [proto
608  * file](https://github.com/googleapis/googleapis/blob/master/google/bigtable/v2/data.proto)
609  * has a nice illustration in the documentation of
610  * `google.bigtable.v2.RowFilter.Interleave`.
611  *
612  * In brief, if the input cells are c1, c2, c3, ..., and you have three
613  * subfilters S1, S2, and S3, the output of Interleave(S1, S2, S3) is:
614  * S1(c1), S2(c1), S3(c1), S1(d2), S2(d2), S3(c2), S1(c3), S2(c3), S3(c2), ...
615  * where some of the Si(c_j) values may be empty if the filter discards the
616  * cell altogether.
617  *
618  * @tparam FilterTypes the type of the filter arguments. They must all be
619  * convertible for Filter.
620  * @param streams the filters to interleave. The filter must contain at least
621  * two streams. The server validates each stream, and will reject them as
622  * described in their corresponding function. The server may also impose
623  * additional restrictions on the overall composition of the Interleave
624  * filter. This function makes no attempt at validating the streams
625  * locally, the Interleave filter is sent as-is to the server.
626  */
627  template <typename... FilterTypes>
628  static Filter Interleave(FilterTypes&&... streams) {
629  static_assert(
630  absl::conjunction<std::is_convertible<FilterTypes, Filter>...>::value,
631  "The arguments passed to Interleave(...) must be convertible"
632  " to Filter");
633  Filter tmp;
634  auto& interleave = *tmp.filter_.mutable_interleave();
635  std::initializer_list<Filter> list{std::forward<FilterTypes>(streams)...};
636  for (Filter const& f : list) {
637  *interleave.add_filters() = f.as_proto();
638  }
639  return tmp;
640  }
641 
642  /**
643  * Return a filter that interleaves the results of a range of filters.
644  *
645  * Similar to #Interleave(), except this function accepts a pair of
646  * Iterators.
647  *
648  * @param begin the begin iterator of the range.
649  * @param end the end iterator of the range.
650  */
651  template <typename Iterator>
652  static Filter InterleaveFromRange(Iterator begin, Iterator end) {
653  static_assert(
654  std::is_convertible<typename std::iterator_traits<Iterator>::value_type,
655  Filter>::value,
656  "The value type of the Iterator arguments passed to"
657  " InterleaveFromRange(...) must be convertible to Filter");
658  Filter tmp;
659  auto& interleave = *tmp.filter_.mutable_interleave();
660  for (auto it = begin; it != end; ++it) {
661  *interleave.add_filters() = it->as_proto();
662  }
663  return tmp;
664  }
665 
666  /**
667  * Return a filter that outputs all cells ignoring intermediate filters.
668  *
669  * Please read the documentation in the
670  * [proto
671  * file](https://github.com/googleapis/googleapis/blob/master/google/bigtable/v2/data.proto)
672  * for a detailed description. In short, this is an advanced filter to
673  * facilitate debugging. You can explore the intermediate results of a
674  * complex filter expression by injecting a filter of this type.
675  */
676  static Filter Sink() {
677  Filter tmp;
678  tmp.filter_.set_sink(true);
679  return tmp;
680  }
681  //@}
682 
683  /// Return the filter expression as a protobuf.
684  ::google::bigtable::v2::RowFilter const& as_proto() const& { return filter_; }
685 
686  /// Move out the underlying protobuf value.
687  ::google::bigtable::v2::RowFilter&& as_proto() && {
688  return std::move(filter_);
689  }
690 
691  private:
692  /// An empty filter, discards all data.
693  Filter() = default;
694 
695  google::bigtable::v2::RowFilter filter_;
696 };
697 
699 } // namespace bigtable
700 } // namespace cloud
701 } // namespace google
702 
703 #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_FILTERS_H