Skip to content

Update the CONCAT scalar function to support Utf8View #11836

Closed

Description

@tshauck

Part of #11752 and #11790

Related: #11766

Currently, a call to CONCAT with a Utf8View datatypes induces a cast. After the change that fixes this issue, it should not.

query TT
EXPLAIN SELECT
  concat(column1_utf8view, column2_utf8view) as c
FROM test;
----
logical_plan
01)Projection: concat(CAST(test.column1_utf8view AS Utf8), CAST(test.column2_utf8view AS Utf8)) AS c
02)--TableScan: test projection=[column1_utf8view, column2_utf8view]

Concat is defined here: https://github.com/apache/datafusion/blob/main/datafusion/functions/src/string/concat.rs

Is your feature request related to a problem or challenge?

We are working to add complete StringView support in DataFusion, which permits potentially much faster processing of string data. See #10918 for more background.

Today, most DataFusion string functions support DataType::Utf8 and DataType::LargeUtf8 and when called with a StringView argument DataFusion will cast the argument back to DataType::Utf8 which is expensive.

To realize the full speed of StringView, we need to ensure that all string functions support the DataType::Utf8View directly.

Describe the solution you'd like

Update the function to support DataType::Utf8View directly

Describe alternatives you've considered

The typical steps are:

  1. Write some tests showing the function doesn't support Utf8View (see the tests in string_view.slt to ensure the arguments are not being cast
  2. Change the Signature of the function to accept Utf8View in addition to Utf8/LargeUtf8
  3. Update the implementation of the function to operate on Utf8View

Example PRs

Additional context

The documentation of string functions can be found here: https://datafusion.apache.org/user-guide/sql/scalar_functions.html#string-functions

To test a function with StringView with datafusion-cli you can use an example like this (replacing starts_with with the relevant function)

> create table foo as values (arrow_cast('foo', 'Utf8View'), arrow_cast('bar', 'Utf8View'));
0 row(s) fetched.
Elapsed 0.043 seconds.

> select starts_with(column1, column2) from foo;
+--------------------------------------+
| starts_with(foo.column1,foo.column2) |
+--------------------------------------+
| false                                |
+--------------------------------------+
1 row(s) fetched.
Elapsed 0.015 seconds.

To see if it is using utf8 view, use EXPLAIN to see the plan and verify there is no CAST. In this example the CAST(column1@0 AS Utf8) indicates that the function is not using Utf8View natively

> explain select starts_with(column1, column2) from foo;
+---------------+------------------------------------------------------------------------------------------------------------------------------+
| plan_type     | plan                                                                                                                         |
+---------------+------------------------------------------------------------------------------------------------------------------------------+
| logical_plan  | Projection: starts_with(CAST(foo.column1 AS Utf8), CAST(foo.column2 AS Utf8))                                                |
|               |   TableScan: foo projection=[column1, column2]                                                                               |
| physical_plan | ProjectionExec: expr=[starts_with(CAST(column1@0 AS Utf8), CAST(column2@1 AS Utf8)) as starts_with(foo.column1,foo.column2)] |
|               |   MemoryExec: partitions=1, partition_sizes=[1]                                                                              |
|               |                                                                                                                              |
+---------------+------------------------------------------------------------------------------------------------------------------------------+
2 row(s) fetched.
Elapsed 0.006 seconds.

It is also often good to test with a constant as well (likewise there should be no cast):

> explain select starts_with(column1, 'foo') from foo;
+---------------+----------------------------------------------------------------------------------------------------------+
| plan_type     | plan                                                                                                     |
+---------------+----------------------------------------------------------------------------------------------------------+
| logical_plan  | Projection: starts_with(CAST(foo.column1 AS Utf8), Utf8("foo"))                                          |
|               |   TableScan: foo projection=[column1]                                                                    |
| physical_plan | ProjectionExec: expr=[starts_with(CAST(column1@0 AS Utf8), foo) as starts_with(foo.column1,Utf8("foo"))] |
|               |   MemoryExec: partitions=1, partition_sizes=[1]                                                          |
|               |                                                                                                          |
+---------------+----------------------------------------------------------------------------------------------------------+
2 row(s) fetched.
Elapsed 0.002 seconds.

### Additional context

_No response_

Activity

  1. changed the title [-]Update the CONCAT scalar function to support Utf8View[/-] [+]Update the `CONCAT` scalar function to support Utf8View[/+] on Aug 5, 2024
  2. changed the title [-]Update the `CONCAT` scalar function to support Utf8View[/-] [+]Update the `CONCAT` scalar function to support `Utf8View`[/+] on Aug 5, 2024
  3. dharanad commented on Aug 6, 2024

    @dharanad
    Contributor

    take

  4. dharanad commented on Aug 7, 2024

    @dharanad
    Contributor

    Maybe i can reference this PR: #11851

  5. tshauck commented on Aug 7, 2024

    @tshauck
    ContributorAuthor

    That's a good one to reference... You also might consider looking at #11787, which similar to this concat func in that you have to consider multiple arguments and their types (e.g. concat'ing a UTF8View with a UTF8). It also has sqllogictests (slt), which it'd be nice to new PRs to have.

  6. alamb commented on Aug 13, 2024

    @alamb
    Contributor

    There are a bunch of PRs now that port functions to Utf8View which can probably be used as examples

  7. tshauck commented on Aug 28, 2024

    @tshauck
    ContributorAuthor

    @dharanad -- hey, are you still working on this? If not, can I take a look. This is one of the three issues still open on #11790 -- we're really close.

  8. dharanad commented on Aug 28, 2024

    @dharanad
    Contributor

    @dharanad -- hey, are you still working on this? If not, can I take a look. This is one of the three issues still open on #11790 -- we're really close.

    Hey @tshauck , please feel free to work on it

  9. devanbenz commented on Aug 28, 2024

    @devanbenz
    Contributor

    take

  10. removed their assignment
    on Aug 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions