diff --git a/planner/core/integration_test.go b/planner/core/integration_test.go index ab7c048c8b431..d517cee8133c5 100644 --- a/planner/core/integration_test.go +++ b/planner/core/integration_test.go @@ -4359,3 +4359,226 @@ func (s *testIntegrationSuite) TestIssue27797(c *C) { result = tk.MustQuery("select col2 from IDT_HP24172 where col1 = 8388607 and col1 in (select col1 from IDT_HP24172);") result.Check(testkit.Rows("")) } +<<<<<<< HEAD +======= + +func (s *testIntegrationSuite) TestIssue27949(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t27949") + tk.MustExec("create table t27949 (a int, b int, key(b))") + tk.MustQuery("explain format = 'brief' select * from t27949 where b=1").Check(testkit.Rows("IndexLookUp 10.00 root ", + "├─IndexRangeScan(Build) 10.00 cop[tikv] table:t27949, index:b(b) range:[1,1], keep order:false, stats:pseudo", + "└─TableRowIDScan(Probe) 10.00 cop[tikv] table:t27949 keep order:false, stats:pseudo")) + tk.MustExec("create global binding for select * from t27949 where b=1 using select * from t27949 ignore index(b) where b=1") + tk.MustQuery("explain format = 'brief' select * from t27949 where b=1").Check(testkit.Rows("TableReader 10.00 root data:Selection", + "└─Selection 10.00 cop[tikv] eq(test.t27949.b, 1)", + " └─TableFullScan 10000.00 cop[tikv] table:t27949 keep order:false, stats:pseudo")) + tk.MustExec("set @@sql_select_limit=100") + tk.MustQuery("explain format = 'brief' select * from t27949 where b=1").Check(testkit.Rows("Limit 10.00 root offset:0, count:100", + "└─TableReader 10.00 root data:Limit", + " └─Limit 10.00 cop[tikv] offset:0, count:100", + " └─Selection 10.00 cop[tikv] eq(test.t27949.b, 1)", + " └─TableFullScan 10000.00 cop[tikv] table:t27949 keep order:false, stats:pseudo")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, index idx_a(a));") + tk.MustExec("create binding for select * from t using select * from t use index(idx_a);") + tk.MustExec("select * from t;") + tk.MustQuery("select @@last_plan_from_binding;").Check(testkit.Rows("1")) + tk.MustExec("prepare stmt from 'select * from t';") + tk.MustExec("execute stmt;") + tk.MustQuery("select @@last_plan_from_binding;").Check(testkit.Rows("1")) +} + +func (s *testIntegrationSuite) TestIssue28154(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + defer func() { + tk.Exec("drop table if exists t") + }() + tk.MustExec("create table t(a TEXT)") + tk.MustExec("insert into t values('abc')") + result := tk.MustQuery("select * from t where from_base64('')") + result.Check(testkit.Rows()) + _, err := tk.Exec("update t set a = 'def' where from_base64('')") + c.Assert(err, NotNil) + c.Assert(err.Error(), Equals, "[types:1292]Truncated incorrect DOUBLE value: ''") + result = tk.MustQuery("select * from t where from_base64('invalidbase64')") + result.Check(testkit.Rows()) + tk.MustExec("update t set a = 'hig' where from_base64('invalidbase64')") + result = tk.MustQuery("select * from t where from_base64('test')") + result.Check(testkit.Rows()) + _, err = tk.Exec("update t set a = 'xyz' where from_base64('test')") + c.Assert(err, NotNil) + c.Assert(err, ErrorMatches, "\\[types:1292\\]Truncated incorrect DOUBLE value.*") + result = tk.MustQuery("select * from t") + result.Check(testkit.Rows("abc")) +} + +func (s *testIntegrationSerialSuite) TestRejectSortForMPP(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (id int, value decimal(6,3), name char(128))") + tk.MustExec("analyze table t") + + // Create virtual tiflash replica info. + dom := domain.GetDomain(tk.Se) + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + c.Assert(exists, IsTrue) + for _, tblInfo := range db.Tables { + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_opt_broadcast_join=0; set @@tidb_enforce_mpp=1;") + + var input []string + var output []struct { + SQL string + Plan []string + } + s.testData.GetTestCases(c, &input, &output) + for i, tt := range input { + s.testData.OnRecord(func() { + output[i].SQL = tt + output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + }) + res := tk.MustQuery(tt) + res.Check(testkit.Rows(output[i].Plan...)) + } +} + +func (s *testIntegrationSerialSuite) TestRegardNULLAsPoint(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + + tk.MustExec("drop table if exists tpk") + tk.MustExec(`create table tuk (a int, b int, c int, unique key (a, b, c))`) + tk.MustExec(`create table tik (a int, b int, c int, key (a, b, c))`) + for _, va := range []string{"NULL", "1"} { + for _, vb := range []string{"NULL", "1"} { + for _, vc := range []string{"NULL", "1"} { + tk.MustExec(fmt.Sprintf(`insert into tuk values (%v, %v, %v)`, va, vb, vc)) + tk.MustExec(fmt.Sprintf(`insert into tik values (%v, %v, %v)`, va, vb, vc)) + if va == "1" && vb == "1" && vc == "1" { + continue + } + // duplicated NULL rows + tk.MustExec(fmt.Sprintf(`insert into tuk values (%v, %v, %v)`, va, vb, vc)) + tk.MustExec(fmt.Sprintf(`insert into tik values (%v, %v, %v)`, va, vb, vc)) + } + } + } + + var input []string + var output []struct { + SQL string + PlanEnabled []string + PlanDisabled []string + Result []string + } + s.testData.GetTestCases(c, &input, &output) + for i, tt := range input { + s.testData.OnRecord(func() { + output[i].SQL = tt + tk.MustExec(`set @@session.tidb_regard_null_as_point=true`) + output[i].PlanEnabled = s.testData.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows()) + output[i].Result = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + + tk.MustExec(`set @@session.tidb_regard_null_as_point=false`) + output[i].PlanDisabled = s.testData.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows()) + }) + tk.MustExec(`set @@session.tidb_regard_null_as_point=true`) + tk.MustQuery("explain " + tt).Check(testkit.Rows(output[i].PlanEnabled...)) + tk.MustQuery(tt).Check(testkit.Rows(output[i].Result...)) + + tk.MustExec(`set @@session.tidb_regard_null_as_point=false`) + tk.MustQuery("explain " + tt).Check(testkit.Rows(output[i].PlanDisabled...)) + tk.MustQuery(tt).Check(testkit.Rows(output[i].Result...)) + } +} + +func (s *testIntegrationSuite) TestIssues29711(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + + tk.MustExec("drop table if exists tbl_29711") + tk.MustExec("CREATE TABLE `tbl_29711` (" + + "`col_250` text COLLATE utf8_unicode_ci NOT NULL," + + "`col_251` enum('Alice','Bob','Charlie','David') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'Charlie'," + + "PRIMARY KEY (`col_251`,`col_250`(1)) NONCLUSTERED);") + tk.MustQuery("explain format=brief " + + "select col_250,col_251 from tbl_29711 where col_251 between 'Bob' and 'David' order by col_250,col_251 limit 6;"). + Check(testkit.Rows( + "TopN 6.00 root test.tbl_29711.col_250, test.tbl_29711.col_251, offset:0, count:6", + "└─IndexLookUp 6.00 root ", + " ├─IndexRangeScan(Build) 30.00 cop[tikv] table:tbl_29711, index:PRIMARY(col_251, col_250) range:[\"Bob\",\"Bob\"], [\"Charlie\",\"Charlie\"], [\"David\",\"David\"], keep order:false, stats:pseudo", + " └─TopN(Probe) 6.00 cop[tikv] test.tbl_29711.col_250, test.tbl_29711.col_251, offset:0, count:6", + " └─TableRowIDScan 30.00 cop[tikv] table:tbl_29711 keep order:false, stats:pseudo", + )) + + tk.MustExec("drop table if exists t29711") + tk.MustExec("CREATE TABLE `t29711` (" + + "`a` varchar(10) DEFAULT NULL," + + "`b` int(11) DEFAULT NULL," + + "`c` int(11) DEFAULT NULL," + + "KEY `ia` (`a`(2)))") + tk.MustQuery("explain format=brief select * from t29711 use index (ia) order by a limit 10;"). + Check(testkit.Rows( + "TopN 10.00 root test.t29711.a, offset:0, count:10", + "└─IndexLookUp 10.00 root ", + " ├─IndexFullScan(Build) 10000.00 cop[tikv] table:t29711, index:ia(a) keep order:false, stats:pseudo", + " └─TopN(Probe) 10.00 cop[tikv] test.t29711.a, offset:0, count:10", + " └─TableRowIDScan 10000.00 cop[tikv] table:t29711 keep order:false, stats:pseudo", + )) +} + +func (s *testIntegrationSuite) TestIssue27313(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a varchar(100), b int, c int, index idx1(a(2), b), index idx2(a))") + tk.MustExec("explain format = 'verbose' select * from t where a = 'abcdefghijk' and b > 4") + // no warning indicates that idx2 is not pruned by idx1. + tk.MustQuery("show warnings").Check(testkit.Rows()) +} + +func (s *testIntegrationSuite) TestIssue30094(c *C) { + tk := testkit.NewTestKit(c, s.store) + + tk.MustExec("use test") + tk.MustExec(`drop table if exists t30094;`) + tk.MustExec(`create table t30094(a varchar(10));`) + tk.MustQuery(`explain format = 'brief' select * from t30094 where cast(a as float) and cast(a as char);`).Check(testkit.Rows( + "TableReader 8000.00 root data:Selection", + "└─Selection 8000.00 cop[tikv] cast(test.t30094.a, float BINARY), cast(test.t30094.a, var_string(5))", + " └─TableFullScan 10000.00 cop[tikv] table:t30094 keep order:false, stats:pseudo", + )) + tk.MustQuery(`explain format = 'brief' select * from t30094 where concat(a,'1') = _binary 0xe59388e59388e59388 collate binary and concat(a,'1') = _binary 0xe598bfe598bfe598bf collate binary;`).Check(testkit.Rows( + "TableReader 8000.00 root data:Selection", + "└─Selection 8000.00 cop[tikv] eq(to_binary(concat(test.t30094.a, \"1\")), \"0xe59388e59388e59388\"), eq(to_binary(concat(test.t30094.a, \"1\")), \"0xe598bfe598bfe598bf\")", + " └─TableFullScan 10000.00 cop[tikv] table:t30094 keep order:false, stats:pseudo", + )) +} + +func (s *testIntegrationSerialSuite) TestIssue30271(c *C) { + defer collate.SetNewCollationEnabledForTest(false) + collate.SetNewCollationEnabledForTest(true) + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a char(10), b char(10), c char(10), index (a, b, c)) collate utf8mb4_bin;") + tk.MustExec("insert into t values ('b', 'a', '1'), ('b', 'A', '2'), ('c', 'a', '3');") + tk.MustExec("set names utf8mb4 collate utf8mb4_general_ci;") + tk.MustQuery("select * from t where (a>'a' and b='a') or (b = 'A' and a < 'd') order by a,c;").Check(testkit.Rows("b a 1", "b A 2", "c a 3")) + +} +>>>>>>> 94be83bfa... *: replace compareDatum by compare and fix wrong optimize order by (#30273) diff --git a/types/datum.go b/types/datum.go index dd2d0557099b8..272111ebd4587 100644 --- a/types/datum.go +++ b/types/datum.go @@ -2034,7 +2034,8 @@ func (ds *datumsSorter) Len() int { } func (ds *datumsSorter) Less(i, j int) bool { - cmp, err := ds.datums[i].CompareDatum(ds.sc, &ds.datums[j]) + // TODO: set collation explicitly when rewrites feedback. + cmp, err := ds.datums[i].Compare(ds.sc, &ds.datums[j], collate.GetCollator(ds.datums[i].Collation())) if err != nil { ds.err = errors.Trace(err) return true @@ -2212,7 +2213,7 @@ func ChangeReverseResultByUpperLowerBound( resRetType.Decimal = int(res.GetMysqlDecimal().GetDigitsInt()) } bound := getDatumBound(&resRetType, rType) - cmp, err := d.CompareDatum(sc, &bound) + cmp, err := d.Compare(sc, &bound, collate.GetCollator(resRetType.Collate)) if err != nil { return d, err } diff --git a/types/datum_test.go b/types/datum_test.go index ef3dc177b0a16..afc75df8d6178 100644 --- a/types/datum_test.go +++ b/types/datum_test.go @@ -481,9 +481,15 @@ func (ts *testDatumSuite) TestChangeReverseResultByUpperLowerBound(c *C) { reverseRes, err := ChangeReverseResultByUpperLowerBound(sc, test.retType, test.a, test.roundType) c.Assert(err, IsNil) var cmp int +<<<<<<< HEAD cmp, err = reverseRes.CompareDatum(sc, &test.res) c.Assert(err, IsNil) c.Assert(cmp, Equals, 0, Commentf("%dth got:%#v, expect:%#v", ith, reverseRes, test.res)) +======= + cmp, err = reverseRes.Compare(sc, &test.res, collate.GetBinaryCollator()) + require.NoError(t, err) + require.Equalf(t, 0, cmp, "%dth got:%#v, expect:%#v", ith, reverseRes, test.res) +>>>>>>> 94be83bfa... *: replace compareDatum by compare and fix wrong optimize order by (#30273) } } diff --git a/util/ranger/detacher.go b/util/ranger/detacher.go index 6a07c531275cf..64ef8d094e2e7 100644 --- a/util/ranger/detacher.go +++ b/util/ranger/detacher.go @@ -704,7 +704,8 @@ func isSameValue(sc *stmtctx.StatementContext, lhs, rhs *valueInfo) (bool, error if lhs == nil || rhs == nil || lhs.mutable || rhs.mutable || lhs.value.Kind() != rhs.value.Kind() { return false, nil } - cmp, err := lhs.value.CompareDatum(sc, rhs.value) + // binary collator may not the best choice, but it can make sure the result is correct. + cmp, err := lhs.value.Compare(sc, rhs.value, collate.GetBinaryCollator()) if err != nil { return false, err } diff --git a/util/rowDecoder/decoder_test.go b/util/rowDecoder/decoder_test.go index f9c0d92e28250..54251e6f79c2a 100644 --- a/util/rowDecoder/decoder_test.go +++ b/util/rowDecoder/decoder_test.go @@ -128,7 +128,7 @@ func TestRowDecoder(t *testing.T) { for i, col := range cols[:len(cols)-1] { v, ok := r[col.ID] if ok { - equal, err1 := v.CompareDatum(sc, &row.output[i]) + equal, err1 := v.Compare(sc, &row.output[i], collate.GetBinaryCollator()) require.Nil(t, err1) require.Equal(t, 0, equal) } else { @@ -142,7 +142,7 @@ func TestRowDecoder(t *testing.T) { for k, v := range r2 { v1, ok := r[k] require.True(t, ok) - equal, err1 := v.CompareDatum(sc, &v1) + equal, err1 := v.Compare(sc, &v1, collate.GetBinaryCollator()) require.Nil(t, err1) require.Equal(t, 0, equal) }