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

Merge release-3.0 to release-3.1 #14788

Merged
merged 123 commits into from
Feb 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
123 commits
Select commit Hold shift + click to select a range
e8e0fe9
planner/core: fix not null flag for using and natural join (#13735) (…
alivxxx Nov 26, 2019
bcf2f07
expression: fix the corner case of CAST int as unsigned real/decimal …
Deardrops Nov 27, 2019
1db38d5
expression : fix function 'binSearch' in builtinIntervalRealSig not …
sre-bot Nov 27, 2019
159c16d
fix single (#13563)
sre-bot Nov 27, 2019
16781a3
types: Fix potential timezone related bugs caused by `gotime.Local` (…
sre-bot Nov 28, 2019
84e4386
store/tikv: fix lockTTL too large if local time is behind timestamp (…
coocood Dec 3, 2019
599d1c4
ddl: update the error message of "modify/change column" to make it ea…
zimulala Dec 3, 2019
ab73fde
executor: fix data race in TestFastAnalyze (#12910) (#13872)
sre-bot Dec 4, 2019
251574b
privilege: using system session to execute internal sql of RBAC (#138…
Dec 5, 2019
b6a30b8
config: add configuration entry make TiDB version string configurable…
reafans Dec 5, 2019
050a356
*: support split partition table region (#12213) (#13929)
crazycs520 Dec 5, 2019
0201879
*: wait for binlog recovering when using HTTP API (#13740) (#13892)
jackysp Dec 6, 2019
cfbe06a
privilege: fix privilege check of `GRANT ROLE` (#13896) (#13932)
sre-bot Dec 6, 2019
c1624d8
planner/core: raise 'No database selected' error for grant statement …
tiancaiamao Dec 6, 2019
e4bcdd4
executor: fix inconsistent of grants privileges with MySQL when execu…
Dec 9, 2019
e329379
executor: report error in `AddRecordLD` function (#13980)
cfzjywxk Dec 10, 2019
9da133f
*: do not start slow-log timer before parsing (#13846) (#13898)
jackysp Dec 10, 2019
d006af9
bindinfo: fix bindinfo bugs when update cache (#13875) (#13891)
alivxxx Dec 10, 2019
969a020
executor: change pessimistic lock wait start for one statement (#13990)
cfzjywxk Dec 10, 2019
cba3e1a
planner: fixup some bugs with `DEFAULT` expression (#13168)(#13211)(#…
Deardrops Dec 11, 2019
35159fe
session: if txn invalid do not active it and return an error (#13935)…
jackysp Dec 11, 2019
ce88d7b
types: fix insert error when convert string to float (#13716) (#14011)
alivxxx Dec 11, 2019
3a10bb8
privilege: fix `REVOKE` privilege check incompatibility with MySQL (#…
sre-bot Dec 11, 2019
b10d1a5
store/tikv: fix a memory leak in the batchClient for the large transa…
sre-bot Dec 12, 2019
c31b745
stats: remove the lower bound of auto analyze ratio (#13995) (#14015)
alivxxx Dec 12, 2019
be7cb4d
bindinfo, planner: fix sql bind when sql has symbol list (#13889) (#1…
SunRunAway Dec 13, 2019
d312f8a
ddl: fix index length calculation (#13779)
sre-bot Dec 16, 2019
13b945d
*: lock unchanged rows for pessimistic transaction (#14045) (#14050)
coocood Dec 16, 2019
b9ba3ef
mocktikv: add the missing ConflictCommitTS (#14064) (#14080)
sre-bot Dec 16, 2019
5d5b071
executor: init the final recv channel of hash agg with enough chunk (…
winoros Dec 17, 2019
2ed7510
tikv: check lock timeout again after resolving lock (#14066) (#14083)
sticnarf Dec 17, 2019
a3ca490
executor: refine the check of onlyFullGroupBy when groupByItem is par…
XuHuaiyu Dec 17, 2019
9a103ef
server: set `system_time_zone` from `systemTZ` (#13934) (#14086)
bb7133 Dec 17, 2019
3ff5455
planner: fix bug for logical rule outer join elimination (#13947) (#1…
lzmhhh123 Dec 17, 2019
d0502a6
privilege: make 'grant all privileges' work right (#11449) (#14092)
lysu Dec 17, 2019
1866f27
table/tables: fix an error message when table has no partition for va…
sre-bot Dec 18, 2019
4d34a76
bindinfo: remove last semicolon of bind sqls (#14110) (#14113)
alivxxx Dec 18, 2019
7ea2a21
privilege: fix privilege check of `CREATE ROLE` and `DROP ROLE` (#139…
Dec 18, 2019
c598e4b
planner/core: add bit column test about display width range (#11985) …
tangenta Dec 18, 2019
f2ae63e
executor: add SHUTDOWN command and privilege check (#12804) (#14104)
lysu Dec 19, 2019
e4c2216
privilege: fix atomic problem of `DROP ROLE` (#14090) (#14130)
Dec 19, 2019
4cfaf04
planner: fix wrong stats for physical union scan (#14093) (#14133)
lzmhhh123 Dec 19, 2019
1c224aa
session: fix `show variable` result of `tidb_enable_window_function` …
sre-bot Dec 19, 2019
fda6d3b
gcworker: fix potential gcworker goroutine leak during tikv down (#13…
lysu Dec 19, 2019
1686c6b
ddl: fix ErrGCTooEarly when adding an index to the partition table (#…
sre-bot Dec 19, 2019
37b1d77
add binlog prewrite time to record binlog prewrite time consume (#14138)
cfzjywxk Dec 19, 2019
9efbf48
session: support 'GLOBAL SCOPE' for `tidb_enable_table_partition` (#1…
bb7133 Dec 20, 2019
b52cccd
*: revert #10124 and remove sql mode `PadCharToFullLength` (#14007) (…
winoros Dec 20, 2019
620a6c0
infoschema, util: Add more fields to table `events_statements_summary…
djshow832 Dec 20, 2019
c6c5fbf
infoschema, util: refresh statement summary table periodically (#1368…
djshow832 Dec 20, 2019
45c52c4
infoschema, util: add table `events_statements_summary_by_digest_hist…
djshow832 Dec 20, 2019
b47381b
infoschema: add 3 fields to statement summary table (#14096) (#14168)
djshow832 Dec 20, 2019
adbb8b9
set global variable tidb_txn_mode to pessimistic during bootstrap. (#…
sre-bot Dec 21, 2019
36e428e
*: fix condition check push down for pessimistic transaction (#14141)…
jackysp Dec 23, 2019
55a6b73
privilege: fix privilege problem after upgrade (#14177) (#14178)
Dec 23, 2019
70e025f
ddl: check foreign key constraint when drop,modify,change column (#14…
crazycs520 Dec 23, 2019
2f3f57a
executor: cherry-pick lock ctx to 3.0 (#14201)
cfzjywxk Dec 24, 2019
1a32e51
executor: add lock keys duration metric (#14194)
cfzjywxk Dec 24, 2019
da1427a
store/tikv: fix CheckStreamTimeoutLoop goroutine leak (#13812) (#14227)
SunRunAway Dec 25, 2019
4eb6c8e
executor: avoid `ProjectoinExec`'s goroutine leak (#14127) (#14226)
fzhedu Dec 26, 2019
eb355be
*: support certificate based authentication (#13955) (#14202)
lysu Dec 26, 2019
37f099d
server: add lock keys duration in slow log (#14246)
cfzjywxk Dec 26, 2019
90a37b9
fix missing register (#14256)
cfzjywxk Dec 27, 2019
6adce23
store/tikv: keepalive with pd (#14118) (#14233)
nolouch Dec 27, 2019
8f13cf1
executor: add rollback in `releaseSysSession` (#14272)
sre-bot Dec 27, 2019
64abbbd
ddl: fix the bug that VIEWs can be dropped by `DROP TABLE` syn… (#14052)
sre-bot Dec 28, 2019
1ee1b74
planner: support plan digest (#13124) (#14258)
crazycs520 Dec 30, 2019
d84aab8
infoschema: add plan digest to slow log and slow_query (#14000) (#14292)
crazycs520 Jan 1, 2020
e1d8b41
infoschema: add plan field to the statement summary tables (#14182) (…
sre-bot Jan 2, 2020
81d276e
server: log last executed prepared stmt when panic (#12905) (#14322)
lysu Jan 2, 2020
017b043
*: only add union scan when dirty table is not empty (#14265) (#14321)
winoros Jan 3, 2020
09003c1
plan, partition: add fast access path for hash partition (#13772) (#1…
Jan 3, 2020
e2ecc32
executor: refactor union_scan executor by using txn_mem_buffer_reader…
crazycs520 Jan 7, 2020
3c90149
ddl: fix anonymous indexes on the `primary` column (#14250) (#14310)
sre-bot Jan 7, 2020
ca3e7ec
server: support tag sql in pprof result (#14312) (#14329)
lysu Jan 7, 2020
00f0015
metrics,store: add a metric for ttlManager to record the lifet… (#14300)
sre-bot Jan 7, 2020
b89108b
executor: fix wrong behavior when `ENUM` column meet Aggregati… (#14364)
sre-bot Jan 7, 2020
60dbae1
*: fix schema change validation for partitioned table when transactio…
tiancaiamao Jan 7, 2020
294f393
executor: refactor union scan and dirty table (#11702) (#14057) (#14383)
crazycs520 Jan 8, 2020
cd8fa79
*: support auto_increment_increment & auto_increment_offset. (#14301…
AilinKid Jan 8, 2020
43ec970
table: avoid write untouched index in auto commit and avoid get untou…
crazycs520 Jan 9, 2020
afd93cb
planner: apply max/min elimination when other aggregations exist (#14…
eurekaka Jan 9, 2020
ae23817
done (#14391)
wjhuang2016 Jan 9, 2020
948b5c6
planner: enhance the rule max_min_eliminate to support multiple agg (…
francis0407 Jan 9, 2020
bf155a7
ddl: check if the dropping index is primary key when doing "drop inde…
zimulala Jan 9, 2020
f0678b4
*: replace conf item `pprof_sql_cpu` with srv var `tidb_pprof_… (#14416)
lysu Jan 11, 2020
d1e0cfa
privilege: fix DBIsVisible privilege check (#14190) (#14386)
Jan 11, 2020
f4ea790
session: fix prepare stmt race in shutdown or kill (#14475)
sre-bot Jan 15, 2020
87fdf87
executor: add check data visibility for point get (#14459) (#14480)
sre-bot Jan 15, 2020
91f8a2a
*: fix transaction lazy initialization in pessimistic mode (#14446) (…
sre-bot Jan 15, 2020
0d84245
expression,table: fix insert partitioned table bug when the time zone…
tiancaiamao Jan 16, 2020
1c279e9
metrics: add statement deadlock detect duration (#14444) (#14484)
sre-bot Jan 16, 2020
50963e7
store: fix potential panic in GC worker (#14403) (#14439)
jackysp Jan 16, 2020
69dc332
expression, executor: correct the funcName for wrapWithIsTrue… (#14516)
sre-bot Jan 19, 2020
82b8b7a
util: wrong memory count when use Tracker.ReplaceChild() (#14513) (#1…
sre-bot Jan 19, 2020
2ddeb25
stats: fix panic when init stats for cm sketch (#14421) (#14470)
alivxxx Jan 19, 2020
8286441
planner: enhance rule partition pruning (#14544) (#14546)
XuHuaiyu Jan 20, 2020
52dae01
bindinfo: set default db for bindings correctly (#14077) (#14548)
alivxxx Jan 20, 2020
d91a052
expression: fix json_key not compatible with MySQL (#14556) (#14561)
hawkingrei Jan 21, 2020
e853ebd
ddl, stats: handle add/trunctate partition events (#14500) (#14566)
sre-bot Jan 23, 2020
b33e1a2
planner: reset plan id before optimizing point get (#14471) (#14595)
djshow832 Feb 3, 2020
1cc43bb
bindinfo: fix bugs when using bindings (#14263)
alivxxx Feb 4, 2020
e304158
metrics: add statement pessimistic retry count (#14619)
sre-bot Feb 4, 2020
6441e1f
executor: merge overlapped ranges when build key ranges for indexJoin…
sre-bot Feb 4, 2020
0c426b1
executor: add privilege check for show bindings (#14443) (#14618)
alivxxx Feb 4, 2020
80d515c
*: make Backoff perceive the Killed flag to fix MAX_EXECUTION_TIME #1…
tiancaiamao Feb 4, 2020
ac3f7f7
executor, util: improve concurrency of statement summary(#14490) (#14…
djshow832 Feb 5, 2020
239c7c4
types: fix parse DATETIME/TIME from string incompatible with MySQL (#…
sre-bot Feb 5, 2020
cc67c19
plugin: support logging rejected connection attempts in audit log (#1…
lysu Feb 5, 2020
ce94978
server: add lock keys counter metric (#14634)
cfzjywxk Feb 5, 2020
f7f504b
json: do not escape html special values (#14518) (#14637)
sre-bot Feb 5, 2020
b1cdfae
ddl: add column name to errBlobKeyWithoutLength error (#13453) (#14377)
sre-bot Feb 5, 2020
49b8ab9
executor: correctly handle panic for hashjoin build phase (#14056) (#…
XuHuaiyu Feb 5, 2020
c8d9c79
bindinfo: fix panic when load invalid sqls (#14645)
alivxxx Feb 5, 2020
45fd958
expression: handle ErrTruncated when dividing decimals in non-… (#14673)
qw4990 Feb 10, 2020
58c2915
executor: grant table level privilege should check table exist (#1454…
tiancaiamao Feb 12, 2020
05c0e50
Merge branch 'release-3.0' into zimuxia/merge-3.0-to-3.1
zimulala Feb 13, 2020
50b23f7
*: tiny update
zimulala Feb 14, 2020
8dbf2d7
planner/core: update tests
zimulala Feb 14, 2020
8b01eba
*: make tests happy
zimulala Feb 14, 2020
cf21205
Merge 14537 to v3.1
zimulala Feb 14, 2020
6762994
fix bind test
lzmhhh123 Feb 14, 2020
0c70ffb
ddl, config: fix data race
zimulala Feb 14, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 46 additions & 139 deletions bindinfo/bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,155 +15,62 @@ package bindinfo

import "github.com/pingcap/parser/ast"

// BindHint will add hints for originStmt according to hintedStmt' hints.
func BindHint(originStmt, hintedStmt ast.StmtNode) ast.StmtNode {
switch x := originStmt.(type) {
case *ast.SelectStmt:
return selectBind(x, hintedStmt.(*ast.SelectStmt))
default:
return originStmt
}
}

func selectBind(originalNode, hintedNode *ast.SelectStmt) *ast.SelectStmt {
if hintedNode.TableHints != nil {
originalNode.TableHints = hintedNode.TableHints
}
if originalNode.From != nil {
originalNode.From.TableRefs = resultSetNodeBind(originalNode.From.TableRefs, hintedNode.From.TableRefs).(*ast.Join)
}
if originalNode.Where != nil {
originalNode.Where = exprBind(originalNode.Where, hintedNode.Where).(ast.ExprNode)
}

if originalNode.Having != nil {
originalNode.Having.Expr = exprBind(originalNode.Having.Expr, hintedNode.Having.Expr)
}

if originalNode.OrderBy != nil {
originalNode.OrderBy = orderByBind(originalNode.OrderBy, hintedNode.OrderBy)
}

if originalNode.Fields != nil {
origFields := originalNode.Fields.Fields
hintFields := hintedNode.Fields.Fields
for idx := range origFields {
origFields[idx].Expr = exprBind(origFields[idx].Expr, hintFields[idx].Expr)
}
}
return originalNode
// HintsSet contains all hints of a query.
type HintsSet struct {
tableHints [][]*ast.TableOptimizerHint // Slice offset is the traversal order of `SelectStmt` in the ast.
indexHints [][]*ast.IndexHint // Slice offset is the traversal order of `TableName` in the ast.
}

func orderByBind(originalNode, hintedNode *ast.OrderByClause) *ast.OrderByClause {
for idx := 0; idx < len(originalNode.Items); idx++ {
originalNode.Items[idx].Expr = exprBind(originalNode.Items[idx].Expr, hintedNode.Items[idx].Expr)
}
return originalNode
type hintProcessor struct {
*HintsSet
// bindHint2Ast indicates the behavior of the processor, `true` for bind hint to ast, `false` for extract hint from ast.
bindHint2Ast bool
tableCounter int
indexCounter int
}

func exprBind(originalNode, hintedNode ast.ExprNode) ast.ExprNode {
switch v := originalNode.(type) {
case *ast.SubqueryExpr:
if v.Query != nil {
v.Query = resultSetNodeBind(v.Query, hintedNode.(*ast.SubqueryExpr).Query)
}
case *ast.ExistsSubqueryExpr:
if v.Sel != nil {
v.Sel.(*ast.SubqueryExpr).Query = resultSetNodeBind(v.Sel.(*ast.SubqueryExpr).Query, hintedNode.(*ast.ExistsSubqueryExpr).Sel.(*ast.SubqueryExpr).Query)
}
case *ast.PatternInExpr:
if v.Sel != nil {
v.Sel.(*ast.SubqueryExpr).Query = resultSetNodeBind(v.Sel.(*ast.SubqueryExpr).Query, hintedNode.(*ast.PatternInExpr).Sel.(*ast.SubqueryExpr).Query)
}
case *ast.BinaryOperationExpr:
if v.L != nil {
v.L = exprBind(v.L, hintedNode.(*ast.BinaryOperationExpr).L)
}
if v.R != nil {
v.R = exprBind(v.R, hintedNode.(*ast.BinaryOperationExpr).R)
}
case *ast.IsNullExpr:
if v.Expr != nil {
v.Expr = exprBind(v.Expr, hintedNode.(*ast.IsNullExpr).Expr)
}
case *ast.IsTruthExpr:
if v.Expr != nil {
v.Expr = exprBind(v.Expr, hintedNode.(*ast.IsTruthExpr).Expr)
}
case *ast.PatternLikeExpr:
if v.Pattern != nil {
v.Pattern = exprBind(v.Pattern, hintedNode.(*ast.PatternLikeExpr).Pattern)
}
case *ast.CompareSubqueryExpr:
if v.L != nil {
v.L = exprBind(v.L, hintedNode.(*ast.CompareSubqueryExpr).L)
}
if v.R != nil {
v.R = exprBind(v.R, hintedNode.(*ast.CompareSubqueryExpr).R)
}
case *ast.BetweenExpr:
if v.Left != nil {
v.Left = exprBind(v.Left, hintedNode.(*ast.BetweenExpr).Left)
}
if v.Right != nil {
v.Right = exprBind(v.Right, hintedNode.(*ast.BetweenExpr).Right)
}
case *ast.UnaryOperationExpr:
if v.V != nil {
v.V = exprBind(v.V, hintedNode.(*ast.UnaryOperationExpr).V)
}
case *ast.CaseExpr:
if v.Value != nil {
v.Value = exprBind(v.Value, hintedNode.(*ast.CaseExpr).Value)
}
if v.ElseClause != nil {
v.ElseClause = exprBind(v.ElseClause, hintedNode.(*ast.CaseExpr).ElseClause)
func (hp *hintProcessor) Enter(in ast.Node) (ast.Node, bool) {
switch v := in.(type) {
case *ast.SelectStmt:
if hp.bindHint2Ast {
if hp.tableCounter < len(hp.tableHints) {
v.TableHints = hp.tableHints[hp.tableCounter]
} else {
v.TableHints = nil
}
hp.tableCounter++
} else {
hp.tableHints = append(hp.tableHints, v.TableHints)
}
case *ast.TableName:
if hp.bindHint2Ast {
if hp.indexCounter < len(hp.indexHints) {
v.IndexHints = hp.indexHints[hp.indexCounter]
} else {
v.IndexHints = nil
}
hp.indexCounter++
} else {
hp.indexHints = append(hp.indexHints, v.IndexHints)
}
}
return originalNode
return in, false
}

func resultSetNodeBind(originalNode, hintedNode ast.ResultSetNode) ast.ResultSetNode {
switch x := originalNode.(type) {
case *ast.Join:
return joinBind(x, hintedNode.(*ast.Join))
case *ast.TableSource:
ts, _ := hintedNode.(*ast.TableSource)
switch v := x.Source.(type) {
case *ast.SelectStmt:
x.Source = selectBind(v, ts.Source.(*ast.SelectStmt))
case *ast.UnionStmt:
x.Source = unionSelectBind(v, hintedNode.(*ast.TableSource).Source.(*ast.UnionStmt))
case *ast.TableName:
x.Source.(*ast.TableName).IndexHints = ts.Source.(*ast.TableName).IndexHints
}
return x
case *ast.SelectStmt:
return selectBind(x, hintedNode.(*ast.SelectStmt))
case *ast.UnionStmt:
return unionSelectBind(x, hintedNode.(*ast.UnionStmt))
default:
return x
}
func (hp *hintProcessor) Leave(in ast.Node) (ast.Node, bool) {
return in, true
}

func joinBind(originalNode, hintedNode *ast.Join) *ast.Join {
if originalNode.Left != nil {
originalNode.Left = resultSetNodeBind(originalNode.Left, hintedNode.Left)
}

if hintedNode.Right != nil {
originalNode.Right = resultSetNodeBind(originalNode.Right, hintedNode.Right)
}

return originalNode
// CollectHint collects hints for a statement.
func CollectHint(in ast.StmtNode) *HintsSet {
hp := hintProcessor{HintsSet: &HintsSet{tableHints: make([][]*ast.TableOptimizerHint, 0, 4), indexHints: make([][]*ast.IndexHint, 0, 4)}}
in.Accept(&hp)
return hp.HintsSet
}

func unionSelectBind(originalNode, hintedNode *ast.UnionStmt) ast.ResultSetNode {
selects := originalNode.SelectList.Selects
for i := len(selects) - 1; i >= 0; i-- {
originalNode.SelectList.Selects[i] = selectBind(selects[i], hintedNode.SelectList.Selects[i])
}

return originalNode
// BindHint will add hints for stmt according to the hints in `hintsSet`.
func BindHint(stmt ast.StmtNode, hintsSet *HintsSet) ast.StmtNode {
hp := hintProcessor{HintsSet: hintsSet, bindHint2Ast: true}
stmt.Accept(&hp)
return stmt
}
70 changes: 68 additions & 2 deletions bindinfo/bind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

. "github.com/pingcap/check"
"github.com/pingcap/parser"
"github.com/pingcap/parser/auth"
"github.com/pingcap/tidb/bindinfo"
"github.com/pingcap/tidb/domain"
"github.com/pingcap/tidb/kv"
Expand Down Expand Up @@ -137,9 +138,9 @@ func (s *testSuite) TestBindParse(c *C) {
c.Check(bindData.UpdateTime, NotNil)

// Test fields with quotes or slashes.
sql = `CREATE GLOBAL BINDING FOR select * from t where a BETWEEN "a" and "b" USING select * from t use index(idx) where a BETWEEN "a\nb\rc\td\0e" and 'x'`
sql = `CREATE GLOBAL BINDING FOR select * from t where i BETWEEN "a" and "b" USING select * from t use index(index_t) where i BETWEEN "a\nb\rc\td\0e" and 'x'`
tk.MustExec(sql)
tk.MustExec(`DROP global binding for select * from t use index(idx) where a BETWEEN "a\nb\rc\td\0e" and "x"`)
tk.MustExec(`DROP global binding for select * from t use index(index_t) where i BETWEEN "a\nb\rc\td\0e" and "x"`)
}

func (s *testSuite) TestGlobalBinding(c *C) {
Expand Down Expand Up @@ -378,6 +379,19 @@ func (s *testSuite) TestGlobalAndSessionBindingBothExist(c *C) {
" └─Selection_14 9990.00 cop[tikv] not(isnull(test.t2.id))",
" └─TableScan_13 10000.00 cop[tikv] table:t2, range:[-inf,+inf], keep order:false, stats:pseudo",
))

tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int, b int, index idx(a))")
tk.MustQuery("explain select * from t where a = -1").Check(testkit.Rows(
"IndexLookUp_10 10.00 root ",
"├─IndexScan_8 10.00 cop[tikv] table:t, index:a, range:[-1,-1], keep order:false, stats:pseudo",
"└─TableScan_9 10.00 cop[tikv] table:t, keep order:false, stats:pseudo"))
tk.MustExec("create global binding for select * from t where a = 10 using select * from t ignore index(idx) where a = 10")
// Should not panic for `-1`.
tk.MustContains("select * from t where a = -1", "Selection")
// Session bindings should be able to cover the global bindings.
tk.MustExec("drop session binding for select * from t where a = 10")
tk.MustContains("select * from t where a = -1", "IndexLookUp")
Copy link
Contributor Author

Choose a reason for hiding this comment

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

PTAL @lamxTyler

}

func (s *testSuite) TestExplain(c *C) {
Expand Down Expand Up @@ -520,3 +534,55 @@ func (s *testSuite) TestBindingCache(c *C) {
res := tk.MustQuery("show global bindings")
c.Assert(len(res.Rows()), Equals, 2)
}

func (s *testSuite) TestDefaultDB(c *C) {
tk := testkit.NewTestKit(c, s.store)
s.cleanBindingEnv(tk)
tk.MustExec("use test")
tk.MustExec("create table t(a int, b int, index idx(a))")
tk.MustExec("create global binding for select * from test.t using select * from test.t use index(idx)")
tk.MustExec("use mysql")
tk.MustQuery("select * from test.t")
// Even in another database, we could still use the bindings.
c.Assert(tk.Se.GetSessionVars().StmtCtx.IndexNames[0], Equals, "t:idx")
tk.MustExec("drop global binding for select * from test.t")
tk.MustQuery("show global bindings").Check(testkit.Rows())

tk.MustExec("use test")
tk.MustExec("create session binding for select * from test.t using select * from test.t use index(idx)")
tk.MustExec("use mysql")
tk.MustQuery("select * from test.t")
// Even in another database, we could still use the bindings.
c.Assert(tk.Se.GetSessionVars().StmtCtx.IndexNames[0], Equals, "t:idx")
}

func (s *testSuite) TestPrivileges(c *C) {
tk := testkit.NewTestKit(c, s.store)
s.cleanBindingEnv(tk)
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int, b int, index idx(a))")
tk.MustExec("create global binding for select * from t using select * from t use index(idx)")
c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue)
rows := tk.MustQuery("show global bindings").Rows()
c.Assert(len(rows), Equals, 1)
tk.MustExec("create user test@'%'")
c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "test", Hostname: "%"}, nil, nil), IsTrue)
rows = tk.MustQuery("show global bindings").Rows()
c.Assert(len(rows), Equals, 0)
}

func (s *testSuite) TestErrorParse(c *C) {
tk := testkit.NewTestKit(c, s.store)
s.cleanBindingEnv(tk)
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int, b int, index idx(a))")
_, err := tk.Exec("create global binding for select * from t where a = '1' using select * from t where a = '")
c.Assert(err, NotNil)
tk.MustExec("create global binding for select * from t where a = '1' using select * from t where a = '1'")
tk.MustExec("update mysql.bind_info set bind_sql = 'select'")
h := s.domain.BindHandle()
// Do not panic.
h.Update(true)
}
4 changes: 2 additions & 2 deletions bindinfo/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package bindinfo
import (
"unsafe"

"github.com/pingcap/parser/ast"
"github.com/pingcap/tidb/metrics"
"github.com/pingcap/tidb/types"
"github.com/pingcap/tidb/util/chunk"
Expand All @@ -34,7 +33,8 @@ const (
// BindMeta stores the basic bind info and bindSql astNode.
type BindMeta struct {
*BindRecord
Ast ast.StmtNode //ast will be used to do query sql bind check
// Hint is the parsed hints, it is used to bind hints to stmt node.
Hint *HintsSet
}

// cache is a k-v map, key is original sql, value is a slice of BindMeta.
Expand Down
5 changes: 3 additions & 2 deletions bindinfo/handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,11 +305,12 @@ func (h *BindHandle) GetAllBindRecord() (bindRecords []*BindMeta) {

func (h *BindHandle) newBindMeta(record *BindRecord) (hash string, meta *BindMeta, err error) {
hash = parser.DigestNormalized(record.OriginalSQL)
meta = &BindMeta{BindRecord: record}
stmtNodes, _, err := h.bindInfo.parser.Parse(record.BindSQL, record.Charset, record.Collation)
if err != nil {
return "", nil, err
return hash, meta, err
}
meta = &BindMeta{BindRecord: record, Ast: stmtNodes[0]}
meta.Hint = CollectHint(stmtNodes[0])
return hash, meta, nil
}

Expand Down
2 changes: 1 addition & 1 deletion bindinfo/session_handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (h *SessionHandle) newBindMeta(record *BindRecord) (hash string, meta *Bind
if err != nil {
return "", nil, err
}
meta = &BindMeta{BindRecord: record, Ast: stmtNodes[0]}
meta = &BindMeta{BindRecord: record, Hint: CollectHint(stmtNodes[0])}
return hash, meta, nil
}

Expand Down
8 changes: 3 additions & 5 deletions cmd/explaintest/r/explain_easy.result
Original file line number Diff line number Diff line change
Expand Up @@ -466,11 +466,9 @@ begin;
insert tb values ('1');
explain select * from ta where a = 1;
id count task operator info
Projection_5 8000.00 root test.ta.a
└─Selection_6 8000.00 root eq(cast(test.ta.a), 1)
└─UnionScan_7 10000.00 root eq(cast(test.ta.a), 1)
└─TableReader_9 10000.00 root data:TableScan_8
└─TableScan_8 10000.00 cop[tikv] table:ta, range:[-inf,+inf], keep order:false, stats:pseudo
Selection_5 8000.00 root eq(cast(test.ta.a), 1)
└─TableReader_7 10000.00 root data:TableScan_6
└─TableScan_6 10000.00 cop[tikv] table:ta, range:[-inf,+inf], keep order:false, stats:pseudo
rollback;
drop table if exists t1, t2;
create table t1(a int, b int, c int, primary key(a, b));
Expand Down
Loading