All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.org.apache.calcite.rel.mutable.MutableRels Maven / Gradle / Ivy

There is a newer version: 5.5.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to you under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hazelcast.org.apache.calcite.rel.mutable;

import com.hazelcast.org.apache.calcite.plan.RelOptUtil;
import com.hazelcast.org.apache.calcite.plan.hep.HepRelVertex;
import com.hazelcast.org.apache.calcite.plan.volcano.RelSubset;
import com.hazelcast.org.apache.calcite.rel.RelNode;
import com.hazelcast.org.apache.calcite.rel.core.Aggregate;
import com.hazelcast.org.apache.calcite.rel.core.Calc;
import com.hazelcast.org.apache.calcite.rel.core.Collect;
import com.hazelcast.org.apache.calcite.rel.core.Correlate;
import com.hazelcast.org.apache.calcite.rel.core.Exchange;
import com.hazelcast.org.apache.calcite.rel.core.Filter;
import com.hazelcast.org.apache.calcite.rel.core.Intersect;
import com.hazelcast.org.apache.calcite.rel.core.Join;
import com.hazelcast.org.apache.calcite.rel.core.Match;
import com.hazelcast.org.apache.calcite.rel.core.Minus;
import com.hazelcast.org.apache.calcite.rel.core.Project;
import com.hazelcast.org.apache.calcite.rel.core.RelFactories;
import com.hazelcast.org.apache.calcite.rel.core.Sample;
import com.hazelcast.org.apache.calcite.rel.core.Sort;
import com.hazelcast.org.apache.calcite.rel.core.TableFunctionScan;
import com.hazelcast.org.apache.calcite.rel.core.TableModify;
import com.hazelcast.org.apache.calcite.rel.core.TableScan;
import com.hazelcast.org.apache.calcite.rel.core.Uncollect;
import com.hazelcast.org.apache.calcite.rel.core.Union;
import com.hazelcast.org.apache.calcite.rel.core.Values;
import com.hazelcast.org.apache.calcite.rel.core.Window;
import com.hazelcast.org.apache.calcite.rel.logical.LogicalCalc;
import com.hazelcast.org.apache.calcite.rel.logical.LogicalCorrelate;
import com.hazelcast.org.apache.calcite.rel.logical.LogicalExchange;
import com.hazelcast.org.apache.calcite.rel.logical.LogicalMatch;
import com.hazelcast.org.apache.calcite.rel.logical.LogicalSort;
import com.hazelcast.org.apache.calcite.rel.logical.LogicalTableFunctionScan;
import com.hazelcast.org.apache.calcite.rel.logical.LogicalTableModify;
import com.hazelcast.org.apache.calcite.rel.logical.LogicalWindow;
import com.hazelcast.org.apache.calcite.rel.type.RelDataType;
import com.hazelcast.org.apache.calcite.rex.RexInputRef;
import com.hazelcast.org.apache.calcite.rex.RexNode;
import com.hazelcast.org.apache.calcite.rex.RexUtil;
import com.hazelcast.org.apache.calcite.sql.type.SqlTypeName;
import com.hazelcast.org.apache.calcite.tools.RelBuilder;
import com.hazelcast.org.apache.calcite.util.Util;
import com.hazelcast.org.apache.calcite.util.mapping.Mapping;
import com.hazelcast.org.apache.calcite.util.mapping.MappingType;
import com.hazelcast.org.apache.calcite.util.mapping.Mappings;

import com.hazelcast.com.google.common.collect.ImmutableList;

import com.hazelcast.org.checkerframework.checker.nullness.qual.Nullable;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static java.util.Objects.requireNonNull;

/** Utilities for dealing with {@link MutableRel}s. */
public abstract class MutableRels {

