Skip to content

[Feature][SDK][Transform] Support parsing SQL NULL literal via NullValueParser #12213

Description

@luchunliang

Description

This feature adds first-class support for the SQL NULL literal in Transform SDK expressions.

Previously, a SELECT expression that used NULL directly (e.g. ifnull(null, 3), coalesce(null, col)) failed during parser construction:

java.lang.ClassCastException: net.sf.jsqlparser.expression.NullValue cannot be cast to net.sf.jsqlparser.schema.Column
	at org.apache.inlong.sdk.transform.process.parser.ParserTools.getTransformParser(ParserTools.java:72)
	at org.apache.inlong.sdk.transform.process.operator.OperatorTools.buildParser(OperatorTools.java:119)
	at org.apache.inlong.sdk.transform.process.function.condition.IfNullFunction.<init>(IfNullFunction.java:57)

With this feature, the NULL literal is resolved to a constant Java null, enabling ifnull(null, x) / coalesce(null, x) / concat_ws(..., null, ...) and similar expressions to work as expected.

Use case

Component

inlong-sdk / transform-sdk

  • org.apache.inlong.sdk.transform.process.parser.NullValueParser (new)
  • Test: org.apache.inlong.sdk.transform.process.function.condition.TestIfNullFunction

Description

This feature adds first-class support for the SQL NULL literal in Transform SDK expressions.

Previously, a SELECT expression that used NULL directly (e.g. ifnull(null, 3), coalesce(null, col)) failed during parser construction:

java.lang.ClassCastException: net.sf.jsqlparser.expression.NullValue cannot be cast to net.sf.jsqlparser.schema.Column
	at org.apache.inlong.sdk.transform.process.parser.ParserTools.getTransformParser(ParserTools.java:72)
	at org.apache.inlong.sdk.transform.process.operator.OperatorTools.buildParser(OperatorTools.java:119)
	at org.apache.inlong.sdk.transform.process.function.condition.IfNullFunction.<init>(IfNullFunction.java:57)

With this feature, the NULL literal is resolved to a constant Java null, enabling ifnull(null, x) / coalesce(null, x) / concat_ws(..., null, ...) and similar expressions to work as expected.

Background

ParserTools.getTransformParser(Expression expr) resolves parsers through a reflective scan that maps Expression sub-types to their parser classes (parserMap). Expression types that are not registered currently fall back to a Column cast:

Class<?> clazz = parserMap.get(expr.getClass());
if (clazz == null) {
    return new ColumnParser((Column) expr);   // NULL literal hits here and crashes
}

The SQL NULL literal is parsed by JSqlParser as net.sf.jsqlparser.expression.NullValue, which is not a Column. Because no parser was registered for it, any NULL literal hit the fallback branch and raised a ClassCastException.

Proposed Change

Introduce a NullValueParser following the existing StringParser pattern:

@TransformParser(values = NullValue.class)
public class NullValueParser implements ValueParser {

    public NullValueParser(NullValue expr) {
        // The NULL literal carries no value; nothing to store.
    }

    @Override
    public Object parse(SourceData sourceData, int rowIndex, Context context) {
        return null;
    }
}

@TransformParser(values = NullValue.class) registers NullValue.class in parserMap, so getTransformParser resolves it through the reflective constructor branch, and NULL literals evaluate to constant null.

Resulting Behavior

  • ifnull(null, numeric2) evaluates its first argument to null, so IfNullFunction falls back to the second argument as expected.
  • Other functions that receive a NULL literal as an argument (e.g. coalesce, num_nulls, concat_ws) no longer fail during parser construction.

Tests

Added a true-NULL-literal case to TestIfNullFunction:

// case6: ifnull(null, numeric2) -- true NULL literal
transformSql = "select ifnull(null,numeric2) from source";
data = "5|3|3|5";
Assert.assertEquals("result=3", output.get(0));

Verified: Tests run: 1, Failures: 0, Errors: 0, Skipped: 0.

Backward Compatibility

  • Fully backward compatible.
  • No public API or method-signature change; only a new parser class is added.
  • Existing column / function / literal parsers are unaffected.

Files Changed

  • inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/process/parser/NullValueParser.java (new)
  • inlong-sdk/transform-sdk/src/test/java/org/apache/inlong/sdk/transform/process/function/condition/TestIfNullFunction.java

Are you willing to submit PR?

  • Yes, I am willing to submit a PR!

Code of Conduct

Activity

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

Metadata

Metadata

Assignees

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions