This is an automated email from the ASF dual-hosted git repository.

jhyde pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git

commit bb94122fa43df86a2ef57fa375e3dc7792666eac
Author: Julian Hyde <[email protected]>
AuthorDate: Fri Jun 28 19:16:23 2024 -0700

    Rework [CALCITE-5869] LEAST_RESTRICTIVE does not use inner type of MEASURE 
for comparisons
---
 .../java/org/apache/calcite/sql/SqlOperator.java   |  6 ------
 .../org/apache/calcite/sql/SqlOperatorBinding.java | 22 ++++++++++++++++++++++
 .../calcite/sql/fun/SqlLibraryOperators.java       |  3 ++-
 .../org/apache/calcite/sql/type/ReturnTypes.java   | 16 ++++++++++++----
 .../apache/calcite/sql/type/SqlTypeTransform.java  |  5 +++++
 .../apache/calcite/sql/type/SqlTypeTransforms.java |  8 ++++++++
 6 files changed, 49 insertions(+), 11 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/sql/SqlOperator.java 
b/core/src/main/java/org/apache/calcite/sql/SqlOperator.java
index 58fc0e5b5b..342113b306 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlOperator.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlOperator.java
@@ -48,7 +48,6 @@ import java.util.Objects;
 import java.util.function.Supplier;
 
 import static org.apache.calcite.linq4j.Nullness.castNonNull;
-import static org.apache.calcite.sql.type.SqlTypeUtil.isMeasure;
 import static org.apache.calcite.util.Static.RESOURCE;
 
 import static java.util.Objects.requireNonNull;
@@ -538,11 +537,6 @@ public abstract class SqlOperator {
             + opBinding.collectOperandTypes());
       }
 
