Skip to content

Commit d3e6a29

Browse files
planner: remove the limitation that predicates can't be pushed through Projection on TableDual (#51329) (#52164)
close #50614
1 parent ca6a857 commit d3e6a29

File tree

4 files changed

+77
-46
lines changed

4 files changed

+77
-46
lines changed

planner/core/issuetest/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ go_test(
66
srcs = ["planner_issue_test.go"],
77
flaky = True,
88
race = "on",
9-
shard_count = 9,
9+
shard_count = 10,
1010
deps = ["//testkit"],
1111
)

planner/core/issuetest/planner_issue_test.go

Lines changed: 72 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -154,53 +154,53 @@ func TestIssue47881(t *testing.T) {
154154
tk.MustExec("create table t2(id int,name varchar(10),name1 varchar(10),name2 varchar(10),`date1` date);")
155155
tk.MustExec("insert into t2 values(1,'tt','ttt','tttt','2099-12-31'),(2,'dd','ddd','dddd','2099-12-31');")
156156
rs := tk.MustQuery(`WITH bzzs AS (
157-
SELECT
158-
count(1) AS bzn
159-
FROM
157+
SELECT
158+
count(1) AS bzn
159+
FROM
160160
t c
161-
),
161+
),
162162
tmp1 AS (
163-
SELECT
164-
t1.*
165-
FROM
166-
t1
167-
LEFT JOIN bzzs ON 1 = 1
168-
WHERE
169-
name IN ('tt')
163+
SELECT
164+
t1.*
165+
FROM
166+
t1
167+
LEFT JOIN bzzs ON 1 = 1
168+
WHERE
169+
name IN ('tt')
170170
AND bzn <> 1
171-
),
171+
),
172172
tmp2 AS (
173-
SELECT
174-
tmp1.*,
175-
date('2099-12-31') AS endate
176-
FROM
173+
SELECT
174+
tmp1.*,
175+
date('2099-12-31') AS endate
176+
FROM
177177
tmp1
178-
),
178+
),
179179
tmp3 AS (
180-
SELECT
181-
*
182-
FROM
183-
tmp2
184-
WHERE
185-
endate > CURRENT_DATE
186-
UNION ALL
187-
SELECT
188-
'1' AS id,
189-
'ss' AS name,
190-
'sss' AS name1,
191-
'ssss' AS name2,
192-
date('2099-12-31') AS endate
193-
FROM
194-
bzzs t1
195-
WHERE
180+
SELECT
181+
*
182+
FROM
183+
tmp2
184+
WHERE
185+
endate > CURRENT_DATE
186+
UNION ALL
187+
SELECT
188+
'1' AS id,
189+
'ss' AS name,
190+
'sss' AS name1,
191+
'ssss' AS name2,
192+
date('2099-12-31') AS endate
193+
FROM
194+
bzzs t1
195+
WHERE
196196
bzn = 1
197-
)
198-
SELECT
199-
c2.id,
200-
c3.id
201-
FROM
202-
t2 db
203-
LEFT JOIN tmp3 c2 ON c2.id = '1'
197+
)
198+
SELECT
199+
c2.id,
200+
c3.id
201+
FROM
202+
t2 db
203+
LEFT JOIN tmp3 c2 ON c2.id = '1'
204204
LEFT JOIN tmp3 c3 ON c3.id = '1';`)
205205
rs.Check(testkit.Rows("1 1", "1 1"))
206206
}
@@ -216,3 +216,35 @@ func TestIssue48969(t *testing.T) {
216216
tk.MustExec("update test2 set value=0 where test2.id in (select * from v1);")
217217
tk.MustQuery("select * from test2").Check(testkit.Rows("1 0", "2 0", "3 0", "4 4", "5 5"))
218218
}
219+
220+
func TestIssue50614(t *testing.T) {
221+
store := testkit.CreateMockStore(t)
222+
tk := testkit.NewTestKit(t, store)
223+
tk.MustExec("use test")
224+
tk.MustExec("drop table if exists tt")
225+
tk.MustExec("create table tt(a bigint, b bigint, c bigint, d bigint, e bigint, primary key(c,d));")
226+
tk.MustQuery("explain format = brief " +
227+
"update tt, (select 1 as c1 ,2 as c2 ,3 as c3, 4 as c4 union all select 2,3,4,5 union all select 3,4,5,6) tmp " +
228+
"set tt.a=tmp.c1, tt.b=tmp.c2 " +
229+
"where tt.c=tmp.c3 and tt.d=tmp.c4 and (tt.c,tt.d) in ((11,111),(22,222),(33,333),(44,444));").Check(
230+
testkit.Rows(
231+
"Update N/A root N/A",
232+
"└─Projection 0.00 root test.tt.a, test.tt.b, test.tt.c, test.tt.d, test.tt.e, Column#18, Column#19, Column#20, Column#21",
233+
" └─Projection 0.00 root test.tt.a, test.tt.b, test.tt.c, test.tt.d, test.tt.e, Column#18, Column#19, Column#20, Column#21",
234+
" └─IndexJoin 0.00 root inner join, inner:TableReader, outer key:Column#20, Column#21, inner key:test.tt.c, test.tt.d, equal cond:eq(Column#20, test.tt.c), eq(Column#21, test.tt.d), other cond:or(or(and(eq(Column#20, 11), eq(test.tt.d, 111)), and(eq(Column#20, 22), eq(test.tt.d, 222))), or(and(eq(Column#20, 33), eq(test.tt.d, 333)), and(eq(Column#20, 44), eq(test.tt.d, 444)))), or(or(and(eq(test.tt.c, 11), eq(Column#21, 111)), and(eq(test.tt.c, 22), eq(Column#21, 222))), or(and(eq(test.tt.c, 33), eq(Column#21, 333)), and(eq(test.tt.c, 44), eq(Column#21, 444))))",
235+
" ├─Union(Build) 0.00 root ",
236+
" │ ├─Projection 0.00 root Column#6, Column#7, Column#8, Column#9",
237+
" │ │ └─Projection 0.00 root 1->Column#6, 2->Column#7, 3->Column#8, 4->Column#9",
238+
" │ │ └─TableDual 0.00 root rows:0",
239+
" │ ├─Projection 0.00 root Column#10, Column#11, Column#12, Column#13",
240+
" │ │ └─Projection 0.00 root 2->Column#10, 3->Column#11, 4->Column#12, 5->Column#13",
241+
" │ │ └─TableDual 0.00 root rows:0",
242+
" │ └─Projection 0.00 root Column#14, Column#15, Column#16, Column#17",
243+
" │ └─Projection 0.00 root 3->Column#14, 4->Column#15, 5->Column#16, 6->Column#17",
244+
" │ └─TableDual 0.00 root rows:0",
245+
" └─TableReader(Probe) 0.00 root data:Selection",
246+
" └─Selection 0.00 cop[tikv] or(or(and(eq(test.tt.c, 11), eq(test.tt.d, 111)), and(eq(test.tt.c, 22), eq(test.tt.d, 222))), or(and(eq(test.tt.c, 33), eq(test.tt.d, 333)), and(eq(test.tt.c, 44), eq(test.tt.d, 444)))), or(or(eq(test.tt.c, 11), eq(test.tt.c, 22)), or(eq(test.tt.c, 33), eq(test.tt.c, 44))), or(or(eq(test.tt.d, 111), eq(test.tt.d, 222)), or(eq(test.tt.d, 333), eq(test.tt.d, 444)))",
247+
" └─TableRangeScan 0.00 cop[tikv] table:tt range: decided by [eq(test.tt.c, Column#20) eq(test.tt.d, Column#21)], keep order:false, stats:pseudo",
248+
),
249+
)
250+
}

