laurentgo commented on a change in pull request #1311: [CALCITE-3187] Make
decimal type inference overridable
URL: https://github.com/apache/calcite/pull/1311#discussion_r303104910
##########
File path:
core/src/main/java/org/apache/calcite/rel/type/RelDataTypeSystem.java
##########
@@ -100,6 +101,212 @@ RelDataType deriveCovarType(RelDataTypeFactory
typeFactory,
/** Whether the least restrictive type of a number of CHAR types of different
* lengths should be a VARCHAR type. And similarly BINARY to VARBINARY. */
boolean shouldConvertRaggedUnionTypesToVarying();
+
+ /**
+ * Infers the return type of a decimal addition. Decimal addition involves
+ * at least one decimal operand and requires both operands to have exact
+ * numeric types.
+ *
+ * @param type1 type of the first operand
+ * @param type2 type of the second operand
+ * @return the result type for a decimal addition.
+ */
+ default RelDataType deriveDecimalPlusType(RelDataTypeFactory typeFactory,
+ RelDataType type1, RelDataType
type2) {
+ /**
+ * Type-inference strategy whereby the result type of a call is the decimal
+ * sum of two exact numeric operands where at least one of the operands is
a
+ * decimal. Let p1, s1 be the precision and scale of the first operand Let
+ * p2, s2 be the precision and scale of the second operand Let p, s be the
+ * precision and scale of the result, Then the result type is a decimal
+ * with:
+ *
+ * <ul>
+ * <li>s = max(s1, s2)</li>
+ * <li>p = max(p1 - s1, p2 - s2) + s + 1</li>
+ * </ul>
+ *
+ * <p>p and s are capped at their maximum values
+ *
+ * @see Glossary#SQL2003 SQL:2003 Part 2 Section 6.26
+ */
+ if (SqlTypeUtil.isExactNumeric(type1)
+ && SqlTypeUtil.isExactNumeric(type2)) {
+ if (SqlTypeUtil.isDecimal(type1)
+ || SqlTypeUtil.isDecimal(type2)) {
+ int p1 = type1.getPrecision();
+ int p2 = type2.getPrecision();
+ int s1 = type1.getScale();
+ int s2 = type2.getScale();
+ int scale = Math.max(s1, s2);
+ assert scale <= getMaxNumericScale();
+ int precision = Math.max(p1 - s1, p2 - s2) + scale + 1;
+ precision =
+ Math.min(
+ precision,
+ getMaxNumericPrecision());
+ assert precision > 0;
+
+ return typeFactory.createSqlType(
+ SqlTypeName.DECIMAL,
+ precision,
+ scale);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Infers the return type of a decimal multiplication. Decimal
+ * multiplication involves at least one decimal operand and requires both
+ * operands to have exact numeric types.
+ *
+ * @param type1 type of the first operand
+ * @param type2 type of the second operand
+ * @return the result type for a decimal multiplication, or null if decimal
+ * multiplication should not be applied to the operands.
+ */
+ default RelDataType deriveDecimalMultiplyType(RelDataTypeFactory typeFactory,
+ RelDataType type1, RelDataType type2) {
+ /**
+ * <p>Implement RelDataTypeFactory with SQL 2003 compliant behavior. Let
p1,
+ * s1 be the precision and scale of the first operand Let p2, s2 be the
+ * precision and scale of the second operand Let p, s be the precision and
+ * scale of the result, Then the result type is a decimal with:
+ *
+ * <ul>
+ * <li>p = p1 + p2</li>
+ * <li>s = s1 + s2</li>
+ * </ul>
+ *
+ * <p>p and s are capped at their maximum values
+ *
+ * @see Glossary#SQL2003 SQL:2003 Part 2 Section 6.26
+ */
+ if (SqlTypeUtil.isExactNumeric(type1)
+ && SqlTypeUtil.isExactNumeric(type2)) {
+ if (SqlTypeUtil.isDecimal(type1)
+ || SqlTypeUtil.isDecimal(type2)) {
+ int p1 = type1.getPrecision();
+ int p2 = type2.getPrecision();
+ int s1 = type1.getScale();
+ int s2 = type2.getScale();
+
+ int scale = s1 + s2;
+ scale = Math.min(scale, getMaxNumericScale());
+ int precision = p1 + p2;
+ precision =
+ Math.min(
+ precision,
+ getMaxNumericPrecision());
+
+ RelDataType ret;
+ ret = typeFactory.createSqlType(
+ SqlTypeName.DECIMAL,
+ precision,
+ scale);
+
+ return ret;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Infers the return type of a decimal division. Decimal division involves
+ * at least one decimal operand and requires both operands to have exact
+ * numeric types.
+ *
+ * @param type1 type of the first operand
+ * @param type2 type of the second operand
+ * @return the result type for a decimal division, or null if decimal
+ * division should not be applied to the operands.
+ */
+ default RelDataType deriveDecimalDivideType(RelDataTypeFactory typeFactory,
+ RelDataType type1, RelDataType type2) {
+ /**
+ * Rules:
+ *
+ * <ul>
+ * <li>Let p1, s1 be the precision and scale of the first operand
+ * <li>Let p2, s2 be the precision and scale of the second operand
+ * <li>Let p, s be the precision and scale of the result
+ * <li>Let d be the number of whole digits in the result
+ * <li>Then the result type is a decimal with:
+ * <ul>
+ * <li>d = p1 - s1 + s2</li>
+ * <li>s < max(6, s1 + p2 + 1)</li>
+ * <li>p = d + s</li>
+ * </ul>
+ * </li>
+ * <li>p and s are capped at their maximum values</li>
+ * </ul>
+ *
+ * @see Glossary#SQL2003 SQL:2003 Part 2 Section 6.26
+ */
+ if (SqlTypeUtil.isExactNumeric(type1)
+ && SqlTypeUtil.isExactNumeric(type2)) {
+ if (SqlTypeUtil.isDecimal(type1)
+ || SqlTypeUtil.isDecimal(type2)) {
+ int p1 = type1.getPrecision();
+ int p2 = type2.getPrecision();
+ int s1 = type1.getScale();
+ int s2 = type2.getScale();
+
+ final int maxNumericPrecision = getMaxNumericPrecision();
+ int dout =
+ Math.min(
+ p1 - s1 + s2,
+ maxNumericPrecision);
+
+ int scale = Math.max(6, s1 + p2 + 1);
+ scale =
+ Math.min(
+ scale,
+ maxNumericPrecision - dout);
+ scale = Math.min(scale, getMaxNumericScale());
+
+ int precision = dout + scale;
+ assert precision <= maxNumericPrecision;
+ assert precision > 0;
+
+ RelDataType ret;
+ ret = typeFactory.
+ createSqlType(
+ SqlTypeName.DECIMAL,
+ precision,
+ scale);
+
+ return ret;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Infers the return type of a decimal mod operation. Decimal mod involves
+ * at least one decimal operand and requires both operands to have exact
+ * numeric types.
+ *
Review comment:
let's mention the rules too
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
With regards,
Apache Git Services