-      // MEASURE wrapper should be removed, e.g. MEASURE<DOUBLE> should just 
be DOUBLE
-      if (isMeasure(returnType) && returnType.getMeasureElementType() != null) 
{
-        returnType = 
Objects.requireNonNull(returnType.getMeasureElementType());
-      }
-
       if (operandTypeInference != null
           && opBinding instanceof SqlCallBinding
           && this instanceof SqlFunction) {
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlOperatorBinding.java 
b/core/src/main/java/org/apache/calcite/sql/SqlOperatorBinding.java
index 439ddb6ead..17c9e84e30 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlOperatorBinding.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlOperatorBinding.java
@@ -23,6 +23,7 @@ import org.apache.calcite.rel.type.RelDataTypeFactoryImpl;
 import org.apache.calcite.runtime.CalciteException;
 import org.apache.calcite.runtime.Resources;
 import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.sql.type.SqlTypeTransform;
 import org.apache.calcite.sql.validate.SqlMonotonicity;
 import org.apache.calcite.sql.validate.SqlValidatorException;
 import org.apache.calcite.util.NlsString;
@@ -299,4 +300,25 @@ public abstract class SqlOperatorBinding {
    */
   public abstract CalciteException newError(
       Resources.ExInst<SqlValidatorException> e);
+
+  /** Returns an operator binding equivalent that is equivalent to this
+   * except that a transform has been applied to each operand type. */
+  public SqlOperatorBinding transform(SqlTypeTransform typeTransform) {
+    final SqlOperatorBinding operatorBinding = this;
+    return new SqlOperatorBinding(typeFactory, sqlOperator) {
+      @Override public int getOperandCount() {
+        return operatorBinding.getOperandCount();
+      }
+
+      @Override public RelDataType getOperandType(int ordinal) {
+        return typeTransform.transformType(operatorBinding,
+            operatorBinding.getOperandType(ordinal));
+      }
+
+      @Override public CalciteException newError(
+          Resources.ExInst<SqlValidatorException> e) {
+        return operatorBinding.newError(e);
+      }
+    };
+  }
 }
diff --git 
a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java 
b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
index 8d98f3fbe3..7d7795b63b 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
@@ -98,7 +98,8 @@ public abstract class SqlLibraryOperators {
   @LibraryOperator(libraries = {CALCITE})
   public static final SqlFunction AGGREGATE =
       SqlBasicAggFunction.create("AGGREGATE", SqlKind.AGGREGATE_FN,
-          ReturnTypes.ARG0, OperandTypes.MEASURE);
+          ReturnTypes.ARG0.andThen(SqlTypeTransforms.FROM_MEASURE),
+          OperandTypes.MEASURE);
 
   /** The "CONVERT_TIMEZONE(tz1, tz2, datetime)" function;
    * converts the timezone of {@code datetime} from {@code tz1} to {@code tz2}.
diff --git a/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java 
b/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java
index f8aaff072c..ea8cd95cfa 100644
--- a/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java
+++ b/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java
@@ -34,6 +34,8 @@ import org.apache.calcite.sql.validate.SqlValidatorNamespace;
 import org.apache.calcite.util.Glossary;
 import org.apache.calcite.util.Util;
 
+import org.checkerframework.checker.nullness.qual.Nullable;
+
 import java.util.AbstractList;
 import java.util.Arrays;
 import java.util.List;
@@ -570,8 +572,14 @@ public abstract class ReturnTypes {
    * @see Glossary#SQL99 SQL:1999 Part 2 Section 9.3
    */
   public static final SqlReturnTypeInference LEAST_RESTRICTIVE =
-      opBinding -> opBinding.getTypeFactory().leastRestrictive(
-          opBinding.collectOperandTypes());
+      andThen(SqlTypeTransforms.FROM_MEASURE_IF::apply,
+          ReturnTypes::leastRestrictive);
+
+  private static @Nullable RelDataType leastRestrictive(
+      SqlOperatorBinding opBinding) {
+    return opBinding.getTypeFactory()
+        .leastRestrictive(opBinding.collectOperandTypes());
+  }
 
   /**
    * Type-inference strategy for NVL2 function. It returns the least 
restrictive type
@@ -1412,6 +1420,6 @@ public abstract class ReturnTypes {
     }
   };
 
-  public static final SqlReturnTypeInference PERCENTILE_DISC_CONT = opBinding 
->
-      opBinding.getCollationType();
+  public static final SqlReturnTypeInference PERCENTILE_DISC_CONT =
+      SqlOperatorBinding::getCollationType;
 }
diff --git 
a/core/src/main/java/org/apache/calcite/sql/type/SqlTypeTransform.java 
b/core/src/main/java/org/apache/calcite/sql/type/SqlTypeTransform.java
index ffdd96812d..9c555080b1 100644
--- a/core/src/main/java/org/apache/calcite/sql/type/SqlTypeTransform.java
+++ b/core/src/main/java/org/apache/calcite/sql/type/SqlTypeTransform.java
@@ -44,4 +44,9 @@ public interface SqlTypeTransform {
   RelDataType transformType(
       SqlOperatorBinding opBinding,
       RelDataType typeToTransform);
+
+  /** Creates an operand type transform. */
+  default SqlOperatorBinding apply(SqlOperatorBinding operatorBinding) {
+    return operatorBinding.transform(this);
+  }
 }
diff --git 
a/core/src/main/java/org/apache/calcite/sql/type/SqlTypeTransforms.java 
b/core/src/main/java/org/apache/calcite/sql/type/SqlTypeTransforms.java
index 2004125261..0c3c064586 100644
--- a/core/src/main/java/org/apache/calcite/sql/type/SqlTypeTransforms.java
+++ b/core/src/main/java/org/apache/calcite/sql/type/SqlTypeTransforms.java
@@ -256,6 +256,14 @@ public abstract class SqlTypeTransforms {
       (opBinding, typeToTransform) ->
           ((MeasureSqlType) typeToTransform).types.get(0);
 
+  /** Parameter type-inference transform that transforms {@code MEASURE<T>} to
+   * {@code T} for some type T, and does nothing to other types. */
+  public static final SqlTypeTransform FROM_MEASURE_IF =
+      (opBinding, typeToTransform) ->
+          SqlTypeUtil.isMeasure(typeToTransform)
+              ? ((MeasureSqlType) typeToTransform).types.get(0)
+              : typeToTransform;
+
   /**
    * Parameter type-inference transform strategy that wraps a given type in an 
array or
    * wraps a field of the given type in an array if the given type is struct 
with one field.

Reply via email to