Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

*: hotfix support use like to build range for new collation columns | tidb-test=pr/2256 #49191

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cmd/explaintest/r/explain_easy.result
Original file line number Diff line number Diff line change
Expand Up @@ -797,14 +797,14 @@ create table t(a binary(16) not null, b varchar(2) default null, c varchar(100)
explain format = 'brief' select * from t where a=x'FA34E1093CB428485734E3917F000000' and b='xb';
id estRows task access object operator info
IndexLookUp 0.10 root
├─IndexRangeScan(Build) 0.10 cop[tikv] table:t, index:a(a, b) range:[0xFA34E1093CB428485734E3917F000000 "xb",0xFA34E1093CB428485734E3917F000000 "xb"], keep order:false, stats:pseudo
├─IndexRangeScan(Build) 0.10 cop[tikv] table:t, index:a(a, b) range:["\xfa4\xe1\t<\xb4(HW4\xe3\x91\x7f\x00\x00\x00" "xb","\xfa4\xe1\t<\xb4(HW4\xe3\x91\x7f\x00\x00\x00" "xb"], keep order:false, stats:pseudo
└─TableRowIDScan(Probe) 0.10 cop[tikv] table:t keep order:false, stats:pseudo
explain format = 'brief' update t set c = 'ssss' where a=x'FA34E1093CB428485734E3917F000000' and b='xb';
id estRows task access object operator info
Update N/A root N/A
└─SelectLock 0.10 root for update 0
└─IndexLookUp 0.10 root
├─IndexRangeScan(Build) 0.10 cop[tikv] table:t, index:a(a, b) range:[0xFA34E1093CB428485734E3917F000000 "xb",0xFA34E1093CB428485734E3917F000000 "xb"], keep order:false, stats:pseudo
├─IndexRangeScan(Build) 0.10 cop[tikv] table:t, index:a(a, b) range:["\xfa4\xe1\t<\xb4(HW4\xe3\x91\x7f\x00\x00\x00" "xb","\xfa4\xe1\t<\xb4(HW4\xe3\x91\x7f\x00\x00\x00" "xb"], keep order:false, stats:pseudo
└─TableRowIDScan(Probe) 0.10 cop[tikv] table:t keep order:false, stats:pseudo
drop table if exists t;
create table t(a int, b int);
Expand Down
3 changes: 2 additions & 1 deletion cmd/explaintest/r/explain_generate_column_substitute.result
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,8 @@ id estRows task access object operator info
StreamAgg 1.00 root funcs:count(Column#6)->Column#4
└─IndexReader 1.00 root index:StreamAgg
└─StreamAgg 1.00 cop[tikv] funcs:count(1)->Column#6
└─IndexRangeScan 250.00 cop[tikv] table:tbl1, index:expression_index(md5(`s`)) range:["02e74f10e0327ad868d138f2b4fdd6f","02e74f10e0327ad868d138f2b4fdd6g"), keep order:false, stats:pseudo
└─Selection 250.00 cop[tikv] like(md5(cast(test.tbl1.s, var_string(20))), "02e74f10e0327ad868d138f2b4fdd6f%", 92)
└─IndexRangeScan 250.00 cop[tikv] table:tbl1, index:expression_index(md5(`s`)) range:["02e74f10e0327ad868d138f2b4fdd6f","02e74f10e0327ad868d138f2b4fdd6g"), keep order:false, stats:pseudo
select count(*) from tbl1 use index() where md5(s) like '02e74f10e0327ad868d138f2b4fdd6f%';
count(*)
64
Expand Down
1,085 changes: 1,085 additions & 0 deletions cmd/explaintest/r/range_scan_for_like.result

Large diffs are not rendered by default.

248 changes: 248 additions & 0 deletions cmd/explaintest/t/range_scan_for_like.test

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions executor/point_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -540,11 +540,13 @@ func EncodeUniqueIndexValuesForKey(ctx sessionctx.Context, tblInfo *model.TableI
colInfo := tblInfo.Columns[idxInfo.Columns[i].Offset]
// table.CastValue will append 0x0 if the string value's length is smaller than the BINARY column's length.
// So we don't use CastValue for string value for now.
// TODO: merge two if branch.
// TODO: The first if branch should have been removed, because the functionality of set the collation of the datum
// have been moved to util/ranger (normal path) and getNameValuePairs/getPointGetValue (fast path). But this change
// will be cherry-picked to a hotfix, so we choose to be a bit conservative and keep this for now.
if colInfo.GetType() == mysql.TypeString || colInfo.GetType() == mysql.TypeVarString || colInfo.GetType() == mysql.TypeVarchar {
var str string
str, err = idxVals[i].ToString()
idxVals[i].SetString(str, colInfo.FieldType.GetCollate())
idxVals[i].SetString(str, idxVals[i].Collation())
} else if colInfo.GetType() == mysql.TypeEnum && (idxVals[i].Kind() == types.KindString || idxVals[i].Kind() == types.KindBytes || idxVals[i].Kind() == types.KindBinaryLiteral) {
var str string
var e types.Enum
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@
" └─TableReader 1.11 root data:TopN",
" └─TopN 1.11 cop[tikv] partition by test.customer.primary_key, test.customer.secondary_key order by test.customer.c_timestamp, offset:0, count:10",
" └─Selection 1.11 cop[tikv] ge(test.customer.c_timestamp, 1661883508511000000)",
" └─TableRangeScan 33.33 cop[tikv] table:customer range:[0x0002 0x0001,0x0002 +inf], keep order:false, stats:pseudo"
" └─TableRangeScan 33.33 cop[tikv] table:customer range:[\"\\x00\\x02\" \"\\x00\\x01\",\"\\x00\\x02\" +inf], keep order:false, stats:pseudo"
],
"Res": null
},
Expand Down
66 changes: 34 additions & 32 deletions planner/core/casetest/testdata/plan_suite_out.json
Original file line number Diff line number Diff line change
Expand Up @@ -2787,11 +2787,11 @@
},
{
"SQL": "select a from t where c_str like ''",
"Best": "IndexReader(Index(t.c_d_e_str)[[\"\",\"\"]])->Projection"
"Best": "IndexReader(Index(t.c_d_e_str)[[\"\",\"\"]]->Sel([like(test.t.c_str, , 92)]))->Projection"
},
{
"SQL": "select a from t where c_str like 'abc'",
"Best": "IndexReader(Index(t.c_d_e_str)[[\"abc\",\"abc\"]])->Projection"
"Best": "IndexReader(Index(t.c_d_e_str)[[\"abc\",\"abc\"]]->Sel([like(test.t.c_str, abc, 92)]))->Projection"
},
{
"SQL": "select a from t where c_str not like 'abc'",
Expand All @@ -2807,43 +2807,43 @@
},
{
"SQL": "select a from t where c_str like 'abc%'",
"Best": "IndexReader(Index(t.c_d_e_str)[[\"abc\",\"abd\")])->Projection"
"Best": "IndexReader(Index(t.c_d_e_str)[[\"abc\",\"abd\")]->Sel([like(test.t.c_str, abc%, 92)]))->Projection"
},
{
"SQL": "select a from t where c_str like 'abc_'",
"Best": "IndexReader(Index(t.c_d_e_str)[(\"abc\",\"abd\")]->Sel([like(test.t.c_str, abc_, 92)]))->Projection"
"Best": "IndexReader(Index(t.c_d_e_str)[[\"abc\",\"abd\")]->Sel([like(test.t.c_str, abc_, 92)]))->Projection"
},
{
"SQL": "select a from t where c_str like 'abc%af'",
"Best": "IndexReader(Index(t.c_d_e_str)[[\"abc\",\"abd\")]->Sel([like(test.t.c_str, abc%af, 92)]))->Projection"
},
{
"SQL": "select a from t where c_str like 'abc\\_' escape ''",
"Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc_\"]])->Projection"
"Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc_\"]]->Sel([like(test.t.c_str, abc\\_, 92)]))->Projection"
},
{
"SQL": "select a from t where c_str like 'abc\\_'",
"Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc_\"]])->Projection"
"Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc_\"]]->Sel([like(test.t.c_str, abc\\_, 92)]))->Projection"
},
{
"SQL": "select a from t where c_str like 'abc\\\\_'",
"Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc_\"]])->Projection"
"Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc_\"]]->Sel([like(test.t.c_str, abc\\_, 92)]))->Projection"
},
{
"SQL": "select a from t where c_str like 'abc\\_%'",
"Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc`\")])->Projection"
"Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc`\")]->Sel([like(test.t.c_str, abc\\_%, 92)]))->Projection"
},
{
"SQL": "select a from t where c_str like 'abc=_%' escape '='",
"Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc`\")])->Projection"
"Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc`\")]->Sel([like(test.t.c_str, abc=_%, 61)]))->Projection"
},
{
"SQL": "select a from t where c_str like 'abc\\__'",
"Best": "IndexReader(Index(t.c_d_e_str)[(\"abc_\",\"abc`\")]->Sel([like(test.t.c_str, abc\\__, 92)]))->Projection"
"Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc`\")]->Sel([like(test.t.c_str, abc\\__, 92)]))->Projection"
},
{
"SQL": "select a from t where c_str like 123",
"Best": "IndexReader(Index(t.c_d_e_str)[[\"123\",\"123\"]])->Projection"
"Best": "IndexReader(Index(t.c_d_e_str)[[\"123\",\"123\"]]->Sel([like(test.t.c_str, 123, 92)]))->Projection"
},
{
"SQL": "select a from t where c = 1.9 and d > 3",
Expand Down Expand Up @@ -8006,21 +8006,21 @@
" │ └─StreamAgg 249.75 root funcs:max(test.tc.id)->Column#14",
" │ └─TopN 62.38 root test.tc.id:desc, offset:0, count:1",
" │ └─IndexLookUp 62.38 root ",
" │ ├─Selection(Build) 62.44 cop[tikv] eq(test.ta.name, test.tc.name)",
" │ ├─Selection(Build) 62.38 cop[tikv] eq(test.ta.name, test.tc.name), like(test.tc.name, \"chad99%\", 92)",
" │ │ └─IndexRangeScan 62437.50 cop[tikv] table:tc, index:idx_tc_name(name) range:[\"chad99\",\"chad9:\"), keep order:false, stats:pseudo",
" │ └─TopN(Probe) 62.38 cop[tikv] test.tc.id:desc, offset:0, count:1",
" │ └─Selection 62.38 cop[tikv] not(isnull(test.tc.id))",
" │ └─TableRowIDScan 62.44 cop[tikv] table:tc keep order:false, stats:pseudo",
" │ └─TableRowIDScan 62.38 cop[tikv] table:tc keep order:false, stats:pseudo",
" └─Selection(Probe) 199.80 root gt(Column#19, 100)",
" └─MaxOneRow 249.75 root ",
" └─StreamAgg 249.75 root funcs:max(test.td.id)->Column#19",
" └─Limit 62.38 root offset:0, count:1",
" └─Projection 62.38 root test.td.id, test.td.name",
" └─IndexLookUp 62.38 root ",
" ├─Selection(Build) 2495.00 cop[tikv] eq(test.ta.id, test.td.id)",
" │ └─IndexFullScan 2495002.50 cop[tikv] table:td, index:idx_tc_id(id) keep order:true, desc, stats:pseudo",
" └─Selection(Probe) 62.38 cop[tikv] like(test.td.name, \"chad999%\", 92)",
" └─TableRowIDScan 2495.00 cop[tikv] table:td keep order:false, stats:pseudo"
" └─TopN 62.38 root test.td.id:desc, offset:0, count:1",
" └─IndexLookUp 62.38 root ",
" ├─Selection(Build) 1560.94 cop[tikv] like(test.td.name, \"chad999%\", 92)",
" │ └─IndexRangeScan 62437.50 cop[tikv] table:td, index:idx_tc_name(name) range:[\"chad999\",\"chad99:\"), keep order:false, stats:pseudo",
" └─TopN(Probe) 62.38 cop[tikv] test.td.id:desc, offset:0, count:1",
" └─Selection 62.38 cop[tikv] eq(test.ta.id, test.td.id), not(isnull(test.td.id))",
" └─TableRowIDScan 1560.94 cop[tikv] table:td keep order:false, stats:pseudo"
],
"Result": null,
"Warning": null
Expand All @@ -8034,29 +8034,31 @@
" │ ├─Apply(Build) 10000.00 root CARTESIAN semi join",
" │ │ ├─TableReader(Build) 10000.00 root data:TableFullScan",
" │ │ │ └─TableFullScan 10000.00 cop[tikv] table:ta keep order:false, stats:pseudo",
" │ │ └─TableReader(Probe) 2500.00 root data:Selection",
" │ │ └─Selection 2500.00 cop[tikv] eq(test.ta.code, test.tb.code), like(test.tb.name, \"chad9%\", 92)",
" │ │ └─TableFullScan 100000000.00 cop[tikv] table:tb keep order:false, stats:pseudo",
" │ │ └─IndexLookUp(Probe) 2500.00 root ",
" │ │ ├─Selection(Build) 62500.00 cop[tikv] like(test.tb.name, \"chad9%\", 92)",
" │ │ │ └─IndexRangeScan 2500000.00 cop[tikv] table:tb, index:idx_tb_name(name) range:[\"chad9\",\"chad:\"), keep order:false, stats:pseudo",
" │ │ └─Selection(Probe) 2500.00 cop[tikv] eq(test.ta.code, test.tb.code)",
" │ │ └─TableRowIDScan 62500.00 cop[tikv] table:tb keep order:false, stats:pseudo",
" │ └─Selection(Probe) 8000.00 root gt(Column#14, 100)",
" │ └─MaxOneRow 10000.00 root ",
" │ └─StreamAgg 10000.00 root funcs:max(test.tc.id)->Column#14",
" │ └─TopN 2497.50 root test.tc.id:desc, offset:0, count:1",
" │ └─IndexLookUp 2497.50 root ",
" │ ├─Selection(Build) 2500.00 cop[tikv] eq(test.ta.name, test.tc.name)",
" │ ├─Selection(Build) 2497.50 cop[tikv] eq(test.ta.name, test.tc.name), like(test.tc.name, \"chad99%\", 92)",
" │ │ └─IndexRangeScan 2500000.00 cop[tikv] table:tc, index:idx_tc_name(name) range:[\"chad99\",\"chad9:\"), keep order:false, stats:pseudo",
" │ └─TopN(Probe) 2497.50 cop[tikv] test.tc.id:desc, offset:0, count:1",
" │ └─Selection 2497.50 cop[tikv] not(isnull(test.tc.id))",
" │ └─TableRowIDScan 2500.00 cop[tikv] table:tc keep order:false, stats:pseudo",
" │ └─TableRowIDScan 2497.50 cop[tikv] table:tc keep order:false, stats:pseudo",
" └─Selection(Probe) 8000.00 root gt(Column#19, 100)",
" └─MaxOneRow 10000.00 root ",
" └─StreamAgg 10000.00 root funcs:max(test.td.id)->Column#19",
" └─Limit 2497.50 root offset:0, count:1",
" └─Projection 2497.50 root test.td.id, test.td.name",
" └─IndexLookUp 2497.50 root ",
" ├─Selection(Build) 99900.00 cop[tikv] eq(test.ta.id, test.td.id)",
" │ └─IndexFullScan 99900000.00 cop[tikv] table:td, index:idx_tc_id(id) keep order:true, desc, stats:pseudo",
" └─Selection(Probe) 2497.50 cop[tikv] like(test.td.name, \"chad999%\", 92)",
" └─TableRowIDScan 99900.00 cop[tikv] table:td keep order:false, stats:pseudo"
" └─TopN 2497.50 root test.td.id:desc, offset:0, count:1",
" └─IndexLookUp 2497.50 root ",
" ├─Selection(Build) 62500.00 cop[tikv] like(test.td.name, \"chad999%\", 92)",
" │ └─IndexRangeScan 2500000.00 cop[tikv] table:td, index:idx_tc_name(name) range:[\"chad999\",\"chad99:\"), keep order:false, stats:pseudo",
" └─TopN(Probe) 2497.50 cop[tikv] test.td.id:desc, offset:0, count:1",
" └─Selection 2497.50 cop[tikv] eq(test.ta.id, test.td.id), not(isnull(test.td.id))",
" └─TableRowIDScan 62500.00 cop[tikv] table:td keep order:false, stats:pseudo"
],
"Result": null,
"Warning": null
Expand Down
14 changes: 7 additions & 7 deletions planner/core/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3535,13 +3535,13 @@ func TestIssues29711(t *testing.T) {
"`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;").
"select col_250,col_251 from tbl_29711 use index (primary) 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",
" ├─IndexRangeScan(Build) 250.00 cop[tikv] table:tbl_29711, index:PRIMARY(col_251, col_250) range:[\"Bob\",\"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",
" └─TableRowIDScan 250.00 cop[tikv] table:tbl_29711 keep order:false, stats:pseudo",
))

