diff --git a/pkg/executor/adapter_test.go b/pkg/executor/adapter_test.go index 1956fa4bda6d6..bc5d08453aa8e 100644 --- a/pkg/executor/adapter_test.go +++ b/pkg/executor/adapter_test.go @@ -16,32 +16,12 @@ package executor_test import ( "testing" - "time" "github.com/pingcap/tidb/pkg/executor" "github.com/pingcap/tidb/pkg/sessionctx/variable" - "github.com/pingcap/tidb/pkg/testkit" "github.com/stretchr/testify/require" ) -func TestQueryTime(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - - costTime := time.Since(tk.Session().GetSessionVars().StartTime) - require.Less(t, costTime, time.Second) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int)") - tk.MustExec("insert into t values(1), (1), (1), (1), (1)") - tk.MustExec("select * from t t1 join t t2 on t1.a = t2.a") - - costTime = time.Since(tk.Session().GetSessionVars().StartTime) - require.Less(t, costTime, time.Second) -} - func TestFormatSQL(t *testing.T) { val := executor.FormatSQL("aaaa") require.Equal(t, "aaaa", val.String()) diff --git a/pkg/executor/cluster_table_test.go b/pkg/executor/cluster_table_test.go index 03b929bac1583..373414b13d91d 100644 --- a/pkg/executor/cluster_table_test.go +++ b/pkg/executor/cluster_table_test.go @@ -19,7 +19,6 @@ import ( "fmt" "net" "os" - "strconv" "testing" "time" @@ -308,120 +307,6 @@ func TestSQLDigestTextRetriever(t *testing.T) { require.Equal(t, "", r.SQLDigestsMap[updateDigest.String()]) } -func TestFunctionDecodeSQLDigests(t *testing.T) { - store, dom := testkit.CreateMockStoreAndDomain(t) - srv := createRPCServer(t, dom) - defer srv.Stop() - - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) - tk.MustExec("set global tidb_enable_stmt_summary = 1") - tk.MustQuery("select @@global.tidb_enable_stmt_summary").Check(testkit.Rows("1")) - tk.MustExec("drop table if exists test_func_decode_sql_digests") - tk.MustExec("create table test_func_decode_sql_digests(id int primary key, v int)") - - q1 := "begin" - norm1, digest1 := parser.NormalizeDigest(q1) - q2 := "select @@tidb_current_ts" - norm2, digest2 := parser.NormalizeDigest(q2) - q3 := "select id, v from test_func_decode_sql_digests where id = 1 for update" - norm3, digest3 := parser.NormalizeDigest(q3) - - // TIDB_DECODE_SQL_DIGESTS function doesn't actually do "decoding", instead it queries `statements_summary` and it's - // variations for the corresponding statements. - // Execute the statements so that the queries will be saved into statements_summary table. - tk.MustExec(q1) - // Save the ts to query the transaction from tidb_trx. - ts, err := strconv.ParseUint(tk.MustQuery(q2).Rows()[0][0].(string), 10, 64) - require.NoError(t, err) - require.Greater(t, ts, uint64(0)) - tk.MustExec(q3) - tk.MustExec("rollback") - - // Test statements truncating. - decoded := fmt.Sprintf(`["%s","%s","%s"]`, norm1, norm2, norm3) - digests := fmt.Sprintf(`["%s","%s","%s"]`, digest1, digest2, digest3) - tk.MustQuery("select tidb_decode_sql_digests(?, 0)", digests).Check(testkit.Rows(decoded)) - // The three queries are shorter than truncate length, equal to truncate length and longer than truncate length respectively. - tk.MustQuery("select tidb_decode_sql_digests(?, ?)", digests, len(norm2)).Check(testkit.Rows( - "[\"begin\",\"select @@tidb_current_ts\",\"select `id` , `v` from `...\"]")) - - // Empty array. - tk.MustQuery("select tidb_decode_sql_digests('[]')").Check(testkit.Rows("[]")) - - // NULL - tk.MustQuery("select tidb_decode_sql_digests(null)").Check(testkit.Rows("")) - - // Array containing wrong types and not-existing digests (maps to null). - tk.MustQuery("select tidb_decode_sql_digests(?)", fmt.Sprintf(`["%s",1,null,"%s",{"a":1},[2],"%s","","abcde"]`, digest1, digest2, digest3)). - Check(testkit.Rows(fmt.Sprintf(`["%s",null,null,"%s",null,null,"%s",null,null]`, norm1, norm2, norm3))) - - // Not JSON array (throws warnings) - tk.MustQuery(`select tidb_decode_sql_digests('{"a":1}')`).Check(testkit.Rows("")) - tk.MustQuery(`show warnings`).Check(testkit.Rows(`Warning 1210 The argument can't be unmarshalled as JSON array: '{"a":1}'`)) - tk.MustQuery(`select tidb_decode_sql_digests('aabbccdd')`).Check(testkit.Rows("")) - tk.MustQuery(`show warnings`).Check(testkit.Rows(`Warning 1210 The argument can't be unmarshalled as JSON array: 'aabbccdd'`)) - - // Invalid argument count. - tk.MustGetErrCode("select tidb_decode_sql_digests('a', 1, 2)", 1582) - tk.MustGetErrCode("select tidb_decode_sql_digests()", 1582) -} - -func TestFunctionDecodeSQLDigestsPrivilege(t *testing.T) { - store, dom := testkit.CreateMockStoreAndDomain(t) - srv := createRPCServer(t, dom) - defer srv.Stop() - - dropUserTk := testkit.NewTestKit(t, store) - require.NoError(t, dropUserTk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) - - tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) - tk.MustExec("create user 'testuser'@'localhost'") - defer dropUserTk.MustExec("drop user 'testuser'@'localhost'") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "testuser", Hostname: "localhost"}, nil, nil, nil)) - tk.MustGetErrMsg("select tidb_decode_sql_digests('[\"aa\"]')", "[expression:1227]Access denied; you need (at least one of) the PROCESS privilege(s) for this operation") - - tk = testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) - tk.MustExec("create user 'testuser2'@'localhost'") - defer dropUserTk.MustExec("drop user 'testuser2'@'localhost'") - tk.MustExec("grant process on *.* to 'testuser2'@'localhost'") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "testuser2", Hostname: "localhost"}, nil, nil, nil)) - tk.MustExec("select tidb_decode_sql_digests('[\"aa\"]')") -} - -func TestFunctionEncodeSQLDigest(t *testing.T) { - store, dom := testkit.CreateMockStoreAndDomain(t) - srv := createRPCServer(t, dom) - defer srv.Stop() - - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) - tk.MustExec("drop table if exists test_func_encode_sql_digest") - tk.MustExec("create table test_func_encode_sql_digest(id int primary key, v int)") - - q1 := "begin" - digest1 := parser.DigestHash(q1) - q2 := "select @@tidb_current_ts" - digest2 := parser.DigestHash(q2) - q3 := "select id, v from test_func_decode_sql_digests where id = 1 for update" - digest3 := parser.DigestHash(q3) - - tk.MustQuery(fmt.Sprintf("select tidb_encode_sql_digest(\"%s\")", q1)).Check(testkit.Rows(digest1.String())) - tk.MustQuery(fmt.Sprintf("select tidb_encode_sql_digest(\"%s\")", q2)).Check(testkit.Rows(digest2.String())) - tk.MustQuery(fmt.Sprintf("select tidb_encode_sql_digest(\"%s\")", q3)).Check(testkit.Rows(digest3.String())) - - tk.MustQuery("select tidb_encode_sql_digest(null)").Check(testkit.Rows("")) - tk.MustGetErrCode("select tidb_encode_sql_digest()", 1582) - - tk.MustQuery("select (select tidb_encode_sql_digest('select 1')) = tidb_encode_sql_digest('select 1;')").Check(testkit.Rows("1")) - tk.MustQuery("select (select tidb_encode_sql_digest('select 1')) = tidb_encode_sql_digest('select 1 ;')").Check(testkit.Rows("1")) - tk.MustQuery("select (select tidb_encode_sql_digest('select 1')) = tidb_encode_sql_digest('select 2 ;')").Check(testkit.Rows("1")) -} - func prepareLogs(t *testing.T, logData []string, fileNames []string) { for i, log := range logData { f, err := os.OpenFile(fileNames[i], os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) diff --git a/pkg/executor/compact_table_test.go b/pkg/executor/compact_table_test.go index eae058bf4f78b..6889692b4a812 100644 --- a/pkg/executor/compact_table_test.go +++ b/pkg/executor/compact_table_test.go @@ -55,80 +55,6 @@ func withMockTiFlash(nodes int) mockstore.MockTiKVStoreOption { ) } -func TestCompactUnknownTable(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - - err := tk.ExecToErr(`alter table test compact tiflash replica;`) - require.Equal(t, "[planner:1046]No database selected", err.Error()) - - err = tk.ExecToErr(`alter table test.foo compact tiflash replica;`) - require.Equal(t, "[schema:1146]Table 'test.foo' doesn't exist", err.Error()) - - tk.MustExec("use test") - err = tk.ExecToErr(`alter table bar compact;`) - require.Equal(t, "[schema:1146]Table 'test.bar' doesn't exist", err.Error()) -} - -func TestCompactTableNoTiFlashReplica(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - - tk.MustExec("use test") - tk.MustExec("create table t(a int)") - tk.MustExec(`alter table t compact tiflash replica;`) - tk.MustQuery(`show warnings;`).Check(testkit.Rows( - `Warning 1105 compact skipped: no tiflash replica in the table`, - )) - - tk.MustExec(`alter table test.t compact;`) - tk.MustQuery(`show warnings;`).Check(testkit.Rows( - `Warning 1105 compact skipped: no tiflash replica in the table`, - )) - - tk = testkit.NewTestKit(t, store) - tk.MustExec(`alter table test.t compact;`) - tk.MustQuery(`show warnings;`).Check(testkit.Rows( - `Warning 1105 compact skipped: no tiflash replica in the table`, - )) -} - -func TestCompactTableNoPartition(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - - tk.MustExec("use test") - tk.MustExec("create table t(a int)") - _, err := tk.Exec("alter table t compact partition p1,p2 tiflash replica;") - require.NotNil(t, err) - require.Equal(t, "table:t is not a partition table, but user specify partition name list:[p1 p2]", err.Error()) -} - -func TestCompactTablePartitionInvalid(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - - tk.MustExec("use test") - tk.MustExec(` - CREATE TABLE t ( - id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, - fname VARCHAR(25) NOT NULL, - lname VARCHAR(25) NOT NULL, - store_id INT NOT NULL, - department_id INT NOT NULL - ) - PARTITION BY RANGE(id) ( - PARTITION p0 VALUES LESS THAN (5), - PARTITION p1 VALUES LESS THAN (10), - PARTITION p2 VALUES LESS THAN (15), - PARTITION p3 VALUES LESS THAN MAXVALUE - ); - `) - _, err := tk.Exec("alter table t compact partition p1,p2,p4 tiflash replica;") - require.NotNil(t, err) - require.Equal(t, "[table:1735]Unknown partition 'p4' in table 't'", err.Error()) -} - func TestCompactTableTooBusy(t *testing.T) { mocker := newCompactRequestMocker(t) mocker.MockFrom(`tiflash0/#1`, func(req *kvrpcpb.CompactRequest) (*kvrpcpb.CompactResponse, error) { diff --git a/pkg/executor/cte_test.go b/pkg/executor/cte_test.go index 4133e4401ed97..a8499402ab43e 100644 --- a/pkg/executor/cte_test.go +++ b/pkg/executor/cte_test.go @@ -27,327 +27,6 @@ import ( "github.com/stretchr/testify/require" ) -func TestBasicCTE(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - - rows := tk.MustQuery("with recursive cte1 as (" + - "select 1 c1 " + - "union all " + - "select c1 + 1 c1 from cte1 where c1 < 5) " + - "select * from cte1") - rows.Check(testkit.Rows("1", "2", "3", "4", "5")) - - // Two seed parts. - rows = tk.MustQuery("with recursive cte1 as (" + - "select 1 c1 " + - "union all " + - "select 2 c1 " + - "union all " + - "select c1 + 1 c1 from cte1 where c1 < 10) " + - "select * from cte1 order by c1") - rows.Check(testkit.Rows("1", "2", "2", "3", "3", "4", "4", "5", "5", "6", "6", "7", "7", "8", "8", "9", "9", "10", "10")) - - // Two recursive parts. - rows = tk.MustQuery("with recursive cte1 as (" + - "select 1 c1 " + - "union all " + - "select 2 c1 " + - "union all " + - "select c1 + 1 c1 from cte1 where c1 < 3 " + - "union all " + - "select c1 + 2 c1 from cte1 where c1 < 5) " + - "select * from cte1 order by c1") - rows.Check(testkit.Rows("1", "2", "2", "3", "3", "3", "4", "4", "5", "5", "5", "6", "6")) - - tk.MustExec("drop table if exists t1;") - tk.MustExec("create table t1(a int);") - tk.MustExec("insert into t1 values(1);") - tk.MustExec("insert into t1 values(2);") - rows = tk.MustQuery("SELECT * FROM t1 dt WHERE EXISTS(WITH RECURSIVE qn AS (SELECT a*0 AS b UNION ALL SELECT b+1 FROM qn WHERE b=0) SELECT * FROM qn WHERE b=a);") - rows.Check(testkit.Rows("1")) - rows = tk.MustQuery("SELECT * FROM t1 dt WHERE EXISTS( WITH RECURSIVE qn AS (SELECT a*0 AS b UNION ALL SELECT b+1 FROM qn WHERE b=0 or b = 1) SELECT * FROM qn WHERE b=a );") - rows.Check(testkit.Rows("1", "2")) - - rows = tk.MustQuery("with recursive c(p) as (select 1), cte(a, b) as (select 1, 1 union select a+1, 1 from cte, c where a < 5) select * from cte order by 1, 2;") - rows.Check(testkit.Rows("1 1", "2 1", "3 1", "4 1", "5 1")) -} - -func TestUnionDistinct(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test;") - - // Basic test. UNION/UNION ALL intersects. - rows := tk.MustQuery("with recursive cte1(c1) as (select 1 union select 1 union select 1 union all select c1 + 1 from cte1 where c1 < 3) select * from cte1 order by c1;") - rows.Check(testkit.Rows("1", "2", "3")) - - rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union all select 1 union select 1 union all select c1 + 1 from cte1 where c1 < 3) select * from cte1 order by c1;") - rows.Check(testkit.Rows("1", "2", "3")) - - tk.MustExec("drop table if exists t1;") - tk.MustExec("create table t1(c1 int, c2 int);") - tk.MustExec("insert into t1 values(1, 1), (1, 2), (2, 2);") - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 c1 from t1) select * from cte1 order by c1;") - rows.Check(testkit.Rows("1", "2", "3")) - - tk.MustExec("drop table if exists t1;") - tk.MustExec("create table t1(c1 int);") - tk.MustExec("insert into t1 values(1), (1), (1), (2), (2), (2);") - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 c1 from cte1 where c1 < 4) select * from cte1 order by c1;") - rows.Check(testkit.Rows("1", "2", "3", "4")) -} - -func TestCTEMaxRecursionDepth(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test;") - - tk.MustExec("set @@cte_max_recursion_depth = -1;") - err := tk.QueryToErr("with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 100) select * from cte1;") - require.EqualError(t, err, "[executor:3636]Recursive query aborted after 1 iterations. Try increasing @@cte_max_recursion_depth to a larger value") - // If there is no recursive part, query runs ok. - rows := tk.MustQuery("with recursive cte1(c1) as (select 1 union select 2) select * from cte1 order by c1;") - rows.Check(testkit.Rows("1", "2")) - rows = tk.MustQuery("with cte1(c1) as (select 1 union select 2) select * from cte1 order by c1;") - rows.Check(testkit.Rows("1", "2")) - - tk.MustExec("set @@cte_max_recursion_depth = 0;") - err = tk.QueryToErr("with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 0) select * from cte1;") - require.EqualError(t, err, "[executor:3636]Recursive query aborted after 1 iterations. Try increasing @@cte_max_recursion_depth to a larger value") - err = tk.QueryToErr("with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 1) select * from cte1;") - require.EqualError(t, err, "[executor:3636]Recursive query aborted after 1 iterations. Try increasing @@cte_max_recursion_depth to a larger value") - // If there is no recursive part, query runs ok. - rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select 2) select * from cte1 order by c1;") - rows.Check(testkit.Rows("1", "2")) - rows = tk.MustQuery("with cte1(c1) as (select 1 union select 2) select * from cte1 order by c1;") - rows.Check(testkit.Rows("1", "2")) - - tk.MustExec("set @@cte_max_recursion_depth = 1;") - rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 0) select * from cte1;") - rows.Check(testkit.Rows("1")) - rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 1) select * from cte1;") - rows.Check(testkit.Rows("1")) - err = tk.QueryToErr("with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 2) select * from cte1;") - require.EqualError(t, err, "[executor:3636]Recursive query aborted after 2 iterations. Try increasing @@cte_max_recursion_depth to a larger value") - // If there is no recursive part, query runs ok. - rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select 2) select * from cte1 order by c1;") - rows.Check(testkit.Rows("1", "2")) - rows = tk.MustQuery("with cte1(c1) as (select 1 union select 2) select * from cte1 order by c1;") - rows.Check(testkit.Rows("1", "2")) -} - -func TestCTEWithLimit(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test;") - - // Basic recursive tests. - rows := tk.MustQuery("with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 5 offset 0) select * from cte1") - rows.Check(testkit.Rows("1", "2", "3", "4", "5")) - - rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 5 offset 1) select * from cte1") - rows.Check(testkit.Rows("2", "3", "4", "5", "6")) - - rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 5 offset 10) select * from cte1") - rows.Check(testkit.Rows("11", "12", "13", "14", "15")) - - rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 5 offset 995) select * from cte1") - rows.Check(testkit.Rows("996", "997", "998", "999", "1000")) - - rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 5 offset 6) select * from cte1;") - rows.Check(testkit.Rows("7", "8", "9", "10", "11")) - - // Test with cte_max_recursion_depth - tk.MustExec("set cte_max_recursion_depth=2;") - rows = tk.MustQuery("with recursive cte1(c1) as (select 0 union select c1 + 1 from cte1 limit 1 offset 2) select * from cte1;") - rows.Check(testkit.Rows("2")) - - err := tk.QueryToErr("with recursive cte1(c1) as (select 0 union select c1 + 1 from cte1 limit 1 offset 3) select * from cte1;") - require.EqualError(t, err, "[executor:3636]Recursive query aborted after 3 iterations. Try increasing @@cte_max_recursion_depth to a larger value") - - tk.MustExec("set cte_max_recursion_depth=1000;") - rows = tk.MustQuery("with recursive cte1(c1) as (select 0 union select c1 + 1 from cte1 limit 5 offset 996) select * from cte1;") - rows.Check(testkit.Rows("996", "997", "998", "999", "1000")) - - err = tk.QueryToErr("with recursive cte1(c1) as (select 0 union select c1 + 1 from cte1 limit 5 offset 997) select * from cte1;") - require.EqualError(t, err, "[executor:3636]Recursive query aborted after 1001 iterations. Try increasing @@cte_max_recursion_depth to a larger value") - - rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 0 offset 1) select * from cte1") - rows.Check(testkit.Rows()) - - rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 0 offset 10) select * from cte1") - rows.Check(testkit.Rows()) - - // Test join. - rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 2 offset 1) select * from cte1 dt1 join cte1 dt2 order by dt1.c1, dt2.c1;") - rows.Check(testkit.Rows("2 2", "2 3", "3 2", "3 3")) - - rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 2 offset 1) select * from cte1 dt1 join cte1 dt2 on dt1.c1 = dt2.c1 order by dt1.c1, dt1.c1;") - rows.Check(testkit.Rows("2 2", "3 3")) - - // Test subquery. - // Different with mysql, maybe it's mysql bug?(https://bugs.mysql.com/bug.php?id=103890&thanks=4) - rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 2 offset 1) select c1 from cte1 where c1 in (select 2);") - rows.Check(testkit.Rows("2")) - - rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 2 offset 1) select c1 from cte1 dt where c1 in (select c1 from cte1 where 1 = dt.c1 - 1);") - rows.Check(testkit.Rows("2")) - - // Test Apply. - rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 2 offset 1) select c1 from cte1 where cte1.c1 = (select dt1.c1 from cte1 dt1 where dt1.c1 = cte1.c1);") - rows.Check(testkit.Rows("2", "3")) - - // Recursive tests with table. - tk.MustExec("drop table if exists t1;") - tk.MustExec("create table t1(c1 int);") - tk.MustExec("insert into t1 values(1), (2), (3);") - - // Error: ERROR 1221 (HY000): Incorrect usage of UNION and LIMIT. - // Limit can only be at the end of SQL stmt. - err = tk.ExecToErr("with recursive cte1(c1) as (select c1 from t1 limit 1 offset 1 union select c1 + 1 from cte1 limit 0 offset 1) select * from cte1") - require.EqualError(t, err, "[planner:1221]Incorrect usage of UNION and LIMIT") - - // Basic non-recusive tests. - rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select 2 order by 1 limit 1 offset 1) select * from cte1") - rows.Check(testkit.Rows("2")) - - rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select 2 order by 1 limit 0 offset 1) select * from cte1") - rows.Check(testkit.Rows()) - - rows = tk.MustQuery("with recursive cte1(c1) as (select 1 union select 2 order by 1 limit 2 offset 0) select * from cte1") - rows.Check(testkit.Rows("1", "2")) - - // Test with table. - tk.MustExec("drop table if exists t1;") - insertStr := "insert into t1 values(0)" - for i := 1; i < 300; i++ { - insertStr += fmt.Sprintf(", (%d)", i) - } - - tk.MustExec("drop table if exists t1;") - tk.MustExec("create table t1(c1 int);") - tk.MustExec(insertStr) - - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 c1 from cte1 limit 1) select * from cte1") - rows.Check(testkit.Rows("0")) - - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 c1 from cte1 limit 1 offset 100) select * from cte1") - rows.Check(testkit.Rows("100")) - - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 c1 from cte1 limit 5 offset 100) select * from cte1") - rows.Check(testkit.Rows("100", "101", "102", "103", "104")) - - // Basic non-recursive tests. - rows = tk.MustQuery("with cte1 as (select c1 from t1 limit 2 offset 1) select * from cte1") - rows.Check(testkit.Rows("1", "2")) - - rows = tk.MustQuery("with cte1 as (select c1 from t1 limit 2 offset 1) select * from cte1 dt1 join cte1 dt2 on dt1.c1 = dt2.c1") - rows.Check(testkit.Rows("1 1", "2 2")) - - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select 2 limit 0 offset 1) select * from cte1") - rows.Check(testkit.Rows()) - - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select 2 limit 0 offset 1) select * from cte1 dt1 join cte1 dt2 on dt1.c1 = dt2.c1") - rows.Check(testkit.Rows()) - - // rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select 2 limit 5 offset 100) select * from cte1") - // rows.Check(testkit.Rows("100", "101", "102", "103", "104")) - - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 limit 3 offset 100) select * from cte1") - rows.Check(testkit.Rows("100", "101", "102")) - - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 limit 3 offset 100) select * from cte1 dt1 join cte1 dt2 on dt1.c1 = dt2.c1") - rows.Check(testkit.Rows("100 100", "101 101", "102 102")) - - // Test limit 0. - tk.MustExec("set cte_max_recursion_depth = 0;") - tk.MustExec("drop table if exists t1;") - tk.MustExec("create table t1(c1 int);") - tk.MustExec("insert into t1 values(0);") - rows = tk.MustQuery("with recursive cte1 as (select 1/c1 c1 from t1 union select c1 + 1 c1 from cte1 where c1 < 2 limit 0) select * from cte1;") - rows.Check(testkit.Rows()) - // MySQL err: ERROR 1365 (22012): Division by 0. Because it gives error when computing 1/c1. - err = tk.QueryToErr("with recursive cte1 as (select 1/c1 c1 from t1 union select c1 + 1 c1 from cte1 where c1 < 2 limit 1) select * from cte1;") - require.EqualError(t, err, "[executor:3636]Recursive query aborted after 1 iterations. Try increasing @@cte_max_recursion_depth to a larger value") - - tk.MustExec("set cte_max_recursion_depth = 1000;") - tk.MustExec("drop table if exists t1;") - tk.MustExec("create table t1(c1 int);") - tk.MustExec("insert into t1 values(1), (2), (3);") - - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 0 offset 2) select * from cte1;") - rows.Check(testkit.Rows()) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 1 offset 2) select * from cte1;") - rows.Check(testkit.Rows("3")) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 2 offset 2) select * from cte1;") - rows.Check(testkit.Rows("3", "4")) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 3 offset 2) select * from cte1;") - rows.Check(testkit.Rows("3", "4", "5")) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 4 offset 2) select * from cte1;") - rows.Check(testkit.Rows("3", "4", "5", "6")) - - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 0 offset 3) select * from cte1;") - rows.Check(testkit.Rows()) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 1 offset 3) select * from cte1;") - rows.Check(testkit.Rows("4")) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 2 offset 3) select * from cte1;") - rows.Check(testkit.Rows("4", "5")) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 3 offset 3) select * from cte1;") - rows.Check(testkit.Rows("4", "5", "6")) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 4 offset 3) select * from cte1;") - rows.Check(testkit.Rows("4", "5", "6", "7")) - - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 0 offset 4) select * from cte1;") - rows.Check(testkit.Rows()) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 1 offset 4) select * from cte1;") - rows.Check(testkit.Rows("5")) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 2 offset 4) select * from cte1;") - rows.Check(testkit.Rows("5", "6")) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 3 offset 4) select * from cte1;") - rows.Check(testkit.Rows("5", "6", "7")) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 4 offset 4) select * from cte1;") - rows.Check(testkit.Rows("5", "6", "7", "8")) - - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 0 offset 2) select * from cte1;") - rows.Check(testkit.Rows()) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 1 offset 2) select * from cte1;") - rows.Check(testkit.Rows("3")) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 2 offset 2) select * from cte1;") - rows.Check(testkit.Rows("3", "2")) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 3 offset 2) select * from cte1;") - rows.Check(testkit.Rows("3", "2", "3")) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 4 offset 2) select * from cte1;") - rows.Check(testkit.Rows("3", "2", "3", "4")) - - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 0 offset 3) select * from cte1;") - rows.Check(testkit.Rows()) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 1 offset 3) select * from cte1;") - rows.Check(testkit.Rows("2")) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 2 offset 3) select * from cte1;") - rows.Check(testkit.Rows("2", "3")) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 3 offset 3) select * from cte1;") - rows.Check(testkit.Rows("2", "3", "4")) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 4 offset 3) select * from cte1;") - rows.Check(testkit.Rows("2", "3", "4", "3")) - - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 0 offset 4) select * from cte1;") - rows.Check(testkit.Rows()) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 1 offset 4) select * from cte1;") - rows.Check(testkit.Rows("3")) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 2 offset 4) select * from cte1;") - rows.Check(testkit.Rows("3", "4")) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 3 offset 4) select * from cte1;") - rows.Check(testkit.Rows("3", "4", "3")) - rows = tk.MustQuery("with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 4 offset 4) select * from cte1;") - rows.Check(testkit.Rows("3", "4", "3", "4")) -} - func TestSpillToDisk(t *testing.T) { store := testkit.CreateMockStore(t) @@ -431,25 +110,6 @@ func TestCTEExecError(t *testing.T) { } } -// https://github.com/pingcap/tidb/issues/33965. -func TestCTEsInView(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test;") - - tk.MustExec("create database if not exists test1;") - tk.MustExec("create table test.t (a int);") - tk.MustExec("create table test1.t (a int);") - tk.MustExec("insert into test.t values (1);") - tk.MustExec("insert into test1.t values (2);") - - tk.MustExec("use test;") - tk.MustExec("create definer='root'@'localhost' view test.v as with tt as (select * from t) select * from tt;") - tk.MustQuery("select * from test.v;").Check(testkit.Rows("1")) - tk.MustExec("use test1;") - tk.MustQuery("select * from test.v;").Check(testkit.Rows("1")) -} - func TestCTEPanic(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) diff --git a/pkg/executor/explain_test.go b/pkg/executor/explain_test.go index 3c720f836f4e0..cb6048953f701 100644 --- a/pkg/executor/explain_test.go +++ b/pkg/executor/explain_test.go @@ -25,118 +25,12 @@ import ( "time" "github.com/pingcap/tidb/pkg/config" - "github.com/pingcap/tidb/pkg/errno" - "github.com/pingcap/tidb/pkg/parser/auth" plannercore "github.com/pingcap/tidb/pkg/planner/core" - "github.com/pingcap/tidb/pkg/session" "github.com/pingcap/tidb/pkg/testkit" "github.com/pingcap/tidb/pkg/types" "github.com/stretchr/testify/require" ) -func TestExplainPrivileges(t *testing.T) { - store := testkit.CreateMockStore(t) - se, err := session.CreateSession4Test(store) - require.NoError(t, err) - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) - tk := testkit.NewTestKit(t, store) - tk.SetSession(se) - - tk.MustExec("create database explaindatabase") - tk.MustExec("use explaindatabase") - tk.MustExec("create table t (id int)") - tk.MustExec("create view v as select * from t") - tk.MustExec(`create user 'explain'@'%'`) - - tk1 := testkit.NewTestKit(t, store) - se, err = session.CreateSession4Test(store) - require.NoError(t, err) - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "explain", Hostname: "%"}, nil, nil, nil)) - tk1.SetSession(se) - - tk.MustExec(`grant select on explaindatabase.v to 'explain'@'%'`) - tk1.MustQuery("show databases").Check(testkit.Rows("INFORMATION_SCHEMA", "explaindatabase")) - - tk1.MustExec("use explaindatabase") - tk1.MustQuery("select * from v") - err = tk1.ExecToErr("explain format = 'brief' select * from v") - require.Equal(t, plannercore.ErrViewNoExplain.Error(), err.Error()) - - tk.MustExec(`grant show view on explaindatabase.v to 'explain'@'%'`) - tk1.MustQuery("explain format = 'brief' select * from v") - - tk.MustExec(`revoke select on explaindatabase.v from 'explain'@'%'`) - - err = tk1.ExecToErr("explain format = 'brief' select * from v") - require.Equal(t, plannercore.ErrTableaccessDenied.GenWithStackByArgs("SELECT", "explain", "%", "v").Error(), err.Error()) - - // https://github.com/pingcap/tidb/issues/34326 - tk.MustExec("create table t1 (i int)") - tk.MustExec("create table t2 (j int)") - tk.MustExec("create table t3 (k int, secret int)") - - tk.MustExec("create view v1 as select * from t1") - tk.MustExec("create view v2 as select * from v1, t2") - tk.MustExec("create view v3 as select k from t3") - - tk.MustExec("grant select, show view on explaindatabase.v2 to 'explain'@'%'") - tk.MustExec("grant show view on explaindatabase.v1 to 'explain'@'%'") - tk.MustExec("grant select, show view on explaindatabase.t3 to 'explain'@'%'") - tk.MustExec("grant select, show view on explaindatabase.v3 to 'explain'@'%'") - - tk1.MustGetErrMsg("explain select * from v1", "[planner:1142]SELECT command denied to user 'explain'@'%' for table 'v1'") - tk1.MustGetErrCode("explain select * from v2", errno.ErrViewNoExplain) - tk1.MustQuery("explain select * from t3") - tk1.MustQuery("explain select * from v3") -} - -func TestExplainCartesianJoin(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (v int)") - - cases := []struct { - sql string - isCartesianJoin bool - }{ - {"explain format = 'brief' select * from t t1, t t2", true}, - {"explain format = 'brief' select * from t t1 where exists (select 1 from t t2 where t2.v > t1.v)", true}, - {"explain format = 'brief' select * from t t1 where exists (select 1 from t t2 where t2.v in (t1.v+1, t1.v+2))", true}, - {"explain format = 'brief' select * from t t1, t t2 where t1.v = t2.v", false}, - } - for _, ca := range cases { - rows := tk.MustQuery(ca.sql).Rows() - ok := false - for _, row := range rows { - str := fmt.Sprintf("%v", row) - if strings.Contains(str, "CARTESIAN") { - ok = true - } - } - - require.Equal(t, ca.isCartesianJoin, ok) - } -} - -func TestExplainWrite(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int)") - tk.MustQuery("explain analyze insert into t select 1") - tk.MustQuery("select * from t").Check(testkit.Rows("1")) - tk.MustQuery("explain analyze update t set a=2 where a=1") - tk.MustQuery("select * from t").Check(testkit.Rows("2")) - tk.MustQuery("explain format = 'brief' insert into t select 1") - tk.MustQuery("select * from t").Check(testkit.Rows("2")) - tk.MustQuery("explain analyze insert into t select 1") - tk.MustQuery("explain analyze replace into t values (3)") - tk.MustQuery("select * from t order by a").Check(testkit.Rows("1", "2", "3")) -} - func TestExplainAnalyzeMemory(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) @@ -413,43 +307,6 @@ func TestExplainAnalyzeCTEMemoryAndDiskInfo(t *testing.T) { require.NotEqual(t, "N/A", rows[4][8].(string)) } -func TestExplainStatementsSummary(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustQuery("desc select * from information_schema.statements_summary").Check(testkit.Rows( - `MemTableScan_4 10000.00 root table:STATEMENTS_SUMMARY `)) - tk.MustQuery("desc select * from information_schema.statements_summary where digest is null").Check(testkit.RowsWithSep("|", - `Selection_5|8000.00|root| isnull(Column#5)`, `└─MemTableScan_6|10000.00|root|table:STATEMENTS_SUMMARY|`)) - tk.MustQuery("desc select * from information_schema.statements_summary where digest = 'abcdefg'").Check(testkit.RowsWithSep(" ", - `MemTableScan_5 10000.00 root table:STATEMENTS_SUMMARY digests: ["abcdefg"]`)) - tk.MustQuery("desc select * from information_schema.statements_summary where digest in ('a','b','c')").Check(testkit.RowsWithSep(" ", - `MemTableScan_5 10000.00 root table:STATEMENTS_SUMMARY digests: ["a","b","c"]`)) -} - -func TestFix29401(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("drop table if exists tt123;") - tk.MustExec(`CREATE TABLE tt123 ( - id int(11) NOT NULL, - a bigint(20) DEFAULT NULL, - b char(20) DEFAULT NULL, - c datetime DEFAULT NULL, - d double DEFAULT NULL, - e json DEFAULT NULL, - f decimal(40,6) DEFAULT NULL, - PRIMARY KEY (id) /*T![clustered_index] CLUSTERED */, - KEY a (a), - KEY b (b), - KEY c (c), - KEY d (d), - KEY f (f) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;`) - tk.MustExec(" explain select /*+ inl_hash_join(t1) */ * from tt123 t1 join tt123 t2 on t1.b=t2.e;") -} - func TestIssue35296AndIssue43024(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) @@ -507,18 +364,6 @@ func TestIssue35911(t *testing.T) { require.EqualValues(t, 5, concurrency) } -func TestIssue35105(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int primary key)") - tk.MustExec("insert into t values (2)") - tk.MustExec("set @@tidb_constraint_check_in_place=1") - require.Error(t, tk.ExecToErr("explain analyze insert into t values (1), (2), (3)")) - tk.MustQuery("select * from t").Check(testkit.Rows("2")) -} - func flatJSONPlan(j *plannercore.ExplainInfoForEncode) (res []*plannercore.ExplainInfoForEncode) { if j == nil { return @@ -649,56 +494,3 @@ func TestExplainFormatInCtx(t *testing.T) { } } } - -func TestExplainFormatPlanCache(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int)") - tk.MustExec("set @@session.tidb_enable_non_prepared_plan_cache = 1") - tk.MustExec("select * from t limit 1") - tk.MustExec("select * from t limit 1") - - // miss - tk.MustExec("explain format = 'plan_cache' select * from (select * from t) t1 limit 1") - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 skip non-prepared plan-cache: queries that have sub-queries are not supported")) - tk.MustExec("explain format = 'plan_cache' select * from (select * from t) t1 limit 1") - tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) - - tk.MustExec("explain analyze format = 'plan_cache' select * from (select * from t) t1 limit 1") - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 skip non-prepared plan-cache: queries that have sub-queries are not supported")) - tk.MustExec("explain analyze format = 'plan_cache' select * from (select * from t) t1 limit 1") - tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) - - // hit - tk.MustExec("explain format = 'plan_cache' select * from t") - tk.MustQuery("show warnings").Check(testkit.Rows()) - tk.MustExec("explain format = 'plan_cache' select * from t") - tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) - - tk.MustExec("explain analyze format = 'plan_cache' select * from t") - tk.MustQuery("show warnings").Check(testkit.Rows()) - tk.MustExec("explain analyze format = 'plan_cache' select * from t") - tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) - - // will not use plan cache - explainFormats := []string{ - types.ExplainFormatBrief, - types.ExplainFormatDOT, - types.ExplainFormatHint, - types.ExplainFormatROW, - types.ExplainFormatVerbose, - types.ExplainFormatTraditional, - types.ExplainFormatBinary, - types.ExplainFormatTiDBJSON, - types.ExplainFormatCostTrace, - } - - tk.MustExec("explain select * from t") - tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) - for _, format := range explainFormats { - tk.MustExec(fmt.Sprintf("explain format = '%v' select * from t", format)) - tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) - } -} diff --git a/pkg/executor/explainfor_test.go b/pkg/executor/explainfor_test.go index a98697852ac2f..18e8e4e721ed1 100644 --- a/pkg/executor/explainfor_test.go +++ b/pkg/executor/explainfor_test.go @@ -167,63 +167,6 @@ func TestIssue11124(t *testing.T) { } } -func TestExplainMemTablePredicate(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustQuery("desc select * from METRICS_SCHEMA.tidb_query_duration where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13' ").Check(testkit.Rows( - "MemTableScan_5 10000.00 root table:tidb_query_duration PromQL:histogram_quantile(0.9, sum(rate(tidb_server_handle_query_duration_seconds_bucket{}[60s])) by (le,sql_type,instance)), start_time:2019-12-23 16:10:13, end_time:2019-12-23 16:30:13, step:1m0s")) - tk.MustQuery("desc select * from METRICS_SCHEMA.up where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13' ").Check(testkit.Rows( - "MemTableScan_5 10000.00 root table:up PromQL:up{}, start_time:2019-12-23 16:10:13, end_time:2019-12-23 16:30:13, step:1m0s")) - tk.MustQuery("desc select * from information_schema.cluster_log where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13'").Check(testkit.Rows( - "MemTableScan_5 10000.00 root table:CLUSTER_LOG start_time:2019-12-23 16:10:13, end_time:2019-12-23 16:30:13")) - tk.MustQuery("desc select * from information_schema.cluster_log where level in ('warn','error') and time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13'").Check(testkit.Rows( - `MemTableScan_5 10000.00 root table:CLUSTER_LOG start_time:2019-12-23 16:10:13, end_time:2019-12-23 16:30:13, log_levels:["error","warn"]`)) - tk.MustQuery("desc select * from information_schema.cluster_log where type in ('high_cpu_1','high_memory_1') and time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13'").Check(testkit.Rows( - `MemTableScan_5 10000.00 root table:CLUSTER_LOG start_time:2019-12-23 16:10:13, end_time:2019-12-23 16:30:13, node_types:["high_cpu_1","high_memory_1"]`)) - tk.MustQuery("desc select * from information_schema.slow_query").Check(testkit.Rows( - "MemTableScan_4 10000.00 root table:SLOW_QUERY only search in the current 'tidb-slow.log' file")) - tk.MustQuery("desc select * from information_schema.slow_query where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13'").Check(testkit.Rows( - "MemTableScan_5 10000.00 root table:SLOW_QUERY start_time:2019-12-23 16:10:13.000000, end_time:2019-12-23 16:30:13.000000")) - tk.MustExec("set @@time_zone = '+00:00';") - tk.MustQuery("desc select * from information_schema.slow_query where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13'").Check(testkit.Rows( - "MemTableScan_5 10000.00 root table:SLOW_QUERY start_time:2019-12-23 16:10:13.000000, end_time:2019-12-23 16:30:13.000000")) -} - -func TestExplainClusterTable(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustQuery("desc select * from information_schema.cluster_config where type in ('tikv', 'tidb')").Check(testkit.Rows( - `MemTableScan_5 10000.00 root table:CLUSTER_CONFIG node_types:["tidb","tikv"]`)) - tk.MustQuery("desc select * from information_schema.cluster_config where instance='192.168.1.7:2379'").Check(testkit.Rows( - `MemTableScan_5 10000.00 root table:CLUSTER_CONFIG instances:["192.168.1.7:2379"]`)) - tk.MustQuery("desc select * from information_schema.cluster_config where type='tidb' and instance='192.168.1.7:2379'").Check(testkit.Rows( - `MemTableScan_5 10000.00 root table:CLUSTER_CONFIG node_types:["tidb"], instances:["192.168.1.7:2379"]`)) -} - -func TestInspectionResultTable(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustQuery("desc select * from information_schema.inspection_result where rule = 'ddl' and rule = 'config'").Check(testkit.Rows( - `MemTableScan_5 10000.00 root table:INSPECTION_RESULT skip_inspection:true`)) - tk.MustQuery("desc select * from information_schema.inspection_result where rule in ('ddl', 'config')").Check(testkit.Rows( - `MemTableScan_5 10000.00 root table:INSPECTION_RESULT rules:["config","ddl"], items:[]`)) - tk.MustQuery("desc select * from information_schema.inspection_result where item in ('ddl.lease', 'raftstore.threadpool')").Check(testkit.Rows( - `MemTableScan_5 10000.00 root table:INSPECTION_RESULT rules:[], items:["ddl.lease","raftstore.threadpool"]`)) - tk.MustQuery("desc select * from information_schema.inspection_result where item in ('ddl.lease', 'raftstore.threadpool') and rule in ('ddl', 'config')").Check(testkit.Rows( - `MemTableScan_5 10000.00 root table:INSPECTION_RESULT rules:["config","ddl"], items:["ddl.lease","raftstore.threadpool"]`)) -} - -func TestInspectionRuleTable(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustQuery("desc select * from information_schema.inspection_rules where type='inspection'").Check(testkit.Rows( - `MemTableScan_5 10000.00 root table:INSPECTION_RULES node_types:["inspection"]`)) - tk.MustQuery("desc select * from information_schema.inspection_rules where type='inspection' or type='summary'").Check(testkit.Rows( - `MemTableScan_5 10000.00 root table:INSPECTION_RULES node_types:["inspection","summary"]`)) - tk.MustQuery("desc select * from information_schema.inspection_rules where type='inspection' and type='summary'").Check(testkit.Rows( - `MemTableScan_5 10000.00 root table:INSPECTION_RULES skip_request: true`)) -} - func TestExplainForConnPlanCache(t *testing.T) { t.Skip("unstable") @@ -286,28 +229,6 @@ func TestExplainForConnPlanCache(t *testing.T) { wg.Wait() } -func TestSavedPlanPanicPlanCache(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec(`set tidb_enable_prepared_plan_cache=1`) - - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int, b int, c int generated always as (a+b) stored)") - tk.MustExec("insert into t(a,b) values(1,1)") - tk.MustExec("begin") - tk.MustExec("update t set b = 2 where a = 1") - tk.MustExec("prepare stmt from 'select b from t where a > ?'") - tk.MustExec("set @p = 0") - tk.MustQuery("execute stmt using @p").Check(testkit.Rows( - "2", - )) - tk.MustExec("set @p = 1") - tk.MustQuery("execute stmt using @p").Check(testkit.Rows()) - err := tk.ExecToErr("insert into t(a,b,c) values(3,3,3)") - require.EqualError(t, err, "[planner:3105]The value specified for generated column 'c' in table 't' is not allowed.") -} - func TestExplainDotForExplainPlan(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) @@ -347,95 +268,6 @@ func TestExplainDotForQuery(t *testing.T) { } } -func TestExplainTableStorage(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustQuery("desc select * from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'information_schema'").Check(testkit.Rows( - "MemTableScan_5 10000.00 root table:TABLE_STORAGE_STATS schema:[\"information_schema\"]")) - tk.MustQuery("desc select * from information_schema.TABLE_STORAGE_STATS where TABLE_NAME = 'schemata'").Check(testkit.Rows( - "MemTableScan_5 10000.00 root table:TABLE_STORAGE_STATS table:[\"schemata\"]")) - tk.MustQuery("desc select * from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'information_schema' and TABLE_NAME = 'schemata'").Check(testkit.Rows( - "MemTableScan_5 10000.00 root table:TABLE_STORAGE_STATS schema:[\"information_schema\"], table:[\"schemata\"]")) -} - -func TestInspectionSummaryTable(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - - tk.MustQuery("desc select * from information_schema.inspection_summary where rule='ddl'").Check(testkit.Rows( - `Selection_5 8000.00 root eq(Column#1, "ddl")`, - `└─MemTableScan_6 10000.00 root table:INSPECTION_SUMMARY rules:["ddl"]`, - )) - tk.MustQuery("desc select * from information_schema.inspection_summary where 'ddl'=rule or rule='config'").Check(testkit.Rows( - `Selection_5 8000.00 root or(eq("ddl", Column#1), eq(Column#1, "config"))`, - `└─MemTableScan_6 10000.00 root table:INSPECTION_SUMMARY rules:["config","ddl"]`, - )) - tk.MustQuery("desc select * from information_schema.inspection_summary where 'ddl'=rule or rule='config' or rule='slow_query'").Check(testkit.Rows( - `Selection_5 8000.00 root or(eq("ddl", Column#1), or(eq(Column#1, "config"), eq(Column#1, "slow_query")))`, - `└─MemTableScan_6 10000.00 root table:INSPECTION_SUMMARY rules:["config","ddl","slow_query"]`, - )) - tk.MustQuery("desc select * from information_schema.inspection_summary where (rule='config' or rule='slow_query') and (metrics_name='metric_name3' or metrics_name='metric_name1')").Check(testkit.Rows( - `Selection_5 8000.00 root or(eq(Column#1, "config"), eq(Column#1, "slow_query")), or(eq(Column#3, "metric_name3"), eq(Column#3, "metric_name1"))`, - `└─MemTableScan_6 10000.00 root table:INSPECTION_SUMMARY rules:["config","slow_query"], metric_names:["metric_name1","metric_name3"]`, - )) - tk.MustQuery("desc select * from information_schema.inspection_summary where rule in ('ddl', 'slow_query')").Check(testkit.Rows( - `Selection_5 8000.00 root in(Column#1, "ddl", "slow_query")`, - `└─MemTableScan_6 10000.00 root table:INSPECTION_SUMMARY rules:["ddl","slow_query"]`, - )) - tk.MustQuery("desc select * from information_schema.inspection_summary where rule in ('ddl', 'slow_query') and metrics_name='metric_name1'").Check(testkit.Rows( - `Selection_5 8000.00 root eq(Column#3, "metric_name1"), in(Column#1, "ddl", "slow_query")`, - `└─MemTableScan_6 10000.00 root table:INSPECTION_SUMMARY rules:["ddl","slow_query"], metric_names:["metric_name1"]`, - )) - tk.MustQuery("desc select * from information_schema.inspection_summary where rule in ('ddl', 'slow_query') and metrics_name in ('metric_name1', 'metric_name2')").Check(testkit.Rows( - `Selection_5 8000.00 root in(Column#1, "ddl", "slow_query"), in(Column#3, "metric_name1", "metric_name2")`, - `└─MemTableScan_6 10000.00 root table:INSPECTION_SUMMARY rules:["ddl","slow_query"], metric_names:["metric_name1","metric_name2"]`, - )) - tk.MustQuery("desc select * from information_schema.inspection_summary where rule='ddl' and metrics_name in ('metric_name1', 'metric_name2')").Check(testkit.Rows( - `Selection_5 8000.00 root eq(Column#1, "ddl"), in(Column#3, "metric_name1", "metric_name2")`, - `└─MemTableScan_6 10000.00 root table:INSPECTION_SUMMARY rules:["ddl"], metric_names:["metric_name1","metric_name2"]`, - )) - tk.MustQuery("desc select * from information_schema.inspection_summary where rule='ddl' and metrics_name='metric_NAME3'").Check(testkit.Rows( - `Selection_5 8000.00 root eq(Column#1, "ddl"), eq(Column#3, "metric_NAME3")`, - `└─MemTableScan_6 10000.00 root table:INSPECTION_SUMMARY rules:["ddl"], metric_names:["metric_name3"]`, - )) - tk.MustQuery("desc select * from information_schema.inspection_summary where rule in ('ddl', 'config') and rule in ('slow_query', 'config')").Check(testkit.Rows( - `Selection_5 8000.00 root in(Column#1, "ddl", "config"), in(Column#1, "slow_query", "config")`, - `└─MemTableScan_6 10000.00 root table:INSPECTION_SUMMARY rules:["config"]`, - )) - tk.MustQuery("desc select * from information_schema.inspection_summary where metrics_name in ('metric_name1', 'metric_name4') and metrics_name in ('metric_name5', 'metric_name4') and rule in ('ddl', 'config') and rule in ('slow_query', 'config') and quantile in (0.80, 0.90)").Check(testkit.Rows( - `Selection_5 8000.00 root in(Column#1, "ddl", "config"), in(Column#1, "slow_query", "config"), in(Column#3, "metric_name1", "metric_name4"), in(Column#3, "metric_name5", "metric_name4")`, - `└─MemTableScan_6 10000.00 root table:INSPECTION_SUMMARY rules:["config"], metric_names:["metric_name4"], quantiles:[0.800000,0.900000]`, - )) - tk.MustQuery("desc select * from information_schema.inspection_summary where metrics_name in ('metric_name1', 'metric_name4') and metrics_name in ('metric_name5', 'metric_name4') and metrics_name in ('metric_name5', 'metric_name1') and metrics_name in ('metric_name1', 'metric_name3')").Check(testkit.Rows( - `Selection_5 8000.00 root in(Column#3, "metric_name1", "metric_name3"), in(Column#3, "metric_name1", "metric_name4"), in(Column#3, "metric_name5", "metric_name1"), in(Column#3, "metric_name5", "metric_name4")`, - `└─MemTableScan_6 10000.00 root table:INSPECTION_SUMMARY skip_inspection: true`, - )) -} - -func TestExplainTiFlashSystemTables(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tiflashInstance := "192.168.1.7:3930" - database := "test" - table := "t" - tk.MustQuery(fmt.Sprintf("desc select * from information_schema.TIFLASH_TABLES where TIFLASH_INSTANCE = '%s'", tiflashInstance)).Check(testkit.Rows( - fmt.Sprintf("MemTableScan_5 10000.00 root table:TIFLASH_TABLES tiflash_instances:[\"%s\"]", tiflashInstance))) - tk.MustQuery(fmt.Sprintf("desc select * from information_schema.TIFLASH_SEGMENTS where TIFLASH_INSTANCE = '%s'", tiflashInstance)).Check(testkit.Rows( - fmt.Sprintf("MemTableScan_5 10000.00 root table:TIFLASH_SEGMENTS tiflash_instances:[\"%s\"]", tiflashInstance))) - tk.MustQuery(fmt.Sprintf("desc select * from information_schema.TIFLASH_TABLES where TIDB_DATABASE = '%s'", database)).Check(testkit.Rows( - fmt.Sprintf("MemTableScan_5 10000.00 root table:TIFLASH_TABLES tidb_databases:[\"%s\"]", database))) - tk.MustQuery(fmt.Sprintf("desc select * from information_schema.TIFLASH_SEGMENTS where TIDB_DATABASE = '%s'", database)).Check(testkit.Rows( - fmt.Sprintf("MemTableScan_5 10000.00 root table:TIFLASH_SEGMENTS tidb_databases:[\"%s\"]", database))) - tk.MustQuery(fmt.Sprintf("desc select * from information_schema.TIFLASH_TABLES where TIDB_TABLE = '%s'", table)).Check(testkit.Rows( - fmt.Sprintf("MemTableScan_5 10000.00 root table:TIFLASH_TABLES tidb_tables:[\"%s\"]", table))) - tk.MustQuery(fmt.Sprintf("desc select * from information_schema.TIFLASH_SEGMENTS where TIDB_TABLE = '%s'", table)).Check(testkit.Rows( - fmt.Sprintf("MemTableScan_5 10000.00 root table:TIFLASH_SEGMENTS tidb_tables:[\"%s\"]", table))) - tk.MustQuery(fmt.Sprintf("desc select * from information_schema.TIFLASH_TABLES where TIFLASH_INSTANCE = '%s' and TIDB_DATABASE = '%s' and TIDB_TABLE = '%s'", tiflashInstance, database, table)).Check(testkit.Rows( - fmt.Sprintf("MemTableScan_5 10000.00 root table:TIFLASH_TABLES tiflash_instances:[\"%s\"], tidb_databases:[\"%s\"], tidb_tables:[\"%s\"]", tiflashInstance, database, table))) - tk.MustQuery(fmt.Sprintf("desc select * from information_schema.TIFLASH_SEGMENTS where TIFLASH_INSTANCE = '%s' and TIDB_DATABASE = '%s' and TIDB_TABLE = '%s'", tiflashInstance, database, table)).Check(testkit.Rows( - fmt.Sprintf("MemTableScan_5 10000.00 root table:TIFLASH_SEGMENTS tiflash_instances:[\"%s\"], tidb_databases:[\"%s\"], tidb_tables:[\"%s\"]", tiflashInstance, database, table))) -} - func TestPointGetUserVarPlanCache(t *testing.T) { store := testkit.CreateMockStore(t) tmp := testkit.NewTestKit(t, store) @@ -892,73 +724,6 @@ func TestIndexMerge4PlanCache(t *testing.T) { tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) } -func TestSetOperations4PlanCache(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec(`set tidb_enable_prepared_plan_cache=1`) - - tk.MustExec("use test") - tk.MustExec("set @@tidb_enable_collect_execution_info=0;") - tk.MustExec("drop table if exists t1, t2;") - tk.MustExec("CREATE TABLE `t1` (a int);") - tk.MustExec("CREATE TABLE `t2` (a int);") - tk.MustExec("insert into t1 values(1), (2);") - tk.MustExec("insert into t2 values(1), (3);") - // test for UNION - tk.MustExec("prepare stmt from 'select * from t1 where a > ? union select * from t2 where a > ?;';") - tk.MustExec("set @a=0, @b=1;") - tk.MustQuery("execute stmt using @a, @b;").Sort().Check(testkit.Rows("1", "2", "3")) - tk.MustQuery("execute stmt using @b, @a;").Sort().Check(testkit.Rows("1", "2", "3")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - tk.MustQuery("execute stmt using @b, @b;").Sort().Check(testkit.Rows("2", "3")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - tk.MustQuery("execute stmt using @a, @a;").Sort().Check(testkit.Rows("1", "2", "3")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - tk.MustExec("prepare stmt from 'select * from t1 where a > ? union all select * from t2 where a > ?;';") - tk.MustExec("set @a=0, @b=1;") - tk.MustQuery("execute stmt using @a, @b;").Sort().Check(testkit.Rows("1", "2", "3")) - tk.MustQuery("execute stmt using @b, @a;").Sort().Check(testkit.Rows("1", "2", "3")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - tk.MustQuery("execute stmt using @b, @b;").Sort().Check(testkit.Rows("2", "3")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - tk.MustQuery("execute stmt using @a, @a;").Sort().Check(testkit.Rows("1", "1", "2", "3")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - // test for EXCEPT - tk.MustExec("prepare stmt from 'select * from t1 where a > ? except select * from t2 where a > ?;';") - tk.MustExec("set @a=0, @b=1;") - tk.MustQuery("execute stmt using @a, @a;").Sort().Check(testkit.Rows("2")) - tk.MustQuery("execute stmt using @b, @a;").Sort().Check(testkit.Rows("2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - tk.MustQuery("execute stmt using @b, @b;").Sort().Check(testkit.Rows("2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - tk.MustQuery("execute stmt using @a, @b;").Sort().Check(testkit.Rows("1", "2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - // test for INTERSECT - tk.MustExec("prepare stmt from 'select * from t1 where a > ? union select * from t2 where a > ?;';") - tk.MustExec("set @a=0, @b=1;") - tk.MustQuery("execute stmt using @a, @a;").Sort().Check(testkit.Rows("1", "2", "3")) - tk.MustQuery("execute stmt using @b, @a;").Sort().Check(testkit.Rows("1", "2", "3")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - tk.MustQuery("execute stmt using @b, @b;").Sort().Check(testkit.Rows("2", "3")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - tk.MustQuery("execute stmt using @a, @b;").Sort().Check(testkit.Rows("1", "2", "3")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - // test for UNION + INTERSECT - tk.MustExec("prepare stmt from 'select * from t1 union all select * from t1 intersect select * from t2;'") - tk.MustQuery("execute stmt;").Sort().Check(testkit.Rows("1", "1", "2")) - - tk.MustExec("prepare stmt from '(select * from t1 union all select * from t1) intersect select * from t2;'") - tk.MustQuery("execute stmt;").Sort().Check(testkit.Rows("1")) - - // test for order by and limit - tk.MustExec("prepare stmt from '(select * from t1 union all select * from t1 intersect select * from t2) order by a limit 2;'") - tk.MustQuery("execute stmt;").Sort().Check(testkit.Rows("1", "1")) -} - func TestSPM4PlanCache(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) @@ -1013,375 +778,6 @@ func TestSPM4PlanCache(t *testing.T) { tk.MustExec("admin reload bindings;") } -func TestHint4PlanCache(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec(`set tidb_enable_prepared_plan_cache=1`) - - tk.MustExec("use test") - tk.MustExec("set @@tidb_enable_collect_execution_info=0;") - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t(a int, index idx_a(a));") - - tk.MustExec("prepare stmt from 'select * from t;';") - tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - tk.MustExec("prepare stmt from 'select /*+ IGNORE_PLAN_CACHE() */ * from t;';") - tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) -} - -func TestIgnorePlanCacheWithPrepare(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - - tk.MustExec("use test") - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t(a int, index idx_a(a));") - tk.MustExec("drop table if exists r;") - tk.MustExec("create table r(a int);") - - // test use_index - tk.MustExec("prepare stmt from 'select * from t;';") - tk.MustExec("create binding for select * from t using select /*+ use_index(t, idx_a) */ * from t;") - tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_binding;").Check(testkit.Rows("1")) - - tk.MustExec("create binding for select * from t using select /*+ ignore_plan_cache() */ * from t;") - tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) - tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_binding;").Check(testkit.Rows("1")) - - tk.MustExec("create binding for select * from t using select /*+ use_index(t, idx_a) */ * from t;") - tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_binding;").Check(testkit.Rows("1")) - - // test straight_join - tk.MustExec("prepare stmt_join from 'select * from t, r where r.a = t.a;';") - tk.MustExec("create binding for select * from t, r where r.a = t.a using select /*+ straight_join() */* from t, r where r.a = t.a;") - tk.MustQuery("execute stmt_join;").Check(testkit.Rows()) - tk.MustQuery("execute stmt_join;").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - tk.MustQuery("execute stmt_join;").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_binding;").Check(testkit.Rows("1")) - - tk.MustExec("create binding for select * from t, r where r.a = t.a using select /*+ ignore_plan_cache() */* from t, r where r.a = t.a;") - tk.MustQuery("execute stmt_join;").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) - tk.MustQuery("execute stmt_join;").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_binding;").Check(testkit.Rows("1")) - - tk.MustExec("create binding for select * from t, r where r.a = t.a using select /*+ straight_join() */* from t, r where r.a = t.a;") - tk.MustQuery("execute stmt_join;").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - tk.MustQuery("execute stmt_join;").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_binding;").Check(testkit.Rows("1")) -} - -func TestSelectView4PlanCache(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec(`set tidb_enable_prepared_plan_cache=1`) - - tk.MustExec("use test") - tk.MustExec("set @@tidb_enable_collect_execution_info=0;") - tk.MustExec("drop table if exists view_t;") - tk.MustExec("create table view_t (a int,b int)") - tk.MustExec("insert into view_t values(1,2)") - tk.MustExec("create definer='root'@'localhost' view view1 as select * from view_t") - tk.MustExec("create definer='root'@'localhost' view view2(c,d) as select * from view_t") - tk.MustExec("create definer='root'@'localhost' view view3(c,d) as select a,b from view_t") - tk.MustExec("create definer='root'@'localhost' view view4 as select * from (select * from (select * from view_t) tb1) tb;") - tk.MustExec("prepare stmt1 from 'select * from view1;'") - tk.MustQuery("execute stmt1;").Check(testkit.Rows("1 2")) - tk.MustQuery("execute stmt1;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - tk.MustExec("prepare stmt2 from 'select * from view2;'") - tk.MustQuery("execute stmt2;").Check(testkit.Rows("1 2")) - tk.MustQuery("execute stmt2;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - tk.MustExec("prepare stmt3 from 'select * from view3;'") - tk.MustQuery("execute stmt3;").Check(testkit.Rows("1 2")) - tk.MustQuery("execute stmt3;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - tk.MustExec("prepare stmt4 from 'select * from view4;'") - tk.MustQuery("execute stmt4;").Check(testkit.Rows("1 2")) - tk.MustQuery("execute stmt4;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - tk.MustExec("drop table view_t;") - tk.MustExec("create table view_t(c int,d int)") - err := tk.ExecToErr("execute stmt1;") - require.Equal(t, "[planner:1356]View 'test.view1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them", err.Error()) - err = tk.ExecToErr("execute stmt2") - require.Equal(t, "[planner:1356]View 'test.view2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them", err.Error()) - err = tk.ExecToErr("execute stmt3") - require.Equal(t, core.ErrViewInvalid.GenWithStackByArgs("test", "view3").Error(), err.Error()) - tk.MustExec("drop table view_t;") - tk.MustExec("create table view_t(a int,b int,c int)") - tk.MustExec("insert into view_t values(1,2,3)") - - tk.MustQuery("execute stmt1;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) - tk.MustQuery("execute stmt1;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - tk.MustQuery("execute stmt2;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) - tk.MustQuery("execute stmt2;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - tk.MustQuery("execute stmt3;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) - tk.MustQuery("execute stmt3;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - tk.MustQuery("execute stmt4;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) - tk.MustQuery("execute stmt4;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - tk.MustExec("alter table view_t drop column a") - tk.MustExec("alter table view_t add column a int after b") - tk.MustExec("update view_t set a=1;") - - tk.MustQuery("execute stmt1;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) - tk.MustQuery("execute stmt1;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - tk.MustQuery("execute stmt2;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) - tk.MustQuery("execute stmt2;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - tk.MustQuery("execute stmt3;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) - tk.MustQuery("execute stmt3;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - tk.MustQuery("execute stmt4;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) - tk.MustQuery("execute stmt4;").Check(testkit.Rows("1 2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - tk.MustExec("drop table view_t;") - tk.MustExec("drop view view1,view2,view3,view4;") - - tk.MustExec("set @@tidb_enable_window_function = 1") - defer func() { - tk.MustExec("set @@tidb_enable_window_function = 0") - }() - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t(a int, b int)") - tk.MustExec("insert into t values (1,1),(1,2),(2,1),(2,2)") - tk.MustExec("create definer='root'@'localhost' view v as select a, first_value(a) over(rows between 1 preceding and 1 following), last_value(a) over(rows between 1 preceding and 1 following) from t") - tk.MustExec("prepare stmt from 'select * from v;';") - tk.MustQuery("execute stmt;").Check(testkit.Rows("1 1 1", "1 1 2", "2 1 2", "2 2 2")) - tk.MustQuery("execute stmt;").Check(testkit.Rows("1 1 1", "1 1 2", "2 1 2", "2 2 2")) - tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) - - tk.MustExec("drop view v;") -} - -func TestInvisibleIndex4PlanCache(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec(`set tidb_enable_prepared_plan_cache=1`) - - tk.MustExec("use test") - tk.MustExec("set @@tidb_enable_collect_execution_info=0;") - tk.MustExec("drop table if exists t;") - tk.MustExec("CREATE TABLE t(c1 INT, index idx_c(c1));") - - tk.MustExec("prepare stmt from 'select * from t use index(idx_c) where c1 > 1;';") - tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - tk.MustExec("ALTER TABLE t ALTER INDEX idx_c INVISIBLE;") - err := tk.ExecToErr("select * from t use index(idx_c) where c1 > 1;") - require.Equal(t, "[planner:1176]Key 'idx_c' doesn't exist in table 't'", err.Error()) - - err = tk.ExecToErr("execute stmt;") - require.Equal(t, "[planner:1176]Key 'idx_c' doesn't exist in table 't'", err.Error()) -} - -func TestCTE4PlanCache(t *testing.T) { - // CTE can not be cached, because part of it will be treated as a subquery. - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec(`set tidb_enable_prepared_plan_cache=1`) - - tk.MustExec("use test") - tk.MustExec("set @@tidb_enable_collect_execution_info=0;") - tk.MustExec("prepare stmt from 'with recursive cte1 as (" + - "select ? c1 " + - "union all " + - "select c1 + 1 c1 from cte1 where c1 < ?) " + - "select * from cte1;';") - tk.MustExec("set @a=5, @b=4, @c=2, @d=1;") - tk.MustQuery("execute stmt using @d, @a").Check(testkit.Rows("1", "2", "3", "4", "5")) - tk.MustQuery("execute stmt using @d, @b").Check(testkit.Rows("1", "2", "3", "4")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) - tk.MustQuery("execute stmt using @c, @b").Check(testkit.Rows("2", "3", "4")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) - - // Two seed parts. - tk.MustExec("prepare stmt from 'with recursive cte1 as (" + - "select 1 c1 " + - "union all " + - "select 2 c1 " + - "union all " + - "select c1 + 1 c1 from cte1 where c1 < ?) " + - "select * from cte1 order by c1;';") - tk.MustExec("set @a=10, @b=2;") - tk.MustQuery("execute stmt using @a").Check(testkit.Rows("1", "2", "2", "3", "3", "4", "4", "5", "5", "6", "6", "7", "7", "8", "8", "9", "9", "10", "10")) - tk.MustQuery("execute stmt using @b").Check(testkit.Rows("1", "2", "2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) - - // Two recursive parts. - tk.MustExec("prepare stmt from 'with recursive cte1 as (" + - "select 1 c1 " + - "union all " + - "select 2 c1 " + - "union all " + - "select c1 + 1 c1 from cte1 where c1 < ? " + - "union all " + - "select c1 + ? c1 from cte1 where c1 < ?) " + - "select * from cte1 order by c1;';") - tk.MustExec("set @a=1, @b=2, @c=3, @d=4, @e=5;") - tk.MustQuery("execute stmt using @c, @b, @e;").Check(testkit.Rows("1", "2", "2", "3", "3", "3", "4", "4", "5", "5", "5", "6", "6")) - tk.MustQuery("execute stmt using @b, @a, @d;").Check(testkit.Rows("1", "2", "2", "2", "3", "3", "3", "4", "4", "4")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) - - tk.MustExec("drop table if exists t1;") - tk.MustExec("create table t1(a int);") - tk.MustExec("insert into t1 values(1);") - tk.MustExec("insert into t1 values(2);") - tk.MustExec("prepare stmt from 'SELECT * FROM t1 dt WHERE EXISTS(WITH RECURSIVE qn AS (SELECT a*? AS b UNION ALL SELECT b+? FROM qn WHERE b=?) SELECT * FROM qn WHERE b=a);';") - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 skip prepared plan-cache: find table test.qn failed: [schema:1146]Table 'test.qn' doesn't exist")) - tk.MustExec("set @a=1, @b=2, @c=3, @d=4, @e=5, @f=0;") - - tk.MustQuery("execute stmt using @f, @a, @f").Check(testkit.Rows("1")) - tk.MustQuery("execute stmt using @a, @b, @a").Sort().Check(testkit.Rows("1", "2")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) - tk.MustQuery("execute stmt using @a, @b, @a").Sort().Check(testkit.Rows("1", "2")) - //tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 skip prepared plan-cache: PhysicalApply plan is un-cacheable")) - - tk.MustExec("prepare stmt from 'with recursive c(p) as (select ?), cte(a, b) as (select 1, 1 union select a+?, 1 from cte, c where a < ?) select * from cte order by 1, 2;';") - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 skip prepared plan-cache: find table test.cte failed: [schema:1146]Table 'test.cte' doesn't exist")) - tk.MustQuery("execute stmt using @a, @a, @e;").Check(testkit.Rows("1 1", "2 1", "3 1", "4 1", "5 1")) - tk.MustQuery("execute stmt using @b, @b, @c;").Check(testkit.Rows("1 1", "3 1")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) -} - -func TestValidity4PlanCache(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec(`set tidb_enable_prepared_plan_cache=1`) - - tk.MustExec("use test") - tk.MustExec("set @@tidb_enable_collect_execution_info=0;") - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t(a int);") - - tk.MustExec("prepare stmt from 'select * from t;';") - tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - tk.MustExec("drop database if exists plan_cache;") - tk.MustExec("create database plan_cache;") - tk.MustExec("use plan_cache;") - tk.MustExec("create table t(a int);") - tk.MustExec("insert into t values(1);") - tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) - tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - tk.MustExec("prepare stmt from 'select * from t;';") - tk.MustQuery("execute stmt;").Check(testkit.Rows("1")) - tk.MustQuery("execute stmt;").Check(testkit.Rows("1")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - - tk.MustExec("use test") // still read plan_cache.t and can hit the cache - tk.MustQuery("execute stmt;").Check(testkit.Rows("1")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) -} - -func TestListPartition4PlanCache(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec(`set tidb_enable_prepared_plan_cache=1`) - - tk.MustExec("use test") - tk.MustExec("set @@tidb_enable_collect_execution_info=0;") - tk.MustExec("set @@session.tidb_enable_list_partition=1;") - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t(a int, b int) PARTITION BY LIST (a) ( PARTITION p0 VALUES IN (1, 2, 3), PARTITION p1 VALUES IN (4, 5, 6));") - - tk.MustExec("set @@tidb_partition_prune_mode='static';") - tk.MustExec("prepare stmt from 'select * from t;';") - tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tk.MustQuery("execute stmt;").Check(testkit.Rows()) - // The list partition plan can not be cached. - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) -} - -func TestMoreSessions4PlanCache(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk2 := testkit.NewTestKit(t, store) - tk.MustExec(`set tidb_enable_prepared_plan_cache=1`) - - tk.MustExec("set @@tidb_enable_collect_execution_info=0;") - tk.MustExec("use test;") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int);") - tk.MustExec("prepare stmt from 'select * from t;';") - - tk.MustQuery("execute stmt").Check(testkit.Rows()) - tk.MustQuery("execute stmt").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) - - tk2.MustExec(`set tidb_enable_prepared_plan_cache=1`) - - tk2.MustExec("use test;") - require.EqualError(t, tk2.ExecToErr("execute stmt;"), "[planner:8111]Prepared statement not found") - tk2.MustExec("prepare stmt from 'select * from t;';") - tk2.MustQuery("execute stmt").Check(testkit.Rows()) - tk2.MustQuery("execute stmt").Check(testkit.Rows()) - tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) - - tk.MustQuery("execute stmt").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) -} - -func TestIssue28792(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("CREATE TABLE t12(a INT, b INT)") - tk.MustExec("CREATE TABLE t97(a INT, b INT UNIQUE NOT NULL);") - r1 := tk.MustQuery("EXPLAIN SELECT t12.a, t12.b FROM t12 LEFT JOIN t97 on t12.b = t97.b;").Rows() - r2 := tk.MustQuery("EXPLAIN SELECT t12.a, t12.b FROM t12 LEFT JOIN t97 use index () on t12.b = t97.b;").Rows() - require.Equal(t, r2, r1) -} - func TestExplainForJSON(t *testing.T) { store := testkit.CreateMockStore(t) tk1 := testkit.NewTestKit(t, store) diff --git a/pkg/executor/grant_test.go b/pkg/executor/grant_test.go index 3a10b7aa5f13b..49cbc785ae56f 100644 --- a/pkg/executor/grant_test.go +++ b/pkg/executor/grant_test.go @@ -19,9 +19,6 @@ import ( "strings" "testing" - "github.com/pingcap/tidb/pkg/errno" - "github.com/pingcap/tidb/pkg/infoschema" - "github.com/pingcap/tidb/pkg/parser/auth" "github.com/pingcap/tidb/pkg/parser/mysql" "github.com/pingcap/tidb/pkg/parser/terror" "github.com/pingcap/tidb/pkg/testkit" @@ -106,29 +103,6 @@ func TestGrantDBScope(t *testing.T) { require.True(t, terror.ErrorEqual(err, exeerrors.ErrWrongUsage.GenWithStackByArgs("DB GRANT", "NON-DB PRIVILEGES"))) } -func TestWithGrantOption(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - // Create a new user. - createUserSQL := `CREATE USER 'testWithGrant'@'localhost' IDENTIFIED BY '123';` - tk.MustExec(createUserSQL) - // Make sure all the db privs for new user is empty. - sql := `SELECT * FROM mysql.db WHERE User="testWithGrant" and host="localhost"` - tk.MustQuery(sql).Check(testkit.Rows()) - - // Grant select priv to the user, with grant option. - tk.MustExec("GRANT select ON test.* TO 'testWithGrant'@'localhost' WITH GRANT OPTION;") - tk.MustQuery("SELECT grant_priv FROM mysql.DB WHERE User=\"testWithGrant\" and host=\"localhost\" and db=\"test\"").Check(testkit.Rows("Y")) - - tk.MustExec("CREATE USER 'testWithGrant1'") - tk.MustQuery("SELECT grant_priv FROM mysql.user WHERE User=\"testWithGrant1\"").Check(testkit.Rows("N")) - tk.MustExec("GRANT ALL ON *.* TO 'testWithGrant1'") - tk.MustQuery("SELECT grant_priv FROM mysql.user WHERE User=\"testWithGrant1\"").Check(testkit.Rows("N")) - tk.MustExec("GRANT ALL ON *.* TO 'testWithGrant1' WITH GRANT OPTION") - tk.MustQuery("SELECT grant_priv FROM mysql.user WHERE User=\"testWithGrant1\"").Check(testkit.Rows("Y")) -} - func TestGrantTableScope(t *testing.T) { store := testkit.CreateMockStore(t) @@ -216,388 +190,3 @@ func TestGrantColumnScope(t *testing.T) { tk.MustGetErrMsg("GRANT SUPER(c2) ON test3 TO 'testCol1'@'localhost';", "[executor:1221]Incorrect usage of COLUMN GRANT and NON-COLUMN PRIVILEGES") } - -func TestIssue2456(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - tk.MustExec("CREATE USER 'dduser'@'%' IDENTIFIED by '123456';") - tk.MustExec("CREATE DATABASE `dddb_%`;") - tk.MustExec("CREATE table `dddb_%`.`te%` (id int);") - tk.MustExec("GRANT ALL PRIVILEGES ON `dddb_%`.* TO 'dduser'@'%';") - tk.MustExec("GRANT ALL PRIVILEGES ON `dddb_%`.`te%` to 'dduser'@'%';") -} - -func TestNoAutoCreateUser(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - tk.MustExec(`DROP USER IF EXISTS 'test'@'%'`) - tk.MustExec(`SET sql_mode='NO_AUTO_CREATE_USER'`) - _, err := tk.Exec(`GRANT ALL PRIVILEGES ON *.* to 'test'@'%' IDENTIFIED BY 'xxx'`) - require.Error(t, err) - require.True(t, terror.ErrorEqual(err, exeerrors.ErrCantCreateUserWithGrant)) -} - -func TestCreateUserWhenGrant(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - tk.MustExec(`DROP USER IF EXISTS 'test'@'%'`) - // This only applies to sql_mode:NO_AUTO_CREATE_USER off - tk.MustExec(`SET SQL_MODE=''`) - tk.MustExec(`GRANT ALL PRIVILEGES ON *.* to 'test'@'%' IDENTIFIED BY 'xxx'`) - // Make sure user is created automatically when grant to a non-exists one. - tk.MustQuery(`SELECT user FROM mysql.user WHERE user='test' and host='%'`).Check( - testkit.Rows("test"), - ) - tk.MustExec(`DROP USER IF EXISTS 'test'@'%'`) - // Grant without a password. - tk.MustExec(`GRANT ALL PRIVILEGES ON *.* to 'test'@'%'`) - // Make sure user is created automatically when grant to a non-exists one. - tk.MustQuery(`SELECT user, plugin FROM mysql.user WHERE user='test' and host='%'`).Check( - testkit.Rows("test mysql_native_password"), - ) - tk.MustExec(`DROP USER IF EXISTS 'test'@'%'`) -} - -func TestCreateUserWithTooLongName(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - err := tk.ExecToErr("CREATE USER '1234567890abcdefGHIKL1234567890abcdefGHIKL@localhost'") - require.Truef(t, terror.ErrorEqual(err, exeerrors.ErrWrongStringLength), "ERROR 1470 (HY000): String '1234567890abcdefGHIKL1234567890abcdefGHIKL' is too long for user name (should be no longer than 32)") - err = tk.ExecToErr("CREATE USER 'some_user_name@host_1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890X'") - require.Truef(t, terror.ErrorEqual(err, exeerrors.ErrWrongStringLength), "ERROR 1470 (HY000): String 'host_1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij12345' is too long for host name (should be no longer than 255)") -} - -func TestGrantPrivilegeAtomic(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - tk.MustExec(`drop role if exists r1, r2, r3, r4;`) - tk.MustExec(`create role r1, r2, r3;`) - tk.MustExec(`create table test.testatomic(x int);`) - - _, err := tk.Exec(`grant update, select, insert, delete on *.* to r1, r2, r4;`) - require.True(t, terror.ErrorEqual(err, exeerrors.ErrCantCreateUserWithGrant)) - tk.MustQuery(`select Update_priv, Select_priv, Insert_priv, Delete_priv from mysql.user where user in ('r1', 'r2', 'r3', 'r4') and host = "%";`).Check(testkit.Rows( - "N N N N", - "N N N N", - "N N N N", - )) - tk.MustExec(`grant update, select, insert, delete on *.* to r1, r2, r3;`) - _, err = tk.Exec(`revoke all on *.* from r1, r2, r4, r3;`) - require.Error(t, err) - tk.MustQuery(`select Update_priv, Select_priv, Insert_priv, Delete_priv from mysql.user where user in ('r1', 'r2', 'r3', 'r4') and host = "%";`).Check(testkit.Rows( - "Y Y Y Y", - "Y Y Y Y", - "Y Y Y Y", - )) - - err = tk.ExecToErr(`grant update, select, insert, delete on test.* to r1, r2, r4;`) - require.True(t, terror.ErrorEqual(err, exeerrors.ErrCantCreateUserWithGrant)) - tk.MustQuery(`select Update_priv, Select_priv, Insert_priv, Delete_priv from mysql.db where user in ('r1', 'r2', 'r3', 'r4') and host = "%";`).Check(testkit.Rows()) - tk.MustExec(`grant update, select, insert, delete on test.* to r1, r2, r3;`) - err = tk.ExecToErr(`revoke all on *.* from r1, r2, r4, r3;`) - require.Error(t, err) - tk.MustQuery(`select Update_priv, Select_priv, Insert_priv, Delete_priv from mysql.db where user in ('r1', 'r2', 'r3', 'r4') and host = "%";`).Check(testkit.Rows( - "Y Y Y Y", - "Y Y Y Y", - "Y Y Y Y", - )) - - err = tk.ExecToErr(`grant update, select, insert, delete on test.testatomic to r1, r2, r4;`) - require.True(t, terror.ErrorEqual(err, exeerrors.ErrCantCreateUserWithGrant)) - tk.MustQuery(`select Table_priv from mysql.tables_priv where user in ('r1', 'r2', 'r3', 'r4') and host = "%";`).Check(testkit.Rows()) - tk.MustExec(`grant update, select, insert, delete on test.testatomic to r1, r2, r3;`) - err = tk.ExecToErr(`revoke all on *.* from r1, r2, r4, r3;`) - require.Error(t, err) - tk.MustQuery(`select Table_priv from mysql.tables_priv where user in ('r1', 'r2', 'r3', 'r4') and host = "%";`).Check(testkit.Rows( - "Select,Insert,Update,Delete", - "Select,Insert,Update,Delete", - "Select,Insert,Update,Delete", - )) - - tk.MustExec(`drop role if exists r1, r2, r3, r4;`) - tk.MustExec(`drop table test.testatomic;`) -} - -func TestIssue2654(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - tk.MustExec(`DROP USER IF EXISTS 'test'@'%'`) - tk.MustExec(`CREATE USER 'test'@'%' IDENTIFIED BY 'test'`) - tk.MustExec("GRANT SELECT ON test.* to 'test'") - rows := tk.MustQuery(`SELECT user,host FROM mysql.user WHERE user='test' and host='%'`) - rows.Check(testkit.Rows(`test %`)) -} - -func TestGrantUnderANSIQuotes(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - // Fix a bug that the GrantExec fails in ANSI_QUOTES sql mode - // The bug is caused by the improper usage of double quotes like: - // INSERT INTO mysql.user ... VALUES ("..", "..", "..") - tk.MustExec(`SET SQL_MODE='ANSI_QUOTES'`) - tk.MustExec(`GRANT ALL PRIVILEGES ON video_ulimit.* TO web@'%' IDENTIFIED BY 'eDrkrhZ>l2sV'`) - tk.MustExec(`REVOKE ALL PRIVILEGES ON video_ulimit.* FROM web@'%';`) - tk.MustExec(`DROP USER IF EXISTS 'web'@'%'`) -} - -func TestMaintainRequire(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - - // test create with require - tk.MustExec(`CREATE USER 'ssl_auser'@'%' require issuer '/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US' subject '/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH' cipher 'AES128-GCM-SHA256'`) - tk.MustExec(`CREATE USER 'ssl_buser'@'%' require subject '/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH' cipher 'AES128-GCM-SHA256'`) - tk.MustExec(`CREATE USER 'ssl_cuser'@'%' require cipher 'AES128-GCM-SHA256'`) - tk.MustExec(`CREATE USER 'ssl_duser'@'%'`) - tk.MustExec(`CREATE USER 'ssl_euser'@'%' require none`) - tk.MustExec(`CREATE USER 'ssl_fuser'@'%' require ssl`) - tk.MustExec(`CREATE USER 'ssl_guser'@'%' require x509`) - tk.MustQuery("select * from mysql.global_priv where `user` like 'ssl_%'").Check(testkit.Rows( - "% ssl_auser {\"ssl_type\":3,\"ssl_cipher\":\"AES128-GCM-SHA256\",\"x509_issuer\":\"/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US\",\"x509_subject\":\"/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH\"}", - "% ssl_buser {\"ssl_type\":3,\"ssl_cipher\":\"AES128-GCM-SHA256\",\"x509_subject\":\"/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH\"}", - "% ssl_cuser {\"ssl_type\":3,\"ssl_cipher\":\"AES128-GCM-SHA256\"}", - "% ssl_duser {}", - "% ssl_euser {}", - "% ssl_fuser {\"ssl_type\":1}", - "% ssl_guser {\"ssl_type\":2}", - )) - - // test grant with require - tk.MustExec("CREATE USER 'u1'@'%'") - tk.MustExec("GRANT ALL ON *.* TO 'u1'@'%' require issuer '/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US' and subject '/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH'") // add new require. - tk.MustQuery("select priv from mysql.global_priv where `Host` = '%' and `User` = 'u1'").Check(testkit.Rows("{\"ssl_type\":3,\"x509_issuer\":\"/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US\",\"x509_subject\":\"/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH\"}")) - tk.MustExec("GRANT ALL ON *.* TO 'u1'@'%' require cipher 'AES128-GCM-SHA256'") // modify always overwrite. - tk.MustQuery("select priv from mysql.global_priv where `Host` = '%' and `User` = 'u1'").Check(testkit.Rows("{\"ssl_type\":3,\"ssl_cipher\":\"AES128-GCM-SHA256\"}")) - tk.MustExec("GRANT select ON *.* TO 'u1'@'%'") // modify without require should not modify old require. - tk.MustQuery("select priv from mysql.global_priv where `Host` = '%' and `User` = 'u1'").Check(testkit.Rows("{\"ssl_type\":3,\"ssl_cipher\":\"AES128-GCM-SHA256\"}")) - tk.MustExec("GRANT ALL ON *.* TO 'u1'@'%' require none") // use require none to clean up require. - tk.MustQuery("select priv from mysql.global_priv where `Host` = '%' and `User` = 'u1'").Check(testkit.Rows("{}")) - - // test alter with require - tk.MustExec("CREATE USER 'u2'@'%'") - tk.MustExec("alter user 'u2'@'%' require ssl") - tk.MustQuery("select priv from mysql.global_priv where `Host` = '%' and `User` = 'u2'").Check(testkit.Rows("{\"ssl_type\":1}")) - tk.MustExec("alter user 'u2'@'%' require x509") - tk.MustQuery("select priv from mysql.global_priv where `Host` = '%' and `User` = 'u2'").Check(testkit.Rows("{\"ssl_type\":2}")) - tk.MustExec("alter user 'u2'@'%' require issuer '/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US' subject '/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH' cipher 'AES128-GCM-SHA256'") - tk.MustQuery("select priv from mysql.global_priv where `Host` = '%' and `User` = 'u2'").Check(testkit.Rows("{\"ssl_type\":3,\"ssl_cipher\":\"AES128-GCM-SHA256\",\"x509_issuer\":\"/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US\",\"x509_subject\":\"/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH\"}")) - tk.MustExec("alter user 'u2'@'%' require none") - tk.MustQuery("select priv from mysql.global_priv where `Host` = '%' and `User` = 'u2'").Check(testkit.Rows("{}")) - - // test show create user - tk.MustExec(`CREATE USER 'u3'@'%' require issuer '/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US' subject '/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH' cipher 'AES128-GCM-SHA256'`) - tk.MustQuery("show create user 'u3'").Check(testkit.Rows("CREATE USER 'u3'@'%' IDENTIFIED WITH 'mysql_native_password' AS '' REQUIRE CIPHER 'AES128-GCM-SHA256' ISSUER '/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US' SUBJECT '/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH' PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK PASSWORD HISTORY DEFAULT PASSWORD REUSE INTERVAL DEFAULT")) - - // check issuer/subject/cipher value - err := tk.ExecToErr(`CREATE USER 'u4'@'%' require issuer 'CN=TiDB,OU=PingCAP'`) - require.Error(t, err) - err = tk.ExecToErr(`CREATE USER 'u5'@'%' require subject '/CN=TiDB\OU=PingCAP'`) - require.Error(t, err) - err = tk.ExecToErr(`CREATE USER 'u6'@'%' require subject '/CN=TiDB\NC=PingCAP'`) - require.Error(t, err) - err = tk.ExecToErr(`CREATE USER 'u7'@'%' require cipher 'AES128-GCM-SHA1'`) - require.Error(t, err) - err = tk.ExecToErr(`CREATE USER 'u8'@'%' require subject '/CN'`) - require.Error(t, err) - tk.MustGetErrMsg(`CREATE USER 'u9'@'%' require cipher 'TLS_AES_256_GCM_SHA384' cipher 'RC4-SHA'`, "Duplicate require CIPHER clause") - tk.MustGetErrMsg(`CREATE USER 'u9'@'%' require issuer 'CN=TiDB,OU=PingCAP' issuer 'CN=TiDB,OU=PingCAP2'`, "Duplicate require ISSUER clause") - tk.MustGetErrMsg(`CREATE USER 'u9'@'%' require subject '/CN=TiDB\OU=PingCAP' subject '/CN=TiDB\OU=PingCAP2'`, "Duplicate require SUBJECT clause") - err = tk.ExecToErr(`CREATE USER 'u9'@'%' require ssl ssl`) - require.Error(t, err) - err = tk.ExecToErr(`CREATE USER 'u9'@'%' require x509 x509`) - require.Error(t, err) -} - -func TestMaintainAuthString(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - tk.MustExec(`CREATE USER 'maint_auth_str1'@'%' IDENTIFIED BY 'foo'`) - tk.MustQuery("SELECT authentication_string FROM mysql.user WHERE `Host` = '%' and `User` = 'maint_auth_str1'").Check(testkit.Rows("*F3A2A51A9B0F2BE2468926B4132313728C250DBF")) - tk.MustExec(`ALTER USER 'maint_auth_str1'@'%' REQUIRE SSL`) - tk.MustQuery("SELECT authentication_string FROM mysql.user WHERE `Host` = '%' and `User` = 'maint_auth_str1'").Check(testkit.Rows("*F3A2A51A9B0F2BE2468926B4132313728C250DBF")) -} - -func TestGrantOnNonExistTable(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - tk.MustExec("create user genius") - tk.MustExec("use test") - err := tk.ExecToErr("select * from nonexist") - require.True(t, terror.ErrorEqual(err, infoschema.ErrTableNotExists)) - err = tk.ExecToErr("grant Select,Insert on nonexist to 'genius'") - require.True(t, terror.ErrorEqual(err, infoschema.ErrTableNotExists)) - - tk.MustExec("create table if not exists xx (id int)") - // Case insensitive, differ from MySQL default behaviour. - // In TiDB, system variable lower_case_table_names = 2, which means compare table name using lower case. - tk.MustExec("grant Select,Insert on XX to 'genius'") - tk.MustExec("grant Select,Insert on xx to 'genius'") - tk.MustExec("grant Select,Update on test.xx to 'genius'") - - // issue #29268 - tk.MustExec("CREATE DATABASE d29268") - defer tk.MustExec("DROP DATABASE IF EXISTS d29268") - tk.MustExec("USE d29268") - tk.MustExec("CREATE USER u29268") - defer tk.MustExec("DROP USER u29268") - - // without create privilege - err = tk.ExecToErr("GRANT SELECT ON t29268 TO u29268") - require.Error(t, err) - require.True(t, terror.ErrorEqual(err, infoschema.ErrTableNotExists)) - err = tk.ExecToErr("GRANT DROP, INSERT ON t29268 TO u29268") - require.Error(t, err) - require.True(t, terror.ErrorEqual(err, infoschema.ErrTableNotExists)) - err = tk.ExecToErr("GRANT UPDATE, CREATE VIEW, SHOW VIEW ON t29268 TO u29268") - require.Error(t, err) - require.True(t, terror.ErrorEqual(err, infoschema.ErrTableNotExists)) - err = tk.ExecToErr("GRANT DELETE, REFERENCES, ALTER ON t29268 TO u29268") - require.Error(t, err) - require.True(t, terror.ErrorEqual(err, infoschema.ErrTableNotExists)) - - // with create privilege - tk.MustExec("GRANT CREATE ON t29268 TO u29268") - tk.MustExec("GRANT CREATE, SELECT ON t29268 TO u29268") - tk.MustExec("GRANT CREATE, DROP, INSERT ON t29268 TO u29268") - - // check privilege - tk.Session().Auth(&auth.UserIdentity{Username: "u29268", Hostname: "localhost"}, nil, nil, nil) - tk.MustExec("USE d29268") - tk.MustExec("CREATE TABLE t29268 (c1 int)") - tk.MustExec("INSERT INTO t29268 VALUES (1), (2)") - tk.MustQuery("SELECT c1 FROM t29268").Check(testkit.Rows("1", "2")) - tk.MustExec("DROP TABLE t29268") - - // check grant all - tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil) - tk.MustExec("GRANT ALL ON t29268 TO u29268") -} - -func TestIssue22721(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("create table if not exists xx (id int)") - tk.MustExec("CREATE USER 'sync_ci_data'@'%' IDENTIFIED BY 'sNGNQo12fEHe0n3vU';") - tk.MustExec("GRANT USAGE ON *.* TO 'sync_ci_data'@'%';") - tk.MustExec("GRANT USAGE ON sync_ci_data.* TO 'sync_ci_data'@'%';") - tk.MustExec("GRANT USAGE ON test.* TO 'sync_ci_data'@'%';") - tk.MustExec("GRANT USAGE ON test.xx TO 'sync_ci_data'@'%';") -} - -func TestPerformanceSchemaPrivGrant(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("create user issue27867;") - defer func() { - tk.MustExec("drop user issue27867;") - }() - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil)) - tk.MustGetErrCode("grant all on performance_schema.* to issue27867;", errno.ErrDBaccessDenied) - // Check case insensitivity - tk.MustGetErrCode("grant all on PERFormanCE_scHemA.* to issue27867;", errno.ErrDBaccessDenied) - // Check other database privileges - tk.MustExec("grant select on performance_schema.* to issue27867;") - tk.MustGetErrCode("grant insert on performance_schema.* to issue27867;", errno.ErrDBaccessDenied) - tk.MustGetErrCode("grant update on performance_schema.* to issue27867;", errno.ErrDBaccessDenied) - tk.MustGetErrCode("grant delete on performance_schema.* to issue27867;", errno.ErrDBaccessDenied) - tk.MustGetErrCode("grant drop on performance_schema.* to issue27867;", errno.ErrDBaccessDenied) - tk.MustGetErrCode("grant lock tables on performance_schema.* to issue27867;", errno.ErrDBaccessDenied) - tk.MustGetErrCode("grant create on performance_schema.* to issue27867;", errno.ErrDBaccessDenied) - tk.MustGetErrCode("grant references on performance_schema.* to issue27867;", errno.ErrDBaccessDenied) - tk.MustGetErrCode("grant alter on PERFormAnCE_scHemA.* to issue27867;", errno.ErrDBaccessDenied) - tk.MustGetErrCode("grant execute on performance_schema.* to issue27867;", errno.ErrDBaccessDenied) - tk.MustGetErrCode("grant index on PERFormanCE_scHemA.* to issue27867;", errno.ErrDBaccessDenied) - tk.MustGetErrCode("grant create view on performance_schema.* to issue27867;", errno.ErrDBaccessDenied) - tk.MustGetErrCode("grant show view on performance_schema.* to issue27867;", errno.ErrDBaccessDenied) -} - -func TestGrantDynamicPrivs(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - tk.MustExec("create user dyn") - - err := tk.ExecToErr("GRANT BACKUP_ADMIN ON test.* TO dyn") - require.True(t, terror.ErrorEqual(err, exeerrors.ErrIllegalPrivilegeLevel)) - err = tk.ExecToErr("GRANT BOGUS_GRANT ON *.* TO dyn") - require.True(t, terror.ErrorEqual(err, exeerrors.ErrDynamicPrivilegeNotRegistered)) - - tk.MustExec("GRANT BACKUP_Admin ON *.* TO dyn") // grant one priv - tk.MustQuery("SELECT * FROM mysql.global_grants WHERE `Host` = '%' AND `User` = 'dyn' ORDER BY user,host,priv,with_grant_option").Check(testkit.Rows("dyn % BACKUP_ADMIN N")) - - tk.MustExec("GRANT SYSTEM_VARIABLES_ADMIN, BACKUP_ADMIN ON *.* TO dyn") // grant multiple - tk.MustQuery("SELECT * FROM mysql.global_grants WHERE `Host` = '%' AND `User` = 'dyn' ORDER BY user,host,priv,with_grant_option").Check( - testkit.Rows("dyn % BACKUP_ADMIN N", "dyn % SYSTEM_VARIABLES_ADMIN N"), - ) - - tk.MustExec("GRANT ROLE_ADMIN, BACKUP_ADMIN ON *.* TO dyn WITH GRANT OPTION") // grant multiple with GRANT option. - tk.MustQuery("SELECT * FROM mysql.global_grants WHERE `Host` = '%' AND `User` = 'dyn' ORDER BY user,host,priv,with_grant_option").Check( - testkit.Rows("dyn % BACKUP_ADMIN Y", "dyn % ROLE_ADMIN Y", "dyn % SYSTEM_VARIABLES_ADMIN N"), - ) - - tk.MustExec("GRANT SYSTEM_VARIABLES_ADMIN, Select, ROLE_ADMIN ON *.* TO dyn") // grant mixed dynamic/non dynamic - tk.MustQuery("SELECT Grant_Priv FROM mysql.user WHERE `Host` = '%' AND `User` = 'dyn'").Check(testkit.Rows("N")) - tk.MustQuery("SELECT WITH_GRANT_OPTION FROM mysql.global_grants WHERE `Host` = '%' AND `User` = 'dyn' AND Priv='SYSTEM_VARIABLES_ADMIN'").Check(testkit.Rows("N")) - - tk.MustExec("GRANT CONNECTION_ADMIN, Insert ON *.* TO dyn WITH GRANT OPTION") // grant mixed dynamic/non dynamic with GRANT option. - tk.MustQuery("SELECT Grant_Priv FROM mysql.user WHERE `Host` = '%' AND `User` = 'dyn'").Check(testkit.Rows("Y")) - tk.MustQuery("SELECT WITH_GRANT_OPTION FROM mysql.global_grants WHERE `Host` = '%' AND `User` = 'dyn' AND Priv='CONNECTION_ADMIN'").Check(testkit.Rows("Y")) -} - -func TestNonExistTableIllegalGrant(t *testing.T) { - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - tk.MustExec("create user u29302") - defer tk.MustExec("drop user u29302") - // Table level, not existing table, illegal privilege - tk.MustGetErrCode("grant create temporary tables on NotExistsD29302.NotExistsT29302 to u29302", mysql.ErrIllegalGrantForTable) - tk.MustGetErrCode("grant lock tables on test.NotExistsT29302 to u29302", mysql.ErrIllegalGrantForTable) - // Column level, not existing table, illegal privilege - tk.MustGetErrCode("grant create temporary tables (NotExistsCol) on NotExistsD29302.NotExistsT29302 to u29302;", mysql.ErrWrongUsage) -} - -func TestIssue34610(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec("DROP DATABASE IF EXISTS d1;") - tk.MustExec("CREATE DATABASE d1;") - tk.MustExec("USE d1;") - tk.MustExec("CREATE USER user_1@localhost;") - defer func() { - tk.MustExec("DROP DATABASE d1;") - tk.MustExec("DROP USER user_1@localhost;") - }() - - tk.MustExec("CREATE TABLE T1(f1 INT);") - tk.MustGetErrCode("CREATE TABLE t1(f1 INT);", mysql.ErrTableExists) - tk.MustExec("GRANT SELECT ON T1 to user_1@localhost;") - tk.MustExec("GRANT SELECT ON t1 to user_1@localhost;") -} - -func TestIssue38293(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.Session().GetSessionVars().User = &auth.UserIdentity{Username: "root", Hostname: "localhost"} - tk.MustExec("DROP USER IF EXISTS test") - tk.MustExec("CREATE USER test") - defer func() { - tk.MustExec("DROP USER test") - }() - tk.MustExec("GRANT SELECT ON `mysql`.`db` TO test") - tk.MustQuery("SELECT `Grantor` FROM `mysql`.`tables_priv` WHERE User = 'test'").Check(testkit.Rows("root@localhost")) -} diff --git a/tests/integrationtest/r/executor/adapter.result b/tests/integrationtest/r/executor/adapter.result new file mode 100644 index 0000000000000..fdb89c456847c --- /dev/null +++ b/tests/integrationtest/r/executor/adapter.result @@ -0,0 +1,34 @@ +set @a = now(); +drop table if exists t; +create table t(a int); +insert into t values (1), (1), (1), (1), (1); +select * from t t1 join t t2 on t1.a = t2.a; +a a +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +1 1 +select timestampdiff(second,@a, now()) < 1; +timestampdiff(second,@a, now()) < 1 +1 diff --git a/tests/integrationtest/r/executor/cluster_table.result b/tests/integrationtest/r/executor/cluster_table.result new file mode 100644 index 0000000000000..e42ad209ed983 --- /dev/null +++ b/tests/integrationtest/r/executor/cluster_table.result @@ -0,0 +1,77 @@ +drop table if exists test_func_encode_sql_digest; +create table test_func_encode_sql_digest(id int primary key, v int); +select tidb_encode_sql_digest("begin"); +tidb_encode_sql_digest("begin") +e6f07d43b5c21db0fbb9a31feac2dc599787763393dd5acbfad80e247eb02ad5 +select tidb_encode_sql_digest("select @@tidb_current_ts"); +tidb_encode_sql_digest("select @@tidb_current_ts") +58f3717da2d79c14773a1e3094aaddeff2b11747d3aef95741151af9acba9d44 +select tidb_encode_sql_digest("select id, v from test_func_decode_sql_digests where id = 1 for update"); +tidb_encode_sql_digest("select id, v from test_func_decode_sql_digests where id = 1 for update") +7e9f826ed22a09940940a42d1aca47a75b3adc3c3fde252f4b912ac886194eb9 +select tidb_encode_sql_digest(null); +tidb_encode_sql_digest(null) +NULL +select tidb_encode_sql_digest(); +Error 1582 (42000): Incorrect parameter count in the call to native function 'tidb_encode_sql_digest' +select (select tidb_encode_sql_digest('select 1')) = tidb_encode_sql_digest('select 1;'); +(select tidb_encode_sql_digest('select 1')) = tidb_encode_sql_digest('select 1;') +1 +select (select tidb_encode_sql_digest('select 1')) = tidb_encode_sql_digest('select 1 ;'); +(select tidb_encode_sql_digest('select 1')) = tidb_encode_sql_digest('select 1 ;') +1 +select (select tidb_encode_sql_digest('select 1')) = tidb_encode_sql_digest('select 2 ;'); +(select tidb_encode_sql_digest('select 1')) = tidb_encode_sql_digest('select 2 ;') +1 +drop user if exists 'testuser'@'localhost'; +create user 'testuser'@'localhost'; +select tidb_decode_sql_digests('["aa"]'); +Error 1227 (42000): Access denied; you need (at least one of) the PROCESS privilege(s) for this operation +grant process on *.* to 'testuser'@'localhost'; +select tidb_decode_sql_digests('["aa"]'); +tidb_decode_sql_digests('["aa"]') +[null] +drop user 'testuser'@'localhost'; +set global tidb_enable_stmt_summary = 1; +select @@global.tidb_enable_stmt_summary; +@@global.tidb_enable_stmt_summary +1 +drop table if exists test_func_decode_sql_digests; +create table test_func_decode_sql_digests(id int primary key, v int); +begin; +select @@tidb_current_ts; +select id, v from test_func_decode_sql_digests where id = 1 for update; +id v +rollback; +select tidb_decode_sql_digests('["e6f07d43b5c21db0fbb9a31feac2dc599787763393dd5acbfad80e247eb02ad5","58f3717da2d79c14773a1e3094aaddeff2b11747d3aef95741151af9acba9d44","7e9f826ed22a09940940a42d1aca47a75b3adc3c3fde252f4b912ac886194eb9"]', 0); +tidb_decode_sql_digests('["e6f07d43b5c21db0fbb9a31feac2dc599787763393dd5acbfad80e247eb02ad5","58f3717da2d79c14773a1e3094aaddeff2b11747d3aef95741151af9acba9d44","7e9f826ed22a09940940a42d1aca47a75b3adc3c3fde252f4b912ac886194eb9"]', 0) +[null,"select @@tidb_current_ts","select `id` , `v` from `test_func_decode_sql_digests` where `id` = ? for update"] +select tidb_decode_sql_digests('["e6f07d43b5c21db0fbb9a31feac2dc599787763393dd5acbfad80e247eb02ad5","58f3717da2d79c14773a1e3094aaddeff2b11747d3aef95741151af9acba9d44","7e9f826ed22a09940940a42d1aca47a75b3adc3c3fde252f4b912ac886194eb9"]', 24); +tidb_decode_sql_digests('["e6f07d43b5c21db0fbb9a31feac2dc599787763393dd5acbfad80e247eb02ad5","58f3717da2d79c14773a1e3094aaddeff2b11747d3aef95741151af9acba9d44","7e9f826ed22a09940940a42d1aca47a75b3adc3c3fde252f4b912ac886194eb9"]', 24) +[null,"select @@tidb_current_ts","select `id` , `v` from `..."] +select tidb_decode_sql_digests('[]'); +tidb_decode_sql_digests('[]') +[] +select tidb_decode_sql_digests(null); +tidb_decode_sql_digests(null) +NULL +select tidb_decode_sql_digests('["e6f07d43b5c21db0fbb9a31feac2dc599787763393dd5acbfad80e247eb02ad5",1,null,"58f3717da2d79c14773a1e3094aaddeff2b11747d3aef95741151af9acba9d44",{"a":1},[2],"7e9f826ed22a09940940a42d1aca47a75b3adc3c3fde252f4b912ac886194eb9","","abcde"]'); +tidb_decode_sql_digests('["e6f07d43b5c21db0fbb9a31feac2dc599787763393dd5acbfad80e247eb02ad5",1,null,"58f3717da2d79c14773a1e3094aaddeff2b11747d3aef95741151af9acba9d44",{"a":1},[2],"7e9f826ed22a09940940a42d1aca47a75b3adc3c3fde252f4b912ac886194eb9","","abcde" +[null,null,null,"select @@tidb_current_ts",null,null,"select `id` , `v` from `test_func_decode_sql_digests` where `id` = ? for update",null,null] +select tidb_decode_sql_digests('{"a":1}'); +tidb_decode_sql_digests('{"a":1}') +NULL +show warnings; +Level Code Message +Warning 1210 The argument can't be unmarshalled as JSON array: '{"a":1}' +select tidb_decode_sql_digests('aabbccdd'); +tidb_decode_sql_digests('aabbccdd') +NULL +show warnings; +Level Code Message +Warning 1210 The argument can't be unmarshalled as JSON array: 'aabbccdd' +select tidb_decode_sql_digests('a', 1, 2); +Error 1582 (42000): Incorrect parameter count in the call to native function 'tidb_decode_sql_digests' +select tidb_decode_sql_digests(); +Error 1582 (42000): Incorrect parameter count in the call to native function 'tidb_decode_sql_digests' +set global tidb_enable_stmt_summary = default; diff --git a/tests/integrationtest/r/executor/compact_table.result b/tests/integrationtest/r/executor/compact_table.result new file mode 100644 index 0000000000000..d4cff588896bc --- /dev/null +++ b/tests/integrationtest/r/executor/compact_table.result @@ -0,0 +1,42 @@ +drop table if exists bar, foo; +alter table test compact tiflash replica; +Error 1046 (3D000): No database selected +alter table executor__compact_table.foo compact tiflash replica; +Error 1146 (42S02): Table 'executor__compact_table.foo' doesn't exist +use executor__compact_table; +alter table bar compact; +Error 1146 (42S02): Table 'executor__compact_table.bar' doesn't exist +drop table if exists t; +create table t(a int); +alter table t compact tiflash replica; +show warnings; +Level Code Message +Warning 1105 compact skipped: no tiflash replica in the table +alter table executor__compact_table.t compact; +show warnings; +Level Code Message +Warning 1105 compact skipped: no tiflash replica in the table +alter table executor__compact_table.t compact; +show warnings; +Level Code Message +Warning 1105 compact skipped: no tiflash replica in the table +drop table if exists t; +create table t(a int); +alter table t compact partition p1,p2 tiflash replica; +Error 1105 (HY000): table:t is not a partition table, but user specify partition name list:[p1 p2] +drop table if exists t; +CREATE TABLE t ( +id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +fname VARCHAR(25) NOT NULL, +lname VARCHAR(25) NOT NULL, +store_id INT NOT NULL, +department_id INT NOT NULL +) +PARTITION BY RANGE(id) ( +PARTITION p0 VALUES LESS THAN (5), +PARTITION p1 VALUES LESS THAN (10), +PARTITION p2 VALUES LESS THAN (15), +PARTITION p3 VALUES LESS THAN MAXVALUE +); +alter table t compact partition p1,p2,p4 tiflash replica; +Error 1735 (HY000): Unknown partition 'p4' in table 't' diff --git a/tests/integrationtest/r/executor/cte.result b/tests/integrationtest/r/executor/cte.result new file mode 100644 index 0000000000000..2721c2f4b9c10 --- /dev/null +++ b/tests/integrationtest/r/executor/cte.result @@ -0,0 +1,407 @@ +with recursive cte1 as (select 1 c1 union all select c1 + 1 c1 from cte1 where c1 < 5) select * from cte1; +c1 +1 +2 +3 +4 +5 +with recursive cte1 as (select 1 c1 union all select 2 c1 union all select c1 + 1 c1 from cte1 where c1 < 10) select * from cte1 order by c1; +c1 +1 +2 +2 +3 +3 +4 +4 +5 +5 +6 +6 +7 +7 +8 +8 +9 +9 +10 +10 +with recursive cte1 as (select 1 c1 union all select 2 c1 union all select c1 + 1 c1 from cte1 where c1 < 3 union all select c1 + 2 c1 from cte1 where c1 < 5) select * from cte1 order by c1; +c1 +1 +2 +2 +3 +3 +3 +4 +4 +5 +5 +5 +6 +6 +drop table if exists t1; +create table t1(a int); +insert into t1 values(1); +insert into t1 values(2); +SELECT * FROM t1 dt WHERE EXISTS(WITH RECURSIVE qn AS (SELECT a*0 AS b UNION ALL SELECT b+1 FROM qn WHERE b=0) SELECT * FROM qn WHERE b=a); +a +1 +SELECT * FROM t1 dt WHERE EXISTS( WITH RECURSIVE qn AS (SELECT a*0 AS b UNION ALL SELECT b+1 FROM qn WHERE b=0 or b = 1) SELECT * FROM qn WHERE b=a ); +a +1 +2 +with recursive c(p) as (select 1), cte(a, b) as (select 1, 1 union select a+1, 1 from cte, c where a < 5) select * from cte order by 1, 2; +a b +1 1 +2 1 +3 1 +4 1 +5 1 +with recursive cte1(c1) as (select 1 union select 1 union select 1 union all select c1 + 1 from cte1 where c1 < 3) select * from cte1 order by c1; +c1 +1 +2 +3 +with recursive cte1(c1) as (select 1 union all select 1 union select 1 union all select c1 + 1 from cte1 where c1 < 3) select * from cte1 order by c1; +c1 +1 +2 +3 +drop table if exists t1; +create table t1(c1 int, c2 int); +insert into t1 values(1, 1), (1, 2), (2, 2); +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 c1 from t1) select * from cte1 order by c1; +c1 +1 +2 +3 +drop table if exists t1; +create table t1(c1 int); +insert into t1 values(1), (1), (1), (2), (2), (2); +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 c1 from cte1 where c1 < 4) select * from cte1 order by c1; +c1 +1 +2 +3 +4 +set @@cte_max_recursion_depth = -1; +with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 100) select * from cte1; +Error 3636 (HY000): Recursive query aborted after 1 iterations. Try increasing @@cte_max_recursion_depth to a larger value +with recursive cte1(c1) as (select 1 union select 2) select * from cte1 order by c1; +c1 +1 +2 +with cte1(c1) as (select 1 union select 2) select * from cte1 order by c1; +c1 +1 +2 +set @@cte_max_recursion_depth = 0; +with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 0) select * from cte1; +Error 3636 (HY000): Recursive query aborted after 1 iterations. Try increasing @@cte_max_recursion_depth to a larger value +with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 1) select * from cte1; +Error 3636 (HY000): Recursive query aborted after 1 iterations. Try increasing @@cte_max_recursion_depth to a larger value +with recursive cte1(c1) as (select 1 union select 2) select * from cte1 order by c1; +c1 +1 +2 +with cte1(c1) as (select 1 union select 2) select * from cte1 order by c1; +c1 +1 +2 +set @@cte_max_recursion_depth = 1; +with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 0) select * from cte1; +c1 +1 +with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 1) select * from cte1; +c1 +1 +with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 2) select * from cte1; +Error 3636 (HY000): Recursive query aborted after 2 iterations. Try increasing @@cte_max_recursion_depth to a larger value +with recursive cte1(c1) as (select 1 union select 2) select * from cte1 order by c1; +c1 +1 +2 +with cte1(c1) as (select 1 union select 2) select * from cte1 order by c1; +c1 +1 +2 +set @@cte_max_recursion_depth = default; +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 5 offset 0) select * from cte1; +c1 +1 +2 +3 +4 +5 +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 5 offset 1) select * from cte1; +c1 +2 +3 +4 +5 +6 +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 5 offset 10) select * from cte1; +c1 +11 +12 +13 +14 +15 +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 5 offset 995) select * from cte1; +c1 +996 +997 +998 +999 +1000 +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 5 offset 6) select * from cte1; +c1 +7 +8 +9 +10 +11 +set cte_max_recursion_depth=2; +with recursive cte1(c1) as (select 0 union select c1 + 1 from cte1 limit 1 offset 2) select * from cte1; +c1 +2 +with recursive cte1(c1) as (select 0 union select c1 + 1 from cte1 limit 1 offset 3) select * from cte1; +Error 3636 (HY000): Recursive query aborted after 3 iterations. Try increasing @@cte_max_recursion_depth to a larger value +set cte_max_recursion_depth=1000; +with recursive cte1(c1) as (select 0 union select c1 + 1 from cte1 limit 5 offset 996) select * from cte1; +c1 +996 +997 +998 +999 +1000 +with recursive cte1(c1) as (select 0 union select c1 + 1 from cte1 limit 5 offset 997) select * from cte1; +Error 3636 (HY000): Recursive query aborted after 1001 iterations. Try increasing @@cte_max_recursion_depth to a larger value +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 0 offset 1) select * from cte1; +c1 +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 0 offset 10) select * from cte1; +c1 +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 2 offset 1) select * from cte1 dt1 join cte1 dt2 order by dt1.c1, dt2.c1; +c1 c1 +2 2 +2 3 +3 2 +3 3 +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 2 offset 1) select * from cte1 dt1 join cte1 dt2 on dt1.c1 = dt2.c1 order by dt1.c1, dt1.c1; +c1 c1 +2 2 +3 3 +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 2 offset 1) select c1 from cte1 where c1 in (select 2); +c1 +2 +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 2 offset 1) select c1 from cte1 dt where c1 in (select c1 from cte1 where 1 = dt.c1 - 1); +c1 +2 +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 2 offset 1) select c1 from cte1 where cte1.c1 = (select dt1.c1 from cte1 dt1 where dt1.c1 = cte1.c1); +c1 +2 +3 +drop table if exists t1; +create table t1(c1 int); +insert into t1 values(1), (2), (3); +with recursive cte1(c1) as (select c1 from t1 limit 1 offset 1 union select c1 + 1 from cte1 limit 0 offset 1) select * from cte1; +Error 1221 (HY000): Incorrect usage of UNION and LIMIT +with recursive cte1(c1) as (select 1 union select 2 order by 1 limit 1 offset 1) select * from cte1; +c1 +2 +with recursive cte1(c1) as (select 1 union select 2 order by 1 limit 0 offset 1) select * from cte1; +c1 +with recursive cte1(c1) as (select 1 union select 2 order by 1 limit 2 offset 0) select * from cte1; +c1 +1 +2 +drop table if exists t1; +create table t1(c1 int); +insert into t1 values(0), (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12), (13), (14), (15), (16), (17), (18), (19), (20), (21), (22), (23), (24), (25), (26), (27), (28), (29), (30), (31), (32), (33), (34), (35), (36), (37), (38), (39), (40), (41), (42), (43), (44), (45), (46), (47), (48), (49), (50), (51), (52), (53), (54), (55), (56), (57), (58), (59), (60), (61), (62), (63), (64), (65), (66), (67), (68), (69), (70), (71), (72), (73), (74), (75), (76), (77), (78), (79), (80), (81), (82), (83), (84), (85), (86), (87), (88), (89), (90), (91), (92), (93), (94), (95), (96), (97), (98), (99), (100), (101), (102), (103), (104), (105), (106), (107), (108), (109), (110), (111), (112), (113), (114), (115), (116), (117), (118), (119), (120), (121), (122), (123), (124), (125), (126), (127), (128), (129), (130), (131), (132), (133), (134), (135), (136), (137), (138), (139), (140), (141), (142), (143), (144), (145), (146), (147), (148), (149), (150), (151), (152), (153), (154), (155), (156), (157), (158), (159), (160), (161), (162), (163), (164), (165), (166), (167), (168), (169), (170), (171), (172), (173), (174), (175), (176), (177), (178), (179), (180), (181), (182), (183), (184), (185), (186), (187), (188), (189), (190), (191), (192), (193), (194), (195), (196), (197), (198), (199), (200), (201), (202), (203), (204), (205), (206), (207), (208), (209), (210), (211), (212), (213), (214), (215), (216), (217), (218), (219), (220), (221), (222), (223), (224), (225), (226), (227), (228), (229), (230), (231), (232), (233), (234), (235), (236), (237), (238), (239), (240), (241), (242), (243), (244), (245), (246), (247), (248), (249), (250), (251), (252), (253), (254), (255), (256), (257), (258), (259), (260), (261), (262), (263), (264), (265), (266), (267), (268), (269), (270), (271), (272), (273), (274), (275), (276), (277), (278), (279), (280), (281), (282), (283), (284), (285), (286), (287), (288), (289), (290), (291), (292), (293), (294), (295), (296), (297), (298), (299); +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 c1 from cte1 limit 1) select * from cte1; +c1 +0 +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 c1 from cte1 limit 1 offset 100) select * from cte1; +c1 +100 +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 c1 from cte1 limit 5 offset 100) select * from cte1; +c1 +100 +101 +102 +103 +104 +with cte1 as (select c1 from t1 limit 2 offset 1) select * from cte1; +c1 +1 +2 +with cte1 as (select c1 from t1 limit 2 offset 1) select * from cte1 dt1 join cte1 dt2 on dt1.c1 = dt2.c1; +c1 c1 +1 1 +2 2 +with recursive cte1(c1) as (select c1 from t1 union select 2 limit 0 offset 1) select * from cte1; +c1 +with recursive cte1(c1) as (select c1 from t1 union select 2 limit 0 offset 1) select * from cte1 dt1 join cte1 dt2 on dt1.c1 = dt2.c1; +c1 c1 +with recursive cte1(c1) as (select c1 from t1 limit 3 offset 100) select * from cte1; +c1 +100 +101 +102 +with recursive cte1(c1) as (select c1 from t1 limit 3 offset 100) select * from cte1 dt1 join cte1 dt2 on dt1.c1 = dt2.c1; +c1 c1 +100 100 +101 101 +102 102 +set cte_max_recursion_depth = 0; +drop table if exists t1; +create table t1(c1 int); +insert into t1 values(0); +with recursive cte1 as (select 1/c1 c1 from t1 union select c1 + 1 c1 from cte1 where c1 < 2 limit 0) select * from cte1; +c1 +with recursive cte1 as (select 1/c1 c1 from t1 union select c1 + 1 c1 from cte1 where c1 < 2 limit 1) select * from cte1; +Error 3636 (HY000): Recursive query aborted after 1 iterations. Try increasing @@cte_max_recursion_depth to a larger value +set cte_max_recursion_depth = 1000; +drop table if exists t1; +create table t1(c1 int); +insert into t1 values(1), (2), (3); +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 0 offset 2) select * from cte1; +c1 +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 1 offset 2) select * from cte1; +c1 +3 +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 2 offset 2) select * from cte1; +c1 +3 +4 +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 3 offset 2) select * from cte1; +c1 +3 +4 +5 +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 4 offset 2) select * from cte1; +c1 +3 +4 +5 +6 +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 0 offset 3) select * from cte1; +c1 +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 1 offset 3) select * from cte1; +c1 +4 +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 2 offset 3) select * from cte1; +c1 +4 +5 +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 3 offset 3) select * from cte1; +c1 +4 +5 +6 +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 4 offset 3) select * from cte1; +c1 +4 +5 +6 +7 +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 0 offset 4) select * from cte1; +c1 +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 1 offset 4) select * from cte1; +c1 +5 +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 2 offset 4) select * from cte1; +c1 +5 +6 +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 3 offset 4) select * from cte1; +c1 +5 +6 +7 +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 4 offset 4) select * from cte1; +c1 +5 +6 +7 +8 +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 0 offset 2) select * from cte1; +c1 +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 1 offset 2) select * from cte1; +c1 +3 +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 2 offset 2) select * from cte1; +c1 +3 +2 +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 3 offset 2) select * from cte1; +c1 +3 +2 +3 +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 4 offset 2) select * from cte1; +c1 +3 +2 +3 +4 +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 0 offset 3) select * from cte1; +c1 +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 1 offset 3) select * from cte1; +c1 +2 +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 2 offset 3) select * from cte1; +c1 +2 +3 +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 3 offset 3) select * from cte1; +c1 +2 +3 +4 +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 4 offset 3) select * from cte1; +c1 +2 +3 +4 +3 +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 0 offset 4) select * from cte1; +c1 +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 1 offset 4) select * from cte1; +c1 +3 +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 2 offset 4) select * from cte1; +c1 +3 +4 +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 3 offset 4) select * from cte1; +c1 +3 +4 +3 +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 4 offset 4) select * from cte1; +c1 +3 +4 +3 +4 +set cte_max_recursion_depth = default; +drop table if exists executor__cte.t; +drop view if exists executor__cte.v; +create database if not exists executor__cte1; +create table executor__cte.t (a int); +create table executor__cte1.t (a int); +insert into executor__cte.t values (1); +insert into executor__cte1.t values (2); +create definer='root'@'localhost' view executor__cte.v as with tt as (select * from t) select * from tt; +select * from executor__cte.v; +a +1 +use executor__cte1; +select * from executor__cte.v; +a +1 +use executor__cte; +drop database executor__cte1; diff --git a/tests/integrationtest/r/executor/explain.result b/tests/integrationtest/r/executor/explain.result new file mode 100644 index 0000000000000..b1753240540db --- /dev/null +++ b/tests/integrationtest/r/executor/explain.result @@ -0,0 +1,302 @@ +drop table if exists t; +create table t (v int); +explain format = 'brief' select * from t t1, t t2; +id estRows task access object operator info +HashJoin 100000000.00 root CARTESIAN inner join +├─TableReader(Build) 10000.00 root data:TableFullScan +│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo +└─TableReader(Probe) 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +explain format = 'brief' select * from t t1 where exists (select 1 from t t2 where t2.v > t1.v); +id estRows task access object operator info +HashJoin 7992.00 root CARTESIAN semi join, other cond:gt(executor__explain.t.v, executor__explain.t.v) +├─TableReader(Build) 9990.00 root data:Selection +│ └─Selection 9990.00 cop[tikv] not(isnull(executor__explain.t.v)) +│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo +└─TableReader(Probe) 9990.00 root data:Selection + └─Selection 9990.00 cop[tikv] not(isnull(executor__explain.t.v)) + └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +explain format = 'brief' select * from t t1 where exists (select 1 from t t2 where t2.v in (t1.v+1, t1.v+2)); +id estRows task access object operator info +HashJoin 8000.00 root CARTESIAN semi join, other cond:in(executor__explain.t.v, plus(executor__explain.t.v, 1), plus(executor__explain.t.v, 2)) +├─TableReader(Build) 10000.00 root data:TableFullScan +│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo +└─TableReader(Probe) 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +explain format = 'brief' select * from t t1, t t2 where t1.v = t2.v; +id estRows task access object operator info +HashJoin 12487.50 root inner join, equal:[eq(executor__explain.t.v, executor__explain.t.v)] +├─TableReader(Build) 9990.00 root data:Selection +│ └─Selection 9990.00 cop[tikv] not(isnull(executor__explain.t.v)) +│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo +└─TableReader(Probe) 9990.00 root data:Selection + └─Selection 9990.00 cop[tikv] not(isnull(executor__explain.t.v)) + └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +drop table if exists t; +create table t (a int); +explain analyze insert into t select 1; +select * from t; +a +1 +explain analyze update t set a=2 where a=1; +select * from t; +a +2 +explain format = 'brief' insert into t select 1; +select * from t; +a +2 +explain analyze insert into t select 1; +explain analyze replace into t values (3); +select * from t order by a; +a +1 +2 +3 +desc format='brief' select * from information_schema.statements_summary; +id estRows task access object operator info +MemTableScan 10000.00 root table:STATEMENTS_SUMMARY +desc format='brief' select * from information_schema.statements_summary where digest is null; +id estRows task access object operator info +Selection 8000.00 root isnull(Column#5) +└─MemTableScan 10000.00 root table:STATEMENTS_SUMMARY +desc format='brief' select * from information_schema.statements_summary where digest = 'abcdefg'; +id estRows task access object operator info +MemTableScan 10000.00 root table:STATEMENTS_SUMMARY digests: ["abcdefg"] +desc format='brief' select * from information_schema.statements_summary where digest in ('a','b','c'); +id estRows task access object operator info +MemTableScan 10000.00 root table:STATEMENTS_SUMMARY digests: ["a","b","c"] +drop table if exists tt123; +CREATE TABLE tt123 ( +id int(11) NOT NULL, +a bigint(20) DEFAULT NULL, +b char(20) DEFAULT NULL, +c datetime DEFAULT NULL, +d double DEFAULT NULL, +e json DEFAULT NULL, +f decimal(40,6) DEFAULT NULL, +PRIMARY KEY (id) /*T![clustered_index] CLUSTERED */, +KEY a (a), +KEY b (b), +KEY c (c), +KEY d (d), +KEY f (f) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; +explain format='brief' select /*+ inl_hash_join(t1) */ * from tt123 t1 join tt123 t2 on t1.b=t2.e; +id estRows task access object operator info +Projection 12500.00 root executor__explain.tt123.id, executor__explain.tt123.a, executor__explain.tt123.b, executor__explain.tt123.c, executor__explain.tt123.d, executor__explain.tt123.e, executor__explain.tt123.f, executor__explain.tt123.id, executor__explain.tt123.a, executor__explain.tt123.b, executor__explain.tt123.c, executor__explain.tt123.d, executor__explain.tt123.e, executor__explain.tt123.f +└─HashJoin 12500.00 root inner join, equal:[eq(executor__explain.tt123.e, Column#15)] + ├─TableReader(Build) 10000.00 root data:TableFullScan + │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo + └─Projection(Probe) 10000.00 root executor__explain.tt123.id, executor__explain.tt123.a, executor__explain.tt123.b, executor__explain.tt123.c, executor__explain.tt123.d, executor__explain.tt123.e, executor__explain.tt123.f, cast(executor__explain.tt123.b, json BINARY)->Column#15 + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +drop table if exists t; +create table t (a int primary key); +insert into t values (2); +set @@tidb_constraint_check_in_place=1; +explain analyze insert into t values (1), (2), (3); +Error 1062 (23000): Duplicate entry '2' for key 't.PRIMARY' +select * from t; +a +2 +set @@tidb_constraint_check_in_place=DEFAULT; +drop table if exists t; +create table t(a int); +set @@session.tidb_enable_non_prepared_plan_cache = 1; +select * from t limit 1; +a +select * from t limit 1; +a +explain format = 'plan_cache' select * from (select * from t) t1 limit 1; +id estRows task access object operator info +Limit_8 1.00 root offset:0, count:1 +└─TableReader_12 1.00 root data:Limit_11 + └─Limit_11 1.00 cop[tikv] offset:0, count:1 + └─TableFullScan_10 1.00 cop[tikv] table:t keep order:false, stats:pseudo +show warnings; +Level Code Message +Warning 1105 skip non-prepared plan-cache: queries that have sub-queries are not supported +explain format = 'plan_cache' select * from (select * from t) t1 limit 1; +id estRows task access object operator info +Limit_8 1.00 root offset:0, count:1 +└─TableReader_12 1.00 root data:Limit_11 + └─Limit_11 1.00 cop[tikv] offset:0, count:1 + └─TableFullScan_10 1.00 cop[tikv] table:t keep order:false, stats:pseudo +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +explain analyze format = 'plan_cache' select * from (select * from t) t1 limit 1; +show warnings; +Level Code Message +Warning 1105 skip non-prepared plan-cache: queries that have sub-queries are not supported +explain analyze format = 'plan_cache' select * from (select * from t) t1 limit 1; +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +explain format = 'plan_cache' select * from t; +id estRows task access object operator info +TableReader_5 10000.00 root data:TableFullScan_4 +└─TableFullScan_4 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +show warnings; +Level Code Message +explain format = 'plan_cache' select * from t; +id estRows task access object operator info +TableReader_5 10000.00 root data:TableFullScan_4 +└─TableFullScan_4 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +explain analyze format = 'plan_cache' select * from t; +show warnings; +Level Code Message +explain analyze format = 'plan_cache' select * from t; +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +explain select * from t; +id estRows task access object operator info +TableReader_5 10000.00 root data:TableFullScan_4 +└─TableFullScan_4 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +explain format = 'brief' select * from t; +id estRows task access object operator info +TableReader 10000.00 root data:TableFullScan +└─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +explain format = 'dot' select * from t; +dot contents + +digraph TableReader_5 { +subgraph cluster5{ +node [style=filled, color=lightgrey] +color=black +label = "root" +"TableReader_5" +} +subgraph cluster4{ +node [style=filled, color=lightgrey] +color=black +label = "cop" +"TableFullScan_4" +} +"TableReader_5" -> "TableFullScan_4" +} + +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +explain format = 'hint' select * from t; +hint +use_index(@`sel_1` `executor__explain`.`t` ) +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +explain format = 'row' select * from t; +id estRows task access object operator info +TableReader_5 10000.00 root data:TableFullScan_4 +└─TableFullScan_4 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +explain format = 'verbose' select * from t; +id estRows estCost task access object operator info +TableReader_5 10000.00 177906.67 root data:TableFullScan_4 +└─TableFullScan_4 10000.00 2035000.00 cop[tikv] table:t keep order:false, stats:pseudo +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +explain format = 'traditional' select * from t; +id estRows task access object operator info +TableReader_5 10000.00 root data:TableFullScan_4 +└─TableFullScan_4 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +explain format = 'binary' select * from t; +binary plan +zQFYCsoBCg1UYWJsZVJlYWRlcl81EncKD1QBEVBGdWxsU2Nhbl80IQEAAAA4DT9BKQABAfBGiMNAOAJAAkoYChYKEWV4ZWN1dG9yX19leHBsYWluEgF0Uh5rZWVwIG9yZGVyOmZhbHNlLCBzdGF0czpwc2V1ZG9w//////8BAwQBeAEGBQEgASFVVVVVlbcFHWYoAUABUhRkYXRhOlQ2kgAAcAUzAQEsAXj///////////8B +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +explain format = 'tidb_json' select * from t; +TiDB_JSON +[ + { + "id": "TableReader_5", + "estRows": "10000.00", + "taskType": "root", + "operatorInfo": "data:TableFullScan_4", + "subOperators": [ + { + "id": "TableFullScan_4", + "estRows": "10000.00", + "taskType": "cop[tikv]", + "accessObject": "table:t", + "operatorInfo": "keep order:false, stats:pseudo" + } + ] + } +] + +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +explain format = 'cost_trace' select * from t; +id estRows estCost costFormula task access object operator info +TableReader_5 10000.00 177906.67 ((scan(10000*logrowsize(32)*tikv_scan_factor(40.7))) + (net(10000*rowsize(16)*tidb_kv_net_factor(3.96))))/15.00 root data:TableFullScan_4 +└─TableFullScan_4 10000.00 2035000.00 scan(10000*logrowsize(32)*tikv_scan_factor(40.7)) cop[tikv] table:t keep order:false, stats:pseudo +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +set @@session.tidb_enable_non_prepared_plan_cache = DEFAULT; +drop table if exists t; +drop view if exists v; +drop user if exists 'explain'@'%'; +create table t (id int); +create view v as select * from t; +create user 'explain'@'%'; +grant select on executor__explain.v to 'explain'@'%'; +show databases; +Database +INFORMATION_SCHEMA +executor__explain +use executor__explain; +select * from v; +id +explain format = 'brief' select * from v; +Error 1345 (HY000): EXPLAIN/SHOW can not be issued; lacking privileges for underlying table +grant show view on executor__explain.v to 'explain'@'%'; +explain format = 'brief' select * from v; +id estRows task access object operator info +TableReader 10000.00 root data:TableFullScan +└─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +revoke select on executor__explain.v from 'explain'@'%'; +explain format = 'brief' select * from v; +Error 1142 (42000): SELECT command denied to user 'explain'@'%' for table 'v' +create table t1 (i int); +create table t2 (j int); +create table t3 (k int, secret int); +create view v1 as select * from t1; +create view v2 as select * from v1, t2; +create view v3 as select k from t3; +grant select, show view on executor__explain.v2 to 'explain'@'%'; +grant show view on executor__explain.v1 to 'explain'@'%'; +grant select, show view on executor__explain.t3 to 'explain'@'%'; +grant select, show view on executor__explain.v3 to 'explain'@'%'; +explain select * from v1; +Error 1142 (42000): SELECT command denied to user 'explain'@'%' for table 'v1' +explain select * from v2; +Error 1345 (HY000): EXPLAIN/SHOW can not be issued; lacking privileges for underlying table +explain select * from t3; +id estRows task access object operator info +TableReader_5 10000.00 root data:TableFullScan_4 +└─TableFullScan_4 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo +explain select * from v3; +id estRows task access object operator info +TableReader_7 10000.00 root data:TableFullScan_6 +└─TableFullScan_6 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo diff --git a/tests/integrationtest/r/executor/explainfor.result b/tests/integrationtest/r/executor/explainfor.result new file mode 100644 index 0000000000000..b6a8f1d0b2f34 --- /dev/null +++ b/tests/integrationtest/r/executor/explainfor.result @@ -0,0 +1,836 @@ +desc format='brief' select * from METRICS_SCHEMA.tidb_query_duration where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13' ; +id estRows task access object operator info +MemTableScan 10000.00 root table:tidb_query_duration PromQL:histogram_quantile(0.9, sum(rate(tidb_server_handle_query_duration_seconds_bucket{}[60s])) by (le,sql_type,instance)), start_time:2019-12-23 16:10:13, end_time:2019-12-23 16:30:13, step:1m0s +desc format='brief' select * from METRICS_SCHEMA.up where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13' ; +id estRows task access object operator info +MemTableScan 10000.00 root table:up PromQL:up{}, start_time:2019-12-23 16:10:13, end_time:2019-12-23 16:30:13, step:1m0s +desc format='brief' select * from information_schema.cluster_log where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13'; +id estRows task access object operator info +MemTableScan 10000.00 root table:CLUSTER_LOG start_time:2019-12-23 16:10:13, end_time:2019-12-23 16:30:13 +desc format='brief' select * from information_schema.cluster_log where level in ('warn','error') and time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13'; +id estRows task access object operator info +MemTableScan 10000.00 root table:CLUSTER_LOG start_time:2019-12-23 16:10:13, end_time:2019-12-23 16:30:13, log_levels:["error","warn"] +desc format='brief' select * from information_schema.cluster_log where type in ('high_cpu_1','high_memory_1') and time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13'; +id estRows task access object operator info +MemTableScan 10000.00 root table:CLUSTER_LOG start_time:2019-12-23 16:10:13, end_time:2019-12-23 16:30:13, node_types:["high_cpu_1","high_memory_1"] +desc format='brief' select * from information_schema.slow_query; +id estRows task access object operator info +MemTableScan 10000.00 root table:SLOW_QUERY only search in the current 'tidb-slow.log' file +desc format='brief' select * from information_schema.slow_query where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13'; +id estRows task access object operator info +MemTableScan 10000.00 root table:SLOW_QUERY start_time:2019-12-23 16:10:13.000000, end_time:2019-12-23 16:30:13.000000 +set @@time_zone = '+00:00'; +desc format='brief' select * from information_schema.slow_query where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13'; +id estRows task access object operator info +MemTableScan 10000.00 root table:SLOW_QUERY start_time:2019-12-23 16:10:13.000000, end_time:2019-12-23 16:30:13.000000 +set @@time_zone = default; +desc format='brief' select * from information_schema.cluster_config where type in ('tikv', 'tidb'); +id estRows task access object operator info +MemTableScan 10000.00 root table:CLUSTER_CONFIG node_types:["tidb","tikv"] +desc format='brief' select * from information_schema.cluster_config where instance='192.168.1.7:2379'; +id estRows task access object operator info +MemTableScan 10000.00 root table:CLUSTER_CONFIG instances:["192.168.1.7:2379"] +desc format='brief' select * from information_schema.cluster_config where type='tidb' and instance='192.168.1.7:2379'; +id estRows task access object operator info +MemTableScan 10000.00 root table:CLUSTER_CONFIG node_types:["tidb"], instances:["192.168.1.7:2379"] +desc format='brief' select * from information_schema.inspection_result where rule = 'ddl' and rule = 'config'; +id estRows task access object operator info +MemTableScan 10000.00 root table:INSPECTION_RESULT skip_inspection:true +desc format='brief' select * from information_schema.inspection_result where rule in ('ddl', 'config'); +id estRows task access object operator info +MemTableScan 10000.00 root table:INSPECTION_RESULT rules:["config","ddl"], items:[] +desc format='brief' select * from information_schema.inspection_result where item in ('ddl.lease', 'raftstore.threadpool'); +id estRows task access object operator info +MemTableScan 10000.00 root table:INSPECTION_RESULT rules:[], items:["ddl.lease","raftstore.threadpool"] +desc format='brief' select * from information_schema.inspection_result where item in ('ddl.lease', 'raftstore.threadpool') and rule in ('ddl', 'config'); +id estRows task access object operator info +MemTableScan 10000.00 root table:INSPECTION_RESULT rules:["config","ddl"], items:["ddl.lease","raftstore.threadpool"] +desc format='brief' select * from information_schema.inspection_rules where type='inspection'; +id estRows task access object operator info +MemTableScan 10000.00 root table:INSPECTION_RULES node_types:["inspection"] +desc format='brief' select * from information_schema.inspection_rules where type='inspection' or type='summary'; +id estRows task access object operator info +MemTableScan 10000.00 root table:INSPECTION_RULES node_types:["inspection","summary"] +desc format='brief' select * from information_schema.inspection_rules where type='inspection' and type='summary'; +id estRows task access object operator info +MemTableScan 10000.00 root table:INSPECTION_RULES skip_request: true +set tidb_enable_prepared_plan_cache=1; +drop table if exists t; +create table t(a int, b int, c int generated always as (a+b) stored); +insert into t(a,b) values(1,1); +begin; +update t set b = 2 where a = 1; +prepare stmt from 'select b from t where a > ?'; +set @p = 0; +execute stmt using @p; +b +2 +set @p = 1; +execute stmt using @p; +b +insert into t(a,b,c) values(3,3,3); +Error 3105 (HY000): The value specified for generated column 'c' in table 't' is not allowed. +rollback; +set tidb_enable_prepared_plan_cache=default; +desc format='brief' select * from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'information_schema'; +id estRows task access object operator info +MemTableScan 10000.00 root table:TABLE_STORAGE_STATS schema:["information_schema"] +desc format='brief' select * from information_schema.TABLE_STORAGE_STATS where TABLE_NAME = 'schemata'; +id estRows task access object operator info +MemTableScan 10000.00 root table:TABLE_STORAGE_STATS table:["schemata"] +desc format='brief' select * from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'information_schema' and TABLE_NAME = 'schemata'; +id estRows task access object operator info +MemTableScan 10000.00 root table:TABLE_STORAGE_STATS schema:["information_schema"], table:["schemata"] +desc format='brief' select * from information_schema.inspection_summary where rule='ddl'; +id estRows task access object operator info +Selection 8000.00 root eq(Column#1, "ddl") +└─MemTableScan 10000.00 root table:INSPECTION_SUMMARY rules:["ddl"] +desc format='brief' select * from information_schema.inspection_summary where 'ddl'=rule or rule='config'; +id estRows task access object operator info +Selection 8000.00 root or(eq("ddl", Column#1), eq(Column#1, "config")) +└─MemTableScan 10000.00 root table:INSPECTION_SUMMARY rules:["config","ddl"] +desc format='brief' select * from information_schema.inspection_summary where 'ddl'=rule or rule='config' or rule='slow_query'; +id estRows task access object operator info +Selection 8000.00 root or(eq("ddl", Column#1), or(eq(Column#1, "config"), eq(Column#1, "slow_query"))) +└─MemTableScan 10000.00 root table:INSPECTION_SUMMARY rules:["config","ddl","slow_query"] +desc format='brief' select * from information_schema.inspection_summary where (rule='config' or rule='slow_query') and (metrics_name='metric_name3' or metrics_name='metric_name1'); +id estRows task access object operator info +Selection 8000.00 root or(eq(Column#1, "config"), eq(Column#1, "slow_query")), or(eq(Column#3, "metric_name3"), eq(Column#3, "metric_name1")) +└─MemTableScan 10000.00 root table:INSPECTION_SUMMARY rules:["config","slow_query"], metric_names:["metric_name1","metric_name3"] +desc format='brief' select * from information_schema.inspection_summary where rule in ('ddl', 'slow_query'); +id estRows task access object operator info +Selection 8000.00 root in(Column#1, "ddl", "slow_query") +└─MemTableScan 10000.00 root table:INSPECTION_SUMMARY rules:["ddl","slow_query"] +desc format='brief' select * from information_schema.inspection_summary where rule in ('ddl', 'slow_query') and metrics_name='metric_name1'; +id estRows task access object operator info +Selection 8000.00 root eq(Column#3, "metric_name1"), in(Column#1, "ddl", "slow_query") +└─MemTableScan 10000.00 root table:INSPECTION_SUMMARY rules:["ddl","slow_query"], metric_names:["metric_name1"] +desc format='brief' select * from information_schema.inspection_summary where rule in ('ddl', 'slow_query') and metrics_name in ('metric_name1', 'metric_name2'); +id estRows task access object operator info +Selection 8000.00 root in(Column#1, "ddl", "slow_query"), in(Column#3, "metric_name1", "metric_name2") +└─MemTableScan 10000.00 root table:INSPECTION_SUMMARY rules:["ddl","slow_query"], metric_names:["metric_name1","metric_name2"] +desc format='brief' select * from information_schema.inspection_summary where rule='ddl' and metrics_name in ('metric_name1', 'metric_name2'); +id estRows task access object operator info +Selection 8000.00 root eq(Column#1, "ddl"), in(Column#3, "metric_name1", "metric_name2") +└─MemTableScan 10000.00 root table:INSPECTION_SUMMARY rules:["ddl"], metric_names:["metric_name1","metric_name2"] +desc format='brief' select * from information_schema.inspection_summary where rule='ddl' and metrics_name='metric_NAME3'; +id estRows task access object operator info +Selection 8000.00 root eq(Column#1, "ddl"), eq(Column#3, "metric_NAME3") +└─MemTableScan 10000.00 root table:INSPECTION_SUMMARY rules:["ddl"], metric_names:["metric_name3"] +desc format='brief' select * from information_schema.inspection_summary where rule in ('ddl', 'config') and rule in ('slow_query', 'config'); +id estRows task access object operator info +Selection 8000.00 root in(Column#1, "ddl", "config"), in(Column#1, "slow_query", "config") +└─MemTableScan 10000.00 root table:INSPECTION_SUMMARY rules:["config"] +desc format='brief' select * from information_schema.inspection_summary where metrics_name in ('metric_name1', 'metric_name4') and metrics_name in ('metric_name5', 'metric_name4') and rule in ('ddl', 'config') and rule in ('slow_query', 'config') and quantile in (0.80, 0.90); +id estRows task access object operator info +Selection 8000.00 root in(Column#1, "ddl", "config"), in(Column#1, "slow_query", "config"), in(Column#3, "metric_name1", "metric_name4"), in(Column#3, "metric_name5", "metric_name4") +└─MemTableScan 10000.00 root table:INSPECTION_SUMMARY rules:["config"], metric_names:["metric_name4"], quantiles:[0.800000,0.900000] +desc format='brief' select * from information_schema.inspection_summary where metrics_name in ('metric_name1', 'metric_name4') and metrics_name in ('metric_name5', 'metric_name4') and metrics_name in ('metric_name5', 'metric_name1') and metrics_name in ('metric_name1', 'metric_name3'); +id estRows task access object operator info +Selection 8000.00 root in(Column#3, "metric_name1", "metric_name3"), in(Column#3, "metric_name1", "metric_name4"), in(Column#3, "metric_name5", "metric_name1"), in(Column#3, "metric_name5", "metric_name4") +└─MemTableScan 10000.00 root table:INSPECTION_SUMMARY skip_inspection: true +desc format='brief' select * from information_schema.TIFLASH_TABLES where TIFLASH_INSTANCE = '192.168.1.7:3930'; +id estRows task access object operator info +MemTableScan 10000.00 root table:TIFLASH_TABLES tiflash_instances:["192.168.1.7:3930"] +desc format='brief' select * from information_schema.TIFLASH_SEGMENTS where TIFLASH_INSTANCE = '192.168.1.7:3930'; +id estRows task access object operator info +MemTableScan 10000.00 root table:TIFLASH_SEGMENTS tiflash_instances:["192.168.1.7:3930"] +desc format='brief' select * from information_schema.TIFLASH_TABLES where TIDB_DATABASE = 'test'; +id estRows task access object operator info +MemTableScan 10000.00 root table:TIFLASH_TABLES tidb_databases:["test"] +desc format='brief' select * from information_schema.TIFLASH_SEGMENTS where TIDB_DATABASE = 'test'; +id estRows task access object operator info +MemTableScan 10000.00 root table:TIFLASH_SEGMENTS tidb_databases:["test"] +desc format='brief' select * from information_schema.TIFLASH_TABLES where TIDB_TABLE = 't'; +id estRows task access object operator info +MemTableScan 10000.00 root table:TIFLASH_TABLES tidb_tables:["t"] +desc format='brief' select * from information_schema.TIFLASH_SEGMENTS where TIDB_TABLE = 't'; +id estRows task access object operator info +MemTableScan 10000.00 root table:TIFLASH_SEGMENTS tidb_tables:["t"] +desc format='brief' select * from information_schema.TIFLASH_TABLES where TIFLASH_INSTANCE = '192.168.1.7:3930' and TIDB_DATABASE = 'test' and TIDB_TABLE = 't'; +id estRows task access object operator info +MemTableScan 10000.00 root table:TIFLASH_TABLES tiflash_instances:["192.168.1.7:3930"], tidb_databases:["test"], tidb_tables:["t"] +desc format='brief' select * from information_schema.TIFLASH_SEGMENTS where TIFLASH_INSTANCE = '192.168.1.7:3930' and TIDB_DATABASE = 'test' and TIDB_TABLE = 't'; +id estRows task access object operator info +MemTableScan 10000.00 root table:TIFLASH_SEGMENTS tiflash_instances:["192.168.1.7:3930"], tidb_databases:["test"], tidb_tables:["t"] +set tidb_enable_prepared_plan_cache=1; +set @@tidb_enable_collect_execution_info=0; +drop table if exists t1, t2; +CREATE TABLE `t1` (a int); +CREATE TABLE `t2` (a int); +insert into t1 values(1), (2); +insert into t2 values(1), (3); +prepare stmt from 'select * from t1 where a > ? union select * from t2 where a > ?;'; +set @a=0, @b=1; +execute stmt using @a, @b; +a +1 +2 +3 +execute stmt using @b, @a; +a +1 +2 +3 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt using @b, @b; +a +2 +3 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt using @a, @a; +a +1 +2 +3 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +prepare stmt from 'select * from t1 where a > ? union all select * from t2 where a > ?;'; +set @a=0, @b=1; +execute stmt using @a, @b; +a +1 +2 +3 +execute stmt using @b, @a; +a +1 +2 +3 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt using @b, @b; +a +2 +3 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt using @a, @a; +a +1 +1 +2 +3 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +prepare stmt from 'select * from t1 where a > ? except select * from t2 where a > ?;'; +set @a=0, @b=1; +execute stmt using @a, @a; +a +2 +execute stmt using @b, @a; +a +2 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt using @b, @b; +a +2 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt using @a, @b; +a +1 +2 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +prepare stmt from 'select * from t1 where a > ? union select * from t2 where a > ?;'; +set @a=0, @b=1; +execute stmt using @a, @a; +a +1 +2 +3 +execute stmt using @b, @a; +a +1 +2 +3 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt using @b, @b; +a +2 +3 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt using @a, @b; +a +1 +2 +3 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +prepare stmt from 'select * from t1 union all select * from t1 intersect select * from t2;'; +execute stmt; +a +1 +1 +2 +prepare stmt from '(select * from t1 union all select * from t1) intersect select * from t2;'; +execute stmt; +a +1 +prepare stmt from '(select * from t1 union all select * from t1 intersect select * from t2) order by a limit 2;'; +execute stmt; +a +1 +1 +set tidb_enable_prepared_plan_cache=default; +set @@tidb_enable_collect_execution_info=default; +set tidb_enable_prepared_plan_cache=1; +set @@tidb_enable_collect_execution_info=0; +drop table if exists t; +create table t(a int, index idx_a(a)); +prepare stmt from 'select * from t;'; +execute stmt; +a +execute stmt; +a +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +prepare stmt from 'select /*+ IGNORE_PLAN_CACHE() */ * from t;'; +execute stmt; +a +execute stmt; +a +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +set tidb_enable_prepared_plan_cache=default; +set @@tidb_enable_collect_execution_info=default; +set tidb_enable_prepared_plan_cache=1; +set @@tidb_enable_collect_execution_info=0; +drop table if exists t; +CREATE TABLE t(c1 INT, index idx_c(c1)); +prepare stmt from 'select * from t use index(idx_c) where c1 > 1;'; +execute stmt; +c1 +execute stmt; +c1 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +ALTER TABLE t ALTER INDEX idx_c INVISIBLE; +select * from t use index(idx_c) where c1 > 1; +Error 1176 (42000): Key 'idx_c' doesn't exist in table 't' +execute stmt; +Error 1176 (42000): Key 'idx_c' doesn't exist in table 't' +set tidb_enable_prepared_plan_cache=default; +set @@tidb_enable_collect_execution_info=default; +set tidb_enable_prepared_plan_cache=1; +set @@tidb_enable_collect_execution_info=0; +prepare stmt from 'with recursive cte1 as (select ? c1 union all select c1 + 1 c1 from cte1 where c1 < ?) select * from cte1;'; +set @a=5, @b=4, @c=2, @d=1; +execute stmt using @d, @a; +c1 +1 +2 +3 +4 +5 +execute stmt using @d, @b; +c1 +1 +2 +3 +4 +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +execute stmt using @c, @b; +c1 +2 +3 +4 +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +prepare stmt from 'with recursive cte1 as (select 1 c1 union all select 2 c1 union all select c1 + 1 c1 from cte1 where c1 < ?) select * from cte1 order by c1;'; +set @a=10, @b=2; +execute stmt using @a; +c1 +1 +2 +2 +3 +3 +4 +4 +5 +5 +6 +6 +7 +7 +8 +8 +9 +9 +10 +10 +execute stmt using @b; +c1 +1 +2 +2 +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +prepare stmt from 'with recursive cte1 as (select 1 c1 union all select 2 c1 union all select c1 + 1 c1 from cte1 where c1 < ? union all select c1 + ? c1 from cte1 where c1 < ?) select * from cte1 order by c1;'; +set @a=1, @b=2, @c=3, @d=4, @e=5; +execute stmt using @c, @b, @e; +c1 +1 +2 +2 +3 +3 +3 +4 +4 +5 +5 +5 +6 +6 +execute stmt using @b, @a, @d; +c1 +1 +2 +2 +2 +3 +3 +3 +4 +4 +4 +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +drop table if exists t1; +create table t1(a int); +insert into t1 values(1); +insert into t1 values(2); +prepare stmt from 'SELECT * FROM t1 dt WHERE EXISTS(WITH RECURSIVE qn AS (SELECT a*? AS b UNION ALL SELECT b+? FROM qn WHERE b=?) SELECT * FROM qn WHERE b=a);'; +show warnings; +Level Code Message +Warning 1105 skip prepared plan-cache: find table executor__explainfor.qn failed: [schema:1146]Table 'executor__explainfor.qn' doesn't exist +set @a=1, @b=2, @c=3, @d=4, @e=5, @f=0; +execute stmt using @f, @a, @f; +a +1 +execute stmt using @a, @b, @a; +a +1 +2 +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +execute stmt using @a, @b, @a; +a +1 +2 +prepare stmt from 'with recursive c(p) as (select ?), cte(a, b) as (select 1, 1 union select a+?, 1 from cte, c where a < ?) select * from cte order by 1, 2;'; +show warnings; +Level Code Message +Warning 1105 skip prepared plan-cache: find table executor__explainfor.cte failed: [schema:1146]Table 'executor__explainfor.cte' doesn't exist +execute stmt using @a, @a, @e; +a b +1 1 +2 1 +3 1 +4 1 +5 1 +execute stmt using @b, @b, @c; +a b +1 1 +3 1 +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +set tidb_enable_prepared_plan_cache=default; +set @@tidb_enable_collect_execution_info=default; +set tidb_enable_prepared_plan_cache=1; +set @@tidb_enable_collect_execution_info=0; +drop table if exists t; +create table t(a int); +prepare stmt from 'select * from t;'; +execute stmt; +a +execute stmt; +a +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +drop database if exists plan_cache; +create database plan_cache; +use plan_cache; +create table t(a int); +insert into t values(1); +execute stmt; +a +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +execute stmt; +a +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +prepare stmt from 'select * from t;'; +execute stmt; +a +1 +execute stmt; +a +1 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt; +a +1 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +set tidb_enable_prepared_plan_cache=default; +set @@tidb_enable_collect_execution_info=default; +set tidb_enable_prepared_plan_cache=1; +set @@tidb_enable_collect_execution_info=0; +set @@session.tidb_enable_list_partition=1; +drop table if exists t; +create table t(a int, b int) PARTITION BY LIST (a) ( PARTITION p0 VALUES IN (1, 2, 3), PARTITION p1 VALUES IN (4, 5, 6)); +set @@tidb_partition_prune_mode='static'; +prepare stmt from 'select * from t;'; +execute stmt; +a b +execute stmt; +a b +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +set tidb_enable_prepared_plan_cache=default; +set @@tidb_enable_collect_execution_info=default; +set @@session.tidb_enable_list_partition=default; +set @@tidb_partition_prune_mode=default; +drop table if exists t12, t97; +CREATE TABLE t12(a INT, b INT); +CREATE TABLE t97(a INT, b INT UNIQUE NOT NULL); +EXPLAIN SELECT t12.a, t12.b FROM t12 LEFT JOIN t97 on t12.b = t97.b; +id estRows task access object operator info +TableReader_7 10000.00 root data:TableFullScan_6 +└─TableFullScan_6 10000.00 cop[tikv] table:t12 keep order:false, stats:pseudo +EXPLAIN SELECT t12.a, t12.b FROM t12 LEFT JOIN t97 use index () on t12.b = t97.b; +id estRows task access object operator info +TableReader_7 10000.00 root data:TableFullScan_6 +└─TableFullScan_6 10000.00 cop[tikv] table:t12 keep order:false, stats:pseudo +set tidb_enable_prepared_plan_cache=1; +set @@tidb_enable_collect_execution_info=0; +drop table if exists t; +create table t(a int); +prepare stmt from 'select * from t;'; +execute stmt; +a +execute stmt; +a +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +set tidb_enable_prepared_plan_cache=1; +execute stmt; +Error 8111 (HY000): Prepared statement not found +prepare stmt from 'select * from t;'; +execute stmt; +a +execute stmt; +a +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt; +a +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +set tidb_enable_prepared_plan_cache=default; +set @@tidb_enable_collect_execution_info=default; +set tidb_enable_prepared_plan_cache=1; +set @@tidb_enable_collect_execution_info=0; +drop view if exists view1, view2, view3, view4; +drop table if exists view_t; +create table view_t (a int,b int); +insert into view_t values(1,2); +create definer='root'@'localhost' view view1 as select * from view_t; +create definer='root'@'localhost' view view2(c,d) as select * from view_t; +create definer='root'@'localhost' view view3(c,d) as select a,b from view_t; +create definer='root'@'localhost' view view4 as select * from (select * from (select * from view_t) tb1) tb; +prepare stmt1 from 'select * from view1;'; +execute stmt1; +a b +1 2 +execute stmt1; +a b +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +prepare stmt2 from 'select * from view2;'; +execute stmt2; +c d +1 2 +execute stmt2; +c d +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +prepare stmt3 from 'select * from view3;'; +execute stmt3; +c d +1 2 +execute stmt3; +c d +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +prepare stmt4 from 'select * from view4;'; +execute stmt4; +a b +1 2 +execute stmt4; +a b +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +drop table view_t; +create table view_t(c int,d int); +execute stmt1; +Error 1356 (HY000): View 'plan_cache.view1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +execute stmt2; +Error 1356 (HY000): View 'plan_cache.view2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +execute stmt3; +Error 1356 (HY000): View 'plan_cache.view3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +drop table view_t; +create table view_t(a int,b int,c int); +insert into view_t values(1,2,3); +execute stmt1; +a b +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +execute stmt1; +a b +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt2; +c d +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +execute stmt2; +c d +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt3; +c d +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +execute stmt3; +c d +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt4; +a b +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +execute stmt4; +a b +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +alter table view_t drop column a; +alter table view_t add column a int after b; +update view_t set a=1; +execute stmt1; +a b +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +execute stmt1; +a b +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt2; +c d +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +execute stmt2; +c d +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt3; +c d +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +execute stmt3; +c d +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt4; +a b +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +execute stmt4; +a b +1 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +drop table view_t; +drop view view1,view2,view3,view4; +set @@tidb_enable_window_function = 1; +drop table if exists t; +create table t(a int, b int); +insert into t values (1,1),(1,2),(2,1),(2,2); +create definer='root'@'localhost' view v as select a, first_value(a) over(rows between 1 preceding and 1 following), last_value(a) over(rows between 1 preceding and 1 following) from t; +prepare stmt from 'select * from v;'; +execute stmt; +a first_value(a) over(rows between 1 preceding and 1 following) last_value(a) over(rows between 1 preceding and 1 following) +1 1 1 +1 1 2 +2 1 2 +2 2 2 +execute stmt; +a first_value(a) over(rows between 1 preceding and 1 following) last_value(a) over(rows between 1 preceding and 1 following) +1 1 1 +1 1 2 +2 1 2 +2 2 2 +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +drop view v; +set @@tidb_enable_window_function = default; +set tidb_enable_prepared_plan_cache=default; +set @@tidb_enable_collect_execution_info=default; +drop table if exists t; +create table t(a int, index idx_a(a)); +drop table if exists r; +create table r(a int); +prepare stmt from 'select * from t;'; +create binding for select * from t using select /*+ use_index(t, idx_a) */ * from t; +execute stmt; +a +execute stmt; +a +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt; +a +select @@last_plan_from_binding; +@@last_plan_from_binding +1 +create binding for select * from t using select /*+ ignore_plan_cache() */ * from t; +execute stmt; +a +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +execute stmt; +a +select @@last_plan_from_binding; +@@last_plan_from_binding +1 +create binding for select * from t using select /*+ use_index(t, idx_a) */ * from t; +execute stmt; +a +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt; +a +select @@last_plan_from_binding; +@@last_plan_from_binding +1 +prepare stmt_join from 'select * from t, r where r.a = t.a;'; +create binding for select * from t, r where r.a = t.a using select /*+ straight_join() */* from t, r where r.a = t.a; +execute stmt_join; +a a +execute stmt_join; +a a +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt_join; +a a +select @@last_plan_from_binding; +@@last_plan_from_binding +1 +create binding for select * from t, r where r.a = t.a using select /*+ ignore_plan_cache() */* from t, r where r.a = t.a; +execute stmt_join; +a a +select @@last_plan_from_cache; +@@last_plan_from_cache +0 +execute stmt_join; +a a +select @@last_plan_from_binding; +@@last_plan_from_binding +1 +create binding for select * from t, r where r.a = t.a using select /*+ straight_join() */* from t, r where r.a = t.a; +execute stmt_join; +a a +select @@last_plan_from_cache; +@@last_plan_from_cache +1 +execute stmt_join; +a a +select @@last_plan_from_binding; +@@last_plan_from_binding +1 diff --git a/tests/integrationtest/r/executor/grant.result b/tests/integrationtest/r/executor/grant.result new file mode 100644 index 0000000000000..6fffe53952a96 --- /dev/null +++ b/tests/integrationtest/r/executor/grant.result @@ -0,0 +1,332 @@ +drop user if exists 'testWithGrant'@'localhost'; +CREATE USER 'testWithGrant'@'localhost' IDENTIFIED BY '123'; +SELECT * FROM mysql.db WHERE User="testWithGrant" and host="localhost"; +Host DB User Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv Create_tmp_table_priv Lock_tables_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Execute_priv Event_priv Trigger_priv +GRANT select ON executor__grant.* TO 'testWithGrant'@'localhost' WITH GRANT OPTION; +SELECT grant_priv FROM mysql.DB WHERE User="testWithGrant" and host="localhost" and db="executor__grant"; +grant_priv +Y +drop user if exists 'testWithGrant1'; +CREATE USER 'testWithGrant1'; +SELECT grant_priv FROM mysql.user WHERE User="testWithGrant1"; +grant_priv +N +GRANT ALL ON *.* TO 'testWithGrant1'; +SELECT grant_priv FROM mysql.user WHERE User="testWithGrant1"; +grant_priv +N +GRANT ALL ON *.* TO 'testWithGrant1' WITH GRANT OPTION; +SELECT grant_priv FROM mysql.user WHERE User="testWithGrant1"; +grant_priv +Y +drop user if exists 'dduser'@'%'; +drop DATABASE if exists `dddb_%`; +CREATE USER 'dduser'@'%' IDENTIFIED by '123456'; +CREATE DATABASE `dddb_%`; +CREATE table `dddb_%`.`te%` (id int); +GRANT ALL PRIVILEGES ON `dddb_%`.* TO 'dduser'@'%'; +GRANT ALL PRIVILEGES ON `dddb_%`.`te%` to 'dduser'@'%'; +DROP USER IF EXISTS 'test'@'%'; +SET sql_mode='NO_AUTO_CREATE_USER'; +GRANT ALL PRIVILEGES ON *.* to 'test'@'%' IDENTIFIED BY 'xxx'; +Error 1410 (42000): You are not allowed to create a user with GRANT +set sql_mode=default; +DROP USER IF EXISTS 'test'@'%'; +SET SQL_MODE=''; +GRANT ALL PRIVILEGES ON *.* to 'test'@'%' IDENTIFIED BY 'xxx'; +SELECT user FROM mysql.user WHERE user='test' and host='%'; +user +test +DROP USER IF EXISTS 'test'@'%'; +GRANT ALL PRIVILEGES ON *.* to 'test'@'%'; +SELECT user, plugin FROM mysql.user WHERE user='test' and host='%'; +user plugin +test mysql_native_password +DROP USER IF EXISTS 'test'@'%'; +set sql_mode=default; +CREATE USER '1234567890abcdefGHIKL1234567890abcdefGHIKL@localhost'; +Error 1470 (HY000): String '1234567890abcdefGHIKL1234567890abcdefGHIKL@localhost' is too long for user name (should be no longer than 32) +CREATE USER 'some_user_name@host_1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890X'; +Error 1470 (HY000): String 'some_user_name@host_1234567890abcdefghij1234567890abcdefghij1234567890' is too long for user name (should be no longer than 32) +drop role if exists r1, r2, r3, r4; +create role r1, r2, r3; +create table executor__grant.testatomic(x int); +grant update, select, insert, delete on *.* to r1, r2, r4; +Error 1410 (42000): You are not allowed to create a user with GRANT +select Update_priv, Select_priv, Insert_priv, Delete_priv from mysql.user where user in ('r1', 'r2', 'r3', 'r4') and host = "%"; +Update_priv Select_priv Insert_priv Delete_priv +N N N N +N N N N +N N N N +grant update, select, insert, delete on *.* to r1, r2, r3; +revoke all on *.* from r1, r2, r4, r3; +Error 1105 (HY000): Unknown user: r4@% +select Update_priv, Select_priv, Insert_priv, Delete_priv from mysql.user where user in ('r1', 'r2', 'r3', 'r4') and host = "%"; +Update_priv Select_priv Insert_priv Delete_priv +Y Y Y Y +Y Y Y Y +Y Y Y Y +grant update, select, insert, delete on executor__grant.* to r1, r2, r4; +Error 1410 (42000): You are not allowed to create a user with GRANT +select Update_priv, Select_priv, Insert_priv, Delete_priv from mysql.db where user in ('r1', 'r2', 'r3', 'r4') and host = "%"; +Update_priv Select_priv Insert_priv Delete_priv +grant update, select, insert, delete on executor__grant.* to r1, r2, r3; +revoke all on *.* from r1, r2, r4, r3; +Error 1105 (HY000): Unknown user: r4@% +select Update_priv, Select_priv, Insert_priv, Delete_priv from mysql.db where user in ('r1', 'r2', 'r3', 'r4') and host = "%"; +Update_priv Select_priv Insert_priv Delete_priv +Y Y Y Y +Y Y Y Y +Y Y Y Y +grant update, select, insert, delete on executor__grant.testatomic to r1, r2, r4; +Error 1410 (42000): You are not allowed to create a user with GRANT +select Table_priv from mysql.tables_priv where user in ('r1', 'r2', 'r3', 'r4') and host = "%"; +Table_priv +grant update, select, insert, delete on executor__grant.testatomic to r1, r2, r3; +revoke all on *.* from r1, r2, r4, r3; +Error 1105 (HY000): Unknown user: r4@% +select Table_priv from mysql.tables_priv where user in ('r1', 'r2', 'r3', 'r4') and host = "%"; +Table_priv +Select,Insert,Update,Delete +Select,Insert,Update,Delete +Select,Insert,Update,Delete +drop role if exists r1, r2, r3, r4; +drop table executor__grant.testatomic; +DROP USER IF EXISTS 'test'@'%'; +CREATE USER 'test'@'%' IDENTIFIED BY 'test'; +GRANT SELECT ON executor__grant.* to 'test'; +SELECT user,host FROM mysql.user WHERE user='test' and host='%'; +user host +test % +SET SQL_MODE='ANSI_QUOTES'; +GRANT ALL PRIVILEGES ON video_ulimit.* TO web@'%' IDENTIFIED BY 'eDrkrhZ>l2sV'; +REVOKE ALL PRIVILEGES ON video_ulimit.* FROM web@'%'; +DROP USER IF EXISTS 'web'@'%'; +set sql_mode=default; +DROP USER if exists 'ssl_auser'@'%'; +DROP USER if exists 'ssl_buser'@'%'; +DROP USER if exists 'ssl_cuser'@'%'; +DROP USER if exists 'ssl_duser'@'%'; +DROP USER if exists 'ssl_euser'@'%'; +DROP USER if exists 'ssl_fuser'@'%'; +DROP USER if exists 'ssl_guser'@'%'; +drop user if exists 'u1'@'%'; +drop user if exists 'u2'@'%'; +drop user if exists 'u3'@'%'; +CREATE USER 'ssl_auser'@'%' require issuer '/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US' subject '/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH' cipher 'AES128-GCM-SHA256'; +CREATE USER 'ssl_buser'@'%' require subject '/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH' cipher 'AES128-GCM-SHA256'; +CREATE USER 'ssl_cuser'@'%' require cipher 'AES128-GCM-SHA256'; +CREATE USER 'ssl_duser'@'%'; +CREATE USER 'ssl_euser'@'%' require none; +CREATE USER 'ssl_fuser'@'%' require ssl; +CREATE USER 'ssl_guser'@'%' require x509; +select * from mysql.global_priv where `user` like 'ssl_%'; +Host User Priv +% ssl_auser {"ssl_type":3,"ssl_cipher":"AES128-GCM-SHA256","x509_issuer":"/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US","x509_subject":"/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH"} +% ssl_buser {"ssl_type":3,"ssl_cipher":"AES128-GCM-SHA256","x509_subject":"/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH"} +% ssl_cuser {"ssl_type":3,"ssl_cipher":"AES128-GCM-SHA256"} +% ssl_duser {} +% ssl_euser {} +% ssl_fuser {"ssl_type":1} +% ssl_guser {"ssl_type":2} +CREATE USER 'u1'@'%'; +GRANT ALL ON *.* TO 'u1'@'%' require issuer '/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US' and subject '/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH'; +select priv from mysql.global_priv where `Host` = '%' and `User` = 'u1'; +priv +{"ssl_type":3,"x509_issuer":"/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US","x509_subject":"/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH"} +GRANT ALL ON *.* TO 'u1'@'%' require cipher 'AES128-GCM-SHA256'; +select priv from mysql.global_priv where `Host` = '%' and `User` = 'u1'; +priv +{"ssl_type":3,"ssl_cipher":"AES128-GCM-SHA256"} +GRANT select ON *.* TO 'u1'@'%'; +select priv from mysql.global_priv where `Host` = '%' and `User` = 'u1'; +priv +{"ssl_type":3,"ssl_cipher":"AES128-GCM-SHA256"} +GRANT ALL ON *.* TO 'u1'@'%' require none; +select priv from mysql.global_priv where `Host` = '%' and `User` = 'u1'; +priv +{} +CREATE USER 'u2'@'%'; +alter user 'u2'@'%' require ssl; +select priv from mysql.global_priv where `Host` = '%' and `User` = 'u2'; +priv +{"ssl_type":1} +alter user 'u2'@'%' require x509; +select priv from mysql.global_priv where `Host` = '%' and `User` = 'u2'; +priv +{"ssl_type":2} +alter user 'u2'@'%' require issuer '/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US' subject '/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH' cipher 'AES128-GCM-SHA256'; +select priv from mysql.global_priv where `Host` = '%' and `User` = 'u2'; +priv +{"ssl_type":3,"ssl_cipher":"AES128-GCM-SHA256","x509_issuer":"/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US","x509_subject":"/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH"} +alter user 'u2'@'%' require none; +select priv from mysql.global_priv where `Host` = '%' and `User` = 'u2'; +priv +{} +CREATE USER 'u3'@'%' require issuer '/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US' subject '/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH' cipher 'AES128-GCM-SHA256'; +show create user 'u3'; +CREATE USER for u3@% +CREATE USER 'u3'@'%' IDENTIFIED WITH 'mysql_native_password' AS '' REQUIRE CIPHER 'AES128-GCM-SHA256' ISSUER '/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US' SUBJECT '/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH' PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK PASSWORD HISTORY DEFAULT PASSWORD REUSE INTERVAL DEFAULT +CREATE USER 'u4'@'%' require issuer 'CN=TiDB,OU=PingCAP'; +Error 1105 (HY000): invalid X509_NAME input: CN=TiDB,OU=PingCAP +CREATE USER 'u5'@'%' require subject '/CN=TiDB\OU=PingCAP'; +Error 1105 (HY000): invalid X509_NAME input: /CN=TiDBOU=PingCAP +CREATE USER 'u6'@'%' require subject '/CN=TiDB\NC=PingCAP'; +Error 1105 (HY000): invalid X509_NAME input: /CN=TiDBNC=PingCAP +CREATE USER 'u7'@'%' require cipher 'AES128-GCM-SHA1'; +Error 1105 (HY000): Unsupported cipher suit: AES128-GCM-SHA1 +CREATE USER 'u8'@'%' require subject '/CN'; +Error 1105 (HY000): invalid X509_NAME input: /CN +CREATE USER 'u9'@'%' require cipher 'TLS_AES_256_GCM_SHA384' cipher 'RC4-SHA'; +Error 1105 (HY000): Duplicate require CIPHER clause +CREATE USER 'u9'@'%' require issuer 'CN=TiDB,OU=PingCAP' issuer 'CN=TiDB,OU=PingCAP2'; +Error 1105 (HY000): Duplicate require ISSUER clause +CREATE USER 'u9'@'%' require subject '/CN=TiDB\OU=PingCAP' subject '/CN=TiDB\OU=PingCAP2'; +Error 1105 (HY000): Duplicate require SUBJECT clause +CREATE USER 'u9'@'%' require ssl ssl; +[parser:1064]You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 36 near "ssl;" +CREATE USER 'u9'@'%' require x509 x509; +[parser:1064]You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 38 near "x509;" +drop user if exists 'maint_auth_str1'@'%'; +CREATE USER 'maint_auth_str1'@'%' IDENTIFIED BY 'foo'; +SELECT authentication_string FROM mysql.user WHERE `Host` = '%' and `User` = 'maint_auth_str1'; +authentication_string +*F3A2A51A9B0F2BE2468926B4132313728C250DBF +ALTER USER 'maint_auth_str1'@'%' REQUIRE SSL; +SELECT authentication_string FROM mysql.user WHERE `Host` = '%' and `User` = 'maint_auth_str1'; +authentication_string +*F3A2A51A9B0F2BE2468926B4132313728C250DBF +drop table if exists xx; +drop user if exists 'sync_ci_data'@'%'; +create table xx (id int); +CREATE USER 'sync_ci_data'@'%' IDENTIFIED BY 'sNGNQo12fEHe0n3vU'; +GRANT USAGE ON *.* TO 'sync_ci_data'@'%'; +GRANT USAGE ON sync_ci_data.* TO 'sync_ci_data'@'%'; +GRANT USAGE ON executor__grant.* TO 'sync_ci_data'@'%'; +GRANT USAGE ON executor__grant.xx TO 'sync_ci_data'@'%'; +drop user if exists issue27867; +create user issue27867; +grant all on performance_schema.* to issue27867; +Error 1044 (42000): Access denied for user 'root'@'%' to database 'performance_schema' +grant all on PERFormanCE_scHemA.* to issue27867; +Error 1044 (42000): Access denied for user 'root'@'%' to database 'PERFormanCE_scHemA' +grant select on performance_schema.* to issue27867; +grant insert on performance_schema.* to issue27867; +Error 1044 (42000): Access denied for user 'root'@'%' to database 'performance_schema' +grant update on performance_schema.* to issue27867; +Error 1044 (42000): Access denied for user 'root'@'%' to database 'performance_schema' +grant delete on performance_schema.* to issue27867; +Error 1044 (42000): Access denied for user 'root'@'%' to database 'performance_schema' +grant drop on performance_schema.* to issue27867; +Error 1044 (42000): Access denied for user 'root'@'%' to database 'performance_schema' +grant lock tables on performance_schema.* to issue27867; +Error 1044 (42000): Access denied for user 'root'@'%' to database 'performance_schema' +grant create on performance_schema.* to issue27867; +Error 1044 (42000): Access denied for user 'root'@'%' to database 'performance_schema' +grant references on performance_schema.* to issue27867; +Error 1044 (42000): Access denied for user 'root'@'%' to database 'performance_schema' +grant alter on PERFormAnCE_scHemA.* to issue27867; +Error 1044 (42000): Access denied for user 'root'@'%' to database 'PERFormAnCE_scHemA' +grant execute on performance_schema.* to issue27867; +Error 1044 (42000): Access denied for user 'root'@'%' to database 'performance_schema' +grant index on PERFormanCE_scHemA.* to issue27867; +Error 1044 (42000): Access denied for user 'root'@'%' to database 'PERFormanCE_scHemA' +grant create view on performance_schema.* to issue27867; +Error 1044 (42000): Access denied for user 'root'@'%' to database 'performance_schema' +grant show view on performance_schema.* to issue27867; +Error 1044 (42000): Access denied for user 'root'@'%' to database 'performance_schema' +drop user issue27867; +drop user if exists dyn; +create user dyn; +GRANT BACKUP_ADMIN ON executor__grant.* TO dyn; +Error 3619 (HY000): Illegal privilege level specified for BACKUP_ADMIN +GRANT BOGUS_GRANT ON *.* TO dyn; +Error 3929 (HY000): Dynamic privilege 'BOGUS_GRANT' is not registered with the server. +GRANT BACKUP_Admin ON *.* TO dyn; +SELECT * FROM mysql.global_grants WHERE `Host` = '%' AND `User` = 'dyn' ORDER BY user,host,priv,with_grant_option; +USER HOST PRIV WITH_GRANT_OPTION +dyn % BACKUP_ADMIN N +GRANT SYSTEM_VARIABLES_ADMIN, BACKUP_ADMIN ON *.* TO dyn; +SELECT * FROM mysql.global_grants WHERE `Host` = '%' AND `User` = 'dyn' ORDER BY user,host,priv,with_grant_option; +USER HOST PRIV WITH_GRANT_OPTION +dyn % BACKUP_ADMIN N +dyn % SYSTEM_VARIABLES_ADMIN N +GRANT ROLE_ADMIN, BACKUP_ADMIN ON *.* TO dyn WITH GRANT OPTION; +SELECT * FROM mysql.global_grants WHERE `Host` = '%' AND `User` = 'dyn' ORDER BY user,host,priv,with_grant_option; +USER HOST PRIV WITH_GRANT_OPTION +dyn % BACKUP_ADMIN Y +dyn % ROLE_ADMIN Y +dyn % SYSTEM_VARIABLES_ADMIN N +GRANT SYSTEM_VARIABLES_ADMIN, Select, ROLE_ADMIN ON *.* TO dyn; +SELECT Grant_Priv FROM mysql.user WHERE `Host` = '%' AND `User` = 'dyn'; +Grant_Priv +N +SELECT WITH_GRANT_OPTION FROM mysql.global_grants WHERE `Host` = '%' AND `User` = 'dyn' AND Priv='SYSTEM_VARIABLES_ADMIN'; +WITH_GRANT_OPTION +N +GRANT CONNECTION_ADMIN, Insert ON *.* TO dyn WITH GRANT OPTION; +SELECT Grant_Priv FROM mysql.user WHERE `Host` = '%' AND `User` = 'dyn'; +Grant_Priv +Y +SELECT WITH_GRANT_OPTION FROM mysql.global_grants WHERE `Host` = '%' AND `User` = 'dyn' AND Priv='CONNECTION_ADMIN'; +WITH_GRANT_OPTION +Y +drop user if exists u29302; +create user u29302; +grant create temporary tables on NotExistsD29302.NotExistsT29302 to u29302; +Error 1144 (42000): Illegal GRANT/REVOKE command; please consult the manual to see which privileges can be used +grant lock tables on executor__grant.NotExistsT29302 to u29302; +Error 1144 (42000): Illegal GRANT/REVOKE command; please consult the manual to see which privileges can be used +grant create temporary tables (NotExistsCol) on NotExistsD29302.NotExistsT29302 to u29302; +Error 1221 (HY000): Incorrect usage of COLUMN GRANT and NON-COLUMN PRIVILEGES +drop user u29302; +drop table if exists t1; +drop user if exists user_1@localhost; +CREATE USER user_1@localhost; +CREATE TABLE T1(f1 INT); +CREATE TABLE t1(f1 INT); +Error 1050 (42S01): Table 'executor__grant.t1' already exists +GRANT SELECT ON T1 to user_1@localhost; +GRANT SELECT ON t1 to user_1@localhost; +DROP USER IF EXISTS test; +CREATE USER test; +GRANT SELECT ON `mysql`.`db` TO test; +SELECT `Grantor` FROM `mysql`.`tables_priv` WHERE User = 'test'; +Grantor +root@% +drop user if exists genius; +drop user if exists u29268; +create user genius; +select * from nonexist; +Error 1146 (42S02): Table 'executor__grant.nonexist' doesn't exist +grant Select,Insert on nonexist to 'genius'; +Error 1146 (42S02): Table 'executor__grant.nonexist' doesn't exist +create table if not exists xx (id int); +grant Select,Insert on XX to 'genius'; +grant Select,Insert on xx to 'genius'; +grant Select,Update on executor__grant.xx to 'genius'; +CREATE DATABASE d29268; +USE d29268; +CREATE USER u29268; +GRANT SELECT ON t29268 TO u29268; +Error 1146 (42S02): Table 'd29268.t29268' doesn't exist +GRANT DROP, INSERT ON t29268 TO u29268; +Error 1146 (42S02): Table 'd29268.t29268' doesn't exist +GRANT UPDATE, CREATE VIEW, SHOW VIEW ON t29268 TO u29268; +Error 1146 (42S02): Table 'd29268.t29268' doesn't exist +GRANT DELETE, REFERENCES, ALTER ON t29268 TO u29268; +Error 1146 (42S02): Table 'd29268.t29268' doesn't exist +GRANT CREATE ON t29268 TO u29268; +GRANT CREATE, SELECT ON t29268 TO u29268; +GRANT CREATE, DROP, INSERT ON t29268 TO u29268; +CREATE TABLE t29268 (c1 int); +INSERT INTO t29268 VALUES (1), (2); +SELECT c1 FROM t29268; +c1 +1 +2 +DROP TABLE t29268; +GRANT ALL ON t29268 TO u29268; +DROP USER u29268; +DROP DATABASE IF EXISTS d29268; +use executor__grant; diff --git a/tests/integrationtest/r/privilege/privileges.result b/tests/integrationtest/r/privilege/privileges.result index 878644ddaecbf..2d0a9eb08407b 100644 --- a/tests/integrationtest/r/privilege/privileges.result +++ b/tests/integrationtest/r/privilege/privileges.result @@ -30,6 +30,7 @@ Error 1142 (42000): DELETE command denied to user 'testnotexist'@'localhost' for DELETE FROM dbnotexists.t1; Error 1142 (42000): DELETE command denied to user 'testnotexist'@'localhost' for table 't1' drop table t1; +drop user if exists u1; CREATE USER u1; CREATE TABLE routine_table (a int); GRANT CREATE ROUTINE on privilege__privileges.* to u1; diff --git a/tests/integrationtest/run-tests.sh b/tests/integrationtest/run-tests.sh index 40e05b91cab38..e0b0b2b1f0037 100755 --- a/tests/integrationtest/run-tests.sh +++ b/tests/integrationtest/run-tests.sh @@ -264,7 +264,6 @@ enabled_new_collation="" if [[ $collation_opt = 0 || $collation_opt = 2 ]]; then enabled_new_collation=0 start_tidb_server - sleep 5 run_mysql_tester kill -15 $SERVER_PID while ps -p $SERVER_PID > /dev/null; do @@ -276,7 +275,6 @@ fi if [[ $collation_opt = 1 || $collation_opt = 2 ]]; then enabled_new_collation=1 start_tidb_server - sleep 5 run_mysql_tester kill -15 $SERVER_PID while ps -p $SERVER_PID > /dev/null; do diff --git a/tests/integrationtest/t/executor/adapter.test b/tests/integrationtest/t/executor/adapter.test new file mode 100644 index 0000000000000..d0a62f5c012f2 --- /dev/null +++ b/tests/integrationtest/t/executor/adapter.test @@ -0,0 +1,8 @@ +# TestQueryTime +set @a = now(); +drop table if exists t; +create table t(a int); +insert into t values (1), (1), (1), (1), (1); +select * from t t1 join t t2 on t1.a = t2.a; +select timestampdiff(second,@a, now()) < 1; + diff --git a/tests/integrationtest/t/executor/cluster_table.test b/tests/integrationtest/t/executor/cluster_table.test new file mode 100644 index 0000000000000..fb4ae84cad2cf --- /dev/null +++ b/tests/integrationtest/t/executor/cluster_table.test @@ -0,0 +1,56 @@ +# TestFunctionEncodeSQLDigest +drop table if exists test_func_encode_sql_digest; +create table test_func_encode_sql_digest(id int primary key, v int); +select tidb_encode_sql_digest("begin"); +select tidb_encode_sql_digest("select @@tidb_current_ts"); +select tidb_encode_sql_digest("select id, v from test_func_decode_sql_digests where id = 1 for update"); +select tidb_encode_sql_digest(null); +-- error 1582 +select tidb_encode_sql_digest(); +select (select tidb_encode_sql_digest('select 1')) = tidb_encode_sql_digest('select 1;'); +select (select tidb_encode_sql_digest('select 1')) = tidb_encode_sql_digest('select 1 ;'); +select (select tidb_encode_sql_digest('select 1')) = tidb_encode_sql_digest('select 2 ;'); + +# TestFunctionDecodeSQLDigestsPrivilege +drop user if exists 'testuser'@'localhost'; +create user 'testuser'@'localhost'; + +connect (conn1, localhost, testuser,,); +connection conn1; +-- error 1227 +select tidb_decode_sql_digests('["aa"]'); +connection default; + +grant process on *.* to 'testuser'@'localhost'; +connection conn1; +select tidb_decode_sql_digests('["aa"]'); +connection default; +disconnect conn1; +drop user 'testuser'@'localhost'; + +# TestFunctionDecodeSQLDigests +set global tidb_enable_stmt_summary = 1; +select @@global.tidb_enable_stmt_summary; +drop table if exists test_func_decode_sql_digests; +create table test_func_decode_sql_digests(id int primary key, v int); +begin; +--disable_result_log +select @@tidb_current_ts; +--enable_result_log +select id, v from test_func_decode_sql_digests where id = 1 for update; +rollback; +select tidb_decode_sql_digests('["e6f07d43b5c21db0fbb9a31feac2dc599787763393dd5acbfad80e247eb02ad5","58f3717da2d79c14773a1e3094aaddeff2b11747d3aef95741151af9acba9d44","7e9f826ed22a09940940a42d1aca47a75b3adc3c3fde252f4b912ac886194eb9"]', 0); +select tidb_decode_sql_digests('["e6f07d43b5c21db0fbb9a31feac2dc599787763393dd5acbfad80e247eb02ad5","58f3717da2d79c14773a1e3094aaddeff2b11747d3aef95741151af9acba9d44","7e9f826ed22a09940940a42d1aca47a75b3adc3c3fde252f4b912ac886194eb9"]', 24); +select tidb_decode_sql_digests('[]'); +select tidb_decode_sql_digests(null); +select tidb_decode_sql_digests('["e6f07d43b5c21db0fbb9a31feac2dc599787763393dd5acbfad80e247eb02ad5",1,null,"58f3717da2d79c14773a1e3094aaddeff2b11747d3aef95741151af9acba9d44",{"a":1},[2],"7e9f826ed22a09940940a42d1aca47a75b3adc3c3fde252f4b912ac886194eb9","","abcde"]'); +select tidb_decode_sql_digests('{"a":1}'); +show warnings; +select tidb_decode_sql_digests('aabbccdd'); +show warnings; +-- error 1582 +select tidb_decode_sql_digests('a', 1, 2); +-- error 1582 +select tidb_decode_sql_digests(); +set global tidb_enable_stmt_summary = default; + diff --git a/tests/integrationtest/t/executor/compact_table.test b/tests/integrationtest/t/executor/compact_table.test new file mode 100644 index 0000000000000..19d3c6402904a --- /dev/null +++ b/tests/integrationtest/t/executor/compact_table.test @@ -0,0 +1,52 @@ +# TestCompactUnknownTable +drop table if exists bar, foo; +connect (conn1, localhost, root,,); +connection conn1; +-- error 1046 +alter table test compact tiflash replica; +-- error 1146 +alter table executor__compact_table.foo compact tiflash replica; +use executor__compact_table; +-- error 1146 +alter table bar compact; +connection default; +disconnect conn1; + +# TestCompactTableNoTiFlashReplica +drop table if exists t; +create table t(a int); +alter table t compact tiflash replica; +show warnings; +alter table executor__compact_table.t compact; +show warnings; +connect (conn1, localhost, root,, executor__compact_table); +connection conn1; +alter table executor__compact_table.t compact; +show warnings; +connection default; +disconnect conn1; + +# TestCompactTableNoPartition +drop table if exists t; +create table t(a int); +-- error 1105 +alter table t compact partition p1,p2 tiflash replica; + +# TestCompactTablePartitionInvalid +drop table if exists t; +CREATE TABLE t ( + id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + fname VARCHAR(25) NOT NULL, + lname VARCHAR(25) NOT NULL, + store_id INT NOT NULL, + department_id INT NOT NULL +) +PARTITION BY RANGE(id) ( + PARTITION p0 VALUES LESS THAN (5), + PARTITION p1 VALUES LESS THAN (10), + PARTITION p2 VALUES LESS THAN (15), + PARTITION p3 VALUES LESS THAN MAXVALUE +); +-- error 1735 +alter table t compact partition p1,p2,p4 tiflash replica; + diff --git a/tests/integrationtest/t/executor/cte.test b/tests/integrationtest/t/executor/cte.test new file mode 100644 index 0000000000000..25bdab72cdee4 --- /dev/null +++ b/tests/integrationtest/t/executor/cte.test @@ -0,0 +1,147 @@ +# TestBasicCTE +with recursive cte1 as (select 1 c1 union all select c1 + 1 c1 from cte1 where c1 < 5) select * from cte1; +with recursive cte1 as (select 1 c1 union all select 2 c1 union all select c1 + 1 c1 from cte1 where c1 < 10) select * from cte1 order by c1; +with recursive cte1 as (select 1 c1 union all select 2 c1 union all select c1 + 1 c1 from cte1 where c1 < 3 union all select c1 + 2 c1 from cte1 where c1 < 5) select * from cte1 order by c1; +drop table if exists t1; +create table t1(a int); +insert into t1 values(1); +insert into t1 values(2); +SELECT * FROM t1 dt WHERE EXISTS(WITH RECURSIVE qn AS (SELECT a*0 AS b UNION ALL SELECT b+1 FROM qn WHERE b=0) SELECT * FROM qn WHERE b=a); +SELECT * FROM t1 dt WHERE EXISTS( WITH RECURSIVE qn AS (SELECT a*0 AS b UNION ALL SELECT b+1 FROM qn WHERE b=0 or b = 1) SELECT * FROM qn WHERE b=a ); +with recursive c(p) as (select 1), cte(a, b) as (select 1, 1 union select a+1, 1 from cte, c where a < 5) select * from cte order by 1, 2; + +# TestUnionDistinct +with recursive cte1(c1) as (select 1 union select 1 union select 1 union all select c1 + 1 from cte1 where c1 < 3) select * from cte1 order by c1; +with recursive cte1(c1) as (select 1 union all select 1 union select 1 union all select c1 + 1 from cte1 where c1 < 3) select * from cte1 order by c1; +drop table if exists t1; +create table t1(c1 int, c2 int); +insert into t1 values(1, 1), (1, 2), (2, 2); +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 c1 from t1) select * from cte1 order by c1; +drop table if exists t1; +create table t1(c1 int); +insert into t1 values(1), (1), (1), (2), (2), (2); +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 c1 from cte1 where c1 < 4) select * from cte1 order by c1; + +# TestCTEMaxRecursionDepth +set @@cte_max_recursion_depth = -1; +-- error 3636 +with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 100) select * from cte1; +with recursive cte1(c1) as (select 1 union select 2) select * from cte1 order by c1; +with cte1(c1) as (select 1 union select 2) select * from cte1 order by c1; +set @@cte_max_recursion_depth = 0; +-- error 3636 +with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 0) select * from cte1; +-- error 3636 +with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 1) select * from cte1; +with recursive cte1(c1) as (select 1 union select 2) select * from cte1 order by c1; +with cte1(c1) as (select 1 union select 2) select * from cte1 order by c1; +set @@cte_max_recursion_depth = 1; +with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 0) select * from cte1; +with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 1) select * from cte1; +-- error 3636 +with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 2) select * from cte1; +with recursive cte1(c1) as (select 1 union select 2) select * from cte1 order by c1; +with cte1(c1) as (select 1 union select 2) select * from cte1 order by c1; +set @@cte_max_recursion_depth = default; + +# TestCTEWithLimit +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 5 offset 0) select * from cte1; +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 5 offset 1) select * from cte1; +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 5 offset 10) select * from cte1; +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 5 offset 995) select * from cte1; +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 5 offset 6) select * from cte1; +set cte_max_recursion_depth=2; +with recursive cte1(c1) as (select 0 union select c1 + 1 from cte1 limit 1 offset 2) select * from cte1; +-- error 3636 +with recursive cte1(c1) as (select 0 union select c1 + 1 from cte1 limit 1 offset 3) select * from cte1; +set cte_max_recursion_depth=1000; +with recursive cte1(c1) as (select 0 union select c1 + 1 from cte1 limit 5 offset 996) select * from cte1; +-- error 3636 +with recursive cte1(c1) as (select 0 union select c1 + 1 from cte1 limit 5 offset 997) select * from cte1; +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 0 offset 1) select * from cte1; +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 0 offset 10) select * from cte1; +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 2 offset 1) select * from cte1 dt1 join cte1 dt2 order by dt1.c1, dt2.c1; +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 2 offset 1) select * from cte1 dt1 join cte1 dt2 on dt1.c1 = dt2.c1 order by dt1.c1, dt1.c1; +# Different with mysql, maybe it's mysql bug?(https://bugs.mysql.com/bug.php?id=103890&thanks=4) +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 2 offset 1) select c1 from cte1 where c1 in (select 2); +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 2 offset 1) select c1 from cte1 dt where c1 in (select c1 from cte1 where 1 = dt.c1 - 1); +with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 2 offset 1) select c1 from cte1 where cte1.c1 = (select dt1.c1 from cte1 dt1 where dt1.c1 = cte1.c1); +drop table if exists t1; +create table t1(c1 int); +insert into t1 values(1), (2), (3); +-- error 1221 +with recursive cte1(c1) as (select c1 from t1 limit 1 offset 1 union select c1 + 1 from cte1 limit 0 offset 1) select * from cte1; +with recursive cte1(c1) as (select 1 union select 2 order by 1 limit 1 offset 1) select * from cte1; +with recursive cte1(c1) as (select 1 union select 2 order by 1 limit 0 offset 1) select * from cte1; +with recursive cte1(c1) as (select 1 union select 2 order by 1 limit 2 offset 0) select * from cte1; +drop table if exists t1; +create table t1(c1 int); +insert into t1 values(0), (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12), (13), (14), (15), (16), (17), (18), (19), (20), (21), (22), (23), (24), (25), (26), (27), (28), (29), (30), (31), (32), (33), (34), (35), (36), (37), (38), (39), (40), (41), (42), (43), (44), (45), (46), (47), (48), (49), (50), (51), (52), (53), (54), (55), (56), (57), (58), (59), (60), (61), (62), (63), (64), (65), (66), (67), (68), (69), (70), (71), (72), (73), (74), (75), (76), (77), (78), (79), (80), (81), (82), (83), (84), (85), (86), (87), (88), (89), (90), (91), (92), (93), (94), (95), (96), (97), (98), (99), (100), (101), (102), (103), (104), (105), (106), (107), (108), (109), (110), (111), (112), (113), (114), (115), (116), (117), (118), (119), (120), (121), (122), (123), (124), (125), (126), (127), (128), (129), (130), (131), (132), (133), (134), (135), (136), (137), (138), (139), (140), (141), (142), (143), (144), (145), (146), (147), (148), (149), (150), (151), (152), (153), (154), (155), (156), (157), (158), (159), (160), (161), (162), (163), (164), (165), (166), (167), (168), (169), (170), (171), (172), (173), (174), (175), (176), (177), (178), (179), (180), (181), (182), (183), (184), (185), (186), (187), (188), (189), (190), (191), (192), (193), (194), (195), (196), (197), (198), (199), (200), (201), (202), (203), (204), (205), (206), (207), (208), (209), (210), (211), (212), (213), (214), (215), (216), (217), (218), (219), (220), (221), (222), (223), (224), (225), (226), (227), (228), (229), (230), (231), (232), (233), (234), (235), (236), (237), (238), (239), (240), (241), (242), (243), (244), (245), (246), (247), (248), (249), (250), (251), (252), (253), (254), (255), (256), (257), (258), (259), (260), (261), (262), (263), (264), (265), (266), (267), (268), (269), (270), (271), (272), (273), (274), (275), (276), (277), (278), (279), (280), (281), (282), (283), (284), (285), (286), (287), (288), (289), (290), (291), (292), (293), (294), (295), (296), (297), (298), (299); +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 c1 from cte1 limit 1) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 c1 from cte1 limit 1 offset 100) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 c1 from cte1 limit 5 offset 100) select * from cte1; +with cte1 as (select c1 from t1 limit 2 offset 1) select * from cte1; +with cte1 as (select c1 from t1 limit 2 offset 1) select * from cte1 dt1 join cte1 dt2 on dt1.c1 = dt2.c1; +with recursive cte1(c1) as (select c1 from t1 union select 2 limit 0 offset 1) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union select 2 limit 0 offset 1) select * from cte1 dt1 join cte1 dt2 on dt1.c1 = dt2.c1; +# with recursive cte1(c1) as (select c1 from t1 union select 2 limit 5 offset 100) select * from cte1" +with recursive cte1(c1) as (select c1 from t1 limit 3 offset 100) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 limit 3 offset 100) select * from cte1 dt1 join cte1 dt2 on dt1.c1 = dt2.c1; +set cte_max_recursion_depth = 0; +drop table if exists t1; +create table t1(c1 int); +insert into t1 values(0); +with recursive cte1 as (select 1/c1 c1 from t1 union select c1 + 1 c1 from cte1 where c1 < 2 limit 0) select * from cte1; +-- error 3636 +with recursive cte1 as (select 1/c1 c1 from t1 union select c1 + 1 c1 from cte1 where c1 < 2 limit 1) select * from cte1; +set cte_max_recursion_depth = 1000; +drop table if exists t1; +create table t1(c1 int); +insert into t1 values(1), (2), (3); +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 0 offset 2) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 1 offset 2) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 2 offset 2) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 3 offset 2) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 4 offset 2) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 0 offset 3) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 1 offset 3) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 2 offset 3) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 3 offset 3) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 4 offset 3) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 0 offset 4) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 1 offset 4) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 2 offset 4) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 3 offset 4) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 from cte1 limit 4 offset 4) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 0 offset 2) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 1 offset 2) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 2 offset 2) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 3 offset 2) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 4 offset 2) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 0 offset 3) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 1 offset 3) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 2 offset 3) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 3 offset 3) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 4 offset 3) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 0 offset 4) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 1 offset 4) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 2 offset 4) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 3 offset 4) select * from cte1; +with recursive cte1(c1) as (select c1 from t1 union all select c1 + 1 from cte1 limit 4 offset 4) select * from cte1; +set cte_max_recursion_depth = default; + +# TestCTEsInView +# https://github.com/pingcap/tidb/issues/33965 +drop table if exists executor__cte.t; +drop view if exists executor__cte.v; +create database if not exists executor__cte1; +create table executor__cte.t (a int); +create table executor__cte1.t (a int); +insert into executor__cte.t values (1); +insert into executor__cte1.t values (2); +create definer='root'@'localhost' view executor__cte.v as with tt as (select * from t) select * from tt; +select * from executor__cte.v; +use executor__cte1; +select * from executor__cte.v; +use executor__cte; +drop database executor__cte1; diff --git a/tests/integrationtest/t/executor/explain.test b/tests/integrationtest/t/executor/explain.test new file mode 100644 index 0000000000000..5d72e5d223a22 --- /dev/null +++ b/tests/integrationtest/t/executor/explain.test @@ -0,0 +1,164 @@ +# TestExplainCartesianJoin +drop table if exists t; +create table t (v int); +explain format = 'brief' select * from t t1, t t2; +explain format = 'brief' select * from t t1 where exists (select 1 from t t2 where t2.v > t1.v); +explain format = 'brief' select * from t t1 where exists (select 1 from t t2 where t2.v in (t1.v+1, t1.v+2)); +explain format = 'brief' select * from t t1, t t2 where t1.v = t2.v; + +# TestExplainWrite +drop table if exists t; +create table t (a int); +--disable_result_log +explain analyze insert into t select 1; +--enable_result_log +select * from t; +--disable_result_log +explain analyze update t set a=2 where a=1; +--enable_result_log +select * from t; +--disable_result_log +explain format = 'brief' insert into t select 1; +--enable_result_log +select * from t; +--disable_result_log +explain analyze insert into t select 1; +explain analyze replace into t values (3); +--enable_result_log +select * from t order by a; + +# TestExplainStatementsSummary +desc format='brief' select * from information_schema.statements_summary; +desc format='brief' select * from information_schema.statements_summary where digest is null; +desc format='brief' select * from information_schema.statements_summary where digest = 'abcdefg'; +desc format='brief' select * from information_schema.statements_summary where digest in ('a','b','c'); + +# TestFix29401 +drop table if exists tt123; +CREATE TABLE tt123 ( + id int(11) NOT NULL, + a bigint(20) DEFAULT NULL, + b char(20) DEFAULT NULL, + c datetime DEFAULT NULL, + d double DEFAULT NULL, + e json DEFAULT NULL, + f decimal(40,6) DEFAULT NULL, + PRIMARY KEY (id) /*T![clustered_index] CLUSTERED */, + KEY a (a), + KEY b (b), + KEY c (c), + KEY d (d), + KEY f (f) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + explain format='brief' select /*+ inl_hash_join(t1) */ * from tt123 t1 join tt123 t2 on t1.b=t2.e; + +# TestIssue35105 +drop table if exists t; +create table t (a int primary key); +insert into t values (2); +set @@tidb_constraint_check_in_place=1; +-- error 1062 +explain analyze insert into t values (1), (2), (3); +select * from t; +set @@tidb_constraint_check_in_place=DEFAULT; + +# TestExplainFormatPlanCache +drop table if exists t; +create table t(a int); +set @@session.tidb_enable_non_prepared_plan_cache = 1; +select * from t limit 1; +select * from t limit 1; +explain format = 'plan_cache' select * from (select * from t) t1 limit 1; +show warnings; +explain format = 'plan_cache' select * from (select * from t) t1 limit 1; +select @@last_plan_from_cache; +--disable_result_log +explain analyze format = 'plan_cache' select * from (select * from t) t1 limit 1; +--enable_result_log +show warnings; +--disable_result_log +explain analyze format = 'plan_cache' select * from (select * from t) t1 limit 1; +--enable_result_log +select @@last_plan_from_cache; +explain format = 'plan_cache' select * from t; +show warnings; +explain format = 'plan_cache' select * from t; +select @@last_plan_from_cache; +--disable_result_log +explain analyze format = 'plan_cache' select * from t; +--enable_result_log +show warnings; +--disable_result_log +explain analyze format = 'plan_cache' select * from t; +--enable_result_log +select @@last_plan_from_cache; +explain select * from t; +select @@last_plan_from_cache; +explain format = 'brief' select * from t; +select @@last_plan_from_cache; +explain format = 'dot' select * from t; +select @@last_plan_from_cache; +explain format = 'hint' select * from t; +select @@last_plan_from_cache; +explain format = 'row' select * from t; +select @@last_plan_from_cache; +explain format = 'verbose' select * from t; +select @@last_plan_from_cache; +explain format = 'traditional' select * from t; +select @@last_plan_from_cache; +explain format = 'binary' select * from t; +select @@last_plan_from_cache; +explain format = 'tidb_json' select * from t; +select @@last_plan_from_cache; +explain format = 'cost_trace' select * from t; +select @@last_plan_from_cache; +set @@session.tidb_enable_non_prepared_plan_cache = DEFAULT; + +# TestExplainPrivileges +drop table if exists t; +drop view if exists v; +drop user if exists 'explain'@'%'; +create table t (id int); +create view v as select * from t; +create user 'explain'@'%'; +grant select on executor__explain.v to 'explain'@'%'; + +connect (conn1, localhost, explain,,); +show databases; +use executor__explain; +select * from v; +-- error 1345 +explain format = 'brief' select * from v; + +connection default; +grant show view on executor__explain.v to 'explain'@'%'; +connection conn1; +explain format = 'brief' select * from v; + +connection default; +revoke select on executor__explain.v from 'explain'@'%'; +connection conn1; +-- error 1142 +explain format = 'brief' select * from v; + +connection default; +create table t1 (i int); +create table t2 (j int); +create table t3 (k int, secret int); +create view v1 as select * from t1; +create view v2 as select * from v1, t2; +create view v3 as select k from t3; +grant select, show view on executor__explain.v2 to 'explain'@'%'; +grant show view on executor__explain.v1 to 'explain'@'%'; +grant select, show view on executor__explain.t3 to 'explain'@'%'; +grant select, show view on executor__explain.v3 to 'explain'@'%'; + +connection conn1; +-- error 1142 +explain select * from v1; +-- error 1345 +explain select * from v2; +explain select * from t3; +explain select * from v3; +disconnect conn1; + diff --git a/tests/integrationtest/t/executor/explainfor.test b/tests/integrationtest/t/executor/explainfor.test new file mode 100644 index 0000000000000..454976647e409 --- /dev/null +++ b/tests/integrationtest/t/executor/explainfor.test @@ -0,0 +1,432 @@ +# TestExplainMemTablePredicate +desc format='brief' select * from METRICS_SCHEMA.tidb_query_duration where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13' ; +desc format='brief' select * from METRICS_SCHEMA.up where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13' ; +desc format='brief' select * from information_schema.cluster_log where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13'; +desc format='brief' select * from information_schema.cluster_log where level in ('warn','error') and time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13'; +desc format='brief' select * from information_schema.cluster_log where type in ('high_cpu_1','high_memory_1') and time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13'; +desc format='brief' select * from information_schema.slow_query; +desc format='brief' select * from information_schema.slow_query where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13'; +set @@time_zone = '+00:00'; +desc format='brief' select * from information_schema.slow_query where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13'; +set @@time_zone = default; + +# TestExplainClusterTable +desc format='brief' select * from information_schema.cluster_config where type in ('tikv', 'tidb'); +desc format='brief' select * from information_schema.cluster_config where instance='192.168.1.7:2379'; +desc format='brief' select * from information_schema.cluster_config where type='tidb' and instance='192.168.1.7:2379'; + +# TestInspectionResultTable +desc format='brief' select * from information_schema.inspection_result where rule = 'ddl' and rule = 'config'; +desc format='brief' select * from information_schema.inspection_result where rule in ('ddl', 'config'); +desc format='brief' select * from information_schema.inspection_result where item in ('ddl.lease', 'raftstore.threadpool'); +desc format='brief' select * from information_schema.inspection_result where item in ('ddl.lease', 'raftstore.threadpool') and rule in ('ddl', 'config'); + +# TestInspectionRuleTable +desc format='brief' select * from information_schema.inspection_rules where type='inspection'; +desc format='brief' select * from information_schema.inspection_rules where type='inspection' or type='summary'; +desc format='brief' select * from information_schema.inspection_rules where type='inspection' and type='summary'; + +# TestSavedPlanPanicPlanCache +set tidb_enable_prepared_plan_cache=1; +drop table if exists t; +create table t(a int, b int, c int generated always as (a+b) stored); +insert into t(a,b) values(1,1); +begin; +update t set b = 2 where a = 1; +prepare stmt from 'select b from t where a > ?'; +set @p = 0; +execute stmt using @p; +set @p = 1; +execute stmt using @p; +-- error 3105 +insert into t(a,b,c) values(3,3,3); +rollback; +set tidb_enable_prepared_plan_cache=default; + +# TestExplainTableStorage +desc format='brief' select * from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'information_schema'; +desc format='brief' select * from information_schema.TABLE_STORAGE_STATS where TABLE_NAME = 'schemata'; +desc format='brief' select * from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'information_schema' and TABLE_NAME = 'schemata'; + +# TestInspectionSummaryTable +desc format='brief' select * from information_schema.inspection_summary where rule='ddl'; +desc format='brief' select * from information_schema.inspection_summary where 'ddl'=rule or rule='config'; +desc format='brief' select * from information_schema.inspection_summary where 'ddl'=rule or rule='config' or rule='slow_query'; +desc format='brief' select * from information_schema.inspection_summary where (rule='config' or rule='slow_query') and (metrics_name='metric_name3' or metrics_name='metric_name1'); +desc format='brief' select * from information_schema.inspection_summary where rule in ('ddl', 'slow_query'); +desc format='brief' select * from information_schema.inspection_summary where rule in ('ddl', 'slow_query') and metrics_name='metric_name1'; +desc format='brief' select * from information_schema.inspection_summary where rule in ('ddl', 'slow_query') and metrics_name in ('metric_name1', 'metric_name2'); +desc format='brief' select * from information_schema.inspection_summary where rule='ddl' and metrics_name in ('metric_name1', 'metric_name2'); +desc format='brief' select * from information_schema.inspection_summary where rule='ddl' and metrics_name='metric_NAME3'; +desc format='brief' select * from information_schema.inspection_summary where rule in ('ddl', 'config') and rule in ('slow_query', 'config'); +desc format='brief' select * from information_schema.inspection_summary where metrics_name in ('metric_name1', 'metric_name4') and metrics_name in ('metric_name5', 'metric_name4') and rule in ('ddl', 'config') and rule in ('slow_query', 'config') and quantile in (0.80, 0.90); +desc format='brief' select * from information_schema.inspection_summary where metrics_name in ('metric_name1', 'metric_name4') and metrics_name in ('metric_name5', 'metric_name4') and metrics_name in ('metric_name5', 'metric_name1') and metrics_name in ('metric_name1', 'metric_name3'); + +# TestExplainTiFlashSystemTables +desc format='brief' select * from information_schema.TIFLASH_TABLES where TIFLASH_INSTANCE = '192.168.1.7:3930'; +desc format='brief' select * from information_schema.TIFLASH_SEGMENTS where TIFLASH_INSTANCE = '192.168.1.7:3930'; +desc format='brief' select * from information_schema.TIFLASH_TABLES where TIDB_DATABASE = 'test'; +desc format='brief' select * from information_schema.TIFLASH_SEGMENTS where TIDB_DATABASE = 'test'; +desc format='brief' select * from information_schema.TIFLASH_TABLES where TIDB_TABLE = 't'; +desc format='brief' select * from information_schema.TIFLASH_SEGMENTS where TIDB_TABLE = 't'; +desc format='brief' select * from information_schema.TIFLASH_TABLES where TIFLASH_INSTANCE = '192.168.1.7:3930' and TIDB_DATABASE = 'test' and TIDB_TABLE = 't'; +desc format='brief' select * from information_schema.TIFLASH_SEGMENTS where TIFLASH_INSTANCE = '192.168.1.7:3930' and TIDB_DATABASE = 'test' and TIDB_TABLE = 't'; + +# TestSetOperations4PlanCache +set tidb_enable_prepared_plan_cache=1; +set @@tidb_enable_collect_execution_info=0; +drop table if exists t1, t2; +CREATE TABLE `t1` (a int); +CREATE TABLE `t2` (a int); +insert into t1 values(1), (2); +insert into t2 values(1), (3); +prepare stmt from 'select * from t1 where a > ? union select * from t2 where a > ?;'; +set @a=0, @b=1; +--sorted_result +execute stmt using @a, @b; +--sorted_result +execute stmt using @b, @a; +select @@last_plan_from_cache; +--sorted_result +execute stmt using @b, @b; +select @@last_plan_from_cache; +--sorted_result +execute stmt using @a, @a; +select @@last_plan_from_cache; +prepare stmt from 'select * from t1 where a > ? union all select * from t2 where a > ?;'; +set @a=0, @b=1; +--sorted_result +execute stmt using @a, @b; +--sorted_result +execute stmt using @b, @a; +select @@last_plan_from_cache; +--sorted_result +execute stmt using @b, @b; +select @@last_plan_from_cache; +--sorted_result +execute stmt using @a, @a; +select @@last_plan_from_cache; +prepare stmt from 'select * from t1 where a > ? except select * from t2 where a > ?;'; +set @a=0, @b=1; +--sorted_result +execute stmt using @a, @a; +--sorted_result +execute stmt using @b, @a; +select @@last_plan_from_cache; +--sorted_result +execute stmt using @b, @b; +select @@last_plan_from_cache; +--sorted_result +execute stmt using @a, @b; +select @@last_plan_from_cache; +prepare stmt from 'select * from t1 where a > ? union select * from t2 where a > ?;'; +set @a=0, @b=1; +--sorted_result +execute stmt using @a, @a; +--sorted_result +execute stmt using @b, @a; +select @@last_plan_from_cache; +--sorted_result +execute stmt using @b, @b; +select @@last_plan_from_cache; +--sorted_result +execute stmt using @a, @b; +select @@last_plan_from_cache; +prepare stmt from 'select * from t1 union all select * from t1 intersect select * from t2;'; +--sorted_result +execute stmt; +prepare stmt from '(select * from t1 union all select * from t1) intersect select * from t2;'; +--sorted_result +execute stmt; +prepare stmt from '(select * from t1 union all select * from t1 intersect select * from t2) order by a limit 2;'; +--sorted_result +execute stmt; +set tidb_enable_prepared_plan_cache=default; +set @@tidb_enable_collect_execution_info=default; + +# TestHint4PlanCache +set tidb_enable_prepared_plan_cache=1; +set @@tidb_enable_collect_execution_info=0; +drop table if exists t; +create table t(a int, index idx_a(a)); +prepare stmt from 'select * from t;'; +execute stmt; +execute stmt; +select @@last_plan_from_cache; +prepare stmt from 'select /*+ IGNORE_PLAN_CACHE() */ * from t;'; +execute stmt; +execute stmt; +select @@last_plan_from_cache; +set tidb_enable_prepared_plan_cache=default; +set @@tidb_enable_collect_execution_info=default; + +# TestInvisibleIndex4PlanCache +set tidb_enable_prepared_plan_cache=1; +set @@tidb_enable_collect_execution_info=0; +drop table if exists t; +CREATE TABLE t(c1 INT, index idx_c(c1)); +prepare stmt from 'select * from t use index(idx_c) where c1 > 1;'; +execute stmt; +execute stmt; +select @@last_plan_from_cache; +ALTER TABLE t ALTER INDEX idx_c INVISIBLE; +-- error 1176 +select * from t use index(idx_c) where c1 > 1; +-- error 1176 +execute stmt; +set tidb_enable_prepared_plan_cache=default; +set @@tidb_enable_collect_execution_info=default; + +# TestCTE4PlanCache +set tidb_enable_prepared_plan_cache=1; +set @@tidb_enable_collect_execution_info=0; +prepare stmt from 'with recursive cte1 as (select ? c1 union all select c1 + 1 c1 from cte1 where c1 < ?) select * from cte1;'; +set @a=5, @b=4, @c=2, @d=1; +--sorted_result +execute stmt using @d, @a; +--sorted_result +execute stmt using @d, @b; +select @@last_plan_from_cache; +--sorted_result +execute stmt using @c, @b; +select @@last_plan_from_cache; +prepare stmt from 'with recursive cte1 as (select 1 c1 union all select 2 c1 union all select c1 + 1 c1 from cte1 where c1 < ?) select * from cte1 order by c1;'; +set @a=10, @b=2; +execute stmt using @a; +execute stmt using @b; +select @@last_plan_from_cache; +prepare stmt from 'with recursive cte1 as (select 1 c1 union all select 2 c1 union all select c1 + 1 c1 from cte1 where c1 < ? union all select c1 + ? c1 from cte1 where c1 < ?) select * from cte1 order by c1;'; +set @a=1, @b=2, @c=3, @d=4, @e=5; +--sorted_result +execute stmt using @c, @b, @e; +--sorted_result +execute stmt using @b, @a, @d; +select @@last_plan_from_cache; +drop table if exists t1; +create table t1(a int); +insert into t1 values(1); +insert into t1 values(2); +prepare stmt from 'SELECT * FROM t1 dt WHERE EXISTS(WITH RECURSIVE qn AS (SELECT a*? AS b UNION ALL SELECT b+? FROM qn WHERE b=?) SELECT * FROM qn WHERE b=a);'; +show warnings; +set @a=1, @b=2, @c=3, @d=4, @e=5, @f=0; +--sorted_result +execute stmt using @f, @a, @f; +--sorted_result +execute stmt using @a, @b, @a; +select @@last_plan_from_cache; +--sorted_result +execute stmt using @a, @b, @a; +prepare stmt from 'with recursive c(p) as (select ?), cte(a, b) as (select 1, 1 union select a+?, 1 from cte, c where a < ?) select * from cte order by 1, 2;'; +show warnings; +--sorted_result +execute stmt using @a, @a, @e; +--sorted_result +execute stmt using @b, @b, @c; +select @@last_plan_from_cache; +set tidb_enable_prepared_plan_cache=default; +set @@tidb_enable_collect_execution_info=default; + +# TestValidity4PlanCache +set tidb_enable_prepared_plan_cache=1; +set @@tidb_enable_collect_execution_info=0; +drop table if exists t; +create table t(a int); +prepare stmt from 'select * from t;'; +execute stmt; +execute stmt; +select @@last_plan_from_cache; +drop database if exists plan_cache; +create database plan_cache; +use plan_cache; +create table t(a int); +insert into t values(1); +execute stmt; +select @@last_plan_from_cache; +execute stmt; +select @@last_plan_from_cache; +prepare stmt from 'select * from t;'; +execute stmt; +execute stmt; +select @@last_plan_from_cache; +execute stmt; +select @@last_plan_from_cache; +set tidb_enable_prepared_plan_cache=default; +set @@tidb_enable_collect_execution_info=default; + +# TestListPartition4PlanCache +set tidb_enable_prepared_plan_cache=1; +set @@tidb_enable_collect_execution_info=0; +set @@session.tidb_enable_list_partition=1; +drop table if exists t; +create table t(a int, b int) PARTITION BY LIST (a) ( PARTITION p0 VALUES IN (1, 2, 3), PARTITION p1 VALUES IN (4, 5, 6)); +set @@tidb_partition_prune_mode='static'; +prepare stmt from 'select * from t;'; +execute stmt; +execute stmt; +select @@last_plan_from_cache; +set tidb_enable_prepared_plan_cache=default; +set @@tidb_enable_collect_execution_info=default; +set @@session.tidb_enable_list_partition=default; +set @@tidb_partition_prune_mode=default; + +# TestIssue28792 +drop table if exists t12, t97; +CREATE TABLE t12(a INT, b INT); +CREATE TABLE t97(a INT, b INT UNIQUE NOT NULL); +EXPLAIN SELECT t12.a, t12.b FROM t12 LEFT JOIN t97 on t12.b = t97.b; +EXPLAIN SELECT t12.a, t12.b FROM t12 LEFT JOIN t97 use index () on t12.b = t97.b; + +# TestMoreSessions4PlanCache +set tidb_enable_prepared_plan_cache=1; +set @@tidb_enable_collect_execution_info=0; +drop table if exists t; +create table t(a int); +prepare stmt from 'select * from t;'; +execute stmt; +execute stmt; +select @@last_plan_from_cache; + +connect (conn1, localhost, root,, executor__explainfor); +set tidb_enable_prepared_plan_cache=1; +-- error 8111 +execute stmt; +prepare stmt from 'select * from t;'; +execute stmt; +execute stmt; +select @@last_plan_from_cache; +connection default; + +execute stmt; +select @@last_plan_from_cache; +set tidb_enable_prepared_plan_cache=default; +set @@tidb_enable_collect_execution_info=default; + +# TestSelectView4PlanCache +set tidb_enable_prepared_plan_cache=1; +set @@tidb_enable_collect_execution_info=0; +drop view if exists view1, view2, view3, view4; +drop table if exists view_t; +create table view_t (a int,b int); +insert into view_t values(1,2); +create definer='root'@'localhost' view view1 as select * from view_t; +create definer='root'@'localhost' view view2(c,d) as select * from view_t; +create definer='root'@'localhost' view view3(c,d) as select a,b from view_t; +create definer='root'@'localhost' view view4 as select * from (select * from (select * from view_t) tb1) tb; +prepare stmt1 from 'select * from view1;'; +execute stmt1; +execute stmt1; +select @@last_plan_from_cache; +prepare stmt2 from 'select * from view2;'; +execute stmt2; +execute stmt2; +select @@last_plan_from_cache; +prepare stmt3 from 'select * from view3;'; +execute stmt3; +execute stmt3; +select @@last_plan_from_cache; +prepare stmt4 from 'select * from view4;'; +execute stmt4; +execute stmt4; +select @@last_plan_from_cache; +drop table view_t; +create table view_t(c int,d int); +-- error 1356 +execute stmt1; +-- error 1356 +execute stmt2; +-- error 1356 +execute stmt3; +drop table view_t; +create table view_t(a int,b int,c int); +insert into view_t values(1,2,3); +execute stmt1; +select @@last_plan_from_cache; +execute stmt1; +select @@last_plan_from_cache; +execute stmt2; +select @@last_plan_from_cache; +execute stmt2; +select @@last_plan_from_cache; +execute stmt3; +select @@last_plan_from_cache; +execute stmt3; +select @@last_plan_from_cache; +execute stmt4; +select @@last_plan_from_cache; +execute stmt4; +select @@last_plan_from_cache; +alter table view_t drop column a; +alter table view_t add column a int after b; +update view_t set a=1; +execute stmt1; +select @@last_plan_from_cache; +execute stmt1; +select @@last_plan_from_cache; +execute stmt2; +select @@last_plan_from_cache; +execute stmt2; +select @@last_plan_from_cache; +execute stmt3; +select @@last_plan_from_cache; +execute stmt3; +select @@last_plan_from_cache; +execute stmt4; +select @@last_plan_from_cache; +execute stmt4; +select @@last_plan_from_cache; +drop table view_t; +drop view view1,view2,view3,view4; +set @@tidb_enable_window_function = 1; +drop table if exists t; +create table t(a int, b int); +insert into t values (1,1),(1,2),(2,1),(2,2); +create definer='root'@'localhost' view v as select a, first_value(a) over(rows between 1 preceding and 1 following), last_value(a) over(rows between 1 preceding and 1 following) from t; +prepare stmt from 'select * from v;'; +execute stmt; +execute stmt; +select @@last_plan_from_cache; +drop view v; +set @@tidb_enable_window_function = default; +set tidb_enable_prepared_plan_cache=default; +set @@tidb_enable_collect_execution_info=default; + +# TestIgnorePlanCacheWithPrepare +drop table if exists t; +create table t(a int, index idx_a(a)); +drop table if exists r; +create table r(a int); +prepare stmt from 'select * from t;'; +create binding for select * from t using select /*+ use_index(t, idx_a) */ * from t; +execute stmt; +execute stmt; +select @@last_plan_from_cache; +execute stmt; +select @@last_plan_from_binding; +create binding for select * from t using select /*+ ignore_plan_cache() */ * from t; +execute stmt; +select @@last_plan_from_cache; +execute stmt; +select @@last_plan_from_binding; +create binding for select * from t using select /*+ use_index(t, idx_a) */ * from t; +execute stmt; +select @@last_plan_from_cache; +execute stmt; +select @@last_plan_from_binding; +prepare stmt_join from 'select * from t, r where r.a = t.a;'; +create binding for select * from t, r where r.a = t.a using select /*+ straight_join() */* from t, r where r.a = t.a; +execute stmt_join; +execute stmt_join; +select @@last_plan_from_cache; +execute stmt_join; +select @@last_plan_from_binding; +create binding for select * from t, r where r.a = t.a using select /*+ ignore_plan_cache() */* from t, r where r.a = t.a; +execute stmt_join; +select @@last_plan_from_cache; +execute stmt_join; +select @@last_plan_from_binding; +create binding for select * from t, r where r.a = t.a using select /*+ straight_join() */* from t, r where r.a = t.a; +execute stmt_join; +select @@last_plan_from_cache; +execute stmt_join; +select @@last_plan_from_binding; + diff --git a/tests/integrationtest/t/executor/grant.test b/tests/integrationtest/t/executor/grant.test new file mode 100644 index 0000000000000..20c3709abbb21 --- /dev/null +++ b/tests/integrationtest/t/executor/grant.test @@ -0,0 +1,292 @@ +# TestWithGrantOption +drop user if exists 'testWithGrant'@'localhost'; +CREATE USER 'testWithGrant'@'localhost' IDENTIFIED BY '123'; +SELECT * FROM mysql.db WHERE User="testWithGrant" and host="localhost"; +GRANT select ON executor__grant.* TO 'testWithGrant'@'localhost' WITH GRANT OPTION; +SELECT grant_priv FROM mysql.DB WHERE User="testWithGrant" and host="localhost" and db="executor__grant"; +drop user if exists 'testWithGrant1'; +CREATE USER 'testWithGrant1'; +SELECT grant_priv FROM mysql.user WHERE User="testWithGrant1"; +GRANT ALL ON *.* TO 'testWithGrant1'; +SELECT grant_priv FROM mysql.user WHERE User="testWithGrant1"; +GRANT ALL ON *.* TO 'testWithGrant1' WITH GRANT OPTION; +SELECT grant_priv FROM mysql.user WHERE User="testWithGrant1"; + +# TestIssue2456 +drop user if exists 'dduser'@'%'; +drop DATABASE if exists `dddb_%`; +CREATE USER 'dduser'@'%' IDENTIFIED by '123456'; +CREATE DATABASE `dddb_%`; +CREATE table `dddb_%`.`te%` (id int); +GRANT ALL PRIVILEGES ON `dddb_%`.* TO 'dduser'@'%'; +GRANT ALL PRIVILEGES ON `dddb_%`.`te%` to 'dduser'@'%'; + +# TestNoAutoCreateUser +DROP USER IF EXISTS 'test'@'%'; +SET sql_mode='NO_AUTO_CREATE_USER'; +-- error 1410 +GRANT ALL PRIVILEGES ON *.* to 'test'@'%' IDENTIFIED BY 'xxx'; +set sql_mode=default; + +# TestCreateUserWhenGrant +DROP USER IF EXISTS 'test'@'%'; +# This only applies to sql_mode:NO_AUTO_CREATE_USER off +SET SQL_MODE=''; +GRANT ALL PRIVILEGES ON *.* to 'test'@'%' IDENTIFIED BY 'xxx'; +# Make sure user is created automatically when grant to a non-exists one. +SELECT user FROM mysql.user WHERE user='test' and host='%'; +DROP USER IF EXISTS 'test'@'%'; +# Grant without a password. +GRANT ALL PRIVILEGES ON *.* to 'test'@'%'; +# Make sure user is created automatically when grant to a non-exists one. +SELECT user, plugin FROM mysql.user WHERE user='test' and host='%'; +DROP USER IF EXISTS 'test'@'%'; +set sql_mode=default; + +# TestCreateUserWithTooLongName +-- error 1470 +CREATE USER '1234567890abcdefGHIKL1234567890abcdefGHIKL@localhost'; +-- error 1470 +CREATE USER 'some_user_name@host_1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890X'; + +# TestGrantPrivilegeAtomic +drop role if exists r1, r2, r3, r4; +create role r1, r2, r3; +create table executor__grant.testatomic(x int); +-- error 1410 +grant update, select, insert, delete on *.* to r1, r2, r4; +select Update_priv, Select_priv, Insert_priv, Delete_priv from mysql.user where user in ('r1', 'r2', 'r3', 'r4') and host = "%"; +grant update, select, insert, delete on *.* to r1, r2, r3; +-- error 1105 +revoke all on *.* from r1, r2, r4, r3; +select Update_priv, Select_priv, Insert_priv, Delete_priv from mysql.user where user in ('r1', 'r2', 'r3', 'r4') and host = "%"; +-- error 1410 +grant update, select, insert, delete on executor__grant.* to r1, r2, r4; +select Update_priv, Select_priv, Insert_priv, Delete_priv from mysql.db where user in ('r1', 'r2', 'r3', 'r4') and host = "%"; +grant update, select, insert, delete on executor__grant.* to r1, r2, r3; +-- error 1105 +revoke all on *.* from r1, r2, r4, r3; +select Update_priv, Select_priv, Insert_priv, Delete_priv from mysql.db where user in ('r1', 'r2', 'r3', 'r4') and host = "%"; +-- error 1410 +grant update, select, insert, delete on executor__grant.testatomic to r1, r2, r4; +select Table_priv from mysql.tables_priv where user in ('r1', 'r2', 'r3', 'r4') and host = "%"; +grant update, select, insert, delete on executor__grant.testatomic to r1, r2, r3; +-- error 1105 +revoke all on *.* from r1, r2, r4, r3; +select Table_priv from mysql.tables_priv where user in ('r1', 'r2', 'r3', 'r4') and host = "%"; +drop role if exists r1, r2, r3, r4; +drop table executor__grant.testatomic; + +# TestIssue2654 +DROP USER IF EXISTS 'test'@'%'; +CREATE USER 'test'@'%' IDENTIFIED BY 'test'; +GRANT SELECT ON executor__grant.* to 'test'; +SELECT user,host FROM mysql.user WHERE user='test' and host='%'; + +# TestGrantUnderANSIQuotes +SET SQL_MODE='ANSI_QUOTES'; +# Fix a bug that the GrantExec fails in ANSI_QUOTES sql mode +# The bug is caused by the improper usage of double quotes like: +# INSERT INTO mysql.user ... VALUES ("..", "..", "..") +GRANT ALL PRIVILEGES ON video_ulimit.* TO web@'%' IDENTIFIED BY 'eDrkrhZ>l2sV'; +REVOKE ALL PRIVILEGES ON video_ulimit.* FROM web@'%'; +DROP USER IF EXISTS 'web'@'%'; +set sql_mode=default; + +# TestMaintainRequire +DROP USER if exists 'ssl_auser'@'%'; +DROP USER if exists 'ssl_buser'@'%'; +DROP USER if exists 'ssl_cuser'@'%'; +DROP USER if exists 'ssl_duser'@'%'; +DROP USER if exists 'ssl_euser'@'%'; +DROP USER if exists 'ssl_fuser'@'%'; +DROP USER if exists 'ssl_guser'@'%'; +drop user if exists 'u1'@'%'; +drop user if exists 'u2'@'%'; +drop user if exists 'u3'@'%'; +CREATE USER 'ssl_auser'@'%' require issuer '/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US' subject '/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH' cipher 'AES128-GCM-SHA256'; +CREATE USER 'ssl_buser'@'%' require subject '/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH' cipher 'AES128-GCM-SHA256'; +CREATE USER 'ssl_cuser'@'%' require cipher 'AES128-GCM-SHA256'; +CREATE USER 'ssl_duser'@'%'; +CREATE USER 'ssl_euser'@'%' require none; +CREATE USER 'ssl_fuser'@'%' require ssl; +CREATE USER 'ssl_guser'@'%' require x509; +select * from mysql.global_priv where `user` like 'ssl_%'; +CREATE USER 'u1'@'%'; +GRANT ALL ON *.* TO 'u1'@'%' require issuer '/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US' and subject '/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH'; +select priv from mysql.global_priv where `Host` = '%' and `User` = 'u1'; +GRANT ALL ON *.* TO 'u1'@'%' require cipher 'AES128-GCM-SHA256'; +select priv from mysql.global_priv where `Host` = '%' and `User` = 'u1'; +GRANT select ON *.* TO 'u1'@'%'; +select priv from mysql.global_priv where `Host` = '%' and `User` = 'u1'; +GRANT ALL ON *.* TO 'u1'@'%' require none; +select priv from mysql.global_priv where `Host` = '%' and `User` = 'u1'; +CREATE USER 'u2'@'%'; +alter user 'u2'@'%' require ssl; +select priv from mysql.global_priv where `Host` = '%' and `User` = 'u2'; +alter user 'u2'@'%' require x509; +select priv from mysql.global_priv where `Host` = '%' and `User` = 'u2'; +alter user 'u2'@'%' require issuer '/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US' subject '/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH' cipher 'AES128-GCM-SHA256'; +select priv from mysql.global_priv where `Host` = '%' and `User` = 'u2'; +alter user 'u2'@'%' require none; +select priv from mysql.global_priv where `Host` = '%' and `User` = 'u2'; +CREATE USER 'u3'@'%' require issuer '/CN=TiDB admin/OU=TiDB/O=PingCAP/L=San Francisco/ST=California/C=US' subject '/CN=tester1/OU=TiDB/O=PingCAP.Inc/L=Haidian/ST=Beijing/C=ZH' cipher 'AES128-GCM-SHA256'; +show create user 'u3'; +-- error 1105 +CREATE USER 'u4'@'%' require issuer 'CN=TiDB,OU=PingCAP'; +-- error 1105 +CREATE USER 'u5'@'%' require subject '/CN=TiDB\OU=PingCAP'; +-- error 1105 +CREATE USER 'u6'@'%' require subject '/CN=TiDB\NC=PingCAP'; +-- error 1105 +CREATE USER 'u7'@'%' require cipher 'AES128-GCM-SHA1'; +-- error 1105 +CREATE USER 'u8'@'%' require subject '/CN'; +-- error 1105 +CREATE USER 'u9'@'%' require cipher 'TLS_AES_256_GCM_SHA384' cipher 'RC4-SHA'; +-- error 1105 +CREATE USER 'u9'@'%' require issuer 'CN=TiDB,OU=PingCAP' issuer 'CN=TiDB,OU=PingCAP2'; +-- error 1105 +CREATE USER 'u9'@'%' require subject '/CN=TiDB\OU=PingCAP' subject '/CN=TiDB\OU=PingCAP2'; +-- error 1064 +CREATE USER 'u9'@'%' require ssl ssl; +-- error 1064 +CREATE USER 'u9'@'%' require x509 x509; + +# TestMaintainAuthString +drop user if exists 'maint_auth_str1'@'%'; +CREATE USER 'maint_auth_str1'@'%' IDENTIFIED BY 'foo'; +SELECT authentication_string FROM mysql.user WHERE `Host` = '%' and `User` = 'maint_auth_str1'; +ALTER USER 'maint_auth_str1'@'%' REQUIRE SSL; +SELECT authentication_string FROM mysql.user WHERE `Host` = '%' and `User` = 'maint_auth_str1'; + +# TestIssue22721 +drop table if exists xx; +drop user if exists 'sync_ci_data'@'%'; +create table xx (id int); +CREATE USER 'sync_ci_data'@'%' IDENTIFIED BY 'sNGNQo12fEHe0n3vU'; +GRANT USAGE ON *.* TO 'sync_ci_data'@'%'; +GRANT USAGE ON sync_ci_data.* TO 'sync_ci_data'@'%'; +GRANT USAGE ON executor__grant.* TO 'sync_ci_data'@'%'; +GRANT USAGE ON executor__grant.xx TO 'sync_ci_data'@'%'; + +# TestPerformanceSchemaPrivGrant +drop user if exists issue27867; +create user issue27867; +-- error 1044 +grant all on performance_schema.* to issue27867; +-- error 1044 +grant all on PERFormanCE_scHemA.* to issue27867; +grant select on performance_schema.* to issue27867; +-- error 1044 +grant insert on performance_schema.* to issue27867; +-- error 1044 +grant update on performance_schema.* to issue27867; +-- error 1044 +grant delete on performance_schema.* to issue27867; +-- error 1044 +grant drop on performance_schema.* to issue27867; +-- error 1044 +grant lock tables on performance_schema.* to issue27867; +-- error 1044 +grant create on performance_schema.* to issue27867; +-- error 1044 +grant references on performance_schema.* to issue27867; +-- error 1044 +grant alter on PERFormAnCE_scHemA.* to issue27867; +-- error 1044 +grant execute on performance_schema.* to issue27867; +-- error 1044 +grant index on PERFormanCE_scHemA.* to issue27867; +-- error 1044 +grant create view on performance_schema.* to issue27867; +-- error 1044 +grant show view on performance_schema.* to issue27867; +drop user issue27867; + +# TestGrantDynamicPrivs +drop user if exists dyn; +create user dyn; +-- error 3619 +GRANT BACKUP_ADMIN ON executor__grant.* TO dyn; +-- error 3929 +GRANT BOGUS_GRANT ON *.* TO dyn; +GRANT BACKUP_Admin ON *.* TO dyn; +SELECT * FROM mysql.global_grants WHERE `Host` = '%' AND `User` = 'dyn' ORDER BY user,host,priv,with_grant_option; +GRANT SYSTEM_VARIABLES_ADMIN, BACKUP_ADMIN ON *.* TO dyn; +SELECT * FROM mysql.global_grants WHERE `Host` = '%' AND `User` = 'dyn' ORDER BY user,host,priv,with_grant_option; +GRANT ROLE_ADMIN, BACKUP_ADMIN ON *.* TO dyn WITH GRANT OPTION; +SELECT * FROM mysql.global_grants WHERE `Host` = '%' AND `User` = 'dyn' ORDER BY user,host,priv,with_grant_option; +GRANT SYSTEM_VARIABLES_ADMIN, Select, ROLE_ADMIN ON *.* TO dyn; +SELECT Grant_Priv FROM mysql.user WHERE `Host` = '%' AND `User` = 'dyn'; +SELECT WITH_GRANT_OPTION FROM mysql.global_grants WHERE `Host` = '%' AND `User` = 'dyn' AND Priv='SYSTEM_VARIABLES_ADMIN'; +GRANT CONNECTION_ADMIN, Insert ON *.* TO dyn WITH GRANT OPTION; +SELECT Grant_Priv FROM mysql.user WHERE `Host` = '%' AND `User` = 'dyn'; +SELECT WITH_GRANT_OPTION FROM mysql.global_grants WHERE `Host` = '%' AND `User` = 'dyn' AND Priv='CONNECTION_ADMIN'; + +# TestNonExistTableIllegalGrant +drop user if exists u29302; +create user u29302; +-- error 1144 +grant create temporary tables on NotExistsD29302.NotExistsT29302 to u29302; +-- error 1144 +grant lock tables on executor__grant.NotExistsT29302 to u29302; +-- error 1221 +grant create temporary tables (NotExistsCol) on NotExistsD29302.NotExistsT29302 to u29302; +drop user u29302; + +# TestIssue34610 +drop table if exists t1; +drop user if exists user_1@localhost; +CREATE USER user_1@localhost; +CREATE TABLE T1(f1 INT); +-- error 1050 +CREATE TABLE t1(f1 INT); +GRANT SELECT ON T1 to user_1@localhost; +GRANT SELECT ON t1 to user_1@localhost; + +# TestIssue38293 +DROP USER IF EXISTS test; +CREATE USER test; +GRANT SELECT ON `mysql`.`db` TO test; +SELECT `Grantor` FROM `mysql`.`tables_priv` WHERE User = 'test'; + +# TestGrantOnNonExistTable +drop user if exists genius; +drop user if exists u29268; +create user genius; +-- error 1146 +select * from nonexist; +-- error 1146 +grant Select,Insert on nonexist to 'genius'; +create table if not exists xx (id int); +grant Select,Insert on XX to 'genius'; +grant Select,Insert on xx to 'genius'; +grant Select,Update on executor__grant.xx to 'genius'; +CREATE DATABASE d29268; +USE d29268; +CREATE USER u29268; +-- error 1146 +GRANT SELECT ON t29268 TO u29268; +-- error 1146 +GRANT DROP, INSERT ON t29268 TO u29268; +-- error 1146 +GRANT UPDATE, CREATE VIEW, SHOW VIEW ON t29268 TO u29268; +-- error 1146 +GRANT DELETE, REFERENCES, ALTER ON t29268 TO u29268; +GRANT CREATE ON t29268 TO u29268; +GRANT CREATE, SELECT ON t29268 TO u29268; +GRANT CREATE, DROP, INSERT ON t29268 TO u29268; + +connect (conn1, localhost, u29268,, d29268); +CREATE TABLE t29268 (c1 int); +INSERT INTO t29268 VALUES (1), (2); +SELECT c1 FROM t29268; +DROP TABLE t29268; +disconnect conn1; + +GRANT ALL ON t29268 TO u29268; +DROP USER u29268; +DROP DATABASE IF EXISTS d29268; +use executor__grant; + diff --git a/tests/integrationtest/t/privilege/privileges.test b/tests/integrationtest/t/privilege/privileges.test index 719253443426e..593eb44422613 100644 --- a/tests/integrationtest/t/privilege/privileges.test +++ b/tests/integrationtest/t/privilege/privileges.test @@ -47,6 +47,7 @@ connection default; drop table t1; # TestGrantRoutine +drop user if exists u1; CREATE USER u1; CREATE TABLE routine_table (a int); GRANT CREATE ROUTINE on privilege__privileges.* to u1;