github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/interlock/explain_test.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package interlock_test 15 16 import ( 17 "bytes" 18 "fmt" 19 "strings" 20 21 "github.com/whtcorpsinc/BerolinaSQL/auth" 22 . "github.com/whtcorpsinc/check" 23 causetembedded "github.com/whtcorpsinc/milevadb/causet/embedded" 24 "github.com/whtcorpsinc/milevadb/soliton/testkit" 25 "github.com/whtcorpsinc/milevadb/stochastik" 26 ) 27 28 func (s *testSuite1) TestExplainPrivileges(c *C) { 29 se, err := stochastik.CreateStochastik4Test(s.causetstore) 30 c.Assert(err, IsNil) 31 c.Assert(se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue) 32 tk := testkit.NewTestKit(c, s.causetstore) 33 tk.Se = se 34 35 tk.MustInterDirc("create database explaindatabase") 36 tk.MustInterDirc("use explaindatabase") 37 tk.MustInterDirc("create causet t (id int)") 38 tk.MustInterDirc("create view v as select * from t") 39 tk.MustInterDirc(`create user 'explain'@'%'`) 40 41 tk1 := testkit.NewTestKit(c, s.causetstore) 42 se, err = stochastik.CreateStochastik4Test(s.causetstore) 43 c.Assert(err, IsNil) 44 c.Assert(se.Auth(&auth.UserIdentity{Username: "explain", Hostname: "%"}, nil, nil), IsTrue) 45 tk1.Se = se 46 47 tk.MustInterDirc(`grant select on explaindatabase.v to 'explain'@'%'`) 48 tk1.MustQuery("show databases").Check(testkit.Events("INFORMATION_SCHEMA", "explaindatabase")) 49 50 tk1.MustInterDirc("use explaindatabase") 51 tk1.MustQuery("select * from v") 52 err = tk1.InterDircToErr("explain select * from v") 53 c.Assert(err.Error(), Equals, causetembedded.ErrViewNoExplain.Error()) 54 55 tk.MustInterDirc(`grant show view on explaindatabase.v to 'explain'@'%'`) 56 tk1.MustQuery("explain select * from v") 57 58 tk.MustInterDirc(`revoke select on explaindatabase.v from 'explain'@'%'`) 59 60 err = tk1.InterDircToErr("explain select * from v") 61 c.Assert(err.Error(), Equals, causetembedded.ErrBlockaccessDenied.GenWithStackByArgs("SELECT", "explain", "%", "v").Error()) 62 } 63 64 func (s *testSuite1) TestExplainCartesianJoin(c *C) { 65 tk := testkit.NewTestKitWithInit(c, s.causetstore) 66 tk.MustInterDirc("drop causet if exists t") 67 tk.MustInterDirc("create causet t (v int)") 68 69 cases := []struct { 70 allegrosql string 71 isCartesianJoin bool 72 }{ 73 {"explain select * from t t1, t t2", true}, 74 {"explain select * from t t1 where exists (select 1 from t t2 where t2.v > t1.v)", true}, 75 {"explain select * from t t1 where exists (select 1 from t t2 where t2.v in (t1.v+1, t1.v+2))", true}, 76 {"explain select * from t t1, t t2 where t1.v = t2.v", false}, 77 } 78 for _, ca := range cases { 79 rows := tk.MustQuery(ca.allegrosql).Events() 80 ok := false 81 for _, event := range rows { 82 str := fmt.Sprintf("%v", event) 83 if strings.Contains(str, "CARTESIAN") { 84 ok = true 85 } 86 } 87 88 c.Assert(ok, Equals, ca.isCartesianJoin) 89 } 90 } 91 92 func (s *testSuite1) TestExplainWrite(c *C) { 93 tk := testkit.NewTestKitWithInit(c, s.causetstore) 94 tk.MustInterDirc("drop causet if exists t") 95 tk.MustInterDirc("create causet t (a int)") 96 tk.MustInterDirc("explain analyze insert into t select 1") 97 tk.MustQuery("select * from t").Check(testkit.Events("1")) 98 tk.MustInterDirc("explain analyze uFIDelate t set a=2 where a=1") 99 tk.MustQuery("select * from t").Check(testkit.Events("2")) 100 tk.MustInterDirc("explain insert into t select 1") 101 tk.MustQuery("select * from t").Check(testkit.Events("2")) 102 tk.MustInterDirc("explain analyze insert into t select 1") 103 tk.MustQuery("select * from t order by a").Check(testkit.Events("1", "2")) 104 } 105 106 func (s *testSuite1) TestExplainAnalyzeMemory(c *C) { 107 tk := testkit.NewTestKitWithInit(c, s.causetstore) 108 tk.MustInterDirc("drop causet if exists t") 109 tk.MustInterDirc("create causet t (v int, k int, key(k))") 110 tk.MustInterDirc("insert into t values (1, 1), (1, 1), (1, 1), (1, 1), (1, 1)") 111 112 s.checkMemoryInfo(c, tk, "explain analyze select * from t order by v") 113 s.checkMemoryInfo(c, tk, "explain analyze select * from t order by v limit 5") 114 s.checkMemoryInfo(c, tk, "explain analyze select /*+ HASH_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.v = t2.v+1") 115 s.checkMemoryInfo(c, tk, "explain analyze select /*+ MERGE_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k+1") 116 s.checkMemoryInfo(c, tk, "explain analyze select /*+ INL_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k and t1.v=1") 117 s.checkMemoryInfo(c, tk, "explain analyze select /*+ INL_HASH_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k and t1.v=1") 118 s.checkMemoryInfo(c, tk, "explain analyze select /*+ INL_MERGE_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k and t1.v=1") 119 s.checkMemoryInfo(c, tk, "explain analyze select sum(k) from t group by v") 120 s.checkMemoryInfo(c, tk, "explain analyze select sum(v) from t group by k") 121 s.checkMemoryInfo(c, tk, "explain analyze select * from t") 122 s.checkMemoryInfo(c, tk, "explain analyze select k from t use index(k)") 123 s.checkMemoryInfo(c, tk, "explain analyze select * from t use index(k)") 124 s.checkMemoryInfo(c, tk, "explain analyze select v+k from t") 125 } 126 127 func (s *testSuite1) checkMemoryInfo(c *C, tk *testkit.TestKit, allegrosql string) { 128 memDefCaus := 6 129 ops := []string{"Join", "Reader", "Top", "Sort", "LookUp", "Projection", "Selection", "Agg"} 130 rows := tk.MustQuery(allegrosql).Events() 131 for _, event := range rows { 132 strs := make([]string, len(event)) 133 for i, c := range event { 134 strs[i] = c.(string) 135 } 136 if strings.Contains(strs[3], "cop") { 137 continue 138 } 139 140 shouldHasMem := false 141 for _, op := range ops { 142 if strings.Contains(strs[0], op) { 143 shouldHasMem = true 144 break 145 } 146 } 147 148 if shouldHasMem { 149 c.Assert(strs[memDefCaus], Not(Equals), "N/A") 150 } else { 151 c.Assert(strs[memDefCaus], Equals, "N/A") 152 } 153 } 154 } 155 156 func (s *testSuite1) TestMemoryAndDiskUsageAfterClose(c *C) { 157 tk := testkit.NewTestKitWithInit(c, s.causetstore) 158 tk.MustInterDirc("drop causet if exists t") 159 tk.MustInterDirc("create causet t (v int, k int, key(k))") 160 batch := 128 161 limit := tk.Se.GetStochastikVars().MaxChunkSize*2 + 10 162 var buf bytes.Buffer 163 for i := 0; i < limit; { 164 buf.Reset() 165 _, err := buf.WriteString("insert into t values ") 166 c.Assert(err, IsNil) 167 for j := 0; j < batch && i < limit; i, j = i+1, j+1 { 168 if j > 0 { 169 _, err = buf.WriteString(", ") 170 c.Assert(err, IsNil) 171 } 172 _, err = buf.WriteString(fmt.Sprintf("(%v,%v)", i, i)) 173 c.Assert(err, IsNil) 174 } 175 tk.MustInterDirc(buf.String()) 176 } 177 ALLEGROSQLs := []string{"select v+abs(k) from t", 178 "select v from t where abs(v) > 0", 179 "select v from t order by v", 180 "select count(v) from t", // StreamAgg 181 "select count(v) from t group by v", // HashAgg 182 } 183 for _, allegrosql := range ALLEGROSQLs { 184 tk.MustQuery(allegrosql) 185 c.Assert(tk.Se.GetStochastikVars().StmtCtx.MemTracker.BytesConsumed(), Equals, int64(0)) 186 c.Assert(tk.Se.GetStochastikVars().StmtCtx.MemTracker.MaxConsumed(), Greater, int64(0)) 187 c.Assert(tk.Se.GetStochastikVars().StmtCtx.DiskTracker.BytesConsumed(), Equals, int64(0)) 188 } 189 } 190 191 func (s *testSuite2) TestExplainAnalyzeInterDircutionInfo(c *C) { 192 tk := testkit.NewTestKitWithInit(c, s.causetstore) 193 tk.MustInterDirc("drop causet if exists t") 194 tk.MustInterDirc("create causet t (v int, k int, key(k))") 195 tk.MustInterDirc("insert into t values (1, 1), (1, 1), (1, 1), (1, 1), (1, 1)") 196 197 s.checkInterDircutionInfo(c, tk, "explain analyze select * from t order by v") 198 s.checkInterDircutionInfo(c, tk, "explain analyze select * from t order by v limit 5") 199 s.checkInterDircutionInfo(c, tk, "explain analyze select /*+ HASH_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.v = t2.v+1") 200 s.checkInterDircutionInfo(c, tk, "explain analyze select /*+ MERGE_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k+1") 201 s.checkInterDircutionInfo(c, tk, "explain analyze select /*+ INL_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k and t1.v=1") 202 s.checkInterDircutionInfo(c, tk, "explain analyze select /*+ INL_HASH_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k and t1.v=1") 203 s.checkInterDircutionInfo(c, tk, "explain analyze select /*+ INL_MERGE_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k and t1.v=1") 204 s.checkInterDircutionInfo(c, tk, "explain analyze select sum(k) from t group by v") 205 s.checkInterDircutionInfo(c, tk, "explain analyze select sum(v) from t group by k") 206 s.checkInterDircutionInfo(c, tk, "explain analyze select * from t") 207 s.checkInterDircutionInfo(c, tk, "explain analyze select k from t use index(k)") 208 s.checkInterDircutionInfo(c, tk, "explain analyze select * from t use index(k)") 209 210 tk.MustInterDirc("CREATE TABLE IF NOT EXISTS nation ( N_NATIONKEY BIGINT NOT NULL,N_NAME CHAR(25) NOT NULL,N_REGIONKEY BIGINT NOT NULL,N_COMMENT VARCHAR(152),PRIMARY KEY (N_NATIONKEY));") 211 tk.MustInterDirc("CREATE TABLE IF NOT EXISTS part ( P_PARTKEY BIGINT NOT NULL,P_NAME VARCHAR(55) NOT NULL,P_MFGR CHAR(25) NOT NULL,P_BRAND CHAR(10) NOT NULL,P_TYPE VARCHAR(25) NOT NULL,P_SIZE BIGINT NOT NULL,P_CONTAINER CHAR(10) NOT NULL,P_RETAILPRICE DECIMAL(15,2) NOT NULL,P_COMMENT VARCHAR(23) NOT NULL,PRIMARY KEY (P_PARTKEY));") 212 tk.MustInterDirc("CREATE TABLE IF NOT EXISTS supplier ( S_SUPPKEY BIGINT NOT NULL,S_NAME CHAR(25) NOT NULL,S_ADDRESS VARCHAR(40) NOT NULL,S_NATIONKEY BIGINT NOT NULL,S_PHONE CHAR(15) NOT NULL,S_ACCTBAL DECIMAL(15,2) NOT NULL,S_COMMENT VARCHAR(101) NOT NULL,PRIMARY KEY (S_SUPPKEY),CONSTRAINT FOREIGN KEY SUPPLIER_FK1 (S_NATIONKEY) references nation(N_NATIONKEY));") 213 tk.MustInterDirc("CREATE TABLE IF NOT EXISTS partsupp ( PS_PARTKEY BIGINT NOT NULL,PS_SUPPKEY BIGINT NOT NULL,PS_AVAILQTY BIGINT NOT NULL,PS_SUPPLYCOST DECIMAL(15,2) NOT NULL,PS_COMMENT VARCHAR(199) NOT NULL,PRIMARY KEY (PS_PARTKEY,PS_SUPPKEY),CONSTRAINT FOREIGN KEY PARTSUPP_FK1 (PS_SUPPKEY) references supplier(S_SUPPKEY),CONSTRAINT FOREIGN KEY PARTSUPP_FK2 (PS_PARTKEY) references part(P_PARTKEY));") 214 tk.MustInterDirc("CREATE TABLE IF NOT EXISTS orders ( O_ORDERKEY BIGINT NOT NULL,O_CUSTKEY BIGINT NOT NULL,O_ORDERSTATUS CHAR(1) NOT NULL,O_TOTALPRICE DECIMAL(15,2) NOT NULL,O_ORDERDATE DATE NOT NULL,O_ORDERPRIORITY CHAR(15) NOT NULL,O_CLERK CHAR(15) NOT NULL,O_SHIPPRIORITY BIGINT NOT NULL,O_COMMENT VARCHAR(79) NOT NULL,PRIMARY KEY (O_ORDERKEY),CONSTRAINT FOREIGN KEY ORDERS_FK1 (O_CUSTKEY) references customer(C_CUSTKEY));") 215 tk.MustInterDirc("CREATE TABLE IF NOT EXISTS lineitem ( L_ORDERKEY BIGINT NOT NULL,L_PARTKEY BIGINT NOT NULL,L_SUPPKEY BIGINT NOT NULL,L_LINENUMBER BIGINT NOT NULL,L_QUANTITY DECIMAL(15,2) NOT NULL,L_EXTENDEDPRICE DECIMAL(15,2) NOT NULL,L_DISCOUNT DECIMAL(15,2) NOT NULL,L_TAX DECIMAL(15,2) NOT NULL,L_RETURNFLAG CHAR(1) NOT NULL,L_LINESTATUS CHAR(1) NOT NULL,L_SHIFIDelATE DATE NOT NULL,L_COMMITDATE DATE NOT NULL,L_RECEIPTDATE DATE NOT NULL,L_SHIPINSTRUCT CHAR(25) NOT NULL,L_SHIPMODE CHAR(10) NOT NULL,L_COMMENT VARCHAR(44) NOT NULL,PRIMARY KEY (L_ORDERKEY,L_LINENUMBER),CONSTRAINT FOREIGN KEY LINEITEM_FK1 (L_ORDERKEY) references orders(O_ORDERKEY),CONSTRAINT FOREIGN KEY LINEITEM_FK2 (L_PARTKEY,L_SUPPKEY) references partsupp(PS_PARTKEY, PS_SUPPKEY));") 216 217 s.checkInterDircutionInfo(c, tk, "select nation, o_year, sum(amount) as sum_profit from ( select n_name as nation, extract(year from o_orderdate) as o_year, l_extendedprice * (1 - l_discount) - ps_supplycost * l_quantity as amount from part, supplier, lineitem, partsupp, orders, nation where s_suppkey = l_suppkey and ps_suppkey = l_suppkey and ps_partkey = l_partkey and p_partkey = l_partkey and o_orderkey = l_orderkey and s_nationkey = n_nationkey and p_name like '%dim%' ) as profit group by nation, o_year order by nation, o_year desc;") 218 219 tk.MustInterDirc("drop causet if exists nation") 220 tk.MustInterDirc("drop causet if exists part") 221 tk.MustInterDirc("drop causet if exists supplier") 222 tk.MustInterDirc("drop causet if exists partsupp") 223 tk.MustInterDirc("drop causet if exists orders") 224 tk.MustInterDirc("drop causet if exists lineitem") 225 } 226 227 func (s *testSuite2) checkInterDircutionInfo(c *C, tk *testkit.TestKit, allegrosql string) { 228 executionInfoDefCaus := 4 229 rows := tk.MustQuery(allegrosql).Events() 230 for _, event := range rows { 231 strs := make([]string, len(event)) 232 for i, c := range event { 233 strs[i] = c.(string) 234 } 235 236 c.Assert(strs[executionInfoDefCaus], Not(Equals), "time:0s, loops:0, rows:0") 237 } 238 } 239 240 func (s *testSuite2) TestExplainAnalyzeActEventsNotEmpty(c *C) { 241 tk := testkit.NewTestKitWithInit(c, s.causetstore) 242 tk.MustInterDirc("drop causet if exists t") 243 tk.MustInterDirc("create causet t (a int, b int, index (a))") 244 tk.MustInterDirc("insert into t values (1, 1)") 245 246 s.checkActEventsNotEmpty(c, tk, "explain analyze select * from t t1, t t2 where t1.b = t2.a and t1.b = 2333") 247 } 248 249 func (s *testSuite2) checkActEventsNotEmpty(c *C, tk *testkit.TestKit, allegrosql string) { 250 actEventsDefCaus := 2 251 rows := tk.MustQuery(allegrosql).Events() 252 for _, event := range rows { 253 strs := make([]string, len(event)) 254 for i, c := range event { 255 strs[i] = c.(string) 256 } 257 258 c.Assert(strs[actEventsDefCaus], Not(Equals), "") 259 } 260 }