planner: non-deterministic expression can not be pushed down throught the join (#65563)

close pingcap/tidb#65486
This commit is contained in:
Weizhen Wang
2026-01-15 15:05:38 +08:00
committed by GitHub
parent 96bdeae43c
commit 53dc671df4
5 changed files with 102 additions and 1 deletions

View File

@ -8,7 +8,10 @@
"select * from t where name='a' and length(name)=1; -- without constant propagated",
"select * from (select 'test' as b from t) n where length(b) > 2; -- can be substituted",
"select foo.a, foo.b, bar.c from foo join bar on foo.a=bar.a where (foo.a,foo.b) in ((1,2),(3,4));",
"select foo.a, foo.b, bar.c from foo left join bar on foo.a=bar.a where (foo.a,foo.b) in ((1,2),(3,4));"
"select foo.a, foo.b, bar.c from foo left join bar on foo.a=bar.a where (foo.a,foo.b) in ((1,2),(3,4));",
"select foo.a, foo.b, bar.c from foo left join bar on foo.a=bar.a where (foo.a,foo.b) in ((1,2),(3,4));",
"select * from foo join bar on foo.a=bar.a where rand() > 0.5;",
"select * from foo join bar on foo.a=bar.a where foo.a = rand();"
]
}
]

View File

@ -60,6 +60,50 @@
" └─TableRangeScan 2.00 cop[tikv] table:bar range: decided by [test.foo.a], keep order:false, stats:pseudo"
],
"Warning": null
},
{
"SQL": "select foo.a, foo.b, bar.c from foo left join bar on foo.a=bar.a where (foo.a,foo.b) in ((1,2),(3,4));",
"Plan": [
"IndexJoin 2.50 root left outer join, inner:TableReader, left side:Selection, outer key:test.foo.a, inner key:test.bar.a, equal cond:eq(test.foo.a, test.bar.a)",
"├─Selection(Build) 2.00 root or(and(eq(test.foo.a, 1), eq(test.foo.b, 2)), and(eq(test.foo.a, 3), eq(test.foo.b, 4)))",
"│ └─Batch_Point_Get 2.00 root table:foo handle:[1 3], keep order:false, desc:false",
"└─TableReader(Probe) 2.00 root data:TableRangeScan",
" └─TableRangeScan 2.00 cop[tikv] table:bar range: decided by [test.foo.a], keep order:false, stats:pseudo"
],
"Warning": null
},
{
"SQL": "select * from foo join bar on foo.a=bar.a where rand() > 0.5;",
"Plan": [
"MergeJoin 12500.00 root inner join, left key:test.foo.a, right key:test.bar.a, other cond:gt(rand(), 0.5)",
"├─TableReader(Build) 10000.00 root data:TableFullScan",
"│ └─TableFullScan 10000.00 cop[tikv] table:bar keep order:true, stats:pseudo",
"└─TableReader(Probe) 10000.00 root data:TableFullScan",
" └─TableFullScan 10000.00 cop[tikv] table:foo keep order:true, stats:pseudo"
],
"Warning": [
"Warning 1105 Scalar function 'rand'(signature: Rand, return type: double) is not supported to push down to tiflash now.",
"Warning 1105 Scalar function 'rand'(signature: Rand, return type: double) is not supported to push down to tiflash now."
]
},
{
"SQL": "select * from foo join bar on foo.a=bar.a where foo.a = rand();",
"Plan": [
"Projection 10000.00 root test.foo.a, test.foo.b, test.foo.c, test.bar.a, test.bar.b, test.bar.c",
"└─MergeJoin 10000.00 root inner join, left key:test.bar.a, right key:test.foo.a",
" ├─Selection(Build) 8000.00 root eq(cast(test.foo.a, double BINARY), rand())",
" │ └─TableReader 10000.00 root data:TableFullScan",
" │ └─TableFullScan 10000.00 cop[tikv] table:foo keep order:true, stats:pseudo",
" └─TableReader(Probe) 10000.00 root data:TableFullScan",
" └─TableFullScan 10000.00 cop[tikv] table:bar keep order:true, stats:pseudo"
],
"Warning": [
"Warning 1105 Scalar function 'rand'(signature: Rand, return type: double) is not supported to push down to storage layer now.",
"Warning 1105 Scalar function 'rand'(signature: Rand, return type: double) is not supported to push down to tiflash now.",
"Warning 1105 Scalar function 'rand'(signature: Rand, return type: double) is not supported to push down to tiflash now.",
"Warning 1105 Scalar function 'rand'(signature: Rand, return type: double) is not supported to push down to tiflash now.",
"Warning 1105 Scalar function 'rand'(signature: Rand, return type: double) is not supported to push down to tiflash now."
]
}
]
}

