From cda183b010a2846afc2e79584f60a92181993a51 Mon Sep 17 00:00:00 2001 From: gaoxingliang Date: Mon, 5 Aug 2019 13:31:25 +0800 Subject: [PATCH 01/10] planner/window: check window args first before checking window specs (#11008) --- planner/core/logical_plan_builder.go | 22 ++++++++++++++++++++++ planner/core/logical_plan_test.go | 8 ++++++++ 2 files changed, 30 insertions(+) diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index 69e831a015009..c3550d7786fef 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -2092,6 +2092,11 @@ func (b *PlanBuilder) buildSelect(ctx context.Context, sel *ast.SelectStmt) (p L var windowMapper map[*ast.WindowFuncExpr]int if hasWindowFuncField { windowFuncs := extractWindowFuncs(sel.Fields.Fields) + // we need to check the func args first before we check the window spec + err := b.checkWindowFuncArgs(ctx, p, windowFuncs, windowAggMap) + if err != nil { + return nil, err + } groupedFuncs, err := b.groupWindowFuncs(windowFuncs) if err != nil { return nil, err @@ -3213,6 +3218,23 @@ func (b *PlanBuilder) buildWindowFunctionFrame(ctx context.Context, spec *ast.Wi return frame, err } +func (b *PlanBuilder) checkWindowFuncArgs(ctx context.Context, p LogicalPlan, windowFuncExprs []*ast.WindowFuncExpr, windowAggMap map[*ast.AggregateFuncExpr]int) error { + for _, windowFuncExpr := range windowFuncExprs { + _, _, _, args, err := b.buildProjectionForWindow(ctx, p, &windowFuncExpr.Spec, windowFuncExpr.Args, windowAggMap) + if err != nil { + return err + } + desc, err := aggregation.NewWindowFuncDesc(b.ctx, windowFuncExpr.F, args) + if err != nil { + return err + } + if desc == nil { + return ErrWrongArguments.GenWithStackByArgs(strings.ToLower(windowFuncExpr.F)) + } + } + return nil +} + func getAllByItems(itemsBuf []*ast.ByItem, spec *ast.WindowSpec) []*ast.ByItem { itemsBuf = itemsBuf[:0] if spec.PartitionBy != nil { diff --git a/planner/core/logical_plan_test.go b/planner/core/logical_plan_test.go index e9334b16ee206..54eab92a11ee6 100644 --- a/planner/core/logical_plan_test.go +++ b/planner/core/logical_plan_test.go @@ -2469,6 +2469,14 @@ func (s *testPlanSuite) TestWindowFunction(c *C) { sql: "SELECT NTH_VALUE(a, 1) FROM LAST IGNORE NULLS over (partition by b order by b), a FROM t", result: "[planner:1235]This version of TiDB doesn't yet support 'IGNORE NULLS'", }, + { + sql: "SELECT NTH_VALUE(fieldA, ATAN(-1)) OVER (w1) AS 'ntile', fieldA, fieldB FROM ( SELECT a AS fieldA, b AS fieldB FROM t ) as te WINDOW w1 AS ( ORDER BY fieldB ASC, fieldA DESC )", + result: "[planner:1210]Incorrect arguments to nth_value", + }, + { + sql: "SELECT NTH_VALUE(fieldA, -1) OVER (w1 PARTITION BY fieldB ORDER BY fieldB , fieldA ) AS 'ntile', fieldA, fieldB FROM ( SELECT a AS fieldA, b AS fieldB FROM t ) as temp WINDOW w1 AS ( ORDER BY fieldB ASC, fieldA DESC )", + result: "[planner:1210]Incorrect arguments to nth_value", + }, } s.Parser.EnableWindowFunc(true) From cc2d22e105316ac9b607057ddeb8126f44fd38b8 Mon Sep 17 00:00:00 2001 From: gaoxingliang Date: Mon, 5 Aug 2019 14:59:18 +0800 Subject: [PATCH 02/10] planner/window: check window args first before checking window specs fix uts (#11008) --- cmd/explaintest/main.go | 3 +- cmd/explaintest/r/window_function.result | 66 ++++++++++++------------ 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/cmd/explaintest/main.go b/cmd/explaintest/main.go index b29b05c93c25e..4e4f6defd9e05 100644 --- a/cmd/explaintest/main.go +++ b/cmd/explaintest/main.go @@ -357,10 +357,9 @@ func (t *tester) execute(query query) error { gotBuf := t.buf.Bytes()[offset:] buf := make([]byte, t.buf.Len()-offset) - if _, err = t.resultFD.ReadAt(buf, int64(offset)); err != nil { + if _, err = t.resultFD.ReadAt(buf, int64(offset)); !(err == nil || err == io.EOF) { return errors.Trace(errors.Errorf("run \"%v\" at line %d err, we got \n%s\nbut read result err %s", st.Text(), query.Line, gotBuf, err)) } - if !bytes.Equal(gotBuf, buf) { return errors.Trace(errors.Errorf("run \"%v\" at line %d err, we need:\n%s\nbut got:\n%s\n", query.Query, query.Line, buf, gotBuf)) } diff --git a/cmd/explaintest/r/window_function.result b/cmd/explaintest/r/window_function.result index 3f4e6132897fe..e75c13a554fe8 100644 --- a/cmd/explaintest/r/window_function.result +++ b/cmd/explaintest/r/window_function.result @@ -4,48 +4,48 @@ create table t (a int, b int, c timestamp, index idx(a)); set @@tidb_enable_window_function = 1; explain select sum(a) over() from t; id count task operator info -Projection_7 10000.00 root sum(a) over() -└─Window_8 10000.00 root sum(cast(test.t.a)) over() - └─TableReader_10 10000.00 root data:TableScan_9 - └─TableScan_9 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo +Projection_8 10000.00 root sum(a) over() +└─Window_9 10000.00 root sum(cast(test.t.a)) over() + └─TableReader_11 10000.00 root data:TableScan_10 + └─TableScan_10 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo explain select sum(a) over(partition by a) from t; id count task operator info -Projection_7 10000.00 root sum(a) over(partition by a) -└─Window_8 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a) - └─IndexReader_10 10000.00 root index:IndexScan_9 - └─IndexScan_9 10000.00 cop table:t, index:a, range:[NULL,+inf], keep order:true, stats:pseudo +Projection_8 10000.00 root sum(a) over(partition by a) +└─Window_9 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a) + └─IndexReader_11 10000.00 root index:IndexScan_10 + └─IndexScan_10 10000.00 cop table:t, index:a, range:[NULL,+inf], keep order:true, stats:pseudo explain select sum(a) over(partition by a order by b) from t; id count task operator info -Projection_7 10000.00 root sum(a) over(partition by a order by b) -└─Window_8 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.b asc range between unbounded preceding and current row) - └─Sort_11 10000.00 root test.t.a:asc, test.t.b:asc - └─TableReader_10 10000.00 root data:TableScan_9 - └─TableScan_9 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo +Projection_8 10000.00 root sum(a) over(partition by a order by b) +└─Window_9 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.b asc range between unbounded preceding and current row) + └─Sort_12 10000.00 root test.t.a:asc, test.t.b:asc + └─TableReader_11 10000.00 root data:TableScan_10 + └─TableScan_10 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo explain select sum(a) over(partition by a order by b rows unbounded preceding) from t; id count task operator info -Projection_7 10000.00 root sum(a) over(partition by a order by b rows unbounded preceding) -└─Window_8 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.b asc rows between unbounded preceding and current row) - └─Sort_11 10000.00 root test.t.a:asc, test.t.b:asc - └─TableReader_10 10000.00 root data:TableScan_9 - └─TableScan_9 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo +Projection_8 10000.00 root sum(a) over(partition by a order by b rows unbounded preceding) +└─Window_9 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.b asc rows between unbounded preceding and current row) + └─Sort_12 10000.00 root test.t.a:asc, test.t.b:asc + └─TableReader_11 10000.00 root data:TableScan_10 + └─TableScan_10 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo explain select sum(a) over(partition by a order by b rows between 1 preceding and 1 following) from t; id count task operator info -Projection_7 10000.00 root sum(a) over(partition by a order by b rows between 1 preceding and 1 following) -└─Window_8 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.b asc rows between 1 preceding and 1 following) - └─Sort_11 10000.00 root test.t.a:asc, test.t.b:asc - └─TableReader_10 10000.00 root data:TableScan_9 - └─TableScan_9 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo +Projection_8 10000.00 root sum(a) over(partition by a order by b rows between 1 preceding and 1 following) +└─Window_9 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.b asc rows between 1 preceding and 1 following) + └─Sort_12 10000.00 root test.t.a:asc, test.t.b:asc + └─TableReader_11 10000.00 root data:TableScan_10 + └─TableScan_10 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo explain select sum(a) over(partition by a order by b range between 1 preceding and 1 following) from t; id count task operator info -Projection_7 10000.00 root sum(a) over(partition by a order by b range between 1 preceding and 1 following) -└─Window_8 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.b asc range between 1 preceding and 1 following) - └─Sort_11 10000.00 root test.t.a:asc, test.t.b:asc - └─TableReader_10 10000.00 root data:TableScan_9 - └─TableScan_9 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo +Projection_8 10000.00 root sum(a) over(partition by a order by b range between 1 preceding and 1 following) +└─Window_9 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.b asc range between 1 preceding and 1 following) + └─Sort_12 10000.00 root test.t.a:asc, test.t.b:asc + └─TableReader_11 10000.00 root data:TableScan_10 + └─TableScan_10 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo explain select sum(a) over(partition by a order by c range between interval '2:30' minute_second preceding and interval '2:30' minute_second following) from t; id count task operator info -Projection_7 10000.00 root sum(a) over(partition by a order by c range between interval '2:30' minute_second preceding and interval '2:30' minute_second following) -└─Window_8 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.c asc range between interval "2:30" "MINUTE_SECOND" preceding and interval "2:30" "MINUTE_SECOND" following) - └─Sort_11 10000.00 root test.t.a:asc, test.t.c:asc - └─TableReader_10 10000.00 root data:TableScan_9 - └─TableScan_9 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo +Projection_8 10000.00 root sum(a) over(partition by a order by c range between interval '2:30' minute_second preceding and interval '2:30' minute_second following) +└─Window_9 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.c asc range between interval "2:30" "MINUTE_SECOND" preceding and interval "2:30" "MINUTE_SECOND" following) + └─Sort_12 10000.00 root test.t.a:asc, test.t.c:asc + └─TableReader_11 10000.00 root data:TableScan_10 + └─TableScan_10 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo From 212a20bdaa9d1c2182d2a93a5ad28edfeacaad09 Mon Sep 17 00:00:00 2001 From: gaoxingliang Date: Wed, 7 Aug 2019 14:03:54 +0800 Subject: [PATCH 03/10] planner/core: default field in order by is not added into fields (#11210) --- expression/integration_test.go | 16 ++++++++++++++++ planner/core/logical_plan_builder.go | 18 ++++++++++++++---- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/expression/integration_test.go b/expression/integration_test.go index c3578ad96d9f7..3f689c5c4f8ce 100644 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -3424,6 +3424,22 @@ func (s *testIntegrationSuite) TestAggregationBuiltinBitAnd(c *C) { result.Check(testkit.Rows("7 7", "5 5", "3 3", "2 2", " 18446744073709551615")) } +func (s *testIntegrationSuite) TestOrderbyWithDefaultFunc(c *C) { + defer s.cleanEnv(c) + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int default null, b int default null)") + tk.MustExec("insert into t values(1, 2), (3, 4)") + tk.MustQuery("select a from t order by default(a)").Check(testkit.Rows("1", "3")) + tk.MustQuery("select a from t order by default(b)").Check(testkit.Rows("1", "3")) + tk.MustQuery("select a, b from t order by default(a)").Check(testkit.Rows("1,2", "3,4")) + tk.MustQuery("select a from t order by length(b)").Check(testkit.Rows("1", "3")) + _, err := tk.Exec("select a, b from t order by default(c)") + c.Assert(err, NotNil) + c.Assert(terror.ErrorEqual(err, plannercore.ErrUnknownColumn.GenWithStackByArgs("c", "order clause")), IsTrue) +} + func (s *testIntegrationSuite) TestAggregationBuiltinGroupConcat(c *C) { defer s.cleanEnv(c) tk := testkit.NewTestKit(c, s.store) diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index c3550d7786fef..d6606a6cf839e 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -1200,8 +1200,8 @@ func (a *havingWindowAndOrderbyExprResolver) Enter(n ast.Node) (node ast.Node, s return n, false } -func (a *havingWindowAndOrderbyExprResolver) resolveFromSchema(v *ast.ColumnNameExpr, schema *expression.Schema) (int, error) { - col, err := schema.FindColumn(v.Name) +func (a *havingWindowAndOrderbyExprResolver) resolveFromSchema(colName *ast.ColumnName, schema *expression.Schema) (int, error) { + col, err := schema.FindColumn(colName) if err != nil { return -1, err } @@ -1253,6 +1253,16 @@ func (a *havingWindowAndOrderbyExprResolver) Leave(n ast.Node) (node ast.Node, o } case *ast.WindowSpec: a.inWindowSpec = false + case *ast.ColumnName: + index, err := a.resolveFromSchema(v, a.p.Schema()) + if err != nil { + a.err = err + return node, false + } + if index == -1 { + a.err = ErrUnknownColumn.GenWithStackByArgs(v.OrigColName(), clauseMsg[a.curClause]) + return node, false + } case *ast.ColumnNameExpr: resolveFieldsFirst := true if a.inAggFunc || a.inWindowFunc || a.inWindowSpec || (a.orderBy && a.inExpr) { @@ -1279,7 +1289,7 @@ func (a *havingWindowAndOrderbyExprResolver) Leave(n ast.Node) (node ast.Node, o } if index == -1 { if a.orderBy { - index, a.err = a.resolveFromSchema(v, a.p.Schema()) + index, a.err = a.resolveFromSchema(v.Name, a.p.Schema()) } else { index, a.err = resolveFromSelectFields(v, a.selectFields, true) } @@ -1288,7 +1298,7 @@ func (a *havingWindowAndOrderbyExprResolver) Leave(n ast.Node) (node ast.Node, o // We should ignore the err when resolving from schema. Because we could resolve successfully // when considering select fields. var err error - index, err = a.resolveFromSchema(v, a.p.Schema()) + index, err = a.resolveFromSchema(v.Name, a.p.Schema()) _ = err if index == -1 && a.curClause != windowClause { index, a.err = resolveFromSelectFields(v, a.selectFields, false) From 98ff1858db40cf53b9adda77a9bc29886b047c24 Mon Sep 17 00:00:00 2001 From: gaoxingliang Date: Thu, 8 Aug 2019 09:05:48 +0800 Subject: [PATCH 04/10] planner/window: fix comments (#11008) --- planner/core/logical_plan_builder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index d6606a6cf839e..9611ea1dfd61b 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -3230,7 +3230,7 @@ func (b *PlanBuilder) buildWindowFunctionFrame(ctx context.Context, spec *ast.Wi func (b *PlanBuilder) checkWindowFuncArgs(ctx context.Context, p LogicalPlan, windowFuncExprs []*ast.WindowFuncExpr, windowAggMap map[*ast.AggregateFuncExpr]int) error { for _, windowFuncExpr := range windowFuncExprs { - _, _, _, args, err := b.buildProjectionForWindow(ctx, p, &windowFuncExpr.Spec, windowFuncExpr.Args, windowAggMap) + _, _, _, args, err := b.buildProjectionForWindow(ctx, p, &ast.WindowSpec{}, windowFuncExpr.Args, windowAggMap) if err != nil { return err } From 447ad5c7bb877c306e9f856857b3ecbcb9056020 Mon Sep 17 00:00:00 2001 From: gaoxingliang Date: Thu, 8 Aug 2019 09:21:38 +0800 Subject: [PATCH 05/10] planner/window: fix comments (#11008) --- planner/core/logical_plan_builder.go | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index 9611ea1dfd61b..d6f6c89ef7051 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -1200,8 +1200,8 @@ func (a *havingWindowAndOrderbyExprResolver) Enter(n ast.Node) (node ast.Node, s return n, false } -func (a *havingWindowAndOrderbyExprResolver) resolveFromSchema(colName *ast.ColumnName, schema *expression.Schema) (int, error) { - col, err := schema.FindColumn(colName) +func (a *havingWindowAndOrderbyExprResolver) resolveFromSchema(v *ast.ColumnNameExpr, schema *expression.Schema) (int, error) { + col, err := schema.FindColumn(v.Name) if err != nil { return -1, err } @@ -1253,16 +1253,6 @@ func (a *havingWindowAndOrderbyExprResolver) Leave(n ast.Node) (node ast.Node, o } case *ast.WindowSpec: a.inWindowSpec = false - case *ast.ColumnName: - index, err := a.resolveFromSchema(v, a.p.Schema()) - if err != nil { - a.err = err - return node, false - } - if index == -1 { - a.err = ErrUnknownColumn.GenWithStackByArgs(v.OrigColName(), clauseMsg[a.curClause]) - return node, false - } case *ast.ColumnNameExpr: resolveFieldsFirst := true if a.inAggFunc || a.inWindowFunc || a.inWindowSpec || (a.orderBy && a.inExpr) { @@ -1289,7 +1279,7 @@ func (a *havingWindowAndOrderbyExprResolver) Leave(n ast.Node) (node ast.Node, o } if index == -1 { if a.orderBy { - index, a.err = a.resolveFromSchema(v.Name, a.p.Schema()) + index, a.err = a.resolveFromSchema(v, a.p.Schema()) } else { index, a.err = resolveFromSelectFields(v, a.selectFields, true) } @@ -1298,7 +1288,7 @@ func (a *havingWindowAndOrderbyExprResolver) Leave(n ast.Node) (node ast.Node, o // We should ignore the err when resolving from schema. Because we could resolve successfully // when considering select fields. var err error - index, err = a.resolveFromSchema(v.Name, a.p.Schema()) + index, err = a.resolveFromSchema(v, a.p.Schema()) _ = err if index == -1 && a.curClause != windowClause { index, a.err = resolveFromSelectFields(v, a.selectFields, false) From ddbdce37b86c0a1b4afd7ecf572046237b1484ec Mon Sep 17 00:00:00 2001 From: gaoxingliang Date: Thu, 8 Aug 2019 09:30:09 +0800 Subject: [PATCH 06/10] planner/window: fix comments (#11008) --- planner/core/logical_plan_builder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index d6f6c89ef7051..c3550d7786fef 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -3220,7 +3220,7 @@ func (b *PlanBuilder) buildWindowFunctionFrame(ctx context.Context, spec *ast.Wi func (b *PlanBuilder) checkWindowFuncArgs(ctx context.Context, p LogicalPlan, windowFuncExprs []*ast.WindowFuncExpr, windowAggMap map[*ast.AggregateFuncExpr]int) error { for _, windowFuncExpr := range windowFuncExprs { - _, _, _, args, err := b.buildProjectionForWindow(ctx, p, &ast.WindowSpec{}, windowFuncExpr.Args, windowAggMap) + _, _, _, args, err := b.buildProjectionForWindow(ctx, p, &windowFuncExpr.Spec, windowFuncExpr.Args, windowAggMap) if err != nil { return err } From 0dd992f7613200f64bbec67f7cf6d332c21bdc3a Mon Sep 17 00:00:00 2001 From: gaoxingliang Date: Thu, 8 Aug 2019 09:36:34 +0800 Subject: [PATCH 07/10] planner/window: fix comments (#11008) --- expression/integration_test.go | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/expression/integration_test.go b/expression/integration_test.go index 3f689c5c4f8ce..c3578ad96d9f7 100644 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -3424,22 +3424,6 @@ func (s *testIntegrationSuite) TestAggregationBuiltinBitAnd(c *C) { result.Check(testkit.Rows("7 7", "5 5", "3 3", "2 2", " 18446744073709551615")) } -func (s *testIntegrationSuite) TestOrderbyWithDefaultFunc(c *C) { - defer s.cleanEnv(c) - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int default null, b int default null)") - tk.MustExec("insert into t values(1, 2), (3, 4)") - tk.MustQuery("select a from t order by default(a)").Check(testkit.Rows("1", "3")) - tk.MustQuery("select a from t order by default(b)").Check(testkit.Rows("1", "3")) - tk.MustQuery("select a, b from t order by default(a)").Check(testkit.Rows("1,2", "3,4")) - tk.MustQuery("select a from t order by length(b)").Check(testkit.Rows("1", "3")) - _, err := tk.Exec("select a, b from t order by default(c)") - c.Assert(err, NotNil) - c.Assert(terror.ErrorEqual(err, plannercore.ErrUnknownColumn.GenWithStackByArgs("c", "order clause")), IsTrue) -} - func (s *testIntegrationSuite) TestAggregationBuiltinGroupConcat(c *C) { defer s.cleanEnv(c) tk := testkit.NewTestKit(c, s.store) From 0e3c0b55ef69efcac65e50afdee3164e408105da Mon Sep 17 00:00:00 2001 From: gaoxingliang Date: Thu, 8 Aug 2019 09:37:16 +0800 Subject: [PATCH 08/10] planner/window: fix comments by using a dummy window spec(#11008) --- planner/core/logical_plan_builder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index c3550d7786fef..d6f6c89ef7051 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -3220,7 +3220,7 @@ func (b *PlanBuilder) buildWindowFunctionFrame(ctx context.Context, spec *ast.Wi func (b *PlanBuilder) checkWindowFuncArgs(ctx context.Context, p LogicalPlan, windowFuncExprs []*ast.WindowFuncExpr, windowAggMap map[*ast.AggregateFuncExpr]int) error { for _, windowFuncExpr := range windowFuncExprs { - _, _, _, args, err := b.buildProjectionForWindow(ctx, p, &windowFuncExpr.Spec, windowFuncExpr.Args, windowAggMap) + _, _, _, args, err := b.buildProjectionForWindow(ctx, p, &ast.WindowSpec{}, windowFuncExpr.Args, windowAggMap) if err != nil { return err } From 24ef841346ce972de801f545af42c9526d5ae4ec Mon Sep 17 00:00:00 2001 From: gaoxingliang Date: Thu, 8 Aug 2019 17:31:30 +0800 Subject: [PATCH 09/10] planner/window: fix comments by using a dummy window spec(#11008) --- planner/core/logical_plan_builder.go | 31 +++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index d6f6c89ef7051..0410bd3f4d2f5 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -3054,6 +3054,35 @@ func (b *PlanBuilder) buildProjectionForWindow(ctx context.Context, p LogicalPla return proj, propertyItems[:lenPartition], propertyItems[lenPartition:], newArgList, nil } +func (b *PlanBuilder) buildArgs4WindowFunc(ctx context.Context, p LogicalPlan, args []ast.ExprNode, aggMap map[*ast.AggregateFuncExpr]int) ([]expression.Expression, error) { + b.optFlag |= flagEliminateProjection + + newArgList := make([]expression.Expression, 0, len(args)) + // use below index for created a new col definition + // it's okay here because we only want to return the args used in window function + newColIndex := 0 + for _, arg := range args { + newArg, np, err := b.rewrite(ctx, arg, p, aggMap, true) + if err != nil { + return nil, err + } + p = np + switch newArg.(type) { + case *expression.Column, *expression.Constant: + newArgList = append(newArgList, newArg) + continue + } + col := &expression.Column{ + ColName: model.NewCIStr(fmt.Sprintf("%d_proj_window_%d", p.ID(), newColIndex)), + UniqueID: b.ctx.GetSessionVars().AllocPlanColumnID(), + RetType: newArg.GetType(), + } + newColIndex += 1 + newArgList = append(newArgList, col) + } + return newArgList, nil +} + func (b *PlanBuilder) buildByItemsForWindow( ctx context.Context, p LogicalPlan, @@ -3220,7 +3249,7 @@ func (b *PlanBuilder) buildWindowFunctionFrame(ctx context.Context, spec *ast.Wi func (b *PlanBuilder) checkWindowFuncArgs(ctx context.Context, p LogicalPlan, windowFuncExprs []*ast.WindowFuncExpr, windowAggMap map[*ast.AggregateFuncExpr]int) error { for _, windowFuncExpr := range windowFuncExprs { - _, _, _, args, err := b.buildProjectionForWindow(ctx, p, &ast.WindowSpec{}, windowFuncExpr.Args, windowAggMap) + args, err := b.buildArgs4WindowFunc(ctx, p, windowFuncExpr.Args, windowAggMap) if err != nil { return err } From 85d9720b3d7d6eb457fd77f706b73fe22f73c723 Mon Sep 17 00:00:00 2001 From: gaoxingliang Date: Fri, 9 Aug 2019 14:18:25 +0800 Subject: [PATCH 10/10] planner/window: fix explain test(#11008) --- cmd/explaintest/r/window_function.result | 66 ++++++++++++------------ 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/cmd/explaintest/r/window_function.result b/cmd/explaintest/r/window_function.result index e75c13a554fe8..3f4e6132897fe 100644 --- a/cmd/explaintest/r/window_function.result +++ b/cmd/explaintest/r/window_function.result @@ -4,48 +4,48 @@ create table t (a int, b int, c timestamp, index idx(a)); set @@tidb_enable_window_function = 1; explain select sum(a) over() from t; id count task operator info -Projection_8 10000.00 root sum(a) over() -└─Window_9 10000.00 root sum(cast(test.t.a)) over() - └─TableReader_11 10000.00 root data:TableScan_10 - └─TableScan_10 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo +Projection_7 10000.00 root sum(a) over() +└─Window_8 10000.00 root sum(cast(test.t.a)) over() + └─TableReader_10 10000.00 root data:TableScan_9 + └─TableScan_9 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo explain select sum(a) over(partition by a) from t; id count task operator info -Projection_8 10000.00 root sum(a) over(partition by a) -└─Window_9 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a) - └─IndexReader_11 10000.00 root index:IndexScan_10 - └─IndexScan_10 10000.00 cop table:t, index:a, range:[NULL,+inf], keep order:true, stats:pseudo +Projection_7 10000.00 root sum(a) over(partition by a) +└─Window_8 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a) + └─IndexReader_10 10000.00 root index:IndexScan_9 + └─IndexScan_9 10000.00 cop table:t, index:a, range:[NULL,+inf], keep order:true, stats:pseudo explain select sum(a) over(partition by a order by b) from t; id count task operator info -Projection_8 10000.00 root sum(a) over(partition by a order by b) -└─Window_9 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.b asc range between unbounded preceding and current row) - └─Sort_12 10000.00 root test.t.a:asc, test.t.b:asc - └─TableReader_11 10000.00 root data:TableScan_10 - └─TableScan_10 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo +Projection_7 10000.00 root sum(a) over(partition by a order by b) +└─Window_8 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.b asc range between unbounded preceding and current row) + └─Sort_11 10000.00 root test.t.a:asc, test.t.b:asc + └─TableReader_10 10000.00 root data:TableScan_9 + └─TableScan_9 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo explain select sum(a) over(partition by a order by b rows unbounded preceding) from t; id count task operator info -Projection_8 10000.00 root sum(a) over(partition by a order by b rows unbounded preceding) -└─Window_9 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.b asc rows between unbounded preceding and current row) - └─Sort_12 10000.00 root test.t.a:asc, test.t.b:asc - └─TableReader_11 10000.00 root data:TableScan_10 - └─TableScan_10 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo +Projection_7 10000.00 root sum(a) over(partition by a order by b rows unbounded preceding) +└─Window_8 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.b asc rows between unbounded preceding and current row) + └─Sort_11 10000.00 root test.t.a:asc, test.t.b:asc + └─TableReader_10 10000.00 root data:TableScan_9 + └─TableScan_9 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo explain select sum(a) over(partition by a order by b rows between 1 preceding and 1 following) from t; id count task operator info -Projection_8 10000.00 root sum(a) over(partition by a order by b rows between 1 preceding and 1 following) -└─Window_9 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.b asc rows between 1 preceding and 1 following) - └─Sort_12 10000.00 root test.t.a:asc, test.t.b:asc - └─TableReader_11 10000.00 root data:TableScan_10 - └─TableScan_10 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo +Projection_7 10000.00 root sum(a) over(partition by a order by b rows between 1 preceding and 1 following) +└─Window_8 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.b asc rows between 1 preceding and 1 following) + └─Sort_11 10000.00 root test.t.a:asc, test.t.b:asc + └─TableReader_10 10000.00 root data:TableScan_9 + └─TableScan_9 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo explain select sum(a) over(partition by a order by b range between 1 preceding and 1 following) from t; id count task operator info -Projection_8 10000.00 root sum(a) over(partition by a order by b range between 1 preceding and 1 following) -└─Window_9 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.b asc range between 1 preceding and 1 following) - └─Sort_12 10000.00 root test.t.a:asc, test.t.b:asc - └─TableReader_11 10000.00 root data:TableScan_10 - └─TableScan_10 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo +Projection_7 10000.00 root sum(a) over(partition by a order by b range between 1 preceding and 1 following) +└─Window_8 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.b asc range between 1 preceding and 1 following) + └─Sort_11 10000.00 root test.t.a:asc, test.t.b:asc + └─TableReader_10 10000.00 root data:TableScan_9 + └─TableScan_9 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo explain select sum(a) over(partition by a order by c range between interval '2:30' minute_second preceding and interval '2:30' minute_second following) from t; id count task operator info -Projection_8 10000.00 root sum(a) over(partition by a order by c range between interval '2:30' minute_second preceding and interval '2:30' minute_second following) -└─Window_9 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.c asc range between interval "2:30" "MINUTE_SECOND" preceding and interval "2:30" "MINUTE_SECOND" following) - └─Sort_12 10000.00 root test.t.a:asc, test.t.c:asc - └─TableReader_11 10000.00 root data:TableScan_10 - └─TableScan_10 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo +Projection_7 10000.00 root sum(a) over(partition by a order by c range between interval '2:30' minute_second preceding and interval '2:30' minute_second following) +└─Window_8 10000.00 root sum(cast(test.t.a)) over(partition by test.t.a order by test.t.c asc range between interval "2:30" "MINUTE_SECOND" preceding and interval "2:30" "MINUTE_SECOND" following) + └─Sort_11 10000.00 root test.t.a:asc, test.t.c:asc + └─TableReader_10 10000.00 root data:TableScan_9 + └─TableScan_9 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo