Package org.apache.drill.optiq

Source Code of org.apache.drill.optiq.DrillJoinRel

/**
* 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 org.apache.drill.optiq;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

import org.eigenbase.rel.InvalidRelException;
import org.eigenbase.rel.JoinRelBase;
import org.eigenbase.rel.JoinRelType;
import org.eigenbase.rel.RelNode;
import org.eigenbase.relopt.RelOptCluster;
import org.eigenbase.relopt.RelOptUtil;
import org.eigenbase.relopt.RelTraitSet;
import org.eigenbase.reltype.RelDataType;
import org.eigenbase.rex.RexNode;
import org.eigenbase.util.Pair;

import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

/**
* Join implemented in Drill.
*/
public class DrillJoinRel extends JoinRelBase implements DrillRel {
  private final List<Integer> leftKeys = new ArrayList<>();
  private final List<Integer> rightKeys = new ArrayList<>();

  /** Creates a DrillJoinRel. */
  public DrillJoinRel(RelOptCluster cluster, RelTraitSet traits, RelNode left, RelNode right, RexNode condition,
      JoinRelType joinType) throws InvalidRelException {
    super(cluster, traits, left, right, condition, joinType, Collections.<String> emptySet());

    RexNode remaining = RelOptUtil.splitJoinCondition(left, right, condition, leftKeys, rightKeys);
    if (!remaining.isAlwaysTrue()) {
      throw new InvalidRelException("DrillJoinRel only supports equi-join");
    }
  }

  @Override
  public DrillJoinRel copy(RelTraitSet traitSet, RexNode condition, RelNode left, RelNode right) {
    try {
      return new DrillJoinRel(getCluster(), traitSet, left, right, condition, joinType);
    } catch (InvalidRelException e) {
      throw new AssertionError(e);
    }
  }

  @Override
  public int implement(DrillImplementor implementor) {
    final List<String> fields = getRowType().getFieldNames();
    assert isUnique(fields);
    final int leftCount = left.getRowType().getFieldCount();
    final List<String> leftFields = fields.subList(0, leftCount);
    final List<String> rightFields = fields.subList(leftCount, fields.size());

    final int leftId = implementInput(implementor, 0, 0, left);
    final int rightId = implementInput(implementor, 1, leftCount, right);

    /*
     * E.g. { op: "join", left: 2, right: 4, conditions: [ {relationship: "==", left: "deptId", right: "deptId"} ] }
     */
    final ObjectNode join = implementor.mapper.createObjectNode();
    join.put("op", "join");
    join.put("left", leftId);
    join.put("right", rightId);
    join.put("type", toDrill(joinType));
    final ArrayNode conditions = implementor.mapper.createArrayNode();
    join.put("conditions", conditions);
    for (Pair<Integer, Integer> pair : Pair.zip(leftKeys, rightKeys)) {
      final ObjectNode condition = implementor.mapper.createObjectNode();
      condition.put("relationship", "==");
      condition.put("left", leftFields.get(pair.left));
      condition.put("right", rightFields.get(pair.right));
      conditions.add(condition);
    }
    return implementor.add(join);
  }

  private int implementInput(DrillImplementor implementor, int i, int offset, RelNode input) {
    final int inputId = implementor.visitChild(this, i, input);
    assert uniqueFieldNames(input.getRowType());
    final List<String> fields = getRowType().getFieldNames();
    final List<String> inputFields = input.getRowType().getFieldNames();
    final List<String> outputFields = fields.subList(offset, offset + inputFields.size());
    if (!outputFields.equals(inputFields)) {
      // Ensure that input field names are the same as output field names.
      // If there are duplicate field names on left and right, fields will get
      // lost.
      return rename(implementor, inputId, inputFields, outputFields);
    } else {
      return inputId;
    }
  }

  private int rename(DrillImplementor implementor, int inputId, List<String> inputFields, List<String> outputFields) {
    final ObjectNode project = implementor.mapper.createObjectNode();
    project.put("op", "project");
    project.put("input", inputId);
    final ArrayNode transforms = implementor.mapper.createArrayNode();
    project.put("projections", transforms);
    for (Pair<String, String> pair : Pair.zip(inputFields, outputFields)) {
      final ObjectNode objectNode = implementor.mapper.createObjectNode();
      transforms.add(objectNode);
      objectNode.put("expr", pair.left);
      objectNode.put("ref", "output." + pair.right);
//      objectNode.put("ref", pair.right);
    }
    return implementor.add(project);
  }

  /**
   * Returns whether there are any elements in common between left and right.
   */
  private static <T> boolean intersects(List<T> left, List<T> right) {
    return new HashSet<>(left).removeAll(right);
  }

  private boolean uniqueFieldNames(RelDataType rowType) {
    return isUnique(rowType.getFieldNames());
  }

  private static <T> boolean isUnique(List<T> list) {
    return new HashSet<>(list).size() == list.size();
  }

  private static String toDrill(JoinRelType joinType) {
    switch (joinType) {
    case LEFT:
      return "left";
    case RIGHT:
      return "right";
    case INNER:
      return "inner";
    case FULL:
      return "outer";
    default:
      throw new AssertionError(joinType);
    }
  }
}
TOP

Related Classes of org.apache.drill.optiq.DrillJoinRel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.