Skip to content

Refactor expressions#550

Merged
bohutang merged 24 commits into
databendlabs:masterfrom
sundy-li:action_dag
May 25, 2021
Merged

Refactor expressions#550
bohutang merged 24 commits into
databendlabs:masterfrom
sundy-li:action_dag

Conversation

@sundy-li

@sundy-li sundy-li commented May 15, 2021

Copy link
Copy Markdown
Member

Summary

RFC: https://github.com/sundy-li/fuse-query/blob/action_dag/website/datafuse/docs/rfcs/query/2021-05-22-plan-expression-refactor.md

  • split ScalarFunction and AggregateFunction
  • expression rewriter and expression visitor
  • expression chain in AST to plan builder (simple version as ActionsDag)
  • testing

A complex Example

EXPLAIN actions = 1
SELECT
    number + 1 AS number,
    number + 2 AS a,
    sum(number % 3) + 4 AS b
FROM numbers(10)
GROUP BY
    number,
    a
HAVING (b + 1) > 3

Query id: 9675ed9e-81fc-40dc-b9c7-5c33746db915

┌─explain───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Expression (Projection)                                                                                                                                   │
│ Actions: PROJECT plus(number, 1) AS number, plus(plus(number, 1), 2) AS a, plus(sum(modulo(plus(number, 1), 3)), 4) AS b                                  │
│   Expression (Before ORDER BY and SELECT)                                                                                                                 │
│   Actions: PROJECT plus(number, 1), plus(plus(number, 1), 2), plus(sum(modulo(plus(number, 1), 3)), 4)                                                    │
│     Filter (HAVING)                                                                                                                                       │
│     Filter column: greater(plus(plus(sum(modulo(plus(number, 1), 3)), 4), 1), 3)                                                                          │
│     Actions: PROJECT plus(number, 1), plus(plus(number, 1), 2), sum(modulo(plus(number, 1), 3))                                                           │
│              ADD 4 UInt8 Const(UInt8)                                                                                                                     │
│              ADD 1 UInt8 Const(UInt8)                                                                                                                     │
│              ADD 3 UInt8 Const(UInt8)                                                                                                                     │
│              FUNCTION plus(sum(modulo(plus(number, 1), 3)), 4) UInt64 = plus(sum(modulo(plus(number, 1), 3)), 4)                                          │
│              REMOVE sum(modulo(plus(number, 1), 3))                                                                                                       │
│              REMOVE 4                                                                                                                                     │
│              FUNCTION plus(plus(sum(modulo(plus(number, 1), 3)), 4), 1) UInt64 = plus(plus(sum(modulo(plus(number, 1), 3)), 4), 1)                        │
│              REMOVE 1                                                                                                                                     │
│              FUNCTION greater(plus(plus(sum(modulo(plus(number, 1), 3)), 4), 1), 3) UInt8 = greater(plus(plus(sum(modulo(plus(number, 1), 3)), 4), 1), 3) │
│              REMOVE plus(plus(sum(modulo(plus(number, 1), 3)), 4), 1)                                                                                     │
│              REMOVE 3                                                                                                                                     │
│       Aggregating                                                                                                                                         │
│       Keys: plus(number, 1), plus(plus(number, 1), 2)                                                                                                     │
│       Aggregates:                                                                                                                                         │
│           sum(modulo(plus(number, 1), 3))                                                                                                                 │
│             Function: sum(UInt8) → UInt64                                                                                                                 │
│             Arguments: modulo(plus(number, 1), 3)                                                                                                         │
│             Argument positions: 2                                                                                                                         │
│         Expression (Before GROUP BY)                                                                                                                      │
│         Actions: ADD 1 UInt8 Const(UInt8)                                                                                                                 │
│                  ADD 2 UInt8 Const(UInt8)                                                                                                                 │
│                  ADD 3 UInt8 Const(UInt8)                                                                                                                 │
│                  FUNCTION plus(number, 1) UInt64 = plus(number, 1)                                                                                        │
│                  REMOVE number                                                                                                                            │
│                  REMOVE 1                                                                                                                                 │
│                  FUNCTION plus(plus(number, 1), 2) UInt64 = plus(plus(number, 1), 2)                                                                      │
│                  REMOVE 2                                                                                                                                 │
│                  FUNCTION modulo(plus(number, 1), 3) UInt8 = modulo(plus(number, 1), 3)                                                                   │
│                  REMOVE 3                                                                                                                                 │
│           SettingQuotaAndLimits (Set limits and quota after reading from storage)                                                                         │
│             ReadFromStorage (SystemNumbers)                                                                                                               │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

38 rows in set. Elapsed: 0.014 sec.

There are some main steps to go:

  1. Alias extracting and expression rewritten by aliases, results will be
SELECT
    number + 1 AS number,
    (number + 1) + 2 AS a,
    sum((number+1)% 3) + 4  as b
FROM numbers(10) group by (number + 1), (number + 1) + 2  having (sum((number+1) % 3) + 4) + 1 > 3
  1. Apply expressions before group by, visit all expressions except aggregate functions.

eg expressions:

plus(number, 1)
plus(plus(number, 1), 2)
modulo(plus(number, 1), 3)
  1. If we already applied expressions, we can make expressions materialized as a Column expression for downstream to get from the block.
ExpressionFunction :  plus(number, 1)     ---> ExpressionColumn:  plus(number, 1) 
  1. Apply expressions to the group by, visit all expressions to find aggregate functions.
 Keys: plus(number, 1), plus(plus(number, 1), 2)
 Aggregates:
    sum(modulo(plus(number, 1), 3))   
  1. Apply expressions after group by

eg:

FUNCTION plus(sum(modulo(plus(number, 1), 3)), 4)

Changelog

  • Improvement

Related Issues

Test Plan

@databend-bot

Copy link
Copy Markdown
Member

Thanks for the contribution!
I have applied any labels matching special text in your title and description.

Please review the labels and make any necessary changes.

@sundy-li sundy-li mentioned this pull request May 24, 2021
@codecov-commenter

codecov-commenter commented May 25, 2021

Copy link
Copy Markdown

Codecov Report

Merging #550 (af0226b) into master (8563bfd) will decrease coverage by 1%.
The diff coverage is 82%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #550    +/-   ##
=======================================
- Coverage      81%     80%    -2%     
=======================================
  Files         292     288     -4     
  Lines       13849   13758    -91     
=======================================
- Hits        11290   11028   -262     
- Misses       2559    2730   +171     
Impacted Files Coverage Δ
common/datavalues/src/data_array.rs 100% <ø> (ø)
common/datavalues/src/data_value.rs 27% <ø> (-3%) ⬇️
common/datavalues/src/data_value_kernel.rs 37% <ø> (ø)
common/datavalues/src/macros.rs 86% <ø> (+27%) ⬆️
common/exception/src/exception.rs 42% <ø> (ø)
common/functions/src/function_alias.rs 0% <0%> (-88%) ⬇️
common/functions/src/function_literal.rs 0% <0%> (-94%) ⬇️
common/functions/src/strings/string.rs 83% <ø> (ø)
common/planners/src/plan_display_test.rs 92% <ø> (ø)
common/planners/src/plan_expression_action_test.rs 95% <0%> (ø)
... and 100 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 8563bfd...af0226b. Read the comment docs.

Comment thread website/datafuse/docs/rfcs/query/2021-05-22-plan-expression-refactor.md Outdated
plan: Result<PlanNode>,
expect: &'static str
expect: &'static str,
err: &'static str

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 is neat to add the expected error here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

err is expected error msg, empty str for normal return.

Comment thread common/aggregate_functions/src/aggregate_avg.rs Outdated
@sundy-li
sundy-li marked this pull request as ready for review May 25, 2021 06:47
@sundy-li
sundy-li requested review from bohutang and zhang2014 May 25, 2021 06:53
Comment thread common/aggregate_functions/src/aggregate_function_factory.rs Outdated
Comment thread common/aggregate_functions/src/test.rs Outdated
Comment thread common/functions/src/test.rs Outdated
"{:?}:{:?}",
plan.exprs[i],
plan.schema().fields()[i].data_type()
plan.exprs[i].to_data_type(&plan.input.schema()).unwrap()

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.

unwrap can cause panic. use ? operator

@sundy-li sundy-li May 25, 2021

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It's for display, may need ErrorCodes to fmt error. We can make another pr to improve this.

use crate::test::Test;
use crate::*;

// Copyright 2020-2021 The Datafuse Authors.

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.

Should be move to file header

/// ExpressionExecutor is a helper struct for expressions and projections
/// Aggregate functions is not covered, because all expressions in aggregate functions functions are executed.
#[derive(Debug, Clone)]
pub struct ExpressionExecutor {

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.

👍 Great work.

@zhang2014 zhang2014 left a comment

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.

LGTM

@ives9638

Copy link
Copy Markdown
Contributor

Feat!

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.

7 participants