Skip to content

feat(nereids): add typeof scalar function#61500

Open
ahmedsaid47 wants to merge 3 commits intoapache:masterfrom
ahmedsaid47:feat/typeof
Open

feat(nereids): add typeof scalar function#61500
ahmedsaid47 wants to merge 3 commits intoapache:masterfrom
ahmedsaid47:feat/typeof

Conversation

@ahmedsaid47
Copy link

@ahmedsaid47 ahmedsaid47 commented Mar 19, 2026

What problem does this PR solve?

Issue Number: close #48203

Related PR: #48201

Problem Summary:

Add the Trino/Presto typeof(expr) scalar function in Nereids.

Before this patch, typeof(...) was not supported in Doris Nereids and Trino/Presto compatibility queries using it could not be analyzed successfully. This implementation adds typeof(expr) -> varchar as an FE-only function and rewrites typeof(...) to a string literal during analysis, so it does not require a BE runtime function. The patch also adds Trino-compatible type display formatting for literals, casts, arrays, maps, rows, decimals, and nested types.

Release note

None

Check List (For Author)

  • Test
    • Regression test
    • Unit Test
    • Manual test (add detailed scripts or steps below)
    • No need to test or manual test. Explain why:
      • This is a refactor/code format and no logic has been changed.
      • Previous test can cover this change.
      • No code files have been changed.
      • Other reason

Manual test steps:

  1. cd fe && mvn -pl fe-core -am -Dcheckstyle.skip=true -Dspotbugs.skip=true -DfailIfNoTests=false -Dtest=org.apache.doris.nereids.trees.expressions.functions.scalar.TypeOfTest test
  2. Start a local single-node Doris cluster with 1 FE and 1 BE.
  3. ./run-regression-test.sh --run -f regression-test/suites/external_table_p0/dialect_compatible/sql/presto/scalar/TestTypeOfFunction.sql -forceGenOut -parallel 1 -times 1
  4. ./run-regression-test.sh --run -f regression-test/suites/external_table_p0/dialect_compatible/sql/presto/scalar/TestTypeOfFunction.sql -parallel 1 -times 1
  • Behavior changed:

    • No.
    • Yes. Add typeof(expr) -> varchar.
  • Does this need documentation?

    • No.
    • Yes.

Check List (For Reviewer who merge this PR)

  • Confirm the release note
  • Confirm test cases
  • Confirm document
  • Add branch pick label

@hello-stephen
Copy link
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@ahmedsaid47 ahmedsaid47 marked this pull request as ready for review March 19, 2026 10:42
Copilot AI review requested due to automatic review settings March 19, 2026 10:42
@ahmedsaid47
Copy link
Author

Validation completed on a real single-node Doris cluster (1 FE + 1 BE).

Executed:

  • mvn -pl fe-core -am -Dcheckstyle.skip=true -Dspotbugs.skip=true -DfailIfNoTests=false -Dtest=org.apache.doris.nereids.trees.expressions.functions.scalar.TypeOfTest test
  • ./run-regression-test.sh --run -f regression-test/suites/external_table_p0/dialect_compatible/sql/presto/scalar/TestTypeOfFunction.sql -forceGenOut -parallel 1 -times 1
  • ./run-regression-test.sh --run -f regression-test/suites/external_table_p0/dialect_compatible/sql/presto/scalar/TestTypeOfFunction.sql -parallel 1 -times 1

Result: TypeOfTest passed and TestTypeOfFunction passed with 0 failed suites on a real FE+BE runtime.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Trino/Presto-compatible typeof(expr) support to the Nereids FE analyzer by rewriting typeof(...) into a VARCHAR literal during analysis, avoiding any BE runtime dependency. This also introduces Trino-style type display formatting for several Doris/Nereids data types so the returned type strings match Trino/Presto expectations.

