Search in sources :

Example 91 with ImmutableBitSet

use of org.apache.calcite.util.ImmutableBitSet in project calcite by apache.

the class RelMdColumnUniqueness method areProjectColumnsUnique.

@Nullable
private static Boolean areProjectColumnsUnique(SingleRel rel, RelMetadataQuery mq, ImmutableBitSet columns, boolean ignoreNulls, List<RexNode> projExprs) {
    RelDataTypeFactory typeFactory = rel.getCluster().getTypeFactory();
    ImmutableBitSet.Builder childColumns = ImmutableBitSet.builder();
    for (int bit : columns) {
        RexNode projExpr = projExprs.get(bit);
        if (projExpr instanceof RexInputRef) {
            childColumns.set(((RexInputRef) projExpr).getIndex());
        } else if (projExpr instanceof RexCall && ignoreNulls) {
            // If the expression is a cast such that the types are the same
            // except for the nullability, then if we're ignoring nulls,
            // it doesn't matter whether the underlying column reference
            // is nullable.  Check that the types are the same by making a
            // nullable copy of both types and then comparing them.
            RexCall call = (RexCall) projExpr;
            if (call.getOperator() != SqlStdOperatorTable.CAST) {
                continue;
            }
            RexNode castOperand = call.getOperands().get(0);
            if (!(castOperand instanceof RexInputRef)) {
                continue;
            }
            RelDataType castType = typeFactory.createTypeWithNullability(projExpr.getType(), true);
            RelDataType origType = typeFactory.createTypeWithNullability(castOperand.getType(), true);
            if (castType.equals(origType)) {
                childColumns.set(((RexInputRef) castOperand).getIndex());
            }
        } else {
            // projection, then skip it.
            continue;
        }
    }
    // If no columns can affect uniqueness, then return unknown
    if (childColumns.cardinality() == 0) {
        return null;
    }
    return mq.areColumnsUnique(rel.getInput(), childColumns.build(), ignoreNulls);
}
Also used : RexCall(org.apache.calcite.rex.RexCall) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) RexInputRef(org.apache.calcite.rex.RexInputRef) RelDataType(org.apache.calcite.rel.type.RelDataType) RexNode(org.apache.calcite.rex.RexNode) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Example 92 with ImmutableBitSet

use of org.apache.calcite.util.ImmutableBitSet in project calcite by apache.

the class RelMdExpressionLineage method getExpressionLineage.

/**
 * Expression lineage from {@link Join}.
 *
 * <p>We only extract the lineage for INNER joins.
 */
