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

org.apache.flink.table.planner.plan.rules.common.CommonTemporalTableJoinRule.scala Maven / Gradle / Ivy

/*
 * 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.rules.common

import org.apache.flink.table.api.TableException
import org.apache.flink.table.connector.source.LookupTableSource
import org.apache.flink.table.planner.plan.nodes.logical.{FlinkLogicalLegacyTableSourceScan, FlinkLogicalRel, FlinkLogicalSnapshot, FlinkLogicalTableSourceScan}
import org.apache.flink.table.planner.plan.nodes.physical.stream.{StreamPhysicalLookupJoin, StreamPhysicalTemporalJoin}
import org.apache.flink.table.planner.plan.schema.{LegacyTableSourceTable, TableSourceTable, TimeIndicatorRelDataType}
import org.apache.flink.table.sources.LookupableTableSource

import org.apache.calcite.plan.hep.HepRelVertex
import org.apache.calcite.rel.RelNode
import org.apache.calcite.rel.core.TableScan
import org.apache.calcite.rel.logical.{LogicalProject, LogicalTableScan}
import org.apache.calcite.rex.{RexCorrelVariable, RexFieldAccess}

/**
  * Base implementation that matches temporal join node.
  *
  * 

The initial temporal table join (FOR SYSTEM_TIME AS OF) is a Correlate, rewrite it into * a Join to make join condition can be pushed-down. The join will be translated into * [[StreamPhysicalLookupJoin]] in physical or translated into [[StreamPhysicalTemporalJoin]]. */ trait CommonTemporalTableJoinRule { protected def matches(snapshot: FlinkLogicalSnapshot): Boolean = { // period specification check snapshot.getPeriod match { // it should be left table's field and is a time attribute case r: RexFieldAccess if r.getType.isInstanceOf[TimeIndicatorRelDataType] && r.getReferenceExpr.isInstanceOf[RexCorrelVariable] => // pass case _ => throw new TableException("Temporal table join currently only supports " + "'FOR SYSTEM_TIME AS OF' left table's time attribute field.") } true } protected def canConvertToLookupJoin( snapshot: FlinkLogicalSnapshot, snapshotInput: FlinkLogicalRel): Boolean = { val isProcessingTime = snapshot.getPeriod.getType match { case t: TimeIndicatorRelDataType if !t.isEventTime => true case _ => false } val tableScan = getTableScan(snapshotInput) val snapshotOnLookupSource = tableScan match { case Some(scan) => isTableSourceScan(scan) && isLookupTableSource(scan) case _ => false } isProcessingTime && snapshotOnLookupSource } private def getTableScan(snapshotInput: RelNode): Option[TableScan] = { snapshotInput match { case tableScan: TableScan => Some(tableScan) // computed column on lookup table case project: LogicalProject if trimHep(project.getInput).isInstanceOf[TableScan] => Some(trimHep(project.getInput).asInstanceOf[TableScan]) case _ => None } } private def isTableSourceScan(relNode: RelNode): Boolean = { relNode match { case r: LogicalTableScan => val table = r.getTable table match { case _: LegacyTableSourceTable[Any] | _: TableSourceTable => true case _ => false } case _: FlinkLogicalLegacyTableSourceScan | _: FlinkLogicalTableSourceScan => true case _ => false } } private def isLookupTableSource(relNode: RelNode): Boolean = relNode match { case scan: FlinkLogicalLegacyTableSourceScan => scan.tableSource.isInstanceOf[LookupableTableSource[_]] case scan: FlinkLogicalTableSourceScan => scan.tableSource.isInstanceOf[LookupTableSource] case scan: LogicalTableScan => scan.getTable match { case table: LegacyTableSourceTable[_] => table.tableSource.isInstanceOf[LookupableTableSource[_]] case table: TableSourceTable => table.tableSource.isInstanceOf[LookupTableSource] case _ => false } case _ => false } /** Trim out the HepRelVertex wrapper and get current relational expression. */ protected def trimHep(node: RelNode): RelNode = { node match { case hepRelVertex: HepRelVertex => hepRelVertex.getCurrentRel case _ => node } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy