*: merge master and fix conflict.
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -4,3 +4,5 @@
|
||||
/interpreter/test
|
||||
/tidb-server/tidb-server
|
||||
coverage.out
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
@ -162,6 +162,7 @@ const (
|
||||
ShowWarnings
|
||||
ShowCharset
|
||||
ShowVariables
|
||||
ShowStatus
|
||||
ShowCollation
|
||||
ShowCreateTable
|
||||
ShowGrants
|
||||
|
||||
10
ddl/ddl.go
10
ddl/ddl.go
@ -33,7 +33,6 @@ import (
|
||||
"github.com/pingcap/tidb/model"
|
||||
"github.com/pingcap/tidb/mysql"
|
||||
"github.com/pingcap/tidb/parser/coldef"
|
||||
"github.com/pingcap/tidb/privilege"
|
||||
"github.com/pingcap/tidb/table"
|
||||
"github.com/pingcap/tidb/terror"
|
||||
"github.com/pingcap/tidb/util/charset"
|
||||
@ -561,15 +560,6 @@ func (d *ddl) DropTable(ctx context.Context, ti table.Ident) (err error) {
|
||||
if err != nil {
|
||||
return errors.Trace(ErrNotExists)
|
||||
}
|
||||
// Check Privilege
|
||||
privChecker := privilege.GetPrivilegeChecker(ctx)
|
||||
hasPriv, err := privChecker.Check(ctx, schema, tb.Meta(), mysql.DropPriv)
|
||||
if err != nil {
|
||||
return errors.Trace(err)
|
||||
}
|
||||
if !hasPriv {
|
||||
return errors.Errorf("You do not have the privilege to drop table %s.%s.", ti.Schema, ti.Name)
|
||||
}
|
||||
|
||||
job := &model.Job{
|
||||
SchemaID: schema.ID,
|
||||
|
||||
@ -62,7 +62,7 @@ func (v *Variable) String() string {
|
||||
func (v *Variable) Eval(ctx context.Context, args map[interface{}]interface{}) (interface{}, error) {
|
||||
name := strings.ToLower(v.Name)
|
||||
sessionVars := variable.GetSessionVars(ctx)
|
||||
globalVars := variable.GetGlobalSysVarAccessor(ctx)
|
||||
globalVars := variable.GetGlobalVarAccessor(ctx)
|
||||
if !v.IsSystem {
|
||||
// user vars
|
||||
if value, ok := sessionVars.Users[name]; ok {
|
||||
|
||||
@ -30,7 +30,7 @@ func (s *testVariableSuite) SetUpSuite(c *C) {
|
||||
nc := mock.NewContext()
|
||||
s.ctx = nc
|
||||
variable.BindSessionVars(s.ctx)
|
||||
variable.BindGlobalSysVarAccessor(s.ctx, nc)
|
||||
variable.BindGlobalVarAccessor(s.ctx, nc)
|
||||
}
|
||||
|
||||
func (s *testVariableSuite) TestVariable(c *C) {
|
||||
|
||||
@ -868,6 +868,8 @@ func convertShow(converter *expressionConverter, v *ast.ShowStmt) (*stmts.ShowSt
|
||||
oldShow.Target = stmt.ShowEngines
|
||||
case ast.ShowVariables:
|
||||
oldShow.Target = stmt.ShowVariables
|
||||
case ast.ShowStatus:
|
||||
oldShow.Target = stmt.ShowStatus
|
||||
case ast.ShowWarnings:
|
||||
oldShow.Target = stmt.ShowWarnings
|
||||
case ast.ShowNone:
|
||||
|
||||
@ -228,6 +228,7 @@ import (
|
||||
signed "SIGNED"
|
||||
some "SOME"
|
||||
start "START"
|
||||
status "STATUS"
|
||||
stringType "string"
|
||||
subDate "SUBDATE"
|
||||
substring "SUBSTRING"
|
||||
@ -482,10 +483,10 @@ import (
|
||||
SelectStmtOpts "Select statement options"
|
||||
SelectStmtGroup "SELECT statement optional GROUP BY clause"
|
||||
SetStmt "Set variable statement"
|
||||
ShowStmt "Show engines/databases/tables/columns/warnings statement"
|
||||
ShowStmt "Show engines/databases/tables/columns/warnings/status statement"
|
||||
ShowDatabaseNameOpt "Show tables/columns statement database name option"
|
||||
ShowTableAliasOpt "Show table alias option"
|
||||
ShowLikeOrWhereOpt "Show like or where condition option"
|
||||
ShowLikeOrWhereOpt "Show like or where clause option"
|
||||
SignedLiteral "Literal or NumLiteral with sign"
|
||||
Statement "statement"
|
||||
StatementList "statement list"
|
||||
@ -1647,7 +1648,7 @@ UnReservedKeyword:
|
||||
"AUTO_INCREMENT" | "AFTER" | "AVG" | "BEGIN" | "BIT" | "BOOL" | "BOOLEAN" | "CHARSET" | "COLUMNS" | "COMMIT"
|
||||
| "DATE" | "DATETIME" | "DEALLOCATE" | "DO" | "END" | "ENGINE" | "ENGINES" | "EXECUTE" | "FIRST" | "FULL"
|
||||
| "LOCAL" | "NAMES" | "OFFSET" | "PASSWORD" %prec lowerThanEq | "PREPARE" | "QUICK" | "ROLLBACK" | "SESSION" | "SIGNED"
|
||||
| "START" | "GLOBAL" | "TABLES"| "TEXT" | "TIME" | "TIMESTAMP" | "TRANSACTION" | "TRUNCATE" | "UNKNOWN"
|
||||
| "START" | "STATUS" | "GLOBAL" | "TABLES"| "TEXT" | "TIME" | "TIMESTAMP" | "TRANSACTION" | "TRUNCATE" | "UNKNOWN"
|
||||
| "VALUE" | "WARNINGS" | "YEAR" | "MODE" | "WEEK" | "ANY" | "SOME" | "USER" | "IDENTIFIED" | "COLLATION"
|
||||
| "COMMENT" | "AVG_ROW_LENGTH" | "CONNECTION" | "CHECKSUM" | "COMPRESSION" | "KEY_BLOCK_SIZE" | "MAX_ROWS" | "MIN_ROWS"
|
||||
| "NATIONAL" | "ROW" | "QUARTER" | "ESCAPE" | "GRANTS"
|
||||
@ -3316,6 +3317,19 @@ ShowStmt:
|
||||
}
|
||||
$$ = stmt
|
||||
}
|
||||
| "SHOW" GlobalScope "STATUS" ShowLikeOrWhereOpt
|
||||
{
|
||||
stmt := &ast.ShowStmt{
|
||||
Tp: ast.ShowStatus,
|
||||
GlobalScope: $2.(bool),
|
||||
}
|
||||
if x, ok := $4.(*ast.PatternLikeExpr); ok {
|
||||
stmt.Pattern = x
|
||||
} else if $4 != nil {
|
||||
stmt.Where = $4.(ast.ExprNode)
|
||||
}
|
||||
$$ = stmt
|
||||
}
|
||||
| "SHOW" "COLLATION" ShowLikeOrWhereOpt
|
||||
{
|
||||
stmt := &ast.ShowStmt{
|
||||
|
||||
@ -240,6 +240,11 @@ func (s *testParserSuite) TestDMLStmt(c *C) {
|
||||
{"SHOW VARIABLES", true},
|
||||
{"SHOW GLOBAL VARIABLES", true},
|
||||
{"SHOW GLOBAL VARIABLES WHERE Variable_name = 'autocommit'", true},
|
||||
{"SHOW STATUS", true},
|
||||
{"SHOW GLOBAL STATUS", true},
|
||||
{"SHOW SESSION STATUS", true},
|
||||
{"SHOW STATUS LIKE 'Up%'", true},
|
||||
{"SHOW STATUS WHERE Variable_name LIKE 'Up%'", true},
|
||||
{`SHOW FULL TABLES FROM icar_qa LIKE play_evolutions`, true},
|
||||
{`SHOW FULL TABLES WHERE Table_Type != 'VIEW'`, true},
|
||||
{`SHOW GRANTS`, true},
|
||||
|
||||
@ -430,6 +430,7 @@ share {s}{h}{a}{r}{e}
|
||||
show {s}{h}{o}{w}
|
||||
some {s}{o}{m}{e}
|
||||
start {s}{t}{a}{r}{t}
|
||||
status {s}{t}{a}{t}{u}{s}
|
||||
subdate {s}{u}{b}{d}{a}{t}{e}
|
||||
substring {s}{u}{b}{s}{t}{r}{i}{n}{g}
|
||||
substring_index {s}{u}{b}{s}{t}{r}{i}{n}{g}_{i}{n}{d}{e}{x}
|
||||
@ -841,6 +842,8 @@ year_month {y}{e}{a}{r}_{m}{o}{n}{t}{h}
|
||||
return some
|
||||
{start} lval.item = string(l.val)
|
||||
return start
|
||||
{status} lval.item = string(l.val)
|
||||
return status
|
||||
{global} lval.item = string(l.val)
|
||||
return global
|
||||
{rand} lval.item = string(l.val)
|
||||
|
||||
@ -148,6 +148,7 @@ func (r *TableDefaultPlan) filterBinOp(ctx context.Context, x *expression.Binary
|
||||
return &indexPlan{
|
||||
src: t,
|
||||
col: c,
|
||||
unique: ix.Unique,
|
||||
idxName: ix.Name.O,
|
||||
idx: ix.X,
|
||||
spans: toSpans(x.Op, rval, seekVal),
|
||||
@ -179,6 +180,7 @@ func (r *TableDefaultPlan) filterIdent(ctx context.Context, x *expression.Ident,
|
||||
return &indexPlan{
|
||||
src: t,
|
||||
col: v,
|
||||
unique: ix.Unique,
|
||||
idxName: ix.Name.L,
|
||||
idx: ix.X,
|
||||
spans: spans,
|
||||
@ -215,6 +217,7 @@ func (r *TableDefaultPlan) filterIsNull(ctx context.Context, x *expression.IsNul
|
||||
return &indexPlan{
|
||||
src: t,
|
||||
col: col,
|
||||
unique: ix.Unique,
|
||||
idxName: ix.Name.L,
|
||||
idx: ix.X,
|
||||
spans: spans,
|
||||
|
||||
@ -25,6 +25,7 @@ import (
|
||||
"github.com/pingcap/tidb/parser/opcode"
|
||||
"github.com/pingcap/tidb/plan"
|
||||
"github.com/pingcap/tidb/table"
|
||||
"github.com/pingcap/tidb/terror"
|
||||
"github.com/pingcap/tidb/util/format"
|
||||
"github.com/pingcap/tidb/util/types"
|
||||
)
|
||||
@ -124,6 +125,7 @@ func (span *indexSpan) cutOffHigh(val interface{}, exclude bool) *indexSpan {
|
||||
type indexPlan struct {
|
||||
src table.Table
|
||||
col *column.Col
|
||||
unique bool
|
||||
idxName string
|
||||
idx kv.Index
|
||||
spans []*indexSpan // multiple spans are ordered by their values and without overlapping.
|
||||
@ -243,6 +245,7 @@ func (r *indexPlan) Filter(ctx context.Context, expr expression.Expression) (pla
|
||||
return &indexPlan{
|
||||
src: r.src,
|
||||
col: r.col,
|
||||
unique: r.unique,
|
||||
idxName: r.idxName,
|
||||
idx: r.idx,
|
||||
spans: spans,
|
||||
@ -325,19 +328,31 @@ func toSpans(op opcode.Op, val, seekVal interface{}) []*indexSpan {
|
||||
}
|
||||
|
||||
// Next implements plan.Plan Next interface.
|
||||
func (r *indexPlan) Next(ctx context.Context) (row *plan.Row, err error) {
|
||||
func (r *indexPlan) Next(ctx context.Context) (*plan.Row, error) {
|
||||
for {
|
||||
if r.cursor == len(r.spans) {
|
||||
return
|
||||
return nil, nil
|
||||
}
|
||||
span := r.spans[r.cursor]
|
||||
if r.isPointLookup(span) {
|
||||
// Do point lookup on index will prevent prefetch cost.
|
||||
row, err := r.pointLookup(ctx, span.lowVal)
|
||||
if err != nil {
|
||||
return nil, errors.Trace(err)
|
||||
}
|
||||
r.cursor++
|
||||
if row != nil {
|
||||
return row, nil
|
||||
}
|
||||
continue
|
||||
}
|
||||
if r.iter == nil {
|
||||
seekVal := span.seekVal
|
||||
if span.lowVal == minNotNullVal {
|
||||
seekVal = []byte{}
|
||||
}
|
||||
var txn kv.Transaction
|
||||
txn, err = ctx.GetTxn(false)
|
||||
txn, err := ctx.GetTxn(false)
|
||||
if err != nil {
|
||||
return nil, errors.Trace(err)
|
||||
}
|
||||
@ -346,9 +361,7 @@ func (r *indexPlan) Next(ctx context.Context) (row *plan.Row, err error) {
|
||||
return nil, types.EOFAsNil(err)
|
||||
}
|
||||
}
|
||||
var idxKey []interface{}
|
||||
var h int64
|
||||
idxKey, h, err = r.iter.Next()
|
||||
idxKey, h, err := r.iter.Next()
|
||||
if err != nil {
|
||||
return nil, types.EOFAsNil(err)
|
||||
}
|
||||
@ -370,20 +383,58 @@ func (r *indexPlan) Next(ctx context.Context) (row *plan.Row, err error) {
|
||||
r.skipLowCmp = false
|
||||
continue
|
||||
}
|
||||
row = &plan.Row{}
|
||||
row.Data, err = r.src.Row(ctx, h)
|
||||
var row *plan.Row
|
||||
row, err = r.lookupRow(ctx, h)
|
||||
if err != nil {
|
||||
return nil, errors.Trace(err)
|
||||
}
|
||||
rowKey := &plan.RowKeyEntry{
|
||||
Tbl: r.src,
|
||||
Key: string(r.src.RecordKey(h, nil)),
|
||||
}
|
||||
row.RowKeys = append(row.RowKeys, rowKey)
|
||||
return
|
||||
return row, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (r *indexPlan) isPointLookup(span *indexSpan) bool {
|
||||
return r.unique && span.lowVal != nil && span.lowVal == span.highVal && !span.lowExclude && !span.highExclude
|
||||
}
|
||||
|
||||
func (r *indexPlan) lookupRow(ctx context.Context, h int64) (*plan.Row, error) {
|
||||
row := &plan.Row{}
|
||||
var err error
|
||||
row.Data, err = r.src.Row(ctx, h)
|
||||
if err != nil {
|
||||
return nil, errors.Trace(err)
|
||||
}
|
||||
rowKey := &plan.RowKeyEntry{
|
||||
Tbl: r.src,
|
||||
Key: string(r.src.RecordKey(h, nil)),
|
||||
}
|
||||
row.RowKeys = append(row.RowKeys, rowKey)
|
||||
return row, nil
|
||||
}
|
||||
|
||||
// pointLookup do not seek index but call Exists method to get a handle, which is cheaper.
|
||||
func (r *indexPlan) pointLookup(ctx context.Context, val interface{}) (*plan.Row, error) {
|
||||
txn, err := ctx.GetTxn(false)
|
||||
if err != nil {
|
||||
return nil, errors.Trace(err)
|
||||
}
|
||||
var exist bool
|
||||
var h int64
|
||||
// We expect a kv.ErrKeyExists Error because we pass -1 as the handle which is not equal to the existed handle.
|
||||
exist, h, err = r.idx.Exist(txn, []interface{}{val}, -1)
|
||||
if !exist {
|
||||
return nil, errors.Trace(err)
|
||||
}
|
||||
if terror.ErrorNotEqual(kv.ErrKeyExists, err) {
|
||||
return nil, errors.Trace(err)
|
||||
}
|
||||
var row *plan.Row
|
||||
row, err = r.lookupRow(ctx, h)
|
||||
if err != nil {
|
||||
return nil, errors.Trace(err)
|
||||
}
|
||||
return row, nil
|
||||
}
|
||||
|
||||
// Close implements plan.Plan Close interface.
|
||||
func (r *indexPlan) Close() error {
|
||||
if r.iter != nil {
|
||||
|
||||
@ -32,6 +32,7 @@ import (
|
||||
"github.com/pingcap/tidb/sessionctx/variable"
|
||||
"github.com/pingcap/tidb/stmt"
|
||||
"github.com/pingcap/tidb/table"
|
||||
"github.com/pingcap/tidb/terror"
|
||||
"github.com/pingcap/tidb/util/charset"
|
||||
"github.com/pingcap/tidb/util/format"
|
||||
)
|
||||
@ -103,6 +104,8 @@ func (s *ShowPlan) GetFields() []*field.ResultField {
|
||||
types = []byte{mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeLonglong}
|
||||
case stmt.ShowVariables:
|
||||
names = []string{"Variable_name", "Value"}
|
||||
case stmt.ShowStatus:
|
||||
names = []string{"Variable_name", "Value"}
|
||||
case stmt.ShowCollation:
|
||||
names = []string{"Collation", "Charset", "Id", "Default", "Compiled", "Sortlen"}
|
||||
types = []byte{mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeLonglong,
|
||||
@ -164,6 +167,8 @@ func (s *ShowPlan) fetchAll(ctx context.Context) error {
|
||||
return s.fetchShowCharset(ctx)
|
||||
case stmt.ShowVariables:
|
||||
return s.fetchShowVariables(ctx)
|
||||
case stmt.ShowStatus:
|
||||
return s.fetchShowStatus(ctx)
|
||||
case stmt.ShowCollation:
|
||||
return s.fetchShowCollation(ctx)
|
||||
case stmt.ShowCreateTable:
|
||||
@ -353,7 +358,7 @@ func (s *ShowPlan) fetchShowTables(ctx context.Context) error {
|
||||
|
||||
func (s *ShowPlan) fetchShowVariables(ctx context.Context) error {
|
||||
sessionVars := variable.GetSessionVars(ctx)
|
||||
globalVars := variable.GetGlobalSysVarAccessor(ctx)
|
||||
globalVars := variable.GetGlobalVarAccessor(ctx)
|
||||
m := map[interface{}]interface{}{}
|
||||
|
||||
for _, v := range variable.SysVars {
|
||||
@ -402,6 +407,86 @@ func (s *ShowPlan) fetchShowVariables(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSessionStatusVar(ctx context.Context, sessionVars *variable.SessionVars,
|
||||
globalVars variable.GlobalVarAccessor, name string) (string, error) {
|
||||
sv, ok := sessionVars.StatusVars[name]
|
||||
if ok {
|
||||
return sv, nil
|
||||
}
|
||||
|
||||
value, err := globalVars.GetGlobalStatusVar(ctx, name)
|
||||
if err != nil && terror.UnknownStatusVar.Equal(err) {
|
||||
return "", errors.Trace(err)
|
||||
}
|
||||
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func getGlobalStatusVar(ctx context.Context, sessionVars *variable.SessionVars,
|
||||
globalVars variable.GlobalVarAccessor, name string) (string, error) {
|
||||
|
||||
value, err := globalVars.GetGlobalStatusVar(ctx, name)
|
||||
if err == nil {
|
||||
return value, nil
|
||||
}
|
||||
|
||||
if terror.UnknownStatusVar.Equal(err) {
|
||||
return "", errors.Trace(err)
|
||||
}
|
||||
|
||||
sv, _ := sessionVars.StatusVars[name]
|
||||
|
||||
return sv, nil
|
||||
}
|
||||
|
||||
func (s *ShowPlan) fetchShowStatus(ctx context.Context) error {
|
||||
sessionVars := variable.GetSessionVars(ctx)
|
||||
globalVars := variable.GetGlobalVarAccessor(ctx)
|
||||
m := map[interface{}]interface{}{}
|
||||
|
||||
for _, v := range variable.StatusVars {
|
||||
if s.Pattern != nil {
|
||||
s.Pattern.Expr = expression.Value{Val: v.Name}
|
||||
} else if s.Where != nil {
|
||||
m[expression.ExprEvalIdentFunc] = func(name string) (interface{}, error) {
|
||||
if strings.EqualFold(name, "Variable_name") {
|
||||
return v.Name, nil
|
||||
}
|
||||
|
||||
return nil, errors.Errorf("unknown field %s", name)
|
||||
}
|
||||
}
|
||||
|
||||
match, err := s.evalCondition(ctx, m)
|
||||
if err != nil {
|
||||
return errors.Trace(err)
|
||||
}
|
||||
if !match {
|
||||
continue
|
||||
}
|
||||
|
||||
var value string
|
||||
if !s.GlobalScope {
|
||||
value, err = getSessionStatusVar(ctx, sessionVars, globalVars, v.Name)
|
||||
if err != nil {
|
||||
return errors.Trace(err)
|
||||
}
|
||||
} else if v.Scope != variable.ScopeSession {
|
||||
value, err = getGlobalStatusVar(ctx, sessionVars, globalVars, v.Name)
|
||||
if err != nil {
|
||||
return errors.Trace(err)
|
||||
}
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
|
||||
row := &plan.Row{Data: []interface{}{v.Name, value}}
|
||||
s.rows = append(s.rows, row)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ShowPlan) fetchShowCharset(ctx context.Context) error {
|
||||
// See: http://dev.mysql.com/doc/refman/5.7/en/show-character-set.html
|
||||
descs := charset.GetAllCharsets()
|
||||
|
||||
@ -56,7 +56,7 @@ func (p *testShowSuit) SetUpSuite(c *C) {
|
||||
nc := mock.NewContext()
|
||||
p.ctx = nc
|
||||
variable.BindSessionVars(p.ctx)
|
||||
variable.BindGlobalSysVarAccessor(p.ctx, nc)
|
||||
variable.BindGlobalVarAccessor(p.ctx, nc)
|
||||
|
||||
p.dbName = "testshowplan"
|
||||
p.store = newStore(c, p.dbName)
|
||||
@ -106,7 +106,7 @@ func (p *testShowSuit) TestSimple(c *C) {
|
||||
c.Assert(fls, HasLen, 2)
|
||||
}
|
||||
|
||||
func (p *testShowSuit) TestShowVariables(c *C) {
|
||||
func (p *testShowSuit) TestShowSysVariables(c *C) {
|
||||
pln := &plans.ShowPlan{
|
||||
Target: stmt.ShowVariables,
|
||||
GlobalScope: true,
|
||||
@ -182,6 +182,94 @@ func (p *testShowSuit) TestShowVariables(c *C) {
|
||||
c.Assert(v, Equals, "on")
|
||||
}
|
||||
|
||||
func (p *testShowSuit) TestShowStatusVariables(c *C) {
|
||||
pln := &plans.ShowPlan{
|
||||
Target: stmt.ShowStatus,
|
||||
GlobalScope: true,
|
||||
Pattern: &expression.PatternLike{
|
||||
Pattern: &expression.Value{
|
||||
Val: "tc_log_page_size",
|
||||
},
|
||||
},
|
||||
}
|
||||
fls := pln.GetFields()
|
||||
c.Assert(fls, HasLen, 2)
|
||||
c.Assert(fls[0].Name, Equals, "Variable_name")
|
||||
c.Assert(fls[1].Name, Equals, "Value")
|
||||
c.Assert(fls[0].Col.Tp, Equals, mysql.TypeVarchar)
|
||||
c.Assert(fls[1].Col.Tp, Equals, mysql.TypeVarchar)
|
||||
|
||||
sessionVars := variable.GetSessionVars(p.ctx)
|
||||
ret := map[string]string{}
|
||||
rset := rsets.Recordset{
|
||||
Ctx: p.ctx,
|
||||
Plan: pln,
|
||||
}
|
||||
rset.Do(func(data []interface{}) (bool, error) {
|
||||
ret[data[0].(string)] = data[1].(string)
|
||||
return true, nil
|
||||
})
|
||||
c.Assert(ret, HasLen, 1)
|
||||
v, ok := ret["tc_log_page_size"]
|
||||
c.Assert(ok, IsTrue)
|
||||
c.Assert(v, Equals, "0")
|
||||
pln.Close()
|
||||
|
||||
sessionVars.StatusVars["tc_log_page_size"] = "1024"
|
||||
pln.GlobalScope = false
|
||||
rset.Do(func(data []interface{}) (bool, error) {
|
||||
ret[data[0].(string)] = data[1].(string)
|
||||
return true, nil
|
||||
})
|
||||
c.Assert(ret, HasLen, 1)
|
||||
v, ok = ret["tc_log_page_size"]
|
||||
c.Assert(ok, IsTrue)
|
||||
c.Assert(v, Equals, "1024")
|
||||
pln.Close()
|
||||
|
||||
pln.Pattern = &expression.PatternLike{
|
||||
Pattern: &expression.Value{
|
||||
Val: "compression",
|
||||
},
|
||||
}
|
||||
sessionVars.StatusVars["compression"] = "on"
|
||||
pln.GlobalScope = true
|
||||
ret = map[string]string{}
|
||||
rset.Do(func(data []interface{}) (bool, error) {
|
||||
ret[data[0].(string)] = data[1].(string)
|
||||
return true, nil
|
||||
})
|
||||
c.Assert(ret, HasLen, 0)
|
||||
|
||||
pln.GlobalScope = false
|
||||
rset.Do(func(data []interface{}) (bool, error) {
|
||||
ret[data[0].(string)] = data[1].(string)
|
||||
return true, nil
|
||||
})
|
||||
c.Assert(ret, HasLen, 1)
|
||||
v, ok = ret["compression"]
|
||||
c.Assert(ok, IsTrue)
|
||||
c.Assert(v, Equals, "on")
|
||||
pln.Close()
|
||||
|
||||
pln.Pattern = nil
|
||||
pln.Where = &expression.BinaryOperation{
|
||||
L: &expression.Ident{CIStr: model.NewCIStr("Variable_name")},
|
||||
R: expression.Value{Val: "aborted_clients"},
|
||||
Op: opcode.EQ,
|
||||
}
|
||||
ret = map[string]string{}
|
||||
sessionVars.StatusVars["aborted_clients"] = "0"
|
||||
rset.Do(func(data []interface{}) (bool, error) {
|
||||
ret[data[0].(string)] = data[1].(string)
|
||||
return true, nil
|
||||
})
|
||||
c.Assert(ret, HasLen, 1)
|
||||
v, ok = ret["aborted_clients"]
|
||||
c.Assert(ok, IsTrue)
|
||||
c.Assert(v, Equals, "0")
|
||||
}
|
||||
|
||||
func (p *testShowSuit) TestIssue540(c *C) {
|
||||
// Show variables where variable_name="time_zone"
|
||||
pln := &plans.ShowPlan{
|
||||
|
||||
51
session.go
51
session.go
@ -265,9 +265,9 @@ func (s *session) ExecRestrictedSQL(ctx context.Context, sql string) (rset.Recor
|
||||
return rs, errors.Trace(err)
|
||||
}
|
||||
|
||||
// GetGlobalSysVar implements RestrictedSQLExecutor.GetGlobalSysVar interface.
|
||||
func (s *session) GetGlobalSysVar(ctx context.Context, name string) (string, error) {
|
||||
sql := fmt.Sprintf(`SELECT VARIABLE_VALUE FROM %s.%s WHERE VARIABLE_NAME="%s";`, mysql.SystemDB, mysql.GlobalVariablesTable, name)
|
||||
// getExecRet executes restricted sql and the result is one column.
|
||||
// It returns a string value.
|
||||
func (s *session) getExecRet(ctx context.Context, sql string) (string, error) {
|
||||
rs, err := s.ExecRestrictedSQL(ctx, sql)
|
||||
if err != nil {
|
||||
return "", errors.Trace(err)
|
||||
@ -278,7 +278,7 @@ func (s *session) GetGlobalSysVar(ctx context.Context, name string) (string, err
|
||||
return "", errors.Trace(err)
|
||||
}
|
||||
if row == nil {
|
||||
return "", fmt.Errorf("Unknown sys var: %s", name)
|
||||
return "", terror.ExecResultIsEmpty
|
||||
}
|
||||
value, err := types.ToString(row.Data[0])
|
||||
if err != nil {
|
||||
@ -287,7 +287,44 @@ func (s *session) GetGlobalSysVar(ctx context.Context, name string) (string, err
|
||||
return value, nil
|
||||
}
|
||||
|
||||
// SetGlobalSysVar implements RestrictedSQLExecutor.SetGlobalSysVar interface.
|
||||
// GetGlobalStatusVar implements GlobalVarAccessor.GetGlobalStatusVar interface.
|
||||
func (s *session) GetGlobalStatusVar(ctx context.Context, name string) (string, error) {
|
||||
// TODO: get global status variables from store.
|
||||
v := variable.GetStatusVar(name)
|
||||
if v == nil {
|
||||
return "", terror.UnknownStatusVar.Gen("unknown status variable:%s", name)
|
||||
}
|
||||
|
||||
return v.Value, nil
|
||||
}
|
||||
|
||||
// SetGlobalStatusVar implements GlobalVarAccessor.SetGlobalStatusVar interface.
|
||||
func (s *session) SetGlobalStatusVar(ctx context.Context, name string, value string) error {
|
||||
// TODO: set global status variables from store.
|
||||
v := variable.GetStatusVar(name)
|
||||
if v == nil {
|
||||
return terror.UnknownStatusVar.Gen("unknown status variable:%s", name)
|
||||
}
|
||||
v.Value = value
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetGlobalSysVar implements GlobalVarAccessor.GetGlobalSysVar interface.
|
||||
func (s *session) GetGlobalSysVar(ctx context.Context, name string) (string, error) {
|
||||
sql := fmt.Sprintf(`SELECT VARIABLE_VALUE FROM %s.%s WHERE VARIABLE_NAME="%s";`, mysql.SystemDB, mysql.GlobalVariablesTable, name)
|
||||
sysVar, err := s.getExecRet(ctx, sql)
|
||||
if err != nil {
|
||||
if terror.ExecResultIsEmpty.Equal(err) {
|
||||
return "", terror.ExecResultIsEmpty.Gen("unknown sys variable:%s", name)
|
||||
}
|
||||
return "", errors.Trace(err)
|
||||
}
|
||||
|
||||
return sysVar, nil
|
||||
}
|
||||
|
||||
// SetGlobalSysVar implements GlobalVarAccessor.SetGlobalSysVar interface.
|
||||
func (s *session) SetGlobalSysVar(ctx context.Context, name string, value string) error {
|
||||
sql := fmt.Sprintf(`UPDATE %s.%s SET VARIABLE_VALUE="%s" WHERE VARIABLE_NAME="%s";`, mysql.SystemDB, mysql.GlobalVariablesTable, value, strings.ToLower(name))
|
||||
_, err := s.ExecRestrictedSQL(ctx, sql)
|
||||
@ -545,8 +582,8 @@ func CreateSession(store kv.Storage) (Session, error) {
|
||||
variable.BindSessionVars(s)
|
||||
variable.GetSessionVars(s).SetStatusFlag(mysql.ServerStatusAutocommit, true)
|
||||
|
||||
// session implements variable.GlobalSysVarAccessor. Bind it to ctx.
|
||||
variable.BindGlobalSysVarAccessor(s, s)
|
||||
// session implements variable.GlobalVarAccessor. Bind it to ctx.
|
||||
variable.BindGlobalVarAccessor(s, s)
|
||||
|
||||
// session implements autocommit.Checker. Bind it to ctx
|
||||
autocommit.BindAutocommitChecker(s, s)
|
||||
|
||||
@ -23,6 +23,8 @@ type SessionVars struct {
|
||||
Users map[string]string
|
||||
// system variables
|
||||
Systems map[string]string
|
||||
// status variables
|
||||
StatusVars map[string]string
|
||||
// prepared statement
|
||||
PreparedStmts map[string]interface{}
|
||||
// prepared statement auto increment id
|
||||
@ -58,6 +60,7 @@ func BindSessionVars(ctx context.Context) {
|
||||
v := &SessionVars{
|
||||
Users: make(map[string]string),
|
||||
Systems: make(map[string]string),
|
||||
StatusVars: make(map[string]string),
|
||||
PreparedStmts: make(map[string]interface{}),
|
||||
}
|
||||
|
||||
|
||||
391
sessionctx/variable/statusvar.go
Normal file
391
sessionctx/variable/statusvar.go
Normal file
@ -0,0 +1,391 @@
|
||||
// Copyright 2015 PingCAP, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package variable
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// StatusVars is global status vars map.
|
||||
var StatusVars map[string]*SysVar
|
||||
|
||||
// GetStatusVar returns status var infomation for name.
|
||||
func GetStatusVar(name string) *SysVar {
|
||||
name = strings.ToLower(name)
|
||||
return StatusVars[name]
|
||||
}
|
||||
|
||||
func init() {
|
||||
StatusVars = make(map[string]*SysVar)
|
||||
for _, v := range defaultStatusVars {
|
||||
StatusVars[v.Name] = v
|
||||
}
|
||||
}
|
||||
|
||||
var defaultStatusVars = []*SysVar{
|
||||
{ScopeGlobal, "aborted_clients", "0"},
|
||||
{ScopeGlobal, "binlog_cache_disk_use", "0"},
|
||||
{ScopeGlobal, "binlog_cache_use", "0"},
|
||||
{ScopeGlobal, "binlog_stmt_cache_disk_use", "0"},
|
||||
{ScopeGlobal, "binlog_stmt_cache_use", "0"},
|
||||
{ScopeGlobal | ScopeSession, "bytes_received", "2262"},
|
||||
{ScopeGlobal | ScopeSession, "bytes_sent", "106142"},
|
||||
{ScopeGlobal | ScopeSession, "com_admin_commands", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_assign_to_keycache", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_alter_db", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_alter_db_upgrade", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_alter_event", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_alter_function", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_alter_procedure", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_alter_server", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_alter_table", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_alter_tablespace", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_alter_user", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_analyze", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_begin", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_binlog", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_call_procedure", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_change_db", "2"},
|
||||
{ScopeGlobal | ScopeSession, "com_change_master", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_change_repl_filter", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_check", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_checksum", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_commit", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_create_db", "1"},
|
||||
{ScopeGlobal | ScopeSession, "com_create_event", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_create_function", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_create_index", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_create_procedure", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_create_server", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_create_table", "1"},
|
||||
{ScopeGlobal | ScopeSession, "com_create_trigger", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_create_udf", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_create_user", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_create_view", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_dealloc_sql", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_delete", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_delete_multi", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_do", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_drop_db", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_drop_event", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_drop_function", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_drop_index", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_drop_procedure", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_drop_server", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_drop_table", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_drop_trigger", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_drop_user", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_drop_view", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_empty_query", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_execute_sql", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_explain_other", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_flush", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_get_diagnostics", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_grant", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_ha_close", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_ha_open", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_ha_read", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_help", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_insert", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_insert_select", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_install_plugin", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_kill", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_load", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_lock_tables", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_optimize", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_preload_keys", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_prepare_sql", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_purge", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_purge_before_date", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_release_savepoint", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_rename_table", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_rename_user", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_repair", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_replace", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_replace_select", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_reset", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_resignal", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_revoke", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_revoke_all", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_rollback", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_rollback_to_savepoint", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_savepoint", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_select", "9"},
|
||||
{ScopeGlobal | ScopeSession, "com_set_option", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_signal", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_binlog_events", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_binlogs", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_charsets", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_collations", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_create_db", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_create_event", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_create_func", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_create_proc", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_create_table", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_create_trigger", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_databases", "1"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_engine_logs", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_engine_mutex", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_engine_status", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_events", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_errors", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_fields", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_function_code", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_function_status", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_grants", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_keys", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_master_status", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_open_tables", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_plugins", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_privileges", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_procedure_code", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_procedure_status", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_processlist", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_profile", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_profiles", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_relaylog_events", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_slave_hosts", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_slave_status", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_status", "25"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_storage_engines", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_table_status", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_tables", "2"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_triggers", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_variables", "4"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_warnings", "2"},
|
||||
{ScopeGlobal | ScopeSession, "com_show_create_user", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_shutdown", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_slave_start", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_slave_stop", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_group_replication_start", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_group_replication_stop", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_stmt_execute", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_stmt_close", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_stmt_fetch", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_stmt_prepare", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_stmt_reset", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_stmt_send_long_data", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_truncate", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_uninstall_plugin", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_unlock_tables", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_update", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_update_multi", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_xa_commit", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_xa_end", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_xa_prepare", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_xa_recover", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_xa_rollback", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_xa_start", "0"},
|
||||
{ScopeGlobal | ScopeSession, "com_stmt_reprepare", "0"},
|
||||
{ScopeSession, "compression", "off"},
|
||||
{ScopeGlobal, "connection_errors_accept", "0"},
|
||||
{ScopeGlobal, "connection_errors_internal", "0"},
|
||||
{ScopeGlobal, "connection_errors_max_connections", "0"},
|
||||
{ScopeGlobal, "connection_errors_peer_address", "0"},
|
||||
{ScopeGlobal, "connection_errors_select", "0"},
|
||||
{ScopeGlobal, "connection_errors_tcpwrap", "0"},
|
||||
{ScopeGlobal, "connections", "3"},
|
||||
{ScopeGlobal | ScopeSession, "created_tmp_disk_tables", "0"},
|
||||
{ScopeGlobal, "created_tmp_files", "6"},
|
||||
{ScopeGlobal | ScopeSession, "created_tmp_tables", "3"},
|
||||
{ScopeGlobal, "delayed_errors", "0"},
|
||||
{ScopeGlobal, "delayed_insert_threads", "0"},
|
||||
{ScopeGlobal, "delayed_writes", "0"},
|
||||
{ScopeGlobal, "flush_commands", "1"},
|
||||
{ScopeGlobal | ScopeSession, "handler_commit", "5"},
|
||||
{ScopeGlobal | ScopeSession, "handler_delete", "0"},
|
||||
{ScopeGlobal | ScopeSession, "handler_discover", "0"},
|
||||
{ScopeGlobal | ScopeSession, "handler_external_lock", "265"},
|
||||
{ScopeGlobal | ScopeSession, "handler_mrr_init", "0"},
|
||||
{ScopeGlobal | ScopeSession, "handler_prepare", "0"},
|
||||
{ScopeGlobal | ScopeSession, "handler_read_first", "8"},
|
||||
{ScopeGlobal | ScopeSession, "handler_read_key", "6"},
|
||||
{ScopeGlobal | ScopeSession, "handler_read_last", "0"},
|
||||
{ScopeGlobal | ScopeSession, "handler_read_next", "1"},
|
||||
{ScopeGlobal | ScopeSession, "handler_read_prev", "0"},
|
||||
{ScopeGlobal | ScopeSession, "handler_read_rnd", "0"},
|
||||
{ScopeGlobal | ScopeSession, "handler_read_rnd_next", "7642"},
|
||||
{ScopeGlobal | ScopeSession, "handler_rollback", "0"},
|
||||
{ScopeGlobal | ScopeSession, "handler_savepoint", "0"},
|
||||
{ScopeGlobal | ScopeSession, "handler_savepoint_rollback", "0"},
|
||||
{ScopeGlobal | ScopeSession, "handler_update", "0"},
|
||||
{ScopeGlobal | ScopeSession, "handler_write", "6"},
|
||||
{ScopeGlobal, "innodb_buffer_pool_dump_status", "notstarted"},
|
||||
{ScopeGlobal, "innodb_buffer_pool_load_status", "Bufferpool(s)loadcom"},
|
||||
{ScopeGlobal, "innodb_buffer_pool_resize_status", "notstarted"},
|
||||
{ScopeGlobal, "innodb_buffer_pool_pages_data", "440"},
|
||||
{ScopeGlobal, "innodb_buffer_pool_bytes_data", "7208960"},
|
||||
{ScopeGlobal, "innodb_buffer_pool_pages_dirty", "0"},
|
||||
{ScopeGlobal, "innodb_buffer_pool_bytes_dirty", "0"},
|
||||
{ScopeGlobal, "innodb_buffer_pool_pages_flushed", "54"},
|
||||
{ScopeGlobal, "innodb_buffer_pool_pages_free", "7751"},
|
||||
{ScopeGlobal, "innodb_buffer_pool_pages_misc", "0"},
|
||||
{ScopeGlobal, "innodb_buffer_pool_pages_total", "8191"},
|
||||
{ScopeGlobal, "innodb_buffer_pool_read_ahead_rnd", "0"},
|
||||
{ScopeGlobal, "innodb_buffer_pool_read_ahead", "0"},
|
||||
{ScopeGlobal, "innodb_buffer_pool_read_ahead_evicted", "0"},
|
||||
{ScopeGlobal, "innodb_buffer_pool_read_requests", "1466"},
|
||||
{ScopeGlobal, "innodb_buffer_pool_reads", "402"},
|
||||
{ScopeGlobal, "innodb_buffer_pool_wait_free", "0"},
|
||||
{ScopeGlobal, "innodb_buffer_pool_write_requests", "400"},
|
||||
{ScopeGlobal, "innodb_data_fsyncs", "24"},
|
||||
{ScopeGlobal, "innodb_data_pending_fsyncs", "0"},
|
||||
{ScopeGlobal, "innodb_data_pending_reads", "0"},
|
||||
{ScopeGlobal, "innodb_data_pending_writes", "0"},
|
||||
{ScopeGlobal, "innodb_data_read", "6656512"},
|
||||
{ScopeGlobal, "innodb_data_reads", "426"},
|
||||
{ScopeGlobal, "innodb_data_writes", "84"},
|
||||
{ScopeGlobal, "innodb_data_written", "1232384"},
|
||||
{ScopeGlobal, "innodb_dblwr_pages_written", "20"},
|
||||
{ScopeGlobal, "innodb_dblwr_writes", "2"},
|
||||
{ScopeGlobal, "innodb_log_waits", "0"},
|
||||
{ScopeGlobal, "innodb_log_write_requests", "14"},
|
||||
{ScopeGlobal, "innodb_log_writes", "8"},
|
||||
{ScopeGlobal, "innodb_os_log_fsyncs", "12"},
|
||||
{ScopeGlobal, "innodb_os_log_pending_fsyncs", "0"},
|
||||
{ScopeGlobal, "innodb_os_log_pending_writes", "0"},
|
||||
{ScopeGlobal, "innodb_os_log_written", "17920"},
|
||||
{ScopeGlobal, "innodb_page_size", "16384"},
|
||||
{ScopeGlobal, "innodb_pages_created", "39"},
|
||||
{ScopeGlobal, "innodb_pages_read", "401"},
|
||||
{ScopeGlobal, "innodb_pages_written", "54"},
|
||||
{ScopeGlobal, "innodb_row_lock_current_waits", "0"},
|
||||
{ScopeGlobal, "innodb_row_lock_time", "0"},
|
||||
{ScopeGlobal, "innodb_row_lock_time_avg", "0"},
|
||||
{ScopeGlobal, "innodb_row_lock_time_max", "0"},
|
||||
{ScopeGlobal, "innodb_row_lock_waits", "0"},
|
||||
{ScopeGlobal, "innodb_rows_deleted", "0"},
|
||||
{ScopeGlobal, "innodb_rows_inserted", "0"},
|
||||
{ScopeGlobal, "innodb_rows_read", "8"},
|
||||
{ScopeGlobal, "innodb_rows_updated", "0"},
|
||||
{ScopeGlobal, "innodb_num_open_files", "17"},
|
||||
{ScopeGlobal, "innodb_truncated_status_writes", "0"},
|
||||
{ScopeGlobal, "innodb_available_undo_logs", "128"},
|
||||
{ScopeSession, "last_query_cost", "104.799000"},
|
||||
{ScopeSession, "last_query_partial_plans", "1"},
|
||||
{ScopeGlobal, "key_blocks_not_flushed", "0"},
|
||||
{ScopeGlobal, "key_blocks_unused", "6695"},
|
||||
{ScopeGlobal, "key_blocks_used", "3"},
|
||||
{ScopeGlobal, "key_read_requests", "6"},
|
||||
{ScopeGlobal, "key_reads", "3"},
|
||||
{ScopeGlobal, "key_write_requests", "0"},
|
||||
{ScopeGlobal, "key_writes", "0"},
|
||||
{ScopeGlobal | ScopeSession, "locked_connects", "0"},
|
||||
{ScopeGlobal | ScopeSession, "max_execution_time_exceeded", "0"},
|
||||
{ScopeGlobal | ScopeSession, "max_execution_time_set", "0"},
|
||||
{ScopeGlobal | ScopeSession, "max_execution_time_set_failed", "0"},
|
||||
{ScopeGlobal, "max_used_connections", "1"},
|
||||
{ScopeGlobal, "max_used_connections_time", "2015-11-0902:49:42"},
|
||||
{ScopeGlobal, "not_flushed_delayed_rows", "0"},
|
||||
{ScopeGlobal, "ongoing_anonymous_transaction_count", "0"},
|
||||
{ScopeGlobal, "open_files", "14"},
|
||||
{ScopeGlobal, "open_streams", "0"},
|
||||
{ScopeGlobal, "open_table_definitions", "105"},
|
||||
{ScopeGlobal | ScopeSession, "Open_tables", "101"},
|
||||
{ScopeGlobal, "opened_files", "142"},
|
||||
{ScopeGlobal | ScopeSession, "opened_table_definitions", "106"},
|
||||
{ScopeGlobal | ScopeSession, "opened_tables", "108"},
|
||||
{ScopeGlobal, "performance_schema_accounts_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_cond_classes_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_cond_instances_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_digest_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_file_classes_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_file_handles_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_file_instances_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_hosts_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_index_stat_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_locker_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_memory_classes_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_metadata_lock_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_mutex_classes_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_mutex_instances_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_nested_statement_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_prepared_statements_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_program_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_rwlock_classes_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_rwlock_instances_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_session_connect_attrs_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_socket_classes_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_socket_instances_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_stage_classes_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_statement_classes_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_table_handles_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_table_instances_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_table_lock_stat_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_thread_classes_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_thread_instances_lost", "0"},
|
||||
{ScopeGlobal, "performance_schema_users_lost", "0"},
|
||||
{ScopeGlobal, "prepared_stmt_count", "0"},
|
||||
{ScopeGlobal, "qcache_free_blocks", "1"},
|
||||
{ScopeGlobal, "qcache_free_memory", "1031832"},
|
||||
{ScopeGlobal, "qcache_hits", "0"},
|
||||
{ScopeGlobal, "qcache_inserts", "0"},
|
||||
{ScopeGlobal, "qcache_lowmem_prunes", "0"},
|
||||
{ScopeGlobal, "qcache_not_cached", "5"},
|
||||
{ScopeGlobal, "qcache_queries_in_cache", "0"},
|
||||
{ScopeGlobal, "qcache_total_blocks", "1"},
|
||||
{ScopeGlobal | ScopeSession, "queries", "56"},
|
||||
{ScopeGlobal | ScopeSession, "questions", "54"},
|
||||
{ScopeGlobal | ScopeSession, "select_full_join", "0"},
|
||||
{ScopeGlobal | ScopeSession, "select_full_range_join", "0"},
|
||||
{ScopeGlobal | ScopeSession, "select_range", "0"},
|
||||
{ScopeGlobal | ScopeSession, "select_range_check", "0"},
|
||||
{ScopeGlobal | ScopeSession, "select_scan", "24"},
|
||||
{ScopeGlobal, "slave_open_temp_tables", "0"},
|
||||
{ScopeGlobal | ScopeSession, "slow_launch_threads", "0"},
|
||||
{ScopeGlobal | ScopeSession, "slow_queries", "0"},
|
||||
{ScopeGlobal | ScopeSession, "sort_merge_passes", "0"},
|
||||
{ScopeGlobal | ScopeSession, "sort_range", "0"},
|
||||
{ScopeGlobal | ScopeSession, "sort_rows", "0"},
|
||||
{ScopeGlobal | ScopeSession, "sort_scan", "0"},
|
||||
{ScopeGlobal, "ssl_accept_renegotiates", "0"},
|
||||
{ScopeGlobal, "ssl_accepts", "0"},
|
||||
{ScopeGlobal, "ssl_callback_cache_hits", "0"},
|
||||
{ScopeGlobal | ScopeSession, "ssl_cipher", ""},
|
||||
{ScopeGlobal | ScopeSession, "ssl_cipher_list", ""},
|
||||
{ScopeGlobal, "ssl_client_connects", "0"},
|
||||
{ScopeGlobal, "ssl_connect_renegotiates", "0"},
|
||||
{ScopeGlobal, "ssl_ctx_verify_depth", "0"},
|
||||
{ScopeGlobal, "ssl_ctx_verify_mode", "0"},
|
||||
{ScopeGlobal | ScopeSession, "Ssl_default_timeout", "0"},
|
||||
{ScopeGlobal, "ssl_finished_accepts", "0"},
|
||||
{ScopeGlobal, "ssl_finished_connects", "0"},
|
||||
{ScopeGlobal | ScopeSession, "ssl_server_not_after", ""},
|
||||
{ScopeGlobal | ScopeSession, "ssl_server_not_before", ""},
|
||||
{ScopeGlobal, "ssl_session_cache_hits", "0"},
|
||||
{ScopeGlobal, "ssl_session_cache_misses", "0"},
|
||||
{ScopeGlobal, "ssl_session_cache_mode", "NONE"},
|
||||
{ScopeGlobal, "ssl_session_cache_overflows", "0"},
|
||||
{ScopeGlobal, "ssl_session_cache_size", "0"},
|
||||
{ScopeGlobal, "ssl_session_cache_timeouts", "0"},
|
||||
{ScopeGlobal | ScopeSession, "ssl_sessions_reused", "0"},
|
||||
{ScopeGlobal, "ssl_used_session_cache_entries", "0"},
|
||||
{ScopeGlobal | ScopeSession, "ssl_verify_depth", "0"},
|
||||
{ScopeGlobal | ScopeSession, "ssl_verify_mode", "0"},
|
||||
{ScopeGlobal | ScopeSession, "ssl_version", ""},
|
||||
{ScopeGlobal, "table_locks_immediate", "123"},
|
||||
{ScopeGlobal, "table_locks_waited", "0"},
|
||||
{ScopeGlobal | ScopeSession, "table_open_cache_hits", "28"},
|
||||
{ScopeGlobal | ScopeSession, "table_open_cache_misses", "108"},
|
||||
{ScopeGlobal | ScopeSession, "table_open_cache_overflows", "0"},
|
||||
{ScopeGlobal, "tc_log_max_pages_used", "0"},
|
||||
{ScopeGlobal, "tc_log_page_size", "0"},
|
||||
{ScopeGlobal, "tc_log_page_waits", "0"},
|
||||
{ScopeGlobal, "threads_cached", "0"},
|
||||
{ScopeGlobal, "threads_connected", "1"},
|
||||
{ScopeGlobal, "threads_created", "1"},
|
||||
{ScopeGlobal, "threads_running", "1"},
|
||||
{ScopeGlobal, "uptime", "15998"},
|
||||
{ScopeGlobal, "uptime_since_flush_status", "15998"},
|
||||
}
|
||||
31
sessionctx/variable/statusvar_test.go
Normal file
31
sessionctx/variable/statusvar_test.go
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2015 PingCAP, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package variable
|
||||
|
||||
import (
|
||||
. "github.com/pingcap/check"
|
||||
)
|
||||
|
||||
var _ = Suite(&testStatusVarSuite{})
|
||||
|
||||
type testStatusVarSuite struct {
|
||||
}
|
||||
|
||||
func (*testStatusVarSuite) TestStatusVar(c *C) {
|
||||
f := GetStatusVar("aborted_clients")
|
||||
c.Assert(f, NotNil)
|
||||
|
||||
f = GetStatusVar("wrong-var-name")
|
||||
c.Assert(f, IsNil)
|
||||
}
|
||||
@ -574,12 +574,16 @@ const (
|
||||
CollationConnection = "collation_connection"
|
||||
)
|
||||
|
||||
// GlobalSysVarAccessor is the interface for accessing global scope system variables.
|
||||
type GlobalSysVarAccessor interface {
|
||||
// GlobalVarAccessor is the interface for accessing global scope system and status variables.
|
||||
type GlobalVarAccessor interface {
|
||||
// GetGlobalSysVar gets the global system variable value for name.
|
||||
GetGlobalSysVar(ctx context.Context, name string) (string, error)
|
||||
// SetGlobalSysVar sets the global system variable name to value.
|
||||
SetGlobalSysVar(ctx context.Context, name string, value string) error
|
||||
// GetGlobalStatusVar gets the global status variable value for name.
|
||||
GetGlobalStatusVar(ctx context.Context, name string) (string, error)
|
||||
// SetGlobalStatusVar sets the global status variable name to value.
|
||||
SetGlobalStatusVar(ctx context.Context, name string, value string) error
|
||||
}
|
||||
|
||||
// globalSysVarAccessorKeyType is a dummy type to avoid naming collision in context.
|
||||
@ -592,14 +596,14 @@ func (k globalSysVarAccessorKeyType) String() string {
|
||||
|
||||
const accessorKey globalSysVarAccessorKeyType = 0
|
||||
|
||||
// BindGlobalSysVarAccessor binds global sysvar accessor to context.
|
||||
func BindGlobalSysVarAccessor(ctx context.Context, accessor GlobalSysVarAccessor) {
|
||||
// BindGlobalVarAccessor binds global var accessor to context.
|
||||
func BindGlobalVarAccessor(ctx context.Context, accessor GlobalVarAccessor) {
|
||||
ctx.SetValue(accessorKey, accessor)
|
||||
}
|
||||
|
||||
// GetGlobalSysVarAccessor gets accessor from ctx.
|
||||
func GetGlobalSysVarAccessor(ctx context.Context) GlobalSysVarAccessor {
|
||||
v, ok := ctx.Value(accessorKey).(GlobalSysVarAccessor)
|
||||
// GetGlobalVarAccessor gets accessor from ctx.
|
||||
func GetGlobalVarAccessor(ctx context.Context) GlobalVarAccessor {
|
||||
v, ok := ctx.Value(accessorKey).(GlobalVarAccessor)
|
||||
if !ok {
|
||||
panic("Miss global sysvar accessor")
|
||||
}
|
||||
|
||||
@ -55,6 +55,7 @@ const (
|
||||
ShowWarnings
|
||||
ShowCharset
|
||||
ShowVariables
|
||||
ShowStatus
|
||||
ShowCollation
|
||||
ShowCreateTable
|
||||
ShowGrants
|
||||
|
||||
@ -24,6 +24,8 @@ import (
|
||||
"github.com/pingcap/tidb/context"
|
||||
"github.com/pingcap/tidb/ddl"
|
||||
"github.com/pingcap/tidb/model"
|
||||
"github.com/pingcap/tidb/mysql"
|
||||
"github.com/pingcap/tidb/privilege"
|
||||
"github.com/pingcap/tidb/rset"
|
||||
"github.com/pingcap/tidb/sessionctx"
|
||||
"github.com/pingcap/tidb/stmt"
|
||||
@ -108,10 +110,34 @@ func (s *DropTableStmt) SetText(text string) {
|
||||
// Exec implements the stmt.Statement Exec interface.
|
||||
func (s *DropTableStmt) Exec(ctx context.Context) (rset.Recordset, error) {
|
||||
var notExistTables []string
|
||||
is := sessionctx.GetDomain(ctx).InfoSchema()
|
||||
for _, ti := range s.TableIdents {
|
||||
err := sessionctx.GetDomain(ctx).DDL().DropTable(ctx, ti.Full(ctx))
|
||||
// TODO: we should return special error for table not exist, checking "not exist" is not enough,
|
||||
// because some other errors may contain this error string too.
|
||||
fullti := ti.Full(ctx)
|
||||
schema, ok := is.SchemaByName(fullti.Schema)
|
||||
if !ok {
|
||||
// TODO: we should return special error for table not exist, checking "not exist" is not enough,
|
||||
// because some other errors may contain this error string too.
|
||||
notExistTables = append(notExistTables, ti.String())
|
||||
continue
|
||||
}
|
||||
tb, err := is.TableByName(fullti.Schema, fullti.Name)
|
||||
if err != nil && strings.HasSuffix(err.Error(), "not exist") {
|
||||
notExistTables = append(notExistTables, ti.String())
|
||||
continue
|
||||
} else if err != nil {
|
||||
return nil, errors.Trace(err)
|
||||
}
|
||||
// Check Privilege
|
||||
privChecker := privilege.GetPrivilegeChecker(ctx)
|
||||
hasPriv, err := privChecker.Check(ctx, schema, tb.Meta(), mysql.DropPriv)
|
||||
if err != nil {
|
||||
return nil, errors.Trace(err)
|
||||
}
|
||||
if !hasPriv {
|
||||
return nil, errors.Errorf("You do not have the privilege to drop table %s.%s.", ti.Schema, ti.Name)
|
||||
}
|
||||
|
||||
err = sessionctx.GetDomain(ctx).DDL().DropTable(ctx, fullti)
|
||||
if terror.ErrorEqual(err, ddl.ErrNotExists) || terror.DatabaseNotExists.Equal(err) {
|
||||
notExistTables = append(notExistTables, ti.String())
|
||||
} else if err != nil {
|
||||
|
||||
@ -100,7 +100,7 @@ func (s *SetStmt) Exec(ctx context.Context) (_ rset.Recordset, err error) {
|
||||
log.Debug("Set sys/user variables")
|
||||
|
||||
sessionVars := variable.GetSessionVars(ctx)
|
||||
globalVars := variable.GetGlobalSysVarAccessor(ctx)
|
||||
globalVars := variable.GetGlobalVarAccessor(ctx)
|
||||
for _, v := range s.Variables {
|
||||
// Variable is case insensitive, we use lower case.
|
||||
name := strings.ToLower(v.Name)
|
||||
|
||||
@ -451,7 +451,8 @@ func (s *testKVSuite) TestConditionIfNotExist(c *C) {
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
c.Assert(success, Greater, int64(1))
|
||||
// At least one txn can success.
|
||||
c.Assert(success, Greater, int64(0))
|
||||
|
||||
// Clean up
|
||||
txn, err := s.s.Begin()
|
||||
|
||||
@ -28,6 +28,10 @@ var (
|
||||
|
||||
CommitNotInTransaction = ClassExecutor.New(CodeCommitNotInTransaction, "commit not in transaction")
|
||||
RollbackNotInTransaction = ClassExecutor.New(CodeRollbackNotInTransaction, "rollback not in transaction")
|
||||
ExecResultIsEmpty = ClassExecutor.New(CodeExecResultIsEmpty, "exec result is empty")
|
||||
|
||||
UnknownStatusVar = ClassVariable.New(CodeUnknownStatusVar, "unknown status variable")
|
||||
UnknownSystemVar = ClassVariable.New(CodeUnknownSystemVar, "unknown system variable")
|
||||
)
|
||||
|
||||
// ErrCode represents a specific error type in a error class.
|
||||
@ -44,6 +48,7 @@ const (
|
||||
const (
|
||||
CodeCommitNotInTransaction ErrCode = iota + 1
|
||||
CodeRollbackNotInTransaction
|
||||
CodeExecResultIsEmpty
|
||||
)
|
||||
|
||||
// KV error codes.
|
||||
@ -52,6 +57,12 @@ const (
|
||||
CodeNoDataForHandle
|
||||
)
|
||||
|
||||
// Variable error codes.
|
||||
const (
|
||||
CodeUnknownStatusVar ErrCode = iota + 1
|
||||
CodeUnknownSystemVar
|
||||
)
|
||||
|
||||
// ErrClass represents a class of errors.
|
||||
type ErrClass int
|
||||
|
||||
@ -63,6 +74,7 @@ const (
|
||||
ClassExecutor
|
||||
ClassKV
|
||||
ClassServer
|
||||
ClassVariable
|
||||
// Add more as needed.
|
||||
)
|
||||
|
||||
|
||||
@ -16,11 +16,11 @@ package mock
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pingcap/tidb/context"
|
||||
"github.com/pingcap/tidb/kv"
|
||||
"github.com/pingcap/tidb/sessionctx/variable"
|
||||
"github.com/pingcap/tidb/terror"
|
||||
)
|
||||
|
||||
var _ context.Context = (*Context)(nil)
|
||||
@ -57,22 +57,39 @@ func (c *Context) FinishTxn(rollback bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetGlobalSysVar implements GlobalSysVarAccessor GetGlobalSysVar interface.
|
||||
func (c *Context) GetGlobalSysVar(ctx context.Context, name string) (string, error) {
|
||||
sysvars := variable.SysVars
|
||||
v, ok := sysvars[strings.ToLower(name)]
|
||||
if !ok {
|
||||
return "", nil
|
||||
// GetGlobalStatusVar implements GlobalVarAccessor GetGlobalStatusVar interface.
|
||||
func (c *Context) GetGlobalStatusVar(ctx context.Context, name string) (string, error) {
|
||||
v := variable.GetStatusVar(name)
|
||||
if v == nil {
|
||||
return "", terror.UnknownStatusVar.Gen("unknown status variable: %s", name)
|
||||
}
|
||||
return v.Value, nil
|
||||
}
|
||||
|
||||
// SetGlobalSysVar implements GlobalSysVarAccessor SetGlobalSysVar interface.
|
||||
// SetGlobalStatusVar implements GlobalVarAccessor SetGlobalStatusVar interface.
|
||||
func (c *Context) SetGlobalStatusVar(ctx context.Context, name string, value string) error {
|
||||
v := variable.GetStatusVar(name)
|
||||
if v == nil {
|
||||
return terror.UnknownStatusVar.Gen("unknown status variable: %s", name)
|
||||
}
|
||||
v.Value = value
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetGlobalSysVar implements GlobalVarAccessor GetGlobalSysVar interface.
|
||||
func (c *Context) GetGlobalSysVar(ctx context.Context, name string) (string, error) {
|
||||
v := variable.GetSysVar(name)
|
||||
if v == nil {
|
||||
return "", terror.UnknownSystemVar.Gen("unknown sys variable: %s", name)
|
||||
}
|
||||
return v.Value, nil
|
||||
}
|
||||
|
||||
// SetGlobalSysVar implements GlobalVarAccessor SetGlobalSysVar interface.
|
||||
func (c *Context) SetGlobalSysVar(ctx context.Context, name string, value string) error {
|
||||
sysvars := variable.SysVars
|
||||
v, ok := sysvars[strings.ToLower(name)]
|
||||
if !ok {
|
||||
return fmt.Errorf("Unknown sys var: %s", name)
|
||||
v := variable.GetSysVar(name)
|
||||
if v == nil {
|
||||
return terror.UnknownSystemVar.Gen("unknown sys variable: %s", name)
|
||||
}
|
||||
v.Value = value
|
||||
return nil
|
||||
|
||||
@ -21,19 +21,11 @@ import (
|
||||
// RoundFloat uses default rounding mode, see http://www.gnu.org/software/libc/manual/html_node/Rounding.html
|
||||
// so we will choose the even number if the result is midway between two representable value.
|
||||
// e.g, 1.5 -> 2, 2.5 -> 2.
|
||||
func RoundFloat(val float64) float64 {
|
||||
v, frac := math.Modf(val)
|
||||
if val >= 0.0 {
|
||||
if frac > 0.5 || (frac == 0.5 && uint64(v)%2 != 0) {
|
||||
v += 1.0
|
||||
}
|
||||
} else {
|
||||
if frac < -0.5 || (frac == -0.5 && uint64(v)%2 != 0) {
|
||||
v -= 1.0
|
||||
}
|
||||
func RoundFloat(f float64) float64 {
|
||||
if math.Remainder(f, 1.0) < 0 {
|
||||
return math.Ceil(f)
|
||||
}
|
||||
|
||||
return v
|
||||
return math.Floor(f)
|
||||
}
|
||||
|
||||
func getMaxFloat(flen int, decimal int) float64 {
|
||||
|
||||
Reference in New Issue
Block a user