Skip to content

Commit

Permalink
This is an automated cherry-pick of pingcap#40593
Browse files Browse the repository at this point in the history
Signed-off-by: ti-chi-bot <[email protected]>
  • Loading branch information
Dousir9 authored and ti-chi-bot committed Feb 8, 2023
1 parent ac6560f commit 8c4319c
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
70 changes: 70 additions & 0 deletions planner/core/plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/pingcap/tidb/config"
"github.com/pingcap/tidb/expression"
"github.com/pingcap/tidb/expression/aggregation"
"github.com/pingcap/tidb/kv"
"github.com/pingcap/tidb/parser/ast"
"github.com/pingcap/tidb/parser/model"
"github.com/pingcap/tidb/parser/mysql"
Expand Down Expand Up @@ -885,3 +886,72 @@ func TestNullEQConditionPlan(t *testing.T) {
{"Point_Get_5", "root", "handle:0"},
})
}
<<<<<<< HEAD
=======

// https://github.com/pingcap/tidb/issues/38304
// https://github.com/pingcap/tidb/issues/38654
func TestOuterJoinOnNull(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("CREATE TABLE t0(c0 BLOB(5), c1 BLOB(5));")
tk.MustExec("CREATE TABLE t1 (c0 BOOL);")
tk.MustExec("INSERT INTO t1 VALUES(false);")
tk.MustExec("INSERT INTO t0(c0, c1) VALUES ('>', true);")
tk.MustQuery("SELECT * FROM t0 LEFT OUTER JOIN t1 ON NULL; ").Check(testkit.Rows("> 1 <nil>"))
tk.MustQuery("SELECT NOT '2' =(t1.c0 AND t0.c1 IS NULL) FROM t0 LEFT OUTER JOIN t1 ON NULL; ").Check(testkit.Rows("1"))
tk.MustQuery("SELECT * FROM t0 LEFT JOIN t1 ON NULL WHERE NOT '2' =(t1.c0 AND t0.c1 IS NULL); ").Check(testkit.Rows("> 1 <nil>"))
tk.MustQuery("SELECT * FROM t0 LEFT JOIN t1 ON NULL WHERE t1.c0 or true; ").Check(testkit.Rows("> 1 <nil>"))
tk.MustQuery("SELECT * FROM t0 LEFT JOIN t1 ON NULL WHERE not(t1.c0 and false); ").Check(testkit.Rows("> 1 <nil>"))

tk.MustExec("CREATE TABLE t2(c0 INT);")
tk.MustExec("CREATE TABLE t3(c0 INT);")
tk.MustExec("INSERT INTO t3 VALUES (1);")
tk.MustQuery("SELECT ((NOT ('i'))AND(t2.c0)) IS NULL FROM t2 RIGHT JOIN t3 ON t3.c0;").Check(testkit.Rows("1"))
tk.MustQuery("SELECT * FROM t2 RIGHT JOIN t3 ON t2.c0 WHERE ((NOT ('i'))AND(t2.c0)) IS NULL;").Check(testkit.Rows("<nil> 1"))
}

func TestJSONPlanInExplain(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1(id int, key(id))")
tk.MustExec("create table t2(id int, key(id))")

var input []string
var output []struct {
SQL string
JSONPlan []*core.ExplainInfoForEncode
}
planSuiteData := core.GetJSONPlanSuiteData()
planSuiteData.LoadTestCases(t, &input, &output)

for i, test := range input {
resJSON := tk.MustQuery(test).Rows()
var res []*core.ExplainInfoForEncode
require.NoError(t, json.Unmarshal([]byte(resJSON[0][0].(string)), &res))
for j, expect := range output[i].JSONPlan {
require.Equal(t, expect.ID, res[j].ID)
require.Equal(t, expect.EstRows, res[j].EstRows)
require.Equal(t, expect.ActRows, res[j].ActRows)
require.Equal(t, expect.TaskType, res[j].TaskType)
require.Equal(t, expect.AccessObject, res[j].AccessObject)
require.Equal(t, expect.OperatorInfo, res[j].OperatorInfo)
}
}
}

func TestIssue40535(t *testing.T) {
store := testkit.CreateMockStore(t)
var cfg kv.InjectionConfig
tk := testkit.NewTestKit(t, kv.NewInjectedStore(store, &cfg))
tk.MustExec("use test;")
tk.MustExec("drop table if exists t1; drop table if exists t2;")
tk.MustExec("CREATE TABLE `t1`(`c1` bigint(20) NOT NULL DEFAULT '-2312745469307452950', `c2` datetime DEFAULT '5316-02-03 06:54:49', `c3` tinyblob DEFAULT NULL, PRIMARY KEY (`c1`) /*T![clustered_index] CLUSTERED */) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;")
tk.MustExec("CREATE TABLE `t2`(`c1` set('kn8pu','7et','vekx6','v3','liwrh','q14','1met','nnd5i','5o0','8cz','l') DEFAULT '7et,vekx6,liwrh,q14,1met', `c2` float DEFAULT '1.683167', KEY `k1` (`c2`,`c1`), KEY `k2` (`c2`)) ENGINE=InnoDB DEFAULT CHARSET=gbk COLLATE=gbk_chinese_ci;")
tk.MustExec("(select /*+ agg_to_cop()*/ locate(t1.c3, t1.c3) as r0, t1.c3 as r1 from t1 where not( IsNull(t1.c1)) order by r0,r1) union all (select concat_ws(',', t2.c2, t2.c1) as r0, t2.c1 as r1 from t2 order by r0, r1) order by 1 limit 273;")
require.Empty(t, tk.Session().LastMessage())
}
>>>>>>> 2aad38831e0 (planner: when pushing `topN` down below `proj`, check whether `topN.ByItems` contains a column(with ID=0) generated by `proj` (#40593))
14 changes: 14 additions & 0 deletions planner/core/rule_topn_push_down.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,20 @@ func (p *LogicalProjection) pushDownTopN(topN *LogicalTopN, opt *logicalOptimize
topN.ByItems = append(topN.ByItems[:i], topN.ByItems[i+1:]...)
}
}

// if topN.ByItems contains a column(with ID=0) generated by projection, projection will prevent the optimizer from pushing topN down.
for _, by := range topN.ByItems {
cols := expression.ExtractColumns(by.Expr)
for _, col := range cols {
if col.ID == 0 && p.Schema().Contains(col) {
// check whether the column is generated by projection
if !p.children[0].Schema().Contains(col) {
p.children[0] = p.children[0].pushDownTopN(nil, opt)
return topN.setChild(p, opt)
}
}
}
}
}
p.children[0] = p.children[0].pushDownTopN(topN, opt)
return p
Expand Down

0 comments on commit 8c4319c

Please sign in to comment.