  public static boolean contains(MutableRel ancestor,
      final MutableRel target) {
    if (ancestor.equals(target)) {
      // Short-cut common case.
      return true;
    }
    try {
      new MutableRelVisitor() {
        @Override public void visit(@Nullable MutableRel node) {
          if (Objects.equals(node, target)) {
            throw Util.FoundOne.NULL;
          }
          super.visit(node);
        }
        // CHECKSTYLE: IGNORE 1
      }.go(ancestor);
      return false;
    } catch (Util.FoundOne e) {
      return true;
    }
  }

  public static @Nullable MutableRel preOrderTraverseNext(MutableRel node) {
    MutableRel parent = node.getParent();
    int ordinal = node.ordinalInParent + 1;
    while (parent != null) {
      if (parent.getInputs().size() > ordinal) {
        return parent.getInputs().get(ordinal);
      }
      node = parent;
      parent = node.getParent();
      ordinal = node.ordinalInParent + 1;
    }
    return null;
  }

  public static List descendants(MutableRel query) {
    final List list = new ArrayList<>();
    descendantsRecurse(list, query);
    return list;
  }

  private static void descendantsRecurse(List list,
      MutableRel rel) {
    list.add(rel);
    for (MutableRel input : rel.getInputs()) {
      descendantsRecurse(list, input);
    }
  }

  /** Based on
   * {@link com.hazelcast.org.apache.calcite.rel.rules.ProjectRemoveRule#strip}. */
  public static MutableRel strip(MutableProject project) {
    return isTrivial(project) ? project.getInput() : project;
  }

  /** Based on
   * {@link com.hazelcast.org.apache.calcite.rel.rules.ProjectRemoveRule#isTrivial(com.hazelcast.org.apache.calcite.rel.core.Project)}. */
  public static boolean isTrivial(MutableProject project) {
    MutableRel child = project.getInput();
    return RexUtil.isIdentity(project.projects, child.rowType);
  }

  /** Equivalent to
   * {@link RelOptUtil#createProject(com.hazelcast.org.apache.calcite.rel.RelNode, java.util.List)}
   * for {@link MutableRel}. */
  public static MutableRel createProject(final MutableRel child,
      final List posList) {
    final RelDataType rowType = child.rowType;
    if (Mappings.isIdentity(posList, rowType.getFieldCount())) {
      return child;
    }
    final Mapping mapping =
        Mappings.create(
            MappingType.INVERSE_SURJECTION,
            rowType.getFieldCount(),
            posList.size());
    for (int i = 0; i < posList.size(); i++) {
      mapping.set(posList.get(i), i);
    }
    return MutableProject.of(
        RelOptUtil.permute(child.cluster.getTypeFactory(), rowType, mapping),
        child,
        new AbstractList() {
          @Override public int size() {
            return posList.size();
          }

          @Override public RexNode get(int index) {
            final int pos = posList.get(index);
            return RexInputRef.of(pos, rowType);
          }
        });
  }

  /**
   * Construct expression list of Project by the given fields of the input.
   */
  public static List createProjectExprs(final MutableRel child,
      final List posList) {
    return posList.stream().map(pos -> RexInputRef.of(pos, child.rowType))
        .collect(Collectors.toList());
  }

  /**
   * Construct expression list of Project by the given fields of the input.
   */
  public static List createProjects(final MutableRel child,
      final List projects) {
    List rexNodeList = new ArrayList<>(projects.size());
    for (RexNode project : projects) {
      if (project instanceof RexInputRef) {
        RexInputRef rexInputRef = (RexInputRef) project;
        rexNodeList.add(RexInputRef.of(rexInputRef.getIndex(), child.rowType));
      } else {
        rexNodeList.add(project);
      }
    }
    return rexNodeList;
  }

  /** Equivalence to {@link com.hazelcast.org.apache.calcite.plan.RelOptUtil#createCastRel}
   * for {@link MutableRel}. */
  public static MutableRel createCastRel(MutableRel rel,
      RelDataType castRowType, boolean rename) {
    RelDataType rowType = rel.rowType;
    if (RelOptUtil.areRowTypesEqual(rowType, castRowType, rename)) {
      // nothing to do
      return rel;
    }
    List castExps =
        RexUtil.generateCastExpressions(rel.cluster.getRexBuilder(),
            castRowType, rowType);
    final List fieldNames =
        rename ? castRowType.getFieldNames() : rowType.getFieldNames();
    return MutableProject.of(rel, castExps, fieldNames);
  }

