Skip to content

Commit

Permalink
KE-11534 [Follow up]KE-42084 merge with new Calcite
Browse files Browse the repository at this point in the history
  • Loading branch information
gleonSun committed Aug 25, 2023
1 parent c24cdda commit 8ab4d43
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 75 deletions.
26 changes: 23 additions & 3 deletions core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
Original file line number Diff line number Diff line change
Expand Up @@ -1005,9 +1005,29 @@ public static int plus(int b0, int b1) {
return (b0 == null || b1 == null) ? castNonNull(null) : b0.add(b1);
}

/** SQL <code>+</code> operator applied to String values. Same as string concat operator. */
public static String plus(String s0, String s1) {
return s0 + s1;
// see https://olapio.atlassian.net/browse/KE-42084
public static Double plus(String s0, String s1) {
try {
return plus(toBigDecimal(s0), toBigDecimal(s1)).doubleValue();
} catch (NumberFormatException ignored) {
return null;
}
}

public static Double plus(String s0, BigDecimal b1) {
try {
return plus(toBigDecimal(s0), b1).doubleValue();
} catch (NumberFormatException ignored) {
return null;
}
}

public static Double plus(String s0, Number b1) {
return plus(s0, toBigDecimal(b1));
}

public static Double plus(Number b1, String s0) {
return plus(s0, toBigDecimal(b1));
}

/** SQL <code>+</code> operator applied to Object values (at least one operand
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,11 @@
package org.apache.calcite.sql.fun;

import org.apache.calcite.avatica.util.TimeUnit;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.sql.SqlAggFunction;
import org.apache.calcite.sql.SqlAsOperator;
import org.apache.calcite.sql.SqlBasicCall;
import org.apache.calcite.sql.SqlBinaryOperator;
import org.apache.calcite.sql.SqlCall;
import org.apache.calcite.sql.SqlCharStringLiteral;
import org.apache.calcite.sql.SqlDescriptorOperator;
import org.apache.calcite.sql.SqlFilterOperator;
import org.apache.calcite.sql.SqlFunction;
Expand All @@ -41,7 +39,6 @@
import org.apache.calcite.sql.SqlNumericLiteral;
import org.apache.calcite.sql.SqlOperandCountRange;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.SqlOperatorBinding;
import org.apache.calcite.sql.SqlOverOperator;
import org.apache.calcite.sql.SqlPostfixOperator;
import org.apache.calcite.sql.SqlPrefixOperator;
Expand All @@ -65,12 +62,9 @@
import org.apache.calcite.sql.type.ReturnTypes;
import org.apache.calcite.sql.type.SqlOperandCountRanges;
import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.calcite.sql.type.SqlTypeUtil;
import org.apache.calcite.sql.util.ReflectiveSqlOperatorTable;
import org.apache.calcite.sql.validate.SqlConformance;
import org.apache.calcite.sql.validate.SqlModality;
import org.apache.calcite.sql.validate.SqlValidator;
import org.apache.calcite.sql.validate.SqlValidatorScope;
import org.apache.calcite.sql2rel.AuxiliaryConverter;
import org.apache.calcite.util.Litmus;
import org.apache.calcite.util.Optionality;
Expand Down Expand Up @@ -591,46 +585,7 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
true,
ReturnTypes.NULLABLE_SUM,
InferTypes.FIRST_KNOWN,
OperandTypes.PLUS_OPERATOR) {
@Override public void validateCall(SqlCall call,
SqlValidator validator,
SqlValidatorScope scope,
SqlValidatorScope operandScope) {
super.validateCall(call, validator, scope, operandScope);
if (call.getOperator() == SqlStdOperatorTable.PLUS) {
RelDataType type1 = validator.deriveType(scope, call.getOperandList().get(0));
RelDataType type2 = validator.deriveType(scope, call.getOperandList().get(1));
if (SqlTypeUtil.isNumeric(type1) && SqlTypeUtil.inStringFamily(type2)) {
return;
}
if (SqlTypeUtil.isNumeric(type2) && SqlTypeUtil.inStringFamily(type1)) {
return;
}
}
for (SqlNode operand : call.getOperandList()) {
if (operand instanceof SqlCharStringLiteral
&& SqlTypeName.STRING_TYPES.contains(((SqlCharStringLiteral) operand).getTypeName())
&& call instanceof SqlBasicCall) {
((SqlBasicCall) call).setOperator(CONCAT);
break;
}
}
}

@Override public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
RelDataType relDataType = ReturnTypes.NULLABLE_SUM.inferReturnType(opBinding);
if (relDataType != null) {
return relDataType;
}
int opBindCnt = opBinding.getOperandCount();
for (int i = 0; i < opBindCnt; i++) {
if (SqlTypeUtil.inCharOrBinaryFamilies(opBinding.getOperandType(i))) {
return ReturnTypes.DYADIC_STRING_SUM_PRECISION_NULLABLE.inferReturnType(opBinding);
}
}
return null;
}
};
OperandTypes.PLUS_OPERATOR);

/**
* Infix datetime plus operator, '<code>DATETIME + INTERVAL</code>'.
Expand Down
42 changes: 22 additions & 20 deletions core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -153,25 +153,27 @@ public static SqlCall stripSeparator(SqlCall call) {
}

/**
* Type-inference strategy for calculation between Decimal and String.
* Type-inference strategy for calculation between Decimal/String and String.
*
*/
public static final SqlReturnTypeInference NUMERIC_STRING =
new SqlReturnTypeInference() {
public RelDataType inferReturnType(
SqlOperatorBinding opBinding) {
RelDataType type1 = opBinding.getOperandType(0);
RelDataType type2 = opBinding.getOperandType(1);
final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
if (SqlTypeUtil.isNumeric(type1) && SqlTypeUtil.inStringFamily(type2)) {
return typeFactory.copyType(type1);
}
if (SqlTypeUtil.isNumeric(type2) && SqlTypeUtil.inStringFamily(type1)) {
return typeFactory.copyType(type2);
}
return null;
public static final SqlReturnTypeInference STRING_ARITHMETIC =
opBinding -> {
RelDataType type1 = opBinding.getOperandType(0);
RelDataType type2 = opBinding.getOperandType(1);
if (SqlTypeUtil.inCharFamily(type1) && SqlTypeUtil.inCharFamily(type2)
&& opBinding.getOperator().getKind() == SqlKind.PLUS
&& Boolean.parseBoolean(
System.getProperty("calcite.compatible-with-mssql-plus", "false"))) {
return ReturnTypes.DYADIC_STRING_SUM_PRECISION_NULLABLE.inferReturnType(opBinding);
}
};
if (SqlTypeUtil.inCharFamily(type1) || SqlTypeUtil.inCharFamily(type2)) {
RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
return typeFactory.createTypeWithNullability(
typeFactory.createSqlType(SqlTypeName.DOUBLE), true);
}
return null;
};

/**
* Type-inference strategy whereby the result type of a call is the type of
* the operand #0 (0-based).
Expand Down Expand Up @@ -661,7 +663,7 @@ public RelDataType inferReturnType(
*/
public static final SqlReturnTypeInference PRODUCT_NULLABLE =
DECIMAL_PRODUCT_NULLABLE.orElse(ARG0_INTERVAL_NULLABLE)
.orElse(LEAST_RESTRICTIVE).orElse(NUMERIC_STRING);
.orElse(STRING_ARITHMETIC).orElse(LEAST_RESTRICTIVE);

/**
* Type-inference strategy whereby the result type of a call is the decimal
Expand Down Expand Up @@ -709,8 +711,8 @@ public RelDataType inferReturnType(
*/
public static final SqlReturnTypeInference QUOTIENT_NULLABLE =
DECIMAL_QUOTIENT_NULLABLE.orElse(DOUBLE_QUOTIENT_NULLABLE)
.orElse(ARG0_INTERVAL_NULLABLE).orElse(LEAST_RESTRICTIVE)
.orElse(NUMERIC_STRING);
.orElse(ARG0_INTERVAL_NULLABLE).orElse(STRING_ARITHMETIC)
.orElse(LEAST_RESTRICTIVE);

/**
* Type-inference strategy whereby the result type of a call is the decimal
Expand Down Expand Up @@ -738,7 +740,7 @@ public RelDataType inferReturnType(
* These rules are used for addition and subtraction.
*/
public static final SqlReturnTypeInference NULLABLE_SUM =
new SqlReturnTypeInferenceChain(DECIMAL_SUM_NULLABLE, LEAST_RESTRICTIVE, NUMERIC_STRING);
new SqlReturnTypeInferenceChain(DECIMAL_SUM_NULLABLE, STRING_ARITHMETIC, LEAST_RESTRICTIVE);

public static final SqlReturnTypeInference DECIMAL_MOD = opBinding -> {
RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1640,10 +1640,6 @@ public static boolean isArray(RelDataType type) {
return type.getSqlTypeName() == SqlTypeName.ARRAY;
}

public static boolean inStringFamily(RelDataType type) {
return SqlTypeFamily.STRING.getTypeNames().contains(type.getSqlTypeName());
}

/** Returns whether a type is ROW. */
public static boolean isRow(RelDataType type) {
SqlTypeName typeName = type.getSqlTypeName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1269,14 +1269,14 @@ private RexNode convertPlus(
@UnknownInitialization StandardConvertletTable this,
SqlRexContext cx, SqlCall call) {
final RexNode rex = convertCall(cx, call);
final RexBuilder rexBuilder = cx.getRexBuilder();
List<RexNode> operands = ((RexCall) rex).getOperands();
switch (rex.getType().getSqlTypeName()) {
case DATE:
case TIME:
case TIMESTAMP:
// Use special "+" operator for datetime + interval.
// Re-order operands, if necessary, so that interval is second.
final RexBuilder rexBuilder = cx.getRexBuilder();
List<RexNode> operands = ((RexCall) rex).getOperands();
if (operands.size() == 2) {
final SqlTypeName sqlTypeName = operands.get(0).getType().getSqlTypeName();
switch (sqlTypeName) {
Expand All @@ -1301,6 +1301,9 @@ private RexNode convertPlus(
}
return rexBuilder.makeCall(rex.getType(),
SqlStdOperatorTable.DATETIME_PLUS, operands);
case CHAR:
case VARCHAR:
return rexBuilder.makeCall(rex.getType(), SqlStdOperatorTable.CONCAT, operands);
default:
return rex;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ public static boolean allAssignable(boolean varArgs, Class[] parameterTypes,
@SuppressWarnings("nullness")
private static boolean assignableFrom(Class parameter, Class argument) {
return parameter.isAssignableFrom(argument)
|| argument.isPrimitive() && parameter.isAssignableFrom(Primitive.box(argument))
|| parameter.isPrimitive()
&& argument.isPrimitive()
&& Primitive.of(parameter).assignableFrom(Primitive.of(argument));
Expand Down

0 comments on commit 8ab4d43

Please sign in to comment.