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 }