com.hazelcast.org.apache.calcite.sql.fun.SqlMonotonicBinaryOperator 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 com.hazelcast.org.apache.calcite.sql.fun;
import com.hazelcast.org.apache.calcite.sql.SqlBinaryOperator;
import com.hazelcast.org.apache.calcite.sql.SqlKind;
import com.hazelcast.org.apache.calcite.sql.SqlOperatorBinding;
import com.hazelcast.org.apache.calcite.sql.type.SqlOperandTypeChecker;
import com.hazelcast.org.apache.calcite.sql.type.SqlOperandTypeInference;
import com.hazelcast.org.apache.calcite.sql.type.SqlReturnTypeInference;
import com.hazelcast.org.apache.calcite.sql.validate.SqlMonotonicity;
import java.math.BigDecimal;
/**
* Base class for binary operators such as addition, subtraction, and
* multiplication which are monotonic for the patterns m op c
and
* c op m
where m is any monotonic expression and c is a constant.
*/
public class SqlMonotonicBinaryOperator extends SqlBinaryOperator {
//~ Constructors -----------------------------------------------------------
public SqlMonotonicBinaryOperator(
String name,
SqlKind kind,
int prec,
boolean isLeftAssoc,
SqlReturnTypeInference returnTypeInference,
SqlOperandTypeInference operandTypeInference,
SqlOperandTypeChecker operandTypeChecker) {
super(
name,
kind,
prec,
isLeftAssoc,
returnTypeInference,
operandTypeInference,
operandTypeChecker);
}
//~ Methods ----------------------------------------------------------------
@Override public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) {
final SqlMonotonicity mono0 = call.getOperandMonotonicity(0);
final SqlMonotonicity mono1 = call.getOperandMonotonicity(1);
// constant constant --> constant
if ((mono1 == SqlMonotonicity.CONSTANT)
&& (mono0 == SqlMonotonicity.CONSTANT)) {
return SqlMonotonicity.CONSTANT;
}
// monotonic constant
if (mono1 == SqlMonotonicity.CONSTANT) {
// mono0 + constant --> mono0
// mono0 - constant --> mono0
if (getName().equals("-")
|| getName().equals("+")) {
return mono0;
}
assert getName().equals("*");
BigDecimal value = call.getOperandLiteralValue(1, BigDecimal.class);
switch (value == null ? 1 : value.signum()) {
case -1:
// mono0 * negative constant --> reverse mono0
return mono0.reverse();
case 0:
// mono0 * 0 --> constant (zero)
return SqlMonotonicity.CONSTANT;
default:
// mono0 * positive constant --> mono0
return mono0;
}
}
// constant mono
if (mono0 == SqlMonotonicity.CONSTANT) {
if (getName().equals("-")) {
// constant - mono1 --> reverse mono1
return mono1.reverse();
}
if (getName().equals("+")) {
// constant + mono1 --> mono1
return mono1;
}
assert getName().equals("*");
if (!call.isOperandNull(0, true)) {
BigDecimal value = call.getOperandLiteralValue(0, BigDecimal.class);
switch (value == null ? 1 : value.signum()) {
case -1:
// negative constant * mono1 --> reverse mono1
return mono1.reverse();
case 0:
// 0 * mono1 --> constant (zero)
return SqlMonotonicity.CONSTANT;
default:
// positive constant * mono1 --> mono1
return mono1;
}
}
}
// strictly asc + strictly asc --> strictly asc
// e.g. 2 * orderid + 3 * orderid
// is strictly increasing if orderid is strictly increasing
// asc + asc --> asc
// e.g. 2 * orderid + 3 * orderid
// is increasing if orderid is increasing
// asc + desc --> not monotonic
// e.g. 2 * orderid + (-3 * orderid) is not monotonic
if (getName().equals("+")) {
if (mono0 == mono1) {
return mono0;
} else if (mono0.unstrict() == mono1.unstrict()) {
return mono0.unstrict();
} else {
return SqlMonotonicity.NOT_MONOTONIC;
}
}
if (getName().equals("-")) {
if (mono0 == mono1.reverse()) {
return mono0;
} else if (mono0.unstrict() == mono1.reverse().unstrict()) {
return mono0.unstrict();
} else {
return SqlMonotonicity.NOT_MONOTONIC;
}
}
if (getName().equals("*")) {
return SqlMonotonicity.NOT_MONOTONIC;
}
return super.getMonotonicity(call);
}
}