Lantao Jin created CALCITE-7858:
-----------------------------------

             Summary: ARG_MIN, ARG_MAX, MIN_BY and MAX_BY accept a 
non-comparable key because OperandTypes.ANY_COMPARABLE never fails
                 Key: CALCITE-7858
                 URL: https://issues.apache.org/jira/browse/CALCITE-7858
             Project: Calcite
          Issue Type: Bug
          Components: core
    Affects Versions: 1.42.0, 1.33.0
            Reporter: Lantao Jin


h2. Problem

{{ARG_MIN(value, key)}} and {{ARG_MAX(value, key)}} (and their aliases 
{{MIN_BY}} / {{MAX_BY}}) require their second operand to be comparable, but the 
validator never enforces it. A key whose type has comparability {{NONE}} (for 
example a structured type defined by a catalog, such as {{ObjectSqlType}} with 
{{RelDataTypeComparability.NONE}}) passes validation, although {{MIN}} and 
{{MAX}} reject the same type with a clear validation error.

h2. Cause

{{OperandTypes.ANY_COMPARABLE}}, the operand checker of these functions, 
returns {{false}} for a non-comparable second operand but never throws, 
whatever {{throwOnFailure}} is:

{code:java}
public static final SqlOperandTypeChecker ANY_COMPARABLE =
    new SqlOperandTypeChecker() {
      @Override public boolean checkOperandTypes(SqlCallBinding callBinding,
          boolean throwOnFailure) {
        getOperandCountRange().isValidCount(callBinding.getOperandCount());
        RelDataType type = callBinding.getOperandType(1);
        return type.getComparability() == RelDataTypeComparability.ALL;
      }
      ...
{code}

{{SqlOperator.validateOperands}} calls {{checkOperandTypes(opBinding, true)}} 
and ignores the returned boolean, relying on the checker to throw, so the 
{{false}} is lost. The result of {{isValidCount}} is discarded in the same way. 
The checker was added with the functions in CALCITE-5283.

h2. How to reproduce

The test catalog's {{EMP_ADDRESS}} table has columns of the structured type 
{{ADDRESS}}, whose comparability is {{NONE}} ({{Fixture.addressType}}). In 
{{SqlValidatorTest}}:

{code:sql}
select arg_min(empno, home_address) from emp_address
{code}

On {{main}} this validates without error, and so do {{arg_max(empno, 
home_address)}} and, with the Spark library, {{min_by(...)}} and 
{{max_by(...)}}. {{MIN(home_address)}}, by contrast, is already rejected at 
validation by {{ComparableOperandTypeChecker}}:

{noformat}
Cannot apply 'MIN' to arguments of type 'MIN(<>)'. Supported form(s): 
'MIN(<COMPARABLE_TYPE>)'
{noformat}

With the fix, the four functions fail the same way, for example:

{noformat}
Cannot apply 'ARG_MIN' to arguments of type 'ARG_MIN(<INTEGER>, <>)'. Supported 
form(s): ARG_MIN(<ANY>, <COMPARABLE_TYPE>)
{noformat}

A non-comparable *value* argument is still allowed: {{arg_min(home_address, 
empno)}} validates.





--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to