@Nullable
public Set<RexNode> getExpressionLineage(Join rel, RelMetadataQuery mq, RexNode outputExpression) {
    final RexBuilder rexBuilder = rel.getCluster().getRexBuilder();
    final RelNode leftInput = rel.getLeft();
    final RelNode rightInput = rel.getRight();
    final int nLeftColumns = leftInput.getRowType().getFieldList().size();
    // Extract input fields referenced by expression
    final ImmutableBitSet inputFieldsUsed = extractInputRefs(outputExpression);
    if (rel.getJoinType().isOuterJoin()) {
        // If we reference the inner side, we will bail out
        if (rel.getJoinType() == JoinRelType.LEFT) {
            ImmutableBitSet rightFields = ImmutableBitSet.range(nLeftColumns, rel.getRowType().getFieldCount());
            if (inputFieldsUsed.intersects(rightFields)) {
                // We cannot map origin of this expression.
                return null;
            }
        } else if (rel.getJoinType() == JoinRelType.RIGHT) {
            ImmutableBitSet leftFields = ImmutableBitSet.range(0, nLeftColumns);
            if (inputFieldsUsed.intersects(leftFields)) {
                // We cannot map origin of this expression.
                return null;
            }
        } else {
            // We cannot map origin of this expression.
            return null;
        }
    }
    // Gather table references
    final Set<RelTableRef> leftTableRefs = mq.getTableReferences(leftInput);
    if (leftTableRefs == null) {
        // Bail out
        return null;
    }
    final Set<RelTableRef> rightTableRefs = mq.getTableReferences(rightInput);
    if (rightTableRefs == null) {
        // Bail out
        return null;
    }
    final Multimap<List<String>, RelTableRef> qualifiedNamesToRefs = HashMultimap.create();
    final Map<RelTableRef, RelTableRef> currentTablesMapping = new HashMap<>();
    for (RelTableRef leftRef : leftTableRefs) {
        qualifiedNamesToRefs.put(leftRef.getQualifiedName(), leftRef);
    }
    for (RelTableRef rightRef : rightTableRefs) {
        int shift = 0;
        Collection<RelTableRef> lRefs = qualifiedNamesToRefs.get(rightRef.getQualifiedName());
        if (lRefs != null) {
            shift = lRefs.size();
        }
        currentTablesMapping.put(rightRef, RelTableRef.of(rightRef.getTable(), shift + rightRef.getEntityNumber()));
    }
    // Infer column origin expressions for given references
    final Map<RexInputRef, Set<RexNode>> mapping = new LinkedHashMap<>();
    for (int idx : inputFieldsUsed) {
        if (idx < nLeftColumns) {
            final RexInputRef inputRef = RexInputRef.of(idx, leftInput.getRowType().getFieldList());
            final Set<RexNode> originalExprs = mq.getExpressionLineage(leftInput, inputRef);
            if (originalExprs == null) {
                // Bail out
                return null;
            }
            // Left input references remain unchanged
            mapping.put(RexInputRef.of(idx, rel.getRowType().getFieldList()), originalExprs);
        } else {
            // Right input.
            final RexInputRef inputRef = RexInputRef.of(idx - nLeftColumns, rightInput.getRowType().getFieldList());
            final Set<RexNode> originalExprs = mq.getExpressionLineage(rightInput, inputRef);
            if (originalExprs == null) {
                // Bail out
                return null;
            }
            // Right input references might need to be updated if there are
            // table names clashes with left input
            final RelDataType fullRowType = SqlValidatorUtil.createJoinType(rexBuilder.getTypeFactory(), rel.getLeft().getRowType(), rel.getRight().getRowType(), null, ImmutableList.of());
            final Set<RexNode> updatedExprs = ImmutableSet.copyOf(Util.transform(originalExprs, e -> RexUtil.swapTableReferences(rexBuilder, e, currentTablesMapping)));
            mapping.put(RexInputRef.of(idx, fullRowType), updatedExprs);
        }
    }
    // Return result
    return createAllPossibleExpressions(rexBuilder, outputExpression, mapping);
}
Also used : Project(org.apache.calcite.rel.core.Project) TableScan(org.apache.calcite.rel.core.TableScan) HashMap(java.util.HashMap) Filter(org.apache.calcite.rel.core.Filter) Multimap(com.google.common.collect.Multimap) RelOptUtil(org.apache.calcite.plan.RelOptUtil) RelSubset(org.apache.calcite.plan.volcano.RelSubset) Join(org.apache.calcite.rel.core.Join) RelTableRef(org.apache.calcite.rex.RexTableInputRef.RelTableRef) ArrayList(java.util.ArrayList) Union(org.apache.calcite.rel.core.Union) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) RexUtil(org.apache.calcite.rex.RexUtil) SqlValidatorUtil(org.apache.calcite.sql.validate.SqlValidatorUtil) HashMultimap(com.google.common.collect.HashMultimap) ImmutableList(com.google.common.collect.ImmutableList) RexNode(org.apache.calcite.rex.RexNode) Pair(org.apache.calcite.util.Pair) KeyFor(org.checkerframework.checker.nullness.qual.KeyFor) Exchange(org.apache.calcite.rel.core.Exchange) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) TableModify(org.apache.calcite.rel.core.TableModify) Nullable(org.checkerframework.checker.nullness.qual.Nullable) LinkedHashSet(java.util.LinkedHashSet) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) RelDataType(org.apache.calcite.rel.type.RelDataType) ImmutableSet(com.google.common.collect.ImmutableSet) RexBuilder(org.apache.calcite.rex.RexBuilder) Collection(java.util.Collection) Set(java.util.Set) RelNode(org.apache.calcite.rel.RelNode) Aggregate(org.apache.calcite.rel.core.Aggregate) Collectors(java.util.stream.Collectors) RexInputRef(org.apache.calcite.rex.RexInputRef) List(java.util.List) Sort(org.apache.calcite.rel.core.Sort) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) Calc(org.apache.calcite.rel.core.Calc) JoinRelType(org.apache.calcite.rel.core.JoinRelType) RexShuttle(org.apache.calcite.rex.RexShuttle) Util(org.apache.calcite.util.Util) RexTableInputRef(org.apache.calcite.rex.RexTableInputRef) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) RelTableRef(org.apache.calcite.rex.RexTableInputRef.RelTableRef) RelDataType(org.apache.calcite.rel.type.RelDataType) LinkedHashMap(java.util.LinkedHashMap) RelNode(org.apache.calcite.rel.RelNode) RexBuilder(org.apache.calcite.rex.RexBuilder) RexInputRef(org.apache.calcite.rex.RexInputRef) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) RexNode(org.apache.calcite.rex.RexNode) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Example 93 with ImmutableBitSet

use of org.apache.calcite.util.ImmutableBitSet in project calcite by apache.

the class RelMdExpressionLineage method getExpressionLineage.

/**
 * Expression lineage from Calc.
 */
@Nullable
public Set<RexNode> getExpressionLineage(Calc calc, RelMetadataQuery mq, RexNode outputExpression) {
    final RelNode input = calc.getInput();
    final RexBuilder rexBuilder = calc.getCluster().getRexBuilder();
    // Extract input fields referenced by expression
    final ImmutableBitSet inputFieldsUsed = extractInputRefs(outputExpression);
    // Infer column origin expressions for given references
    final Map<RexInputRef, Set<RexNode>> mapping = new LinkedHashMap<>();
    Pair<ImmutableList<RexNode>, ImmutableList<RexNode>> calcProjectsAndFilter = calc.getProgram().split();
    for (int idx : inputFieldsUsed) {
        final RexNode inputExpr = calcProjectsAndFilter.getKey().get(idx);
        final Set<RexNode> originalExprs = mq.getExpressionLineage(input, inputExpr);
        if (originalExprs == null) {
            // Bail out
            return null;
        }
        final RexInputRef ref = RexInputRef.of(idx, calc.getRowType().getFieldList());
        mapping.put(ref, originalExprs);
    }
    // Return result
    return createAllPossibleExpressions(rexBuilder, outputExpression, mapping);
}
Also used : HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) RelNode(org.apache.calcite.rel.RelNode) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) ImmutableList(com.google.common.collect.ImmutableList) RexBuilder(org.apache.calcite.rex.RexBuilder) RexInputRef(org.apache.calcite.rex.RexInputRef) LinkedHashMap(java.util.LinkedHashMap) RexNode(org.apache.calcite.rex.RexNode) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Example 94 with ImmutableBitSet

use of org.apache.calcite.util.ImmutableBitSet in project calcite by apache.

the class RelMdExpressionLineage method getExpressionLineage.

/**
 * Expression lineage from {@link Union}.
 *
 * <p>For Union operator, we might be able to extract multiple origins for the
 * references in the given expression.
 */