View File

@ -60,6 +60,50 @@
" └─TableRangeScan 2.00 cop[tikv] table:bar range: decided by [test.foo.a], keep order:false, stats:pseudo"
],
"Warning": null
},
{
"SQL": "select foo.a, foo.b, bar.c from foo left join bar on foo.a=bar.a where (foo.a,foo.b) in ((1,2),(3,4));",
"Plan": [
"IndexJoin 2.50 root left outer join, inner:TableReader, left side:Selection, outer key:test.foo.a, inner key:test.bar.a, equal cond:eq(test.foo.a, test.bar.a)",
"├─Selection(Build) 2.00 root or(and(eq(test.foo.a, 1), eq(test.foo.b, 2)), and(eq(test.foo.a, 3), eq(test.foo.b, 4)))",
"│ └─Batch_Point_Get 2.00 root table:foo handle:[1 3], keep order:false, desc:false",
"└─TableReader(Probe) 2.00 root data:TableRangeScan",
" └─TableRangeScan 2.00 cop[tikv] table:bar range: decided by [test.foo.a], keep order:false, stats:pseudo"
],
"Warning": null
},
{
"SQL": "select * from foo join bar on foo.a=bar.a where rand() > 0.5;",
"Plan": [
"MergeJoin 12500.00 root inner join, left key:test.foo.a, right key:test.bar.a, other cond:gt(rand(), 0.5)",
"├─TableReader(Build) 10000.00 root data:TableFullScan",
"│ └─TableFullScan 10000.00 cop[tikv] table:bar keep order:true, stats:pseudo",
"└─TableReader(Probe) 10000.00 root data:TableFullScan",
" └─TableFullScan 10000.00 cop[tikv] table:foo keep order:true, stats:pseudo"
],
"Warning": [
"Warning 1105 Scalar function 'rand'(signature: Rand, return type: double) is not supported to push down to tiflash now.",
"Warning 1105 Scalar function 'rand'(signature: Rand, return type: double) is not supported to push down to tiflash now."
]
},
{
"SQL": "select * from foo join bar on foo.a=bar.a where foo.a = rand();",
"Plan": [
"Projection 10000.00 root test.foo.a, test.foo.b, test.foo.c, test.bar.a, test.bar.b, test.bar.c",
"└─MergeJoin 10000.00 root inner join, left key:test.bar.a, right key:test.foo.a",
" ├─Selection(Build) 8000.00 root eq(cast(test.foo.a, double BINARY), rand())",
" │ └─TableReader 10000.00 root data:TableFullScan",
" │ └─TableFullScan 10000.00 cop[tikv] table:foo keep order:true, stats:pseudo",
" └─TableReader(Probe) 10000.00 root data:TableFullScan",
" └─TableFullScan 10000.00 cop[tikv] table:bar keep order:true, stats:pseudo"
],
"Warning": [
"Warning 1105 Scalar function 'rand'(signature: Rand, return type: double) is not supported to push down to storage layer now.",
"Warning 1105 Scalar function 'rand'(signature: Rand, return type: double) is not supported to push down to tiflash now.",
"Warning 1105 Scalar function 'rand'(signature: Rand, return type: double) is not supported to push down to tiflash now.",
"Warning 1105 Scalar function 'rand'(signature: Rand, return type: double) is not supported to push down to tiflash now.",
"Warning 1105 Scalar function 'rand'(signature: Rand, return type: double) is not supported to push down to tiflash now."
]
}
]
}

View File

@ -1477,6 +1477,15 @@ func (p *LogicalJoin) ExtractOnCondition(
// `columns` may be empty, if the condition is like `correlated_column op constant`, or `constant`,
// push this kind of constant condition down according to join type.
if len(columns) == 0 {
// The IsMutableEffectsExpr check is primarily designed to prevent mutable expressions
// like rand() > 0.5 from being pushed down; instead, such expressions should remain
// in other conditions.
// Checking len(columns) == 0 first is to let filter like rand() > tbl.col
// to be able pushdown as left or right condition
if expression.IsMutableEffectsExpr(expr) {
otherCond = append(otherCond, expr)
continue
}
leftCond, rightCond = p.pushDownConstExpr(expr, leftCond, rightCond, deriveLeft || deriveRight)
continue
}

View File

@ -29,6 +29,7 @@ func TestMain(m *testing.M) {
goleak.IgnoreTopFunction("github.com/lestrrat-go/httprc.runFetchWorker"),
goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"),
goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"),
goleak.IgnoreTopFunction("internal/poll.runtime_pollWait"),
}
goleak.VerifyTestMain(m, opts...)
}