Search in sources :

Example 26 with Filter

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.core.Filter in project beam by apache.

the class MongoDbTable method translateRexNodeToBson.

/**
 * Recursively translates a single RexNode to MongoDB Bson filter. Supports simple comparison
 * operations, negation, and nested conjunction/disjunction. Boolean fields are translated as an
 * `$eq` operation with a boolean `true`.
 *
 * @param node {@code RexNode} to translate.
 * @return {@code Bson} filter.
 */
private Bson translateRexNodeToBson(RexNode node) {
    final IntFunction<String> fieldIdToName = i -> getSchema().getField(i).getName();
    // Supported operations are described in MongoDbFilter#isSupported
    if (node instanceof RexCall) {
        RexCall compositeNode = (RexCall) node;
        List<RexLiteral> literals = new ArrayList<>();
        List<RexInputRef> inputRefs = new ArrayList<>();
        for (RexNode operand : compositeNode.getOperands()) {
            if (operand instanceof RexLiteral) {
                literals.add((RexLiteral) operand);
            } else if (operand instanceof RexInputRef) {
                inputRefs.add((RexInputRef) operand);
            }
        }
        // Operation is a comparison, since one of the operands in a field reference.
        if (inputRefs.size() == 1) {
            RexInputRef inputRef = inputRefs.get(0);
            String inputFieldName = fieldIdToName.apply(inputRef.getIndex());
            if (literals.size() > 0) {
                // Convert literal value to the same Java type as the field we are comparing to.
                Object literal = convertToExpectedType(inputRef, literals.get(0));
                switch(node.getKind()) {
                    case IN:
                        return Filters.in(inputFieldName, convertToExpectedType(inputRef, literals));
                    case EQUALS:
                        return Filters.eq(inputFieldName, literal);
                    case NOT_EQUALS:
                        return Filters.not(Filters.eq(inputFieldName, literal));
                    case LESS_THAN:
                        return Filters.lt(inputFieldName, literal);
                    case GREATER_THAN:
                        return Filters.gt(inputFieldName, literal);
                    case GREATER_THAN_OR_EQUAL:
                        return Filters.gte(inputFieldName, literal);
                    case LESS_THAN_OR_EQUAL:
                        return Filters.lte(inputFieldName, literal);
                    default:
                        // Encountered an unexpected node kind, RuntimeException below.
                        break;
                }
            } else if (node.getKind().equals(SqlKind.NOT)) {
                // Ex: `where not boolean_field`
                return Filters.not(translateRexNodeToBson(inputRef));
            } else {
                throw new RuntimeException("Cannot create a filter for an unsupported node: " + node.toString());
            }
        } else {
            // Operation is a conjunction/disjunction.
            switch(node.getKind()) {
                case AND:
                    // Recursively construct filter for each operand of conjunction.
                    return Filters.and(compositeNode.getOperands().stream().map(this::translateRexNodeToBson).collect(Collectors.toList()));
                case OR:
                    // Recursively construct filter for each operand of disjunction.
                    return Filters.or(compositeNode.getOperands().stream().map(this::translateRexNodeToBson).collect(Collectors.toList()));
                default:
                    // Encountered an unexpected node kind, RuntimeException below.
                    break;
            }
        }
        throw new RuntimeException("Encountered an unexpected node kind: " + node.getKind().toString());
    } else if (node instanceof RexInputRef && node.getType().getSqlTypeName().equals(SqlTypeName.BOOLEAN)) {
        // Boolean field, must be true. Ex: `select * from table where bool_field`
        return Filters.eq(fieldIdToName.apply(((RexInputRef) node).getIndex()), true);
    }
    throw new RuntimeException("Was expecting a RexCall or a boolean RexInputRef, but received: " + node.getClass().getSimpleName());
}
Also used : Document(org.bson.Document) PBegin(org.apache.beam.sdk.values.PBegin) LoggerFactory(org.slf4j.LoggerFactory) MongoDbIO(org.apache.beam.sdk.io.mongodb.MongoDbIO) IsBounded(org.apache.beam.sdk.values.PCollection.IsBounded) JsonToRow(org.apache.beam.sdk.transforms.JsonToRow) SimpleFunction(org.apache.beam.sdk.transforms.SimpleFunction) ProjectSupport(org.apache.beam.sdk.extensions.sql.meta.ProjectSupport) Table(org.apache.beam.sdk.extensions.sql.meta.Table) Matcher(java.util.regex.Matcher) AND(org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.sql.SqlKind.AND) RexLiteral(org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexLiteral) MapElements(org.apache.beam.sdk.transforms.MapElements) SchemaBaseBeamTable(org.apache.beam.sdk.extensions.sql.meta.SchemaBaseBeamTable) FieldType(org.apache.beam.sdk.schemas.Schema.FieldType) Collectors(java.util.stream.Collectors) FindQuery(org.apache.beam.sdk.io.mongodb.FindQuery) Serializable(java.io.Serializable) InvalidTableException(org.apache.beam.sdk.extensions.sql.meta.provider.InvalidTableException) VisibleForTesting(org.apache.beam.vendor.calcite.v1_28_0.com.google.common.annotations.VisibleForTesting) COMPARISON(org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.sql.SqlKind.COMPARISON) POutput(org.apache.beam.sdk.values.POutput) List(java.util.List) ParDo(org.apache.beam.sdk.transforms.ParDo) BeamTableStatistics(org.apache.beam.sdk.extensions.sql.impl.BeamTableStatistics) ImmutableList(org.apache.beam.vendor.guava.v26_0_jre.com.google.common.collect.ImmutableList) Pattern(java.util.regex.Pattern) Experimental(org.apache.beam.sdk.annotations.Experimental) RexNode(org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexNode) JsonWriterSettings(org.bson.json.JsonWriterSettings) SqlKind(org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.sql.SqlKind) SelectHelpers(org.apache.beam.sdk.schemas.utils.SelectHelpers) ArrayList(java.util.ArrayList) PTransform(org.apache.beam.sdk.transforms.PTransform) Filters(com.mongodb.client.model.Filters) DefaultTableFilter(org.apache.beam.sdk.extensions.sql.meta.DefaultTableFilter) Bson(org.bson.conversions.Bson) ToJson(org.apache.beam.sdk.transforms.ToJson) JsonMode(org.bson.json.JsonMode) FieldAccessDescriptor(org.apache.beam.sdk.schemas.FieldAccessDescriptor) Row(org.apache.beam.sdk.values.Row) PipelineOptions(org.apache.beam.sdk.options.PipelineOptions) IntFunction(java.util.function.IntFunction) FieldTypeDescriptors(org.apache.beam.sdk.schemas.FieldTypeDescriptors) DoFn(org.apache.beam.sdk.transforms.DoFn) Logger(org.slf4j.Logger) BeamSqlTableFilter(org.apache.beam.sdk.extensions.sql.meta.BeamSqlTableFilter) PCollection(org.apache.beam.sdk.values.PCollection) Schema(org.apache.beam.sdk.schemas.Schema) RexCall(org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexCall) SqlTypeName(org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.sql.type.SqlTypeName) RexInputRef(org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexInputRef) OR(org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.sql.SqlKind.OR) RexCall(org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexCall) RexLiteral(org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexLiteral) ArrayList(java.util.ArrayList) RexInputRef(org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexInputRef) RexNode(org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexNode)

