Skip to content

CommonSubexprEliminate + leaf-expression pushdown duplicate a UDF call wrapped in get_field #25329

Description

@bert-beyondloops

Describe the bug

When a non-pushable (KeepInPlace) function call appears once bare and once wrapped in get_field(...),

CommonSubexprEliminate correctly deduplicates the bare occurrence into a __common_expr_N column — but leaf-expression pushdown (ExtractLeafExpressions / PushDownLeafProjections) then re-derives the full original call a second time when it tries to push the get_field expression down, because __common_expr_N's Column reference is indistinguishable, at the ExpressionPlacement level, from a genuine cheap base-table column.

Net effect: the function is evaluated twice instead of once.

To Reproduce

Using here the arrow_field UDF as an example since this function returns a struct type.

  CREATE TABLE t (a INT) AS VALUES (1), (2);                                                                                                                                                                                       
                                                                                                                                                                                                                                   
  EXPLAIN SELECT                                                                                                                                                                                                                   
      CASE WHEN arrow_field(a) IS NOT NULL                                                                                                                                                                                         
           THEN get_field(arrow_field(a), 'name') END AS c1                                                                                                                                                                        
  FROM t;   

Actual physical plan

+---------------+-------------------------------+
| plan_type     | plan                          |
+---------------+-------------------------------+
| physical_plan | ┌───────────────────────────┐ |
|               | │       ProjectionExec      │ |
|               | │    --------------------   │ |
|               | │            c1:            │ |
|               | │  CASE WHEN arrow_field(a) │ |
|               | │      IS NOT NULL THEN     │ |
|               | │          get_field        │ |
|               | │      (arrow_field(a),     │ |
|               | │          name) END        │ |
|               | └─────────────┬─────────────┘ |
|               | ┌─────────────┴─────────────┐ |
|               | │       DataSourceExec      │ |
|               | │    --------------------   │ |
|               | │         bytes: 112        │ |
|               | │       format: memory      │ |
|               | │          rows: 1          │ |
|               | └───────────────────────────┘ |
|               |                               |
+---------------+-------------------------------+                                                                                                                              

The function (arrow_field) is called twice.

Expected behavior

Expected physical plan

+---------------+-------------------------------+
| plan_type     | plan                          |
+---------------+-------------------------------+
| physical_plan | ┌───────────────────────────┐ |
|               | │       ProjectionExec      │ |
|               | │    --------------------   │ |
|               | │            c1:            │ |
|               | │ CASE WHEN __common_expr_1 │ |
|               | │      IS NOT NULL THEN     │ |
|               | │          get_field        │ |
|               | │     (__common_expr_1,     │ |
|               | │          name) END        │ |
|               | └─────────────┬─────────────┘ |
|               | ┌─────────────┴─────────────┐ |
|               | │       ProjectionExec      │ |
|               | │    --------------------   │ |
|               | │      __common_expr_1:     │ |
|               | │       arrow_field(a)      │ |
|               | └─────────────┬─────────────┘ |
|               | ┌─────────────┴─────────────┐ |
|               | │       DataSourceExec      │ |
|               | │    --------------------   │ |
|               | │         bytes: 112        │ |
|               | │       format: memory      │ |
|               | │          rows: 1          │ |
|               | └───────────────────────────┘ |
|               |                               |
+---------------+-------------------------------+

The function (arrow_field) is called once;
get_field references the shared __common_expr_1 column.

Additional context

No response

Activity

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

Metadata

Metadata

Labels

bugSomething isn't working

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions