github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/stochastikctx/variable/varsutil.go (about)

     1  // Copyright 2020 WHTCORPS INC, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package variable
    15  
    16  import (
    17  	"encoding/json"
    18  	"fmt"
    19  	"math"
    20  	"strconv"
    21  	"strings"
    22  	"sync"
    23  	"sync/atomic"
    24  	"time"
    25  
    26  	"github.com/cznic/mathutil"
    27  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    28  	"github.com/whtcorpsinc/BerolinaSQL/ast"
    29  	"github.com/whtcorpsinc/errors"
    30  	"github.com/whtcorpsinc/milevadb/config"
    31  	"github.com/whtcorpsinc/milevadb/ekv"
    32  	"github.com/whtcorpsinc/milevadb/soliton/defCauslate"
    33  	"github.com/whtcorpsinc/milevadb/soliton/timeutil"
    34  	"github.com/whtcorpsinc/milevadb/types"
    35  )
    36  
    37  // secondsPerYear represents seconds in a normal year. Leap year is not considered here.
    38  const secondsPerYear = 60 * 60 * 24 * 365
    39  
    40  // SetDBSReorgWorkerCounter sets dbsReorgWorkerCounter count.
    41  // Max worker count is maxDBSReorgWorkerCount.
    42  func SetDBSReorgWorkerCounter(cnt int32) {
    43  	if cnt > maxDBSReorgWorkerCount {
    44  		cnt = maxDBSReorgWorkerCount
    45  	}
    46  	atomic.StoreInt32(&dbsReorgWorkerCounter, cnt)
    47  }
    48  
    49  // GetDBSReorgWorkerCounter gets dbsReorgWorkerCounter.
    50  func GetDBSReorgWorkerCounter() int32 {
    51  	return atomic.LoadInt32(&dbsReorgWorkerCounter)
    52  }
    53  
    54  // SetDBSReorgBatchSize sets dbsReorgBatchSize size.
    55  // Max batch size is MaxDBSReorgBatchSize.
    56  func SetDBSReorgBatchSize(cnt int32) {
    57  	if cnt > MaxDBSReorgBatchSize {
    58  		cnt = MaxDBSReorgBatchSize
    59  	}
    60  	if cnt < MinDBSReorgBatchSize {
    61  		cnt = MinDBSReorgBatchSize
    62  	}
    63  	atomic.StoreInt32(&dbsReorgBatchSize, cnt)
    64  }
    65  
    66  // GetDBSReorgBatchSize gets dbsReorgBatchSize.
    67  func GetDBSReorgBatchSize() int32 {
    68  	return atomic.LoadInt32(&dbsReorgBatchSize)
    69  }
    70  
    71  // SetDBSErrorCountLimit sets dbsErrorCountlimit size.
    72  func SetDBSErrorCountLimit(cnt int64) {
    73  	atomic.StoreInt64(&dbsErrorCountlimit, cnt)
    74  }
    75  
    76  // GetDBSErrorCountLimit gets dbsErrorCountlimit size.
    77  func GetDBSErrorCountLimit() int64 {
    78  	return atomic.LoadInt64(&dbsErrorCountlimit)
    79  }
    80  
    81  // SetMaxDeltaSchemaCount sets maxDeltaSchemaCount size.
    82  func SetMaxDeltaSchemaCount(cnt int64) {
    83  	atomic.StoreInt64(&maxDeltaSchemaCount, cnt)
    84  }
    85  
    86  // GetMaxDeltaSchemaCount gets maxDeltaSchemaCount size.
    87  func GetMaxDeltaSchemaCount() int64 {
    88  	return atomic.LoadInt64(&maxDeltaSchemaCount)
    89  }
    90  
    91  // GetStochastikSystemVar gets a system variable.
    92  // If it is a stochastik only variable, use the default value defined in code.
    93  // Returns error if there is no such variable.
    94  func GetStochastikSystemVar(s *StochastikVars, key string) (string, error) {
    95  	key = strings.ToLower(key)
    96  	gVal, ok, err := GetStochastikOnlySysVars(s, key)
    97  	if err != nil || ok {
    98  		return gVal, err
    99  	}
   100  	gVal, err = s.GlobalVarsAccessor.GetGlobalSysVar(key)
   101  	if err != nil {
   102  		return "", err
   103  	}
   104  	s.systems[key] = gVal
   105  	return gVal, nil
   106  }
   107  
   108  // GetStochastikOnlySysVars get the default value defined in code for stochastik only variable.
   109  // The return bool value indicates whether it's a stochastik only variable.
   110  func GetStochastikOnlySysVars(s *StochastikVars, key string) (string, bool, error) {
   111  	sysVar := SysVars[key]
   112  	if sysVar == nil {
   113  		return "", false, ErrUnknownSystemVar.GenWithStackByArgs(key)
   114  	}
   115  	// For virtual system variables:
   116  	switch sysVar.Name {
   117  	case MilevaDBCurrentTS:
   118  		return fmt.Sprintf("%d", s.TxnCtx.StartTS), true, nil
   119  	case MilevaDBLastTxnInfo:
   120  		info, err := json.Marshal(s.LastTxnInfo)
   121  		if err != nil {
   122  			return "", true, err
   123  		}
   124  		return string(info), true, nil
   125  	case MilevaDBGeneralLog:
   126  		return fmt.Sprintf("%d", atomic.LoadUint32(&ProcessGeneralLog)), true, nil
   127  	case MilevaDBPProfALLEGROSQLCPU:
   128  		val := "0"
   129  		if EnablePProfALLEGROSQLCPU.Load() {
   130  			val = "1"
   131  		}
   132  		return val, true, nil
   133  	case MilevaDBExpensiveQueryTimeThreshold:
   134  		return fmt.Sprintf("%d", atomic.LoadUint64(&ExpensiveQueryTimeThreshold)), true, nil
   135  	case MilevaDBConfig:
   136  		conf := config.GetGlobalConfig()
   137  		j, err := json.MarshalIndent(conf, "", "\t")
   138  		if err != nil {
   139  			return "", false, err
   140  		}
   141  		return string(j), true, nil
   142  	case MilevaDBForcePriority:
   143  		return allegrosql.Priority2Str[allegrosql.PriorityEnum(atomic.LoadInt32(&ForcePriority))], true, nil
   144  	case MilevaDBDBSSlowOprThreshold:
   145  		return strconv.FormatUint(uint64(atomic.LoadUint32(&DBSSlowOprThreshold)), 10), true, nil
   146  	case PluginDir:
   147  		return config.GetGlobalConfig().Plugin.Dir, true, nil
   148  	case PluginLoad:
   149  		return config.GetGlobalConfig().Plugin.Load, true, nil
   150  	case MilevaDBSlowLogThreshold:
   151  		return strconv.FormatUint(atomic.LoadUint64(&config.GetGlobalConfig().Log.SlowThreshold), 10), true, nil
   152  	case MilevaDBRecordCausetInSlowLog:
   153  		return strconv.FormatUint(uint64(atomic.LoadUint32(&config.GetGlobalConfig().Log.RecordCausetInSlowLog)), 10), true, nil
   154  	case MilevaDBEnableSlowLog:
   155  		return BoolToIntStr(config.GetGlobalConfig().Log.EnableSlowLog), true, nil
   156  	case MilevaDBQueryLogMaxLen:
   157  		return strconv.FormatUint(atomic.LoadUint64(&config.GetGlobalConfig().Log.QueryLogMaxLen), 10), true, nil
   158  	case MilevaDBCheckMb4ValueInUTF8:
   159  		return BoolToIntStr(config.GetGlobalConfig().CheckMb4ValueInUTF8), true, nil
   160  	case MilevaDBCaptureCausetBaseline:
   161  		return CaptureCausetBaseline.GetVal(), true, nil
   162  	case MilevaDBFoundInCausetCache:
   163  		return BoolToIntStr(s.PrevFoundInCausetCache), true, nil
   164  	case MilevaDBEnableDefCauslectInterDircutionInfo:
   165  		return BoolToIntStr(config.GetGlobalConfig().EnableDefCauslectInterDircutionInfo), true, nil
   166  	}
   167  	sVal, ok := s.GetSystemVar(key)
   168  	if ok {
   169  		return sVal, true, nil
   170  	}
   171  	if sysVar.Scope&ScopeGlobal == 0 {
   172  		// None-Global variable can use pre-defined default value.
   173  		return sysVar.Value, true, nil
   174  	}
   175  	return "", false, nil
   176  }
   177  
   178  // GetGlobalSystemVar gets a global system variable.
   179  func GetGlobalSystemVar(s *StochastikVars, key string) (string, error) {
   180  	key = strings.ToLower(key)
   181  	gVal, ok, err := GetScopeNoneSystemVar(key)
   182  	if err != nil || ok {
   183  		return gVal, err
   184  	}
   185  	gVal, err = s.GlobalVarsAccessor.GetGlobalSysVar(key)
   186  	if err != nil {
   187  		return "", err
   188  	}
   189  	return gVal, nil
   190  }
   191  
   192  // GetScopeNoneSystemVar checks the validation of `key`,
   193  // and return the default value if its scope is `ScopeNone`.
   194  func GetScopeNoneSystemVar(key string) (string, bool, error) {
   195  	sysVar := SysVars[key]
   196  	if sysVar == nil {
   197  		return "", false, ErrUnknownSystemVar.GenWithStackByArgs(key)
   198  	}
   199  	if sysVar.Scope == ScopeNone {
   200  		return sysVar.Value, true, nil
   201  	}
   202  	return "", false, nil
   203  }
   204  
   205  // epochShiftBits is used to reserve logical part of the timestamp.
   206  const epochShiftBits = 18
   207  
   208  // SetStochastikSystemVar sets system variable and uFIDelates StochastikVars states.
   209  func SetStochastikSystemVar(vars *StochastikVars, name string, value types.Causet) error {
   210  	name = strings.ToLower(name)
   211  	sysVar := SysVars[name]
   212  	if sysVar == nil {
   213  		return ErrUnknownSystemVar
   214  	}
   215  	sVal := ""
   216  	var err error
   217  	if !value.IsNull() {
   218  		sVal, err = value.ToString()
   219  	}
   220  	if err != nil {
   221  		return err
   222  	}
   223  	sVal, err = ValidateSetSystemVar(vars, name, sVal, ScopeStochastik)
   224  	if err != nil {
   225  		return err
   226  	}
   227  	CheckDeprecationSetSystemVar(vars, name)
   228  	return vars.SetSystemVar(name, sVal)
   229  }
   230  
   231  // ValidateGetSystemVar checks if system variable exists and validates its scope when get system variable.
   232  func ValidateGetSystemVar(name string, isGlobal bool) error {
   233  	sysVar, exists := SysVars[name]
   234  	if !exists {
   235  		return ErrUnknownSystemVar.GenWithStackByArgs(name)
   236  	}
   237  	switch sysVar.Scope {
   238  	case ScopeGlobal:
   239  		if !isGlobal {
   240  			return ErrIncorrectScope.GenWithStackByArgs(name, "GLOBAL")
   241  		}
   242  	case ScopeStochastik:
   243  		if isGlobal {
   244  			return ErrIncorrectScope.GenWithStackByArgs(name, "SESSION")
   245  		}
   246  	}
   247  	return nil
   248  }
   249  
   250  func checkUInt64SystemVar(name, value string, min, max uint64, vars *StochastikVars) (string, error) {
   251  	if len(value) == 0 {
   252  		return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
   253  	}
   254  	if value[0] == '-' {
   255  		_, err := strconv.ParseInt(value, 10, 64)
   256  		if err != nil {
   257  			return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
   258  		}
   259  		vars.StmtCtx.AppendWarning(ErrTruncatedWrongValue.GenWithStackByArgs(name, value))
   260  		return fmt.Sprintf("%d", min), nil
   261  	}
   262  	val, err := strconv.ParseUint(value, 10, 64)
   263  	if err != nil {
   264  		return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
   265  	}
   266  	if val < min {
   267  		vars.StmtCtx.AppendWarning(ErrTruncatedWrongValue.GenWithStackByArgs(name, value))
   268  		return fmt.Sprintf("%d", min), nil
   269  	}
   270  	if val > max {
   271  		vars.StmtCtx.AppendWarning(ErrTruncatedWrongValue.GenWithStackByArgs(name, value))
   272  		return fmt.Sprintf("%d", max), nil
   273  	}
   274  	return value, nil
   275  }
   276  
   277  func checkInt64SystemVar(name, value string, min, max int64, vars *StochastikVars) (string, error) {
   278  	val, err := strconv.ParseInt(value, 10, 64)
   279  	if err != nil {
   280  		return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
   281  	}
   282  	if val < min {
   283  		vars.StmtCtx.AppendWarning(ErrTruncatedWrongValue.GenWithStackByArgs(name, value))
   284  		return fmt.Sprintf("%d", min), nil
   285  	}
   286  	if val > max {
   287  		vars.StmtCtx.AppendWarning(ErrTruncatedWrongValue.GenWithStackByArgs(name, value))
   288  		return fmt.Sprintf("%d", max), nil
   289  	}
   290  	return value, nil
   291  }
   292  
   293  func checkInt64SystemVarWithError(name, value string, min, max int64) (string, error) {
   294  	val, err := strconv.ParseInt(value, 10, 64)
   295  	if err != nil {
   296  		return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
   297  	}
   298  	if val < min || val > max {
   299  		return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   300  	}
   301  	return value, nil
   302  }
   303  
   304  const (
   305  	// initChunkSizeUpperBound indicates upper bound value of milevadb_init_chunk_size.
   306  	initChunkSizeUpperBound = 32
   307  	// maxChunkSizeLowerBound indicates lower bound value of milevadb_max_chunk_size.
   308  	maxChunkSizeLowerBound = 32
   309  )
   310  
   311  // CheckDeprecationSetSystemVar checks if the system variable is deprecated.
   312  func CheckDeprecationSetSystemVar(s *StochastikVars, name string) {
   313  	switch name {
   314  	case MilevaDBIndexLookupConcurrency, MilevaDBIndexLookupJoinConcurrency,
   315  		MilevaDBHashJoinConcurrency, MilevaDBHashAggPartialConcurrency, MilevaDBHashAggFinalConcurrency,
   316  		MilevaDBProjectionConcurrency, MilevaDBWindowConcurrency:
   317  		s.StmtCtx.AppendWarning(errWarnDeprecatedSyntax.FastGenByArgs(name, MilevaDBInterlockingDirectorateConcurrency))
   318  	case MilevaDBMemQuotaHashJoin, MilevaDBMemQuotaMergeJoin,
   319  		MilevaDBMemQuotaSort, MilevaDBMemQuotaTopn,
   320  		MilevaDBMemQuotaIndexLookupReader, MilevaDBMemQuotaIndexLookupJoin,
   321  		MilevaDBMemQuotaNestedLoopApply:
   322  		s.StmtCtx.AppendWarning(errWarnDeprecatedSyntax.FastGenByArgs(name, MilevaDBMemQuotaQuery))
   323  	}
   324  }
   325  
   326  // ValidateSetSystemVar checks if system variable satisfies specific restriction.
   327  func ValidateSetSystemVar(vars *StochastikVars, name string, value string, scope ScopeFlag) (string, error) {
   328  	if strings.EqualFold(value, "DEFAULT") {
   329  		if val := GetSysVar(name); val != nil {
   330  			return val.Value, nil
   331  		}
   332  		return value, ErrUnknownSystemVar.GenWithStackByArgs(name)
   333  	}
   334  	switch name {
   335  	case ConnectTimeout:
   336  		return checkUInt64SystemVar(name, value, 2, secondsPerYear, vars)
   337  	case DefaultWeekFormat:
   338  		return checkUInt64SystemVar(name, value, 0, 7, vars)
   339  	case DelayKeyWrite:
   340  		if strings.EqualFold(value, "ON") || value == "1" {
   341  			return "ON", nil
   342  		} else if strings.EqualFold(value, "OFF") || value == "0" {
   343  			return "OFF", nil
   344  		} else if strings.EqualFold(value, "ALL") || value == "2" {
   345  			return "ALL", nil
   346  		}
   347  		return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   348  	case FlushTime:
   349  		return checkUInt64SystemVar(name, value, 0, secondsPerYear, vars)
   350  	case ForeignKeyChecks:
   351  		if strings.EqualFold(value, "ON") || value == "1" {
   352  			// MilevaDB does not yet support foreign keys.
   353  			// For now, resist the change and show a warning.
   354  			vars.StmtCtx.AppendWarning(ErrUnsupportedValueForVar.GenWithStackByArgs(name, value))
   355  			return "OFF", nil
   356  		} else if strings.EqualFold(value, "OFF") || value == "0" {
   357  			return "OFF", nil
   358  		}
   359  		return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   360  	case GroupConcatMaxLen:
   361  		// https://dev.allegrosql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_group_concat_max_len
   362  		// Minimum Value 4
   363  		// Maximum Value (64-bit platforms) 18446744073709551615
   364  		// Maximum Value (32-bit platforms) 4294967295
   365  		maxLen := uint64(math.MaxUint64)
   366  		if mathutil.IntBits == 32 {
   367  			maxLen = uint64(math.MaxUint32)
   368  		}
   369  		return checkUInt64SystemVar(name, value, 4, maxLen, vars)
   370  	case InteractiveTimeout:
   371  		return checkUInt64SystemVar(name, value, 1, secondsPerYear, vars)
   372  	case InnodbCommitConcurrency:
   373  		return checkUInt64SystemVar(name, value, 0, 1000, vars)
   374  	case InnodbFastShutdown:
   375  		return checkUInt64SystemVar(name, value, 0, 2, vars)
   376  	case InnodbLockWaitTimeout:
   377  		return checkUInt64SystemVar(name, value, 1, 1073741824, vars)
   378  	// See "https://dev.allegrosql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_max_allowed_packet"
   379  	case MaxAllowedPacket:
   380  		return checkUInt64SystemVar(name, value, 1024, MaxOfMaxAllowedPacket, vars)
   381  	case MaxConnections:
   382  		return checkUInt64SystemVar(name, value, 1, 100000, vars)
   383  	case MaxConnectErrors:
   384  		return checkUInt64SystemVar(name, value, 1, math.MaxUint64, vars)
   385  	case MaxSortLength:
   386  		return checkUInt64SystemVar(name, value, 4, 8388608, vars)
   387  	case MaxSpRecursionDepth:
   388  		return checkUInt64SystemVar(name, value, 0, 255, vars)
   389  	case MaxUserConnections:
   390  		return checkUInt64SystemVar(name, value, 0, 4294967295, vars)
   391  	case OldPasswords:
   392  		return checkUInt64SystemVar(name, value, 0, 2, vars)
   393  	case MilevaDBMaxDeltaSchemaCount:
   394  		return checkInt64SystemVar(name, value, 100, 16384, vars)
   395  	case StochastikTrackGtids:
   396  		if strings.EqualFold(value, "OFF") || value == "0" {
   397  			return "OFF", nil
   398  		} else if strings.EqualFold(value, "OWN_GTID") || value == "1" {
   399  			return "OWN_GTID", nil
   400  		} else if strings.EqualFold(value, "ALL_GTIDS") || value == "2" {
   401  			return "ALL_GTIDS", nil
   402  		}
   403  		return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   404  	case ALLEGROSQLSelectLimit:
   405  		return checkUInt64SystemVar(name, value, 0, math.MaxUint64, vars)
   406  	case MilevaDBStoreLimit:
   407  		return checkInt64SystemVar(name, value, 0, math.MaxInt64, vars)
   408  	case SyncBinlog:
   409  		return checkUInt64SystemVar(name, value, 0, 4294967295, vars)
   410  	case BlockDefinitionCache:
   411  		return checkUInt64SystemVar(name, value, 400, 524288, vars)
   412  	case TmpBlockSize:
   413  		return checkUInt64SystemVar(name, value, 1024, math.MaxUint64, vars)
   414  	case WaitTimeout:
   415  		return checkUInt64SystemVar(name, value, 0, 31536000, vars)
   416  	case MaxPreparedStmtCount:
   417  		return checkInt64SystemVar(name, value, -1, 1048576, vars)
   418  	case AutoIncrementIncrement, AutoIncrementOffset:
   419  		return checkUInt64SystemVar(name, value, 1, math.MaxUint16, vars)
   420  	case TimeZone:
   421  		if strings.EqualFold(value, "SYSTEM") {
   422  			return "SYSTEM", nil
   423  		}
   424  		_, err := parseTimeZone(value)
   425  		return value, err
   426  	case ValidatePasswordLength, ValidatePasswordNumberCount:
   427  		return checkUInt64SystemVar(name, value, 0, math.MaxUint64, vars)
   428  	case WarningCount, ErrorCount:
   429  		return value, ErrReadOnly.GenWithStackByArgs(name)
   430  	case EnforceGtidConsistency:
   431  		if strings.EqualFold(value, "OFF") || value == "0" {
   432  			return "OFF", nil
   433  		} else if strings.EqualFold(value, "ON") || value == "1" {
   434  			return "ON", nil
   435  		} else if strings.EqualFold(value, "WARN") || value == "2" {
   436  			return "WARN", nil
   437  		}
   438  		return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   439  	case QueryCacheType:
   440  		if strings.EqualFold(value, "OFF") || value == "0" {
   441  			return "OFF", nil
   442  		} else if strings.EqualFold(value, "ON") || value == "1" {
   443  			return "ON", nil
   444  		} else if strings.EqualFold(value, "DEMAND") || value == "2" {
   445  			return "DEMAND", nil
   446  		}
   447  		return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   448  	case SecureAuth:
   449  		if strings.EqualFold(value, "ON") || value == "1" {
   450  			return "1", nil
   451  		}
   452  		return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   453  	case WindowingUseHighPrecision:
   454  		if strings.EqualFold(value, "OFF") || value == "0" {
   455  			return "OFF", nil
   456  		} else if strings.EqualFold(value, "ON") || value == "1" {
   457  			return "ON", nil
   458  		}
   459  		return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   460  	case MilevaDBOptBCJ:
   461  		if (strings.EqualFold(value, "ON") || value == "1") && vars.AllowBatchCop == 0 {
   462  			return value, ErrWrongValueForVar.GenWithStackByArgs("Can't set Broadcast Join to 1 but milevadb_allow_batch_cop is 0, please active batch cop at first.")
   463  		}
   464  		return value, nil
   465  	case MilevaDBSkipUTF8Check, MilevaDBSkipASCIICheck, MilevaDBOptAggPushDown,
   466  		MilevaDBOptDistinctAggPushDown, MilevaDBOptInSubqToJoinAnPosetDagg, MilevaDBEnableFastAnalyze,
   467  		MilevaDBBatchInsert, MilevaDBDisableTxnAutoRetry, MilevaDBEnableStreaming, MilevaDBEnableChunkRPC,
   468  		MilevaDBBatchDelete, MilevaDBBatchCommit, MilevaDBEnableCascadesCausetAppend, MilevaDBEnableWindowFunction, MilevaDBPProfALLEGROSQLCPU,
   469  		MilevaDBLowResolutionTSO, MilevaDBEnableIndexMerge, MilevaDBEnableNoopFuncs,
   470  		MilevaDBCheckMb4ValueInUTF8, MilevaDBEnableSlowLog, MilevaDBRecordCausetInSlowLog,
   471  		MilevaDBScatterRegion, MilevaDBGeneralLog, MilevaDBConstraintCheckInPlace, MilevaDBEnableVectorizedExpression,
   472  		MilevaDBFoundInCausetCache, MilevaDBEnableDefCauslectInterDircutionInfo, MilevaDBAllowAutoRandExplicitInsert,
   473  		MilevaDBEnableClusteredIndex, MilevaDBEnableTelemetry, MilevaDBEnableChangeDeferredCausetType, MilevaDBEnableAmendPessimisticTxn:
   474  		fallthrough
   475  	case GeneralLog, AvoidTemporalUpgrade, BigBlocks, CheckProxyUsers, LogBin,
   476  		CoreFile, EndMakersInJSON, ALLEGROSQLLogBin, OfflineMode, PseudoSlaveMode, LowPriorityUFIDelates,
   477  		SkipNameResolve, ALLEGROSQLSafeUFIDelates, serverReadOnly, SlaveAllowBatching,
   478  		Flush, PerformanceSchema, LocalInFile, ShowOldTemporals, KeepFilesOnCreate, AutoCommit,
   479  		ALLEGROSQLWarnings, UniqueChecks, OldAlterBlock, LogBinTrustFunctionCreators, ALLEGROSQLBigSelects,
   480  		BinlogDirectNonTransactionalUFIDelates, ALLEGROSQLQuoteShowCreate, AutomaticSpPrivileges,
   481  		RelayLogPurge, ALLEGROSQLAutoIsNull, QueryCacheWlockInvalidate, ValidatePasswordCheckUserName,
   482  		SuperReadOnly, BinlogOrderCommits, MasterVerifyChecksum, BinlogRowQueryLogEvents, LogSlowSlaveStatements,
   483  		LogSlowAdminStatements, LogQueriesNotUsingIndexes, Profiling:
   484  		if strings.EqualFold(value, "ON") {
   485  			return "1", nil
   486  		} else if strings.EqualFold(value, "OFF") {
   487  			return "0", nil
   488  		}
   489  		val, err := strconv.ParseInt(value, 10, 64)
   490  		if err == nil {
   491  			if val == 0 {
   492  				return "0", nil
   493  			} else if val == 1 {
   494  				return "1", nil
   495  			}
   496  		}
   497  		return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   498  	case MyISAMUseMmap, InnodbBlockLocks, InnodbStatusOutput, InnodbAdaptiveFlushing, InnodbRandomReadAhead,
   499  		InnodbStatsPersistent, InnodbBufferPoolLoadAbort, InnodbBufferPoolLoadNow, InnodbBufferPoolDumpNow,
   500  		InnodbCmpPerIndexEnabled, InnodbFilePerBlock, InnodbPrintAllDeadlocks,
   501  		InnodbStrictMode, InnodbAdaptiveHashIndex, InnodbFtEnableStopword, InnodbStatusOutputLocks:
   502  		if strings.EqualFold(value, "ON") {
   503  			return "1", nil
   504  		} else if strings.EqualFold(value, "OFF") {
   505  			return "0", nil
   506  		}
   507  		val, err := strconv.ParseInt(value, 10, 64)
   508  		if err == nil {
   509  			if val == 1 || val < 0 {
   510  				return "1", nil
   511  			} else if val == 0 {
   512  				return "0", nil
   513  			}
   514  		}
   515  		return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   516  	case MaxInterDircutionTime:
   517  		return checkUInt64SystemVar(name, value, 0, math.MaxUint64, vars)
   518  	case ThreadPoolSize:
   519  		return checkUInt64SystemVar(name, value, 1, 64, vars)
   520  	case MilevaDBEnableBlockPartition:
   521  		switch {
   522  		case strings.EqualFold(value, "ON") || value == "1":
   523  			return "on", nil
   524  		case strings.EqualFold(value, "OFF") || value == "0":
   525  			return "off", nil
   526  		case strings.EqualFold(value, "AUTO"):
   527  			return "auto", nil
   528  		}
   529  		return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   530  	case MilevaDBDBSReorgBatchSize:
   531  		return checkUInt64SystemVar(name, value, uint64(MinDBSReorgBatchSize), uint64(MaxDBSReorgBatchSize), vars)
   532  	case MilevaDBDBSErrorCountLimit:
   533  		return checkUInt64SystemVar(name, value, uint64(0), math.MaxInt64, vars)
   534  	case MilevaDBExpensiveQueryTimeThreshold:
   535  		return checkUInt64SystemVar(name, value, MinExpensiveQueryTimeThreshold, math.MaxInt64, vars)
   536  	case MilevaDBIndexLookupConcurrency,
   537  		MilevaDBIndexLookupJoinConcurrency,
   538  		MilevaDBHashJoinConcurrency,
   539  		MilevaDBHashAggPartialConcurrency,
   540  		MilevaDBHashAggFinalConcurrency,
   541  		MilevaDBWindowConcurrency:
   542  		v, err := strconv.Atoi(value)
   543  		if err != nil {
   544  			return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
   545  		}
   546  		if v <= 0 && v != ConcurrencyUnset {
   547  			return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   548  		}
   549  		return value, nil
   550  	case MilevaDBInterlockingDirectorateConcurrency,
   551  		MilevaDBDistALLEGROSQLScanConcurrency,
   552  		MilevaDBIndexSerialScanConcurrency,
   553  		MilevaDBIndexJoinBatchSize,
   554  		MilevaDBIndexLookupSize,
   555  		MilevaDBDBSReorgWorkerCount,
   556  		MilevaDBBackoffLockFast, MilevaDBBackOffWeight,
   557  		MilevaDBOptimizerSelectivityLevel:
   558  		v, err := strconv.Atoi(value)
   559  		if err != nil {
   560  			return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
   561  		}
   562  		if v <= 0 {
   563  			return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   564  		}
   565  		return value, nil
   566  	case MilevaDBOptCorrelationExpFactor, MilevaDBDMLBatchSize:
   567  		v, err := strconv.Atoi(value)
   568  		if err != nil {
   569  			return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
   570  		}
   571  		if v < 0 {
   572  			return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   573  		}
   574  		return value, nil
   575  	case MilevaDBOptCorrelationThreshold:
   576  		v, err := strconv.ParseFloat(value, 64)
   577  		if err != nil {
   578  			return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
   579  		}
   580  		if v < 0 || v > 1 {
   581  			return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   582  		}
   583  		return value, nil
   584  	case MilevaDBAllowBatchCop:
   585  		v, err := strconv.ParseInt(value, 10, 64)
   586  		if err != nil {
   587  			return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
   588  		}
   589  		if v == 0 && vars.AllowBCJ {
   590  			return value, ErrWrongValueForVar.GenWithStackByArgs("Can't set batch cop 0 but milevadb_opt_broadcast_join is 1, please set milevadb_opt_broadcast_join 0 at first")
   591  		}
   592  		if v < 0 || v > 2 {
   593  			return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   594  		}
   595  		return value, nil
   596  	case MilevaDBOptCPUFactor,
   597  		MilevaDBOptTiFlashConcurrencyFactor,
   598  		MilevaDBOptCopCPUFactor,
   599  		MilevaDBOptNetworkFactor,
   600  		MilevaDBOptScanFactor,
   601  		MilevaDBOptDescScanFactor,
   602  		MilevaDBOptSeekFactor,
   603  		MilevaDBOptMemoryFactor,
   604  		MilevaDBOptDiskFactor,
   605  		MilevaDBOptConcurrencyFactor:
   606  		v, err := strconv.ParseFloat(value, 64)
   607  		if err != nil {
   608  			return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
   609  		}
   610  		if v < 0 {
   611  			return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   612  		}
   613  		return value, nil
   614  	case MilevaDBProjectionConcurrency,
   615  		MilevaDBMemQuotaQuery,
   616  		MilevaDBMemQuotaHashJoin,
   617  		MilevaDBMemQuotaMergeJoin,
   618  		MilevaDBMemQuotaSort,
   619  		MilevaDBMemQuotaTopn,
   620  		MilevaDBMemQuotaIndexLookupReader,
   621  		MilevaDBMemQuotaIndexLookupJoin,
   622  		MilevaDBMemQuotaNestedLoopApply,
   623  		MilevaDBRetryLimit,
   624  		MilevaDBSlowLogThreshold,
   625  		MilevaDBQueryLogMaxLen,
   626  		MilevaDBEvolveCausetTaskMaxTime:
   627  		_, err := strconv.ParseInt(value, 10, 64)
   628  		if err != nil {
   629  			return value, ErrWrongValueForVar.GenWithStackByArgs(name)
   630  		}
   631  		return value, nil
   632  	case MilevaDBAutoAnalyzeStartTime, MilevaDBAutoAnalyzeEndTime, MilevaDBEvolveCausetTaskStartTime, MilevaDBEvolveCausetTaskEndTime:
   633  		v, err := setDayTime(vars, value)
   634  		if err != nil {
   635  			return "", err
   636  		}
   637  		return v, nil
   638  	case MilevaDBAutoAnalyzeRatio:
   639  		v, err := strconv.ParseFloat(value, 64)
   640  		if err != nil || v < 0 {
   641  			return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   642  		}
   643  		return value, nil
   644  	case TxnIsolation, TransactionIsolation:
   645  		upVal := strings.ToUpper(value)
   646  		_, exists := TxIsolationNames[upVal]
   647  		if !exists {
   648  			return "", ErrWrongValueForVar.GenWithStackByArgs(name, value)
   649  		}
   650  		switch upVal {
   651  		case "SERIALIZABLE", "READ-UNCOMMITTED":
   652  			skipIsolationLevelCheck, err := GetStochastikSystemVar(vars, MilevaDBSkipIsolationLevelCheck)
   653  			returnErr := ErrUnsupportedIsolationLevel.GenWithStackByArgs(value)
   654  			if err != nil {
   655  				returnErr = err
   656  			}
   657  			if !MilevaDBOptOn(skipIsolationLevelCheck) || err != nil {
   658  				return "", returnErr
   659  			}
   660  			//SET TRANSACTION ISOLATION LEVEL will affect two internal variables:
   661  			// 1. tx_isolation
   662  			// 2. transaction_isolation
   663  			// The following if condition is used to deduplicate two same warnings.
   664  			if name == "transaction_isolation" {
   665  				vars.StmtCtx.AppendWarning(returnErr)
   666  			}
   667  		}
   668  		return upVal, nil
   669  	case MilevaDBInitChunkSize:
   670  		v, err := strconv.Atoi(value)
   671  		if err != nil {
   672  			return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
   673  		}
   674  		if v <= 0 {
   675  			return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   676  		}
   677  		if v > initChunkSizeUpperBound {
   678  			return value, errors.Errorf("milevadb_init_chunk_size(%d) cannot be bigger than %d", v, initChunkSizeUpperBound)
   679  		}
   680  		return value, nil
   681  	case MilevaDBMaxChunkSize:
   682  		v, err := strconv.Atoi(value)
   683  		if err != nil {
   684  			return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
   685  		}
   686  		if v < maxChunkSizeLowerBound {
   687  			return value, errors.Errorf("milevadb_max_chunk_size(%d) cannot be smaller than %d", v, maxChunkSizeLowerBound)
   688  		}
   689  		return value, nil
   690  	case MilevaDBOptJoinReorderThreshold:
   691  		v, err := strconv.Atoi(value)
   692  		if err != nil {
   693  			return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
   694  		}
   695  		if v < 0 || v >= 64 {
   696  			return value, errors.Errorf("milevadb_join_order_algo_threshold(%d) cannot be smaller than 0 or larger than 63", v)
   697  		}
   698  	case MilevaDBWaitSplitRegionTimeout:
   699  		v, err := strconv.Atoi(value)
   700  		if err != nil {
   701  			return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
   702  		}
   703  		if v <= 0 {
   704  			return value, errors.Errorf("milevadb_wait_split_region_timeout(%d) cannot be smaller than 1", v)
   705  		}
   706  	case MilevaDBReplicaRead:
   707  		if strings.EqualFold(value, "follower") {
   708  			return "follower", nil
   709  		} else if strings.EqualFold(value, "leader-and-follower") {
   710  			return "leader-and-follower", nil
   711  		} else if strings.EqualFold(value, "leader") || len(value) == 0 {
   712  			return "leader", nil
   713  		}
   714  		return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   715  	case MilevaDBTxnMode:
   716  		switch strings.ToUpper(value) {
   717  		case ast.Pessimistic, ast.Optimistic, "":
   718  		default:
   719  			return value, ErrWrongValueForVar.GenWithStackByArgs(MilevaDBTxnMode, value)
   720  		}
   721  	case MilevaDBRowFormatVersion:
   722  		v, err := strconv.Atoi(value)
   723  		if err != nil {
   724  			return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
   725  		}
   726  		if v != DefMilevaDBRowFormatV1 && v != DefMilevaDBRowFormatV2 {
   727  			return value, errors.Errorf("Unsupported event format version %d", v)
   728  		}
   729  	case MilevaDBPartitionPruneMode:
   730  		if !PartitionPruneMode(value).Valid() {
   731  			return value, ErrWrongTypeForVar.GenWithStackByArgs(name)
   732  		}
   733  	case MilevaDBAllowRemoveAutoInc, MilevaDBUseCausetBaselines, MilevaDBEvolveCausetBaselines, MilevaDBEnableParallelApply:
   734  		switch {
   735  		case strings.EqualFold(value, "ON") || value == "1":
   736  			return "on", nil
   737  		case strings.EqualFold(value, "OFF") || value == "0":
   738  			return "off", nil
   739  		}
   740  		return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   741  	case MilevaDBCaptureCausetBaseline:
   742  		switch {
   743  		case strings.EqualFold(value, "ON") || value == "1":
   744  			return "on", nil
   745  		case strings.EqualFold(value, "OFF") || value == "0":
   746  			return "off", nil
   747  		case value == "":
   748  			return "", nil
   749  		}
   750  		return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   751  	case MilevaDBEnableStmtSummary, MilevaDBStmtSummaryInternalQuery:
   752  		switch {
   753  		case strings.EqualFold(value, "ON") || value == "1":
   754  			return "1", nil
   755  		case strings.EqualFold(value, "OFF") || value == "0":
   756  			return "0", nil
   757  		case value == "":
   758  			if scope == ScopeStochastik {
   759  				return "", nil
   760  			}
   761  		}
   762  		return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   763  	case MilevaDBStmtSummaryRefreshInterval:
   764  		if value == "" && scope == ScopeStochastik {
   765  			return "", nil
   766  		}
   767  		return checkInt64SystemVarWithError(name, value, 1, math.MaxInt32)
   768  	case MilevaDBStmtSummaryHistorySize:
   769  		if value == "" && scope == ScopeStochastik {
   770  			return "", nil
   771  		}
   772  		return checkInt64SystemVarWithError(name, value, 0, math.MaxUint8)
   773  	case MilevaDBStmtSummaryMaxStmtCount:
   774  		if value == "" && scope == ScopeStochastik {
   775  			return "", nil
   776  		}
   777  		return checkInt64SystemVarWithError(name, value, 1, math.MaxInt16)
   778  	case MilevaDBStmtSummaryMaxALLEGROSQLLength:
   779  		if value == "" && scope == ScopeStochastik {
   780  			return "", nil
   781  		}
   782  		return checkInt64SystemVarWithError(name, value, 0, math.MaxInt32)
   783  	case MilevaDBIsolationReadEngines:
   784  		engines := strings.Split(value, ",")
   785  		var formatVal string
   786  		for i, engine := range engines {
   787  			engine = strings.TrimSpace(engine)
   788  			if i != 0 {
   789  				formatVal += ","
   790  			}
   791  			switch {
   792  			case strings.EqualFold(engine, ekv.EinsteinDB.Name()):
   793  				formatVal += ekv.EinsteinDB.Name()
   794  			case strings.EqualFold(engine, ekv.TiFlash.Name()):
   795  				formatVal += ekv.TiFlash.Name()
   796  			case strings.EqualFold(engine, ekv.MilevaDB.Name()):
   797  				formatVal += ekv.MilevaDB.Name()
   798  			default:
   799  				return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   800  			}
   801  		}
   802  		return formatVal, nil
   803  	case MilevaDBMetricSchemaStep, MilevaDBMetricSchemaRangeDuration:
   804  		v, err := strconv.ParseInt(value, 10, 64)
   805  		if err != nil {
   806  			return value, ErrWrongValueForVar.GenWithStackByArgs(name, value)
   807  		}
   808  		if v < 10 || v > 60*60*60 {
   809  			return value, errors.Errorf("%v(%d) cannot be smaller than %v or larger than %v", name, v, 10, 60*60*60)
   810  		}
   811  		return value, nil
   812  	case DefCauslationConnection, DefCauslationDatabase, DefCauslationServer:
   813  		if _, err := defCauslate.GetDefCauslationByName(value); err != nil {
   814  			return value, errors.Trace(err)
   815  		}
   816  	case MilevaDBShardAllocateStep:
   817  		return checkInt64SystemVar(name, value, 1, math.MaxInt64, vars)
   818  	}
   819  	return value, nil
   820  }
   821  
   822  // MilevaDBOptOn could be used for all milevadb stochastik variable options, we use "ON"/1 to turn on those options.
   823  func MilevaDBOptOn(opt string) bool {
   824  	return strings.EqualFold(opt, "ON") || opt == "1"
   825  }
   826  
   827  func milevadbOptPositiveInt32(opt string, defaultVal int) int {
   828  	val, err := strconv.Atoi(opt)
   829  	if err != nil || val <= 0 {
   830  		return defaultVal
   831  	}
   832  	return val
   833  }
   834  
   835  func milevadbOptInt64(opt string, defaultVal int64) int64 {
   836  	val, err := strconv.ParseInt(opt, 10, 64)
   837  	if err != nil {
   838  		return defaultVal
   839  	}
   840  	return val
   841  }
   842  
   843  func milevadbOptFloat64(opt string, defaultVal float64) float64 {
   844  	val, err := strconv.ParseFloat(opt, 64)
   845  	if err != nil {
   846  		return defaultVal
   847  	}
   848  	return val
   849  }
   850  
   851  func parseTimeZone(s string) (*time.Location, error) {
   852  	if strings.EqualFold(s, "SYSTEM") {
   853  		return timeutil.SystemLocation(), nil
   854  	}
   855  
   856  	loc, err := time.LoadLocation(s)
   857  	if err == nil {
   858  		return loc, nil
   859  	}
   860  
   861  	// The value can be given as a string indicating an offset from UTC, such as '+10:00' or '-6:00'.
   862  	// The time zone's value should in [-12:59,+14:00].
   863  	if strings.HasPrefix(s, "+") || strings.HasPrefix(s, "-") {
   864  		d, err := types.ParseDuration(nil, s[1:], 0)
   865  		if err == nil {
   866  			if s[0] == '-' {
   867  				if d.Duration > 12*time.Hour+59*time.Minute {
   868  					return nil, ErrUnknownTimeZone.GenWithStackByArgs(s)
   869  				}
   870  			} else {
   871  				if d.Duration > 14*time.Hour {
   872  					return nil, ErrUnknownTimeZone.GenWithStackByArgs(s)
   873  				}
   874  			}
   875  
   876  			ofst := int(d.Duration / time.Second)
   877  			if s[0] == '-' {
   878  				ofst = -ofst
   879  			}
   880  			return time.FixedZone("", ofst), nil
   881  		}
   882  	}
   883  
   884  	return nil, ErrUnknownTimeZone.GenWithStackByArgs(s)
   885  }
   886  
   887  func setSnapshotTS(s *StochastikVars, sVal string) error {
   888  	if sVal == "" {
   889  		s.SnapshotTS = 0
   890  		return nil
   891  	}
   892  
   893  	if tso, err := strconv.ParseUint(sVal, 10, 64); err == nil {
   894  		s.SnapshotTS = tso
   895  		return nil
   896  	}
   897  
   898  	t, err := types.ParseTime(s.StmtCtx, sVal, allegrosql.TypeTimestamp, types.MaxFsp)
   899  	if err != nil {
   900  		return err
   901  	}
   902  
   903  	t1, err := t.GoTime(s.TimeZone)
   904  	s.SnapshotTS = GoTimeToTS(t1)
   905  	return err
   906  }
   907  
   908  // GoTimeToTS converts a Go time to uint64 timestamp.
   909  func GoTimeToTS(t time.Time) uint64 {
   910  	ts := (t.UnixNano() / int64(time.Millisecond)) << epochShiftBits
   911  	return uint64(ts)
   912  }
   913  
   914  const (
   915  	localDayTimeFormat = "15:04"
   916  	// FullDayTimeFormat is the full format of analyze start time and end time.
   917  	FullDayTimeFormat = "15:04 -0700"
   918  )
   919  
   920  func setDayTime(s *StochastikVars, val string) (string, error) {
   921  	var t time.Time
   922  	var err error
   923  	if len(val) <= len(localDayTimeFormat) {
   924  		t, err = time.ParseInLocation(localDayTimeFormat, val, s.TimeZone)
   925  	} else {
   926  		t, err = time.ParseInLocation(FullDayTimeFormat, val, s.TimeZone)
   927  	}
   928  	if err != nil {
   929  		return "", err
   930  	}
   931  	return t.Format(FullDayTimeFormat), nil
   932  }
   933  
   934  // serverGlobalVariable is used to handle variables that acts in server and global scope.
   935  type serverGlobalVariable struct {
   936  	sync.Mutex
   937  	serverVal string
   938  	globalVal string
   939  }
   940  
   941  // Set sets the value according to variable scope.
   942  func (v *serverGlobalVariable) Set(val string, isServer bool) {
   943  	v.Lock()
   944  	if isServer {
   945  		v.serverVal = val
   946  	} else {
   947  		v.globalVal = val
   948  	}
   949  	v.Unlock()
   950  }
   951  
   952  // GetVal gets the value.
   953  func (v *serverGlobalVariable) GetVal() string {
   954  	v.Lock()
   955  	defer v.Unlock()
   956  	if v.serverVal != "" {
   957  		return v.serverVal
   958  	}
   959  	return v.globalVal
   960  }