tk.MustExec("drop table if exists t29711")
Expand Down Expand Up @@ -5015,14 +5015,14 @@ func TestPlanCacheForIndexJoinRangeFallback(t *testing.T) {
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1(a int, b varchar(10), c varchar(10), index idx_a_b(a, b))")
tk.MustExec("create table t2(d int)")
tk.MustExec("set @@tidb_opt_range_max_size=1275")
// 1275 is enough for [? a,? a], [? b,? b], [? c,? c] but is not enough for [? aaaaaa,? aaaaaa], [? bbbbbb,? bbbbbb], [? cccccc,? cccccc].
tk.MustExec("set @@tidb_opt_range_max_size=1260")
// 1260 is enough for [? a,? a], [? b,? b], [? c,? c] but is not enough for [? aaaaaa,? aaaaaa], [? bbbbbb,? bbbbbb], [? cccccc,? cccccc].
rows := tk.MustQuery("explain format='brief' select /*+ inl_join(t1) */ * from t1 join t2 on t1.a = t2.d where t1.b in ('a', 'b', 'c')").Rows()
require.True(t, strings.Contains(rows[6][4].(string), "range: decided by [eq(test.t1.a, test.t2.d) in(test.t1.b, a, b, c)]"))
tk.MustQuery("show warnings").Check(testkit.Rows())
rows = tk.MustQuery("explain format='brief' select /*+ inl_join(t1) */ * from t1 join t2 on t1.a = t2.d where t1.b in ('aaaaaa', 'bbbbbb', 'cccccc');").Rows()
require.True(t, strings.Contains(rows[6][4].(string), "range: decided by [eq(test.t1.a, test.t2.d)]"))
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Memory capacity of 1275 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen"))
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Memory capacity of 1260 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen"))

tk.MustExec("prepare stmt1 from 'select /*+ inl_join(t1) */ * from t1 join t2 on t1.a = t2.d where t1.b in (?, ?, ?)'")
tk.MustExec("set @a='a', @b='b', @c='c'")
Expand All @@ -5043,7 +5043,7 @@ func TestPlanCacheForIndexJoinRangeFallback(t *testing.T) {
tk.MustExec("prepare stmt2 from 'select /*+ inl_join(t1) */ * from t1 join t2 on t1.a = t2.d where t1.b in (?, ?, ?, ?, ?)'")
tk.MustExec("set @a='a', @b='b', @c='c', @d='d', @e='e'")
tk.MustExec("execute stmt2 using @a, @b, @c, @d, @e")
tk.MustQuery("show warnings").Sort().Check(testkit.Rows("Warning 1105 Memory capacity of 1275 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen",
tk.MustQuery("show warnings").Sort().Check(testkit.Rows("Warning 1105 Memory capacity of 1260 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen",
"Warning 1105 skip prepared plan-cache: in-list is too long"))
tk.MustExec("execute stmt2 using @a, @b, @c, @d, @e")
tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0"))
Expand Down
5 changes: 3 additions & 2 deletions planner/core/plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -605,8 +605,9 @@ func TestIssue25729(t *testing.T) {
for i := 0; i < 10; i++ {
tk.MustQuery("explain format='brief' select * from t1 where concat(a, b) like \"aadwa\" and a = \"a\";").Check(testkit.Rows(
"Projection 0.10 root test.t1.a, test.t1.b",
"└─IndexReader 0.10 root index:IndexRangeScan",
" └─IndexRangeScan 0.10 cop[tikv] table:t1, index:idx2(a, concat(`a`, `b`), b) range:[\"a\" \"aadwa\",\"a\" \"aadwa\"], keep order:false, stats:pseudo"))
"└─IndexReader 0.10 root index:Selection",
" └─Selection 0.10 cop[tikv] like(concat(test.t1.a, test.t1.b), \"aadwa\", 92)",
" └─IndexRangeScan 0.10 cop[tikv] table:t1, index:idx2(a, concat(`a`, `b`), b) range:[\"a\" \"aadwa\",\"a\" \"aadwa\"], keep order:false, stats:pseudo"))

tk.MustQuery("explain format='brief' select b from t1 where concat(a, b) >= \"aa\" and a = \"b\";").Check(testkit.Rows(
"Projection 33.33 root test.t1.b",
Expand Down
Loading