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)