Class FilterRequirement

java.lang.Object
org.apache.calcite.sql.validate.FilterRequirement

public class FilterRequirement extends Object
Filtering requirements of a query, describing "must-filter" fields and "bypass" fields.

"Must-filter" fields must be filtered for a query to be considered valid; and "bypass" fields can defuse the errors if they are filtered on as an alternative.

Filter requirements originate in a SemanticTable in the model and propagate to any query that uses that table.

For example, consider table t, which has a must-filter field f and bypass-fields b0 and b1, and the following queries:

  1. Query select f from t is invalid because there is no filter on f.
  2. Query select * from (select f from t) gives an error in the subquery because there is no filter on f.
  3. Query select f from t where f = 1 is valid because there is a filter on f.
  4. Query select * from (select f from t) where f = 1 is valid because there is a filter on f.
  5. Query select f from t where b0 = 1 is valid because there is a filter on the bypass-field b0.

FilterRequirement is immutable, and has an instance EMPTY with no filters.

Notes on remnantFilterFields

remnantFilterFields identifies whether the query should error at the top level query. It is populated with the filter-field value when a filter-field is not selected or filtered on, but a bypass-field for the table is selected.

A remnant-filter field is no longer accessible by the enclosing query, and so the query can no longer be defused by filtering on it. We must keep track of the remnant-filter field because the query can still be defused by filtering on a bypass-field.

For example, consider table t with a must-filter field f and bypass-fields b0 and b1.

  1. Query select b0, b1 from t results in filterFields = [], bypassFields = [b0, b1], remnantFilterFields = [f]. The query is invalid because it is a top-level query and remnantFilterFields is not empty.
  2. Query select * from (select b0, b1 from t) where b0 = 1 is valid. When unwrapping the subquery we get the same FilterRequirement as the previous example: filterFields = [], bypassFields = [b0, b1], remnantFilterFields = [f]. But when unwrapping the top-level query, the filter on b0 defuses the remnantFilterField requirement of [f] because it originated in the same table, resulting in the following: filterFields = [], bypassFields = [b0, b1], remnantFilterFields = []. The query is valid because remnantFilterFields is now empty.
See Also:
  • Field Details

    • EMPTY

      public static final FilterRequirement EMPTY
      Empty filter requirement.
    • filterFields

      public final ImmutableBitSet filterFields
      Ordinals (in the row type) of the "must-filter" fields, fields that must be filtered in a query.
    • bypassFields

      public final ImmutableBitSet bypassFields
      Ordinals (in the row type) of the "bypass" fields, fields that can defuse validation errors on filterFields if filtered on.
    • remnantFilterFields

      public final com.google.common.collect.ImmutableSet<SqlQualified> remnantFilterFields
      Set of SqlQualified instances representing fields that have not been defused in the current query, but can still be defused by filtering on a bypass field in the enclosing query.