feat(nereids): add typeof scalar function#61500
feat(nereids): add typeof scalar function#61500ahmedsaid47 wants to merge 3 commits intoapache:masterfrom
Conversation
|
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
|
Validation completed on a real single-node Doris cluster (1 FE + 1 BE). Executed:
Result: |
There was a problem hiding this comment.
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
TypeOfscalar function (analyze-time rewrite toVarcharLiteral) and register/visit it in Nereids. - Capture original CAST/TRY_CAST type SQL text (
explicitTypeSql) to improve Trino-compatible type-name display (notably forDECIMALdefaults). - 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.
| public Optional<String> getExplicitTypeSql() { | ||
| return Optional.ofNullable(explicitTypeSql); | ||
| } |
There was a problem hiding this comment.
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.
| public TryCast withChildren(List<Expression> children) { | ||
| Preconditions.checkArgument(children.size() == 1); | ||
| return new TryCast(children, targetType, isExplicitType); | ||
| return new TryCast(children, targetType, isExplicitType, explicitTypeSql); | ||
| } |
There was a problem hiding this comment.
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.
| @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"); | ||
| } |
There was a problem hiding this comment.
Added targeted assertions in 0cbb1d9 for the remaining mappings introduced by TypeOfDisplayName, including float -> real, varbinary -> varbinary, datev2 -> date, and timev2 -> time(0).
|
Pushed follow-up commit |
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 addstypeof(expr) -> varcharas an FE-only function and rewritestypeof(...)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)
Manual test steps:
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./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 1Behavior changed:
typeof(expr) -> varchar.Does this need documentation?
Check List (For Reviewer who merge this PR)