Skip to content

Commit 1577799

Browse files
authored
planner: remove the limitation that predicates can't be pushed through Projection on TableDual (#51329) (#52125)
close #50614
1 parent efd2fab commit 1577799

File tree

3 files changed

+76
-45
lines changed

3 files changed

+76
-45
lines changed

planner/core/issuetest/planner_issue_test.go

Lines changed: 72 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -103,53 +103,53 @@ func TestIssue47781(t *testing.T) {
103103
tk.MustExec("create table t2(id int,name varchar(10),name1 varchar(10),name2 varchar(10),`date1` date)")
104104
tk.MustExec("insert into t2 values(1,'tt','ttt','tttt','2099-12-31'),(2,'dd','ddd','dddd','2099-12-31')")
105105
tk.MustQuery(`WITH bzzs AS (
106-
SELECT
107-
count(1) AS bzn
108-
FROM
106+
SELECT
107+
count(1) AS bzn
108+
FROM
109109
t c
110-
),
110+
),
111111
tmp1 AS (
112-
SELECT
113-
t1.*
114-
FROM
115-
t1
116-
LEFT JOIN bzzs ON 1 = 1
117-
WHERE
118-
name IN ('tt')
112+
SELECT
113+
t1.*
114+
FROM
115+
t1
116+
LEFT JOIN bzzs ON 1 = 1
117+
WHERE
118+
name IN ('tt')
119119
AND bzn <> 1
120-
),
120+
),
121121
tmp2 AS (
122-
SELECT
123-
tmp1.*,
124-
date('2099-12-31') AS endate
125-
FROM
122+
SELECT
123+
tmp1.*,
124+
date('2099-12-31') AS endate
125+
FROM
126126
tmp1
127-
),
127+
),
128128
tmp3 AS (
129-
SELECT
130-
*
131-
FROM
132-
tmp2
133-
WHERE
134-
endate > CURRENT_DATE
135-
UNION ALL
136-
SELECT
137-
'1' AS id,
138-
'ss' AS name,
139-
'sss' AS name1,
140-
'ssss' AS name2,
141-
date('2099-12-31') AS endate
142-
FROM
143-
bzzs t1
144-
WHERE
129+
SELECT
130+
*
131+
FROM
132+
tmp2
133+
WHERE
134+
endate > CURRENT_DATE
135+
UNION ALL
136+
SELECT
137+
'1' AS id,
138+
'ss' AS name,
139+
'sss' AS name1,
140+
'ssss' AS name2,
141+
date('2099-12-31') AS endate
142+
FROM
143+
bzzs t1
144+
WHERE
145145
bzn = 1
146-
)
147-
SELECT
148-
c2.id,
149-
c3.id
150-
FROM
151-
t2 db
152-
LEFT JOIN tmp3 c2 ON c2.id = '1'
146+
)
147+
SELECT
148+
c2.id,
149+
c3.id
150+
FROM
151+
t2 db
152+
LEFT JOIN tmp3 c2 ON c2.id = '1'
153153
LEFT JOIN tmp3 c3 ON c3.id = '1';`).Check(testkit.Rows("1 1", "1 1"))
154154
}
155155

@@ -167,3 +167,35 @@ func TestIssue51560(t *testing.T) {
167167
tk.MustQuery("select b.b from A a left join (B b left join C c on b.b = c.b) on b.b = a.b where a.a in (2, 3);").Sort().Check(testkit.Rows("1", "2"))
168168
tk.MustQuery("select b.b from A a left join (B b left join C c on b.b = c.b) on b.b = a.b where a.a in (2, 3, null);").Sort().Check(testkit.Rows("1", "2"))
169169
}
170+
171+
func TestIssue50614(t *testing.T) {
172+
store := testkit.CreateMockStore(t)
173+
tk := testkit.NewTestKit(t, store)
174+
tk.MustExec("use test")
175+
tk.MustExec("drop table if exists tt")
176+
tk.MustExec("create table tt(a bigint, b bigint, c bigint, d bigint, e bigint, primary key(c,d));")
177+
tk.MustQuery("explain format = brief " +
178+
"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 " +
179+
"set tt.a=tmp.c1, tt.b=tmp.c2 " +
180+
"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(
181+
testkit.Rows(
182+
"Update N/A root N/A",
183+
"└─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",
184+
" └─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",
185+
" └─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))))",
186+
" ├─Union(Build) 0.00 root ",
187+
" │ ├─Projection 0.00 root Column#6, Column#7, Column#8, Column#9",
188+
" │ │ └─Projection 0.00 root 1->Column#6, 2->Column#7, 3->Column#8, 4->Column#9",
189+
" │ │ └─TableDual 0.00 root rows:0",
190+
" │ ├─Projection 0.00 root Column#10, Column#11, Column#12, Column#13",
191+
" │ │ └─Projection 0.00 root 2->Column#10, 3->Column#11, 4->Column#12, 5->Column#13",
192+
" │ │ └─TableDual 0.00 root rows:0",
193+
" │ └─Projection 0.00 root Column#14, Column#15, Column#16, Column#17",
194+
" │ └─Projection 0.00 root 3->Column#14, 4->Column#15, 5->Column#16, 6->Column#17",
195+
" │ └─TableDual 0.00 root rows:0",
196+
" └─TableReader(Probe) 0.00 root data:Selection",
197+
" └─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)))",
198+
" └─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",
199+
),
200+
)
201+
}

planner/core/logical_plans.go

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

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

1149+
// RowCount could only be 0 or 1.
11461150
RowCount int
11471151
}
11481152

planner/core/rule_predicate_push_down.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -505,11 +505,6 @@ func (p *LogicalProjection) PredicatePushDown(predicates []expression.Expression
505505
return predicates, child
506506
}
507507
}
508-
if len(p.children) == 1 {
509-
if _, isDual := p.children[0].(*LogicalTableDual); isDual {
510-
return predicates, p
511-
}
512-
}
513508
for _, cond := range predicates {
514509
substituted, hasFailed, newFilter := expression.ColumnSubstituteImpl(cond, p.Schema(), p.Exprs, true)
515510
if substituted && !hasFailed && !expression.HasGetSetVarFunc(newFilter) {

0 commit comments

Comments
 (0)