diff --git a/executor/ddl_test.go b/executor/ddl_test.go index c31a409d0b77b..8fc754930ab10 100644 --- a/executor/ddl_test.go +++ b/executor/ddl_test.go @@ -254,6 +254,47 @@ func (s *testSuite3) TestCreateView(c *C) { tk.MustExec("drop view v") } +func (s *testSuite3) TestCreateViewWithOverlongColName(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("create table t(a int)") + defer tk.MustExec("drop table t") + tk.MustExec("create view v as select distinct'" + strings.Repeat("a", 65) + "', " + + "max('" + strings.Repeat("b", 65) + "'), " + + "'cccccccccc', '" + strings.Repeat("d", 65) + "';") + resultCreateStmt := "CREATE ALGORITHM=UNDEFINED DEFINER=``@`` SQL SECURITY DEFINER VIEW `v` (`name_exp_1`, `name_exp_2`, `cccccccccc`, `name_exp_4`) AS SELECT DISTINCT '" + strings.Repeat("a", 65) + "',MAX('" + strings.Repeat("b", 65) + "'),'cccccccccc','" + strings.Repeat("d", 65) + "'" + tk.MustQuery("select * from v") + tk.MustQuery("select name_exp_1, name_exp_2, cccccccccc, name_exp_4 from v") + tk.MustQuery("show create view v").Check(testkit.Rows("v " + resultCreateStmt + " ")) + tk.MustExec("drop view v;") + tk.MustExec(resultCreateStmt) + + tk.MustExec("drop view v ") + tk.MustExec("create definer='root'@'localhost' view v as select 'a', '" + strings.Repeat("b", 65) + "' from t " + + "union select '" + strings.Repeat("c", 65) + "', " + + "count(distinct '" + strings.Repeat("b", 65) + "', " + + "'c');") + resultCreateStmt = "CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v` (`a`, `name_exp_2`) AS SELECT 'a','" + strings.Repeat("b", 65) + "' FROM `test`.`t` UNION SELECT '" + strings.Repeat("c", 65) + "',COUNT(DISTINCT '" + strings.Repeat("b", 65) + "', 'c')" + tk.MustQuery("select * from v") + tk.MustQuery("select a, name_exp_2 from v") + tk.MustQuery("show create view v").Check(testkit.Rows("v " + resultCreateStmt + " ")) + tk.MustExec("drop view v;") + tk.MustExec(resultCreateStmt) + + tk.MustExec("drop view v ") + tk.MustExec("create definer='root'@'localhost' view v as select 'a' as '" + strings.Repeat("b", 65) + "' from t;") + tk.MustQuery("select * from v") + tk.MustQuery("select name_exp_1 from v") + resultCreateStmt = "CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v` (`name_exp_1`) AS SELECT 'a' AS `" + strings.Repeat("b", 65) + "` FROM `test`.`t`" + tk.MustQuery("show create view v").Check(testkit.Rows("v " + resultCreateStmt + " ")) + tk.MustExec("drop view v;") + tk.MustExec(resultCreateStmt) + + tk.MustExec("drop view v ") + err := tk.ExecToErr("create view v(`" + strings.Repeat("b", 65) + "`) as select a from t;") + c.Assert(err.Error(), Equals, "[ddl:1059]Identifier name 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' is too long") +} + func (s *testSuite3) TestCreateDropDatabase(c *C) { tk := testkit.NewTestKit(c, s.store) tk.MustExec("create database if not exists drop_test;") diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 6fcc84b3e89b9..b49ae3b3eed87 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -2204,6 +2204,7 @@ func (b *PlanBuilder) buildDDL(ctx context.Context, node ast.DDLNode) (Plan, err } schema := plan.Schema() if v.Cols == nil { + adjustOverlongViewColname(plan.(LogicalPlan)) v.Cols = make([]model.CIStr, len(schema.Columns)) for i, col := range schema.Columns { v.Cols[i] = col.ColName @@ -2212,14 +2213,12 @@ func (b *PlanBuilder) buildDDL(ctx context.Context, node ast.DDLNode) (Plan, err if len(v.Cols) != schema.Len() { return nil, ddl.ErrViewWrongList } - if _, ok := plan.(LogicalPlan); ok { - if b.ctx.GetSessionVars().User != nil { - authErr = ErrTableaccessDenied.GenWithStackByArgs("CREATE VIEW", b.ctx.GetSessionVars().User.Hostname, - b.ctx.GetSessionVars().User.Username, v.ViewName.Name.L) - } - b.visitInfo = appendVisitInfo(b.visitInfo, mysql.CreateViewPriv, v.ViewName.Schema.L, - v.ViewName.Name.L, "", authErr) + if b.ctx.GetSessionVars().User != nil { + authErr = ErrTableaccessDenied.GenWithStackByArgs("CREATE VIEW", b.ctx.GetSessionVars().User.Hostname, + b.ctx.GetSessionVars().User.Username, v.ViewName.Name.L) } + b.visitInfo = appendVisitInfo(b.visitInfo, mysql.CreateViewPriv, v.ViewName.Schema.L, + v.ViewName.Name.L, "", authErr) if v.Definer.CurrentUser && b.ctx.GetSessionVars().User != nil { v.Definer = b.ctx.GetSessionVars().User } @@ -2592,3 +2591,15 @@ func buildChecksumTableSchema() *expression.Schema { schema.Append(buildColumn("", "Total_bytes", mysql.TypeLonglong, 22)) return schema } + +// adjustOverlongViewColname adjusts the overlong outputNames of a view to +// `new_exp_$off` where `$off` is the offset of the output column, $off starts from 1. +// There is still some MySQL compatible problems. +func adjustOverlongViewColname(plan LogicalPlan) { + outputCols := plan.Schema().Columns + for i := range outputCols { + if outputName := outputCols[i].ColName.L; len(outputName) > mysql.MaxColumnNameLength { + outputCols[i].ColName = model.NewCIStr(fmt.Sprintf("name_exp_%d", i+1)) + } + } +}