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

expression: fix a bug caused by cast function signature wrong in aggregation push down #28805

Merged
merged 9 commits into from
Nov 1, 2021
23 changes: 23 additions & 0 deletions expression/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10393,6 +10393,29 @@ func (s *testIntegrationSuite) TestIdentity(c *C) {
tk.MustQuery("SELECT @@identity, LAST_INSERT_ID()").Check(testkit.Rows("3 3"))
}

func (s *testIntegrationSuite) TestIssue28804(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("drop table if exists perf_offline_day;")
tk.MustExec(`CREATE TABLE perf_offline_day (
uuid varchar(50),
ts timestamp NOT NULL,
user_id varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
platform varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
host_id bigint(20) DEFAULT NULL,
PRIMARY KEY (uuid,ts) /*T![clustered_index] NONCLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
PARTITION BY RANGE ( UNIX_TIMESTAMP(ts) ) (
PARTITION p20210906 VALUES LESS THAN (1630944000),
PARTITION p20210907 VALUES LESS THAN (1631030400),
PARTITION p20210908 VALUES LESS THAN (1631116800),
PARTITION p20210909 VALUES LESS THAN (1631203200)
);`)
tk.MustExec("set @@tidb_partition_prune_mode = 'static'")
tk.MustExec("INSERT INTO `perf_offline_day` VALUES ('dd082c8a-3bab-4431-943a-348fe0592abd','2021-09-08 13:00:07','Xg9C8zq81jGNbugM', 'pc', 12345);")
tk.MustQuery("SELECT cast(floor(hour(ts) / 4) as char) as win_start FROM perf_offline_day partition (p20210907, p20210908) GROUP BY win_start;").Check(testkit.Rows("3"))
}

func (s *testIntegrationSuite) TestIssue28643(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
Expand Down
12 changes: 9 additions & 3 deletions expression/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,15 +224,21 @@ func ColumnSubstituteImpl(expr Expression, schema *Schema, newExprs []Expression
newExpr.SetCoercibility(v.Coercibility())
return true, newExpr
case *ScalarFunction:
substituted := false
if v.FuncName.L == ast.Cast {
tiancaiamao marked this conversation as resolved.
Show resolved Hide resolved
newFunc := v.Clone().(*ScalarFunction)
_, newFunc.GetArgs()[0] = ColumnSubstituteImpl(newFunc.GetArgs()[0], schema, newExprs)
return true, newFunc
substituted, newFunc.GetArgs()[0] = ColumnSubstituteImpl(newFunc.GetArgs()[0], schema, newExprs)
if substituted {
// Workaround for issue https://github.com/pingcap/tidb/issues/28804
e := NewFunctionInternal(v.GetCtx(), v.FuncName.L, v.RetType, newFunc.GetArgs()...)
e.SetCoercibility(v.Coercibility())
return true, e
}
return false, newFunc
}
// cowExprRef is a copy-on-write util, args array allocation happens only
// when expr in args is changed
refExprArr := cowExprRef{v.GetArgs(), nil}
substituted := false
_, coll := DeriveCollationFromExprs(v.GetCtx(), v.GetArgs()...)
for idx, arg := range v.GetArgs() {
changed, newFuncExpr := ColumnSubstituteImpl(arg, schema, newExprs)
Expand Down
14 changes: 7 additions & 7 deletions planner/core/testdata/integration_serial_suite_out.json
Original file line number Diff line number Diff line change
Expand Up @@ -2821,23 +2821,23 @@
{
"SQL": "desc format='brief' select /*+ use_index_merge(t) */ * from t where a =1 or (b=1 and length(b)=1)",
"Plan": [
"IndexMerge 1.72 root ",
"IndexMerge 8.00 root ",
"├─IndexRangeScan(Build) 1.00 cop[tikv] table:t, index:a(a) range:[1,1], keep order:false",
"├─Selection(Build) 0.80 cop[tikv] eq(length(cast(1, var_string(20))), 1)",
"├─Selection(Build) 0.80 cop[tikv] 1",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is expected, because after fixing the bug, the constant propagate can infer that
b = 1 and length(b) = 1 is always true.
So the this filter condition changes and the cost of the plan changes...

"│ └─IndexRangeScan 1.00 cop[tikv] table:t, index:b(b) range:[1,1], keep order:false",
"└─TableRowIDScan(Probe) 1.72 cop[tikv] table:t keep order:false"
"└─TableRowIDScan(Probe) 8.00 cop[tikv] table:t keep order:false"
],
"Warnings": null
},
{
"SQL": "desc format='brief' select /*+ use_index_merge(t) */ * from t where (a=1 and length(a)=1) or (b=1 and length(b)=1)",
"Plan": [
"IndexMerge 1.54 root ",
"├─Selection(Build) 0.80 cop[tikv] eq(length(cast(1, var_string(20))), 1)",
"IndexMerge 8.00 root ",
"├─Selection(Build) 0.80 cop[tikv] 1",
"│ └─IndexRangeScan 1.00 cop[tikv] table:t, index:a(a) range:[1,1], keep order:false",
"├─Selection(Build) 0.80 cop[tikv] eq(length(cast(1, var_string(20))), 1)",
"├─Selection(Build) 0.80 cop[tikv] 1",
"│ └─IndexRangeScan 1.00 cop[tikv] table:t, index:b(b) range:[1,1], keep order:false",
"└─TableRowIDScan(Probe) 1.54 cop[tikv] table:t keep order:false"
"└─TableRowIDScan(Probe) 8.00 cop[tikv] table:t keep order:false"
],
"Warnings": null
},
Expand Down