예제 #1
0
파일: variable.go 프로젝트: lovedboy/tidb
// 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
}
예제 #2
0
파일: show.go 프로젝트: jmptrader/tidb
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
}
예제 #3
0
파일: show.go 프로젝트: astaxie/tidb
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
}
예제 #4
0
파일: show.go 프로젝트: kellerli/tidb
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
}
예제 #5
0
파일: show.go 프로젝트: huozhe3136/tidb
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
}
예제 #6
0
파일: evaluator.go 프로젝트: astaxie/tidb
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
}
예제 #7
0
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
}
예제 #8
0
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
}
예제 #9
0
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
}
예제 #10
0
파일: set.go 프로젝트: lovedboy/tidb
// 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
}
예제 #11
0
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
}
예제 #12
0
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
}