1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/hanchuanchuan-goInception

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Это зеркальный репозиторий, синхронизируется ежедневно с исходного репозитория.
Клонировать/Скачать
varsutil.go 13 КБ
Копировать Редактировать Исходные данные Просмотреть построчно История
hanchuanchuan Отправлено 6 лет назад 27f3c5a
// Copyright 2016 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 (
"encoding/json"
"fmt"
"math"
"strconv"
"strings"
"sync/atomic"
"time"
"github.com/hanchuanchuan/goInception/config"
"github.com/hanchuanchuan/goInception/mysql"
"github.com/hanchuanchuan/goInception/types"
"github.com/hanchuanchuan/goInception/util/timeutil"
"github.com/pingcap/errors"
)
// secondsPerYear represents seconds in a normal year. Leap year is not considered here.
const secondsPerYear = 60 * 60 * 24 * 365
// SetDDLReorgWorkerCounter sets ddlReorgWorkerCounter count.
// Max worker count is maxDDLReorgWorkerCount.
func SetDDLReorgWorkerCounter(cnt int32) {
if cnt > maxDDLReorgWorkerCount {
cnt = maxDDLReorgWorkerCount
}
atomic.StoreInt32(&ddlReorgWorkerCounter, cnt)
}
// GetDDLReorgWorkerCounter gets ddlReorgWorkerCounter.
func GetDDLReorgWorkerCounter() int32 {
return atomic.LoadInt32(&ddlReorgWorkerCounter)
}
// GetSessionSystemVar gets a system variable.
// If it is a session only variable, use the default value defined in code.
// Returns error if there is no such variable.
func GetSessionSystemVar(s *SessionVars, key string) (string, error) {
key = strings.ToLower(key)
gVal, ok, err := GetSessionOnlySysVars(s, key)
if err != nil || ok {
return gVal, errors.Trace(err)
}
gVal, err = s.GlobalVarsAccessor.GetGlobalSysVar(key)
if err != nil {
return "", errors.Trace(err)
}
s.systems[key] = gVal
return gVal, nil
}
// GetSessionOnlySysVars get the default value defined in code for session only variable.
// The return bool value indicates whether it's a session only variable.
func GetSessionOnlySysVars(s *SessionVars, key string) (string, bool, error) {
sysVar := SysVars[key]
if sysVar == nil {
return "", false, UnknownSystemVar.GenWithStackByArgs(key)
}
// For virtual system variables:
switch sysVar.Name {
case TiDBCurrentTS:
return fmt.Sprintf("%d", s.TxnCtx.StartTS), true, nil
case TiDBGeneralLog:
return fmt.Sprintf("%d", atomic.LoadUint32(&ProcessGeneralLog)), true, nil
case TiDBConfig:
conf := config.GetGlobalConfig()
j, err := json.MarshalIndent(conf, "", "\t")
if err != nil {
return "", false, errors.Trace(err)
}
return string(j), true, nil
case TiDBForcePriority:
return mysql.Priority2Str[mysql.PriorityEnum(atomic.LoadInt32(&ForcePriority))], true, nil
}
sVal, ok := s.systems[key]
if ok {
return sVal, true, nil
}
if sysVar.Scope&ScopeGlobal == 0 {
// None-Global variable can use pre-defined default value.
return sysVar.Value, true, nil
}
return "", false, nil
}
// GetGlobalSystemVar gets a global system variable.
func GetGlobalSystemVar(s *SessionVars, key string) (string, error) {
key = strings.ToLower(key)
gVal, ok, err := GetScopeNoneSystemVar(key)
if err != nil || ok {
return gVal, errors.Trace(err)
}
gVal, err = s.GlobalVarsAccessor.GetGlobalSysVar(key)
if err != nil {
return "", errors.Trace(err)
}
return gVal, nil
}
// GetScopeNoneSystemVar checks the validation of `key`,
// and return the default value if its scope is `ScopeNone`.
func GetScopeNoneSystemVar(key string) (string, bool, error) {
sysVar := SysVars[key]
if sysVar == nil {
return "", false, UnknownSystemVar.GenWithStackByArgs(key)
}
if sysVar.Scope == ScopeNone {
return sysVar.Value, true, nil
}
return "", false, nil
}
// epochShiftBits is used to reserve logical part of the timestamp.
const epochShiftBits = 18
// SetSessionSystemVar sets system variable and updates SessionVars states.
func SetSessionSystemVar(vars *SessionVars, name string, value types.Datum) error {
name = strings.ToLower(name)
sysVar := SysVars[name]
if sysVar == nil {
return UnknownSystemVar
}
sVal := ""
var err error
if !value.IsNull() {
sVal, err = value.ToString()
}
if err != nil {
return errors.Trace(err)
}
sVal, err = ValidateSetSystemVar(vars, name, sVal)
if err != nil {
return errors.Trace(err)
}
return vars.SetSystemVar(name, sVal)
}
// ValidateGetSystemVar checks if system variable exists and validates its scope when get system variable.
func ValidateGetSystemVar(name string, isGlobal bool) error {
sysVar, exists := SysVars[name]
if !exists {
return UnknownSystemVar.GenWithStackByArgs(name)
}
switch sysVar.Scope {
case ScopeGlobal, ScopeNone:
if !isGlobal {
return ErrIncorrectScope.GenWithStackByArgs(name, "GLOBAL")
}
case ScopeSession:
if isGlobal {
return ErrIncorrectScope.GenWithStackByArgs(name, "SESSION")
}
}
return nil
}
func checkUInt64SystemVar(name, value string, min, max uint64, vars *SessionVars) (string, error) {
if value[0] == '-' {
_, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
}
vars.StmtCtx.AppendWarning(ErrTruncatedWrongValue.GenWithStackByArgs(name, value))
return fmt.Sprintf("%d", min), nil
}
val, err := strconv.ParseUint(value, 10, 64)
if err != nil {
return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
}
if val < min {
vars.StmtCtx.AppendWarning(ErrTruncatedWrongValue.GenWithStackByArgs(name, value))
return fmt.Sprintf("%d", min), nil
}
if val > max {
vars.StmtCtx.AppendWarning(ErrTruncatedWrongValue.GenWithStackByArgs(name, value))
return fmt.Sprintf("%d", max), nil
}
return value, nil
}
func checkInt64SystemVar(name, value string, min, max int64, vars *SessionVars) (string, error) {
val, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
}
if val < min {
vars.StmtCtx.AppendWarning(ErrTruncatedWrongValue.GenWithStackByArgs(name, value))
return fmt.Sprintf("%d", min), nil
}
if val > max {
vars.StmtCtx.AppendWarning(ErrTruncatedWrongValue.GenWithStackByArgs(name, value))
return fmt.Sprintf("%d", max), nil
}
return value, nil
}
// ValidateSetSystemVar checks if system variable satisfies specific restriction.
func ValidateSetSystemVar(vars *SessionVars, name string, value string) (string, error) {
if strings.EqualFold(value, "DEFAULT") {
if val := GetSysVar(name); val != nil {
return val.Value, nil
}
return value, UnknownSystemVar.GenWithStackByArgs(name)
}
switch name {
case ConnectTimeout:
return checkUInt64SystemVar(name, value, 2, secondsPerYear, vars)
case DefaultWeekFormat:
return checkUInt64SystemVar(name, value, 0, 7, vars)
case DelayKeyWrite:
if strings.EqualFold(value, "ON") || value == "1" {
return "ON", nil
} else if strings.EqualFold(value, "OFF") || value == "0" {
return "OFF", nil
} else if strings.EqualFold(value, "ALL") || value == "2" {
return "ALL", nil
}
return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
case FlushTime:
return checkUInt64SystemVar(name, value, 0, secondsPerYear, vars)
case GroupConcatMaxLen:
// The reasonable range of 'group_concat_max_len' is 4~18446744073709551615(64-bit platforms)
// See https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_group_concat_max_len for details
return checkUInt64SystemVar(name, value, 4, math.MaxUint64, vars)
case InteractiveTimeout:
return checkUInt64SystemVar(name, value, 1, secondsPerYear, vars)
case InnodbCommitConcurrency:
return checkUInt64SystemVar(name, value, 0, 1000, vars)
case InnodbFastShutdown:
return checkUInt64SystemVar(name, value, 0, 2, vars)
case InnodbLockWaitTimeout:
return checkUInt64SystemVar(name, value, 1, 1073741824, vars)
case MaxConnections:
return checkUInt64SystemVar(name, value, 1, 100000, vars)
case MaxConnectErrors:
return checkUInt64SystemVar(name, value, 1, math.MaxUint64, vars)
case MaxSortLength:
return checkUInt64SystemVar(name, value, 4, 8388608, vars)
case MaxSpRecursionDepth:
return checkUInt64SystemVar(name, value, 0, 255, vars)
case MaxUserConnections:
return checkUInt64SystemVar(name, value, 0, 4294967295, vars)
case OldPasswords:
return checkUInt64SystemVar(name, value, 0, 2, vars)
case SessionTrackGtids:
if strings.EqualFold(value, "OFF") || value == "0" {
return "OFF", nil
} else if strings.EqualFold(value, "OWN_GTID") || value == "1" {
return "OWN_GTID", nil
} else if strings.EqualFold(value, "ALL_GTIDS") || value == "2" {
return "ALL_GTIDS", nil
}
return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
case SQLSelectLimit:
return checkUInt64SystemVar(name, value, 0, math.MaxUint64, vars)
case SyncBinlog:
return checkUInt64SystemVar(name, value, 0, 4294967295, vars)
case TableDefinitionCache:
return checkUInt64SystemVar(name, value, 400, 524288, vars)
case TmpTableSize:
return checkUInt64SystemVar(name, value, 1024, math.MaxUint64, vars)
case TimeZone:
if strings.EqualFold(value, "SYSTEM") {
return "SYSTEM", nil
}
return value, nil
case WarningCount, ErrorCount:
return value, ErrReadOnly.GenWithStackByArgs(name)
case GeneralLog, TiDBGeneralLog, AvoidTemporalUpgrade, BigTables, CheckProxyUsers, CoreFile, EndMakersInJSON, SQLLogBin, OfflineMode,
PseudoSlaveMode, LowPriorityUpdates, SkipNameResolve, ForeignKeyChecks, SQLSafeUpdates, TiDBConstraintCheckInPlace:
if strings.EqualFold(value, "ON") || value == "1" {
return "1", nil
} else if strings.EqualFold(value, "OFF") || value == "0" {
return "0", nil
}
return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
case AutocommitVar, TiDBSkipUTF8Check, TiDBOptAggPushDown,
TiDBOptInSubqUnFolding, TiDBEnableTablePartition,
TiDBBatchInsert, TiDBDisableTxnAutoRetry, TiDBEnableStreaming,
TiDBBatchDelete, TiDBEnableCascadesPlanner:
if strings.EqualFold(value, "ON") || value == "1" || strings.EqualFold(value, "OFF") || value == "0" {
return value, nil
}
return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
case TiDBIndexLookupConcurrency, TiDBIndexLookupJoinConcurrency, TiDBIndexJoinBatchSize,
TiDBIndexLookupSize,
TiDBHashJoinConcurrency,
TiDBHashAggPartialConcurrency,
TiDBHashAggFinalConcurrency,
TiDBDistSQLScanConcurrency,
TiDBIndexSerialScanConcurrency, TiDBDDLReorgWorkerCount,
TiDBBackoffLockFast, TiDBMaxChunkSize,
TiDBDMLBatchSize, TiDBOptimizerSelectivityLevel:
v, err := strconv.Atoi(value)
if err != nil {
return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
}
if v <= 0 {
return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
}
return value, nil
case TiDBProjectionConcurrency,
TIDBMemQuotaQuery,
TIDBMemQuotaHashJoin,
TIDBMemQuotaMergeJoin,
TIDBMemQuotaSort,
TIDBMemQuotaTopn,
TIDBMemQuotaIndexLookupReader,
TIDBMemQuotaIndexLookupJoin,
TIDBMemQuotaNestedLoopApply,
TiDBRetryLimit:
_, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return value, ErrWrongValueForVar.GenWithStackByArgs(name)
}
return value, nil
case TiDBAutoAnalyzeStartTime, TiDBAutoAnalyzeEndTime:
v, err := setAnalyzeTime(vars, value)
if err != nil {
return "", errors.Trace(err)
}
return v, nil
}
return value, nil
}
// TiDBOptOn could be used for all tidb session variable options, we use "ON"/1 to turn on those options.
func TiDBOptOn(opt string) bool {
return strings.EqualFold(opt, "ON") || opt == "1"
}
func tidbOptPositiveInt32(opt string, defaultVal int) int {
val, err := strconv.Atoi(opt)
if err != nil || val <= 0 {
return defaultVal
}
return val
}
func tidbOptInt64(opt string, defaultVal int64) int64 {
val, err := strconv.ParseInt(opt, 10, 64)
if err != nil {
return defaultVal
}
return val
}
func parseTimeZone(s string) (*time.Location, error) {
if strings.EqualFold(s, "SYSTEM") {
return timeutil.SystemLocation(), nil
}
loc, err := time.LoadLocation(s)
if err == nil {
return loc, nil
}
// The value can be given as a string indicating an offset from UTC, such as '+10:00' or '-6:00'.
if strings.HasPrefix(s, "+") || strings.HasPrefix(s, "-") {
d, err := types.ParseDuration(nil, s[1:], 0)
if err == nil {
ofst := int(d.Duration / time.Second)
if s[0] == '-' {
ofst = -ofst
}
return time.FixedZone("", ofst), nil
}
}
return nil, ErrUnknownTimeZone.GenWithStackByArgs(s)
}
func setSnapshotTS(s *SessionVars, sVal string) error {
if sVal == "" {
s.SnapshotTS = 0
return nil
}
if tso, err := strconv.ParseUint(sVal, 10, 64); err == nil {
s.SnapshotTS = tso
return nil
}
t, err := types.ParseTime(s.StmtCtx, sVal, mysql.TypeTimestamp, types.MaxFsp)
if err != nil {
return errors.Trace(err)
}
// TODO: Consider time_zone variable.
t1, err := t.Time.GoTime(time.Local)
s.SnapshotTS = GoTimeToTS(t1)
return errors.Trace(err)
}
// GoTimeToTS converts a Go time to uint64 timestamp.
func GoTimeToTS(t time.Time) uint64 {
ts := (t.UnixNano() / int64(time.Millisecond)) << epochShiftBits
return uint64(ts)
}
const (
analyzeLocalTimeFormat = "15:04"
// AnalyzeFullTimeFormat is the full format of analyze start time and end time.
AnalyzeFullTimeFormat = "15:04 -0700"
)
func setAnalyzeTime(s *SessionVars, val string) (string, error) {
var t time.Time
var err error
if len(val) <= len(analyzeLocalTimeFormat) {
t, err = time.ParseInLocation(analyzeLocalTimeFormat, val, s.TimeZone)
} else {
t, err = time.ParseInLocation(AnalyzeFullTimeFormat, val, s.TimeZone)
}
if err != nil {
return "", errors.Trace(err)
}
return t.Format(AnalyzeFullTimeFormat), nil
}

Комментарий ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/hanchuanchuan-goInception.git
git@gitlife.ru:oschina-mirror/hanchuanchuan-goInception.git
oschina-mirror
hanchuanchuan-goInception
hanchuanchuan-goInception
v1.3.0