Example 27 with Filter

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.core.Filter in project druid by druid-io.

the class DruidJoinRule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    final Join join = call.rel(0);
    final DruidRel<?> left = call.rel(1);
    final DruidRel<?> right = call.rel(2);
    final RexBuilder rexBuilder = join.getCluster().getRexBuilder();
    final DruidRel<?> newLeft;
    final DruidRel<?> newRight;
    final Filter leftFilter;
    final List<RexNode> newProjectExprs = new ArrayList<>();
    // Already verified to be present in "matches", so just call "get".
    // Can't be final, because we're going to reassign it up to a couple of times.
    ConditionAnalysis conditionAnalysis = analyzeCondition(join.getCondition(), join.getLeft().getRowType(), right).get();
    final boolean isLeftDirectAccessPossible = enableLeftScanDirect && (left instanceof DruidQueryRel);
    if (left.getPartialDruidQuery().stage() == PartialDruidQuery.Stage.SELECT_PROJECT && (isLeftDirectAccessPossible || left.getPartialDruidQuery().getWhereFilter() == null)) {
        // Swap the left-side projection above the join, so the left side is a simple scan or mapping. This helps us
        // avoid subqueries.
        final RelNode leftScan = left.getPartialDruidQuery().getScan();
        final Project leftProject = left.getPartialDruidQuery().getSelectProject();
        leftFilter = left.getPartialDruidQuery().getWhereFilter();
        // Left-side projection expressions rewritten to be on top of the join.
        newProjectExprs.addAll(leftProject.getProjects());
        newLeft = left.withPartialQuery(PartialDruidQuery.create(leftScan));
        conditionAnalysis = conditionAnalysis.pushThroughLeftProject(leftProject);
    } else {
        // Leave left as-is. Write input refs that do nothing.
        for (int i = 0; i < left.getRowType().getFieldCount(); i++) {
            newProjectExprs.add(rexBuilder.makeInputRef(join.getRowType().getFieldList().get(i).getType(), i));
        }
        newLeft = left;
        leftFilter = null;
    }
    if (right.getPartialDruidQuery().stage() == PartialDruidQuery.Stage.SELECT_PROJECT && right.getPartialDruidQuery().getWhereFilter() == null && !right.getPartialDruidQuery().getSelectProject().isMapping() && conditionAnalysis.onlyUsesMappingsFromRightProject(right.getPartialDruidQuery().getSelectProject())) {
        // Swap the right-side projection above the join, so the right side is a simple scan or mapping. This helps us
        // avoid subqueries.
        final RelNode rightScan = right.getPartialDruidQuery().getScan();
        final Project rightProject = right.getPartialDruidQuery().getSelectProject();
        // Right-side projection expressions rewritten to be on top of the join.
        for (final RexNode rexNode : RexUtil.shift(rightProject.getProjects(), newLeft.getRowType().getFieldCount())) {
            if (join.getJoinType().generatesNullsOnRight()) {
                newProjectExprs.add(makeNullableIfLiteral(rexNode, rexBuilder));
            } else {
                newProjectExprs.add(rexNode);
            }
        }
        newRight = right.withPartialQuery(PartialDruidQuery.create(rightScan));
        conditionAnalysis = conditionAnalysis.pushThroughRightProject(rightProject);
    } else {
        // Leave right as-is. Write input refs that do nothing.
        for (int i = 0; i < right.getRowType().getFieldCount(); i++) {
            newProjectExprs.add(rexBuilder.makeInputRef(join.getRowType().getFieldList().get(left.getRowType().getFieldCount() + i).getType(), newLeft.getRowType().getFieldCount() + i));
        }
        newRight = right;
    }
    // Druid join written on top of the new left and right sides.
    final DruidJoinQueryRel druidJoin = DruidJoinQueryRel.create(join.copy(join.getTraitSet(), conditionAnalysis.getCondition(rexBuilder), newLeft, newRight, join.getJoinType(), join.isSemiJoinDone()), leftFilter, left.getPlannerContext());
    final RelBuilder relBuilder = call.builder().push(druidJoin).project(RexUtil.fixUp(rexBuilder, newProjectExprs, RelOptUtil.getFieldTypeList(druidJoin.getRowType())));
    call.transformTo(relBuilder.build());
}
Also used : DruidJoinQueryRel(org.apache.druid.sql.calcite.rel.DruidJoinQueryRel) RelBuilder(org.apache.calcite.tools.RelBuilder) ArrayList(java.util.ArrayList) Join(org.apache.calcite.rel.core.Join) DruidQueryRel(org.apache.druid.sql.calcite.rel.DruidQueryRel) Project(org.apache.calcite.rel.core.Project) RelNode(org.apache.calcite.rel.RelNode) Filter(org.apache.calcite.rel.core.Filter) RexBuilder(org.apache.calcite.rex.RexBuilder) RexNode(org.apache.calcite.rex.RexNode)

Example 28 with Filter

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.core.Filter in project hazelcast by hazelcast.

the class FilterIntoScanLogicalRule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    Filter filter = call.rel(0);
    FullScanLogicalRel scan = call.rel(1);
    HazelcastTable table = OptUtils.extractHazelcastTable(scan);
    RexNode existingCondition = table.getFilter();
    // inline the table projections into the merged condition. For example, if we have this relexp:
    // Filter[$0=?]
    // Scan[projects=[$1 + $2]
    // The filter condition will be converted to:
    // [$1 + $2 = ?]
    RexNode convertedCondition = inlineExpression(table.getProjects(), filter.getCondition());
    if (existingCondition != null) {
        convertedCondition = RexUtil.composeConjunction(scan.getCluster().getRexBuilder(), Arrays.asList(existingCondition, convertedCondition), true);
    }
    HazelcastRelOptTable convertedTable = OptUtils.createRelTable((HazelcastRelOptTable) scan.getTable(), table.withFilter(convertedCondition), scan.getCluster().getTypeFactory());
    FullScanLogicalRel rel = new FullScanLogicalRel(scan.getCluster(), OptUtils.toLogicalConvention(scan.getTraitSet()), convertedTable, scan.eventTimePolicyProvider(), scan.watermarkedColumnIndex());
    call.transformTo(rel);
}
Also used : Filter(org.apache.calcite.rel.core.Filter) HazelcastRelOptTable(com.hazelcast.jet.sql.impl.schema.HazelcastRelOptTable) HazelcastTable(com.hazelcast.jet.sql.impl.schema.HazelcastTable) RexNode(org.apache.calcite.rex.RexNode)

Example 29 with Filter

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.core.Filter in project hazelcast by hazelcast.

the class SlidingWindowFilterTransposeRule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    final Filter filter = call.rel(0);
    final SlidingWindow sw = call.rel(1);
    RexVisitorImpl<Void> visitor = new RexVisitorImpl<Void>(true) {

        @Override
        public Void visitInputRef(RexInputRef ref) {
            int index = ref.getIndex();
            if (index == sw.windowStartIndex() || index == sw.windowEndIndex()) {
                throw QueryException.error("Can't apply filter criteria to window bounds");
            }
            return super.visitInputRef(ref);
        }
    };
    filter.getCondition().accept(visitor);
    final Filter newFilter = filter.copy(filter.getTraitSet(), sw.getInput(), filter.getCondition());
    final SlidingWindow topSW = (SlidingWindow) sw.copy(sw.getTraitSet(), singletonList(newFilter));
    call.transformTo(topSW);
}
Also used : SlidingWindow(com.hazelcast.jet.sql.impl.opt.SlidingWindow) Filter(org.apache.calcite.rel.core.Filter) RexInputRef(org.apache.calcite.rex.RexInputRef) RexVisitorImpl(org.apache.calcite.rex.RexVisitorImpl)

Example 30 with Filter

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.core.Filter in project hive by apache.

the class MaterializedViewRewritingRelVisitor method check.

private void check(Union union) {
    // We found the Union
    if (union.getInputs().size() != 2) {
        // Bail out
        throw new ReturnedValue(false);
    }
    // First branch should have the query (with write ID filter conditions)
    new RelVisitor() {

        @Override
        public void visit(RelNode node, int ordinal, RelNode parent) {
            if (node instanceof TableScan || node instanceof Filter || node instanceof Project || node instanceof Join) {
                // We can continue
                super.visit(node, ordinal, parent);
            } else if (node instanceof Aggregate && containsAggregate) {
                Aggregate aggregate = (Aggregate) node;
                for (int i = 0; i < aggregate.getAggCallList().size(); ++i) {
                    AggregateCall aggregateCall = aggregate.getAggCallList().get(i);
                    if (aggregateCall.getAggregation().getKind() == SqlKind.COUNT && aggregateCall.getArgList().size() == 0) {
                        countIndex = i + aggregate.getGroupCount();
                        break;
                    }
                }
                // We can continue
                super.visit(node, ordinal, parent);
            } else {
                throw new ReturnedValue(false);
            }
        }
    }.go(union.getInput(0));
    // Second branch should only have the MV
    new RelVisitor() {

        @Override
        public void visit(RelNode node, int ordinal, RelNode parent) {
            if (node instanceof TableScan) {
                // We can continue
                // TODO: Need to check that this is the same MV that we are rebuilding
                RelOptHiveTable hiveTable = (RelOptHiveTable) node.getTable();
                if (!hiveTable.getHiveTableMD().isMaterializedView()) {
                    // If it is not a materialized view, we do not rewrite it
                    throw new ReturnedValue(false);
                }
                if (containsAggregate && !AcidUtils.isFullAcidTable(hiveTable.getHiveTableMD())) {
                    // we do not rewrite it (we need MERGE support)
                    throw new ReturnedValue(false);
                }
            } else if (node instanceof Project) {
                // We can continue
                super.visit(node, ordinal, parent);
            } else {
                throw new ReturnedValue(false);
            }
        }
    }.go(union.getInput(1));
    // We pass all the checks, we can rewrite
    throw new ReturnedValue(true);
}
Also used : AggregateCall(org.apache.calcite.rel.core.AggregateCall) TableScan(org.apache.calcite.rel.core.TableScan) Project(org.apache.calcite.rel.core.Project) RelOptHiveTable(org.apache.hadoop.hive.ql.optimizer.calcite.RelOptHiveTable) RelNode(org.apache.calcite.rel.RelNode) Filter(org.apache.calcite.rel.core.Filter) Join(org.apache.calcite.rel.core.Join) RelVisitor(org.apache.calcite.rel.RelVisitor) Aggregate(org.apache.calcite.rel.core.Aggregate)

Aggregations

Filter (org.apache.calcite.rel.core.Filter)67 RexNode (org.apache.calcite.rex.RexNode)38 RelNode (org.apache.calcite.rel.RelNode)35 Project (org.apache.calcite.rel.core.Project)23 ArrayList (java.util.ArrayList)20 RexBuilder (org.apache.calcite.rex.RexBuilder)17 Aggregate (org.apache.calcite.rel.core.Aggregate)15 RelBuilder (org.apache.calcite.tools.RelBuilder)15 Join (org.apache.calcite.rel.core.Join)13 TableScan (org.apache.calcite.rel.core.TableScan)11 List (java.util.List)10 Sort (org.apache.calcite.rel.core.Sort)10 RelOptUtil (org.apache.calcite.plan.RelOptUtil)8 ImmutableList (com.google.common.collect.ImmutableList)7 Collectors (java.util.stream.Collectors)7 LogicalFilter (org.apache.calcite.rel.logical.LogicalFilter)7 RelDataType (org.apache.calcite.rel.type.RelDataType)7 RexInputRef (org.apache.calcite.rex.RexInputRef)7 RexUtil (org.apache.calcite.rex.RexUtil)7 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)7