diff --git a/planner/core/integration_test.go b/planner/core/integration_test.go index 929a5c5aca..b18f1649bd 100644 --- a/planner/core/integration_test.go +++ b/planner/core/integration_test.go @@ -4111,6 +4111,18 @@ func (s *testIntegrationSerialSuite) TestIssue26214(c *C) { c.Assert(core.ErrUnknownColumn.Equal(err), IsTrue) } +func (s *testIntegrationSuite) TestCreateViewWithWindowFunc(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t6;") + tk.MustExec("CREATE TABLE t6(t TIME, ts TIMESTAMP);") + tk.MustExec("INSERT INTO t6 VALUES ('12:30', '2016-07-05 08:30:42');") + tk.MustExec("drop view if exists v;") + tk.MustExec("CREATE definer='root'@'localhost' VIEW v AS SELECT COUNT(*) OVER w0, COUNT(*) OVER w from t6 WINDOW w0 AS (), w AS (w0 ORDER BY t);") + rows := tk.MustQuery("select * from v;") + rows.Check(testkit.Rows("1 1")) +} + func (s *testIntegrationSerialSuite) TestLimitPushDown(c *C) { tk := testkit.NewTestKit(c, s.store) tk.MustExec("use test") diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index a9a3978329..8b68ee4701 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -1133,6 +1133,9 @@ func (b *PlanBuilder) buildProjectionField(ctx context.Context, p LogicalPlan, f if isCol { return col, name, nil } + if expr == nil { + return nil, name, nil + } newCol := &expression.Column{ UniqueID: b.ctx.GetSessionVars().AllocPlanColumnID(), RetType: expr.GetType(), @@ -3175,15 +3178,37 @@ func unfoldWildStar(field *ast.SelectField, outputName types.NameSlice, column [ return resultList } -func (b *PlanBuilder) addAliasName(selectFields []*ast.SelectField, p LogicalPlan) (resultList []*ast.SelectField, err error) { - if len(selectFields) != len(p.OutputNames()) { - return nil, errors.Errorf("lengths of selectFields and OutputNames are not equal(%d, %d)", - len(selectFields), len(p.OutputNames())) +func (b *PlanBuilder) addAliasName(ctx context.Context, selectFields []*ast.SelectField, p LogicalPlan) (resultList []*ast.SelectField, err error) { + projOutNames := make([]*types.FieldName, 0, len(selectFields)) + for _, field := range selectFields { + colNameField, isColumnNameExpr := field.Expr.(*ast.ColumnNameExpr) + if isColumnNameExpr { + colName := colNameField.Name.Name + if field.AsName.L != "" { + colName = field.AsName + } + projOutNames = append(projOutNames, &types.FieldName{ + TblName: colNameField.Name.Table, + OrigTblName: colNameField.Name.Table, + ColName: colName, + OrigColName: colNameField.Name.Name, + DBName: colNameField.Name.Schema, + }) + } else { + // create view v as select name_const('col', 100); + // The column in v should be 'col', so we call `buildProjectionField` to handle this. + _, name, err := b.buildProjectionField(ctx, p, field, nil) + if err != nil { + return nil, err + } + projOutNames = append(projOutNames, name) + } } + for i, field := range selectFields { newField := *field if newField.AsName.L == "" { - newField.AsName = p.OutputNames()[i].ColName + newField.AsName = projOutNames[i].ColName } resultList = append(resultList, &newField) } @@ -3475,6 +3500,11 @@ func (b *PlanBuilder) buildSelect(ctx context.Context, sel *ast.SelectStmt) (p L return nil, err } if b.capFlag&canExpandAST != 0 { + // To be compabitle with MySQL, we add alias name for each select field when creating view. + sel.Fields.Fields, err = b.addAliasName(ctx, sel.Fields.Fields, p) + if err != nil { + return nil, err + } originalFields = sel.Fields.Fields } @@ -3585,17 +3615,6 @@ func (b *PlanBuilder) buildSelect(ctx context.Context, sel *ast.SelectStmt) (p L return nil, err } - if b.capFlag&canExpandAST != 0 { - // To be compabitle with MySQL, we add alias name for each select field when creating view. - // This function assumes one to one mapping between sel.Fields.Fields and p.OutputNames(). - // So we do this step right after Projection is built. - sel.Fields.Fields, err = b.addAliasName(sel.Fields.Fields, p) - if err != nil { - return nil, err - } - originalFields = sel.Fields.Fields - } - if sel.Having != nil { b.curClause = havingClause p, err = b.buildSelection(ctx, p, sel.Having.Expr, havingMap)