Skip to content

Commit f12b205

Browse files
committed
Merge branch 'master' into partition-table-split
2 parents 8fd783c + 36bb1ae commit f12b205

File tree

101 files changed

+3768
-710
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

101 files changed

+3768
-710
lines changed

bindinfo/bind.go

+169
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
// Copyright 2019 PingCAP, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
package bindinfo
15+
16+
import "github.com/pingcap/parser/ast"
17+
18+
// BindHint will add hints for originStmt according to hintedStmt' hints.
19+
func BindHint(originStmt, hintedStmt ast.StmtNode) ast.StmtNode {
20+
switch x := originStmt.(type) {
21+
case *ast.SelectStmt:
22+
return selectBind(x, hintedStmt.(*ast.SelectStmt))
23+
default:
24+
return originStmt
25+
}
26+
}
27+
28+
func selectBind(originalNode, hintedNode *ast.SelectStmt) *ast.SelectStmt {
29+
if hintedNode.TableHints != nil {
30+
originalNode.TableHints = hintedNode.TableHints
31+
}
32+
if originalNode.From != nil {
33+
originalNode.From.TableRefs = resultSetNodeBind(originalNode.From.TableRefs, hintedNode.From.TableRefs).(*ast.Join)
34+
}
35+
if originalNode.Where != nil {
36+
originalNode.Where = exprBind(originalNode.Where, hintedNode.Where).(ast.ExprNode)
37+
}
38+
39+
if originalNode.Having != nil {
40+
originalNode.Having.Expr = exprBind(originalNode.Having.Expr, hintedNode.Having.Expr)
41+
}
42+
43+
if originalNode.OrderBy != nil {
44+
originalNode.OrderBy = orderByBind(originalNode.OrderBy, hintedNode.OrderBy)
45+
}
46+
47+
if originalNode.Fields != nil {
48+
origFields := originalNode.Fields.Fields
49+
hintFields := hintedNode.Fields.Fields
50+
for idx := range origFields {
51+
origFields[idx].Expr = exprBind(origFields[idx].Expr, hintFields[idx].Expr)
52+
}
53+
}
54+
return originalNode
55+
}
56+
57+
func orderByBind(originalNode, hintedNode *ast.OrderByClause) *ast.OrderByClause {
58+
for idx := 0; idx < len(originalNode.Items); idx++ {
59+
originalNode.Items[idx].Expr = exprBind(originalNode.Items[idx].Expr, hintedNode.Items[idx].Expr)
60+
}
61+
return originalNode
62+
}
63+
64+
func exprBind(originalNode, hintedNode ast.ExprNode) ast.ExprNode {
65+
switch v := originalNode.(type) {
66+
case *ast.SubqueryExpr:
67+
if v.Query != nil {
68+
v.Query = resultSetNodeBind(v.Query, hintedNode.(*ast.SubqueryExpr).Query)
69+
}
70+
case *ast.ExistsSubqueryExpr:
71+
if v.Sel != nil {
72+
v.Sel.(*ast.SubqueryExpr).Query = resultSetNodeBind(v.Sel.(*ast.SubqueryExpr).Query, hintedNode.(*ast.ExistsSubqueryExpr).Sel.(*ast.SubqueryExpr).Query)
73+
}
74+
case *ast.PatternInExpr:
75+
if v.Sel != nil {
76+
v.Sel.(*ast.SubqueryExpr).Query = resultSetNodeBind(v.Sel.(*ast.SubqueryExpr).Query, hintedNode.(*ast.PatternInExpr).Sel.(*ast.SubqueryExpr).Query)
77+
}
78+
case *ast.BinaryOperationExpr:
79+
if v.L != nil {
80+
v.L = exprBind(v.L, hintedNode.(*ast.BinaryOperationExpr).L)
81+
}
82+
if v.R != nil {
83+
v.R = exprBind(v.R, hintedNode.(*ast.BinaryOperationExpr).R)
84+
}
85+
case *ast.IsNullExpr:
86+
if v.Expr != nil {
87+
v.Expr = exprBind(v.Expr, hintedNode.(*ast.IsNullExpr).Expr)
88+
}
89+
case *ast.IsTruthExpr:
90+
if v.Expr != nil {
91+
v.Expr = exprBind(v.Expr, hintedNode.(*ast.IsTruthExpr).Expr)
92+
}
93+
case *ast.PatternLikeExpr:
94+
if v.Pattern != nil {
95+
v.Pattern = exprBind(v.Pattern, hintedNode.(*ast.PatternLikeExpr).Pattern)
96+
}
97+
case *ast.CompareSubqueryExpr:
98+
if v.L != nil {
99+
v.L = exprBind(v.L, hintedNode.(*ast.CompareSubqueryExpr).L)
100+
}
101+
if v.R != nil {
102+
v.R = exprBind(v.R, hintedNode.(*ast.CompareSubqueryExpr).R)
103+
}
104+
case *ast.BetweenExpr:
105+
if v.Left != nil {
106+
v.Left = exprBind(v.Left, hintedNode.(*ast.BetweenExpr).Left)
107+
}
108+
if v.Right != nil {
109+
v.Right = exprBind(v.Right, hintedNode.(*ast.BetweenExpr).Right)
110+
}
111+
case *ast.UnaryOperationExpr:
112+
if v.V != nil {
113+
v.V = exprBind(v.V, hintedNode.(*ast.UnaryOperationExpr).V)
114+
}
115+
case *ast.CaseExpr:
116+
if v.Value != nil {
117+
v.Value = exprBind(v.Value, hintedNode.(*ast.CaseExpr).Value)
118+
}
119+
if v.ElseClause != nil {
120+
v.ElseClause = exprBind(v.ElseClause, hintedNode.(*ast.CaseExpr).ElseClause)
121+
}
122+
}
123+
return originalNode
124+
}
125+
126+
func resultSetNodeBind(originalNode, hintedNode ast.ResultSetNode) ast.ResultSetNode {
127+
switch x := originalNode.(type) {
128+
case *ast.Join:
129+
return joinBind(x, hintedNode.(*ast.Join))
130+
case *ast.TableSource:
131+
ts, _ := hintedNode.(*ast.TableSource)
132+
switch v := x.Source.(type) {
133+
case *ast.SelectStmt:
134+
x.Source = selectBind(v, ts.Source.(*ast.SelectStmt))
135+
case *ast.UnionStmt:
136+
x.Source = unionSelectBind(v, hintedNode.(*ast.TableSource).Source.(*ast.UnionStmt))
137+
case *ast.TableName:
138+
x.Source.(*ast.TableName).IndexHints = ts.Source.(*ast.TableName).IndexHints
139+
}
140+
return x
141+
case *ast.SelectStmt:
142+
return selectBind(x, hintedNode.(*ast.SelectStmt))
143+
case *ast.UnionStmt:
144+
return unionSelectBind(x, hintedNode.(*ast.UnionStmt))
145+
default:
146+
return x
147+
}
148+
}
149+
150+
func joinBind(originalNode, hintedNode *ast.Join) *ast.Join {
151+
if originalNode.Left != nil {
152+
originalNode.Left = resultSetNodeBind(originalNode.Left, hintedNode.Left)
153+
}
154+
155+
if hintedNode.Right != nil {
156+
originalNode.Right = resultSetNodeBind(originalNode.Right, hintedNode.Right)
157+
}
158+
159+
return originalNode
160+
}
161+
162+
func unionSelectBind(originalNode, hintedNode *ast.UnionStmt) ast.ResultSetNode {
163+
selects := originalNode.SelectList.Selects
164+
for i := len(selects) - 1; i >= 0; i-- {
165+
originalNode.SelectList.Selects[i] = selectBind(selects[i], hintedNode.SelectList.Selects[i])
166+
}
167+
168+
return originalNode
169+
}