@Nullable
public Set<RexNode> getExpressionLineage(Union rel, RelMetadataQuery mq, RexNode outputExpression) {
    final RexBuilder rexBuilder = rel.getCluster().getRexBuilder();
    // Extract input fields referenced by expression
    final ImmutableBitSet inputFieldsUsed = extractInputRefs(outputExpression);
    // Infer column origin expressions for given references
    final Multimap<List<String>, RelTableRef> qualifiedNamesToRefs = HashMultimap.create();
    final Map<RexInputRef, Set<RexNode>> mapping = new LinkedHashMap<>();
    for (RelNode input : rel.getInputs()) {
        // Gather table references
        final Map<RelTableRef, RelTableRef> currentTablesMapping = new HashMap<>();
        final Set<RelTableRef> tableRefs = mq.getTableReferences(input);
        if (tableRefs == null) {
            // Bail out
            return null;
        }
        for (RelTableRef tableRef : tableRefs) {
            int shift = 0;
            Collection<RelTableRef> lRefs = qualifiedNamesToRefs.get(tableRef.getQualifiedName());
            if (lRefs != null) {
                shift = lRefs.size();
            }
            currentTablesMapping.put(tableRef, RelTableRef.of(tableRef.getTable(), shift + tableRef.getEntityNumber()));
        }
        // Map references
        for (int idx : inputFieldsUsed) {
            final RexInputRef inputRef = RexInputRef.of(idx, input.getRowType().getFieldList());
            final Set<RexNode> originalExprs = mq.getExpressionLineage(input, inputRef);
            if (originalExprs == null) {
                // Bail out
                return null;
            }
            // References might need to be updated
            final RexInputRef ref = RexInputRef.of(idx, rel.getRowType().getFieldList());
            final Set<RexNode> updatedExprs = originalExprs.stream().map(e -> RexUtil.swapTableReferences(rexBuilder, e, currentTablesMapping)).collect(Collectors.toSet());
            final Set<RexNode> set = mapping.get(ref);
            if (set != null) {
                set.addAll(updatedExprs);
            } else {
                mapping.put(ref, updatedExprs);
            }
        }
        // Add to existing qualified names
        for (RelTableRef newRef : currentTablesMapping.values()) {
            qualifiedNamesToRefs.put(newRef.getQualifiedName(), newRef);
        }
    }
    // Return result
    return createAllPossibleExpressions(rexBuilder, outputExpression, mapping);
}
Also used : Project(org.apache.calcite.rel.core.Project) TableScan(org.apache.calcite.rel.core.TableScan) HashMap(java.util.HashMap) Filter(org.apache.calcite.rel.core.Filter) Multimap(com.google.common.collect.Multimap) RelOptUtil(org.apache.calcite.plan.RelOptUtil) RelSubset(org.apache.calcite.plan.volcano.RelSubset) Join(org.apache.calcite.rel.core.Join) RelTableRef(org.apache.calcite.rex.RexTableInputRef.RelTableRef) ArrayList(java.util.ArrayList) Union(org.apache.calcite.rel.core.Union) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) RexUtil(org.apache.calcite.rex.RexUtil) SqlValidatorUtil(org.apache.calcite.sql.validate.SqlValidatorUtil) HashMultimap(com.google.common.collect.HashMultimap) ImmutableList(com.google.common.collect.ImmutableList) RexNode(org.apache.calcite.rex.RexNode) Pair(org.apache.calcite.util.Pair) KeyFor(org.checkerframework.checker.nullness.qual.KeyFor) Exchange(org.apache.calcite.rel.core.Exchange) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) TableModify(org.apache.calcite.rel.core.TableModify) Nullable(org.checkerframework.checker.nullness.qual.Nullable) LinkedHashSet(java.util.LinkedHashSet) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) RelDataType(org.apache.calcite.rel.type.RelDataType) ImmutableSet(com.google.common.collect.ImmutableSet) RexBuilder(org.apache.calcite.rex.RexBuilder) Collection(java.util.Collection) Set(java.util.Set) RelNode(org.apache.calcite.rel.RelNode) Aggregate(org.apache.calcite.rel.core.Aggregate) Collectors(java.util.stream.Collectors) RexInputRef(org.apache.calcite.rex.RexInputRef) List(java.util.List) Sort(org.apache.calcite.rel.core.Sort) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) Calc(org.apache.calcite.rel.core.Calc) JoinRelType(org.apache.calcite.rel.core.JoinRelType) RexShuttle(org.apache.calcite.rex.RexShuttle) Util(org.apache.calcite.util.Util) RexTableInputRef(org.apache.calcite.rex.RexTableInputRef) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) RelTableRef(org.apache.calcite.rex.RexTableInputRef.RelTableRef) LinkedHashMap(java.util.LinkedHashMap) RelNode(org.apache.calcite.rel.RelNode) RexBuilder(org.apache.calcite.rex.RexBuilder) RexInputRef(org.apache.calcite.rex.RexInputRef) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) RexNode(org.apache.calcite.rex.RexNode) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Example 95 with ImmutableBitSet

use of org.apache.calcite.util.ImmutableBitSet in project calcite by apache.

the class RelMdAllPredicates method getAllPredicates.

/**
 * Add the Join condition to the list obtained from the input.
 */