planner/core/logical_plans.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,9 +1142,13 @@ type LogicalMaxOneRow struct {
11421142
}
11431143

11441144
// LogicalTableDual represents a dual table plan.
1145+
// Note that sometimes we don't set schema for LogicalTableDual (most notably in buildTableDual()), which means
1146+
// outputting 0/1 row with zero column. This semantic may be different from your expectation sometimes but should not
1147+
// cause any actual problems now.
11451148
type LogicalTableDual struct {
11461149
logicalSchemaProducer
11471150

1151+
// RowCount could only be 0 or 1.
11481152
RowCount int
11491153
}
11501154

planner/core/rule_predicate_push_down.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -508,11 +508,6 @@ func (p *LogicalProjection) PredicatePushDown(predicates []expression.Expression
508508
return predicates, child
509509
}
510510
}
511-
if len(p.children) == 1 {
512-
if _, isDual := p.children[0].(*LogicalTableDual); isDual {
513-
return predicates, p
514-
}
515-
}
516511
for _, cond := range predicates {
517512
substituted, hasFailed, newFilter := expression.ColumnSubstituteImpl(cond, p.Schema(), p.Exprs, true)
518513
if substituted && !hasFailed && !expression.HasGetSetVarFunc(newFilter) {

0 commit comments

Comments
 (0)