Skip to content

isthmus: nothing detects a Substrait function that has no FunctionMappings entry but does have a Calcite operator #1276

Description

@nielspardon

FunctionConverter builds its signatures map exclusively from the FunctionMappings sig lists, keyed on SqlOperator identity, with no fall-back matching an operator to a same-named Substrait function. A Substrait scalar function with no entry therefore has no FunctionFinder, and every Calcite call to it fails with Unable to convert call X(...) at runtime. Nothing surfaces the gap earlier than that: FunctionConverter logs No binding for function: {} at DEBUG for the extension side, and a Sig whose name matches no loaded function is dropped from matcherMap with no log at all.

Roughly 38 of the 126 scalar function names currently have no finder. Most are harmless — Calcite has no operator for swapcase, title, capitalize, string_split, so there is nothing to map. The interesting subset is the names where a real Calcite operator does exist and already resolves in the validator, so a query parses and then dies at conversion: currently around nine, including REPEAT, OCTET_LENGTH, BIT_LENGTH, CARDINALITY, LOG1P, CONCAT_WS, REGEXP_REPLACE, IS_NAN and NULLIF.

That subset is mechanically detectable — enumerate getUnmappedFunctions(extensions.scalarFunctions(), SCALAR_SIGS), look each name up in the provider's operator table, and compare against a checked-in expected list. A test like that turns each new occurrence into a build failure instead of a bug report, and would have found #781, #1222 and the two entries added in #1251 in one pass.

Two things worth folding into the same test while it is being written:

  • Nothing validates the other direction either — that a Sig's Substrait name resolves to a loaded extension function. s(SqlStdOperatorTable.BETWEEN) derives the name "between asymmetric", which matches no function and is silently inert; it is the only dead entry across the three sig lists today. A typo such as "init_cap" would compile and pass spotless, PMD and javadoc, and surface only as a runtime conversion failure.
  • Adding a bare Sig is not automatically safe, so the detector should be an inventory rather than an auto-fix. Probing the nine names above with bare sigs, five convert correctly, four fail on operand shape — and regexp_replace silently bound a 3-operand Calcite call to regexp_replace:str_str_str_i64_i64, i.e. produced a wrong plan instead of an error. That is also the argument against a generic name-matching fall-back in FunctionConverter.

#1012 restructures this mapping wholesale, and its testing strategy lists reverse-N:1, registration-conflict and ArgAdapter invertibility checks but no unmapped-function inventory. Filing this separately so the baseline exists either way.

Found while reviewing #1251.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions