Package org.eigenbase.rel

Source Code of org.eigenbase.rel.JoinInfo$NonEquiJoinInfo

/*
// 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.eigenbase.rel;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;

import org.eigenbase.relopt.RelOptUtil;
import org.eigenbase.reltype.RelDataType;
import org.eigenbase.rex.RexBuilder;
import org.eigenbase.rex.RexNode;
import org.eigenbase.rex.RexUtil;
import org.eigenbase.sql.fun.SqlStdOperatorTable;
import org.eigenbase.util.ImmutableIntList;
import org.eigenbase.util.mapping.IntPair;

import net.hydromatic.optiq.util.BitSets;

import com.google.common.base.Preconditions;

/** An analyzed join condition.
*
* <p>It is useful for the many algorithms that care whether a join is an
* equi-join.
*
* <p>You can create one using {@link #of}, or call {@link JoinRelBase#analyzeCondition()};
* many kinds of join cache their join info, especially those that are
* equi-joins and sub-class {@link org.eigenbase.rel.rules.EquiJoinRel}.</p>
*
* @see JoinRelBase#analyzeCondition() */
public abstract class JoinInfo {
  public final ImmutableIntList leftKeys;
  public final ImmutableIntList rightKeys;

  /** Creates a JoinInfo. */
  protected JoinInfo(ImmutableIntList leftKeys, ImmutableIntList rightKeys) {
    this.leftKeys = Preconditions.checkNotNull(leftKeys);
    this.rightKeys = Preconditions.checkNotNull(rightKeys);
    assert leftKeys.size() == rightKeys.size();
  }

  /** Creates a {@code JoinInfo} by analyzing a condition. */
  public static JoinInfo of(RelNode left, RelNode right, RexNode condition) {
    final List<Integer> leftKeys = new ArrayList<Integer>();
    final List<Integer> rightKeys = new ArrayList<Integer>();
    RexNode remaining =
        RelOptUtil.splitJoinCondition(left, right, condition, leftKeys,
            rightKeys);
    if (remaining.isAlwaysTrue()) {
      return new EquiJoinInfo(ImmutableIntList.copyOf(leftKeys),
          ImmutableIntList.copyOf(rightKeys));
    } else {
      return new NonEquiJoinInfo(ImmutableIntList.copyOf(leftKeys),
          ImmutableIntList.copyOf(rightKeys), remaining);
    }
  }

  /** Creates an equi-join. */
  public static JoinInfo of(ImmutableIntList leftKeys,
      ImmutableIntList rightKeys) {
    return new EquiJoinInfo(leftKeys, rightKeys);
  }

  /** Returns whether this is an equi-join. */
  public abstract boolean isEqui();

  /** Returns a list of (left, right) key ordinals. */
  public List<IntPair> pairs() {
    return IntPair.zip(leftKeys, rightKeys);
  }

  public BitSet leftSet() {
    return BitSets.of(leftKeys);
  }

  public BitSet rightSet() {
    return BitSets.of(rightKeys);
  }

  public abstract RexNode getRemaining(RexBuilder rexBuilder);

  public RexNode getEquiCondition(final RelNode left, final RelNode right,
      final RexBuilder rexBuilder) {
    final List<RelDataType> leftTypes =
        RelOptUtil.getFieldTypeList(left.getRowType());
    final List<RelDataType> rightTypes =
        RelOptUtil.getFieldTypeList(right.getRowType());
    return RexUtil.composeConjunction(rexBuilder,
        new AbstractList<RexNode>() {
          @Override public RexNode get(int index) {
            final int leftKey = leftKeys.get(index);
            final int rightKey = rightKeys.get(index);
            return rexBuilder.makeCall(SqlStdOperatorTable.EQUALS,
                rexBuilder.makeInputRef(leftTypes.get(leftKey), leftKey),
                rexBuilder.makeInputRef(rightTypes.get(rightKey),
                    leftTypes.size() + rightKey));
          }

          @Override public int size() {
            return leftKeys.size();
          }
        },
        false);
  }

  /** JoinInfo that represents an equi-join. */
  private static class EquiJoinInfo extends JoinInfo {
    protected EquiJoinInfo(ImmutableIntList leftKeys,
        ImmutableIntList rightKeys) {
      super(leftKeys, rightKeys);
    }

    @Override public boolean isEqui() {
      return true;
    }

    @Override public RexNode getRemaining(RexBuilder rexBuilder) {
      return rexBuilder.makeLiteral(true);
    }
  }

  /** JoinInfo that represents a non equi-join. */
  private static class NonEquiJoinInfo extends JoinInfo {
    public final RexNode remaining;

    protected NonEquiJoinInfo(ImmutableIntList leftKeys,
        ImmutableIntList rightKeys, RexNode remaining) {
      super(leftKeys, rightKeys);
      this.remaining = Preconditions.checkNotNull(remaining);
      assert !remaining.isAlwaysTrue();
    }

    @Override public boolean isEqui() {
      return false;
    }

    @Override public RexNode getRemaining(RexBuilder rexBuilder) {
      return remaining;
    }
  }
}

// End JoinInfo.java
TOP

Related Classes of org.eigenbase.rel.JoinInfo$NonEquiJoinInfo

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.