@Nullable
public RelOptPredicateList getAllPredicates(Join join, RelMetadataQuery mq) {
    if (join.getJoinType().isOuterJoin()) {
        // We cannot map origin of this expression.
        return null;
    }
    final RexBuilder rexBuilder = join.getCluster().getRexBuilder();
    final RexNode pred = join.getCondition();
    final Multimap<List<String>, RelTableRef> qualifiedNamesToRefs = HashMultimap.create();
    RelOptPredicateList newPreds = RelOptPredicateList.EMPTY;
    for (RelNode input : join.getInputs()) {
        final RelOptPredicateList inputPreds = mq.getAllPredicates(input);
        if (inputPreds == null) {
            // Bail out
            return null;
        }
        // Gather table references
        final Set<RelTableRef> tableRefs = mq.getTableReferences(input);
        if (tableRefs == null) {
            return null;
        }
        if (input == join.getLeft()) {
            // Left input references remain unchanged
            for (RelTableRef leftRef : tableRefs) {
                qualifiedNamesToRefs.put(leftRef.getQualifiedName(), leftRef);
            }
            newPreds = newPreds.union(rexBuilder, inputPreds);
        } else {
            // Right input references might need to be updated if there are table name
            // clashes with left input
            final Map<RelTableRef, RelTableRef> currentTablesMapping = new HashMap<>();
            for (RelTableRef rightRef : tableRefs) {
                int shift = 0;
                Collection<RelTableRef> lRefs = qualifiedNamesToRefs.get(rightRef.getQualifiedName());
                if (lRefs != null) {
                    shift = lRefs.size();
                }
                currentTablesMapping.put(rightRef, RelTableRef.of(rightRef.getTable(), shift + rightRef.getEntityNumber()));
            }
            final List<RexNode> updatedPreds = Util.transform(inputPreds.pulledUpPredicates, e -> RexUtil.swapTableReferences(rexBuilder, e, currentTablesMapping));
            newPreds = newPreds.union(rexBuilder, RelOptPredicateList.of(rexBuilder, updatedPreds));
        }
    }
    // Extract input fields referenced by Join condition
    final Set<RelDataTypeField> inputExtraFields = new LinkedHashSet<>();
    final RelOptUtil.InputFinder inputFinder = new RelOptUtil.InputFinder(inputExtraFields);
    pred.accept(inputFinder);
    final ImmutableBitSet inputFieldsUsed = inputFinder.build();
    // Infer column origin expressions for given references
    final Map<RexInputRef, Set<RexNode>> mapping = new LinkedHashMap<>();
    final RelDataType fullRowType = SqlValidatorUtil.createJoinType(rexBuilder.getTypeFactory(), join.getLeft().getRowType(), join.getRight().getRowType(), null, ImmutableList.of());
    for (int idx : inputFieldsUsed) {
        final RexInputRef inputRef = RexInputRef.of(idx, fullRowType.getFieldList());
        final Set<RexNode> originalExprs = mq.getExpressionLineage(join, inputRef);
        if (originalExprs == null) {
            // Bail out
            return null;
        }
        final RexInputRef ref = RexInputRef.of(idx, fullRowType.getFieldList());
        mapping.put(ref, originalExprs);
    }
    // Replace with new expressions and return union of predicates
    final Set<RexNode> allExprs = RelMdExpressionLineage.createAllPossibleExpressions(rexBuilder, pred, mapping);
    if (allExprs == null) {
        return null;
    }
    return newPreds.union(rexBuilder, RelOptPredicateList.of(rexBuilder, allExprs));
}
Also used : LinkedHashSet(java.util.LinkedHashSet) LinkedHashSet(java.util.LinkedHashSet) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) Set(java.util.Set) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) RelDataType(org.apache.calcite.rel.type.RelDataType) LinkedHashMap(java.util.LinkedHashMap) RelOptPredicateList(org.apache.calcite.plan.RelOptPredicateList) RexBuilder(org.apache.calcite.rex.RexBuilder) ImmutableList(com.google.common.collect.ImmutableList) RelOptPredicateList(org.apache.calcite.plan.RelOptPredicateList) List(java.util.List) RelOptUtil(org.apache.calcite.plan.RelOptUtil) RelTableRef(org.apache.calcite.rex.RexTableInputRef.RelTableRef) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) RexInputRef(org.apache.calcite.rex.RexInputRef) RexNode(org.apache.calcite.rex.RexNode) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Aggregations

ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)365 RexNode (org.apache.calcite.rex.RexNode)196 RelNode (org.apache.calcite.rel.RelNode)183 ArrayList (java.util.ArrayList)179 AggregateCall (org.apache.calcite.rel.core.AggregateCall)116 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)98 RexBuilder (org.apache.calcite.rex.RexBuilder)92 RelDataType (org.apache.calcite.rel.type.RelDataType)89 RexInputRef (org.apache.calcite.rex.RexInputRef)79 HashMap (java.util.HashMap)68 Aggregate (org.apache.calcite.rel.core.Aggregate)62 RelBuilder (org.apache.calcite.tools.RelBuilder)59 Pair (org.apache.calcite.util.Pair)57 List (java.util.List)49 ImmutableList (com.google.common.collect.ImmutableList)48 HashSet (java.util.HashSet)45 LinkedHashSet (java.util.LinkedHashSet)45 Join (org.apache.calcite.rel.core.Join)45 RelMetadataQuery (org.apache.calcite.rel.metadata.RelMetadataQuery)45 Nullable (org.checkerframework.checker.nullness.qual.Nullable)43