github.com/matrixorigin/matrixone@v0.7.0/pkg/frontend/session.go (about) 1 // Copyright 2021 Matrix Origin 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package frontend 16 17 import ( 18 "bytes" 19 "context" 20 "fmt" 21 "runtime" 22 "strings" 23 "sync" 24 "time" 25 26 "github.com/google/uuid" 27 "github.com/matrixorigin/matrixone/pkg/catalog" 28 "github.com/matrixorigin/matrixone/pkg/common/moerr" 29 "github.com/matrixorigin/matrixone/pkg/common/mpool" 30 moruntime "github.com/matrixorigin/matrixone/pkg/common/runtime" 31 "github.com/matrixorigin/matrixone/pkg/config" 32 "github.com/matrixorigin/matrixone/pkg/container/batch" 33 "github.com/matrixorigin/matrixone/pkg/container/vector" 34 "github.com/matrixorigin/matrixone/pkg/defines" 35 "github.com/matrixorigin/matrixone/pkg/logutil" 36 "github.com/matrixorigin/matrixone/pkg/objectio" 37 logservicepb "github.com/matrixorigin/matrixone/pkg/pb/logservice" 38 "github.com/matrixorigin/matrixone/pkg/pb/plan" 39 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 40 plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan" 41 "github.com/matrixorigin/matrixone/pkg/sql/util" 42 "github.com/matrixorigin/matrixone/pkg/txn/client" 43 "github.com/matrixorigin/matrixone/pkg/txn/clock" 44 "github.com/matrixorigin/matrixone/pkg/txn/storage/memorystorage" 45 "github.com/matrixorigin/matrixone/pkg/util/errutil" 46 "github.com/matrixorigin/matrixone/pkg/util/metric" 47 "github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace" 48 "github.com/matrixorigin/matrixone/pkg/vm/engine" 49 "github.com/matrixorigin/matrixone/pkg/vm/engine/memoryengine" 50 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/moengine" 51 "github.com/matrixorigin/matrixone/pkg/vm/process" 52 ) 53 54 const MaxPrepareNumberInOneSession = 64 55 56 // TODO: this variable should be configure by set variable 57 const MoDefaultErrorCount = 64 58 59 type ShowStatementType int 60 61 const ( 62 NotShowStatement ShowStatementType = 0 63 ShowColumns ShowStatementType = 1 64 ShowTableStatus ShowStatementType = 2 65 ) 66 67 type TxnHandler struct { 68 storage engine.Engine 69 txnClient TxnClient 70 ses *Session 71 txn TxnOperator 72 mu sync.Mutex 73 entryMu sync.Mutex 74 } 75 76 func InitTxnHandler(storage engine.Engine, txnClient TxnClient) *TxnHandler { 77 h := &TxnHandler{ 78 storage: &engine.EntireEngine{Engine: storage}, 79 txnClient: txnClient, 80 } 81 return h 82 } 83 84 // we don't need to lock. TxnHandler is holded by one session. 85 func (th *TxnHandler) SetTempEngine(te engine.Engine) { 86 ee := th.storage.(*engine.EntireEngine) 87 ee.TempEngine = te 88 } 89 90 type profileType uint8 91 92 const ( 93 profileTypeAccountWithName profileType = 1 << 0 94 profileTypeAccountWithId = 1 << 1 95 profileTypeSessionId = 1 << 2 96 profileTypeConnectionWithId = 1 << 3 97 profileTypeConnectionWithIp = 1 << 4 98 99 profileTypeAll = profileTypeAccountWithName | profileTypeAccountWithId | 100 profileTypeSessionId | profileTypeConnectionWithId | profileTypeConnectionWithIp 101 102 profileTypeConcise = profileTypeConnectionWithId 103 ) 104 105 type Session struct { 106 // account id 107 accountId uint32 108 109 //protocol layer 110 protocol Protocol 111 112 //cmd from the client 113 cmd CommandType 114 115 //for test 116 mrs *MysqlResultSet 117 118 // mpool 119 mp *mpool.MPool 120 121 pu *config.ParameterUnit 122 123 isInternal bool 124 125 data [][]interface{} 126 ep *ExportParam 127 showStmtType ShowStatementType 128 129 txnHandler *TxnHandler 130 txnCompileCtx *TxnCompilerContext 131 storage engine.Engine 132 sql string 133 134 sysVars map[string]interface{} 135 userDefinedVars map[string]interface{} 136 gSysVars *GlobalSystemVariables 137 138 //the server status 139 serverStatus uint16 140 141 //the option bits 142 optionBits uint32 143 144 prepareStmts map[string]*PrepareStmt 145 lastStmtId uint32 146 147 requestCtx context.Context 148 149 //it gets the result set from the pipeline and send it to the client 150 outputCallback func(interface{}, *batch.Batch) error 151 152 //all the result set of executing the sql in background task 153 allResultSet []*MysqlResultSet 154 155 tenant *TenantInfo 156 157 uuid uuid.UUID 158 159 timeZone *time.Location 160 161 priv *privilege 162 163 errInfo *errInfo 164 165 //fromRealUser distinguish the sql that the user inputs from the one 166 //that the internal or background program executes 167 fromRealUser bool 168 169 cache *privilegeCache 170 171 profiles [8]string 172 173 mu sync.Mutex 174 175 flag bool 176 lastInsertID uint64 177 178 skipAuth bool 179 180 sqlSourceType string 181 182 InitTempEngine bool 183 184 tempTablestorage *memorystorage.Storage 185 186 isBackgroundSession bool 187 188 tStmt *motrace.StatementInfo 189 190 ast tree.Statement 191 192 rs *plan.ResultColDef 193 194 QueryId []string 195 196 blockIdx int 197 198 p *plan.Plan 199 200 limitResultSize float64 // MB 201 202 curResultSize float64 // MB 203 204 createdTime time.Time 205 206 expiredTime time.Time 207 208 planCache *planCache 209 210 autoIncrCaches defines.AutoIncrCaches 211 } 212 213 // The update version. Four function. 214 func (ses *Session) SetAutoIncrCaches(autocaches defines.AutoIncrCaches) { 215 ses.mu.Lock() 216 defer ses.mu.Unlock() 217 ses.autoIncrCaches = autocaches 218 } 219 220 func (ses *Session) GetAutoIncrCaches() defines.AutoIncrCaches { 221 ses.mu.Lock() 222 defer ses.mu.Unlock() 223 return ses.autoIncrCaches 224 } 225 226 const saveQueryIdCnt = 10 227 228 func (ses *Session) pushQueryId(uuid string) { 229 if len(ses.QueryId) > saveQueryIdCnt { 230 ses.QueryId = ses.QueryId[1:] 231 } 232 ses.QueryId = append(ses.QueryId, uuid) 233 } 234 235 // Clean up all resources hold by the session. As of now, the mpool 236 func (ses *Session) Dispose() { 237 if ses.flag { 238 mp := ses.GetMemPool() 239 mpool.DeleteMPool(mp) 240 ses.SetMemPool(mp) 241 } 242 ses.cleanCache() 243 } 244 245 type errInfo struct { 246 codes []uint16 247 msgs []string 248 maxCnt int 249 } 250 251 func (e *errInfo) push(code uint16, msg string) { 252 if e.maxCnt > 0 && len(e.codes) > e.maxCnt { 253 e.codes = e.codes[1:] 254 e.msgs = e.msgs[1:] 255 } 256 e.codes = append(e.codes, code) 257 e.msgs = append(e.msgs, msg) 258 } 259 260 func (e *errInfo) length() int { 261 return len(e.codes) 262 } 263 264 func NewSession(proto Protocol, mp *mpool.MPool, pu *config.ParameterUnit, gSysVars *GlobalSystemVariables, flag bool) *Session { 265 txnHandler := InitTxnHandler(pu.StorageEngine, pu.TxnClient) 266 ses := &Session{ 267 protocol: proto, 268 mp: mp, 269 pu: pu, 270 ep: &ExportParam{ 271 ExportParam: &tree.ExportParam{ 272 Outfile: false, 273 Fields: &tree.Fields{}, 274 Lines: &tree.Lines{}, 275 }, 276 }, 277 txnHandler: txnHandler, 278 //TODO:fix database name after the catalog is ready 279 txnCompileCtx: InitTxnCompilerContext(txnHandler, proto.GetDatabaseName()), 280 storage: &engine.EntireEngine{Engine: pu.StorageEngine}, 281 gSysVars: gSysVars, 282 283 serverStatus: 0, 284 optionBits: 0, 285 286 outputCallback: getDataFromPipeline, 287 timeZone: time.Local, 288 errInfo: &errInfo{ 289 codes: make([]uint16, 0, MoDefaultErrorCount), 290 msgs: make([]string, 0, MoDefaultErrorCount), 291 maxCnt: MoDefaultErrorCount, 292 }, 293 cache: &privilegeCache{}, 294 blockIdx: 0, 295 planCache: newPlanCache(100), 296 } 297 if flag { 298 ses.sysVars = gSysVars.CopySysVarsToSession() 299 ses.userDefinedVars = make(map[string]interface{}) 300 ses.prepareStmts = make(map[string]*PrepareStmt) 301 } 302 ses.flag = flag 303 ses.uuid, _ = uuid.NewUUID() 304 ses.SetOptionBits(OPTION_AUTOCOMMIT) 305 ses.GetTxnCompileCtx().SetSession(ses) 306 ses.GetTxnHandler().SetSession(ses) 307 308 var err error 309 if ses.mp == nil { 310 // If no mp, we create one for session. Use GuestMmuLimitation as cap. 311 // fixed pool size can be another param, or should be computed from cap, 312 // but here, too lazy, just use Mid. 313 // 314 // XXX MPOOL 315 // We don't have a way to close a session, so the only sane way of creating 316 // a mpool is to use NoFixed 317 ses.mp, err = mpool.NewMPool("pipeline-"+ses.GetUUIDString(), pu.SV.GuestMmuLimitation, mpool.NoFixed) 318 if err != nil { 319 panic(err) 320 } 321 } 322 323 runtime.SetFinalizer(ses, func(ss *Session) { 324 ss.Dispose() 325 }) 326 return ses 327 } 328 329 // BackgroundSession executing the sql in background 330 type BackgroundSession struct { 331 *Session 332 cancel context.CancelFunc 333 } 334 335 // NewBackgroundSession generates an independent background session executing the sql 336 func NewBackgroundSession(ctx context.Context, mp *mpool.MPool, PU *config.ParameterUnit, gSysVars *GlobalSystemVariables, autoincrcaches defines.AutoIncrCaches) *BackgroundSession { 337 ses := NewSession(&FakeProtocol{}, mp, PU, gSysVars, false) 338 ses.SetOutputCallback(fakeDataSetFetcher) 339 ses.SetAutoIncrCaches(autoincrcaches) 340 if stmt := motrace.StatementFromContext(ctx); stmt != nil { 341 logutil.Infof("session uuid: %s -> background session uuid: %s", uuid.UUID(stmt.SessionID).String(), ses.uuid.String()) 342 } 343 cancelBackgroundCtx, cancelBackgroundFunc := context.WithCancel(ctx) 344 ses.SetRequestContext(cancelBackgroundCtx) 345 ses.SetBackgroundSession(true) 346 backSes := &BackgroundSession{ 347 Session: ses, 348 cancel: cancelBackgroundFunc, 349 } 350 return backSes 351 } 352 353 func (bgs *BackgroundSession) Close() { 354 if bgs.cancel != nil { 355 bgs.cancel() 356 } 357 358 if bgs.Session != nil { 359 bgs.Session.ep = nil 360 bgs.Session.errInfo.codes = nil 361 bgs.Session.errInfo.msgs = nil 362 bgs.Session.errInfo = nil 363 bgs.Session.cache.invalidate() 364 bgs.Session.cache = nil 365 bgs.Session.txnCompileCtx = nil 366 bgs.Session.txnHandler = nil 367 bgs.Session.gSysVars = nil 368 } 369 bgs = nil 370 } 371 372 func (ses *Session) GetIncBlockIdx() int { 373 ses.blockIdx++ 374 return ses.blockIdx 375 } 376 377 func (ses *Session) ResetBlockIdx() { 378 ses.blockIdx = 0 379 } 380 381 func (ses *Session) SetBackgroundSession(b bool) { 382 ses.mu.Lock() 383 defer ses.mu.Unlock() 384 ses.isBackgroundSession = b 385 } 386 387 func (ses *Session) IsBackgroundSession() bool { 388 ses.mu.Lock() 389 defer ses.mu.Unlock() 390 return ses.isBackgroundSession 391 } 392 393 func (ses *Session) cachePlan(sql string, stmts []tree.Statement, plans []*plan.Plan) { 394 ses.mu.Lock() 395 defer ses.mu.Unlock() 396 ses.planCache.cache(sql, stmts, plans) 397 } 398 399 func (ses *Session) getCachedPlan(sql string) *cachedPlan { 400 ses.mu.Lock() 401 defer ses.mu.Unlock() 402 return ses.planCache.get(sql) 403 } 404 405 func (ses *Session) isCached(sql string) bool { 406 ses.mu.Lock() 407 defer ses.mu.Unlock() 408 return ses.planCache.isCached(sql) 409 } 410 411 func (ses *Session) cleanCache() { 412 ses.mu.Lock() 413 defer ses.mu.Unlock() 414 ses.planCache.clean() 415 } 416 417 func (ses *Session) setSkipCheckPrivilege(b bool) { 418 ses.mu.Lock() 419 defer ses.mu.Unlock() 420 ses.skipAuth = b 421 } 422 423 func (ses *Session) skipCheckPrivilege() bool { 424 ses.mu.Lock() 425 defer ses.mu.Unlock() 426 return ses.skipAuth 427 } 428 429 func (ses *Session) makeProfile(profileTyp profileType) { 430 ses.mu.Lock() 431 defer ses.mu.Unlock() 432 var mask profileType 433 var profile string 434 account := ses.tenant 435 for i := uint8(0); i < 8; i++ { 436 mask = 1 << i 437 switch mask & profileTyp { 438 case profileTypeAccountWithName: 439 if account != nil { 440 profile = fmt.Sprintf("account: %s user: %s role: %s", account.GetTenant(), account.GetUser(), account.GetDefaultRole()) 441 } 442 case profileTypeAccountWithId: 443 if account != nil { 444 profile = fmt.Sprintf("accountId: %d userId: %d roleId: %d", account.GetTenantID(), account.GetUserID(), account.GetDefaultRoleID()) 445 } 446 case profileTypeSessionId: 447 profile = "sessionId " + ses.uuid.String() 448 case profileTypeConnectionWithId: 449 if ses.protocol != nil { 450 profile = fmt.Sprintf("connectionId %d", ses.protocol.ConnectionID()) 451 } 452 case profileTypeConnectionWithIp: 453 if ses.protocol != nil { 454 h, p, _, _ := ses.protocol.Peer() 455 profile = "client " + h + ":" + p 456 } 457 default: 458 profile = "" 459 } 460 ses.profiles[i] = profile 461 } 462 } 463 464 func (ses *Session) MakeProfile() { 465 ses.makeProfile(profileTypeAll) 466 } 467 468 func (ses *Session) getProfile(profileTyp profileType) string { 469 ses.mu.Lock() 470 defer ses.mu.Unlock() 471 var mask profileType 472 sb := bytes.Buffer{} 473 for i := uint8(0); i < 8; i++ { 474 mask = 1 << i 475 if mask&profileTyp != 0 { 476 if sb.Len() != 0 { 477 sb.WriteByte(' ') 478 } 479 sb.WriteString(ses.profiles[i]) 480 } 481 } 482 return sb.String() 483 } 484 485 func (ses *Session) GetConciseProfile() string { 486 return ses.getProfile(profileTypeConcise) 487 } 488 489 func (ses *Session) GetCompleteProfile() string { 490 return ses.getProfile(profileTypeAll) 491 } 492 493 func (ses *Session) IfInitedTempEngine() bool { 494 ses.mu.Lock() 495 defer ses.mu.Unlock() 496 return ses.InitTempEngine 497 } 498 499 func (ses *Session) GetTempTableStorage() *memorystorage.Storage { 500 if ses.tempTablestorage == nil { 501 panic("temp table storage is not initialized") 502 } 503 return ses.tempTablestorage 504 } 505 506 func (ses *Session) SetTempTableStorage(ck clock.Clock) (*logservicepb.DNStore, error) { 507 // Without concurrency, there is no potential for data competition 508 509 // Arbitrary value is OK since it's single sharded. Let's use 0xbeef 510 // suggested by @reusee 511 shard := logservicepb.DNShardInfo{ 512 ShardID: 0xbeef, 513 ReplicaID: 0xbeef, 514 } 515 shards := []logservicepb.DNShardInfo{ 516 shard, 517 } 518 // Arbitrary value is OK, for more information about TEMPORARY_TABLE_DN_ADDR, please refer to the comment in defines/const.go 519 dnAddr := defines.TEMPORARY_TABLE_DN_ADDR 520 dnStore := logservicepb.DNStore{ 521 UUID: uuid.NewString(), 522 ServiceAddress: dnAddr, 523 Shards: shards, 524 } 525 526 ms, err := memorystorage.NewMemoryStorage( 527 mpool.MustNewZero(), 528 ck, 529 memoryengine.RandomIDGenerator, 530 ) 531 if err != nil { 532 return nil, err 533 } 534 ses.tempTablestorage = ms 535 return &dnStore, nil 536 } 537 538 func (ses *Session) GetPrivilegeCache() *privilegeCache { 539 ses.mu.Lock() 540 defer ses.mu.Unlock() 541 return ses.cache 542 } 543 544 func (ses *Session) InvalidatePrivilegeCache() { 545 ses.mu.Lock() 546 defer ses.mu.Unlock() 547 ses.cache.invalidate() 548 } 549 550 // GetBackgroundExec generates a background executor 551 func (ses *Session) GetBackgroundExec(ctx context.Context) BackgroundExec { 552 return NewBackgroundHandler(ctx, ses.GetMemPool(), ses.GetParameterUnit(), ses.autoIncrCaches) 553 } 554 555 func (ses *Session) GetIsInternal() bool { 556 ses.mu.Lock() 557 defer ses.mu.Unlock() 558 return ses.isInternal 559 } 560 561 func (ses *Session) SetMemPool(mp *mpool.MPool) { 562 ses.mu.Lock() 563 defer ses.mu.Unlock() 564 ses.mp = mp 565 } 566 567 func (ses *Session) GetMemPool() *mpool.MPool { 568 ses.mu.Lock() 569 defer ses.mu.Unlock() 570 return ses.mp 571 } 572 573 func (ses *Session) GetParameterUnit() *config.ParameterUnit { 574 ses.mu.Lock() 575 defer ses.mu.Unlock() 576 return ses.pu 577 } 578 579 func (ses *Session) GetData() [][]interface{} { 580 ses.mu.Lock() 581 defer ses.mu.Unlock() 582 return ses.data 583 } 584 585 func (ses *Session) SetData(data [][]interface{}) { 586 ses.mu.Lock() 587 defer ses.mu.Unlock() 588 ses.data = data 589 } 590 591 func (ses *Session) AppendData(row []interface{}) { 592 ses.mu.Lock() 593 defer ses.mu.Unlock() 594 ses.data = append(ses.data, row) 595 } 596 597 func (ses *Session) SetExportParam(ep *tree.ExportParam) { 598 ses.mu.Lock() 599 defer ses.mu.Unlock() 600 ses.ep.ExportParam = ep 601 } 602 603 func (ses *Session) GetExportParam() *ExportParam { 604 ses.mu.Lock() 605 defer ses.mu.Unlock() 606 return ses.ep 607 } 608 609 func (ses *Session) SetShowStmtType(sst ShowStatementType) { 610 ses.mu.Lock() 611 defer ses.mu.Unlock() 612 ses.showStmtType = sst 613 } 614 615 func (ses *Session) GetShowStmtType() ShowStatementType { 616 ses.mu.Lock() 617 defer ses.mu.Unlock() 618 return ses.showStmtType 619 } 620 621 func (ses *Session) GetOutputCallback() func(interface{}, *batch.Batch) error { 622 ses.mu.Lock() 623 defer ses.mu.Unlock() 624 return ses.outputCallback 625 } 626 627 func (ses *Session) GetErrInfo() *errInfo { 628 ses.mu.Lock() 629 defer ses.mu.Unlock() 630 return ses.errInfo 631 } 632 633 func (ses *Session) GenNewStmtId() uint32 { 634 ses.mu.Lock() 635 defer ses.mu.Unlock() 636 ses.lastStmtId = ses.lastStmtId + 1 637 return ses.lastStmtId 638 } 639 640 func (ses *Session) GetLastStmtId() uint32 { 641 ses.mu.Lock() 642 defer ses.mu.Unlock() 643 return ses.lastStmtId 644 } 645 646 func (ses *Session) SetLastInsertID(num uint64) { 647 ses.mu.Lock() 648 defer ses.mu.Unlock() 649 ses.lastInsertID = num 650 } 651 652 func (ses *Session) GetLastInsertID() uint64 { 653 ses.mu.Lock() 654 defer ses.mu.Unlock() 655 return ses.lastInsertID 656 } 657 658 func (ses *Session) SetRequestContext(reqCtx context.Context) { 659 ses.mu.Lock() 660 defer ses.mu.Unlock() 661 ses.requestCtx = reqCtx 662 } 663 664 func (ses *Session) GetRequestContext() context.Context { 665 ses.mu.Lock() 666 defer ses.mu.Unlock() 667 return ses.requestCtx 668 } 669 670 func (ses *Session) SetTimeZone(loc *time.Location) { 671 ses.mu.Lock() 672 defer ses.mu.Unlock() 673 ses.timeZone = loc 674 } 675 676 func (ses *Session) GetTimeZone() *time.Location { 677 ses.mu.Lock() 678 defer ses.mu.Unlock() 679 return ses.timeZone 680 } 681 682 func (ses *Session) SetCmd(cmd CommandType) { 683 ses.mu.Lock() 684 defer ses.mu.Unlock() 685 ses.cmd = cmd 686 } 687 688 func (ses *Session) GetCmd() CommandType { 689 ses.mu.Lock() 690 defer ses.mu.Unlock() 691 return ses.cmd 692 } 693 694 func (ses *Session) SetMysqlResultSet(mrs *MysqlResultSet) { 695 ses.mu.Lock() 696 defer ses.mu.Unlock() 697 ses.mrs = mrs 698 } 699 700 func (ses *Session) GetMysqlResultSet() *MysqlResultSet { 701 ses.mu.Lock() 702 defer ses.mu.Unlock() 703 return ses.mrs 704 } 705 706 func (ses *Session) AppendMysqlResultSetOfBackgroundTask(mrs *MysqlResultSet) { 707 ses.mu.Lock() 708 defer ses.mu.Unlock() 709 ses.allResultSet = append(ses.allResultSet, mrs) 710 } 711 712 func (ses *Session) GetAllMysqlResultSet() []*MysqlResultSet { 713 ses.mu.Lock() 714 defer ses.mu.Unlock() 715 return ses.allResultSet 716 } 717 718 func (ses *Session) ClearAllMysqlResultSet() { 719 ses.mu.Lock() 720 defer ses.mu.Unlock() 721 if ses.allResultSet != nil { 722 ses.allResultSet = ses.allResultSet[:0] 723 } 724 } 725 726 func (ses *Session) GetTenantInfo() *TenantInfo { 727 ses.mu.Lock() 728 defer ses.mu.Unlock() 729 return ses.tenant 730 } 731 732 // GetTenantName return tenant name according to GetTenantInfo and stmt. 733 // 734 // With stmt = nil, should be only called in TxnHandler.NewTxn, TxnHandler.CommitTxn, TxnHandler.RollbackTxn 735 func (ses *Session) GetTenantName(stmt tree.Statement) string { 736 tenant := sysAccountName 737 if ses.GetTenantInfo() != nil && (stmt == nil || !IsPrepareStatement(stmt)) { 738 tenant = ses.GetTenantInfo().GetTenant() 739 } 740 return tenant 741 } 742 743 func (ses *Session) GetUUID() []byte { 744 ses.mu.Lock() 745 defer ses.mu.Unlock() 746 return ses.uuid[:] 747 } 748 749 func (ses *Session) GetUUIDString() string { 750 ses.mu.Lock() 751 defer ses.mu.Unlock() 752 return ses.uuid.String() 753 } 754 755 func (ses *Session) SetTenantInfo(ti *TenantInfo) { 756 ses.mu.Lock() 757 defer ses.mu.Unlock() 758 ses.tenant = ti 759 } 760 761 func (ses *Session) SetPrepareStmt(name string, prepareStmt *PrepareStmt) error { 762 ses.mu.Lock() 763 defer ses.mu.Unlock() 764 if _, ok := ses.prepareStmts[name]; !ok { 765 if len(ses.prepareStmts) >= MaxPrepareNumberInOneSession { 766 return moerr.NewInvalidState(ses.requestCtx, "too many prepared statement, max %d", MaxPrepareNumberInOneSession) 767 } 768 } 769 ses.prepareStmts[name] = prepareStmt 770 return nil 771 } 772 773 func (ses *Session) GetPrepareStmt(name string) (*PrepareStmt, error) { 774 ses.mu.Lock() 775 defer ses.mu.Unlock() 776 if prepareStmt, ok := ses.prepareStmts[name]; ok { 777 return prepareStmt, nil 778 } 779 return nil, moerr.NewInvalidState(ses.requestCtx, "prepared statement '%s' does not exist", name) 780 } 781 782 func (ses *Session) RemovePrepareStmt(name string) { 783 ses.mu.Lock() 784 defer ses.mu.Unlock() 785 delete(ses.prepareStmts, name) 786 } 787 788 func (ses *Session) SetSysVar(name string, value interface{}) { 789 ses.mu.Lock() 790 defer ses.mu.Unlock() 791 ses.sysVars[name] = value 792 } 793 794 func (ses *Session) GetSysVar(name string) interface{} { 795 ses.mu.Lock() 796 defer ses.mu.Unlock() 797 return ses.sysVars[name] 798 } 799 800 func (ses *Session) GetSysVars() map[string]interface{} { 801 ses.mu.Lock() 802 defer ses.mu.Unlock() 803 return ses.sysVars 804 } 805 806 func (ses *Session) GetGlobalSysVars() *GlobalSystemVariables { 807 ses.mu.Lock() 808 defer ses.mu.Unlock() 809 return ses.gSysVars 810 } 811 812 // SetGlobalVar sets the value of system variable in global. 813 // used by SET GLOBAL 814 func (ses *Session) SetGlobalVar(name string, value interface{}) error { 815 return ses.GetGlobalSysVars().SetGlobalSysVar(ses.GetRequestContext(), name, value) 816 } 817 818 // GetGlobalVar gets this value of the system variable in global 819 func (ses *Session) GetGlobalVar(name string) (interface{}, error) { 820 gSysVars := ses.GetGlobalSysVars() 821 if def, val, ok := gSysVars.GetGlobalSysVar(name); ok { 822 if def.GetScope() == ScopeSession { 823 //empty 824 return nil, moerr.NewInternalError(ses.GetRequestContext(), errorSystemVariableSessionEmpty()) 825 } 826 return val, nil 827 } 828 return nil, moerr.NewInternalError(ses.GetRequestContext(), errorSystemVariableDoesNotExist()) 829 } 830 831 func (ses *Session) GetTxnCompileCtx() *TxnCompilerContext { 832 ses.mu.Lock() 833 defer ses.mu.Unlock() 834 return ses.txnCompileCtx 835 } 836 837 // SetSessionVar sets the value of system variable in session 838 func (ses *Session) SetSessionVar(name string, value interface{}) error { 839 gSysVars := ses.GetGlobalSysVars() 840 if def, _, ok := gSysVars.GetGlobalSysVar(name); ok { 841 if def.GetScope() == ScopeGlobal { 842 return moerr.NewInternalError(ses.GetRequestContext(), errorSystemVariableIsGlobal()) 843 } 844 //scope session & both 845 if !def.GetDynamic() { 846 return moerr.NewInternalError(ses.GetRequestContext(), errorSystemVariableIsReadOnly()) 847 } 848 849 cv, err := def.GetType().Convert(value) 850 if err != nil { 851 errutil.ReportError(ses.GetRequestContext(), err) 852 return err 853 } 854 855 if def.UpdateSessVar == nil { 856 ses.SetSysVar(def.GetName(), cv) 857 } else { 858 return def.UpdateSessVar(ses, ses.GetSysVars(), def.GetName(), cv) 859 } 860 } else { 861 return moerr.NewInternalError(ses.GetRequestContext(), errorSystemVariableDoesNotExist()) 862 } 863 return nil 864 } 865 866 // GetSessionVar gets this value of the system variable in session 867 func (ses *Session) GetSessionVar(name string) (interface{}, error) { 868 gSysVars := ses.GetGlobalSysVars() 869 if def, gVal, ok := gSysVars.GetGlobalSysVar(name); ok { 870 ciname := strings.ToLower(name) 871 if def.GetScope() == ScopeGlobal { 872 return gVal, nil 873 } 874 return ses.GetSysVar(ciname), nil 875 } else { 876 return nil, moerr.NewInternalError(ses.GetRequestContext(), errorSystemVariableDoesNotExist()) 877 } 878 } 879 880 func (ses *Session) CopyAllSessionVars() map[string]interface{} { 881 ses.mu.Lock() 882 defer ses.mu.Unlock() 883 cp := make(map[string]interface{}) 884 for k, v := range ses.sysVars { 885 cp[k] = v 886 } 887 return cp 888 } 889 890 // SetUserDefinedVar sets the user defined variable to the value in session 891 func (ses *Session) SetUserDefinedVar(name string, value interface{}) error { 892 ses.mu.Lock() 893 defer ses.mu.Unlock() 894 ses.userDefinedVars[strings.ToLower(name)] = value 895 return nil 896 } 897 898 // GetUserDefinedVar gets value of the user defined variable 899 func (ses *Session) GetUserDefinedVar(name string) (SystemVariableType, interface{}, error) { 900 ses.mu.Lock() 901 defer ses.mu.Unlock() 902 val, ok := ses.userDefinedVars[strings.ToLower(name)] 903 if !ok { 904 return SystemVariableNullType{}, nil, nil 905 } 906 return InitSystemVariableStringType(name), val, nil 907 } 908 909 func (ses *Session) GetTxnHandler() *TxnHandler { 910 ses.mu.Lock() 911 defer ses.mu.Unlock() 912 return ses.txnHandler 913 } 914 915 func (ses *Session) SetSql(sql string) { 916 ses.mu.Lock() 917 defer ses.mu.Unlock() 918 ses.sql = sql 919 } 920 921 func (ses *Session) GetSql() string { 922 ses.mu.Lock() 923 defer ses.mu.Unlock() 924 return ses.sql 925 } 926 927 func (ses *Session) IsTaeEngine() bool { 928 ses.mu.Lock() 929 defer ses.mu.Unlock() 930 e, isEntire := ses.storage.(*engine.EntireEngine) 931 if isEntire { 932 _, ok := e.Engine.(moengine.TxnEngine) 933 return ok 934 } else { 935 _, ok := ses.storage.(moengine.TxnEngine) 936 return ok 937 } 938 } 939 940 func (ses *Session) IsEntireEngine() bool { 941 ses.mu.Lock() 942 defer ses.mu.Unlock() 943 _, isEntire := ses.storage.(*engine.EntireEngine) 944 if isEntire { 945 return true 946 } else { 947 return false 948 } 949 } 950 951 func (ses *Session) GetStorage() engine.Engine { 952 ses.mu.Lock() 953 defer ses.mu.Unlock() 954 return ses.storage 955 } 956 957 func (ses *Session) SetTempEngine(ctx context.Context, te engine.Engine) error { 958 ses.mu.Lock() 959 defer ses.mu.Unlock() 960 ee := ses.storage.(*engine.EntireEngine) 961 ee.TempEngine = te 962 ses.requestCtx = ctx 963 return nil 964 } 965 966 func (ses *Session) GetDatabaseName() string { 967 return ses.GetMysqlProtocol().GetDatabaseName() 968 } 969 970 func (ses *Session) SetDatabaseName(db string) { 971 ses.GetMysqlProtocol().SetDatabaseName(db) 972 ses.GetTxnCompileCtx().SetDatabase(db) 973 } 974 975 func (ses *Session) DatabaseNameIsEmpty() bool { 976 return len(ses.GetDatabaseName()) == 0 977 } 978 979 func (ses *Session) GetUserName() string { 980 return ses.GetMysqlProtocol().GetUserName() 981 } 982 983 func (ses *Session) SetUserName(uname string) { 984 ses.GetMysqlProtocol().SetUserName(uname) 985 } 986 987 func (ses *Session) GetConnectionID() uint32 { 988 return ses.GetMysqlProtocol().ConnectionID() 989 } 990 991 func (ses *Session) GetPeer() (string, string) { 992 rh, rp, _, _ := ses.GetMysqlProtocol().Peer() 993 return rh, rp 994 } 995 996 func (ses *Session) SetOptionBits(bit uint32) { 997 ses.mu.Lock() 998 defer ses.mu.Unlock() 999 ses.optionBits |= bit 1000 } 1001 1002 func (ses *Session) ClearOptionBits(bit uint32) { 1003 ses.mu.Lock() 1004 defer ses.mu.Unlock() 1005 ses.optionBits &= ^bit 1006 } 1007 1008 func (ses *Session) OptionBitsIsSet(bit uint32) bool { 1009 ses.mu.Lock() 1010 defer ses.mu.Unlock() 1011 return ses.optionBits&bit != 0 1012 } 1013 1014 func (ses *Session) SetServerStatus(bit uint16) { 1015 ses.mu.Lock() 1016 defer ses.mu.Unlock() 1017 ses.serverStatus |= bit 1018 } 1019 1020 func (ses *Session) ClearServerStatus(bit uint16) { 1021 ses.mu.Lock() 1022 defer ses.mu.Unlock() 1023 ses.serverStatus &= ^bit 1024 } 1025 1026 func (ses *Session) ServerStatusIsSet(bit uint16) bool { 1027 ses.mu.Lock() 1028 defer ses.mu.Unlock() 1029 return ses.serverStatus&bit != 0 1030 } 1031 1032 /* 1033 InMultiStmtTransactionMode checks the session is in multi-statement transaction mode. 1034 OPTION_NOT_AUTOCOMMIT: After the autocommit is off, the multi-statement transaction is 1035 started implicitly by the first statement of the transaction. 1036 OPTION_BEGIN: Whenever the autocommit is on or off, the multi-statement transaction is 1037 started explicitly by the BEGIN statement. 1038 1039 But it does not denote the transaction is active or not. 1040 1041 Cases | set Autocommit = 1/0 | BEGIN statement | 1042 --------------------------------------------------- 1043 Case1 1 Yes 1044 Case2 1 No 1045 Case3 0 Yes 1046 Case4 0 No 1047 --------------------------------------------------- 1048 1049 If it is Case1,Case3,Cass4, Then 1050 1051 InMultiStmtTransactionMode returns true. 1052 Also, the bit SERVER_STATUS_IN_TRANS will be set. 1053 1054 If it is Case2, Then 1055 1056 InMultiStmtTransactionMode returns false 1057 */ 1058 func (ses *Session) InMultiStmtTransactionMode() bool { 1059 return ses.OptionBitsIsSet(OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) 1060 } 1061 1062 /* 1063 InActiveMultiStmtTransaction checks the session is in multi-statement transaction mode 1064 and there is an active transaction. 1065 1066 But sometimes, the session does not start an active transaction even if it is in multi- 1067 statement transaction mode. 1068 1069 For example: there is no active transaction. 1070 set autocommit = 0; 1071 select 1; 1072 1073 For example: there is an active transaction. 1074 begin; 1075 select 1; 1076 1077 When the statement starts the multi-statement transaction(select * from table), this flag 1078 won't be set until we access the tables. 1079 */ 1080 func (ses *Session) InActiveMultiStmtTransaction() bool { 1081 return ses.ServerStatusIsSet(SERVER_STATUS_IN_TRANS) 1082 } 1083 1084 /* 1085 TxnStart starts the transaction implicitly and idempotent 1086 1087 When it is in multi-statement transaction mode: 1088 1089 Set SERVER_STATUS_IN_TRANS bit; 1090 Starts a new transaction if there is none. Reuse the current transaction if there is one. 1091 1092 When it is not in single statement transaction mode: 1093 1094 Starts a new transaction if there is none. Reuse the current transaction if there is one. 1095 */ 1096 func (ses *Session) TxnStart() error { 1097 var err error 1098 if ses.InMultiStmtTransactionMode() { 1099 ses.SetServerStatus(SERVER_STATUS_IN_TRANS) 1100 } 1101 if !ses.GetTxnHandler().IsValidTxn() { 1102 err = ses.GetTxnHandler().NewTxn() 1103 } 1104 return err 1105 } 1106 1107 /* 1108 TxnCommitSingleStatement commits the single statement transaction. 1109 1110 Cases | set Autocommit = 1/0 | BEGIN statement | 1111 --------------------------------------------------- 1112 Case1 1 Yes 1113 Case2 1 No 1114 Case3 0 Yes 1115 Case4 0 No 1116 --------------------------------------------------- 1117 1118 If it is Case1,Case3,Cass4, Then 1119 1120 InMultiStmtTransactionMode returns true. 1121 Also, the bit SERVER_STATUS_IN_TRANS will be set. 1122 1123 If it is Case2, Then 1124 1125 InMultiStmtTransactionMode returns false 1126 */ 1127 func (ses *Session) TxnCommitSingleStatement(stmt tree.Statement) error { 1128 var err error 1129 /* 1130 Commit Rules: 1131 1, if it is in single-statement mode: 1132 it commits. 1133 2, if it is in multi-statement mode: 1134 if the statement is the one can be executed in the active transaction, 1135 the transaction need to be committed at the end of the statement. 1136 */ 1137 if !ses.InMultiStmtTransactionMode() || 1138 ses.InActiveTransaction() && NeedToBeCommittedInActiveTransaction(stmt) { 1139 err = ses.GetTxnHandler().CommitTxn() 1140 ses.ClearServerStatus(SERVER_STATUS_IN_TRANS) 1141 ses.ClearOptionBits(OPTION_BEGIN) 1142 } 1143 return err 1144 } 1145 1146 /* 1147 TxnRollbackSingleStatement rollbacks the single statement transaction. 1148 1149 Cases | set Autocommit = 1/0 | BEGIN statement | 1150 --------------------------------------------------- 1151 Case1 1 Yes 1152 Case2 1 No 1153 Case3 0 Yes 1154 Case4 0 No 1155 --------------------------------------------------- 1156 1157 If it is Case1,Case3,Cass4, Then 1158 1159 InMultiStmtTransactionMode returns true. 1160 Also, the bit SERVER_STATUS_IN_TRANS will be set. 1161 1162 If it is Case2, Then 1163 1164 InMultiStmtTransactionMode returns false 1165 */ 1166 func (ses *Session) TxnRollbackSingleStatement(stmt tree.Statement) error { 1167 var err error 1168 /* 1169 Rollback Rules: 1170 1, if it is in single-statement mode (Case2): 1171 it rollbacks. 1172 2, if it is in multi-statement mode (Case1,Case3,Case4): 1173 the transaction need to be rollback at the end of the statement. 1174 (every error will abort the transaction.) 1175 */ 1176 if !ses.InMultiStmtTransactionMode() || 1177 ses.InActiveTransaction() { 1178 err = ses.GetTxnHandler().RollbackTxn() 1179 ses.ClearServerStatus(SERVER_STATUS_IN_TRANS) 1180 ses.ClearOptionBits(OPTION_BEGIN) 1181 } 1182 return err 1183 } 1184 1185 /* 1186 TxnBegin begins a new transaction. 1187 It commits the current transaction implicitly. 1188 */ 1189 func (ses *Session) TxnBegin() error { 1190 var err error 1191 if ses.InMultiStmtTransactionMode() { 1192 ses.ClearServerStatus(SERVER_STATUS_IN_TRANS) 1193 err = ses.GetTxnHandler().CommitTxn() 1194 } 1195 ses.ClearOptionBits(OPTION_BEGIN) 1196 if err != nil { 1197 /* 1198 fix issue 6024. 1199 When we get a w-w conflict during commit the txn, 1200 we convert the error into a readable error. 1201 */ 1202 if moerr.IsMoErrCode(err, moerr.ErrTxnWWConflict) { 1203 return moerr.NewInternalError(ses.GetRequestContext(), writeWriteConflictsErrorInfo()) 1204 } 1205 return err 1206 } 1207 ses.SetOptionBits(OPTION_BEGIN) 1208 ses.SetServerStatus(SERVER_STATUS_IN_TRANS) 1209 err = ses.GetTxnHandler().NewTxn() 1210 return err 1211 } 1212 1213 // TxnCommit commits the current transaction. 1214 func (ses *Session) TxnCommit() error { 1215 var err error 1216 ses.ClearServerStatus(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY) 1217 err = ses.GetTxnHandler().CommitTxn() 1218 ses.ClearServerStatus(SERVER_STATUS_IN_TRANS) 1219 ses.ClearOptionBits(OPTION_BEGIN) 1220 return err 1221 } 1222 1223 // TxnRollback rollbacks the current transaction. 1224 func (ses *Session) TxnRollback() error { 1225 var err error 1226 ses.ClearServerStatus(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY) 1227 err = ses.GetTxnHandler().RollbackTxn() 1228 ses.ClearOptionBits(OPTION_BEGIN) 1229 return err 1230 } 1231 1232 /* 1233 InActiveTransaction checks if it is in an active transaction. 1234 */ 1235 func (ses *Session) InActiveTransaction() bool { 1236 if ses.InActiveMultiStmtTransaction() { 1237 return true 1238 } else { 1239 return ses.GetTxnHandler().IsValidTxn() 1240 } 1241 } 1242 1243 /* 1244 SetAutocommit sets the value of the system variable 'autocommit'. 1245 1246 The rule is that we can not execute the statement 'set parameter = value' in 1247 an active transaction whichever it is started by BEGIN or in 'set autocommit = 0;'. 1248 */ 1249 func (ses *Session) SetAutocommit(on bool) error { 1250 if ses.InActiveTransaction() { 1251 return moerr.NewInternalError(ses.requestCtx, parameterModificationInTxnErrorInfo()) 1252 } 1253 if on { 1254 ses.ClearOptionBits(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT) 1255 ses.SetServerStatus(SERVER_STATUS_AUTOCOMMIT) 1256 } else { 1257 ses.ClearServerStatus(SERVER_STATUS_AUTOCOMMIT) 1258 ses.SetOptionBits(OPTION_NOT_AUTOCOMMIT) 1259 } 1260 return nil 1261 } 1262 1263 func (ses *Session) SetOutputCallback(callback func(interface{}, *batch.Batch) error) { 1264 ses.mu.Lock() 1265 defer ses.mu.Unlock() 1266 ses.outputCallback = callback 1267 } 1268 1269 func (ses *Session) skipAuthForSpecialUser() bool { 1270 if ses.GetTenantInfo() != nil { 1271 ok, _, _ := isSpecialUser(ses.GetTenantInfo().GetUser()) 1272 return ok 1273 } 1274 return false 1275 } 1276 1277 // AuthenticateUser verifies the password of the user. 1278 func (ses *Session) AuthenticateUser(userInput string) ([]byte, error) { 1279 var defaultRoleID int64 1280 var defaultRole string 1281 var tenant *TenantInfo 1282 var err error 1283 var rsset []ExecResult 1284 var tenantID int64 1285 var userID int64 1286 var pwd, accountStatus string 1287 var pwdBytes []byte 1288 var isSpecial bool 1289 var specialAccount *TenantInfo 1290 1291 //Get tenant info 1292 tenant, err = GetTenantInfo(ses.GetRequestContext(), userInput) 1293 if err != nil { 1294 return nil, err 1295 } 1296 1297 ses.SetTenantInfo(tenant) 1298 ses.MakeProfile() 1299 sessionProfile := ses.GetConciseProfile() 1300 1301 logDebugf(sessionProfile, "check special user") 1302 // check the special user for initilization 1303 isSpecial, pwdBytes, specialAccount = isSpecialUser(tenant.GetUser()) 1304 if isSpecial && specialAccount.IsMoAdminRole() { 1305 ses.SetTenantInfo(specialAccount) 1306 return pwdBytes, nil 1307 } 1308 1309 ses.SetTenantInfo(tenant) 1310 1311 //step1 : check tenant exists or not in SYS tenant context 1312 sysTenantCtx := context.WithValue(ses.GetRequestContext(), defines.TenantIDKey{}, uint32(sysAccountID)) 1313 sysTenantCtx = context.WithValue(sysTenantCtx, defines.UserIDKey{}, uint32(rootID)) 1314 sysTenantCtx = context.WithValue(sysTenantCtx, defines.RoleIDKey{}, uint32(moAdminRoleID)) 1315 sqlForCheckTenant := getSqlForCheckTenant(tenant.GetTenant()) 1316 pu := ses.GetParameterUnit() 1317 mp := ses.GetMemPool() 1318 logDebugf(sessionProfile, "check tenant %s exists", tenant) 1319 rsset, err = executeSQLInBackgroundSession(sysTenantCtx, mp, pu, sqlForCheckTenant, ses.GetAutoIncrCaches()) 1320 if err != nil { 1321 return nil, err 1322 } 1323 if !execResultArrayHasData(rsset) { 1324 return nil, moerr.NewInternalError(sysTenantCtx, "there is no tenant %s", tenant.GetTenant()) 1325 } 1326 1327 //account id 1328 tenantID, err = rsset[0].GetInt64(sysTenantCtx, 0, 0) 1329 if err != nil { 1330 return nil, err 1331 } 1332 1333 //account status 1334 accountStatus, err = rsset[0].GetString(sysTenantCtx, 0, 2) 1335 if err != nil { 1336 return nil, err 1337 } 1338 1339 if strings.ToLower(accountStatus) == tree.AccountStatusSuspend.String() { 1340 return nil, moerr.NewInternalError(sysTenantCtx, "Account %s is suspended", tenant.GetTenant()) 1341 } 1342 1343 tenant.SetTenantID(uint32(tenantID)) 1344 //step2 : check user exists or not in general tenant. 1345 //step3 : get the password of the user 1346 1347 tenantCtx := context.WithValue(ses.GetRequestContext(), defines.TenantIDKey{}, uint32(tenantID)) 1348 1349 logDebugf(sessionProfile, "check user of %s exists", tenant) 1350 //Get the password of the user in an independent session 1351 sqlForPasswordOfUser := getSqlForPasswordOfUser(tenant.GetUser()) 1352 rsset, err = executeSQLInBackgroundSession(tenantCtx, mp, pu, sqlForPasswordOfUser, ses.GetAutoIncrCaches()) 1353 if err != nil { 1354 return nil, err 1355 } 1356 if !execResultArrayHasData(rsset) { 1357 return nil, moerr.NewInternalError(tenantCtx, "there is no user %s", tenant.GetUser()) 1358 } 1359 1360 userID, err = rsset[0].GetInt64(tenantCtx, 0, 0) 1361 if err != nil { 1362 return nil, err 1363 } 1364 1365 pwd, err = rsset[0].GetString(tenantCtx, 0, 1) 1366 if err != nil { 1367 return nil, err 1368 } 1369 1370 //the default_role in the mo_user table. 1371 //the default_role is always valid. public or other valid role. 1372 defaultRoleID, err = rsset[0].GetInt64(tenantCtx, 0, 2) 1373 if err != nil { 1374 return nil, err 1375 } 1376 1377 tenant.SetUserID(uint32(userID)) 1378 tenant.SetDefaultRoleID(uint32(defaultRoleID)) 1379 1380 /* 1381 login case 1: tenant:user 1382 1.get the default_role of the user in mo_user 1383 1384 login case 2: tenant:user:role 1385 1.check the role has been granted to the user 1386 -yes: go on 1387 -no: error 1388 1389 */ 1390 //it denotes that there is no default role in the input 1391 if tenant.HasDefaultRole() { 1392 logDebugf(sessionProfile, "check default role of user %s.", tenant) 1393 //step4 : check role exists or not 1394 sqlForCheckRoleExists := getSqlForRoleIdOfRole(tenant.GetDefaultRole()) 1395 rsset, err = executeSQLInBackgroundSession(tenantCtx, mp, pu, sqlForCheckRoleExists, ses.GetAutoIncrCaches()) 1396 if err != nil { 1397 return nil, err 1398 } 1399 1400 if !execResultArrayHasData(rsset) { 1401 return nil, moerr.NewInternalError(tenantCtx, "there is no role %s", tenant.GetDefaultRole()) 1402 } 1403 1404 logDebugf(sessionProfile, "check granted role of user %s.", tenant) 1405 //step4.2 : check the role has been granted to the user or not 1406 sqlForRoleOfUser := getSqlForRoleOfUser(userID, tenant.GetDefaultRole()) 1407 rsset, err = executeSQLInBackgroundSession(tenantCtx, mp, pu, sqlForRoleOfUser, ses.GetAutoIncrCaches()) 1408 if err != nil { 1409 return nil, err 1410 } 1411 if !execResultArrayHasData(rsset) { 1412 return nil, moerr.NewInternalError(tenantCtx, "the role %s has not been granted to the user %s", 1413 tenant.GetDefaultRole(), tenant.GetUser()) 1414 } 1415 1416 defaultRoleID, err = rsset[0].GetInt64(tenantCtx, 0, 0) 1417 if err != nil { 1418 return nil, err 1419 } 1420 tenant.SetDefaultRoleID(uint32(defaultRoleID)) 1421 } else { 1422 logDebugf(sessionProfile, "check designated role of user %s.", tenant) 1423 //the get name of default_role from mo_role 1424 sql := getSqlForRoleNameOfRoleId(defaultRoleID) 1425 rsset, err = executeSQLInBackgroundSession(tenantCtx, mp, pu, sql, ses.GetAutoIncrCaches()) 1426 if err != nil { 1427 return nil, err 1428 } 1429 if !execResultArrayHasData(rsset) { 1430 return nil, moerr.NewInternalError(tenantCtx, "get the default role of the user %s failed", tenant.GetUser()) 1431 } 1432 1433 defaultRole, err = rsset[0].GetString(tenantCtx, 0, 0) 1434 if err != nil { 1435 return nil, err 1436 } 1437 tenant.SetDefaultRole(defaultRole) 1438 } 1439 1440 logInfo(sessionProfile, tenant.String()) 1441 1442 return []byte(pwd), nil 1443 } 1444 1445 func (ses *Session) GetPrivilege() *privilege { 1446 ses.mu.Lock() 1447 defer ses.mu.Unlock() 1448 return ses.priv 1449 } 1450 1451 func (ses *Session) SetPrivilege(priv *privilege) { 1452 ses.mu.Lock() 1453 defer ses.mu.Unlock() 1454 ses.priv = priv 1455 } 1456 1457 func (ses *Session) SetFromRealUser(b bool) { 1458 ses.mu.Lock() 1459 defer ses.mu.Unlock() 1460 ses.fromRealUser = b 1461 } 1462 1463 func (ses *Session) GetFromRealUser() bool { 1464 ses.mu.Lock() 1465 defer ses.mu.Unlock() 1466 return ses.fromRealUser 1467 } 1468 1469 func (th *TxnHandler) SetSession(ses *Session) { 1470 th.mu.Lock() 1471 defer th.mu.Unlock() 1472 th.ses = ses 1473 } 1474 1475 func (th *TxnHandler) GetTxnClient() TxnClient { 1476 th.mu.Lock() 1477 defer th.mu.Unlock() 1478 return th.txnClient 1479 } 1480 1481 // TxnClientNew creates a new txn 1482 func (th *TxnHandler) TxnClientNew() error { 1483 var err error 1484 th.mu.Lock() 1485 defer th.mu.Unlock() 1486 if th.txnClient == nil { 1487 panic("must set txn client") 1488 } 1489 1490 var opts []client.TxnOption 1491 rt := moruntime.ProcessLevelRuntime() 1492 if rt != nil { 1493 if v, ok := rt.GetGlobalVariables(moruntime.TxnOptions); ok { 1494 opts = v.([]client.TxnOption) 1495 } 1496 } 1497 1498 th.txn, err = th.txnClient.New(opts...) 1499 if err != nil { 1500 return err 1501 } 1502 if th.txn == nil { 1503 return moerr.NewInternalError(th.ses.GetRequestContext(), "TxnClientNew: txnClient new a null txn") 1504 } 1505 return err 1506 } 1507 1508 // NewTxn commits the old transaction if it existed. 1509 // Then it creates the new transaction. 1510 func (th *TxnHandler) NewTxn() error { 1511 var err error 1512 ctx := th.GetSession().GetRequestContext() 1513 if th.IsValidTxn() { 1514 err = th.CommitTxn() 1515 if err != nil { 1516 /* 1517 fix issue 6024. 1518 When we get a w-w conflict during commit the txn, 1519 we convert the error into a readable error. 1520 */ 1521 if moerr.IsMoErrCode(err, moerr.ErrTxnWWConflict) { 1522 return moerr.NewInternalError(ctx, writeWriteConflictsErrorInfo()) 1523 } 1524 return err 1525 } 1526 } 1527 th.SetInvalid() 1528 defer func() { 1529 if err != nil { 1530 tenant := th.ses.GetTenantName(nil) 1531 incTransactionErrorsCounter(tenant, metric.SQLTypeBegin) 1532 } 1533 }() 1534 err = th.TxnClientNew() 1535 if err != nil { 1536 return err 1537 } 1538 if ctx == nil { 1539 panic("context should not be nil") 1540 } 1541 storage := th.GetStorage() 1542 err = storage.New(ctx, th.GetTxnOperator()) 1543 return err 1544 } 1545 1546 // IsValidTxn checks the transaction is true or not. 1547 func (th *TxnHandler) IsValidTxn() bool { 1548 th.mu.Lock() 1549 defer th.mu.Unlock() 1550 return th.txn != nil 1551 } 1552 1553 func (th *TxnHandler) SetInvalid() { 1554 th.mu.Lock() 1555 defer th.mu.Unlock() 1556 th.txn = nil 1557 } 1558 1559 func (th *TxnHandler) GetTxnOperator() TxnOperator { 1560 th.mu.Lock() 1561 defer th.mu.Unlock() 1562 return th.txn 1563 } 1564 1565 func (th *TxnHandler) GetSession() *Session { 1566 th.mu.Lock() 1567 defer th.mu.Unlock() 1568 return th.ses 1569 } 1570 1571 func (th *TxnHandler) CommitTxn() error { 1572 th.entryMu.Lock() 1573 defer th.entryMu.Unlock() 1574 if !th.IsValidTxn() { 1575 return nil 1576 } 1577 ses := th.GetSession() 1578 sessionProfile := ses.GetConciseProfile() 1579 ctx := ses.GetRequestContext() 1580 if ctx == nil { 1581 panic("context should not be nil") 1582 } 1583 if ses.tempTablestorage != nil { 1584 ctx = context.WithValue(ctx, defines.TemporaryDN{}, ses.tempTablestorage) 1585 } 1586 storage := th.GetStorage() 1587 ctx, cancel := context.WithTimeout( 1588 ctx, 1589 storage.Hints().CommitOrRollbackTimeout, 1590 ) 1591 defer cancel() 1592 var err, err2 error 1593 defer func() { 1594 // metric count 1595 tenant := ses.GetTenantName(nil) 1596 incTransactionCounter(tenant) 1597 if err != nil { 1598 incTransactionErrorsCounter(tenant, metric.SQLTypeCommit) 1599 } 1600 }() 1601 txnOp := th.GetTxnOperator() 1602 if txnOp == nil { 1603 logErrorf(sessionProfile, "CommitTxn: txn operator is null") 1604 } 1605 1606 txnId := txnOp.Txn().DebugString() 1607 logDebugf(sessionProfile, "CommitTxn txnId:%s", txnId) 1608 defer func() { 1609 logDebugf(sessionProfile, "CommitTxn exit txnId:%s", txnId) 1610 }() 1611 if err = storage.Commit(ctx, txnOp); err != nil { 1612 th.SetInvalid() 1613 logErrorf(sessionProfile, "CommitTxn: storage commit failed. txnId:%s error:%v", txnId, err) 1614 if txnOp != nil { 1615 err2 = txnOp.Rollback(ctx) 1616 if err2 != nil { 1617 logErrorf(sessionProfile, "CommitTxn: txn operator rollback failed. txnId:%s error:%v", txnId, err2) 1618 } 1619 } 1620 return err 1621 } 1622 if txnOp != nil { 1623 err = txnOp.Commit(ctx) 1624 if err != nil { 1625 th.SetInvalid() 1626 logErrorf(sessionProfile, "CommitTxn: txn operator commit failed. txnId:%s error:%v", txnId, err) 1627 } 1628 } 1629 th.SetInvalid() 1630 return err 1631 } 1632 1633 func (th *TxnHandler) RollbackTxn() error { 1634 th.entryMu.Lock() 1635 defer th.entryMu.Unlock() 1636 if !th.IsValidTxn() { 1637 return nil 1638 } 1639 ses := th.GetSession() 1640 sessionProfile := ses.GetConciseProfile() 1641 ctx := ses.GetRequestContext() 1642 if ctx == nil { 1643 panic("context should not be nil") 1644 } 1645 if ses.tempTablestorage != nil { 1646 ctx = context.WithValue(ctx, defines.TemporaryDN{}, ses.tempTablestorage) 1647 } 1648 storage := th.GetStorage() 1649 ctx, cancel := context.WithTimeout( 1650 ctx, 1651 storage.Hints().CommitOrRollbackTimeout, 1652 ) 1653 defer cancel() 1654 var err, err2 error 1655 defer func() { 1656 // metric count 1657 tenant := ses.GetTenantName(nil) 1658 incTransactionCounter(tenant) 1659 incTransactionErrorsCounter(tenant, metric.SQLTypeOther) // exec rollback cnt 1660 if err != nil { 1661 incTransactionErrorsCounter(tenant, metric.SQLTypeRollback) 1662 } 1663 }() 1664 txnOp := th.GetTxnOperator() 1665 if txnOp == nil { 1666 logErrorf(sessionProfile, "RollbackTxn: txn operator is null") 1667 } 1668 txnId := txnOp.Txn().DebugString() 1669 logDebugf(sessionProfile, "RollbackTxn txnId:%s", txnId) 1670 defer func() { 1671 logDebugf(sessionProfile, "RollbackTxn exit txnId:%s", txnId) 1672 }() 1673 if err = storage.Rollback(ctx, txnOp); err != nil { 1674 th.SetInvalid() 1675 logErrorf(sessionProfile, "RollbackTxn: storage rollback failed. txnId:%s error:%v", txnId, err) 1676 if txnOp != nil { 1677 err2 = txnOp.Rollback(ctx) 1678 if err2 != nil { 1679 logErrorf(sessionProfile, "RollbackTxn: txn operator rollback failed. txnId:%s error:%v", txnId, err2) 1680 } 1681 } 1682 return err 1683 } 1684 if txnOp != nil { 1685 err = txnOp.Rollback(ctx) 1686 if err != nil { 1687 th.SetInvalid() 1688 logErrorf(sessionProfile, "RollbackTxn: txn operator commit failed. txnId:%s error:%v", txnId, err) 1689 } 1690 } 1691 th.SetInvalid() 1692 return err 1693 } 1694 1695 func (th *TxnHandler) GetStorage() engine.Engine { 1696 th.mu.Lock() 1697 defer th.mu.Unlock() 1698 return th.storage 1699 } 1700 1701 func (th *TxnHandler) GetTxn() (TxnOperator, error) { 1702 err := th.GetSession().TxnStart() 1703 if err != nil { 1704 logutil.Errorf("GetTxn. error:%v", err) 1705 return nil, err 1706 } 1707 return th.GetTxnOperator(), nil 1708 } 1709 1710 func (th *TxnHandler) GetTxnOnly() TxnOperator { 1711 th.mu.Lock() 1712 defer th.mu.Unlock() 1713 return th.txn 1714 } 1715 1716 var _ plan2.CompilerContext = &TxnCompilerContext{} 1717 1718 type QueryType int 1719 1720 const ( 1721 TXN_DEFAULT QueryType = iota 1722 TXN_DELETE 1723 TXN_UPDATE 1724 ) 1725 1726 type TxnCompilerContext struct { 1727 dbName string 1728 QryTyp QueryType 1729 txnHandler *TxnHandler 1730 ses *Session 1731 proc *process.Process 1732 buildAlterView bool 1733 dbOfView, nameOfView string 1734 mu sync.Mutex 1735 } 1736 1737 func (tcc *TxnCompilerContext) SetBuildingAlterView(yesOrNo bool, dbName, viewName string) { 1738 tcc.mu.Lock() 1739 defer tcc.mu.Unlock() 1740 tcc.buildAlterView = yesOrNo 1741 tcc.dbOfView = dbName 1742 tcc.nameOfView = viewName 1743 } 1744 1745 func (tcc *TxnCompilerContext) GetBuildingAlterView() (bool, string, string) { 1746 tcc.mu.Lock() 1747 defer tcc.mu.Unlock() 1748 return tcc.buildAlterView, tcc.dbOfView, tcc.nameOfView 1749 } 1750 1751 func InitTxnCompilerContext(txn *TxnHandler, db string) *TxnCompilerContext { 1752 return &TxnCompilerContext{txnHandler: txn, dbName: db, QryTyp: TXN_DEFAULT} 1753 } 1754 1755 func (tcc *TxnCompilerContext) GetQueryType() QueryType { 1756 tcc.mu.Lock() 1757 defer tcc.mu.Unlock() 1758 return tcc.QryTyp 1759 } 1760 1761 func (tcc *TxnCompilerContext) SetSession(ses *Session) { 1762 tcc.mu.Lock() 1763 defer tcc.mu.Unlock() 1764 tcc.ses = ses 1765 } 1766 1767 func (tcc *TxnCompilerContext) GetSession() *Session { 1768 tcc.mu.Lock() 1769 defer tcc.mu.Unlock() 1770 return tcc.ses 1771 } 1772 1773 func (tcc *TxnCompilerContext) GetTxnHandler() *TxnHandler { 1774 tcc.mu.Lock() 1775 defer tcc.mu.Unlock() 1776 return tcc.txnHandler 1777 } 1778 1779 func (tcc *TxnCompilerContext) GetUserName() string { 1780 tcc.mu.Lock() 1781 defer tcc.mu.Unlock() 1782 return tcc.ses.GetUserName() 1783 } 1784 1785 func (tcc *TxnCompilerContext) SetQueryType(qryTyp QueryType) { 1786 tcc.mu.Lock() 1787 defer tcc.mu.Unlock() 1788 tcc.QryTyp = qryTyp 1789 } 1790 1791 func (tcc *TxnCompilerContext) SetDatabase(db string) { 1792 tcc.mu.Lock() 1793 defer tcc.mu.Unlock() 1794 tcc.dbName = db 1795 } 1796 1797 func (tcc *TxnCompilerContext) DefaultDatabase() string { 1798 tcc.mu.Lock() 1799 defer tcc.mu.Unlock() 1800 return tcc.dbName 1801 } 1802 1803 func (tcc *TxnCompilerContext) GetRootSql() string { 1804 return tcc.GetSession().GetSql() 1805 } 1806 1807 func (tcc *TxnCompilerContext) GetAccountId() uint32 { 1808 return tcc.ses.accountId 1809 } 1810 1811 func (tcc *TxnCompilerContext) GetContext() context.Context { 1812 return tcc.ses.requestCtx 1813 } 1814 1815 func (tcc *TxnCompilerContext) DatabaseExists(name string) bool { 1816 var err error 1817 var txn TxnOperator 1818 txn, err = tcc.GetTxnHandler().GetTxn() 1819 if err != nil { 1820 return false 1821 } 1822 //open database 1823 ses := tcc.GetSession() 1824 _, err = tcc.GetTxnHandler().GetStorage().Database(ses.GetRequestContext(), name, txn) 1825 if err != nil { 1826 logErrorf(ses.GetConciseProfile(), "get database %v failed. error %v", name, err) 1827 return false 1828 } 1829 1830 return true 1831 } 1832 1833 // getRelation returns the context (maybe updated) and the relation 1834 func (tcc *TxnCompilerContext) getRelation(dbName string, tableName string) (context.Context, engine.Relation, error) { 1835 dbName, err := tcc.ensureDatabaseIsNotEmpty(dbName) 1836 if err != nil { 1837 return nil, nil, err 1838 } 1839 1840 ses := tcc.GetSession() 1841 ctx := ses.GetRequestContext() 1842 account := ses.GetTenantInfo() 1843 if isClusterTable(dbName, tableName) { 1844 //if it is the cluster table in the general account, switch into the sys account 1845 if account != nil && account.GetTenantID() != sysAccountID { 1846 ctx = context.WithValue(ctx, defines.TenantIDKey{}, uint32(sysAccountID)) 1847 } 1848 } 1849 1850 txn, err := tcc.GetTxnHandler().GetTxn() 1851 if err != nil { 1852 return nil, nil, err 1853 } 1854 1855 //open database 1856 db, err := tcc.GetTxnHandler().GetStorage().Database(ctx, dbName, txn) 1857 if err != nil { 1858 logErrorf(ses.GetConciseProfile(), "get database %v error %v", dbName, err) 1859 return nil, nil, err 1860 } 1861 1862 // tableNames, err := db.Relations(ctx) 1863 // if err != nil { 1864 // return nil, nil, err 1865 // } 1866 // logDebugf(ses.GetConciseProfile(), "dbName %v tableNames %v", dbName, tableNames) 1867 1868 //open table 1869 table, err := db.Relation(ctx, tableName) 1870 if err != nil { 1871 tmpTable, e := tcc.getTmpRelation(ctx, engine.GetTempTableName(dbName, tableName)) 1872 if e != nil { 1873 logutil.Errorf("get table %v error %v", tableName, err) 1874 return nil, nil, err 1875 } else { 1876 table = tmpTable 1877 } 1878 } 1879 return ctx, table, nil 1880 } 1881 1882 func (tcc *TxnCompilerContext) getTmpRelation(ctx context.Context, tableName string) (engine.Relation, error) { 1883 e := tcc.ses.storage 1884 txn, err := tcc.txnHandler.GetTxn() 1885 if err != nil { 1886 return nil, err 1887 } 1888 db, err := e.Database(ctx, defines.TEMPORARY_DBNAME, txn) 1889 if err != nil { 1890 logutil.Errorf("get temp database error %v", err) 1891 return nil, err 1892 } 1893 table, err := db.Relation(ctx, tableName) 1894 return table, err 1895 } 1896 1897 func (tcc *TxnCompilerContext) ensureDatabaseIsNotEmpty(dbName string) (string, error) { 1898 if len(dbName) == 0 { 1899 dbName = tcc.DefaultDatabase() 1900 } 1901 if len(dbName) == 0 { 1902 return "", moerr.NewNoDB(tcc.GetContext()) 1903 } 1904 return dbName, nil 1905 } 1906 1907 func (tcc *TxnCompilerContext) ResolveById(tableId uint64) (*plan2.ObjectRef, *plan2.TableDef) { 1908 ses := tcc.GetSession() 1909 ctx := ses.GetRequestContext() 1910 txn, err := tcc.GetTxnHandler().GetTxn() 1911 if err != nil { 1912 return nil, nil 1913 } 1914 dbName, tableName, table, err := tcc.GetTxnHandler().GetStorage().GetRelationById(ctx, txn, tableId) 1915 if err != nil { 1916 return nil, nil 1917 } 1918 return tcc.getTableDef(ctx, table, dbName, tableName) 1919 } 1920 1921 func (tcc *TxnCompilerContext) Resolve(dbName string, tableName string) (*plan2.ObjectRef, *plan2.TableDef) { 1922 dbName, err := tcc.ensureDatabaseIsNotEmpty(dbName) 1923 if err != nil { 1924 return nil, nil 1925 } 1926 ctx, table, err := tcc.getRelation(dbName, tableName) 1927 if err != nil { 1928 return nil, nil 1929 } 1930 return tcc.getTableDef(ctx, table, dbName, tableName) 1931 } 1932 1933 func (tcc *TxnCompilerContext) getTableDef(ctx context.Context, table engine.Relation, dbName, tableName string) (*plan2.ObjectRef, *plan2.TableDef) { 1934 tableId := table.GetTableID(ctx) 1935 engineDefs, err := table.TableDefs(ctx) 1936 if err != nil { 1937 return nil, nil 1938 } 1939 1940 var clusterByDef *plan2.ClusterByDef 1941 var cols []*plan2.ColDef 1942 var defs []*plan2.TableDefType 1943 var properties []*plan2.Property 1944 var TableType, Createsql string 1945 var CompositePkey *plan2.ColDef = nil 1946 var partitionInfo *plan2.PartitionByDef 1947 var viewSql *plan2.ViewDef 1948 var foreignKeys []*plan2.ForeignKeyDef 1949 var primarykey *plan2.PrimaryKeyDef 1950 var indexes []*plan2.IndexDef 1951 var refChildTbls []uint64 1952 for _, def := range engineDefs { 1953 if attr, ok := def.(*engine.AttributeDef); ok { 1954 isCPkey := util.JudgeIsCompositePrimaryKeyColumn(attr.Attr.Name) 1955 col := &plan2.ColDef{ 1956 ColId: attr.Attr.ID, 1957 Name: attr.Attr.Name, 1958 Typ: &plan2.Type{ 1959 Id: int32(attr.Attr.Type.Oid), 1960 Width: attr.Attr.Type.Width, 1961 Precision: attr.Attr.Type.Precision, 1962 Scale: attr.Attr.Type.Scale, 1963 AutoIncr: attr.Attr.AutoIncrement, 1964 Table: tableName, 1965 NotNullable: attr.Attr.Default != nil && !attr.Attr.Default.NullAbility, 1966 }, 1967 Primary: attr.Attr.Primary, 1968 Default: attr.Attr.Default, 1969 OnUpdate: attr.Attr.OnUpdate, 1970 Comment: attr.Attr.Comment, 1971 ClusterBy: attr.Attr.ClusterBy, 1972 } 1973 if isCPkey { 1974 CompositePkey = col 1975 continue 1976 } 1977 if attr.Attr.ClusterBy { 1978 clusterByDef = &plan.ClusterByDef{ 1979 Name: attr.Attr.Name, 1980 } 1981 if util.JudgeIsCompositeClusterByColumn(attr.Attr.Name) { 1982 continue 1983 } 1984 } 1985 cols = append(cols, col) 1986 } else if pro, ok := def.(*engine.PropertiesDef); ok { 1987 for _, p := range pro.Properties { 1988 switch p.Key { 1989 case catalog.SystemRelAttr_Kind: 1990 TableType = p.Value 1991 case catalog.SystemRelAttr_CreateSQL: 1992 Createsql = p.Value 1993 default: 1994 } 1995 properties = append(properties, &plan2.Property{ 1996 Key: p.Key, 1997 Value: p.Value, 1998 }) 1999 } 2000 } else if viewDef, ok := def.(*engine.ViewDef); ok { 2001 viewSql = &plan2.ViewDef{ 2002 View: viewDef.View, 2003 } 2004 } else if c, ok := def.(*engine.ConstraintDef); ok { 2005 for _, ct := range c.Cts { 2006 switch k := ct.(type) { 2007 case *engine.IndexDef: 2008 indexes = k.Indexes 2009 case *engine.ForeignKeyDef: 2010 foreignKeys = k.Fkeys 2011 case *engine.RefChildTableDef: 2012 refChildTbls = k.Tables 2013 case *engine.PrimaryKeyDef: 2014 primarykey = k.Pkey 2015 } 2016 } 2017 } else if commnetDef, ok := def.(*engine.CommentDef); ok { 2018 properties = append(properties, &plan2.Property{ 2019 Key: catalog.SystemRelAttr_Comment, 2020 Value: commnetDef.Comment, 2021 }) 2022 } else if partitionDef, ok := def.(*engine.PartitionDef); ok { 2023 p := &plan2.PartitionByDef{} 2024 err = p.UnMarshalPartitionInfo(([]byte)(partitionDef.Partition)) 2025 if err != nil { 2026 return nil, nil 2027 } 2028 partitionInfo = p 2029 } 2030 } 2031 if len(properties) > 0 { 2032 defs = append(defs, &plan2.TableDefType{ 2033 Def: &plan2.TableDef_DefType_Properties{ 2034 Properties: &plan2.PropertiesDef{ 2035 Properties: properties, 2036 }, 2037 }, 2038 }) 2039 } 2040 2041 if tcc.GetQueryType() != TXN_DEFAULT { 2042 hideKeys, err := table.GetHideKeys(ctx) 2043 if err != nil { 2044 return nil, nil 2045 } 2046 hideKey := hideKeys[0] 2047 cols = append(cols, &plan2.ColDef{ 2048 Name: hideKey.Name, 2049 Typ: &plan2.Type{ 2050 Id: int32(hideKey.Type.Oid), 2051 Width: hideKey.Type.Width, 2052 Precision: hideKey.Type.Precision, 2053 Scale: hideKey.Type.Scale, 2054 }, 2055 Primary: hideKey.Primary, 2056 }) 2057 } 2058 2059 //convert 2060 obj := &plan2.ObjectRef{ 2061 SchemaName: dbName, 2062 ObjName: tableName, 2063 } 2064 originCols := make([]*plan2.ColDef, len(cols)) 2065 for i, col := range cols { 2066 originCols[i] = plan2.DeepCopyColDef(col) 2067 } 2068 2069 tableDef := &plan2.TableDef{ 2070 TblId: tableId, 2071 Name: tableName, 2072 Cols: cols, 2073 Defs: defs, 2074 TableType: TableType, 2075 Createsql: Createsql, 2076 Pkey: primarykey, 2077 CompositePkey: CompositePkey, 2078 ViewSql: viewSql, 2079 Partition: partitionInfo, 2080 Fkeys: foreignKeys, 2081 RefChildTbls: refChildTbls, 2082 ClusterBy: clusterByDef, 2083 OriginCols: originCols, 2084 Indexes: indexes, 2085 } 2086 return obj, tableDef 2087 } 2088 2089 func (tcc *TxnCompilerContext) ResolveVariable(varName string, isSystemVar, isGlobalVar bool) (interface{}, error) { 2090 if isSystemVar { 2091 if isGlobalVar { 2092 return tcc.GetSession().GetGlobalVar(varName) 2093 } else { 2094 return tcc.GetSession().GetSessionVar(varName) 2095 } 2096 } else { 2097 _, val, err := tcc.GetSession().GetUserDefinedVar(varName) 2098 return val, err 2099 } 2100 } 2101 2102 func (tcc *TxnCompilerContext) ResolveAccountIds(accountNames []string) ([]uint32, error) { 2103 var err error 2104 var sql string 2105 var accountIds []uint32 2106 var erArray []ExecResult 2107 var targetAccountId uint64 2108 if len(accountNames) == 0 { 2109 return []uint32{}, nil 2110 } 2111 2112 dedup := make(map[string]int8) 2113 for _, name := range accountNames { 2114 dedup[name] = 1 2115 } 2116 2117 ses := tcc.GetSession() 2118 ctx := ses.GetRequestContext() 2119 bh := ses.GetBackgroundExec(ctx) 2120 defer bh.Close() 2121 2122 err = bh.Exec(ctx, "begin;") 2123 if err != nil { 2124 goto handleFailed 2125 } 2126 2127 for name := range dedup { 2128 sql = getSqlForCheckTenant(name) 2129 bh.ClearExecResultSet() 2130 err = bh.Exec(ctx, sql) 2131 if err != nil { 2132 goto handleFailed 2133 } 2134 2135 erArray, err = getResultSet(ctx, bh) 2136 if err != nil { 2137 goto handleFailed 2138 } 2139 2140 if execResultArrayHasData(erArray) { 2141 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 2142 targetAccountId, err = erArray[0].GetUint64(ctx, i, 0) 2143 if err != nil { 2144 goto handleFailed 2145 } 2146 } 2147 accountIds = append(accountIds, uint32(targetAccountId)) 2148 } else { 2149 return nil, moerr.NewInternalError(ctx, "there is no account %s", name) 2150 } 2151 } 2152 2153 err = bh.Exec(ctx, "commit;") 2154 if err != nil { 2155 goto handleFailed 2156 } 2157 return accountIds, err 2158 handleFailed: 2159 //ROLLBACK the transaction 2160 rbErr := bh.Exec(ctx, "rollback;") 2161 if rbErr != nil { 2162 return nil, rbErr 2163 } 2164 return nil, err 2165 } 2166 2167 func (tcc *TxnCompilerContext) GetPrimaryKeyDef(dbName string, tableName string) []*plan2.ColDef { 2168 dbName, err := tcc.ensureDatabaseIsNotEmpty(dbName) 2169 if err != nil { 2170 return nil 2171 } 2172 ctx, relation, err := tcc.getRelation(dbName, tableName) 2173 if err != nil { 2174 return nil 2175 } 2176 2177 priKeys, err := relation.GetPrimaryKeys(ctx) 2178 if err != nil { 2179 return nil 2180 } 2181 if len(priKeys) == 0 { 2182 return nil 2183 } 2184 2185 priDefs := make([]*plan2.ColDef, 0, len(priKeys)) 2186 for _, key := range priKeys { 2187 priDefs = append(priDefs, &plan2.ColDef{ 2188 Name: key.Name, 2189 Typ: &plan2.Type{ 2190 Id: int32(key.Type.Oid), 2191 Width: key.Type.Width, 2192 Precision: key.Type.Precision, 2193 Scale: key.Type.Scale, 2194 Size: key.Type.Size, 2195 }, 2196 Primary: key.Primary, 2197 }) 2198 } 2199 return priDefs 2200 } 2201 2202 func (tcc *TxnCompilerContext) GetHideKeyDef(dbName string, tableName string) *plan2.ColDef { 2203 dbName, err := tcc.ensureDatabaseIsNotEmpty(dbName) 2204 if err != nil { 2205 return nil 2206 } 2207 ctx, relation, err := tcc.getRelation(dbName, tableName) 2208 if err != nil { 2209 return nil 2210 } 2211 2212 hideKeys, err := relation.GetHideKeys(ctx) 2213 if err != nil { 2214 return nil 2215 } 2216 if len(hideKeys) == 0 { 2217 return nil 2218 } 2219 hideKey := hideKeys[0] 2220 2221 hideDef := &plan2.ColDef{ 2222 Name: hideKey.Name, 2223 Typ: &plan2.Type{ 2224 Id: int32(hideKey.Type.Oid), 2225 Width: hideKey.Type.Width, 2226 Precision: hideKey.Type.Precision, 2227 Scale: hideKey.Type.Scale, 2228 Size: hideKey.Type.Size, 2229 }, 2230 Primary: hideKey.Primary, 2231 } 2232 return hideDef 2233 } 2234 2235 func fixColumnName(cols []*engine.Attribute, expr *plan.Expr) { 2236 switch exprImpl := expr.Expr.(type) { 2237 case *plan.Expr_F: 2238 for _, arg := range exprImpl.F.Args { 2239 fixColumnName(cols, arg) 2240 } 2241 case *plan.Expr_Col: 2242 exprImpl.Col.Name = cols[exprImpl.Col.ColPos].Name 2243 } 2244 } 2245 2246 func (tcc *TxnCompilerContext) Stats(obj *plan2.ObjectRef, e *plan2.Expr) (stats *plan2.Stats) { 2247 2248 dbName := obj.GetSchemaName() 2249 dbName, err := tcc.ensureDatabaseIsNotEmpty(dbName) 2250 if err != nil { 2251 return 2252 } 2253 tableName := obj.GetObjName() 2254 ctx, table, err := tcc.getRelation(dbName, tableName) 2255 if err != nil { 2256 return 2257 } 2258 if e != nil { 2259 cols, _ := table.TableColumns(ctx) 2260 fixColumnName(cols, e) 2261 } 2262 stats, _ = table.Stats(ctx, e) 2263 return stats 2264 } 2265 2266 func (tcc *TxnCompilerContext) GetProcess() *process.Process { 2267 tcc.mu.Lock() 2268 defer tcc.mu.Unlock() 2269 return tcc.proc 2270 } 2271 2272 func (tcc *TxnCompilerContext) GetQueryResultMeta(uuid string) ([]*plan.ColDef, string, error) { 2273 proc := tcc.proc 2274 // get file size 2275 fs := objectio.NewObjectFS(proc.FileService, catalog.QueryResultMetaDir) 2276 dirs, err := fs.ListDir(catalog.QueryResultMetaDir) 2277 if err != nil { 2278 return nil, "", err 2279 } 2280 var size int64 = -1 2281 name := catalog.BuildQueryResultMetaName(proc.SessionInfo.Account, uuid) 2282 for _, d := range dirs { 2283 if d.Name == name { 2284 size = d.Size 2285 } 2286 } 2287 if size == -1 { 2288 return nil, "", moerr.NewQueryIdNotFound(proc.Ctx, uuid) 2289 } 2290 // read meta's meta 2291 path := catalog.BuildQueryResultMetaPath(proc.SessionInfo.Account, uuid) 2292 reader, err := objectio.NewObjectReader(path, proc.FileService) 2293 if err != nil { 2294 return nil, "", err 2295 } 2296 bs, err := reader.ReadAllMeta(proc.Ctx, size, proc.Mp()) 2297 if err != nil { 2298 return nil, "", err 2299 } 2300 idxs := make([]uint16, 2) 2301 idxs[0] = catalog.COLUMNS_IDX 2302 idxs[1] = catalog.RESULT_PATH_IDX 2303 // read meta's data 2304 iov, err := reader.Read(proc.Ctx, bs[0].GetExtent(), idxs, proc.Mp()) 2305 if err != nil { 2306 return nil, "", err 2307 } 2308 // cols 2309 vec := vector.New(catalog.MetaColTypes[catalog.COLUMNS_IDX]) 2310 if err = vec.Read(iov.Entries[0].Object.([]byte)); err != nil { 2311 return nil, "", err 2312 } 2313 def := vector.MustStrCols(vec)[0] 2314 r := &plan.ResultColDef{} 2315 if err = r.Unmarshal([]byte(def)); err != nil { 2316 return nil, "", err 2317 } 2318 // paths 2319 vec = vector.New(catalog.MetaColTypes[catalog.RESULT_PATH_IDX]) 2320 if err = vec.Read(iov.Entries[1].Object.([]byte)); err != nil { 2321 return nil, "", err 2322 } 2323 str := vector.MustStrCols(vec)[0] 2324 return r.ResultCols, str, nil 2325 } 2326 2327 func (tcc *TxnCompilerContext) SetProcess(proc *process.Process) { 2328 tcc.mu.Lock() 2329 defer tcc.mu.Unlock() 2330 tcc.proc = proc 2331 } 2332 2333 // fakeDataSetFetcher gets the result set from the pipeline and save it in the session. 2334 // It will not send the result to the client. 2335 func fakeDataSetFetcher(handle interface{}, dataSet *batch.Batch) error { 2336 if handle == nil || dataSet == nil { 2337 return nil 2338 } 2339 2340 ses := handle.(*Session) 2341 oq := newFakeOutputQueue(ses.GetMysqlResultSet()) 2342 n := vector.Length(dataSet.Vecs[0]) 2343 for j := 0; j < n; j++ { //row index 2344 if dataSet.Zs[j] <= 0 { 2345 continue 2346 } 2347 _, err := extractRowFromEveryVector(ses, dataSet, int64(j), oq) 2348 if err != nil { 2349 return err 2350 } 2351 } 2352 err := oq.flush() 2353 if err != nil { 2354 return err 2355 } 2356 ses.AppendMysqlResultSetOfBackgroundTask(ses.GetMysqlResultSet()) 2357 return nil 2358 } 2359 2360 // getResultSet extracts the result set 2361 func getResultSet(ctx context.Context, bh BackgroundExec) ([]ExecResult, error) { 2362 results := bh.GetExecResultSet() 2363 rsset := make([]ExecResult, len(results)) 2364 for i, value := range results { 2365 if er, ok := value.(ExecResult); ok { 2366 rsset[i] = er 2367 } else { 2368 return nil, moerr.NewInternalError(ctx, "it is not the type of result set") 2369 } 2370 } 2371 return rsset, nil 2372 } 2373 2374 // executeSQLInBackgroundSession executes the sql in an independent session and transaction. 2375 // It sends nothing to the client. 2376 func executeSQLInBackgroundSession(ctx context.Context, mp *mpool.MPool, pu *config.ParameterUnit, sql string, autoIncrCaches defines.AutoIncrCaches) ([]ExecResult, error) { 2377 bh := NewBackgroundHandler(ctx, mp, pu, autoIncrCaches) 2378 defer bh.Close() 2379 logutil.Debugf("background exec sql:%v", sql) 2380 err := bh.Exec(ctx, sql) 2381 logutil.Debugf("background exec sql done") 2382 if err != nil { 2383 return nil, err 2384 } 2385 2386 //get the result set 2387 //TODO: debug further 2388 //mrsArray := ses.GetAllMysqlResultSet() 2389 //for _, mrs := range mrsArray { 2390 // for i := uint64(0); i < mrs.GetRowCount(); i++ { 2391 // row, err := mrs.GetRow(i) 2392 // if err != nil { 2393 // return err 2394 // } 2395 // logutil.Info(row) 2396 // } 2397 //} 2398 2399 return getResultSet(ctx, bh) 2400 } 2401 2402 type BackgroundHandler struct { 2403 mce *MysqlCmdExecutor 2404 ses *BackgroundSession 2405 } 2406 2407 var NewBackgroundHandler = func(ctx context.Context, mp *mpool.MPool, pu *config.ParameterUnit, autoincrcaches defines.AutoIncrCaches) BackgroundExec { 2408 bh := &BackgroundHandler{ 2409 mce: NewMysqlCmdExecutor(), 2410 ses: NewBackgroundSession(ctx, mp, pu, GSysVariables, autoincrcaches), 2411 } 2412 return bh 2413 } 2414 2415 func (bh *BackgroundHandler) Close() { 2416 bh.mce.Close() 2417 bh.ses.Close() 2418 } 2419 2420 func (bh *BackgroundHandler) Exec(ctx context.Context, sql string) error { 2421 bh.mce.SetSession(bh.ses.Session) 2422 if ctx == nil { 2423 ctx = bh.ses.GetRequestContext() 2424 } else { 2425 bh.ses.SetRequestContext(ctx) 2426 } 2427 bh.mce.ChooseDoQueryFunc(bh.ses.GetParameterUnit().SV.EnableDoComQueryInProgress) 2428 //logutil.Debugf("-->bh:%s", sql) 2429 err := bh.mce.GetDoQueryFunc()(ctx, sql) 2430 if err != nil { 2431 return err 2432 } 2433 return err 2434 } 2435 2436 func (bh *BackgroundHandler) GetExecResultSet() []interface{} { 2437 mrs := bh.ses.GetAllMysqlResultSet() 2438 ret := make([]interface{}, len(mrs)) 2439 for i, mr := range mrs { 2440 ret[i] = mr 2441 } 2442 return ret 2443 } 2444 2445 func (bh *BackgroundHandler) ClearExecResultSet() { 2446 bh.ses.ClearAllMysqlResultSet() 2447 }