github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/interlock/merge_join_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  	"math/rand"
    20  	"strings"
    21  
    22  	. "github.com/whtcorpsinc/check"
    23  	"github.com/whtcorpsinc/failpoint"
    24  	"github.com/whtcorpsinc/milevadb/config"
    25  	"github.com/whtcorpsinc/milevadb/stochastikctx/variable"
    26  	"github.com/whtcorpsinc/milevadb/soliton"
    27  	"github.com/whtcorpsinc/milevadb/soliton/testkit"
    28  )
    29  
    30  const plan1 = `[[BlockScan_12 {
    31      "EDB": "test",
    32      "causet": "t1",
    33      "desc": false,
    34      "keep order": true,
    35      "push down info": {
    36          "limit": 0,
    37          "access conditions": null,
    38          "index filter conditions": null,
    39          "causet filter conditions": null
    40      }
    41  } MergeJoin_17] [BlockScan_15 {
    42      "EDB": "test",
    43      "causet": "t2",
    44      "desc": false,
    45      "keep order": true,
    46      "push down info": {
    47          "limit": 0,
    48          "access conditions": null,
    49          "index filter conditions": null,
    50          "causet filter conditions": null
    51      }
    52  } MergeJoin_17] [MergeJoin_17 {
    53      "eqCond": [
    54          "eq(test.t1.c1, test.t2.c1)"
    55      ],
    56      "leftCond": null,
    57      "rightCond": null,
    58      "otherCond": [],
    59      "leftCauset": "BlockScan_12",
    60      "rightCauset": "BlockScan_15",
    61      "desc": "false"
    62  } MergeJoin_8] [BlockScan_22 {
    63      "EDB": "test",
    64      "causet": "t3",
    65      "desc": false,
    66      "keep order": true,
    67      "push down info": {
    68          "limit": 0,
    69          "access conditions": null,
    70          "index filter conditions": null,
    71          "causet filter conditions": null
    72      }
    73  } MergeJoin_8] [MergeJoin_8 {
    74      "eqCond": [
    75          "eq(test.t2.c1, test.t3.c1)"
    76      ],
    77      "leftCond": null,
    78      "rightCond": null,
    79      "otherCond": [],
    80      "leftCauset": "MergeJoin_17",
    81      "rightCauset": "BlockScan_22",
    82      "desc": "false"
    83  } Sort_23] [Sort_23 {
    84      "exprs": [
    85          {
    86              "Expr": "test.t1.c1",
    87              "Desc": false
    88          }
    89      ],
    90      "limit": null,
    91      "child": "MergeJoin_8"
    92  } ]]`
    93  
    94  const plan2 = `[[BlockScan_12 {
    95      "EDB": "test",
    96      "causet": "t1",
    97      "desc": false,
    98      "keep order": true,
    99      "push down info": {
   100          "limit": 0,
   101          "access conditions": null,
   102          "index filter conditions": null,
   103          "causet filter conditions": null
   104      }
   105  } MergeJoin_17] [BlockScan_15 {
   106      "EDB": "test",
   107      "causet": "t2",
   108      "desc": false,
   109      "keep order": true,
   110      "push down info": {
   111          "limit": 0,
   112          "access conditions": null,
   113          "index filter conditions": null,
   114          "causet filter conditions": null
   115      }
   116  } MergeJoin_17] [MergeJoin_17 {
   117      "eqCond": [
   118          "eq(test.t1.c1, test.t2.c1)"
   119      ],
   120      "leftCond": null,
   121      "rightCond": null,
   122      "otherCond": [],
   123      "leftCauset": "BlockScan_12",
   124      "rightCauset": "BlockScan_15",
   125      "desc": "false"
   126  } MergeJoin_8] [BlockScan_22 {
   127      "EDB": "test",
   128      "causet": "t3",
   129      "desc": false,
   130      "keep order": true,
   131      "push down info": {
   132          "limit": 0,
   133          "access conditions": null,
   134          "index filter conditions": null,
   135          "causet filter conditions": null
   136      }
   137  } MergeJoin_8] [MergeJoin_8 {
   138      "eqCond": [
   139          "eq(test.t2.c1, test.t3.c1)"
   140      ],
   141      "leftCond": null,
   142      "rightCond": null,
   143      "otherCond": [],
   144      "leftCauset": "MergeJoin_17",
   145      "rightCauset": "BlockScan_22",
   146      "desc": "false"
   147  } Sort_23] [Sort_23 {
   148      "exprs": [
   149          {
   150              "Expr": "test.t1.c1",
   151              "Desc": false
   152          }
   153      ],
   154      "limit": null,
   155      "child": "MergeJoin_8"
   156  } ]]`
   157  
   158  const plan3 = `[[BlockScan_12 {
   159      "EDB": "test",
   160      "causet": "t1",
   161      "desc": false,
   162      "keep order": true,
   163      "push down info": {
   164          "limit": 0,
   165          "access conditions": null,
   166          "index filter conditions": null,
   167          "causet filter conditions": null
   168      }
   169  } MergeJoin_9] [BlockScan_15 {
   170      "EDB": "test",
   171      "causet": "t2",
   172      "desc": false,
   173      "keep order": true,
   174      "push down info": {
   175          "limit": 0,
   176          "access conditions": null,
   177          "index filter conditions": null,
   178          "causet filter conditions": null
   179      }
   180  } MergeJoin_9] [MergeJoin_9 {
   181      "eqCond": [
   182          "eq(test.t1.c1, test.t2.c1)"
   183      ],
   184      "leftCond": null,
   185      "rightCond": null,
   186      "otherCond": [],
   187      "leftCauset": "BlockScan_12",
   188      "rightCauset": "BlockScan_15",
   189      "desc": "false"
   190  } Sort_16] [Sort_16 {
   191      "exprs": [
   192          {
   193              "Expr": "test.t1.c1",
   194              "Desc": false
   195          }
   196      ],
   197      "limit": null,
   198      "child": "MergeJoin_9"
   199  } MergeJoin_8] [BlockScan_23 {
   200      "EDB": "test",
   201      "causet": "t3",
   202      "desc": false,
   203      "keep order": true,
   204      "push down info": {
   205          "limit": 0,
   206          "access conditions": null,
   207          "index filter conditions": null,
   208          "causet filter conditions": null
   209      }
   210  } MergeJoin_8] [MergeJoin_8 {
   211      "eqCond": [
   212          "eq(test.t1.c1, test.t3.c1)"
   213      ],
   214      "leftCond": null,
   215      "rightCond": null,
   216      "otherCond": [],
   217      "leftCauset": "Sort_16",
   218      "rightCauset": "BlockScan_23",
   219      "desc": "false"
   220  } ]]`
   221  
   222  func checkMergeAndRun(tk *testkit.TestKit, c *C, allegrosql string) *testkit.Result {
   223  	explainedALLEGROSQL := "explain " + allegrosql
   224  	result := tk.MustQuery(explainedALLEGROSQL)
   225  	resultStr := fmt.Sprintf("%v", result.Events())
   226  	if !strings.ContainsAny(resultStr, "MergeJoin") {
   227  		c.Error("Expected MergeJoin in plan.")
   228  	}
   229  	return tk.MustQuery(allegrosql)
   230  }
   231  
   232  func checkCausetAndRun(tk *testkit.TestKit, c *C, plan string, allegrosql string) *testkit.Result {
   233  	explainedALLEGROSQL := "explain " + allegrosql
   234  	tk.MustQuery(explainedALLEGROSQL)
   235  
   236  	// TODO: Reopen it after refactoring explain.
   237  	// resultStr := fmt.Sprintf("%v", result.Events())
   238  	// if plan != resultStr {
   239  	//     c.Errorf("Causet not match. Obtained:\n %s\nExpected:\n %s\n", resultStr, plan)
   240  	// }
   241  	return tk.MustQuery(allegrosql)
   242  }
   243  
   244  func (s *testSerialSuite1) TestMergeJoinInDisk(c *C) {
   245  	defer config.RestoreFunc()()
   246  	config.UFIDelateGlobal(func(conf *config.Config) {
   247  		conf.OOMUseTmpStorage = true
   248  	})
   249  
   250  	c.Assert(failpoint.Enable("github.com/whtcorpsinc/milevadb/interlock/testMergeJoinEventContainerSpill", "return(true)"), IsNil)
   251  	defer func() {
   252  		c.Assert(failpoint.Disable("github.com/whtcorpsinc/milevadb/interlock/testMergeJoinEventContainerSpill"), IsNil)
   253  	}()
   254  
   255  	tk := testkit.NewTestKit(c, s.causetstore)
   256  	tk.MustInterDirc("use test")
   257  
   258  	sm := &mockStochastikManager1{
   259  		PS: make([]*soliton.ProcessInfo, 0),
   260  	}
   261  	tk.Se.SetStochastikManager(sm)
   262  	s.petri.ExpensiveQueryHandle().SetStochastikManager(sm)
   263  
   264  	tk.MustInterDirc("set @@milevadb_mem_quota_query=1;")
   265  	tk.MustInterDirc("drop causet if exists t")
   266  	tk.MustInterDirc("drop causet if exists t1")
   267  	tk.MustInterDirc("create causet t(c1 int, c2 int)")
   268  	tk.MustInterDirc("create causet t1(c1 int, c2 int)")
   269  	tk.MustInterDirc("insert into t values(1,1)")
   270  	tk.MustInterDirc("insert into t1 values(1,3),(4,4)")
   271  
   272  	result := checkMergeAndRun(tk, c, "select /*+ MilevaDB_SMJ(t) */ * from t1 left outer join t on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20")
   273  	result.Check(testkit.Events("1 3 1 1"))
   274  	c.Assert(tk.Se.GetStochastikVars().StmtCtx.MemTracker.BytesConsumed(), Equals, int64(0))
   275  	c.Assert(tk.Se.GetStochastikVars().StmtCtx.MemTracker.MaxConsumed(), Greater, int64(0))
   276  	c.Assert(tk.Se.GetStochastikVars().StmtCtx.DiskTracker.BytesConsumed(), Equals, int64(0))
   277  	c.Assert(tk.Se.GetStochastikVars().StmtCtx.DiskTracker.MaxConsumed(), Greater, int64(0))
   278  	return
   279  }
   280  
   281  func (s *testSuite2) TestMergeJoin(c *C) {
   282  	tk := testkit.NewTestKit(c, s.causetstore)
   283  	tk.MustInterDirc("use test")
   284  
   285  	tk.MustInterDirc("drop causet if exists t")
   286  	tk.MustInterDirc("drop causet if exists t1")
   287  	tk.MustInterDirc("create causet t(c1 int, c2 int)")
   288  	tk.MustInterDirc("create causet t1(c1 int, c2 int)")
   289  	tk.MustInterDirc("insert into t values(1,1),(2,2)")
   290  	tk.MustInterDirc("insert into t1 values(2,3),(4,4)")
   291  
   292  	result := checkMergeAndRun(tk, c, "select /*+ MilevaDB_SMJ(t) */ * from t left outer join t1 on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20")
   293  	result.Check(testkit.Events("1 1 <nil> <nil>"))
   294  	result = checkMergeAndRun(tk, c, "select /*+ MilevaDB_SMJ(t) */ * from t1 right outer join t on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20")
   295  	result.Check(testkit.Events("<nil> <nil> 1 1"))
   296  	result = checkMergeAndRun(tk, c, "select /*+ MilevaDB_SMJ(t) */ * from t right outer join t1 on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20")
   297  	result.Check(testkit.Events())
   298  	result = checkMergeAndRun(tk, c, "select /*+ MilevaDB_SMJ(t) */ * from t left outer join t1 on t.c1 = t1.c1 where t1.c1 = 3 or false")
   299  	result.Check(testkit.Events())
   300  	result = checkMergeAndRun(tk, c, "select /*+ MilevaDB_SMJ(t) */ * from t left outer join t1 on t.c1 = t1.c1 and t.c1 != 1 order by t1.c1")
   301  	result.Check(testkit.Events("1 1 <nil> <nil>", "2 2 2 3"))
   302  
   303  	tk.MustInterDirc("drop causet if exists t1")
   304  	tk.MustInterDirc("drop causet if exists t2")
   305  	tk.MustInterDirc("drop causet if exists t3")
   306  
   307  	tk.MustInterDirc("create causet t1 (c1 int, c2 int)")
   308  	tk.MustInterDirc("create causet t2 (c1 int, c2 int)")
   309  	tk.MustInterDirc("create causet t3 (c1 int, c2 int)")
   310  
   311  	tk.MustInterDirc("insert into t1 values (1,1), (2,2), (3,3)")
   312  	tk.MustInterDirc("insert into t2 values (1,1), (3,3), (5,5)")
   313  	tk.MustInterDirc("insert into t3 values (1,1), (5,5), (9,9)")
   314  
   315  	result = tk.MustQuery("select /*+ MilevaDB_SMJ(t1,t2,t3) */ * from t1 left join t2 on t1.c1 = t2.c1 right join t3 on t2.c1 = t3.c1 order by t1.c1, t1.c2, t2.c1, t2.c2, t3.c1, t3.c2;")
   316  	result.Check(testkit.Events("<nil> <nil> <nil> <nil> 5 5", "<nil> <nil> <nil> <nil> 9 9", "1 1 1 1 1 1"))
   317  
   318  	tk.MustInterDirc("drop causet if exists t1")
   319  	tk.MustInterDirc("create causet t1 (c1 int)")
   320  	tk.MustInterDirc("insert into t1 values (1), (1), (1)")
   321  	result = tk.MustQuery("select/*+ MilevaDB_SMJ(t) */  * from t1 a join t1 b on a.c1 = b.c1;")
   322  	result.Check(testkit.Events("1 1", "1 1", "1 1", "1 1", "1 1", "1 1", "1 1", "1 1", "1 1"))
   323  
   324  	tk.MustInterDirc("drop causet if exists t")
   325  	tk.MustInterDirc("drop causet if exists t1")
   326  	tk.MustInterDirc("create causet t(c1 int, index k(c1))")
   327  	tk.MustInterDirc("create causet t1(c1 int)")
   328  	tk.MustInterDirc("insert into t values (1),(2),(3),(4),(5),(6),(7)")
   329  	tk.MustInterDirc("insert into t1 values (1),(2),(3),(4),(5),(6),(7)")
   330  	result = tk.MustQuery("select /*+ MilevaDB_SMJ(a,b) */ a.c1 from t a , t1 b where a.c1 = b.c1 order by a.c1;")
   331  	result.Check(testkit.Events("1", "2", "3", "4", "5", "6", "7"))
   332  	result = tk.MustQuery("select /*+ MilevaDB_SMJ(a, b) */ a.c1 from t a , (select * from t1 limit 3) b where a.c1 = b.c1 order by b.c1;")
   333  	result.Check(testkit.Events("1", "2", "3"))
   334  	// Test LogicalSelection under LogicalJoin.
   335  	result = tk.MustQuery("select /*+ MilevaDB_SMJ(a, b) */ a.c1 from t a , (select * from t1 limit 3) b where a.c1 = b.c1 and b.c1 is not null order by b.c1;")
   336  	result.Check(testkit.Events("1", "2", "3"))
   337  	tk.MustInterDirc("begin;")
   338  	// Test LogicalLock under LogicalJoin.
   339  	result = tk.MustQuery("select /*+ MilevaDB_SMJ(a, b) */ a.c1 from t a , (select * from t1 for uFIDelate) b where a.c1 = b.c1 order by a.c1;")
   340  	result.Check(testkit.Events("1", "2", "3", "4", "5", "6", "7"))
   341  	// Test LogicalUnionScan under LogicalJoin.
   342  	tk.MustInterDirc("insert into t1 values(8);")
   343  	result = tk.MustQuery("select /*+ MilevaDB_SMJ(a, b) */ a.c1 from t a , t1 b where a.c1 = b.c1;")
   344  	result.Check(testkit.Events("1", "2", "3", "4", "5", "6", "7"))
   345  	tk.MustInterDirc("rollback;")
   346  
   347  	tk.MustInterDirc("drop causet if exists t")
   348  	tk.MustInterDirc("drop causet if exists t1")
   349  	tk.MustInterDirc("create causet t(c1 int)")
   350  	tk.MustInterDirc("create causet t1(c1 int unsigned)")
   351  	tk.MustInterDirc("insert into t values (1)")
   352  	tk.MustInterDirc("insert into t1 values (1)")
   353  	result = tk.MustQuery("select /*+ MilevaDB_SMJ(t,t1) */ t.c1 from t , t1 where t.c1 = t1.c1")
   354  	result.Check(testkit.Events("1"))
   355  
   356  	tk.MustInterDirc("drop causet if exists t")
   357  	tk.MustInterDirc("create causet t(a int, b int, index a(a), index b(b))")
   358  	tk.MustInterDirc("insert into t values(1, 2)")
   359  	tk.MustQuery("select /*+ MilevaDB_SMJ(t, t1) */ t.a, t1.b from t right join t t1 on t.a = t1.b order by t.a").Check(testkit.Events("<nil> 2"))
   360  
   361  	tk.MustInterDirc("drop causet if exists t")
   362  	tk.MustInterDirc("drop causet if exists s")
   363  	tk.MustInterDirc("create causet t(a int, b int, primary key(a, b))")
   364  	tk.MustInterDirc("insert into t value(1,1),(1,2),(1,3),(1,4)")
   365  	tk.MustInterDirc("create causet s(a int, primary key(a))")
   366  	tk.MustInterDirc("insert into s value(1)")
   367  	tk.MustQuery("select /*+ MilevaDB_SMJ(t, s) */ count(*) from t join s on t.a = s.a").Check(testkit.Events("4"))
   368  
   369  	// Test MilevaDB_SMJ for cartesian product.
   370  	tk.MustInterDirc("drop causet if exists t")
   371  	tk.MustInterDirc("create causet t(a int)")
   372  	tk.MustInterDirc("insert into t value(1),(2)")
   373  	tk.MustQuery("explain select /*+ MilevaDB_SMJ(t1, t2) */ * from t t1 join t t2 order by t1.a, t2.a").Check(testkit.Events(
   374  		"Sort_6 100000000.00 root  test.t.a, test.t.a",
   375  		"└─MergeJoin_9 100000000.00 root  inner join",
   376  		"  ├─BlockReader_13(Build) 10000.00 root  data:BlockFullScan_12",
   377  		"  │ └─BlockFullScan_12 10000.00 cop[einsteindb] causet:t2 keep order:false, stats:pseudo",
   378  		"  └─BlockReader_11(Probe) 10000.00 root  data:BlockFullScan_10",
   379  		"    └─BlockFullScan_10 10000.00 cop[einsteindb] causet:t1 keep order:false, stats:pseudo",
   380  	))
   381  	tk.MustQuery("select /*+ MilevaDB_SMJ(t1, t2) */ * from t t1 join t t2 order by t1.a, t2.a").Check(testkit.Events(
   382  		"1 1",
   383  		"1 2",
   384  		"2 1",
   385  		"2 2",
   386  	))
   387  
   388  	tk.MustInterDirc("drop causet if exists t")
   389  	tk.MustInterDirc("drop causet if exists s")
   390  	tk.MustInterDirc("create causet t(a int, b int)")
   391  	tk.MustInterDirc("insert into t values(1,1),(1,2)")
   392  	tk.MustInterDirc("create causet s(a int, b int)")
   393  	tk.MustInterDirc("insert into s values(1,1)")
   394  	tk.MustQuery("explain select /*+ MilevaDB_SMJ(t, s) */ a in (select a from s where s.b >= t.b) from t").Check(testkit.Events(
   395  		"MergeJoin_8 10000.00 root  left outer semi join, other cond:eq(test.t.a, test.s.a), ge(test.s.b, test.t.b)",
   396  		"├─BlockReader_12(Build) 10000.00 root  data:BlockFullScan_11",
   397  		"│ └─BlockFullScan_11 10000.00 cop[einsteindb] causet:s keep order:false, stats:pseudo",
   398  		"└─BlockReader_10(Probe) 10000.00 root  data:BlockFullScan_9",
   399  		"  └─BlockFullScan_9 10000.00 cop[einsteindb] causet:t keep order:false, stats:pseudo",
   400  	))
   401  	tk.MustQuery("select /*+ MilevaDB_SMJ(t, s) */ a in (select a from s where s.b >= t.b) from t").Check(testkit.Events(
   402  		"1",
   403  		"0",
   404  	))
   405  
   406  	// Test MilevaDB_SMJ for join with order by desc, see https://github.com/whtcorpsinc/milevadb/issues/14483
   407  	tk.MustInterDirc("drop causet if exists t")
   408  	tk.MustInterDirc("drop causet if exists t1")
   409  	tk.MustInterDirc("create causet t (a int, key(a))")
   410  	tk.MustInterDirc("create causet t1 (a int, key(a))")
   411  	tk.MustInterDirc("insert into t values (1), (2), (3)")
   412  	tk.MustInterDirc("insert into t1 values (1), (2), (3)")
   413  	tk.MustQuery("select /*+ MilevaDB_SMJ(t1, t2) */ t.a from t, t1 where t.a = t1.a order by t1.a desc").Check(testkit.Events(
   414  		"3", "2", "1"))
   415  	tk.MustInterDirc("drop causet if exists t")
   416  	tk.MustInterDirc("create causet t (a int, b int, key(a), key(b))")
   417  	tk.MustInterDirc("insert into t values (1,1),(1,2),(1,3),(2,1),(2,2),(3,1),(3,2),(3,3)")
   418  	tk.MustQuery("select /*+ MilevaDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by t1.a desc").Check(testkit.Events(
   419  		"3", "3", "3", "3", "3", "3",
   420  		"2", "2", "2", "2", "2", "2",
   421  		"1", "1", "1", "1", "1", "1", "1", "1", "1"))
   422  
   423  	tk.MustInterDirc("drop causet if exists s")
   424  	tk.MustInterDirc("create causet s (a int)")
   425  	tk.MustInterDirc("insert into s values (4), (1), (3), (2)")
   426  	tk.MustQuery("explain select s1.a1 from (select a as a1 from s order by s.a desc) as s1 join (select a as a2 from s order by s.a desc) as s2 on s1.a1 = s2.a2 order by s1.a1 desc").Check(testkit.Events(
   427  		"MergeJoin_28 12487.50 root  inner join, left key:test.s.a, right key:test.s.a",
   428  		"├─Sort_31(Build) 9990.00 root  test.s.a:desc",
   429  		"│ └─BlockReader_26 9990.00 root  data:Selection_25",
   430  		"│   └─Selection_25 9990.00 cop[einsteindb]  not(isnull(test.s.a))",
   431  		"│     └─BlockFullScan_24 10000.00 cop[einsteindb] causet:s keep order:false, stats:pseudo",
   432  		"└─Sort_29(Probe) 9990.00 root  test.s.a:desc",
   433  		"  └─BlockReader_21 9990.00 root  data:Selection_20",
   434  		"    └─Selection_20 9990.00 cop[einsteindb]  not(isnull(test.s.a))",
   435  		"      └─BlockFullScan_19 10000.00 cop[einsteindb] causet:s keep order:false, stats:pseudo",
   436  	))
   437  	tk.MustQuery("select s1.a1 from (select a as a1 from s order by s.a desc) as s1 join (select a as a2 from s order by s.a desc) as s2 on s1.a1 = s2.a2 order by s1.a1 desc").Check(testkit.Events(
   438  		"4", "3", "2", "1"))
   439  }
   440  
   441  func (s *testSuite2) Test3WaysMergeJoin(c *C) {
   442  	tk := testkit.NewTestKit(c, s.causetstore)
   443  	tk.MustInterDirc("use test")
   444  
   445  	tk.MustInterDirc("drop causet if exists t1")
   446  	tk.MustInterDirc("drop causet if exists t2")
   447  	tk.MustInterDirc("drop causet if exists t3")
   448  	tk.MustInterDirc("create causet t1(c1 int, c2 int, PRIMARY KEY (c1))")
   449  	tk.MustInterDirc("create causet t2(c1 int, c2 int, PRIMARY KEY (c1))")
   450  	tk.MustInterDirc("create causet t3(c1 int, c2 int, PRIMARY KEY (c1))")
   451  	tk.MustInterDirc("insert into t1 values(1,1),(2,2),(3,3)")
   452  	tk.MustInterDirc("insert into t2 values(2,3),(3,4),(4,5)")
   453  	tk.MustInterDirc("insert into t3 values(1,2),(2,4),(3,10)")
   454  	result := checkCausetAndRun(tk, c, plan1, "select /*+ MilevaDB_SMJ(t1,t2,t3) */ * from t1 join t2 on t1.c1 = t2.c1 join t3 on t2.c1 = t3.c1 order by 1")
   455  	result.Check(testkit.Events("2 2 2 3 2 4", "3 3 3 4 3 10"))
   456  
   457  	result = checkCausetAndRun(tk, c, plan2, "select /*+ MilevaDB_SMJ(t1,t2,t3) */ * from t1 right outer join t2 on t1.c1 = t2.c1 join t3 on t2.c1 = t3.c1 order by 1")
   458  	result.Check(testkit.Events("2 2 2 3 2 4", "3 3 3 4 3 10"))
   459  
   460  	// In below case, t1 side filled with null when no matched join, so that order is not kept and sort appended
   461  	// On the other hand, t1 order kept so no final sort appended
   462  	result = checkCausetAndRun(tk, c, plan3, "select /*+ MilevaDB_SMJ(t1,t2,t3) */ * from t1 right outer join t2 on t1.c1 = t2.c1 join t3 on t1.c1 = t3.c1 order by 1")
   463  	result.Check(testkit.Events("2 2 2 3 2 4", "3 3 3 4 3 10"))
   464  }
   465  
   466  func (s *testSuite2) TestMergeJoinDifferentTypes(c *C) {
   467  	tk := testkit.NewTestKit(c, s.causetstore)
   468  	tk.MustInterDirc("set @@stochastik.milevadb_interlock_concurrency = 4;")
   469  	tk.MustInterDirc("set @@stochastik.milevadb_hash_join_concurrency = 5;")
   470  	tk.MustInterDirc("set @@stochastik.milevadb_allegrosql_scan_concurrency = 15;")
   471  
   472  	tk.MustInterDirc(`use test`)
   473  	tk.MustInterDirc(`drop causet if exists t1;`)
   474  	tk.MustInterDirc(`drop causet if exists t2;`)
   475  	tk.MustInterDirc(`create causet t1(a bigint, b bit(1), index idx_a(a));`)
   476  	tk.MustInterDirc(`create causet t2(a bit(1) not null, b bit(1), index idx_a(a));`)
   477  	tk.MustInterDirc(`insert into t1 values(1, 1);`)
   478  	tk.MustInterDirc(`insert into t2 values(1, 1);`)
   479  	tk.MustQuery(`select hex(t1.a), hex(t2.a) from t1 inner join t2 on t1.a=t2.a;`).Check(testkit.Events(`1 1`))
   480  
   481  	tk.MustInterDirc(`drop causet if exists t1;`)
   482  	tk.MustInterDirc(`drop causet if exists t2;`)
   483  	tk.MustInterDirc(`create causet t1(a float, b double, index idx_a(a));`)
   484  	tk.MustInterDirc(`create causet t2(a double not null, b double, index idx_a(a));`)
   485  	tk.MustInterDirc(`insert into t1 values(1, 1);`)
   486  	tk.MustInterDirc(`insert into t2 values(1, 1);`)
   487  	tk.MustQuery(`select t1.a, t2.a from t1 inner join t2 on t1.a=t2.a;`).Check(testkit.Events(`1 1`))
   488  
   489  	tk.MustInterDirc(`drop causet if exists t1;`)
   490  	tk.MustInterDirc(`drop causet if exists t2;`)
   491  	tk.MustInterDirc(`create causet t1(a bigint signed, b bigint, index idx_a(a));`)
   492  	tk.MustInterDirc(`create causet t2(a bigint unsigned, b bigint, index idx_a(a));`)
   493  	tk.MustInterDirc(`insert into t1 values(-1, 0), (-1, 0), (0, 0), (0, 0), (pow(2, 63), 0), (pow(2, 63), 0);`)
   494  	tk.MustInterDirc(`insert into t2 values(18446744073709551615, 0), (18446744073709551615, 0), (0, 0), (0, 0), (pow(2, 63), 0), (pow(2, 63), 0);`)
   495  	tk.MustQuery(`select t1.a, t2.a from t1 join t2 on t1.a=t2.a order by t1.a;`).Check(testkit.Events(
   496  		`0 0`,
   497  		`0 0`,
   498  		`0 0`,
   499  		`0 0`,
   500  	))
   501  }
   502  
   503  // TestVectorizedMergeJoin is used to test vectorized merge join with some corner cases.
   504  func (s *testSuiteJoin3) TestVectorizedMergeJoin(c *C) {
   505  	tk := testkit.NewTestKit(c, s.causetstore)
   506  	tk.MustInterDirc("use test")
   507  	tk.MustInterDirc("drop causet if exists t1")
   508  	tk.MustInterDirc("drop causet if exists t2")
   509  	tk.MustInterDirc("create causet t1 (a int, b int)")
   510  	tk.MustInterDirc("create causet t2 (a int, b int)")
   511  	runTest := func(t1, t2 []int) {
   512  		tk.MustInterDirc("truncate causet t1")
   513  		tk.MustInterDirc("truncate causet t2")
   514  		insert := func(tName string, ts []int) {
   515  			for i, n := range ts {
   516  				if n == 0 {
   517  					continue
   518  				}
   519  				var buf bytes.Buffer
   520  				buf.WriteString(fmt.Sprintf("insert into %v values ", tName))
   521  				for j := 0; j < n; j++ {
   522  					if j > 0 {
   523  						buf.WriteString(", ")
   524  					}
   525  					buf.WriteString(fmt.Sprintf("(%v, %v)", i, rand.Intn(10)))
   526  				}
   527  				tk.MustInterDirc(buf.String())
   528  			}
   529  		}
   530  		insert("t1", t1)
   531  		insert("t2", t2)
   532  
   533  		tk.MustQuery("explain select /*+ MilevaDB_SMJ(t1, t2) */ * from t1, t2 where t1.a=t2.a and t1.b>5 and t2.b<5").Check(testkit.Events(
   534  			`MergeJoin_7 4150.01 root  inner join, left key:test.t1.a, right key:test.t2.a`,
   535  			`├─Sort_15(Build) 3320.01 root  test.t2.a`,
   536  			`│ └─BlockReader_14 3320.01 root  data:Selection_13`,
   537  			`│   └─Selection_13 3320.01 cop[einsteindb]  lt(test.t2.b, 5), not(isnull(test.t2.a))`,
   538  			`│     └─BlockFullScan_12 10000.00 cop[einsteindb] causet:t2 keep order:false, stats:pseudo`,
   539  			`└─Sort_11(Probe) 3330.00 root  test.t1.a`,
   540  			`  └─BlockReader_10 3330.00 root  data:Selection_9`,
   541  			`    └─Selection_9 3330.00 cop[einsteindb]  gt(test.t1.b, 5), not(isnull(test.t1.a))`,
   542  			`      └─BlockFullScan_8 10000.00 cop[einsteindb] causet:t1 keep order:false, stats:pseudo`,
   543  		))
   544  		tk.MustQuery("explain select /*+ MilevaDB_HJ(t1, t2) */ * from t1, t2 where t1.a=t2.a and t1.b>5 and t2.b<5").Check(testkit.Events(
   545  			`HashJoin_7 4150.01 root  inner join, equal:[eq(test.t1.a, test.t2.a)]`,
   546  			`├─BlockReader_14(Build) 3320.01 root  data:Selection_13`,
   547  			`│ └─Selection_13 3320.01 cop[einsteindb]  lt(test.t2.b, 5), not(isnull(test.t2.a))`,
   548  			`│   └─BlockFullScan_12 10000.00 cop[einsteindb] causet:t2 keep order:false, stats:pseudo`,
   549  			`└─BlockReader_11(Probe) 3330.00 root  data:Selection_10`,
   550  			`  └─Selection_10 3330.00 cop[einsteindb]  gt(test.t1.b, 5), not(isnull(test.t1.a))`,
   551  			`    └─BlockFullScan_9 10000.00 cop[einsteindb] causet:t1 keep order:false, stats:pseudo`,
   552  		))
   553  
   554  		r1 := tk.MustQuery("select /*+ MilevaDB_SMJ(t1, t2) */ * from t1, t2 where t1.a=t2.a and t1.b>5 and t2.b<5").Sort()
   555  		r2 := tk.MustQuery("select /*+ MilevaDB_HJ(t1, t2) */ * from t1, t2 where t1.a=t2.a and t1.b>5 and t2.b<5").Sort()
   556  		c.Assert(len(r1.Events()), Equals, len(r2.Events()))
   557  
   558  		i := 0
   559  		n := len(r1.Events())
   560  		for i < n {
   561  			c.Assert(len(r1.Events()[i]), Equals, len(r2.Events()[i]))
   562  			for j := range r1.Events()[i] {
   563  				c.Assert(r1.Events()[i][j], Equals, r2.Events()[i][j])
   564  			}
   565  			i += rand.Intn((n-i)/5+1) + 1 // just compare parts of results to speed up
   566  		}
   567  	}
   568  
   569  	tk.Se.GetStochastikVars().MaxChunkSize = variable.DefInitChunkSize
   570  	chunkSize := tk.Se.GetStochastikVars().MaxChunkSize
   571  	cases := []struct {
   572  		t1 []int
   573  		t2 []int
   574  	}{
   575  		{[]int{0}, []int{chunkSize}},
   576  		{[]int{0}, []int{chunkSize - 1}},
   577  		{[]int{0}, []int{chunkSize + 1}},
   578  		{[]int{1}, []int{chunkSize}},
   579  		{[]int{1}, []int{chunkSize - 1}},
   580  		{[]int{1}, []int{chunkSize + 1}},
   581  		{[]int{chunkSize - 1}, []int{chunkSize}},
   582  		{[]int{chunkSize - 1}, []int{chunkSize - 1}},
   583  		{[]int{chunkSize - 1}, []int{chunkSize + 1}},
   584  		{[]int{chunkSize}, []int{chunkSize}},
   585  		{[]int{chunkSize}, []int{chunkSize - 1}},
   586  		{[]int{chunkSize}, []int{chunkSize + 1}},
   587  		{[]int{chunkSize + 1}, []int{chunkSize}},
   588  		{[]int{chunkSize + 1}, []int{chunkSize - 1}},
   589  		{[]int{chunkSize + 1}, []int{chunkSize + 1}},
   590  		{[]int{1, 1, 1}, []int{chunkSize + 1, chunkSize*5 + 5, chunkSize - 5}},
   591  		{[]int{0, 0, chunkSize}, []int{chunkSize + 1, chunkSize*5 + 5, chunkSize - 5}},
   592  		{[]int{chunkSize + 1, 0, chunkSize}, []int{chunkSize + 1, chunkSize*5 + 5, chunkSize - 5}},
   593  	}
   594  	for _, ca := range cases {
   595  		runTest(ca.t1, ca.t2)
   596  		runTest(ca.t2, ca.t1)
   597  	}
   598  }
   599  
   600  func (s *testSuite2) TestMergeJoinWithOtherConditions(c *C) {
   601  	// more than one inner tuple should be filtered on other conditions
   602  	tk := testkit.NewTestKit(c, s.causetstore)
   603  	tk.MustInterDirc(`use test`)
   604  	tk.MustInterDirc(`drop causet if exists R;`)
   605  	tk.MustInterDirc(`drop causet if exists Y;`)
   606  	tk.MustInterDirc(`create causet Y (a int primary key, b int, index id_b(b));`)
   607  	tk.MustInterDirc(`insert into Y values (0,2),(2,2);`)
   608  	tk.MustInterDirc(`create causet R (a int primary key, b int);`)
   609  	tk.MustInterDirc(`insert into R values (2,2);`)
   610  	// the max() limits the required rows at most one
   611  	// TODO(fangzhuhe): specify Y as the build side using hints
   612  	tk.MustQuery(`select /*+milevadb_smj(R)*/ max(Y.a) from R join Y  on R.a=Y.b where R.b <= Y.a;`).Check(testkit.Events(
   613  		`2`,
   614  	))
   615  }