Skip to content

feat: Use NativeType in get_example_type, information schema - #21737

Open
theirix wants to merge 17 commits into
apache:mainfrom
theirix:type-signature-native-type
Open

theirix wants to merge 17 commits into
apache:mainfrom
theirix:type-signature-native-type

Conversation

@theirix

@theirix theirix commented Apr 19, 2026 •

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

Moving from physical types: get_example_types and the information schema use Arrow DataType, but it is usually sufficient to use Datafusion's NativeType instead.

Let's introduce a new API get_representative_types, based on NativeType, and deprecate the public get_example_types API

It is a logical continuation of #15965

What changes are included in this PR?

Are these changes tested?

  • Tests are passing
  • Added more tests to check schema for different types of functions

Are there any user-facing changes?

  • Deprecation of the TypeSignature::get_example_types API

@github-actions github-actions Bot added logical-expr Logical plan and expressions catalog Related to the catalog crate labels Apr 19, 2026
@theirix
theirix marked this pull request as ready for review April 19, 2026 20:28
Comment thread datafusion/expr-common/src/signature.rs Outdated

#[deprecated(since = "46.0.0", note = "See get_example_types instead")]
pub fn get_possible_types(&self) -> Vec<Vec<DataType>> {
pub fn get_possible_types(&self) -> Vec<Vec<NativeType>> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hm. A public API break for a deprecated method ... Maybe it is time to just remove it ?!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That's true. I will drop get_possible_types. However, get_example_types is also public - it is used in the information schema internally, and can be used by DF users.

Since it breaks the expr-common API, how about deprecating the get_example_types signature and adding a NativeType-based get_representative_types?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@martin-g to avoid breaking changes in the get_example_types (my miss), I've introduced the new method, while deprecating get_example_types.

The Signature API is heavily DataType-based, so the get_example_types. Should we let them coexist, or even move the NativeType-based logic to the information schema? cc @jayzhan211

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It seems the NativeType is not powerful enough to fully replace DataType here.
For example https://github.com/apache/datafusion/pull/21737/changes#diff-52d29120f24c2a01793f6d729fdb7898abaa8d2320db75aba5cbb06cd714930eR505-R516 shows that there are no counterparts for Union's UnionMode and Map's keys_sorted and defaults should be used. And this may lead to confusions.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Undoubtedly, it's not a replacement now. The question for this improvement is whether we'd like to provide changes only to the information-schema, which benefits from native types (then we move code there), or also provide a public API for the Signature to support NativeType alongside DataType (as now).

At the same time, UDFs are migrating to TypeSignature, abstracting from physical data types.

Comment thread datafusion/expr-common/src/signature.rs Outdated
Comment thread datafusion/catalog/src/information_schema.rs Outdated
Comment thread datafusion/catalog/src/information_schema.rs Outdated
Comment thread datafusion/catalog/src/information_schema.rs Outdated
Comment thread datafusion/expr-common/src/signature.rs Outdated
theirix and others added 5 commits April 20, 2026 20:08
Co-authored-by: Martin Grigorov <martin-g@users.noreply.github.com>
Instead, add the new `get_representative_types` API with NativeType.
Deprecated old `get_example_types` and related helpers, left as-is
to avoid breaking API change.
Comment thread datafusion/expr-common/src/signature.rs Outdated
///
/// This is used for `information_schema` and can be used to generate
/// documentation or error messages.
/// Remove with `get_example_types`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should be a comment (//) instead of rustdoc (///)

Comment thread datafusion/expr-common/src/signature.rs Outdated

#[deprecated(since = "46.0.0", note = "See get_example_types instead")]
pub fn get_possible_types(&self) -> Vec<Vec<DataType>> {
pub fn get_possible_types(&self) -> Vec<Vec<NativeType>> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It seems the NativeType is not powerful enough to fully replace DataType here.
For example https://github.com/apache/datafusion/pull/21737/changes#diff-52d29120f24c2a01793f6d729fdb7898abaa8d2320db75aba5cbb06cd714930eR505-R516 shows that there are no counterparts for Union's UnionMode and Map's keys_sorted and defaults should be used. And this may lead to confusions.

@Jefffrey Jefffrey left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

sorry it took so long for me to get around to looking at this 😅

NativeType::Boolean => Ok(DataType::Boolean),
NativeType::Int8 => Ok(DataType::Int8),
NativeType::Int16 => Ok(DataType::Int16),
NativeType::Int32 => Ok(DataType::Int32),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It feels like we're just moving this logic from where it was in get_example_types to here; I think to properly work towards closing the original issue we might need a larger rework around how datatypes work with information schema, otherwise we're still stuck with this datatype <---> nativetype interwork no matter where we move it 🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@Jefffrey , thank you for this! I took another look and reworked it significantly.

I agree, UDF's field and return type resolvers are still on physical Arrow types, and the high-level rework should be done as part of the bigger #12622 epic. I think this could be a small step toward that migration.

Instead of moving a huge mapping around, I decided to reuse the existing LogicalType::default_cast_for logical-physical mapping. It is much leaner now, and all the logic is consolidated in one place, not spread across crates. We can reason on logical types for the catalog. When we remove the deprecated get_example_types, there won't be any traces of the mapping in the high-level catalog and expr crates. What do you think?

@martin-g, regarding your concern - the details of mapping, keys_sorted, and nested structures are now the responsibility of a LogicalType

@github-actions

Copy link
Copy Markdown

Thank you for your contribution. Unfortunately, this pull request is stale because it has been open 60 days with no activity. Please remove the stale label or comment or this will be closed in 7 days.

@github-actions github-actions Bot added the Stale PR has not had any activity for some time label Aug 14, 2026
@github-actions github-actions Bot added sqllogictest SQL Logic Tests (.slt) common Related to common crate labels Aug 18, 2026
@github-actions

github-actions Bot commented Aug 18, 2026 •

Copy link
Copy Markdown

Thank you for opening this pull request!

Reviewer note: cargo-semver-checks reported the current version number is not SemVer-compatible with the changes in this pull request (compared against the base branch).

Details
     Cloning apache/main
    Building datafusion-catalog v55.1.0 (current)
       Built [  27.633s] (current)
     Parsing datafusion-catalog v55.1.0 (current)
      Parsed [   0.016s] (current)
    Building datafusion-catalog v55.1.0 (baseline)
       Built [  25.465s] (baseline)
     Parsing datafusion-catalog v55.1.0 (baseline)
      Parsed [   0.016s] (baseline)
    Checking datafusion-catalog v55.1.0 -> v55.1.0 (no change; assume patch)
     Checked [   0.083s] 223 checks: 223 pass, 31 skip
     Summary no semver update required
    Finished [  54.712s] datafusion-catalog
    Building datafusion-common v55.1.0 (current)
       Built [  21.623s] (current)
     Parsing datafusion-common v55.1.0 (current)
      Parsed [   0.045s] (current)
    Building datafusion-common v55.1.0 (baseline)
       Built [  21.151s] (baseline)
     Parsing datafusion-common v55.1.0 (baseline)
      Parsed [   0.043s] (baseline)
    Checking datafusion-common v55.1.0 -> v55.1.0 (no change; assume patch)
     Checked [   0.528s] 223 checks: 223 pass, 31 skip
     Summary no semver update required
    Finished [  44.497s] datafusion-common
    Building datafusion-expr-common v55.1.0 (current)
       Built [  11.711s] (current)
     Parsing datafusion-expr-common v55.1.0 (current)
      Parsed [   0.012s] (current)
    Building datafusion-expr-common v55.1.0 (baseline)
       Built [  11.617s] (baseline)
     Parsing datafusion-expr-common v55.1.0 (baseline)
      Parsed [   0.012s] (baseline)
    Checking datafusion-expr-common v55.1.0 -> v55.1.0 (no change; assume patch)
     Checked [   0.157s] 223 checks: 222 pass, 1 fail, 0 warn, 31 skip

--- failure type_method_marked_deprecated: type method #[deprecated] added ---

Description:
A type method is now #[deprecated]. Downstream crates will get a compiler warning when using this method.
        ref: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-deprecated-attribute
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.50.0/src/lints/type_method_marked_deprecated.ron

Failed in:
  method datafusion_expr_common::signature::TypeSignature::get_example_types in /home/runner/work/datafusion/datafusion/datafusion/expr-common/src/signature.rs:937

     Summary semver requires new minor version: 0 major and 1 minor checks failed
    Finished [  24.245s] datafusion-expr-common
    Building datafusion-sqllogictest v55.1.0 (current)
       Built [  56.702s] (current)
     Parsing datafusion-sqllogictest v55.1.0 (current)
      Parsed [   0.011s] (current)
    Building datafusion-sqllogictest v55.1.0 (baseline)
       Built [  57.278s] (baseline)
     Parsing datafusion-sqllogictest v55.1.0 (baseline)
      Parsed [   0.012s] (baseline)
    Checking datafusion-sqllogictest v55.1.0 -> v55.1.0 (no change; assume patch)
     Checked [   0.066s] 223 checks: 223 pass, 31 skip
     Summary no semver update required
    Finished [ 116.666s] datafusion-sqllogictest

@github-actions github-actions Bot added the auto detected api change Auto detected API change label Aug 18, 2026
@codecov-commenter

codecov-commenter commented Aug 18, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.44409% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.66%. Comparing base (6a792c6) to head (f8a88d9).
⚠️ Report is 107 commits behind head on main.

Files with missing lines Patch % Lines
datafusion/catalog/src/information_schema.rs 93.93% 3 Missing and 3 partials ⚠️
datafusion/common/src/types/native.rs 97.64% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #21737      +/-   ##
==========================================
+ Coverage   82.49%   82.66%   +0.16%     
==========================================
  Files        1140     1147       +7     
  Lines      438555   446575    +8020     
  Branches   438555   446575    +8020     
==========================================
+ Hits       361803   369176    +7373     
- Misses      54880    54997     +117     
- Partials    21872    22402     +530     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@theirix

theirix commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

bot unstale ?

@github-actions github-actions Bot removed the Stale PR has not had any activity for some time label Aug 19, 2026
@Jefffrey

Copy link
Copy Markdown
Contributor

maybe @jayzhan211 can help take a look at this

@jayzhan211 jayzhan211 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks @theirix , here is a suggestion

.collect::<Result<Vec<FieldRef>>>()?;
// Even with collecting results into a set, drop duplicates early
arg_fields.sort();
arg_fields.dedup();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Field's Ord compares name first, and every field is named arg_{i}, so dedup() never removes anything. sort() is a no-op up to 10 args, but from 11 args it reorders them lexicographically (arg_0, arg_1, arg_10, arg_2, …). The return type is then computed from permuted argument types, while the arg_types shown keep the original order.

Repro: a UDF with Signature::exact(vec![DataType::Int32; 10] + [DataType::Utf8]) whose return_type returns the last arg. get_udf_args_and_return_types reports args [Int32 ×10, String] with return type Some("Int32") instead of Some("String").

The BTreeSet collect already dedups rows, so drop both lines:

-                let mut arg_fields = arg_types
+                let arg_fields = arg_types
                     .iter()
                     .enumerate()
                     .map(|(i, t)| resolve_informational_field(i, t))
                     .collect::<Result<Vec<FieldRef>>>()?;
-                // Even with collecting results into a set, drop duplicates early
-                arg_fields.sort();
-                arg_fields.dedup();

Please add a test with more than 10 heterogeneous args.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thank you, it's a good spot. Removed the dedup to have an expected result (backed by a unit test)

@jayzhan211 jayzhan211 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks @theirix , here are suggestions

fn resolve_informational_field(idx: usize, t: &NativeType) -> Result<FieldRef> {
// Since a native type maps to several physical types, resolve it against `Null` data type
// to get the canonical `DataType` for the native type
let data_type = t.default_cast_for(&DataType::Null)?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Resolving each NativeType against Null collapses String to Utf8View, so string functions that return Int64 for LargeUtf8 lose that row. Diffing information_schema.routines/parameters against the base shows the Int64 OUT row disappearing for bit_length, char_length, character_length, find_in_set, instr, length, levenshtein, octet_length, position, strpos. If that's intended, please pin it in information_schema.slt and mention it under user-facing changes:

query TT rowsort
select routine_name, data_type from information_schema.routines where routine_name = 'length';
----
length Int32

Comment thread parquet-testing

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we need this change?

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

Labels

auto detected api change Auto detected API change catalog Related to the catalog crate common Related to common crate logical-expr Logical plan and expressions sqllogictest SQL Logic Tests (.slt)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Return NativeType instead of DataType for get_example_types

5 participants