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

org.apache.flink.table.plan.rules.logical.JoinConditionTypeCoerceRule.scala Maven / Gradle / Ivy

There is a newer version: 1.5.1
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 org.apache.flink.table.plan.rules.logical

import org.apache.flink.table.plan.util.FlinkRexUtil

import org.apache.calcite.plan.RelOptRule.{any, operand}
import org.apache.calcite.plan.{RelOptRule, RelOptRuleCall, RelOptUtil}
import org.apache.calcite.rel.`type`.RelDataTypeFactory
import org.apache.calcite.rel.core.Join
import org.apache.calcite.rex.{RexCall, RexInputRef, RexNode}
import org.apache.calcite.sql.SqlKind
import org.apache.calcite.sql.`type`.SqlTypeUtil

import scala.collection.JavaConversions._
import scala.collection.mutable

/**
  * This rule is used to coerce the both sides of EQUALS(`=`) operator in Join condition
  * to the same type while sans nullability.
  *
  * 

For most cases, we already did the type coercion during type validation by implicit * type coercion or during sqlNode to relNode conversion, this rule just does a rechecking * to ensure a strongly uniform equals type, so that during a HashJoin shuffle we can have * the same hashcode of the same value. */ class JoinConditionTypeCoerceRule extends RelOptRule( operand(classOf[Join], any), "JoinConditionTypeCoerceRule") { override def matches(call: RelOptRuleCall): Boolean = { val join: Join = call.rel(0) val dataTypeFactory = call.builder().getTypeFactory hasEqualsRefsOfDifferentTypes( dataTypeFactory, join.getCondition) } override def onMatch(call: RelOptRuleCall): Unit = { val join: Join = call.rel(0) val cond = join.getCondition val builder = call.builder() val rexBuilder = builder.getRexBuilder val dataTypeFactory = builder.getTypeFactory if (cond.isAlwaysTrue) { return } val newJoinFilters = mutable.ArrayBuffer[RexNode]() val joinFilters = RelOptUtil.conjunctions(join.getCondition) joinFilters.foreach { case c: RexCall if c.isA(SqlKind.EQUALS) => (c.operands.head, c.operands.last) match { case (ref1: RexInputRef, ref2: RexInputRef) if !SqlTypeUtil.equalSansNullability( dataTypeFactory, ref1.getType, ref2.getType) => val refList = ref1 :: ref2 :: Nil val targetType = rexBuilder.getTypeFactory.leastRestrictive( refList.map(ref => ref.getType)) newJoinFilters += builder.equals( rexBuilder.ensureType(targetType, ref1, true), rexBuilder.ensureType(targetType, ref2, true)) case _ => newJoinFilters += c } case f: RexNode => newJoinFilters += f } val newCondExp = builder.and( FlinkRexUtil.simplify(rexBuilder, builder.and(newJoinFilters))) val newJoinRel = join.copy( join.getTraitSet, newCondExp, join.getLeft, join.getRight, join.getJoinType, join.isSemiJoinDone) call.transformTo(newJoinRel) } private def hasEqualsRefsOfDifferentTypes( typeFactory: RelDataTypeFactory, node: RexNode): Boolean = { val joinFilters = RelOptUtil.conjunctions(node) joinFilters.exists { case c: RexCall if c.isA(SqlKind.EQUALS) => (c.operands.head, c.operands.last) match { case (ref1: RexInputRef, ref2: RexInputRef) => !SqlTypeUtil.equalSansNullability( typeFactory, ref1.getType, ref2.getType) case _ => false } case _ => false } } } object JoinConditionTypeCoerceRule { val INSTANCE = new JoinConditionTypeCoerceRule }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy