/* * 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.*; import org.eigenbase.relopt.*; import org.eigenbase.reltype.RelDataTypeField; import org.eigenbase.rex.*; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; /** * A JoinRel represents two relational expressions joined according to some * condition. * * <p>Some rules: * * <ul> <li>{@link org.eigenbase.rel.rules.ExtractJoinFilterRule} converts an * {@link JoinRel inner join} to a {@link FilterRel filter} on top of a {@link * JoinRel cartesian inner join}. <li>{@code * net.sf.farrago.fennel.rel.FennelCartesianJoinRule} implements a JoinRel as a * cartesian product. </ul> */ public final class JoinRel extends JoinRelBase { //~ Instance fields -------------------------------------------------------- // NOTE jvs 14-Mar-2006: Normally we don't use state like this // to control rule firing, but due to the non-local nature of // semijoin optimizations, it's pretty much required. private final boolean semiJoinDone; private final ImmutableList<RelDataTypeField> systemFieldList; //~ Constructors ----------------------------------------------------------- /** * Creates a JoinRel. * * @param cluster Cluster * @param left Left input * @param right Right input * @param condition Join condition * @param joinType Join type * @param variablesStopped Set of names of variables which are set by the * LHS and used by the RHS and are not available to * nodes above this JoinRel in the tree */ public JoinRel( RelOptCluster cluster, RelNode left, RelNode right, RexNode condition, JoinRelType joinType, Set<String> variablesStopped) { this( cluster, left, right, condition, joinType, variablesStopped, false, ImmutableList.<RelDataTypeField>of()); } /** * Creates a JoinRel, flagged with whether it has been translated to a * semi-join. * * @param cluster Cluster * @param left Left input * @param right Right input * @param condition Join condition * @param joinType Join type * @param variablesStopped Set of names of variables which are set by the * LHS and used by the RHS and are not available to * nodes above this JoinRel in the tree * @param semiJoinDone Whether this join has been translated to a * semi-join * @param systemFieldList List of system fields that will be prefixed to * output row type; typically empty but must not be * null * @see #isSemiJoinDone() */ public JoinRel( RelOptCluster cluster, RelNode left, RelNode right, RexNode condition, JoinRelType joinType, Set<String> variablesStopped, boolean semiJoinDone, ImmutableList<RelDataTypeField> systemFieldList) { super( cluster, cluster.traitSetOf(Convention.NONE), left, right, condition, joinType, variablesStopped); assert systemFieldList != null; this.semiJoinDone = semiJoinDone; this.systemFieldList = systemFieldList; } /** * Creates a JoinRel by parsing serialized output. */ public JoinRel(RelInput input) { this( input.getCluster(), input.getInputs().get(0), input.getInputs().get(1), input.getExpression("condition"), input.getEnum("joinType", JoinRelType.class), ImmutableSet.<String>of(), false, ImmutableList.<RelDataTypeField>of()); } //~ Methods ---------------------------------------------------------------- @Override public JoinRel copy(RelTraitSet traitSet, RexNode conditionExpr, RelNode left, RelNode right, JoinRelType joinType, boolean semiJoinDone) { assert traitSet.containsIfApplicable(Convention.NONE); return new JoinRel( getCluster(), left, right, conditionExpr, joinType, this.variablesStopped, semiJoinDone, this.systemFieldList); } @Override public RelNode accept(RelShuttle shuttle) { return shuttle.visit(this); } public RelWriter explainTerms(RelWriter pw) { // Don't ever print semiJoinDone=false. This way, we // don't clutter things up in optimizers that don't use semi-joins. return super.explainTerms(pw) .itemIf("semiJoinDone", semiJoinDone, semiJoinDone); } @Override public boolean isSemiJoinDone() { return semiJoinDone; } public List<RelDataTypeField> getSystemFieldList() { return systemFieldList; } } // End JoinRel.java