  public static RelNode fromMutable(MutableRel node) {
    return fromMutable(node, RelFactories.LOGICAL_BUILDER.create(node.cluster, null));
  }

  public static RelNode fromMutable(MutableRel node, RelBuilder relBuilder) {
    switch (node.type) {
    case TABLE_SCAN:
    case VALUES:
      return ((MutableLeafRel) node).rel;
    case PROJECT:
      final MutableProject project = (MutableProject) node;
      relBuilder.push(fromMutable(project.input, relBuilder));
      relBuilder.project(project.projects, project.rowType.getFieldNames(), true);
      return relBuilder.build();
    case FILTER:
      final MutableFilter filter = (MutableFilter) node;
      relBuilder.push(fromMutable(filter.input, relBuilder));
      relBuilder.filter(filter.condition);
      return relBuilder.build();
    case AGGREGATE:
      final MutableAggregate aggregate = (MutableAggregate) node;
      relBuilder.push(fromMutable(aggregate.input, relBuilder));
      relBuilder.aggregate(
          relBuilder.groupKey(aggregate.groupSet, aggregate.groupSets),
          aggregate.aggCalls);
      return relBuilder.build();
    case SORT:
      final MutableSort sort = (MutableSort) node;
      return LogicalSort.create(fromMutable(sort.input, relBuilder), sort.collation,
          sort.offset, sort.fetch);
    case CALC:
      final MutableCalc calc = (MutableCalc) node;
      return LogicalCalc.create(fromMutable(calc.input, relBuilder), calc.program);
    case EXCHANGE:
      final MutableExchange exchange = (MutableExchange) node;
      return LogicalExchange.create(
          fromMutable(exchange.getInput(), relBuilder), exchange.distribution);
    case COLLECT: {
      final MutableCollect collect = (MutableCollect) node;
      final RelNode child = fromMutable(collect.getInput(), relBuilder);
      return Collect.create(child, SqlTypeName.MULTISET, collect.fieldName);
    }
    case UNCOLLECT: {
      final MutableUncollect uncollect = (MutableUncollect) node;
      final RelNode child = fromMutable(uncollect.getInput(), relBuilder);
      return Uncollect.create(child.getTraitSet(), child, uncollect.withOrdinality,
          Collections.emptyList());
    }
    case WINDOW: {
      final MutableWindow window = (MutableWindow) node;
      final RelNode child = fromMutable(window.getInput(), relBuilder);
      return LogicalWindow.create(child.getTraitSet(),
          child, window.constants, window.rowType, window.groups);
    }
    case MATCH: {
      final MutableMatch match = (MutableMatch) node;
      final RelNode child = fromMutable(match.getInput(), relBuilder);
      return LogicalMatch.create(child, match.rowType, match.pattern,
          match.strictStart, match.strictEnd, match.patternDefinitions,
          match.measures, match.after, match.subsets, match.allRows,
          match.partitionKeys, match.orderKeys, match.interval);
    }
    case TABLE_MODIFY:
      final MutableTableModify modify = (MutableTableModify) node;
      return LogicalTableModify.create(modify.table, modify.catalogReader,
          fromMutable(modify.getInput(), relBuilder), modify.operation, modify.updateColumnList,
          modify.sourceExpressionList, modify.flattened);
    case SAMPLE:
      final MutableSample sample = (MutableSample) node;
      return new Sample(sample.cluster, fromMutable(sample.getInput(), relBuilder), sample.params);
    case TABLE_FUNCTION_SCAN:
      final MutableTableFunctionScan tableFunctionScan = (MutableTableFunctionScan) node;
      return LogicalTableFunctionScan.create(tableFunctionScan.cluster,
          fromMutables(tableFunctionScan.getInputs(), relBuilder), tableFunctionScan.rexCall,
          tableFunctionScan.elementType, tableFunctionScan.rowType,
          tableFunctionScan.columnMappings);
    case JOIN:
      final MutableJoin join = (MutableJoin) node;
      relBuilder.push(fromMutable(join.getLeft(), relBuilder));
      relBuilder.push(fromMutable(join.getRight(), relBuilder));
      relBuilder.join(join.joinType, join.condition, join.variablesSet);
      return relBuilder.build();
    case CORRELATE:
      final MutableCorrelate correlate = (MutableCorrelate) node;
      return LogicalCorrelate.create(fromMutable(correlate.getLeft(), relBuilder),
          fromMutable(correlate.getRight(), relBuilder),
          ImmutableList.of(), correlate.correlationId,
          correlate.requiredColumns, correlate.joinType);
    case UNION:
      final MutableUnion union = (MutableUnion) node;
      relBuilder.pushAll(MutableRels.fromMutables(union.inputs, relBuilder));
      relBuilder.union(union.all, union.inputs.size());
      return relBuilder.build();
    case MINUS:
      final MutableMinus minus = (MutableMinus) node;
      relBuilder.pushAll(MutableRels.fromMutables(minus.inputs, relBuilder));
      relBuilder.minus(minus.all, minus.inputs.size());
      return relBuilder.build();
    case INTERSECT:
      final MutableIntersect intersect = (MutableIntersect) node;
      relBuilder.pushAll(MutableRels.fromMutables(intersect.inputs, relBuilder));
      relBuilder.intersect(intersect.all, intersect.inputs.size());
      return relBuilder.build();
    default:
      throw new AssertionError(node.deep());
    }
  }

  private static List fromMutables(List nodes,
      final RelBuilder relBuilder) {
    return Util.transform(nodes,
        mutableRel -> fromMutable(mutableRel, relBuilder));
  }

  public static MutableRel toMutable(RelNode rel) {
    if (rel instanceof HepRelVertex) {
      return toMutable(((HepRelVertex) rel).getCurrentRel());
    }
    if (rel instanceof RelSubset) {
      RelSubset subset = (RelSubset) rel;
      RelNode best = subset.getBest();
      if (best == null) {
        best = requireNonNull(subset.getOriginal(),
            () -> "subset.getOriginal() is null for " + subset);
      }
      return toMutable(best);
    }
    if (rel instanceof TableScan) {
      return MutableScan.of((TableScan) rel);
    }
    if (rel instanceof Values) {
      return MutableValues.of((Values) rel);
    }
    if (rel instanceof Project) {
      final Project project = (Project) rel;
      final MutableRel input = toMutable(project.getInput());
      return MutableProject.of(input, project.getProjects(),
          project.getRowType().getFieldNames());
    }
    if (rel instanceof Filter) {
      final Filter filter = (Filter) rel;
      final MutableRel input = toMutable(filter.getInput());
      return MutableFilter.of(input, filter.getCondition());
    }
    if (rel instanceof Aggregate) {
      final Aggregate aggregate = (Aggregate) rel;
      final MutableRel input = toMutable(aggregate.getInput());
      return MutableAggregate.of(input, aggregate.getGroupSet(),
          aggregate.getGroupSets(), aggregate.getAggCallList());
    }
    if (rel instanceof Sort) {
      final Sort sort = (Sort) rel;
      final MutableRel input = toMutable(sort.getInput());
      return MutableSort.of(input, sort.getCollation(), sort.offset, sort.fetch);
    }
    if (rel instanceof Calc) {
      final Calc calc = (Calc) rel;
      final MutableRel input = toMutable(calc.getInput());
      return MutableCalc.of(input, calc.getProgram());
    }
    if (rel instanceof Exchange) {
      final Exchange exchange = (Exchange) rel;
      final MutableRel input = toMutable(exchange.getInput());
      return MutableExchange.of(input, exchange.getDistribution());
    }
    if (rel instanceof Collect) {
      final Collect collect = (Collect) rel;
      final MutableRel input = toMutable(collect.getInput());
      return MutableCollect.of(collect.getRowType(), input, collect.getFieldName());
    }
    if (rel instanceof Uncollect) {
      final Uncollect uncollect = (Uncollect) rel;
      final MutableRel input = toMutable(uncollect.getInput());
      return MutableUncollect.of(uncollect.getRowType(), input, uncollect.withOrdinality);
    }
    if (rel instanceof Window) {
      final Window window = (Window) rel;
      final MutableRel input = toMutable(window.getInput());
      return MutableWindow.of(window.getRowType(),
          input, window.groups, window.getConstants());
    }
    if (rel instanceof Match) {
      final Match match = (Match) rel;
      final MutableRel input = toMutable(match.getInput());
      return MutableMatch.of(match.getRowType(),
        input, match.getPattern(), match.isStrictStart(), match.isStrictEnd(),
        match.getPatternDefinitions(), match.getMeasures(), match.getAfter(),
        match.getSubsets(), match.isAllRows(), match.getPartitionKeys(),
        match.getOrderKeys(), match.getInterval());
    }
    if (rel instanceof TableModify) {
      final TableModify modify = (TableModify) rel;
      final MutableRel input = toMutable(modify.getInput());
      return MutableTableModify.of(modify.getRowType(), input, modify.getTable(),
          modify.getCatalogReader(), modify.getOperation(), modify.getUpdateColumnList(),
          modify.getSourceExpressionList(), modify.isFlattened());
    }
    if (rel instanceof Sample) {
      final Sample sample = (Sample) rel;
      final MutableRel input = toMutable(sample.getInput());
      return MutableSample.of(input, sample.getSamplingParameters());
    }
    if (rel instanceof TableFunctionScan) {
      final TableFunctionScan tableFunctionScan = (TableFunctionScan) rel;
      final List inputs = toMutables(tableFunctionScan.getInputs());
      return MutableTableFunctionScan.of(tableFunctionScan.getCluster(),
          tableFunctionScan.getRowType(), inputs, tableFunctionScan.getCall(),
          tableFunctionScan.getElementType(), tableFunctionScan.getColumnMappings());
    }
    // It is necessary that SemiJoin is placed in front of Join here, since SemiJoin
    // is a sub-class of Join.
    if (rel instanceof Join) {
      final Join join = (Join) rel;
      final MutableRel left = toMutable(join.getLeft());
      final MutableRel right = toMutable(join.getRight());
      return MutableJoin.of(join.getRowType(), left, right,
          join.getCondition(), join.getJoinType(), join.getVariablesSet());
    }
    if (rel instanceof Correlate) {
      final Correlate correlate = (Correlate) rel;
      final MutableRel left = toMutable(correlate.getLeft());
      final MutableRel right = toMutable(correlate.getRight());
      return MutableCorrelate.of(correlate.getRowType(), left, right,
          correlate.getCorrelationId(), correlate.getRequiredColumns(),
          correlate.getJoinType());
    }
    if (rel instanceof Union) {
      final Union union = (Union) rel;
      final List inputs = toMutables(union.getInputs());
      return MutableUnion.of(union.getRowType(), inputs, union.all);
    }
    if (rel instanceof Minus) {
      final Minus minus = (Minus) rel;
      final List inputs = toMutables(minus.getInputs());
      return MutableMinus.of(minus.getRowType(), inputs, minus.all);
    }
    if (rel instanceof Intersect) {
      final Intersect intersect = (Intersect) rel;
      final List inputs = toMutables(intersect.getInputs());
      return MutableIntersect.of(intersect.getRowType(), inputs, intersect.all);
    }
    throw new RuntimeException("cannot translate " + rel + " to MutableRel");
  }

  private static List toMutables(List nodes) {
    return nodes.stream().map(MutableRels::toMutable)
        .collect(Collectors.toList());
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy