Skip to content

Commit

Permalink
planner: Do not allow variables in create view (#57474) (#59632)
Browse files Browse the repository at this point in the history
close #53176
  • Loading branch information
ti-chi-bot authored Feb 20, 2025
1 parent 921ae60 commit 14318a2
Show file tree
Hide file tree
Showing 8 changed files with 239 additions and 3 deletions.
5 changes: 5 additions & 0 deletions errors.toml
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,11 @@ error = '''
View's SELECT contains a '%s' clause
'''

["ddl:1351"]
error = '''
View's SELECT contains a variable or parameter
'''

["ddl:1353"]
error = '''
In definition of view, derived table or common table expression, SELECT list and column names list have different column counts
Expand Down
5 changes: 2 additions & 3 deletions pkg/executor/test/ddl/ddl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,8 @@ func TestCreateView(t *testing.T) {
// drop multiple views in a statement
tk.MustExec("drop view v1,v2,v3,v4,v5,v6")
// view with variable
tk.MustExec("create view v1 (c,d) as select a,b+@@global.max_user_connections from t1")
tk.MustGetErrMsg("create view v1 (c,d) as select a,b from t1 where a = @@global.max_user_connections", "[schema:1050]Table 'test.v1' already exists")
tk.MustExec("drop view v1")
tk.MustGetErrMsg("create view v1 (c,d) as select a,b+@@global.max_user_connections from t1", "[ddl:1351]View's SELECT contains a variable or parameter")
tk.MustGetErrMsg("create view v1 (c,d) as select a,b from t1 where a = @@global.max_user_connections", "[ddl:1351]View's SELECT contains a variable or parameter")
// view with different col counts
tk.MustGetErrCode("create view v1 (c,d,e) as select a,b from t1 ", errno.ErrViewWrongList)
tk.MustGetErrCode("create view v1 (c) as select a,b from t1 ", errno.ErrViewWrongList)
Expand Down
30 changes: 30 additions & 0 deletions pkg/planner/core/planbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -4827,6 +4827,32 @@ func convertValueListToData(valueList []ast.ExprNode, handleColInfos []*model.Co
return data, nil
}

type userVariableChecker struct {
hasUserVariables bool
}

func (e *userVariableChecker) Enter(in ast.Node) (ast.Node, bool) {
if _, ok := in.(*ast.VariableExpr); ok {
e.hasUserVariables = true
return in, true
}
return in, false
}

func (*userVariableChecker) Leave(in ast.Node) (ast.Node, bool) {
return in, true
}

// Check for UserVariables
func checkForUserVariables(in ast.Node) error {
v := &userVariableChecker{hasUserVariables: false}
_, ok := in.Accept(v)
if !ok || v.hasUserVariables {
return dbterror.ErrViewSelectVariable
}
return nil
}

func (b *PlanBuilder) buildDDL(ctx context.Context, node ast.DDLNode) (Plan, error) {
var authErr error
switch v := node.(type) {
Expand Down Expand Up @@ -4974,6 +5000,10 @@ func (b *PlanBuilder) buildDDL(ctx context.Context, node ast.DDLNode) (Plan, err
v.ReferTable.Name.L, "", authErr)
}
case *ast.CreateViewStmt:
err := checkForUserVariables(v.Select)
if err != nil {
return nil, err
}
b.isCreateView = true
b.capFlag |= canExpandAST | renameView
b.renamingViewName = v.ViewName.Schema.L + "." + v.ViewName.Name.L
Expand Down
2 changes: 2 additions & 0 deletions pkg/util/dbterror/ddl_terror.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ var (
ErrErrorOnRename = ClassDDL.NewStd(mysql.ErrErrorOnRename)
// ErrViewSelectClause returns error for create view with select into clause
ErrViewSelectClause = ClassDDL.NewStd(mysql.ErrViewSelectClause)
// ErrViewSelectVariable returns error for create view with select into clause
ErrViewSelectVariable = ClassDDL.NewStd(mysql.ErrViewSelectVariable)

// ErrNotAllowedTypeInPartition returns not allowed type error when creating table partition with unsupported expression type.
ErrNotAllowedTypeInPartition = ClassDDL.NewStd(mysql.ErrFieldTypeNotAllowedAsPartitionField)
Expand Down
8 changes: 8 additions & 0 deletions tests/integrationtest/r/ddl/ddl_error.result
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,11 @@ Error 1450 (HY000): Changing schema from 'ddl__ddl_error' to 'ddl__ddl_error2' i
rename table ddl__ddl_error.view_1 to ddl__ddl_error2.view_1;
Error 1450 (HY000): Changing schema from 'ddl__ddl_error' to 'ddl__ddl_error2' is not allowed.
rename table ddl__ddl_error.view_1 to ddl__ddl_error.view_1000;
create view sql_mode_view as select @@sql_mode;
Error 1351 (HY000): View's SELECT contains a variable or parameter
create view sql_mode_view as select @@global.sql_mode;
Error 1351 (HY000): View's SELECT contains a variable or parameter
create view sql_mode_view as select @a;
Error 1351 (HY000): View's SELECT contains a variable or parameter
create view sql_mode_view as select 1 where @a = 4;
Error 1351 (HY000): View's SELECT contains a variable or parameter
96 changes: 96 additions & 0 deletions tests/integrationtest/r/executor/ddl.result
Original file line number Diff line number Diff line change
Expand Up @@ -296,3 +296,99 @@ ALTER TABLE t_1 ADD FOREIGN KEY fk_t_id(t_id) references t(id);
Error 8152 (HY000): Set TTL for a table referenced by foreign key is not allowed
drop table t,t_1;
set global tidb_enable_foreign_key=default;
drop table if exists source_table, t1, t2, test_v_nested;
drop view if exists view_t, v, v1, v2, v3, v4, v5, v6, v7, v_nested, v_nested2;
CREATE TABLE source_table (id INT NOT NULL DEFAULT 1, name varchar(255), PRIMARY KEY(id));
CREATE VIEW view_t AS select id , name from source_table;
CREATE VIEW view_t AS select id , name from source_table;
Error 1050 (42S01): Table 'executor__ddl.view_t' already exists
create view v1 (c,d) as select a,b from t1;
Error 1146 (42S02): Table 'executor__ddl.t1' doesn't exist
create table t1 (a int ,b int);
insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10);
create view v1 (c) as select b+1 from t1;
create view v2 as select b+1 from t1;
create view v3 as select b+1 as c from t1;
create view v4 (c) as select b+1 as d from t1;
create view v5 as select * from t1;
create view v6 (c,d) as select * from t1;
create view v7 (c,d,e) as select * from t1;
Error 1353 (HY000): In definition of view, derived table or common table expression, SELECT list and column names list have different column counts
drop view v1,v2,v3,v4,v5,v6;
create view v1 (c,d) as select a,b+@@global.max_user_connections from t1;
Error 1351 (HY000): View's SELECT contains a variable or parameter
create view v1 (c,d) as select a,b from t1 where a = @@global.max_user_connections;
Error 1351 (HY000): View's SELECT contains a variable or parameter
create view v1 (c,d,e) as select a,b from t1 ;
Error 1353 (HY000): In definition of view, derived table or common table expression, SELECT list and column names list have different column counts
create view v1 (c) as select a,b from t1 ;
Error 1353 (HY000): In definition of view, derived table or common table expression, SELECT list and column names list have different column counts
drop view if exists v1;
create view v1 (c,d) as select a,b from t1;
create or replace view v1 (c,d) as select a,b from t1 ;
create table if not exists t1 (a int ,b int);
create or replace view t1 as select * from t1;
Error 1347 (HY000): 'executor__ddl.t1' is not VIEW
prepare stmt from "create view v10 (x) as select 1";
execute stmt;

drop table if exists t1, t2;
drop view if exists v;
create view v as select * from t1 union select * from t2;
Error 1146 (42S02): Table 'executor__ddl.t1' doesn't exist
create table t1(a int, b int);
create table t2(a int, b int);
insert into t1 values(1,2), (1,1), (1,2);
insert into t2 values(1,1),(1,3);
create definer='root'@'localhost' view v as select * from t1 union select * from t2;
select * from v;
a b
1 1
1 2
1 3
alter table t1 drop column a;
select * from v;
Error 1356 (HY000): View 'executor__ddl.v' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
alter table t1 add column a int;
select * from v;
a b
NULL 1
NULL 2
1 1
1 3
alter table t1 drop column a;
alter table t2 drop column b;
select * from v;
Error 1356 (HY000): View 'executor__ddl.v' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
drop view v;
create view v as (select * from t1);
drop view v;
create view v as (select * from t1 union select * from t2);
drop view v;
drop view if exists v_if_exists;
show warnings;
Level Code Message
Note 1051 Unknown table 'executor__ddl.v_if_exists'
create view v1_if_exists as (select * from t1);
drop view if exists v1_if_exists,v2_if_exists,v3_if_exists;
show warnings;
Level Code Message
Note 1051 Unknown table 'executor__ddl.v2_if_exists'
Note 1051 Unknown table 'executor__ddl.v3_if_exists'
create table test_v_nested(a int);
create definer='root'@'localhost' view v_nested as select * from test_v_nested;
create definer='root'@'localhost' view v_nested2 as select * from v_nested;
create or replace definer='root'@'localhost' view v_nested as select * from v_nested2;
Error 1146 (42S02): Table 'executor__ddl.v_nested' doesn't exist
drop table test_v_nested;
drop view v_nested, v_nested2;
create view v_stale as select * from source_table as of timestamp current_timestamp(3);
Error 1356 (HY000): View 'executor__ddl.v_stale' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
drop view if exists v1,v2;
drop table if exists t1;
CREATE TABLE t1(a INT, b INT);
CREATE DEFINER=1234567890abcdefGHIKL1234567890abcdefGHIKL@localhost VIEW v1 AS SELECT a FROM t1;
Error 1470 (HY000): String '1234567890abcdefGHIKL1234567890abcdefGHIKL' is too long for user name (should be no longer than 32)
CREATE DEFINER=some_user_name@host_1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890X VIEW v2 AS SELECT b FROM t1;
Error 1470 (HY000): String 'host_1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij12345' is too long for host name (should be no longer than 255)
DROP VIEW IF EXISTS view_t;
9 changes: 9 additions & 0 deletions tests/integrationtest/t/ddl/ddl_error.test
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,12 @@ rename table ddl__ddl_error.view_1 to ddl__ddl_error2.view_1;
rename table ddl__ddl_error.view_1 to ddl__ddl_error2.view_1;
rename table ddl__ddl_error.view_1 to ddl__ddl_error.view_1000;

# issue 53176
-- error 1351
create view sql_mode_view as select @@sql_mode;
-- error 1351
create view sql_mode_view as select @@global.sql_mode;
-- error 1351
create view sql_mode_view as select @a;
-- error 1351
create view sql_mode_view as select 1 where @a = 4;
87 changes: 87 additions & 0 deletions tests/integrationtest/t/executor/ddl.test
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,90 @@ CREATE TABLE t_1 (t_id int);
ALTER TABLE t_1 ADD FOREIGN KEY fk_t_id(t_id) references t(id);
drop table t,t_1;
set global tidb_enable_foreign_key=default;

# TestCreateView
drop table if exists source_table, t1, t2, test_v_nested;
drop view if exists view_t, v, v1, v2, v3, v4, v5, v6, v7, v_nested, v_nested2;
CREATE TABLE source_table (id INT NOT NULL DEFAULT 1, name varchar(255), PRIMARY KEY(id));
CREATE VIEW view_t AS select id , name from source_table;
-- error 1050
CREATE VIEW view_t AS select id , name from source_table;
-- error 1146
create view v1 (c,d) as select a,b from t1;
create table t1 (a int ,b int);
insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10);
create view v1 (c) as select b+1 from t1;
create view v2 as select b+1 from t1;
create view v3 as select b+1 as c from t1;
create view v4 (c) as select b+1 as d from t1;
create view v5 as select * from t1;
create view v6 (c,d) as select * from t1;
-- error 1353
create view v7 (c,d,e) as select * from t1;
drop view v1,v2,v3,v4,v5,v6;
-- error 1351
create view v1 (c,d) as select a,b+@@global.max_user_connections from t1;
-- error 1351
create view v1 (c,d) as select a,b from t1 where a = @@global.max_user_connections;
-- error 1353
create view v1 (c,d,e) as select a,b from t1 ;
-- error 1353
create view v1 (c) as select a,b from t1 ;
drop view if exists v1;
create view v1 (c,d) as select a,b from t1;
create or replace view v1 (c,d) as select a,b from t1 ;
create table if not exists t1 (a int ,b int);
-- error 1347
create or replace view t1 as select * from t1;
prepare stmt from "create view v10 (x) as select 1";
execute stmt;
drop table if exists t1, t2;
drop view if exists v;
-- error 1146
create view v as select * from t1 union select * from t2;
create table t1(a int, b int);
create table t2(a int, b int);
insert into t1 values(1,2), (1,1), (1,2);
insert into t2 values(1,1),(1,3);
create definer='root'@'localhost' view v as select * from t1 union select * from t2;
--sorted_result
select * from v;
alter table t1 drop column a;
-- error 1356
select * from v;
alter table t1 add column a int;
--sorted_result
select * from v;
alter table t1 drop column a;
alter table t2 drop column b;
-- error 1356
select * from v;
drop view v;
create view v as (select * from t1);
drop view v;
create view v as (select * from t1 union select * from t2);
drop view v;
drop view if exists v_if_exists;
show warnings;
create view v1_if_exists as (select * from t1);
drop view if exists v1_if_exists,v2_if_exists,v3_if_exists;
show warnings;
create table test_v_nested(a int);
create definer='root'@'localhost' view v_nested as select * from test_v_nested;
create definer='root'@'localhost' view v_nested2 as select * from v_nested;
-- error 1146
create or replace definer='root'@'localhost' view v_nested as select * from v_nested2;
drop table test_v_nested;
drop view v_nested, v_nested2;
## Refer https://github.com/pingcap/tidb/issues/25876
-- error 1356
create view v_stale as select * from source_table as of timestamp current_timestamp(3);
## Refer https://github.com/pingcap/tidb/issues/32682
drop view if exists v1,v2;
drop table if exists t1;
CREATE TABLE t1(a INT, b INT);
-- error 1470
CREATE DEFINER=1234567890abcdefGHIKL1234567890abcdefGHIKL@localhost VIEW v1 AS SELECT a FROM t1;
-- error 1470
CREATE DEFINER=some_user_name@host_1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890X VIEW v2 AS SELECT b FROM t1;
DROP VIEW IF EXISTS view_t;

0 comments on commit 14318a2

Please sign in to comment.