github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/interlock/simple.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 interlock 15 16 import ( 17 "context" 18 "fmt" 19 "os" 20 "strings" 21 "time" 22 23 "github.com/ngaut/pools" 24 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 25 "github.com/whtcorpsinc/BerolinaSQL/ast" 26 "github.com/whtcorpsinc/BerolinaSQL/auth" 27 "github.com/whtcorpsinc/BerolinaSQL/perceptron" 28 "github.com/whtcorpsinc/BerolinaSQL/terror" 29 "github.com/whtcorpsinc/errors" 30 "github.com/whtcorpsinc/milevadb/causet" 31 "github.com/whtcorpsinc/milevadb/causet/embedded" 32 "github.com/whtcorpsinc/milevadb/config" 33 "github.com/whtcorpsinc/milevadb/ekv" 34 "github.com/whtcorpsinc/milevadb/metrics" 35 "github.com/whtcorpsinc/milevadb/petri" 36 "github.com/whtcorpsinc/milevadb/plugin" 37 "github.com/whtcorpsinc/milevadb/privilege" 38 "github.com/whtcorpsinc/milevadb/schemareplicant" 39 "github.com/whtcorpsinc/milevadb/soliton" 40 "github.com/whtcorpsinc/milevadb/soliton/chunk" 41 "github.com/whtcorpsinc/milevadb/soliton/logutil" 42 "github.com/whtcorpsinc/milevadb/soliton/replog" 43 "github.com/whtcorpsinc/milevadb/soliton/sqlexec" 44 "github.com/whtcorpsinc/milevadb/stochastikctx" 45 "github.com/whtcorpsinc/milevadb/stochastikctx/variable" 46 "go.uber.org/zap" 47 ) 48 49 var ( 50 transactionDurationPessimisticRollback = metrics.TransactionDuration.WithLabelValues(metrics.LblPessimistic, metrics.LblRollback) 51 transactionDurationOptimisticRollback = metrics.TransactionDuration.WithLabelValues(metrics.LblOptimistic, metrics.LblRollback) 52 ) 53 54 // SimpleInterDirc represents simple memex interlock. 55 // For memexs do simple execution. 56 // includes `UseStmt`, 'SetStmt`, `DoStmt`, 57 // `BeginStmt`, `CommitStmt`, `RollbackStmt`. 58 // TODO: list all simple memexs. 59 type SimpleInterDirc struct { 60 baseInterlockingDirectorate 61 62 Statement ast.StmtNode 63 done bool 64 is schemareplicant.SchemaReplicant 65 } 66 67 func (e *baseInterlockingDirectorate) getSysStochastik() (stochastikctx.Context, error) { 68 dom := petri.GetPetri(e.ctx) 69 sysStochastikPool := dom.SysStochastikPool() 70 ctx, err := sysStochastikPool.Get() 71 if err != nil { 72 return nil, err 73 } 74 restrictedCtx := ctx.(stochastikctx.Context) 75 restrictedCtx.GetStochastikVars().InRestrictedALLEGROSQL = true 76 return restrictedCtx, nil 77 } 78 79 func (e *baseInterlockingDirectorate) releaseSysStochastik(ctx stochastikctx.Context) { 80 if ctx == nil { 81 return 82 } 83 dom := petri.GetPetri(e.ctx) 84 sysStochastikPool := dom.SysStochastikPool() 85 if _, err := ctx.(sqlexec.ALLEGROSQLInterlockingDirectorate).InterDircute(context.Background(), "rollback"); err != nil { 86 ctx.(pools.Resource).Close() 87 return 88 } 89 sysStochastikPool.Put(ctx.(pools.Resource)) 90 } 91 92 // Next implements the InterlockingDirectorate Next interface. 93 func (e *SimpleInterDirc) Next(ctx context.Context, req *chunk.Chunk) (err error) { 94 if e.done { 95 return nil 96 } 97 98 if e.autoNewTxn() { 99 // Commit the old transaction, like DBS. 100 if err := e.ctx.NewTxn(ctx); err != nil { 101 return err 102 } 103 defer func() { e.ctx.GetStochastikVars().SetStatusFlag(allegrosql.ServerStatusInTrans, false) }() 104 } 105 106 switch x := e.Statement.(type) { 107 case *ast.GrantRoleStmt: 108 err = e.executeGrantRole(x) 109 case *ast.UseStmt: 110 err = e.executeUse(x) 111 case *ast.FlushStmt: 112 err = e.executeFlush(x) 113 case *ast.AlterInstanceStmt: 114 err = e.executeAlterInstance(x) 115 case *ast.BeginStmt: 116 err = e.executeBegin(ctx, x) 117 case *ast.CommitStmt: 118 e.executeCommit(x) 119 case *ast.RollbackStmt: 120 err = e.executeRollback(x) 121 case *ast.CreateUserStmt: 122 err = e.executeCreateUser(ctx, x) 123 case *ast.AlterUserStmt: 124 err = e.executeAlterUser(x) 125 case *ast.DropUserStmt: 126 err = e.executeDropUser(x) 127 case *ast.SetPwdStmt: 128 err = e.executeSetPwd(x) 129 case *ast.KillStmt: 130 err = e.executeKillStmt(x) 131 case *ast.BinlogStmt: 132 // We just ignore it. 133 return nil 134 case *ast.DropStatsStmt: 135 err = e.executeDropStats(x) 136 case *ast.SetRoleStmt: 137 err = e.executeSetRole(x) 138 case *ast.RevokeRoleStmt: 139 err = e.executeRevokeRole(x) 140 case *ast.SetDefaultRoleStmt: 141 err = e.executeSetDefaultRole(x) 142 case *ast.ShutdownStmt: 143 err = e.executeShutdown(x) 144 case *ast.CreateStatisticsStmt: 145 err = e.executeCreateStatistics(x) 146 case *ast.DropStatisticsStmt: 147 err = e.executeDropStatistics(x) 148 case *ast.AdminStmt: 149 err = e.executeAdminReloadStatistics(x) 150 } 151 e.done = true 152 return err 153 } 154 155 func (e *SimpleInterDirc) setDefaultRoleNone(s *ast.SetDefaultRoleStmt) error { 156 restrictedCtx, err := e.getSysStochastik() 157 if err != nil { 158 return err 159 } 160 defer e.releaseSysStochastik(restrictedCtx) 161 sqlInterlockingDirectorate := restrictedCtx.(sqlexec.ALLEGROSQLInterlockingDirectorate) 162 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "begin"); err != nil { 163 return err 164 } 165 for _, u := range s.UserList { 166 if u.Hostname == "" { 167 u.Hostname = "%" 168 } 169 allegrosql := fmt.Sprintf("DELETE IGNORE FROM allegrosql.default_roles WHERE USER='%s' AND HOST='%s';", u.Username, u.Hostname) 170 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), allegrosql); err != nil { 171 logutil.BgLogger().Error(fmt.Sprintf("Error occur when executing %s", allegrosql)) 172 if _, rollbackErr := sqlInterlockingDirectorate.InterDircute(context.Background(), "rollback"); rollbackErr != nil { 173 return rollbackErr 174 } 175 return err 176 } 177 } 178 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "commit"); err != nil { 179 return err 180 } 181 return nil 182 } 183 184 func (e *SimpleInterDirc) setDefaultRoleRegular(s *ast.SetDefaultRoleStmt) error { 185 for _, user := range s.UserList { 186 exists, err := userExists(e.ctx, user.Username, user.Hostname) 187 if err != nil { 188 return err 189 } 190 if !exists { 191 return ErrCannotUser.GenWithStackByArgs("SET DEFAULT ROLE", user.String()) 192 } 193 } 194 for _, role := range s.RoleList { 195 exists, err := userExists(e.ctx, role.Username, role.Hostname) 196 if err != nil { 197 return err 198 } 199 if !exists { 200 return ErrCannotUser.GenWithStackByArgs("SET DEFAULT ROLE", role.String()) 201 } 202 } 203 204 restrictedCtx, err := e.getSysStochastik() 205 if err != nil { 206 return err 207 } 208 defer e.releaseSysStochastik(restrictedCtx) 209 sqlInterlockingDirectorate := restrictedCtx.(sqlexec.ALLEGROSQLInterlockingDirectorate) 210 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "begin"); err != nil { 211 return err 212 } 213 for _, user := range s.UserList { 214 if user.Hostname == "" { 215 user.Hostname = "%" 216 } 217 allegrosql := fmt.Sprintf("DELETE IGNORE FROM allegrosql.default_roles WHERE USER='%s' AND HOST='%s';", user.Username, user.Hostname) 218 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), allegrosql); err != nil { 219 logutil.BgLogger().Error(fmt.Sprintf("Error occur when executing %s", allegrosql)) 220 if _, rollbackErr := sqlInterlockingDirectorate.InterDircute(context.Background(), "rollback"); rollbackErr != nil { 221 return rollbackErr 222 } 223 return err 224 } 225 for _, role := range s.RoleList { 226 allegrosql := fmt.Sprintf("INSERT IGNORE INTO allegrosql.default_roles values('%s', '%s', '%s', '%s');", user.Hostname, user.Username, role.Hostname, role.Username) 227 checker := privilege.GetPrivilegeManager(e.ctx) 228 ok := checker.FindEdge(e.ctx, role, user) 229 if ok { 230 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), allegrosql); err != nil { 231 logutil.BgLogger().Error(fmt.Sprintf("Error occur when executing %s", allegrosql)) 232 if _, rollbackErr := sqlInterlockingDirectorate.InterDircute(context.Background(), "rollback"); rollbackErr != nil { 233 return rollbackErr 234 } 235 return err 236 } 237 } else { 238 if _, rollbackErr := sqlInterlockingDirectorate.InterDircute(context.Background(), "rollback"); rollbackErr != nil { 239 return rollbackErr 240 } 241 return ErrRoleNotGranted.GenWithStackByArgs(role.String(), user.String()) 242 } 243 } 244 } 245 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "commit"); err != nil { 246 return err 247 } 248 return nil 249 } 250 251 func (e *SimpleInterDirc) setDefaultRoleAll(s *ast.SetDefaultRoleStmt) error { 252 for _, user := range s.UserList { 253 exists, err := userExists(e.ctx, user.Username, user.Hostname) 254 if err != nil { 255 return err 256 } 257 if !exists { 258 return ErrCannotUser.GenWithStackByArgs("SET DEFAULT ROLE", user.String()) 259 } 260 } 261 restrictedCtx, err := e.getSysStochastik() 262 if err != nil { 263 return err 264 } 265 defer e.releaseSysStochastik(restrictedCtx) 266 sqlInterlockingDirectorate := restrictedCtx.(sqlexec.ALLEGROSQLInterlockingDirectorate) 267 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "begin"); err != nil { 268 return err 269 } 270 for _, user := range s.UserList { 271 if user.Hostname == "" { 272 user.Hostname = "%" 273 } 274 allegrosql := fmt.Sprintf("DELETE IGNORE FROM allegrosql.default_roles WHERE USER='%s' AND HOST='%s';", user.Username, user.Hostname) 275 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), allegrosql); err != nil { 276 logutil.BgLogger().Error(fmt.Sprintf("Error occur when executing %s", allegrosql)) 277 if _, rollbackErr := sqlInterlockingDirectorate.InterDircute(context.Background(), "rollback"); rollbackErr != nil { 278 return rollbackErr 279 } 280 return err 281 } 282 allegrosql = fmt.Sprintf("INSERT IGNORE INTO allegrosql.default_roles(HOST,USER,DEFAULT_ROLE_HOST,DEFAULT_ROLE_USER) "+ 283 "SELECT TO_HOST,TO_USER,FROM_HOST,FROM_USER FROM allegrosql.role_edges WHERE TO_HOST='%s' AND TO_USER='%s';", user.Hostname, user.Username) 284 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), allegrosql); err != nil { 285 if _, rollbackErr := sqlInterlockingDirectorate.InterDircute(context.Background(), "rollback"); rollbackErr != nil { 286 return rollbackErr 287 } 288 return err 289 } 290 } 291 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "commit"); err != nil { 292 return err 293 } 294 return nil 295 } 296 297 func (e *SimpleInterDirc) setDefaultRoleForCurrentUser(s *ast.SetDefaultRoleStmt) (err error) { 298 checker := privilege.GetPrivilegeManager(e.ctx) 299 user, allegrosql := s.UserList[0], "" 300 if user.Hostname == "" { 301 user.Hostname = "%" 302 } 303 switch s.SetRoleOpt { 304 case ast.SetRoleNone: 305 allegrosql = fmt.Sprintf("DELETE IGNORE FROM allegrosql.default_roles WHERE USER='%s' AND HOST='%s';", user.Username, user.Hostname) 306 case ast.SetRoleAll: 307 allegrosql = fmt.Sprintf("INSERT IGNORE INTO allegrosql.default_roles(HOST,USER,DEFAULT_ROLE_HOST,DEFAULT_ROLE_USER) "+ 308 "SELECT TO_HOST,TO_USER,FROM_HOST,FROM_USER FROM allegrosql.role_edges WHERE TO_HOST='%s' AND TO_USER='%s';", user.Hostname, user.Username) 309 case ast.SetRoleRegular: 310 allegrosql = "INSERT IGNORE INTO allegrosql.default_roles values" 311 for i, role := range s.RoleList { 312 ok := checker.FindEdge(e.ctx, role, user) 313 if !ok { 314 return ErrRoleNotGranted.GenWithStackByArgs(role.String(), user.String()) 315 } 316 allegrosql += fmt.Sprintf("('%s', '%s', '%s', '%s')", user.Hostname, user.Username, role.Hostname, role.Username) 317 if i != len(s.RoleList)-1 { 318 allegrosql += "," 319 } 320 } 321 } 322 323 restrictedCtx, err := e.getSysStochastik() 324 if err != nil { 325 return err 326 } 327 defer e.releaseSysStochastik(restrictedCtx) 328 sqlInterlockingDirectorate := restrictedCtx.(sqlexec.ALLEGROSQLInterlockingDirectorate) 329 330 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "begin"); err != nil { 331 return err 332 } 333 334 deleteALLEGROSQL := fmt.Sprintf("DELETE IGNORE FROM allegrosql.default_roles WHERE USER='%s' AND HOST='%s';", user.Username, user.Hostname) 335 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), deleteALLEGROSQL); err != nil { 336 logutil.BgLogger().Error(fmt.Sprintf("Error occur when executing %s", allegrosql)) 337 if _, rollbackErr := sqlInterlockingDirectorate.InterDircute(context.Background(), "rollback"); rollbackErr != nil { 338 return rollbackErr 339 } 340 return err 341 } 342 343 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), allegrosql); err != nil { 344 logutil.BgLogger().Error(fmt.Sprintf("Error occur when executing %s", allegrosql)) 345 if _, rollbackErr := sqlInterlockingDirectorate.InterDircute(context.Background(), "rollback"); rollbackErr != nil { 346 return rollbackErr 347 } 348 return err 349 } 350 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "commit"); err != nil { 351 return err 352 } 353 return nil 354 } 355 356 func (e *SimpleInterDirc) executeSetDefaultRole(s *ast.SetDefaultRoleStmt) (err error) { 357 stochastikVars := e.ctx.GetStochastikVars() 358 checker := privilege.GetPrivilegeManager(e.ctx) 359 if checker == nil { 360 return errors.New("miss privilege checker") 361 } 362 363 if len(s.UserList) == 1 && stochastikVars.User != nil { 364 u, h := s.UserList[0].Username, s.UserList[0].Hostname 365 if u == stochastikVars.User.Username && h == stochastikVars.User.AuthHostname { 366 err = e.setDefaultRoleForCurrentUser(s) 367 petri.GetPetri(e.ctx).NotifyUFIDelatePrivilege(e.ctx) 368 return 369 } 370 } 371 372 activeRoles := stochastikVars.ActiveRoles 373 if !checker.RequestVerification(activeRoles, allegrosql.SystemDB, allegrosql.DefaultRoleBlock, "", allegrosql.UFIDelatePriv) { 374 if !checker.RequestVerification(activeRoles, "", "", "", allegrosql.CreateUserPriv) { 375 return embedded.ErrSpecificAccessDenied.GenWithStackByArgs("CREATE USER") 376 } 377 } 378 379 switch s.SetRoleOpt { 380 case ast.SetRoleAll: 381 err = e.setDefaultRoleAll(s) 382 case ast.SetRoleNone: 383 err = e.setDefaultRoleNone(s) 384 case ast.SetRoleRegular: 385 err = e.setDefaultRoleRegular(s) 386 } 387 if err != nil { 388 return 389 } 390 petri.GetPetri(e.ctx).NotifyUFIDelatePrivilege(e.ctx) 391 return 392 } 393 394 func (e *SimpleInterDirc) setRoleRegular(s *ast.SetRoleStmt) error { 395 // Deal with ALLEGROALLEGROSQL like `SET ROLE role1, role2;` 396 checkDup := make(map[string]*auth.RoleIdentity, len(s.RoleList)) 397 // Check whether RoleNameList contain duplicate role name. 398 for _, r := range s.RoleList { 399 key := r.String() 400 checkDup[key] = r 401 } 402 roleList := make([]*auth.RoleIdentity, 0, 10) 403 for _, v := range checkDup { 404 roleList = append(roleList, v) 405 } 406 407 checker := privilege.GetPrivilegeManager(e.ctx) 408 ok, roleName := checker.ActiveRoles(e.ctx, roleList) 409 if !ok { 410 u := e.ctx.GetStochastikVars().User 411 return ErrRoleNotGranted.GenWithStackByArgs(roleName, u.String()) 412 } 413 return nil 414 } 415 416 func (e *SimpleInterDirc) setRoleAll(s *ast.SetRoleStmt) error { 417 // Deal with ALLEGROALLEGROSQL like `SET ROLE ALL;` 418 checker := privilege.GetPrivilegeManager(e.ctx) 419 user, host := e.ctx.GetStochastikVars().User.AuthUsername, e.ctx.GetStochastikVars().User.AuthHostname 420 roles := checker.GetAllRoles(user, host) 421 ok, roleName := checker.ActiveRoles(e.ctx, roles) 422 if !ok { 423 u := e.ctx.GetStochastikVars().User 424 return ErrRoleNotGranted.GenWithStackByArgs(roleName, u.String()) 425 } 426 return nil 427 } 428 429 func (e *SimpleInterDirc) setRoleAllExcept(s *ast.SetRoleStmt) error { 430 // Deal with ALLEGROALLEGROSQL like `SET ROLE ALL EXCEPT role1, role2;` 431 for _, r := range s.RoleList { 432 if r.Hostname == "" { 433 r.Hostname = "%" 434 } 435 } 436 checker := privilege.GetPrivilegeManager(e.ctx) 437 user, host := e.ctx.GetStochastikVars().User.AuthUsername, e.ctx.GetStochastikVars().User.AuthHostname 438 roles := checker.GetAllRoles(user, host) 439 440 filter := func(arr []*auth.RoleIdentity, f func(*auth.RoleIdentity) bool) []*auth.RoleIdentity { 441 i, j := 0, 0 442 for i = 0; i < len(arr); i++ { 443 if f(arr[i]) { 444 arr[j] = arr[i] 445 j++ 446 } 447 } 448 return arr[:j] 449 } 450 banned := func(r *auth.RoleIdentity) bool { 451 for _, ban := range s.RoleList { 452 if ban.Hostname == r.Hostname && ban.Username == r.Username { 453 return false 454 } 455 } 456 return true 457 } 458 459 afterExcept := filter(roles, banned) 460 ok, roleName := checker.ActiveRoles(e.ctx, afterExcept) 461 if !ok { 462 u := e.ctx.GetStochastikVars().User 463 return ErrRoleNotGranted.GenWithStackByArgs(roleName, u.String()) 464 } 465 return nil 466 } 467 468 func (e *SimpleInterDirc) setRoleDefault(s *ast.SetRoleStmt) error { 469 // Deal with ALLEGROALLEGROSQL like `SET ROLE DEFAULT;` 470 checker := privilege.GetPrivilegeManager(e.ctx) 471 user, host := e.ctx.GetStochastikVars().User.AuthUsername, e.ctx.GetStochastikVars().User.AuthHostname 472 roles := checker.GetDefaultRoles(user, host) 473 ok, roleName := checker.ActiveRoles(e.ctx, roles) 474 if !ok { 475 u := e.ctx.GetStochastikVars().User 476 return ErrRoleNotGranted.GenWithStackByArgs(roleName, u.String()) 477 } 478 return nil 479 } 480 481 func (e *SimpleInterDirc) setRoleNone(s *ast.SetRoleStmt) error { 482 // Deal with ALLEGROALLEGROSQL like `SET ROLE NONE;` 483 checker := privilege.GetPrivilegeManager(e.ctx) 484 roles := make([]*auth.RoleIdentity, 0) 485 ok, roleName := checker.ActiveRoles(e.ctx, roles) 486 if !ok { 487 u := e.ctx.GetStochastikVars().User 488 return ErrRoleNotGranted.GenWithStackByArgs(roleName, u.String()) 489 } 490 return nil 491 } 492 493 func (e *SimpleInterDirc) executeSetRole(s *ast.SetRoleStmt) error { 494 switch s.SetRoleOpt { 495 case ast.SetRoleRegular: 496 return e.setRoleRegular(s) 497 case ast.SetRoleAll: 498 return e.setRoleAll(s) 499 case ast.SetRoleAllExcept: 500 return e.setRoleAllExcept(s) 501 case ast.SetRoleNone: 502 return e.setRoleNone(s) 503 case ast.SetRoleDefault: 504 return e.setRoleDefault(s) 505 } 506 return nil 507 } 508 509 func (e *SimpleInterDirc) dbAccessDenied(dbname string) error { 510 user := e.ctx.GetStochastikVars().User 511 u := user.Username 512 h := user.Hostname 513 if len(user.AuthUsername) > 0 && len(user.AuthHostname) > 0 { 514 u = user.AuthUsername 515 h = user.AuthHostname 516 } 517 return ErrDBaccessDenied.GenWithStackByArgs(u, h, dbname) 518 } 519 520 func (e *SimpleInterDirc) executeUse(s *ast.UseStmt) error { 521 dbname := perceptron.NewCIStr(s.DBName) 522 523 checker := privilege.GetPrivilegeManager(e.ctx) 524 if checker != nil && e.ctx.GetStochastikVars().User != nil { 525 if !checker.DBIsVisible(e.ctx.GetStochastikVars().ActiveRoles, dbname.String()) { 526 return e.dbAccessDenied(dbname.O) 527 } 528 } 529 530 dbinfo, exists := e.is.SchemaByName(dbname) 531 if !exists { 532 return schemareplicant.ErrDatabaseNotExists.GenWithStackByArgs(dbname) 533 } 534 e.ctx.GetStochastikVars().CurrentDBChanged = dbname.O != e.ctx.GetStochastikVars().CurrentDB 535 e.ctx.GetStochastikVars().CurrentDB = dbname.O 536 // character_set_database is the character set used by the default database. 537 // The server sets this variable whenever the default database changes. 538 // See http://dev.allegrosql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_character_set_database 539 stochastikVars := e.ctx.GetStochastikVars() 540 err := stochastikVars.SetSystemVar(variable.CharsetDatabase, dbinfo.Charset) 541 if err != nil { 542 return err 543 } 544 dbDefCauslate := dbinfo.DefCauslate 545 if dbDefCauslate == "" { 546 // Since we have checked the charset, the dbDefCauslate here shouldn't be "". 547 dbDefCauslate = getDefaultDefCauslate(dbinfo.Charset) 548 } 549 return stochastikVars.SetSystemVar(variable.DefCauslationDatabase, dbDefCauslate) 550 } 551 552 func (e *SimpleInterDirc) executeBegin(ctx context.Context, s *ast.BeginStmt) error { 553 // If BEGIN is the first memex in TxnCtx, we can reuse the existing transaction, without the 554 // need to call NewTxn, which commits the existing transaction and begins a new one. 555 txnCtx := e.ctx.GetStochastikVars().TxnCtx 556 if txnCtx.History != nil { 557 err := e.ctx.NewTxn(ctx) 558 if err != nil { 559 return err 560 } 561 } 562 // With START TRANSACTION, autocommit remains disabled until you end 563 // the transaction with COMMIT or ROLLBACK. The autocommit mode then 564 // reverts to its previous state. 565 e.ctx.GetStochastikVars().SetStatusFlag(allegrosql.ServerStatusInTrans, true) 566 // Call ctx.Txn(true) to active pending txn. 567 txnMode := s.Mode 568 if txnMode == "" { 569 txnMode = e.ctx.GetStochastikVars().TxnMode 570 } 571 if txnMode == ast.Pessimistic { 572 e.ctx.GetStochastikVars().TxnCtx.IsPessimistic = true 573 } 574 txn, err := e.ctx.Txn(true) 575 if err != nil { 576 return err 577 } 578 if e.ctx.GetStochastikVars().TxnCtx.IsPessimistic { 579 txn.SetOption(ekv.Pessimistic, true) 580 } 581 return nil 582 } 583 584 func (e *SimpleInterDirc) executeRevokeRole(s *ast.RevokeRoleStmt) error { 585 for _, role := range s.Roles { 586 exists, err := userExists(e.ctx, role.Username, role.Hostname) 587 if err != nil { 588 return errors.Trace(err) 589 } 590 if !exists { 591 return ErrCannotUser.GenWithStackByArgs("REVOKE ROLE", role.String()) 592 } 593 } 594 595 restrictedCtx, err := e.getSysStochastik() 596 if err != nil { 597 return err 598 } 599 defer e.releaseSysStochastik(restrictedCtx) 600 sqlInterlockingDirectorate := restrictedCtx.(sqlexec.ALLEGROSQLInterlockingDirectorate) 601 602 // begin a transaction to insert role graph edges. 603 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "begin"); err != nil { 604 return errors.Trace(err) 605 } 606 for _, user := range s.Users { 607 exists, err := userExists(e.ctx, user.Username, user.Hostname) 608 if err != nil { 609 return errors.Trace(err) 610 } 611 if !exists { 612 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "rollback"); err != nil { 613 return errors.Trace(err) 614 } 615 return ErrCannotUser.GenWithStackByArgs("REVOKE ROLE", user.String()) 616 } 617 for _, role := range s.Roles { 618 if role.Hostname == "" { 619 role.Hostname = "%" 620 } 621 allegrosql := fmt.Sprintf(`DELETE IGNORE FROM %s.%s WHERE FROM_HOST='%s' and FROM_USER='%s' and TO_HOST='%s' and TO_USER='%s'`, allegrosql.SystemDB, allegrosql.RoleEdgeBlock, role.Hostname, role.Username, user.Hostname, user.Username) 622 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), allegrosql); err != nil { 623 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "rollback"); err != nil { 624 return errors.Trace(err) 625 } 626 return ErrCannotUser.GenWithStackByArgs("REVOKE ROLE", role.String()) 627 } 628 allegrosql = fmt.Sprintf(`DELETE IGNORE FROM %s.%s WHERE DEFAULT_ROLE_HOST='%s' and DEFAULT_ROLE_USER='%s' and HOST='%s' and USER='%s'`, allegrosql.SystemDB, allegrosql.DefaultRoleBlock, role.Hostname, role.Username, user.Hostname, user.Username) 629 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), allegrosql); err != nil { 630 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "rollback"); err != nil { 631 return errors.Trace(err) 632 } 633 return ErrCannotUser.GenWithStackByArgs("REVOKE ROLE", role.String()) 634 } 635 } 636 } 637 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "commit"); err != nil { 638 return err 639 } 640 petri.GetPetri(e.ctx).NotifyUFIDelatePrivilege(e.ctx) 641 return nil 642 } 643 644 func (e *SimpleInterDirc) executeCommit(s *ast.CommitStmt) { 645 e.ctx.GetStochastikVars().SetStatusFlag(allegrosql.ServerStatusInTrans, false) 646 } 647 648 func (e *SimpleInterDirc) executeRollback(s *ast.RollbackStmt) error { 649 sessVars := e.ctx.GetStochastikVars() 650 logutil.BgLogger().Debug("execute rollback memex", zap.Uint64("conn", sessVars.ConnectionID)) 651 sessVars.SetStatusFlag(allegrosql.ServerStatusInTrans, false) 652 txn, err := e.ctx.Txn(false) 653 if err != nil { 654 return err 655 } 656 if txn.Valid() { 657 duration := time.Since(sessVars.TxnCtx.CreateTime).Seconds() 658 if sessVars.TxnCtx.IsPessimistic { 659 transactionDurationPessimisticRollback.Observe(duration) 660 } else { 661 transactionDurationOptimisticRollback.Observe(duration) 662 } 663 sessVars.TxnCtx.ClearDelta() 664 return txn.Rollback() 665 } 666 return nil 667 } 668 669 func (e *SimpleInterDirc) executeCreateUser(ctx context.Context, s *ast.CreateUserStmt) error { 670 // Check `CREATE USER` privilege. 671 if !config.GetGlobalConfig().Security.SkipGrantBlock { 672 checker := privilege.GetPrivilegeManager(e.ctx) 673 if checker == nil { 674 return errors.New("miss privilege checker") 675 } 676 activeRoles := e.ctx.GetStochastikVars().ActiveRoles 677 if !checker.RequestVerification(activeRoles, allegrosql.SystemDB, allegrosql.UserBlock, "", allegrosql.InsertPriv) { 678 if s.IsCreateRole { 679 if !checker.RequestVerification(activeRoles, "", "", "", allegrosql.CreateRolePriv) && 680 !checker.RequestVerification(activeRoles, "", "", "", allegrosql.CreateUserPriv) { 681 return embedded.ErrSpecificAccessDenied.GenWithStackByArgs("CREATE ROLE or CREATE USER") 682 } 683 } 684 if !s.IsCreateRole && !checker.RequestVerification(activeRoles, "", "", "", allegrosql.CreateUserPriv) { 685 return embedded.ErrSpecificAccessDenied.GenWithStackByArgs("CREATE User") 686 } 687 } 688 } 689 690 privData, err := tlsOption2GlobalPriv(s.TLSOptions) 691 if err != nil { 692 return err 693 } 694 695 users := make([]string, 0, len(s.Specs)) 696 privs := make([]string, 0, len(s.Specs)) 697 for _, spec := range s.Specs { 698 exists, err1 := userExists(e.ctx, spec.User.Username, spec.User.Hostname) 699 if err1 != nil { 700 return err1 701 } 702 if exists { 703 user := fmt.Sprintf(`'%s'@'%s'`, spec.User.Username, spec.User.Hostname) 704 if !s.IfNotExists { 705 if s.IsCreateRole { 706 return ErrCannotUser.GenWithStackByArgs("CREATE ROLE", user) 707 } 708 return ErrCannotUser.GenWithStackByArgs("CREATE USER", user) 709 } 710 err := schemareplicant.ErrUserAlreadyExists.GenWithStackByArgs(user) 711 e.ctx.GetStochastikVars().StmtCtx.AppendNote(err) 712 continue 713 } 714 pwd, ok := spec.EncodedPassword() 715 if !ok { 716 return errors.Trace(ErrPasswordFormat) 717 } 718 user := fmt.Sprintf(`('%s', '%s', '%s')`, spec.User.Hostname, spec.User.Username, pwd) 719 if s.IsCreateRole { 720 user = fmt.Sprintf(`('%s', '%s', '%s', 'Y')`, spec.User.Hostname, spec.User.Username, pwd) 721 } 722 users = append(users, user) 723 724 if len(privData) != 0 { 725 priv := fmt.Sprintf(`('%s', '%s', '%s')`, spec.User.Hostname, spec.User.Username, replog.String(privData)) 726 privs = append(privs, priv) 727 } 728 } 729 if len(users) == 0 { 730 return nil 731 } 732 733 allegrosql := fmt.Sprintf(`INSERT INTO %s.%s (Host, User, authentication_string) VALUES %s;`, allegrosql.SystemDB, allegrosql.UserBlock, strings.Join(users, ", ")) 734 if s.IsCreateRole { 735 allegrosql = fmt.Sprintf(`INSERT INTO %s.%s (Host, User, authentication_string, Account_locked) VALUES %s;`, allegrosql.SystemDB, allegrosql.UserBlock, strings.Join(users, ", ")) 736 } 737 738 restrictedCtx, err := e.getSysStochastik() 739 if err != nil { 740 return err 741 } 742 defer e.releaseSysStochastik(restrictedCtx) 743 sqlInterlockingDirectorate := restrictedCtx.(sqlexec.ALLEGROSQLInterlockingDirectorate) 744 745 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "begin"); err != nil { 746 return errors.Trace(err) 747 } 748 _, err = sqlInterlockingDirectorate.InterDircute(context.Background(), allegrosql) 749 if err != nil { 750 if _, rollbackErr := sqlInterlockingDirectorate.InterDircute(context.Background(), "rollback"); rollbackErr != nil { 751 return rollbackErr 752 } 753 return err 754 } 755 if len(privs) != 0 { 756 allegrosql = fmt.Sprintf("INSERT IGNORE INTO %s.%s (Host, User, Priv) VALUES %s", allegrosql.SystemDB, allegrosql.GlobalPrivBlock, strings.Join(privs, ", ")) 757 _, err = sqlInterlockingDirectorate.InterDircute(context.Background(), allegrosql) 758 if err != nil { 759 if _, rollbackErr := sqlInterlockingDirectorate.InterDircute(context.Background(), "rollback"); rollbackErr != nil { 760 return rollbackErr 761 } 762 return err 763 } 764 } 765 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "commit"); err != nil { 766 return errors.Trace(err) 767 } 768 petri.GetPetri(e.ctx).NotifyUFIDelatePrivilege(e.ctx) 769 return err 770 } 771 772 func (e *SimpleInterDirc) executeAlterUser(s *ast.AlterUserStmt) error { 773 if s.CurrentAuth != nil { 774 user := e.ctx.GetStochastikVars().User 775 if user == nil { 776 return errors.New("Stochastik user is empty") 777 } 778 // Use AuthHostname to search the user record, set Hostname as AuthHostname. 779 userCopy := *user 780 userCopy.Hostname = userCopy.AuthHostname 781 spec := &ast.UserSpec{ 782 User: &userCopy, 783 AuthOpt: s.CurrentAuth, 784 } 785 s.Specs = []*ast.UserSpec{spec} 786 } 787 788 privData, err := tlsOption2GlobalPriv(s.TLSOptions) 789 if err != nil { 790 return err 791 } 792 793 failedUsers := make([]string, 0, len(s.Specs)) 794 for _, spec := range s.Specs { 795 if spec.User.CurrentUser { 796 user := e.ctx.GetStochastikVars().User 797 spec.User.Username = user.Username 798 spec.User.Hostname = user.AuthHostname 799 } 800 801 exists, err := userExists(e.ctx, spec.User.Username, spec.User.Hostname) 802 if err != nil { 803 return err 804 } 805 if !exists { 806 user := fmt.Sprintf(`'%s'@'%s'`, spec.User.Username, spec.User.Hostname) 807 failedUsers = append(failedUsers, user) 808 continue 809 } 810 pwd, ok := spec.EncodedPassword() 811 if !ok { 812 return errors.Trace(ErrPasswordFormat) 813 } 814 allegrosql := fmt.Sprintf(`UFIDelATE %s.%s SET authentication_string = '%s' WHERE Host = '%s' and User = '%s';`, 815 allegrosql.SystemDB, allegrosql.UserBlock, pwd, spec.User.Hostname, spec.User.Username) 816 _, _, err = e.ctx.(sqlexec.RestrictedALLEGROSQLInterlockingDirectorate).InterDircRestrictedALLEGROSQL(allegrosql) 817 if err != nil { 818 failedUsers = append(failedUsers, spec.User.String()) 819 } 820 821 if len(privData) > 0 { 822 allegrosql = fmt.Sprintf("INSERT INTO %s.%s (Host, User, Priv) VALUES ('%s','%s','%s') ON DUPLICATE KEY UFIDelATE Priv = values(Priv)", 823 allegrosql.SystemDB, allegrosql.GlobalPrivBlock, spec.User.Hostname, spec.User.Username, replog.String(privData)) 824 _, _, err = e.ctx.(sqlexec.RestrictedALLEGROSQLInterlockingDirectorate).InterDircRestrictedALLEGROSQL(allegrosql) 825 if err != nil { 826 failedUsers = append(failedUsers, spec.User.String()) 827 } 828 } 829 } 830 if len(failedUsers) > 0 { 831 // Commit the transaction even if we returns error 832 txn, err := e.ctx.Txn(true) 833 if err != nil { 834 return err 835 } 836 err = txn.Commit(stochastikctx.SetCommitCtx(context.Background(), e.ctx)) 837 if err != nil { 838 return err 839 } 840 if !s.IfExists { 841 return ErrCannotUser.GenWithStackByArgs("ALTER USER", strings.Join(failedUsers, ",")) 842 } 843 for _, user := range failedUsers { 844 err := schemareplicant.ErrUserDropExists.GenWithStackByArgs(user) 845 e.ctx.GetStochastikVars().StmtCtx.AppendNote(err) 846 } 847 } 848 petri.GetPetri(e.ctx).NotifyUFIDelatePrivilege(e.ctx) 849 return nil 850 } 851 852 func (e *SimpleInterDirc) executeGrantRole(s *ast.GrantRoleStmt) error { 853 stochastikVars := e.ctx.GetStochastikVars() 854 for i, user := range s.Users { 855 if user.CurrentUser { 856 s.Users[i].Username = stochastikVars.User.AuthUsername 857 s.Users[i].Hostname = stochastikVars.User.AuthHostname 858 } 859 } 860 861 for _, role := range s.Roles { 862 exists, err := userExists(e.ctx, role.Username, role.Hostname) 863 if err != nil { 864 return err 865 } 866 if !exists { 867 return ErrCannotUser.GenWithStackByArgs("GRANT ROLE", role.String()) 868 } 869 } 870 for _, user := range s.Users { 871 exists, err := userExists(e.ctx, user.Username, user.Hostname) 872 if err != nil { 873 return err 874 } 875 if !exists { 876 return ErrCannotUser.GenWithStackByArgs("GRANT ROLE", user.String()) 877 } 878 } 879 880 restrictedCtx, err := e.getSysStochastik() 881 if err != nil { 882 return err 883 } 884 defer e.releaseSysStochastik(restrictedCtx) 885 sqlInterlockingDirectorate := restrictedCtx.(sqlexec.ALLEGROSQLInterlockingDirectorate) 886 887 // begin a transaction to insert role graph edges. 888 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "begin"); err != nil { 889 return err 890 } 891 892 for _, user := range s.Users { 893 for _, role := range s.Roles { 894 allegrosql := fmt.Sprintf(`INSERT IGNORE INTO %s.%s (FROM_HOST, FROM_USER, TO_HOST, TO_USER) VALUES ('%s','%s','%s','%s')`, allegrosql.SystemDB, allegrosql.RoleEdgeBlock, role.Hostname, role.Username, user.Hostname, user.Username) 895 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), allegrosql); err != nil { 896 logutil.BgLogger().Error(fmt.Sprintf("Error occur when executing %s", allegrosql)) 897 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "rollback"); err != nil { 898 return err 899 } 900 return ErrCannotUser.GenWithStackByArgs("GRANT ROLE", user.String()) 901 } 902 } 903 } 904 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "commit"); err != nil { 905 return err 906 } 907 petri.GetPetri(e.ctx).NotifyUFIDelatePrivilege(e.ctx) 908 return nil 909 } 910 911 func (e *SimpleInterDirc) executeDropUser(s *ast.DropUserStmt) error { 912 // Check privileges. 913 // Check `CREATE USER` privilege. 914 if !config.GetGlobalConfig().Security.SkipGrantBlock { 915 checker := privilege.GetPrivilegeManager(e.ctx) 916 if checker == nil { 917 return errors.New("miss privilege checker") 918 } 919 activeRoles := e.ctx.GetStochastikVars().ActiveRoles 920 if !checker.RequestVerification(activeRoles, allegrosql.SystemDB, allegrosql.UserBlock, "", allegrosql.DeletePriv) { 921 if s.IsDropRole { 922 if !checker.RequestVerification(activeRoles, "", "", "", allegrosql.DropRolePriv) && 923 !checker.RequestVerification(activeRoles, "", "", "", allegrosql.CreateUserPriv) { 924 return embedded.ErrSpecificAccessDenied.GenWithStackByArgs("DROP ROLE or CREATE USER") 925 } 926 } 927 if !s.IsDropRole && !checker.RequestVerification(activeRoles, "", "", "", allegrosql.CreateUserPriv) { 928 return embedded.ErrSpecificAccessDenied.GenWithStackByArgs("CREATE USER") 929 } 930 } 931 } 932 933 failedUsers := make([]string, 0, len(s.UserList)) 934 sysStochastik, err := e.getSysStochastik() 935 defer e.releaseSysStochastik(sysStochastik) 936 if err != nil { 937 return err 938 } 939 sqlInterlockingDirectorate := sysStochastik.(sqlexec.ALLEGROSQLInterlockingDirectorate) 940 941 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "begin"); err != nil { 942 return err 943 } 944 945 for _, user := range s.UserList { 946 exists, err := userExists(e.ctx, user.Username, user.Hostname) 947 if err != nil { 948 return err 949 } 950 if !exists { 951 if s.IfExists { 952 e.ctx.GetStochastikVars().StmtCtx.AppendNote(schemareplicant.ErrUserDropExists.GenWithStackByArgs(user)) 953 } else { 954 failedUsers = append(failedUsers, user.String()) 955 break 956 } 957 } 958 959 // begin a transaction to delete a user. 960 allegrosql := fmt.Sprintf(`DELETE FROM %s.%s WHERE Host = '%s' and User = '%s';`, allegrosql.SystemDB, allegrosql.UserBlock, user.Hostname, user.Username) 961 if _, err = sqlInterlockingDirectorate.InterDircute(context.Background(), allegrosql); err != nil { 962 failedUsers = append(failedUsers, user.String()) 963 break 964 } 965 966 // delete privileges from allegrosql.global_priv 967 allegrosql = fmt.Sprintf(`DELETE FROM %s.%s WHERE Host = '%s' and User = '%s';`, allegrosql.SystemDB, allegrosql.GlobalPrivBlock, user.Hostname, user.Username) 968 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), allegrosql); err != nil { 969 failedUsers = append(failedUsers, user.String()) 970 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "rollback"); err != nil { 971 return err 972 } 973 continue 974 } 975 976 // delete privileges from allegrosql.EDB 977 allegrosql = fmt.Sprintf(`DELETE FROM %s.%s WHERE Host = '%s' and User = '%s';`, allegrosql.SystemDB, allegrosql.DBBlock, user.Hostname, user.Username) 978 if _, err = sqlInterlockingDirectorate.InterDircute(context.Background(), allegrosql); err != nil { 979 failedUsers = append(failedUsers, user.String()) 980 break 981 } 982 983 // delete privileges from allegrosql.blocks_priv 984 allegrosql = fmt.Sprintf(`DELETE FROM %s.%s WHERE Host = '%s' and User = '%s';`, allegrosql.SystemDB, allegrosql.BlockPrivBlock, user.Hostname, user.Username) 985 if _, err = sqlInterlockingDirectorate.InterDircute(context.Background(), allegrosql); err != nil { 986 failedUsers = append(failedUsers, user.String()) 987 break 988 } 989 990 // delete relationship from allegrosql.role_edges 991 allegrosql = fmt.Sprintf(`DELETE FROM %s.%s WHERE TO_HOST = '%s' and TO_USER = '%s';`, allegrosql.SystemDB, allegrosql.RoleEdgeBlock, user.Hostname, user.Username) 992 if _, err = sqlInterlockingDirectorate.InterDircute(context.Background(), allegrosql); err != nil { 993 failedUsers = append(failedUsers, user.String()) 994 break 995 } 996 997 allegrosql = fmt.Sprintf(`DELETE FROM %s.%s WHERE FROM_HOST = '%s' and FROM_USER = '%s';`, allegrosql.SystemDB, allegrosql.RoleEdgeBlock, user.Hostname, user.Username) 998 if _, err = sqlInterlockingDirectorate.InterDircute(context.Background(), allegrosql); err != nil { 999 failedUsers = append(failedUsers, user.String()) 1000 break 1001 } 1002 1003 // delete relationship from allegrosql.default_roles 1004 allegrosql = fmt.Sprintf(`DELETE FROM %s.%s WHERE DEFAULT_ROLE_HOST = '%s' and DEFAULT_ROLE_USER = '%s';`, allegrosql.SystemDB, allegrosql.DefaultRoleBlock, user.Hostname, user.Username) 1005 if _, err = sqlInterlockingDirectorate.InterDircute(context.Background(), allegrosql); err != nil { 1006 failedUsers = append(failedUsers, user.String()) 1007 break 1008 } 1009 1010 allegrosql = fmt.Sprintf(`DELETE FROM %s.%s WHERE HOST = '%s' and USER = '%s';`, allegrosql.SystemDB, allegrosql.DefaultRoleBlock, user.Hostname, user.Username) 1011 if _, err = sqlInterlockingDirectorate.InterDircute(context.Background(), allegrosql); err != nil { 1012 failedUsers = append(failedUsers, user.String()) 1013 break 1014 } 1015 //TODO: need delete defCausumns_priv once we implement defCausumns_priv functionality. 1016 } 1017 1018 if len(failedUsers) == 0 { 1019 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "commit"); err != nil { 1020 return err 1021 } 1022 } else { 1023 if _, err := sqlInterlockingDirectorate.InterDircute(context.Background(), "rollback"); err != nil { 1024 return err 1025 } 1026 if s.IsDropRole { 1027 return ErrCannotUser.GenWithStackByArgs("DROP ROLE", strings.Join(failedUsers, ",")) 1028 } 1029 return ErrCannotUser.GenWithStackByArgs("DROP USER", strings.Join(failedUsers, ",")) 1030 } 1031 petri.GetPetri(e.ctx).NotifyUFIDelatePrivilege(e.ctx) 1032 return nil 1033 } 1034 1035 func userExists(ctx stochastikctx.Context, name string, host string) (bool, error) { 1036 allegrosql := fmt.Sprintf(`SELECT * FROM %s.%s WHERE User='%s' AND Host='%s';`, allegrosql.SystemDB, allegrosql.UserBlock, name, host) 1037 rows, _, err := ctx.(sqlexec.RestrictedALLEGROSQLInterlockingDirectorate).InterDircRestrictedALLEGROSQL(allegrosql) 1038 if err != nil { 1039 return false, err 1040 } 1041 return len(rows) > 0, nil 1042 } 1043 1044 func (e *SimpleInterDirc) executeSetPwd(s *ast.SetPwdStmt) error { 1045 var u, h string 1046 if s.User == nil { 1047 if e.ctx.GetStochastikVars().User == nil { 1048 return errors.New("Stochastik error is empty") 1049 } 1050 u = e.ctx.GetStochastikVars().User.AuthUsername 1051 h = e.ctx.GetStochastikVars().User.AuthHostname 1052 } else { 1053 checker := privilege.GetPrivilegeManager(e.ctx) 1054 activeRoles := e.ctx.GetStochastikVars().ActiveRoles 1055 if checker != nil && !checker.RequestVerification(activeRoles, "", "", "", allegrosql.SuperPriv) { 1056 return ErrDBaccessDenied.GenWithStackByArgs(u, h, "allegrosql") 1057 } 1058 u = s.User.Username 1059 h = s.User.Hostname 1060 } 1061 exists, err := userExists(e.ctx, u, h) 1062 if err != nil { 1063 return err 1064 } 1065 if !exists { 1066 return errors.Trace(ErrPasswordNoMatch) 1067 } 1068 1069 // uFIDelate allegrosql.user 1070 allegrosql := fmt.Sprintf(`UFIDelATE %s.%s SET authentication_string='%s' WHERE User='%s' AND Host='%s';`, allegrosql.SystemDB, allegrosql.UserBlock, auth.EncodePassword(s.Password), u, h) 1071 _, _, err = e.ctx.(sqlexec.RestrictedALLEGROSQLInterlockingDirectorate).InterDircRestrictedALLEGROSQL(allegrosql) 1072 petri.GetPetri(e.ctx).NotifyUFIDelatePrivilege(e.ctx) 1073 return err 1074 } 1075 1076 func (e *SimpleInterDirc) executeKillStmt(s *ast.KillStmt) error { 1077 conf := config.GetGlobalConfig() 1078 if s.MilevaDBExtension || conf.CompatibleKillQuery { 1079 sm := e.ctx.GetStochastikManager() 1080 if sm == nil { 1081 return nil 1082 } 1083 sm.Kill(s.ConnectionID, s.Query) 1084 } else { 1085 err := errors.New("Invalid operation. Please use 'KILL MilevaDB [CONNECTION | QUERY] connectionID' instead") 1086 e.ctx.GetStochastikVars().StmtCtx.AppendWarning(err) 1087 } 1088 return nil 1089 } 1090 1091 func (e *SimpleInterDirc) executeFlush(s *ast.FlushStmt) error { 1092 switch s.Tp { 1093 case ast.FlushBlocks: 1094 if s.ReadLock { 1095 return errors.New("FLUSH TABLES WITH READ LOCK is not supported. Please use @@milevadb_snapshot") 1096 } 1097 case ast.FlushPrivileges: 1098 // If skip-grant-causet is configured, do not flush privileges. 1099 // Because LoadPrivilegeLoop does not run and the privilege Handle is nil, 1100 // Call dom.PrivilegeHandle().UFIDelate would panic. 1101 if config.GetGlobalConfig().Security.SkipGrantBlock { 1102 return nil 1103 } 1104 1105 dom := petri.GetPetri(e.ctx) 1106 sysStochastikPool := dom.SysStochastikPool() 1107 ctx, err := sysStochastikPool.Get() 1108 if err != nil { 1109 return err 1110 } 1111 defer sysStochastikPool.Put(ctx) 1112 err = dom.PrivilegeHandle().UFIDelate(ctx.(stochastikctx.Context)) 1113 return err 1114 case ast.FlushMilevaDBPlugin: 1115 dom := petri.GetPetri(e.ctx) 1116 for _, pluginName := range s.Plugins { 1117 err := plugin.NotifyFlush(dom, pluginName) 1118 if err != nil { 1119 return err 1120 } 1121 } 1122 } 1123 return nil 1124 } 1125 1126 func (e *SimpleInterDirc) executeAlterInstance(s *ast.AlterInstanceStmt) error { 1127 if s.ReloadTLS { 1128 logutil.BgLogger().Info("execute reload tls", zap.Bool("NoRollbackOnError", s.NoRollbackOnError)) 1129 sm := e.ctx.GetStochastikManager() 1130 tlsCfg, err := soliton.LoadTLSCertificates( 1131 variable.SysVars["ssl_ca"].Value, 1132 variable.SysVars["ssl_key"].Value, 1133 variable.SysVars["ssl_cert"].Value, 1134 ) 1135 if err != nil { 1136 if !s.NoRollbackOnError || config.GetGlobalConfig().Security.RequireSecureTransport { 1137 return err 1138 } 1139 logutil.BgLogger().Warn("reload TLS fail but keep working without TLS due to 'no rollback on error'") 1140 } 1141 sm.UFIDelateTLSConfig(tlsCfg) 1142 } 1143 return nil 1144 } 1145 1146 func (e *SimpleInterDirc) executeDropStats(s *ast.DropStatsStmt) error { 1147 h := petri.GetPetri(e.ctx).StatsHandle() 1148 err := h.DeleteBlockStatsFromKV(s.Block.BlockInfo.ID) 1149 if err != nil { 1150 return err 1151 } 1152 return h.UFIDelate(schemareplicant.GetSchemaReplicant(e.ctx)) 1153 } 1154 1155 func (e *SimpleInterDirc) autoNewTxn() bool { 1156 switch e.Statement.(type) { 1157 case *ast.CreateUserStmt, *ast.AlterUserStmt, *ast.DropUserStmt: 1158 return true 1159 } 1160 return false 1161 } 1162 1163 func (e *SimpleInterDirc) executeShutdown(s *ast.ShutdownStmt) error { 1164 sessVars := e.ctx.GetStochastikVars() 1165 logutil.BgLogger().Info("execute shutdown memex", zap.Uint64("conn", sessVars.ConnectionID)) 1166 p, err := os.FindProcess(os.Getpid()) 1167 if err != nil { 1168 return err 1169 } 1170 1171 // Call with async 1172 go asyncDelayShutdown(p, time.Second) 1173 1174 return nil 1175 } 1176 1177 // #14239 - https://github.com/whtcorpsinc/milevadb/issues/14239 1178 // Need repair 'shutdown' command behavior. 1179 // Response of MilevaDB is different to MyALLEGROSQL. 1180 // This function need to run with async perceptron, otherwise it will causet main coroutine 1181 func asyncDelayShutdown(p *os.Process, delay time.Duration) { 1182 time.Sleep(delay) 1183 err := p.Kill() 1184 if err != nil { 1185 panic(err) 1186 } 1187 } 1188 1189 func (e *SimpleInterDirc) executeCreateStatistics(s *ast.CreateStatisticsStmt) (err error) { 1190 // Not support Cardinality and Dependency statistics type for now. 1191 if s.StatsType == ast.StatsTypeCardinality || s.StatsType == ast.StatsTypeDependency { 1192 return terror.ClassOptimizer.New(allegrosql.ErrInternal, allegrosql.MyALLEGROSQLErrName[allegrosql.ErrInternal]).GenWithStack("Cardinality and Dependency statistics types are not supported") 1193 } 1194 if _, ok := e.is.SchemaByName(s.Block.Schema); !ok { 1195 return schemareplicant.ErrDatabaseNotExists.GenWithStackByArgs(s.Block.Schema) 1196 } 1197 t, err := e.is.BlockByName(s.Block.Schema, s.Block.Name) 1198 if err != nil { 1199 return schemareplicant.ErrBlockNotExists.GenWithStackByArgs(s.Block.Schema, s.Block.Name) 1200 } 1201 tblInfo := t.Meta() 1202 defCausIDs := make([]int64, 0, 2) 1203 // Check whether defCausumns exist. 1204 for _, defCausName := range s.DeferredCausets { 1205 defCaus := causet.FindDefCaus(t.VisibleDefCauss(), defCausName.Name.L) 1206 if defCaus == nil { 1207 return terror.ClassDBS.New(allegrosql.ErrKeyDeferredCausetDoesNotExits, allegrosql.MyALLEGROSQLErrName[allegrosql.ErrKeyDeferredCausetDoesNotExits]).GenWithStack("defCausumn does not exist: %s", defCausName.Name.L) 1208 } 1209 if s.StatsType == ast.StatsTypeCorrelation && tblInfo.PKIsHandle && allegrosql.HasPriKeyFlag(defCaus.Flag) { 1210 warn := errors.New("No need to create correlation statistics on the integer primary key defCausumn") 1211 e.ctx.GetStochastikVars().StmtCtx.AppendWarning(warn) 1212 return nil 1213 } 1214 defCausIDs = append(defCausIDs, defCaus.ID) 1215 } 1216 if len(defCausIDs) != 2 && (s.StatsType == ast.StatsTypeCorrelation || s.StatsType == ast.StatsTypeDependency) { 1217 return terror.ClassOptimizer.New(allegrosql.ErrInternal, allegrosql.MyALLEGROSQLErrName[allegrosql.ErrInternal]).GenWithStack("Only support Correlation and Dependency statistics types on 2 defCausumns") 1218 } 1219 if len(defCausIDs) < 1 && s.StatsType == ast.StatsTypeCardinality { 1220 return terror.ClassOptimizer.New(allegrosql.ErrInternal, allegrosql.MyALLEGROSQLErrName[allegrosql.ErrInternal]).GenWithStack("Only support Cardinality statistics type on at least 2 defCausumns") 1221 } 1222 // TODO: check whether covering index exists for cardinality / dependency types. 1223 1224 // Call utilities of statistics.Handle to modify system blocks instead of doing DML directly, 1225 // because locking in Handle can guarantee the correctness of `version` in system blocks. 1226 return petri.GetPetri(e.ctx).StatsHandle().InsertExtendedStats(s.StatsName, s.Block.Schema.L, defCausIDs, int(s.StatsType), tblInfo.ID, s.IfNotExists) 1227 } 1228 1229 func (e *SimpleInterDirc) executeDropStatistics(s *ast.DropStatisticsStmt) error { 1230 EDB := e.ctx.GetStochastikVars().CurrentDB 1231 if EDB == "" { 1232 return embedded.ErrNoDB 1233 } 1234 // Call utilities of statistics.Handle to modify system blocks instead of doing DML directly, 1235 // because locking in Handle can guarantee the correctness of `version` in system blocks. 1236 return petri.GetPetri(e.ctx).StatsHandle().MarkExtendedStatsDeleted(s.StatsName, EDB, -1) 1237 } 1238 1239 func (e *SimpleInterDirc) executeAdminReloadStatistics(s *ast.AdminStmt) error { 1240 if s.Tp != ast.AdminReloadStatistics { 1241 return terror.ClassOptimizer.New(allegrosql.ErrInternal, allegrosql.MyALLEGROSQLErrName[allegrosql.ErrInternal]).GenWithStack("This AdminStmt is not ADMIN RELOAD STATISTICS") 1242 } 1243 return petri.GetPetri(e.ctx).StatsHandle().ReloadExtendedStatistics() 1244 }