// Eval implements the Expression Eval interface. func (v *Variable) Eval(ctx context.Context, args map[interface{}]interface{}) (interface{}, error) { name := strings.ToLower(v.Name) sessionVars := variable.GetSessionVars(ctx) globalVars := variable.GetGlobalVarAccessor(ctx) if !v.IsSystem { // user vars if value, ok := sessionVars.Users[name]; ok { return value, nil } // select null user vars is permitted. return nil, nil } _, ok := variable.SysVars[name] if !ok { // select null sys vars is not permitted return nil, variable.UnknownSystemVar.Gen("Unknown system variable '%s'", name) } if !v.IsGlobal { if value, ok := sessionVars.Systems[name]; ok { return value, nil } } value, err := globalVars.GetGlobalSysVar(ctx, name) if err != nil { return nil, errors.Trace(err) } return value, nil }
func (e *ShowExec) fetchShowVariables() error { sessionVars := variable.GetSessionVars(e.ctx) globalVars := variable.GetGlobalVarAccessor(e.ctx) for _, v := range variable.SysVars { var err error var value string if !e.GlobalScope { // Try to get Session Scope variable value first. sv := sessionVars.GetSystemVar(v.Name) if sv.IsNull() { value, err = globalVars.GetGlobalSysVar(e.ctx, v.Name) if err != nil { return errors.Trace(err) } sv.SetString(value) err = sessionVars.SetSystemVar(v.Name, sv) if err != nil { return errors.Trace(err) } } value = sv.GetString() } else { value, err = globalVars.GetGlobalSysVar(e.ctx, v.Name) if err != nil { return errors.Trace(err) } } row := &Row{Data: types.MakeDatums(v.Name, value)} e.rows = append(e.rows, row) } return nil }
func (e *ShowExec) fetchShowVariables() error { sessionVars := variable.GetSessionVars(e.ctx) globalVars := variable.GetGlobalVarAccessor(e.ctx) for _, v := range variable.SysVars { var err error var value string if !e.GlobalScope { // Try to get Session Scope variable value first. sv, ok := sessionVars.Systems[v.Name] if ok { value = sv } else { // If session scope variable is not set, get the global scope value. value, err = globalVars.GetGlobalSysVar(e.ctx, v.Name) if err != nil { return errors.Trace(err) } } } else { value, err = globalVars.GetGlobalSysVar(e.ctx, v.Name) if err != nil { return errors.Trace(err) } } row := &Row{Data: types.MakeDatums(v.Name, value)} e.rows = append(e.rows, row) } return nil }
func (s *ShowPlan) fetchShowVariables(ctx context.Context) error { sessionVars := variable.GetSessionVars(ctx) globalVars := variable.GetGlobalVarAccessor(ctx) m := map[interface{}]interface{}{} for _, v := range variable.SysVars { 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 { // Try to get Session Scope variable value first. sv, ok := sessionVars.Systems[v.Name] if ok { value = sv } else { // If session scope variable is not set, get the global scope value. value, err = globalVars.GetGlobalSysVar(ctx, v.Name) if err != nil { return errors.Trace(err) } } } else { value, err = globalVars.GetGlobalSysVar(ctx, v.Name) if err != nil { return errors.Trace(err) } } row := &plan.Row{Data: []interface{}{v.Name, value}} s.rows = append(s.rows, row) } return 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 (e *Evaluator) variable(v *ast.VariableExpr) bool { name := strings.ToLower(v.Name) sessionVars := variable.GetSessionVars(e.ctx) globalVars := variable.GetGlobalVarAccessor(e.ctx) if !v.IsSystem { // user vars if value, ok := sessionVars.Users[name]; ok { v.SetString(value) return true } // select null user vars is permitted. v.SetNull() return true } _, ok := variable.SysVars[name] if !ok { // select null sys vars is not permitted e.err = variable.UnknownSystemVar.Gen("Unknown system variable '%s'", name) return false } if !v.IsGlobal { if value, ok := sessionVars.Systems[name]; ok { v.SetString(value) return true } } value, err := globalVars.GetGlobalSysVar(e.ctx, name) if err != nil { e.err = errors.Trace(err) return false } v.SetString(value) return true }
func (e *Evaluator) variable(v *ast.VariableExpr) bool { name := strings.ToLower(v.Name) sessionVars := variable.GetSessionVars(e.ctx) globalVars := variable.GetGlobalVarAccessor(e.ctx) if !v.IsSystem { if v.Value != nil && !v.Value.GetDatum().IsNull() { strVal, err := v.Value.GetDatum().ToString() if err != nil { e.err = errors.Trace(err) return false } sessionVars.Users[name] = strings.ToLower(strVal) v.SetString(strVal) return true } // user vars if value, ok := sessionVars.Users[name]; ok { v.SetString(value) return true } // select null user vars is permitted. v.SetNull() return true } sysVar, ok := variable.SysVars[name] if !ok { // select null sys vars is not permitted e.err = variable.UnknownSystemVar.Gen("Unknown system variable '%s'", name) return false } if sysVar.Scope == variable.ScopeNone { v.SetString(sysVar.Value) return true } if !v.IsGlobal { d := sessionVars.GetSystemVar(name) if d.IsNull() { if sysVar.Scope&variable.ScopeGlobal == 0 { d.SetString(sysVar.Value) } else { // Get global system variable and fill it in session. globalVal, err := globalVars.GetGlobalSysVar(e.ctx, name) if err != nil { e.err = errors.Trace(err) return false } d.SetString(globalVal) err = sessionVars.SetSystemVar(name, d) if err != nil { e.err = errors.Trace(err) return false } } } v.SetDatum(d) return true } value, err := globalVars.GetGlobalSysVar(e.ctx, name) if err != nil { e.err = errors.Trace(err) return false } v.SetString(value) return true }
func (er *expressionRewriter) rewriteVariable(v *ast.VariableExpr) bool { stkLen := len(er.ctxStack) name := strings.ToLower(v.Name) sessionVars := variable.GetSessionVars(er.b.ctx) globalVars := variable.GetGlobalVarAccessor(er.b.ctx) if !v.IsSystem { var d types.Datum var err error if v.Value != nil { d, err = er.ctxStack[stkLen-1].Eval(nil, er.b.ctx) if err != nil { er.err = errors.Trace(err) return false } er.ctxStack = er.ctxStack[:stkLen-1] } if !d.IsNull() { strVal, err := d.ToString() if err != nil { er.err = errors.Trace(err) return false } sessionVars.Users[name] = strings.ToLower(strVal) er.ctxStack = append(er.ctxStack, datumToConstant(d, mysql.TypeString)) } else if value, ok := sessionVars.Users[name]; ok { er.ctxStack = append(er.ctxStack, datumToConstant(types.NewStringDatum(value), mysql.TypeString)) } else { // select null user vars is permitted. er.ctxStack = append(er.ctxStack, &expression.Constant{RetType: types.NewFieldType(mysql.TypeNull)}) } return true } sysVar, ok := variable.SysVars[name] if !ok { // select null sys vars is not permitted er.err = variable.UnknownSystemVar.Gen("Unknown system variable '%s'", name) return false } if sysVar.Scope == variable.ScopeNone { er.ctxStack = append(er.ctxStack, datumToConstant(types.NewDatum(sysVar.Value), mysql.TypeString)) return true } if v.IsGlobal { value, err := globalVars.GetGlobalSysVar(er.b.ctx, name) if err != nil { er.err = errors.Trace(err) return false } er.ctxStack = append(er.ctxStack, datumToConstant(types.NewDatum(value), mysql.TypeString)) return true } d := sessionVars.GetSystemVar(name) if d.IsNull() { if sysVar.Scope&variable.ScopeGlobal == 0 { d.SetString(sysVar.Value) } else { // Get global system variable and fill it in session. globalVal, err := globalVars.GetGlobalSysVar(er.b.ctx, name) if err != nil { er.err = errors.Trace(err) return false } d.SetString(globalVal) err = sessionVars.SetSystemVar(name, d) if err != nil { er.err = errors.Trace(err) return false } } } er.ctxStack = append(er.ctxStack, datumToConstant(d, mysql.TypeString)) return true }
func (e *SimpleExec) executeSet(s *ast.SetStmt) error { sessionVars := variable.GetSessionVars(e.ctx) globalVars := variable.GetGlobalVarAccessor(e.ctx) for _, v := range s.Variables { // Variable is case insensitive, we use lower case. if v.Name == ast.SetNames { // This is set charset stmt. cs := v.Value.GetValue().(string) var co string if v.ExtendValue != nil { co = v.ExtendValue.GetValue().(string) } err := e.setCharset(cs, co) if err != nil { return errors.Trace(err) } continue } name := strings.ToLower(v.Name) if !v.IsSystem { // Set user variable. value, err := evaluator.Eval(e.ctx, v.Value) if err != nil { return errors.Trace(err) } if value.IsNull() { delete(sessionVars.Users, name) } else { svalue, err1 := value.ToString() if err1 != nil { return errors.Trace(err1) } sessionVars.Users[name] = fmt.Sprintf("%v", svalue) } continue } // Set system variable sysVar := variable.GetSysVar(name) if sysVar == nil { return variable.UnknownSystemVar.Gen("Unknown system variable '%s'", name) } if sysVar.Scope == variable.ScopeNone { return errors.Errorf("Variable '%s' is a read only variable", name) } if v.IsGlobal { // Set global scope system variable. if sysVar.Scope&variable.ScopeGlobal == 0 { return errors.Errorf("Variable '%s' is a SESSION variable and can't be used with SET GLOBAL", name) } value, err := evaluator.Eval(e.ctx, v.Value) if err != nil { return errors.Trace(err) } if value.IsNull() { value.SetString("") } svalue, err := value.ToString() if err != nil { return errors.Trace(err) } err = globalVars.SetGlobalSysVar(e.ctx, name, svalue) if err != nil { return errors.Trace(err) } } else { // Set session scope system variable. if sysVar.Scope&variable.ScopeSession == 0 { return errors.Errorf("Variable '%s' is a GLOBAL variable and should be set with SET GLOBAL", name) } value, err := evaluator.Eval(e.ctx, v.Value) if err != nil { return errors.Trace(err) } err = sessionVars.SetSystemVar(name, value) if err != nil { return errors.Trace(err) } } } return nil }
// Exec implements the stmt.Statement Exec interface. func (s *SetStmt) Exec(ctx context.Context) (_ rset.Recordset, err error) { log.Debug("Set sys/user variables") sessionVars := variable.GetSessionVars(ctx) globalVars := variable.GetGlobalVarAccessor(ctx) for _, v := range s.Variables { // Variable is case insensitive, we use lower case. name := strings.ToLower(v.Name) if !v.IsSystem { // User variable. value, err := v.getValue(ctx) if err != nil { return nil, errors.Trace(err) } if value == nil { delete(sessionVars.Users, name) } else { sessionVars.Users[name] = fmt.Sprintf("%v", value) } return nil, nil } sysVar := variable.GetSysVar(name) if sysVar == nil { return nil, variable.UnknownSystemVar.Gen("Unknown system variable '%s'", name) } if sysVar.Scope == variable.ScopeNone { return nil, errors.Errorf("Variable '%s' is a read only variable", name) } if v.IsGlobal { if sysVar.Scope&variable.ScopeGlobal > 0 { value, err := v.getValue(ctx) if err != nil { return nil, errors.Trace(err) } if value == nil { value = "" } svalue, err := types.ToString(value) if err != nil { return nil, errors.Trace(err) } err = globalVars.SetGlobalSysVar(ctx, name, svalue) return nil, errors.Trace(err) } return nil, errors.Errorf("Variable '%s' is a SESSION variable and can't be used with SET GLOBAL", name) } if sysVar.Scope&variable.ScopeSession > 0 { if value, err := v.getValue(ctx); err != nil { return nil, errors.Trace(err) } else if value == nil { sessionVars.Systems[name] = "" } else { sessionVars.Systems[name] = fmt.Sprintf("%v", value) } return nil, nil } return nil, errors.Errorf("Variable '%s' is a GLOBAL variable and should be set with SET GLOBAL", name) } return nil, nil }
func (er *expressionRewriter) rewriteVariable(v *ast.VariableExpr) { stkLen := len(er.ctxStack) name := strings.ToLower(v.Name) sessionVars := variable.GetSessionVars(er.b.ctx) globalVars := variable.GetGlobalVarAccessor(er.b.ctx) if !v.IsSystem { if v.Value != nil { er.ctxStack[stkLen-1], er.err = expression.NewFunction(ast.SetVar, er.ctxStack[stkLen-1].GetType(), datumToConstant(types.NewDatum(name), mysql.TypeString), er.ctxStack[stkLen-1]) return } if _, ok := sessionVars.Users[name]; ok { f, err := expression.NewFunction(ast.GetVar, // TODO: Here is wrong, the sessionVars should store a name -> Datum map. Will fix it later. types.NewFieldType(mysql.TypeString), datumToConstant(types.NewStringDatum(name), mysql.TypeString)) if err != nil { er.err = errors.Trace(err) return } er.ctxStack = append(er.ctxStack, f) } else { // select null user vars is permitted. er.ctxStack = append(er.ctxStack, &expression.Constant{RetType: types.NewFieldType(mysql.TypeNull)}) } return } sysVar, ok := variable.SysVars[name] if !ok { // select null sys vars is not permitted er.err = variable.UnknownSystemVar.Gen("Unknown system variable '%s'", name) return } if sysVar.Scope == variable.ScopeNone { er.ctxStack = append(er.ctxStack, datumToConstant(types.NewDatum(sysVar.Value), mysql.TypeString)) return } if v.IsGlobal { value, err := globalVars.GetGlobalSysVar(er.b.ctx, name) if err != nil { er.err = errors.Trace(err) return } er.ctxStack = append(er.ctxStack, datumToConstant(types.NewDatum(value), mysql.TypeString)) return } d := sessionVars.GetSystemVar(name) if d.IsNull() { if sysVar.Scope&variable.ScopeGlobal == 0 { d.SetString(sysVar.Value) } else { // Get global system variable and fill it in session. globalVal, err := globalVars.GetGlobalSysVar(er.b.ctx, name) if err != nil { er.err = errors.Trace(err) return } d.SetString(globalVal) err = sessionVars.SetSystemVar(name, d) if err != nil { er.err = errors.Trace(err) return } } } er.ctxStack = append(er.ctxStack, datumToConstant(d, mysql.TypeString)) return }
func (e *SimpleExec) executeSet(s *ast.SetStmt) error { sessionVars := variable.GetSessionVars(e.ctx) globalVars := variable.GetGlobalVarAccessor(e.ctx) for _, v := range s.Variables { // Variable is case insensitive, we use lower case. name := strings.ToLower(v.Name) if !v.IsSystem { // Set user variable. value, err := evaluator.Eval(e.ctx, v.Value) if err != nil { return errors.Trace(err) } if value == nil { delete(sessionVars.Users, name) } else { sessionVars.Users[name] = fmt.Sprintf("%v", value) } continue } // Set system variable sysVar := variable.GetSysVar(name) if sysVar == nil { return variable.UnknownSystemVar.Gen("Unknown system variable '%s'", name) } if sysVar.Scope == variable.ScopeNone { return errors.Errorf("Variable '%s' is a read only variable", name) } if v.IsGlobal { // Set global scope system variable. if sysVar.Scope&variable.ScopeGlobal == 0 { return errors.Errorf("Variable '%s' is a SESSION variable and can't be used with SET GLOBAL", name) } value, err := evaluator.Eval(e.ctx, v.Value) if err != nil { return errors.Trace(err) } if value == nil { value = "" } svalue, err := types.ToString(value) if err != nil { return errors.Trace(err) } err = globalVars.SetGlobalSysVar(e.ctx, name, svalue) if err != nil { return errors.Trace(err) } } else { // Set session scope system variable. if sysVar.Scope&variable.ScopeSession == 0 { return errors.Errorf("Variable '%s' is a GLOBAL variable and should be set with SET GLOBAL", name) } if value, err := evaluator.Eval(e.ctx, v.Value); err != nil { return errors.Trace(err) } else if value == nil { sessionVars.Systems[name] = "" } else { sessionVars.Systems[name] = fmt.Sprintf("%v", value) } } } return nil }