// LoadCommonGlobalVariableIfNeeded loads and applies commonly used global variables for the session // right before creating a transaction for the first time. func (s *session) loadCommonGlobalVariablesIfNeeded() error { vars := s.sessionVars if vars.CommonGlobalLoaded { return nil } if s.Value(context.Initing) != nil { // When running bootstrap or upgrade, we should not access global storage. return nil } // Set the variable to true to prevent cyclic recursive call. vars.CommonGlobalLoaded = true rs, err := s.ExecRestrictedSQL(s, loadCommonGlobalVarsSQL) if err != nil { vars.CommonGlobalLoaded = false log.Errorf("Failed to load common global variables.") return errors.Trace(err) } for { row, err1 := rs.Next() if err1 != nil { vars.CommonGlobalLoaded = false log.Errorf("Failed to load common global variables.") return errors.Trace(err1) } if row == nil { break } varName := row.Data[0].GetString() if d := varsutil.GetSystemVar(vars, varName); d.IsNull() { varsutil.SetSystemVar(s.sessionVars, varName, row.Data[1]) } } vars.CommonGlobalLoaded = true return nil }
func (e *ShowExec) fetchShowVariables() error { sessionVars := e.ctx.GetSessionVars() globalVars := sessionVars.GlobalVarsAccessor for _, v := range variable.SysVars { var err error var value string if !e.GlobalScope { // Try to get Session Scope variable value first. sv := varsutil.GetSystemVar(sessionVars, v.Name) if sv.IsNull() { value, err = globalVars.GetGlobalSysVar(v.Name) if err != nil { return errors.Trace(err) } sv.SetString(value) err = varsutil.SetSystemVar(sessionVars, v.Name, sv) if err != nil { return errors.Trace(err) } } value = sv.GetString() } else { value, err = globalVars.GetGlobalSysVar(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 dataForSessionVar(ctx context.Context) (records [][]types.Datum, err error) { sessionVars := ctx.GetSessionVars() globalVars := sessionVars.GlobalVarsAccessor for _, v := range variable.SysVars { var value string sv := varsutil.GetSystemVar(sessionVars, v.Name) if sv.IsNull() { value, err = globalVars.GetGlobalSysVar(v.Name) if err != nil { return nil, errors.Trace(err) } sv.SetString(value) err = varsutil.SetSystemVar(sessionVars, v.Name, sv) if err != nil { return nil, errors.Trace(err) } } value = sv.GetString() row := types.MakeDatums(v.Name, value) records = append(records, row) } return }
func (e *Evaluator) variable(v *ast.VariableExpr) bool { name := strings.ToLower(v.Name) sessionVars := e.ctx.GetSessionVars() globalVars := sessionVars.GlobalVarsAccessor 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.GenByArgs(name) return false } if sysVar.Scope == variable.ScopeNone { v.SetString(sysVar.Value) return true } if !v.IsGlobal { d := varsutil.GetSystemVar(sessionVars, 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(name) if err != nil { e.err = errors.Trace(err) return false } d.SetString(globalVal) err = varsutil.SetSystemVar(sessionVars, name, d) if err != nil { e.err = errors.Trace(err) return false } } } v.SetDatum(d) return true } value, err := globalVars.GetGlobalSysVar(name) if err != nil { e.err = errors.Trace(err) return false } v.SetString(value) return true }
func (e *SetExecutor) executeSet() error { sessionVars := e.ctx.GetSessionVars() for _, v := range e.vars { // Variable is case insensitive, we use lower case. if v.Name == ast.SetNames { // This is set charset stmt. cs := v.Expr.(*expression.Constant).Value.GetString() var co string if v.ExtendValue != nil { co = v.ExtendValue.Value.GetString() } 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 := v.Expr.Eval(nil, e.ctx) 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.GenByArgs(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 := e.getVarValue(v, sysVar) if err != nil { return errors.Trace(err) } if value.IsNull() { value.SetString("") } svalue, err := value.ToString() if err != nil { return errors.Trace(err) } err = sessionVars.GlobalVarsAccessor.SetGlobalSysVar(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 := e.getVarValue(v, nil) if err != nil { return errors.Trace(err) } err = varsutil.SetSystemVar(sessionVars, name, value) if err != nil { return errors.Trace(err) } e.loadSnapshotInfoSchemaIfNeeded(name) log.Infof("[%d] set system variable %s = %s", sessionVars.ConnectionID, name, value.GetString()) } } return nil }
func (er *expressionRewriter) rewriteVariable(v *ast.VariableExpr) { stkLen := len(er.ctxStack) name := strings.ToLower(v.Name) sessionVars := er.b.ctx.GetSessionVars() globalVars := sessionVars.GlobalVarsAccessor 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.GenByArgs(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(name) if err != nil { er.err = errors.Trace(err) return } er.ctxStack = append(er.ctxStack, datumToConstant(types.NewDatum(value), mysql.TypeString)) return } d := varsutil.GetSystemVar(sessionVars, 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(name) if err != nil { er.err = errors.Trace(err) return } d.SetString(globalVal) err = varsutil.SetSystemVar(sessionVars, name, d) if err != nil { er.err = errors.Trace(err) return } } } er.ctxStack = append(er.ctxStack, datumToConstant(d, mysql.TypeString)) return }
func (s *testEvaluatorSuite) TestGetTimeValue(c *C) { defer testleak.AfterTest(c)() v, err := GetTimeValue(nil, "2012-12-12 00:00:00", mysql.TypeTimestamp, types.MinFsp) c.Assert(err, IsNil) c.Assert(v.Kind(), Equals, types.KindMysqlTime) timeValue := v.GetMysqlTime() c.Assert(timeValue.String(), Equals, "2012-12-12 00:00:00") ctx := mock.NewContext() sessionVars := ctx.GetSessionVars() varsutil.SetSystemVar(sessionVars, "timestamp", types.NewStringDatum("")) v, err = GetTimeValue(ctx, "2012-12-12 00:00:00", mysql.TypeTimestamp, types.MinFsp) c.Assert(err, IsNil) c.Assert(v.Kind(), Equals, types.KindMysqlTime) timeValue = v.GetMysqlTime() c.Assert(timeValue.String(), Equals, "2012-12-12 00:00:00") varsutil.SetSystemVar(sessionVars, "timestamp", types.NewStringDatum("0")) v, err = GetTimeValue(ctx, "2012-12-12 00:00:00", mysql.TypeTimestamp, types.MinFsp) c.Assert(err, IsNil) c.Assert(v.Kind(), Equals, types.KindMysqlTime) timeValue = v.GetMysqlTime() c.Assert(timeValue.String(), Equals, "2012-12-12 00:00:00") varsutil.SetSystemVar(sessionVars, "timestamp", types.Datum{}) v, err = GetTimeValue(ctx, "2012-12-12 00:00:00", mysql.TypeTimestamp, types.MinFsp) c.Assert(err, IsNil) c.Assert(v.Kind(), Equals, types.KindMysqlTime) timeValue = v.GetMysqlTime() c.Assert(timeValue.String(), Equals, "2012-12-12 00:00:00") varsutil.SetSystemVar(sessionVars, "timestamp", types.NewStringDatum("1234")) tbl := []struct { Expr interface{} Ret interface{} }{ {"2012-12-12 00:00:00", "2012-12-12 00:00:00"}, {CurrentTimestamp, time.Unix(1234, 0).Format(types.TimeFormat)}, {ZeroTimestamp, "0000-00-00 00:00:00"}, {ast.NewValueExpr("2012-12-12 00:00:00"), "2012-12-12 00:00:00"}, {ast.NewValueExpr(int64(0)), "0000-00-00 00:00:00"}, {ast.NewValueExpr(nil), nil}, {&ast.FuncCallExpr{FnName: model.NewCIStr(CurrentTimestamp)}, CurrentTimestamp}, {&ast.UnaryOperationExpr{Op: opcode.Minus, V: ast.NewValueExpr(int64(0))}, "0000-00-00 00:00:00"}, } for i, t := range tbl { comment := Commentf("expr: %d", i) v, err := GetTimeValue(ctx, t.Expr, mysql.TypeTimestamp, types.MinFsp) c.Assert(err, IsNil) switch v.Kind() { case types.KindMysqlTime: c.Assert(v.GetMysqlTime().String(), DeepEquals, t.Ret, comment) default: c.Assert(v.GetValue(), DeepEquals, t.Ret, comment) } } errTbl := []struct { Expr interface{} }{ {"2012-13-12 00:00:00"}, {ast.NewValueExpr("2012-13-12 00:00:00")}, {ast.NewValueExpr(int64(1))}, {&ast.FuncCallExpr{FnName: model.NewCIStr("xxx")}}, {&ast.UnaryOperationExpr{Op: opcode.Minus, V: ast.NewValueExpr(int64(1))}}, } for _, t := range errTbl { _, err := GetTimeValue(ctx, t.Expr, mysql.TypeTimestamp, types.MinFsp) c.Assert(err, NotNil) } }