From f43de91e445ea6d5f54d7ed530b4f77aefad0580 Mon Sep 17 00:00:00 2001 From: Yuanjia Zhang Date: Mon, 21 Feb 2022 13:03:41 +0800 Subject: [PATCH] cherry pick #32440 to release-5.1 Signed-off-by: ti-srebot --- planner/core/integration_test.go | 39 +++++++ planner/core/prepare_test.go | 193 +++++++++++++++++++++++++++++++ util/ranger/points.go | 6 +- 3 files changed, 237 insertions(+), 1 deletion(-) diff --git a/planner/core/integration_test.go b/planner/core/integration_test.go index 624ff5ea84906..10797154218f6 100644 --- a/planner/core/integration_test.go +++ b/planner/core/integration_test.go @@ -3195,6 +3195,45 @@ func (s *testIntegrationSuite) TestIssue22892(c *C) { tk.MustQuery("select * from t2 where a not between 1 and 2;").Check(testkit.Rows("0")) } +<<<<<<< HEAD +======= +func (s *testIntegrationSuite) TestIssue26719(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec(`create table tx (a int) partition by range (a) (partition p0 values less than (10), partition p1 values less than (20))`) + tk.MustExec(`insert into tx values (1)`) + tk.MustExec("set @@tidb_partition_prune_mode='dynamic'") + + tk.MustExec(`begin`) + tk.MustExec(`delete from tx where a in (1)`) + tk.MustQuery(`select * from tx PARTITION(p0)`).Check(testkit.Rows()) + tk.MustQuery(`select * from tx`).Check(testkit.Rows()) + tk.MustExec(`rollback`) +} + +func (s *testIntegrationSuite) TestIssue32428(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("create table `t1` (`a` enum('aa') DEFAULT NULL, KEY `k` (`a`))") + tk.MustExec("insert into t1 values('aa')") + tk.MustExec("insert into t1 values(null)") + tk.MustQuery("select a from t1 where a<=>'aa'").Check(testkit.Rows("aa")) + tk.MustQuery("select a from t1 where a<=>null").Check(testkit.Rows("")) + + tk.MustExec(`CREATE TABLE IDT_MULTI15860STROBJSTROBJ ( + COL1 enum('aa') DEFAULT NULL, + COL2 int(41) DEFAULT NULL, + COL3 year(4) DEFAULT NULL, + KEY U_M_COL4 (COL1,COL2), + KEY U_M_COL5 (COL3,COL2))`) + tk.MustExec(`insert into IDT_MULTI15860STROBJSTROBJ values("aa", 1013610488, 1982)`) + tk.MustQuery(`SELECT * FROM IDT_MULTI15860STROBJSTROBJ t1 RIGHT JOIN IDT_MULTI15860STROBJSTROBJ t2 ON t1.col1 <=> t2.col1 where t1.col1 is null and t2.col1 = "aa"`).Check(testkit.Rows()) // empty result + tk.MustExec(`prepare stmt from "SELECT * FROM IDT_MULTI15860STROBJSTROBJ t1 RIGHT JOIN IDT_MULTI15860STROBJSTROBJ t2 ON t1.col1 <=> t2.col1 where t1.col1 is null and t2.col1 = ?"`) + tk.MustExec(`set @a="aa"`) + tk.MustQuery(`execute stmt using @a`).Check(testkit.Rows()) // empty result +} + +>>>>>>> 1b04c3b05... planner: fix wrong range calculation for Nulleq function on Enum values (#32440) func (s *testIntegrationSerialSuite) TestPushDownProjectionForTiFlash(c *C) { tk := testkit.NewTestKit(c, s.store) tk.MustExec("use test") diff --git a/planner/core/prepare_test.go b/planner/core/prepare_test.go index f243d54907905..1a25b29301a10 100644 --- a/planner/core/prepare_test.go +++ b/planner/core/prepare_test.go @@ -1194,7 +1194,200 @@ func (s *testPlanSerialSuite) TestIssue23671(c *C) { tk.MustQuery("execute s1 using @a, @b, @c").Check(testkit.Rows("1 1")) tk.MustExec("set @a=1, @b=1, @c=10") tk.MustQuery("execute s1 using @a, @b, @c").Check(testkit.Rows("1 1", "2 2")) +<<<<<<< HEAD tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) +======= + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) +} + +func TestIssue29296(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := core.PreparedPlanCacheEnabled() + defer core.SetPreparedPlanCache(orgEnable) + core.SetPreparedPlanCache(true) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ + PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), + }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) + + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists UK_MU14722`) + tk.MustExec(`CREATE TABLE UK_MU14722 ( + COL1 tinytext DEFAULT NULL, + COL2 tinyint(16) DEFAULT NULL, + COL3 datetime DEFAULT NULL, + COL4 int(11) DEFAULT NULL, + UNIQUE KEY U_M_COL (COL1(10)), + UNIQUE KEY U_M_COL2 (COL2), + UNIQUE KEY U_M_COL3 (COL3))`) + tk.MustExec(`insert into UK_MU14722 values("輮睅麤敜溺她晁瀪襄頮鹛涓誗钷廔筪惌嶙鎢塴", -121, "3383-02-19 07:58:28" , -639457963), + ("偧孇鱓鼂瘠钻篝醗時鷷聽箌磇砀玸眞扦鸇祈灇", 127, "7902-03-05 08:54:04", -1094128660), + ("浀玡慃淛漉围甧鴎史嬙砊齄w章炢忲噑硓哈樘", -127, "5813-04-16 03:07:20", -333397107), + ("鑝粼啎鸼贖桖弦簼赭蠅鏪鐥蕿捐榥疗耹岜鬓槊", -117, "7753-11-24 10:14:24", 654872077)`) + tk.MustExec(`prepare stmt from 'SELECT * FROM UK_MU14722 WHERE col2 > ? OR col2 BETWEEN ? AND ? ORDER BY COL2 + ? LIMIT 3'`) + tk.MustExec(`set @a=30410, @b=3937, @c=22045, @d=-4374`) + tk.MustQuery(`execute stmt using @a,@b,@c,@d`).Check(testkit.Rows()) + tk.MustExec(`set @a=127, @b=127, @c=127, @d=127`) + tk.MustQuery(`execute stmt using @a,@b,@c,@d`).Check(testkit.Rows(`偧孇鱓鼂瘠钻篝醗時鷷聽箌磇砀玸眞扦鸇祈灇 127 7902-03-05 08:54:04 -1094128660`)) +} + +func TestIssue28246(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := core.PreparedPlanCacheEnabled() + defer core.SetPreparedPlanCache(orgEnable) + core.SetPreparedPlanCache(true) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ + PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), + }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) + + tk.MustExec("use test") + tk.MustExec("drop table if exists PK_AUTO_RANDOM9111;") + tk.MustExec("CREATE TABLE `PK_AUTO_RANDOM9111` ( `COL1` bigint(45) NOT NULL , `COL2` varchar(20) DEFAULT NULL, `COL4` datetime DEFAULT NULL, `COL3` bigint(20) DEFAULT NULL, `COL5` float DEFAULT NULL, PRIMARY KEY (`COL1`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;") + tk.MustExec("insert into PK_AUTO_RANDOM9111(col1) values (-9223372036854775808), (9223372036854775807);") + tk.MustExec("set @a=9223372036854775807, @b=1") + tk.MustExec(`prepare stmt from 'select min(col1) from PK_AUTO_RANDOM9111 where col1 > ?;';`) + tk.MustQuery("execute stmt using @a").Check(testkit.Rows("")) + // The plan contains the tableDual, so it will not be cached. + tk.MustQuery("execute stmt using @a").Check(testkit.Rows("")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk.MustQuery("execute stmt using @b").Check(testkit.Rows("9223372036854775807")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk.MustQuery("execute stmt using @a").Check(testkit.Rows("")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) +} + +func TestIssue29805(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := core.PreparedPlanCacheEnabled() + defer core.SetPreparedPlanCache(orgEnable) + core.SetPreparedPlanCache(true) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ + PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), + }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) + + tk.MustExec("use test") + tk.MustExec("set tidb_enable_clustered_index=on;") + tk.MustExec("drop table if exists PK_TCOLLATION10197;") + tk.MustExec("CREATE TABLE `PK_TCOLLATION10197` (`COL1` char(1) NOT NULL, PRIMARY KEY (`COL1`(1)) /*T![clustered_index] CLUSTERED */) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;") + tk.MustExec("insert into PK_TCOLLATION10197 values('龺');") + tk.MustExec("set @a='畻', @b='龺';") + tk.MustExec(`prepare stmt from 'select/*+ hash_agg() */ count(distinct col1) from PK_TCOLLATION10197 where col1 > ?;';`) + tk.MustQuery("execute stmt using @a").Check(testkit.Rows("1")) + tk.MustQuery("execute stmt using @b").Check(testkit.Rows("0")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + + tk.MustExec(`prepare stmt from 'select/*+ hash_agg() */ count(distinct col1) from PK_TCOLLATION10197 where col1 > ?;';`) + tk.MustQuery("execute stmt using @b").Check(testkit.Rows("0")) + + tk.MustQuery("select/*+ hash_agg() */ count(distinct col1) from PK_TCOLLATION10197 where col1 > '龺';").Check(testkit.Rows("0")) +} + +func TestIssue29993(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := core.PreparedPlanCacheEnabled() + defer core.SetPreparedPlanCache(orgEnable) + core.SetPreparedPlanCache(true) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ + PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), + }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) + + tk.MustExec("use test") + + // test PointGet + cluster index + tk.MustExec("set tidb_enable_clustered_index=on;") + tk.MustExec("drop table if exists t;") + tk.MustExec("CREATE TABLE `t` (`COL1` enum('a', 'b') NOT NULL PRIMARY KEY, col2 int) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;") + tk.MustExec("insert into t values('a', 1), ('b', 2);") + tk.MustExec("set @a='a', @b='b', @z='z';") + tk.MustExec(`prepare stmt from 'select col1 from t where col1 = ? and col2 in (1, 2);';`) + tk.MustQuery("execute stmt using @a").Check(testkit.Rows("a")) + tk.MustQuery("execute stmt using @b").Check(testkit.Rows("b")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery("execute stmt using @z").Check(testkit.Rows()) + // The length of range have been changed, so the plan can not be cached. + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk.MustQuery("execute stmt using @z").Check(testkit.Rows()) + + // test batchPointGet + cluster index + tk.MustExec("drop table if exists t;") + tk.MustExec("CREATE TABLE `t` (`COL1` enum('a', 'b') NOT NULL, col2 int, PRIMARY KEY(col1, col2)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;") + tk.MustExec("insert into t values('a', 1), ('b', 2);") + tk.MustExec("set @a='a', @b='b', @z='z';") + tk.MustExec(`prepare stmt from 'select col1 from t where (col1, col2) in ((?, 1));';`) + tk.MustQuery("execute stmt using @a").Check(testkit.Rows("a")) + tk.MustQuery("execute stmt using @b").Check(testkit.Rows()) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery("execute stmt using @z").Check(testkit.Rows()) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery("execute stmt using @z").Check(testkit.Rows()) + + // test PointGet + non cluster index + tk.MustExec("set tidb_enable_clustered_index=off;") + tk.MustExec("drop table if exists t;") + tk.MustExec("CREATE TABLE `t` (`COL1` enum('a', 'b') NOT NULL PRIMARY KEY, col2 int) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;") + tk.MustExec("insert into t values('a', 1), ('b', 2);") + tk.MustExec("set @a='a', @b='b', @z='z';") + tk.MustExec(`prepare stmt from 'select col1 from t where col1 = ? and col2 in (1, 2);';`) + tk.MustQuery("execute stmt using @a").Check(testkit.Rows("a")) + tk.MustQuery("execute stmt using @b").Check(testkit.Rows("b")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery("execute stmt using @z").Check(testkit.Rows()) + // The length of range have been changed, so the plan can not be cached. + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk.MustQuery("execute stmt using @z").Check(testkit.Rows()) + + // test batchPointGet + non cluster index + tk.MustExec("drop table if exists t;") + tk.MustExec("CREATE TABLE `t` (`COL1` enum('a', 'b') NOT NULL, col2 int, PRIMARY KEY(col1, col2)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;") + tk.MustExec("insert into t values('a', 1), ('b', 2);") + tk.MustExec("set @a='a', @b='b', @z='z';") + tk.MustExec(`prepare stmt from 'select col1 from t where (col1, col2) in ((?, 1));';`) + tk.MustQuery("execute stmt using @a").Check(testkit.Rows("a")) + tk.MustQuery("execute stmt using @b").Check(testkit.Rows()) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery("execute stmt using @z").Check(testkit.Rows()) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery("execute stmt using @z").Check(testkit.Rows()) +} + +func TestIssue30100(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := core.PreparedPlanCacheEnabled() + defer core.SetPreparedPlanCache(orgEnable) + core.SetPreparedPlanCache(true) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ + PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), + }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t(col1 enum('aa', 'bb'), col2 int, index(col1, col2));") + tk.MustExec("insert into t values('aa', 333);") + tk.MustExec(`prepare stmt from 'SELECT * FROM t t1 JOIN t t2 ON t1.col1 = t2.col1 WHERE t1.col1 <=> NULL';`) + 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 * FROM t t1 JOIN t t2 ON t1.col1 = t2.col1 WHERE t1.col1 <=> NULL and t2.col2 > ?';`) + tk.MustExec("set @a=0;") + tk.MustQuery("execute stmt using @a").Check(testkit.Rows()) + tk.MustQuery("execute stmt using @a").Check(testkit.Rows()) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) +>>>>>>> 1b04c3b05... planner: fix wrong range calculation for Nulleq function on Enum values (#32440) } func (s *testPlanSerialSuite) TestPartitionTable(c *C) { diff --git a/util/ranger/points.go b/util/ranger/points.go index 8030e7ad2bc99..591f7de6d2ca7 100644 --- a/util/ranger/points.go +++ b/util/ranger/points.go @@ -456,6 +456,10 @@ func handleEnumFromBinOp(sc *stmtctx.StatementContext, ft *types.FieldType, val res = append(res, &point{value: d, excl: false, start: false}) } + if op == ast.NullEQ && val.IsNull() { + res = append(res, &point{start: true}, &point{}) // null point + } + tmpEnum := types.Enum{} for i := 0; i <= len(ft.Elems); i++ { if i == 0 { @@ -484,7 +488,7 @@ func handleEnumFromBinOp(sc *stmtctx.StatementContext, ft *types.FieldType, val if v >= 0 { appendPointFunc(d) } - case ast.EQ: + case ast.EQ, ast.NullEQ: if v == 0 { appendPointFunc(d) }