Changes:

  • Introduce TypeOf scalar function (analyze-time rewrite to VarcharLiteral) and register/visit it in Nereids.
  • Capture original CAST/TRY_CAST type SQL text (explicitTypeSql) to improve Trino-compatible type-name display (notably for DECIMAL defaults).
  • Add unit tests and update Presto-dialect regression SQL + expected output for typeof.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
regression-test/suites/external_table_p0/dialect_compatible/sql/presto/scalar/TestTypeOfFunction.sql Adds typeof(...) queries under Presto dialect for various types and expressions.
regression-test/data/external_table_p0/dialect_compatible/sql/presto/scalar/TestTypeOfFunction.out Adds expected outputs matching Trino/Presto type display strings.
fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/scalar/TypeOfTest.java New unit tests covering analyze-time rewrite + complex type display formatting.
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java Adds visitor hook for the new TypeOf scalar function.
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/TryCast.java Threads explicitTypeSql through TRY_CAST construction/cloning paths.
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/TypeOfDisplayName.java New utility to produce Trino-compatible type display names for TYPEOF.
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/TypeOf.java New scalar function implementation: custom signature + analyze-time rewrite.
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Cast.java Adds explicitTypeSql storage/accessor and propagates it through cloning APIs.
fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java Persists CAST/TRY_CAST original type SQL text into Cast/TryCast nodes.
fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java Registers typeof as a built-in scalar function.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +80 to +82
public Optional<String> getExplicitTypeSql() {
return Optional.ofNullable(explicitTypeSql);
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0cbb1d9. Cast.equals() and computeHashCode() now include both isExplicitType and explicitTypeSql, so casts with the same analyzed target type but different explicit type text no longer collide in expression-keyed rewrites/CSE.

Comment on lines 75 to 78
public TryCast withChildren(List<Expression> children) {
Preconditions.checkArgument(children.size() == 1);
return new TryCast(children, targetType, isExplicitType);
return new TryCast(children, targetType, isExplicitType, explicitTypeSql);
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0cbb1d9 as well. TryCast now inherits the metadata-aware equality semantics from Cast, and its hash code also includes the explicit type metadata so TRY_CAST expressions stay consistent with their behavior in rewrite/CSE paths.

Comment on lines +45 to +60
@Test
void testAnalyzeTimeRewriteForTrinoExamples() {
assertTypeOfRewrite("typeof(123)", "integer");
assertTypeOfRewrite("typeof('cat')", "varchar(3)");
assertTypeOfRewrite("typeof(cast(1 as bigint))", "bigint");
assertTypeOfRewrite("typeof(cast(1 as varchar))", "varchar");
assertTypeOfRewrite("typeof(cast(null as varchar(10)))", "varchar(10)");
assertTypeOfRewrite("typeof(try_cast(null as varchar(10)))", "varchar(10)");
assertTypeOfRewrite("typeof(cast(null as char(3)))", "char(3)");
assertTypeOfRewrite("typeof(cast(null as decimal(5,1)))", "decimal(5,1)");
assertTypeOfRewrite("typeof(cast(null as decimal))", "decimal(38,0)");
assertTypeOfRewrite("typeof(try_cast(null as decimal))", "decimal(38,0)");
assertTypeOfRewrite("typeof(concat('ala', 'ma', 'kota'))", "varchar");
assertTypeOfRewrite("typeof(typeof(123))", "varchar");
assertTypeOfRewrite("typeof(2 + sin(2) + 2.3)", "double");
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added targeted assertions in 0cbb1d9 for the remaining mappings introduced by TypeOfDisplayName, including float -> real, varbinary -> varbinary, datev2 -> date, and timev2 -> time(0).

@ahmedsaid47
Copy link
Author

Pushed follow-up commit 0cbb1d90 to address the review feedback on Cast/TryCast equality-hash semantics and to add the missing TypeOfDisplayName mapping assertions. Re-ran TypeOfTest on the latest head and it passed.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Good First Issue] Support All SQL Functions in Other SQL System

3 participants