bindinfo/bind_test.go

+204
Original file line numberDiff line numberDiff line change
@@ -220,3 +220,207 @@ func (s *testSuite) TestGlobalBinding(c *C) {
220220
_, err = tk.Exec("create global binding for select * from t using select * from t1 use index for join(index_t)")
221221
c.Assert(err, NotNil, Commentf("err %v", err))
222222
}
223+
224+
func (s *testSuite) TestSessionBinding(c *C) {
225+
tk := testkit.NewTestKit(c, s.store)
226+
s.cleanBindingEnv(tk)
227+
tk.MustExec("use test")
228+
tk.MustExec("drop table if exists t")
229+
tk.MustExec("drop table if exists t1")
230+
tk.MustExec("create table t(i int, s varchar(20))")
231+
tk.MustExec("create table t1(i int, s varchar(20))")
232+
tk.MustExec("create index index_t on t(i,s)")
233+
234+
_, err := tk.Exec("create session binding for select * from t where i>100 using select * from t use index(index_t) where i>100")
235+
c.Assert(err, IsNil, Commentf("err %v", err))
236+
237+
time.Sleep(time.Second * 1)
238+
_, err = tk.Exec("create session binding for select * from t where i>99 using select * from t use index(index_t) where i>99")
239+
c.Assert(err, IsNil)
240+
241+
handle := tk.Se.Value(bindinfo.SessionBindInfoKeyType).(*bindinfo.SessionHandle)
242+
bindData := handle.GetBindRecord("select * from t where i > ?", "test")
243+
c.Check(bindData, NotNil)
244+
c.Check(bindData.OriginalSQL, Equals, "select * from t where i > ?")
245+
c.Check(bindData.BindSQL, Equals, "select * from t use index(index_t) where i>99")
246+
c.Check(bindData.Db, Equals, "test")
247+
c.Check(bindData.Status, Equals, "using")
248+
c.Check(bindData.Charset, NotNil)
249+
c.Check(bindData.Collation, NotNil)
250+
c.Check(bindData.CreateTime, NotNil)
251+
c.Check(bindData.UpdateTime, NotNil)
252+
253+
rs, err := tk.Exec("show global bindings")
254+
c.Assert(err, IsNil)
255+
chk := rs.NewRecordBatch()
256+
err = rs.Next(context.TODO(), chk)
257+
c.Check(err, IsNil)
258+
c.Check(chk.NumRows(), Equals, 0)
259+
260+
rs, err = tk.Exec("show session bindings")
261+
c.Assert(err, IsNil)
262+
chk = rs.NewRecordBatch()
263+
err = rs.Next(context.TODO(), chk)
264+
c.Check(err, IsNil)
265+
c.Check(chk.NumRows(), Equals, 1)
266+
row := chk.GetRow(0)
267+
c.Check(row.GetString(0), Equals, "select * from t where i > ?")
268+
c.Check(row.GetString(1), Equals, "select * from t use index(index_t) where i>99")
269+
c.Check(row.GetString(2), Equals, "test")
270+
c.Check(row.GetString(3), Equals, "using")
271+
c.Check(row.GetTime(4), NotNil)
272+
c.Check(row.GetTime(5), NotNil)
273+
c.Check(row.GetString(6), NotNil)
274+
c.Check(row.GetString(7), NotNil)
275+
276+
_, err = tk.Exec("drop session binding for select * from t where i>99")
277+
c.Assert(err, IsNil)
278+
bindData = handle.GetBindRecord("select * from t where i > ?", "test")
279+
c.Check(bindData, NotNil)
280+
c.Check(bindData.OriginalSQL, Equals, "select * from t where i > ?")
281+
c.Check(bindData.Status, Equals, "deleted")
282+
}
283+
284+
func (s *testSuite) TestGlobalAndSessionBindingBothExist(c *C) {
285+
tk := testkit.NewTestKit(c, s.store)
286+
s.cleanBindingEnv(tk)
287+
tk.MustExec("use test")
288+
tk.MustExec("drop table if exists t1")
289+
tk.MustExec("drop table if exists t2")
290+
tk.MustExec("create table t1(id int)")
291+
tk.MustExec("create table t2(id int)")
292+
293+
tk.MustQuery("explain SELECT * from t1,t2 where t1.id = t2.id").Check(testkit.Rows(
294+
"HashLeftJoin_8 12487.50 root inner join, inner:TableReader_15, equal:[eq(test.t1.id, test.t2.id)]",
295+
"├─TableReader_12 9990.00 root data:Selection_11",
296+
"│ └─Selection_11 9990.00 cop not(isnull(test.t1.id))",
297+
"│ └─TableScan_10 10000.00 cop table:t1, range:[-inf,+inf], keep order:false, stats:pseudo",
298+
"└─TableReader_15 9990.00 root data:Selection_14",
299+
" └─Selection_14 9990.00 cop not(isnull(test.t2.id))",
300+
" └─TableScan_13 10000.00 cop table:t2, range:[-inf,+inf], keep order:false, stats:pseudo",
301+
))
302+
303+
tk.MustQuery("explain SELECT /*+ TIDB_SMJ(t1, t2) */ * from t1,t2 where t1.id = t2.id").Check(testkit.Rows(
304+
"MergeJoin_7 12487.50 root inner join, left key:test.t1.id, right key:test.t2.id",
305+
"├─Sort_11 9990.00 root test.t1.id:asc",
306+
"│ └─TableReader_10 9990.00 root data:Selection_9",
307+
"│ └─Selection_9 9990.00 cop not(isnull(test.t1.id))",
308+
"│ └─TableScan_8 10000.00 cop table:t1, range:[-inf,+inf], keep order:false, stats:pseudo",
309+
"└─Sort_15 9990.00 root test.t2.id:asc",
310+
" └─TableReader_14 9990.00 root data:Selection_13",
311+
" └─Selection_13 9990.00 cop not(isnull(test.t2.id))",
312+
" └─TableScan_12 10000.00 cop table:t2, range:[-inf,+inf], keep order:false, stats:pseudo",
313+
))
314+
315+
tk.MustExec("create global binding for SELECT * from t1,t2 where t1.id = t2.id using SELECT /*+ TIDB_SMJ(t1, t2) */ * from t1,t2 where t1.id = t2.id")
316+
317+
tk.MustQuery("explain SELECT * from t1,t2 where t1.id = t2.id").Check(testkit.Rows(
318+
"MergeJoin_7 12487.50 root inner join, left key:test.t1.id, right key:test.t2.id",
319+
"├─Sort_11 9990.00 root test.t1.id:asc",
320+
"│ └─TableReader_10 9990.00 root data:Selection_9",
321+
"│ └─Selection_9 9990.00 cop not(isnull(test.t1.id))",
322+
"│ └─TableScan_8 10000.00 cop table:t1, range:[-inf,+inf], keep order:false, stats:pseudo",
323+
"└─Sort_15 9990.00 root test.t2.id:asc",
324+
" └─TableReader_14 9990.00 root data:Selection_13",
325+
" └─Selection_13 9990.00 cop not(isnull(test.t2.id))",
326+
" └─TableScan_12 10000.00 cop table:t2, range:[-inf,+inf], keep order:false, stats:pseudo",
327+
))
328+
329+
tk.MustExec("drop global binding for SELECT * from t1,t2 where t1.id = t2.id")
330+
331+
tk.MustQuery("explain SELECT * from t1,t2 where t1.id = t2.id").Check(testkit.Rows(
332+
"HashLeftJoin_8 12487.50 root inner join, inner:TableReader_15, equal:[eq(test.t1.id, test.t2.id)]",
333+
"├─TableReader_12 9990.00 root data:Selection_11",
334+
"│ └─Selection_11 9990.00 cop not(isnull(test.t1.id))",
335+
"│ └─TableScan_10 10000.00 cop table:t1, range:[-inf,+inf], keep order:false, stats:pseudo",
336+
"└─TableReader_15 9990.00 root data:Selection_14",
337+
" └─Selection_14 9990.00 cop not(isnull(test.t2.id))",
338+
" └─TableScan_13 10000.00 cop table:t2, range:[-inf,+inf], keep order:false, stats:pseudo",
339+
))
340+
}
341+
342+
func (s *testSuite) TestExplain(c *C) {
343+
tk := testkit.NewTestKit(c, s.store)
344+
s.cleanBindingEnv(tk)
345+
tk.MustExec("use test")
346+
tk.MustExec("drop table if exists t1")
347+
tk.MustExec("drop table if exists t2")
348+
tk.MustExec("create table t1(id int)")
349+
tk.MustExec("create table t2(id int)")
350+
351+
tk.MustQuery("explain SELECT * from t1,t2 where t1.id = t2.id").Check(testkit.Rows(
352+
"HashLeftJoin_8 12487.50 root inner join, inner:TableReader_15, equal:[eq(test.t1.id, test.t2.id)]",
353+
"├─TableReader_12 9990.00 root data:Selection_11",
354+
"│ └─Selection_11 9990.00 cop not(isnull(test.t1.id))",
355+
"│ └─TableScan_10 10000.00 cop table:t1, range:[-inf,+inf], keep order:false, stats:pseudo",
356+
"└─TableReader_15 9990.00 root data:Selection_14",
357+
" └─Selection_14 9990.00 cop not(isnull(test.t2.id))",
358+
" └─TableScan_13 10000.00 cop table:t2, range:[-inf,+inf], keep order:false, stats:pseudo",
359+
))
360+
361+
tk.MustQuery("explain SELECT /*+ TIDB_SMJ(t1, t2) */ * from t1,t2 where t1.id = t2.id").Check(testkit.Rows(
362+
"MergeJoin_7 12487.50 root inner join, left key:test.t1.id, right key:test.t2.id",
363+
"├─Sort_11 9990.00 root test.t1.id:asc",
364+
"│ └─TableReader_10 9990.00 root data:Selection_9",
365+
"│ └─Selection_9 9990.00 cop not(isnull(test.t1.id))",
366+
"│ └─TableScan_8 10000.00 cop table:t1, range:[-inf,+inf], keep order:false, stats:pseudo",
367+
"└─Sort_15 9990.00 root test.t2.id:asc",
368+
" └─TableReader_14 9990.00 root data:Selection_13",
369+
" └─Selection_13 9990.00 cop not(isnull(test.t2.id))",
370+
" └─TableScan_12 10000.00 cop table:t2, range:[-inf,+inf], keep order:false, stats:pseudo",
371+
))
372+
373+
tk.MustExec("create global binding for SELECT * from t1,t2 where t1.id = t2.id using SELECT /*+ TIDB_SMJ(t1, t2) */ * from t1,t2 where t1.id = t2.id")
374+
375+
tk.MustQuery("explain SELECT * from t1,t2 where t1.id = t2.id").Check(testkit.Rows(
376+
"MergeJoin_7 12487.50 root inner join, left key:test.t1.id, right key:test.t2.id",
377+
"├─Sort_11 9990.00 root test.t1.id:asc",
378+
"│ └─TableReader_10 9990.00 root data:Selection_9",
379+
"│ └─Selection_9 9990.00 cop not(isnull(test.t1.id))",
380+
"│ └─TableScan_8 10000.00 cop table:t1, range:[-inf,+inf], keep order:false, stats:pseudo",
381+
"└─Sort_15 9990.00 root test.t2.id:asc",
382+
" └─TableReader_14 9990.00 root data:Selection_13",
383+
" └─Selection_13 9990.00 cop not(isnull(test.t2.id))",
384+
" └─TableScan_12 10000.00 cop table:t2, range:[-inf,+inf], keep order:false, stats:pseudo",
385+
))
386+
387+
tk.MustExec("drop global binding for SELECT * from t1,t2 where t1.id = t2.id")
388+
}
389+
390+
func (s *testSuite) TestErrorBind(c *C) {
391+
tk := testkit.NewTestKit(c, s.store)
392+
s.cleanBindingEnv(tk)
393+
tk.MustExec("use test")
394+
tk.MustExec("drop table if exists t")
395+
tk.MustExec("drop table if exists t1")
396+
tk.MustExec("create table t(i int, s varchar(20))")
397+
tk.MustExec("create table t1(i int, s varchar(20))")
398+
tk.MustExec("create index index_t on t(i,s)")
399+
400+
_, err := tk.Exec("create global binding for select * from t where i>100 using select * from t use index(index_t) where i>100")
401+
c.Assert(err, IsNil, Commentf("err %v", err))
402+
403+
bindData := s.domain.BindHandle().GetBindRecord("select * from t where i > ?", "test")
404+
c.Check(bindData, NotNil)
405+
c.Check(bindData.OriginalSQL, Equals, "select * from t where i > ?")
406+
c.Check(bindData.BindSQL, Equals, "select * from t use index(index_t) where i>100")
407+
c.Check(bindData.Db, Equals, "test")
408+
c.Check(bindData.Status, Equals, "using")
409+
c.Check(bindData.Charset, NotNil)
410+
c.Check(bindData.Collation, NotNil)
411+
c.Check(bindData.CreateTime, NotNil)
412+
c.Check(bindData.UpdateTime, NotNil)
413+
414+
tk.MustExec("drop index index_t on t")
415+
_, err = tk.Exec("select * from t where i > 10")
416+
c.Check(err, IsNil)
417+
418+
s.domain.BindHandle().DropInvalidBindRecord()
419+
420+
rs, err := tk.Exec("show global bindings")
421+
c.Assert(err, IsNil)
422+
chk := rs.NewRecordBatch()
423+
err = rs.Next(context.TODO(), chk)
424+
c.Check(err, IsNil)
425+
c.Check(chk.NumRows(), Equals, 0)
426+
}

0 commit comments

Comments
 (0)