org.apache.flink.table.expressions.comparison.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_2.11 Show documentation
Show all versions of flink-table-planner_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 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.expressions
import org.apache.calcite.rex.RexNode
import org.apache.calcite.sql.SqlOperator
import org.apache.calcite.sql.fun.SqlStdOperatorTable
import org.apache.calcite.tools.RelBuilder
import org.apache.flink.api.common.typeinfo.BasicTypeInfo._
import org.apache.flink.api.common.typeinfo.{BasicTypeInfo, TypeInformation}
import org.apache.flink.table.typeutils.TypeCheckUtils.{isArray, isComparable, isNumeric}
import org.apache.flink.table.validate._
import scala.collection.JavaConversions._
abstract class BinaryComparison extends BinaryExpression {
private[flink] def sqlOperator: SqlOperator
override private[flink] def toRexNode(implicit relBuilder: RelBuilder): RexNode = {
relBuilder.call(sqlOperator, children.map(_.toRexNode))
}
override private[flink] def resultType = BOOLEAN_TYPE_INFO
override private[flink] def validateInput(): ValidationResult =
(left.resultType, right.resultType) match {
case (lType, rType) if isNumeric(lType) && isNumeric(rType) => ValidationSuccess
case (lType, rType) if isComparable(lType) && lType == rType => ValidationSuccess
case (lType, rType) =>
ValidationFailure(
s"Comparison is only supported for numeric types and " +
s"comparable types of same type, got $lType and $rType")
}
}
case class EqualTo(left: PlannerExpression, right: PlannerExpression) extends BinaryComparison {
override def toString = s"$left === $right"
private[flink] val sqlOperator: SqlOperator = SqlStdOperatorTable.EQUALS
override private[flink] def validateInput(): ValidationResult =
(left.resultType, right.resultType) match {
case (lType, rType) if isNumeric(lType) && isNumeric(rType) => ValidationSuccess
case (lType, rType) if lType == rType => ValidationSuccess
case (lType, rType) if isArray(lType) && lType.getTypeClass == rType.getTypeClass =>
ValidationSuccess
case (lType, rType) =>
ValidationFailure(s"Equality predicate on incompatible types: $lType and $rType")
}
}
case class NotEqualTo(left: PlannerExpression, right: PlannerExpression) extends BinaryComparison {
override def toString = s"$left !== $right"
private[flink] val sqlOperator: SqlOperator = SqlStdOperatorTable.NOT_EQUALS
override private[flink] def validateInput(): ValidationResult =
(left.resultType, right.resultType) match {
case (lType, rType) if isNumeric(lType) && isNumeric(rType) => ValidationSuccess
case (lType, rType) if lType == rType => ValidationSuccess
case (lType, rType) if isArray(lType) && lType.getTypeClass == rType.getTypeClass =>
ValidationSuccess
case (lType, rType) =>
ValidationFailure(s"Inequality predicate on incompatible types: $lType and $rType")
}
}
case class GreaterThan(left: PlannerExpression, right: PlannerExpression) extends BinaryComparison {
override def toString = s"$left > $right"
private[flink] val sqlOperator: SqlOperator = SqlStdOperatorTable.GREATER_THAN
}
case class GreaterThanOrEqual(left: PlannerExpression, right: PlannerExpression)
extends BinaryComparison {
override def toString = s"$left >= $right"
private[flink] val sqlOperator: SqlOperator = SqlStdOperatorTable.GREATER_THAN_OR_EQUAL
}
case class LessThan(left: PlannerExpression, right: PlannerExpression) extends BinaryComparison {
override def toString = s"$left < $right"
private[flink] val sqlOperator: SqlOperator = SqlStdOperatorTable.LESS_THAN
}
case class LessThanOrEqual(left: PlannerExpression, right: PlannerExpression)
extends BinaryComparison {
override def toString = s"$left <= $right"
private[flink] val sqlOperator: SqlOperator = SqlStdOperatorTable.LESS_THAN_OR_EQUAL
}
case class IsNull(child: PlannerExpression) extends UnaryExpression {
override def toString = s"($child).isNull"
override private[flink] def toRexNode(implicit relBuilder: RelBuilder): RexNode = {
relBuilder.isNull(child.toRexNode)
}
override private[flink] def resultType = BOOLEAN_TYPE_INFO
}
case class IsNotNull(child: PlannerExpression) extends UnaryExpression {
override def toString = s"($child).isNotNull"
override private[flink] def toRexNode(implicit relBuilder: RelBuilder): RexNode = {
relBuilder.isNotNull(child.toRexNode)
}
override private[flink] def resultType = BOOLEAN_TYPE_INFO
}
case class IsTrue(child: PlannerExpression) extends UnaryExpression {
override def toString = s"($child).isTrue"
override private[flink] def toRexNode(implicit relBuilder: RelBuilder): RexNode = {
relBuilder.call(SqlStdOperatorTable.IS_TRUE, child.toRexNode)
}
override private[flink] def resultType = BOOLEAN_TYPE_INFO
}
case class IsFalse(child: PlannerExpression) extends UnaryExpression {
override def toString = s"($child).isFalse"
override private[flink] def toRexNode(implicit relBuilder: RelBuilder): RexNode = {
relBuilder.call(SqlStdOperatorTable.IS_FALSE, child.toRexNode)
}
override private[flink] def resultType = BOOLEAN_TYPE_INFO
}
case class IsNotTrue(child: PlannerExpression) extends UnaryExpression {
override def toString = s"($child).isNotTrue"
override private[flink] def toRexNode(implicit relBuilder: RelBuilder): RexNode = {
relBuilder.call(SqlStdOperatorTable.IS_NOT_TRUE, child.toRexNode)
}
override private[flink] def resultType = BOOLEAN_TYPE_INFO
}
case class IsNotFalse(child: PlannerExpression) extends UnaryExpression {
override def toString = s"($child).isNotFalse"
override private[flink] def toRexNode(implicit relBuilder: RelBuilder): RexNode = {
relBuilder.call(SqlStdOperatorTable.IS_NOT_FALSE, child.toRexNode)
}
override private[flink] def resultType = BOOLEAN_TYPE_INFO
}
abstract class BetweenComparison(
expr: PlannerExpression,
lowerBound: PlannerExpression,
upperBound: PlannerExpression)
extends PlannerExpression {
override private[flink] def resultType: TypeInformation[_] = BasicTypeInfo.BOOLEAN_TYPE_INFO
override private[flink] def children: Seq[PlannerExpression] = Seq(expr, lowerBound, upperBound)
override private[flink] def validateInput(): ValidationResult = {
(expr.resultType, lowerBound.resultType, upperBound.resultType) match {
case (exprType, lowerType, upperType)
if isNumeric(exprType) && isNumeric(lowerType) && isNumeric(upperType) =>
ValidationSuccess
case (exprType, lowerType, upperType)
if isComparable(exprType) && exprType == lowerType && exprType == upperType =>
ValidationSuccess
case (exprType, lowerType, upperType) =>
ValidationFailure(
s"Between is only supported for numeric types and " +
s"identical comparable types, but got $exprType, $lowerType and $upperType"
)
}
}
}
case class Between(
expr: PlannerExpression,
lowerBound: PlannerExpression,
upperBound: PlannerExpression)
extends BetweenComparison(expr, lowerBound, upperBound) {
override def toString: String = s"($expr).between($lowerBound, $upperBound)"
override private[flink] def toRexNode(implicit relBuilder: RelBuilder): RexNode = {
relBuilder.and(
relBuilder.call(
SqlStdOperatorTable.GREATER_THAN_OR_EQUAL,
expr.toRexNode,
lowerBound.toRexNode
),
relBuilder.call(
SqlStdOperatorTable.LESS_THAN_OR_EQUAL,
expr.toRexNode,
upperBound.toRexNode
)
)
}
}
case class NotBetween(
expr: PlannerExpression,
lowerBound: PlannerExpression,
upperBound: PlannerExpression)
extends BetweenComparison(expr, lowerBound, upperBound) {
override def toString: String = s"($expr).notBetween($lowerBound, $upperBound)"
override private[flink] def toRexNode(implicit relBuilder: RelBuilder): RexNode = {
relBuilder.or(
relBuilder.call(
SqlStdOperatorTable.LESS_THAN,
expr.toRexNode,
lowerBound.toRexNode
),
relBuilder.call(
SqlStdOperatorTable.GREATER_THAN,
expr.toRexNode,
upperBound.toRexNode
)
)
}
}