From ee3619ce1c00008c231ce375af14bdab1b0a6f49 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 fa88887fae90c..52f80e4efbbfe 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 @@ -3099,6 +3104,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 987f91befaee0..4482026f822e3 100644 --- a/planner/core/logical_plan_test.go +++ b/planner/core/logical_plan_test.go @@ -2485,6 +2485,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 f94a75b2cff28b0febba5c4686e9edab4df5c7d4 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 34eb979683f68..17f5f40a6dff5 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 3c36924013d0a0ffdc7cdf12ab48eb7c0f3ef620 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 32bde832f3b39..c3b59f93be390 100644 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -3322,6 +3322,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 52f80e4efbbfe..5ceb7488704ed 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 f0c592649fbdd99dfa06b0bf5b2dabd62bd2964c 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 5ceb7488704ed..ad7a222854a8d 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -3116,7 +3116,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 82740f0a2f6383d298058669b786502ade7b3847 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 ad7a222854a8d..938869ffff5e2 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 19722ebac21abb10c650a269f651774af48bf17f 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 938869ffff5e2..52f80e4efbbfe 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -3106,7 +3106,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 5fa8be3b0c6754f2dc75f97e3a02e0916c31deaa 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 c3b59f93be390..32bde832f3b39 100644 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -3322,22 +3322,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 ee146a61055014a703e893812b539af78449bb05 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 52f80e4efbbfe..938869ffff5e2 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -3106,7 +3106,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 ea42dd6c39e941f00e032b2932ccf424ab100cbf 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 938869ffff5e2..517746047d580 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -2943,6 +2943,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, @@ -3106,7 +3135,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 02a98afde8024d7d9c24a9701440e1fc40cf5ceb 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