|
14 | 14 | import org.apache.calcite.rex.RexBuilder; |
15 | 15 | import org.apache.calcite.rex.RexLiteral; |
16 | 16 | import org.apache.calcite.rex.RexNode; |
| 17 | +import org.apache.calcite.sql.SqlCallBinding; |
17 | 18 | import org.apache.calcite.sql.SqlIntervalQualifier; |
| 19 | +import org.apache.calcite.sql.SqlKind; |
| 20 | +import org.apache.calcite.sql.SqlOperator; |
18 | 21 | import org.apache.calcite.sql.fun.SqlStdOperatorTable; |
19 | 22 | import org.apache.calcite.sql.parser.SqlParserPos; |
20 | 23 | import org.apache.calcite.sql.type.SqlTypeName; |
21 | 24 | import org.apache.calcite.sql.type.SqlTypeUtil; |
| 25 | +import org.apache.calcite.sql.validate.implicit.TypeCoercionImpl; |
22 | 26 | import org.opensearch.sql.ast.expression.SpanUnit; |
23 | 27 | import org.opensearch.sql.calcite.type.AbstractExprRelDataType; |
24 | 28 | import org.opensearch.sql.calcite.utils.OpenSearchTypeFactory; |
@@ -185,4 +189,34 @@ else if ((SqlTypeUtil.isApproximateNumeric(sourceType) || SqlTypeUtil.isDecimal( |
185 | 189 | } |
186 | 190 | return super.makeCast(pos, type, exp, matchNullability, safe, format); |
187 | 191 | } |
| 192 | + |
| 193 | + /** |
| 194 | + * Derives the return type of call to an operator. |
| 195 | + * |
| 196 | + * <p>In Calcite, coercion between STRING and NUMERIC operands takes place during converting SQL |
| 197 | + * to RelNode. However, as we are building logical plans directly, the coercion is not yet |
| 198 | + * implemented at this point. Hence, we duplicate {@link |
| 199 | + * TypeCoercionImpl#binaryArithmeticWithStrings} here to infer the correct type, enabling |
| 200 | + * operations like {@code "5" / 10}. The actual coercion will be inserted later when performing |
| 201 | + * validation on SqlNode. |
| 202 | + * |
| 203 | + * @see TypeCoercionImpl#binaryArithmeticCoercion(SqlCallBinding) |
| 204 | + * @param op the operator being called |
| 205 | + * @param exprs actual operands |
| 206 | + * @return derived type |
| 207 | + */ |
| 208 | + @Override |
| 209 | + public RelDataType deriveReturnType(SqlOperator op, List<? extends RexNode> exprs) { |
| 210 | + if (op.getKind().belongsTo(SqlKind.BINARY_ARITHMETIC) && exprs.size() == 2) { |
| 211 | + final RelDataType type1 = exprs.get(0).getType(); |
| 212 | + final RelDataType type2 = exprs.get(1).getType(); |
| 213 | + if (OpenSearchTypeFactory.isNumericType(type1) && OpenSearchTypeFactory.isCharacter(type2)) { |
| 214 | + return type1; |
| 215 | + } else if (OpenSearchTypeFactory.isCharacter(type1) |
| 216 | + && OpenSearchTypeFactory.isNumericType(type2)) { |
| 217 | + return type2; |
| 218 | + } |
| 219 | + } |
| 220 | + return super.deriveReturnType(op, exprs); |
| 221 | + } |
188 | 222 | } |
0 commit comments