org.apache.flink.table.planner.plan.nodes.physical.batch.BatchPhysicalCalcBase.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of flink-table-planner-blink_2.11 Show documentation
Show all versions of flink-table-planner-blink_2.11 Show documentation
This module bridges Table/SQL API and runtime. It contains
all resources that are required during pre-flight and runtime
phase. The content of this module is work-in-progress. It will
replace flink-table-planner once it is stable. See FLINK-11439
and FLIP-32 for more details.
/*
* 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.flink.table.planner.plan.nodes.physical.batch
import org.apache.flink.table.planner.plan.`trait`.{FlinkRelDistribution, FlinkRelDistributionTraitDef, TraitUtil}
import org.apache.flink.table.planner.plan.nodes.common.CommonCalc
import org.apache.calcite.plan._
import org.apache.calcite.rel._
import org.apache.calcite.rel.`type`.RelDataType
import org.apache.calcite.rel.core.Calc
import org.apache.calcite.rex.{RexCall, RexInputRef, RexProgram}
import org.apache.calcite.sql.SqlKind
import org.apache.calcite.util.mapping.{Mapping, MappingType, Mappings}
import scala.collection.JavaConversions._
/**
* Base batch physical RelNode for [[Calc]].
*/
abstract class BatchPhysicalCalcBase(
cluster: RelOptCluster,
traitSet: RelTraitSet,
inputRel: RelNode,
calcProgram: RexProgram,
outputRowType: RelDataType)
extends CommonCalc(cluster, traitSet, inputRel, calcProgram)
with BatchPhysicalRel {
override def deriveRowType(): RelDataType = outputRowType
override def satisfyTraits(requiredTraitSet: RelTraitSet): Option[RelNode] = {
val requiredDistribution = requiredTraitSet.getTrait(FlinkRelDistributionTraitDef.INSTANCE)
// Does not push broadcast distribution trait down into Calc.
if (requiredDistribution.getType == RelDistribution.Type.BROADCAST_DISTRIBUTED) {
return None
}
val projects = calcProgram.getProjectList.map(calcProgram.expandLocalRef)
def getProjectMapping: Mapping = {
val mapping = Mappings.create(MappingType.INVERSE_FUNCTION,
getInput.getRowType.getFieldCount, projects.size)
projects.zipWithIndex.foreach {
case (project, index) =>
project match {
case inputRef: RexInputRef => mapping.set(inputRef.getIndex, index)
case call: RexCall if call.getKind == SqlKind.AS =>
call.getOperands.head match {
case inputRef: RexInputRef => mapping.set(inputRef.getIndex, index)
case _ => // ignore
}
case _ => // ignore
}
}
mapping.inverse()
}
val mapping = getProjectMapping
val appliedDistribution = requiredDistribution.apply(mapping)
// If both distribution and collation can be satisfied, satisfy both. If only distribution
// can be satisfied, only satisfy distribution. There is no possibility to only satisfy
// collation here except for there is no distribution requirement.
if ((!requiredDistribution.isTop) && (appliedDistribution eq FlinkRelDistribution.ANY)) {
return None
}
val requiredCollation = requiredTraitSet.getTrait(RelCollationTraitDef.INSTANCE)
val appliedCollation = TraitUtil.apply(requiredCollation, mapping)
val canCollationPushedDown = !appliedCollation.getFieldCollations.isEmpty
// If required traits only contains collation requirements, but collation keys are not columns
// from input, then no need to satisfy required traits.
if ((appliedDistribution eq FlinkRelDistribution.ANY) && !canCollationPushedDown) {
return None
}
var inputRequiredTraits = getInput.getTraitSet
var providedTraits = getTraitSet
if (!appliedDistribution.isTop) {
inputRequiredTraits = inputRequiredTraits.replace(appliedDistribution)
providedTraits = providedTraits.replace(requiredDistribution)
}
if (canCollationPushedDown) {
inputRequiredTraits = inputRequiredTraits.replace(appliedCollation)
providedTraits = providedTraits.replace(requiredCollation)
}
val newInput = RelOptRule.convert(getInput, inputRequiredTraits)
Some(copy(providedTraits, Seq(newInput)))
}
}