Repository: apache/flink
File: flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/functions/inference/TypeInferenceOperandInference.java (Java)

Code before:
        this.typeInference = typeInference;
    }

    @Override
    public void inferOperandTypes(
            SqlCallBinding callBinding, RelDataType returnType, RelDataType[] operandTypes) {
        final CallContext callContext =
                new CallBindingCallContext(
                        dataTypeFactory,
                        definition,
                        callBinding,
                        returnType,
                        typeInference.getStaticArguments().orElse(null));
        try {
            if (TypeInferenceUtil.validateArgumentCount(
                    typeInference.getInputTypeStrategy().getArgumentCount(),
                    callContext.getArgumentDataTypes().size(),
                    false)) {
                inferOperandTypesOrError(unwrapTypeFactory(callBinding), callContext, operandTypes);
            }
        } catch (ValidationException e) {
            // let operand checker fail
        } catch (CalciteContextException e) {
            throw e;
        } catch (Throwable t) {
            if (t.getCause() instanceof CalciteContextException) {
                throw (CalciteContextException) t.getCause();
            }
            throw createUnexpectedException(callContext, t);
        }
    }

    // --------------------------------------------------------------------------------------------

    private void inferOperandTypesOrError(
            FlinkTypeFactory typeFactory, CallContext callContext, RelDataType[] operandTypes) {
        final List<DataType> expectedDataTypes;

        // Static arguments have the highest priority
        final List<StaticArgument> staticArgs = typeInference.getStaticArguments().orElse(null);
        if (staticArgs != null) {
            expectedDataTypes =
                    staticArgs.stream()
                            .map(staticArg -> staticArg.getDataType().orElse(null))
                            .collect(Collectors.toList());
        } else {
            expectedDataTypes =
                    typeInference
                            .getInputTypeStrategy()
                            .inferInputTypes(callContext, false)
                            .orElse(null);

Review comment (suggestion):
I am curious, do we need to check down the chain of causes for a match, rather than the first cause? I am not sure if we can get into this situation, where the cause of the cause is a CalciteContextException or the like. Maybe using [this code](https://github.com/apache/flink/blob/e42cdd1efe354d406c8791f319292d3b185d9281/flink-core/src/main/java/org/apache/flink/util/ExceptionUtils.java#L473)

Code after:
        this.typeInference = typeInference;
    }

    @Override
    public void inferOperandTypes(
            SqlCallBinding callBinding, RelDataType returnType, RelDataType[] operandTypes) {
        final CallContext callContext =
                new CallBindingCallContext(
                        dataTypeFactory,
                        definition,
                        callBinding,
                        returnType,
                        typeInference.getStaticArguments().orElse(null));
        try {
            if (TypeInferenceUtil.validateArgumentCount(
                    typeInference.getInputTypeStrategy().getArgumentCount(),
                    callContext.getArgumentDataTypes().size(),
                    false)) {
                inferOperandTypesOrError(unwrapTypeFactory(callBinding), callContext, operandTypes);
            }
        } catch (ValidationException e) {
            // let operand checker fail
        } catch (CalciteContextException e) {
            throw e;
        } catch (Throwable t) {
            throw createUnexpectedException(callContext, t);
        }
    }

    // --------------------------------------------------------------------------------------------

    private void inferOperandTypesOrError(
            FlinkTypeFactory typeFactory, CallContext callContext, RelDataType[] operandTypes) {
        final List<DataType> expectedDataTypes;

        // Static arguments have the highest priority
        final List<StaticArgument> staticArgs = typeInference.getStaticArguments().orElse(null);
        if (staticArgs != null) {
            expectedDataTypes =
                    staticArgs.stream()
                            .map(staticArg -> staticArg.getDataType().orElse(null))
                            .collect(Collectors.toList());
        } else {
            expectedDataTypes =
                    typeInference
                            .getInputTypeStrategy()
                            .inferInputTypes(callContext, false)
                            .orElse(null);
        }

        // Early out for invalid input