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  }