github.com/matrixorigin/matrixone@v1.2.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 "sync/atomic" 25 "time" 26 27 "github.com/matrixorigin/matrixone/pkg/logutil" 28 29 "github.com/google/uuid" 30 31 "github.com/matrixorigin/matrixone/pkg/bootstrap/versions" 32 "github.com/matrixorigin/matrixone/pkg/common/buffer" 33 "github.com/matrixorigin/matrixone/pkg/common/moerr" 34 "github.com/matrixorigin/matrixone/pkg/common/mpool" 35 "github.com/matrixorigin/matrixone/pkg/container/batch" 36 "github.com/matrixorigin/matrixone/pkg/defines" 37 "github.com/matrixorigin/matrixone/pkg/pb/plan" 38 "github.com/matrixorigin/matrixone/pkg/pb/query" 39 "github.com/matrixorigin/matrixone/pkg/pb/status" 40 "github.com/matrixorigin/matrixone/pkg/sql/colexec" 41 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 42 plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan" 43 "github.com/matrixorigin/matrixone/pkg/util/errutil" 44 db_holder "github.com/matrixorigin/matrixone/pkg/util/export/etl/db" 45 v2 "github.com/matrixorigin/matrixone/pkg/util/metric/v2" 46 "github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace" 47 "github.com/matrixorigin/matrixone/pkg/vm/process" 48 ) 49 50 var MaxPrepareNumberInOneSession int = 100000 51 52 // TODO: this variable should be configure by set variable 53 const MoDefaultErrorCount = 64 54 55 type ShowStatementType int 56 57 const ( 58 NotShowStatement ShowStatementType = 0 59 ShowTableStatus ShowStatementType = 1 60 ) 61 62 type ConnType int 63 64 const ( 65 ConnTypeUnset ConnType = 0 66 ConnTypeInternal ConnType = 1 67 ConnTypeExternal ConnType = 2 68 ) 69 70 type TS string 71 72 const ( 73 // Created 74 TSCreatedStart TS = "TSCreatedStart" 75 TSCreatedEnd TS = "TSCreatedEnd" 76 77 // Handler 78 TSEstablishStart TS = "TSEstablishStart" 79 TSEstablishEnd TS = "TSEstablishEnd" 80 TSUpgradeTLSStart TS = "TSUpgradeTLSStart" 81 TSUpgradeTLSEnd TS = "TSUpgradeTLSEnd" 82 83 // mysql protocol 84 TSAuthenticateStart TS = "TSAuthenticateStart" 85 TSAuthenticateEnd TS = "TSAuthenticateEnd" 86 TSSendErrPacketStart TS = "TSSendErrPacketStart" 87 TSSendErrPacketEnd TS = "TSSendErrPacketEnd" 88 TSSendOKPacketStart TS = "TSSendOKPacketStart" 89 TSSendOKPacketEnd TS = "TSSendOKPacketEnd" 90 91 // session 92 TSCheckTenantStart TS = "TSCheckTenantStart" 93 TSCheckTenantEnd TS = "TSCheckTenantEnd" 94 TSCheckUserStart TS = "TSCheckUserStart" 95 TSCheckUserEnd TS = "TSCheckUserEnd" 96 TSCheckRoleStart TS = "TSCheckRoleStart" 97 TSCheckRoleEnd TS = "TSCheckRoleEnd" 98 TSCheckDbNameStart TS = "TSCheckDbNameStart" 99 TSCheckDbNameEnd TS = "TSCheckDbNameEnd" 100 TSInitGlobalSysVarStart TS = "TSInitGlobalSysVarStart" 101 TSInitGlobalSysVarEnd TS = "TSInitGlobalSysVarEnd" 102 ) 103 104 type Session struct { 105 feSessionImpl 106 107 //cmd from the client 108 cmd CommandType 109 110 // the process of the session 111 proc *process.Process 112 113 isInternal bool 114 115 data [][]interface{} 116 ep *ExportConfig 117 showStmtType ShowStatementType 118 sysVars map[string]interface{} 119 userDefinedVars map[string]*UserDefinedVar 120 121 prepareStmts map[string]*PrepareStmt 122 lastStmtId uint32 123 124 priv *privilege 125 126 errInfo *errInfo 127 128 //fromRealUser distinguish the sql that the user inputs from the one 129 //that the internal or background program executes 130 fromRealUser bool 131 132 cache *privilegeCache 133 134 mu sync.Mutex 135 136 isNotBackgroundSession bool 137 lastInsertID uint64 138 tStmt *motrace.StatementInfo 139 140 ast tree.Statement 141 142 queryId []string 143 144 blockIdx int 145 146 p *plan.Plan 147 148 limitResultSize float64 // MB 149 150 curResultSize float64 // MB 151 152 // sentRows used to record rows it sent to client for motrace.StatementInfo. 153 // If there is NO exec_plan, sentRows will be 0. 154 sentRows atomic.Int64 155 // writeCsvBytes is used to record bytes sent by `select ... into 'file.csv'` for motrace.StatementInfo 156 writeCsvBytes atomic.Int64 157 // packetCounter count the packet communicated with client. 158 packetCounter atomic.Int64 159 // payloadCounter count the payload send by `load data` 160 payloadCounter int64 161 162 createdTime time.Time 163 164 expiredTime time.Time 165 166 planCache *planCache 167 168 statsCache *plan2.StatsCache 169 seqCurValues map[uint64]string 170 171 /* 172 CORNER CASE: 173 174 create sequence seq1; 175 set @@a = (select nextval(seq1)); // a = 1 176 select currval('seq1');// 1 177 select lastval('seq1');// right value is 1 178 179 We execute the expr of 'set var = expr' in a background session, 180 the last value of the seq1 is saved in the background session. 181 182 If we want to get the right value the lastval('seq1'), we need save 183 the last value of the seq1 in the session that starts the background session. 184 185 So, we define the type of seqLastValue as *string for updating its value conveniently. 186 187 TODO: we need to reimplement the sequence in some extent traced by issue #9847. 188 */ 189 seqLastValue *string 190 191 sqlHelper *SqlHelper 192 193 rm *RoutineManager 194 195 rt *Routine 196 197 // requestLabel is the CN label info requested from client. 198 requestLabel map[string]string 199 // connTyp indicates the type of connection. Default is ConnTypeUnset. 200 // If it is internal connection, the value will be ConnTypeInternal, otherwise, 201 // the value will be ConnTypeExternal. 202 connType ConnType 203 204 // startedAt is the session start time. 205 startedAt time.Time 206 207 // queryEnd is the time when the query ends 208 queryEnd time.Time 209 // queryInProgress indicates whether the query is in progress 210 queryInProgress atomic.Bool 211 // queryInExecute indicates whether the query is in execute 212 queryInExecute atomic.Bool 213 214 // timestampMap record timestamp for statistical purposes 215 timestampMap map[TS]time.Time 216 217 // insert sql for create table as select stmt 218 createAsSelectSql string 219 220 // FromProxy denotes whether the session is dispatched from proxy 221 fromProxy bool 222 // If the connection is from proxy, client address is the real address of client. 223 clientAddr string 224 proxyAddr string 225 226 disableTrace bool 227 } 228 229 func (ses *Session) GetTxnHandler() *TxnHandler { 230 ses.mu.Lock() 231 defer ses.mu.Unlock() 232 return ses.txnHandler 233 } 234 235 func (ses *Session) GetTenantInfo() *TenantInfo { 236 ses.mu.Lock() 237 defer ses.mu.Unlock() 238 return ses.tenant 239 } 240 241 func (ses *Session) SendRows() int64 { 242 return ses.sentRows.Load() 243 } 244 245 func (ses *Session) GetStmtInfo() *motrace.StatementInfo { 246 return ses.tStmt 247 } 248 249 func (ses *Session) getNextProcessId() string { 250 /* 251 temporary method: 252 routineId + sqlCount 253 */ 254 routineId := ses.GetMysqlProtocol().ConnectionID() 255 return fmt.Sprintf("%d%d", routineId, ses.GetSqlCount()) 256 } 257 258 func (ses *Session) SetPlan(plan *plan.Plan) { 259 ses.p = plan 260 } 261 262 func (ses *Session) GetProc() *process.Process { 263 return ses.proc 264 } 265 266 func (ses *Session) GetStatsCache() *plan2.StatsCache { 267 return ses.statsCache 268 } 269 270 func (ses *Session) GetSessionStart() time.Time { 271 ses.mu.Lock() 272 defer ses.mu.Unlock() 273 return ses.startedAt 274 } 275 276 func (ses *Session) SetQueryEnd(t time.Time) { 277 ses.mu.Lock() 278 defer ses.mu.Unlock() 279 ses.queryEnd = t 280 } 281 282 func (ses *Session) GetQueryEnd() time.Time { 283 ses.mu.Lock() 284 defer ses.mu.Unlock() 285 return ses.queryEnd 286 } 287 288 func (ses *Session) SetQueryInProgress(b bool) { 289 ses.queryInProgress.Store(b) 290 } 291 292 func (ses *Session) GetQueryInProgress() bool { 293 return ses.queryInProgress.Load() 294 } 295 296 func (ses *Session) SetQueryInExecute(b bool) { 297 ses.queryInExecute.Store(b) 298 } 299 300 func (ses *Session) GetQueryInExecute() bool { 301 return ses.queryInExecute.Load() 302 } 303 304 func (ses *Session) setRoutineManager(rm *RoutineManager) { 305 ses.mu.Lock() 306 defer ses.mu.Unlock() 307 ses.rm = rm 308 } 309 310 func (ses *Session) getRoutineManager() *RoutineManager { 311 ses.mu.Lock() 312 defer ses.mu.Unlock() 313 return ses.rm 314 } 315 316 func (ses *Session) setRoutine(rt *Routine) { 317 ses.mu.Lock() 318 defer ses.mu.Unlock() 319 ses.rt = rt 320 } 321 322 func (ses *Session) getRoutine() *Routine { 323 ses.mu.Lock() 324 defer ses.mu.Unlock() 325 return ses.rt 326 } 327 328 func (ses *Session) SetSeqLastValue(proc *process.Process) { 329 ses.mu.Lock() 330 defer ses.mu.Unlock() 331 *ses.seqLastValue = proc.SessionInfo.SeqLastValue[0] 332 } 333 334 func (ses *Session) DeleteSeqValues(proc *process.Process) { 335 ses.mu.Lock() 336 defer ses.mu.Unlock() 337 for _, k := range proc.SessionInfo.SeqDeleteKeys { 338 delete(ses.seqCurValues, k) 339 } 340 } 341 342 func (ses *Session) AddSeqValues(proc *process.Process) { 343 ses.mu.Lock() 344 defer ses.mu.Unlock() 345 for k, v := range proc.SessionInfo.SeqAddValues { 346 ses.seqCurValues[k] = v 347 } 348 } 349 350 func (ses *Session) GetSeqLastValue() string { 351 ses.mu.Lock() 352 defer ses.mu.Unlock() 353 return *ses.seqLastValue 354 } 355 356 func (ses *Session) CopySeqToProc(proc *process.Process) { 357 ses.mu.Lock() 358 defer ses.mu.Unlock() 359 for k, v := range ses.seqCurValues { 360 proc.SessionInfo.SeqCurValues[k] = v 361 } 362 proc.SessionInfo.SeqLastValue[0] = *ses.seqLastValue 363 } 364 365 func (ses *Session) InheritSequenceData(other *Session) { 366 ses.mu.Lock() 367 defer ses.mu.Unlock() 368 ses.seqCurValues = other.seqCurValues 369 ses.seqLastValue = other.seqLastValue 370 } 371 372 func (ses *Session) GetSqlHelper() *SqlHelper { 373 ses.mu.Lock() 374 defer ses.mu.Unlock() 375 return ses.sqlHelper 376 } 377 378 func (ses *Session) CountPayload(length int) { 379 if ses == nil { 380 return 381 } 382 ses.payloadCounter += int64(length) 383 } 384 func (ses *Session) CountPacket(delta int64) { 385 if ses == nil { 386 return 387 } 388 ses.packetCounter.Add(delta) 389 } 390 func (ses *Session) GetPacketCnt() int64 { 391 if ses == nil { 392 return 0 393 } 394 return ses.packetCounter.Load() 395 } 396 func (ses *Session) ResetPacketCounter() { 397 if ses == nil { 398 return 399 } 400 ses.packetCounter.Store(0) 401 ses.payloadCounter = 0 402 } 403 404 // SetTStmt do set the Session.tStmt 405 // 1. init-set at RecordStatement, which means the statement is started. 406 // 2. reset at logStatementStringStatus, which means the statement is finished. 407 func (ses *Session) SetTStmt(stmt *motrace.StatementInfo) { 408 ses.mu.Lock() 409 defer ses.mu.Unlock() 410 ses.tStmt = stmt 411 } 412 413 const saveQueryIdCnt = 10 414 415 func (ses *Session) pushQueryId(uuid string) { 416 if len(ses.queryId) > saveQueryIdCnt { 417 ses.queryId = ses.queryId[1:] 418 } 419 ses.queryId = append(ses.queryId, uuid) 420 } 421 422 func (ses *Session) getQueryId(internalSql bool) []string { 423 if internalSql { 424 cnt := len(ses.queryId) 425 //the last one is cnt-1 426 if cnt > 0 { 427 return ses.queryId[:cnt-1] 428 } else { 429 return ses.queryId[:cnt] 430 } 431 } 432 return ses.queryId 433 } 434 435 type errInfo struct { 436 codes []uint16 437 msgs []string 438 maxCnt int 439 } 440 441 func (e *errInfo) push(code uint16, msg string) { 442 if e.maxCnt > 0 && len(e.codes) > e.maxCnt { 443 e.codes = e.codes[1:] 444 e.msgs = e.msgs[1:] 445 } 446 e.codes = append(e.codes, code) 447 e.msgs = append(e.msgs, msg) 448 } 449 450 func (e *errInfo) length() int { 451 return len(e.codes) 452 } 453 454 func NewSession(connCtx context.Context, proto MysqlProtocol, mp *mpool.MPool, gSysVars *GlobalSystemVariables, isNotBackgroundSession bool, sharedTxnHandler *TxnHandler) *Session { 455 //if the sharedTxnHandler exists,we use its txnCtx and txnOperator in this session. 456 //Currently, we only use the sharedTxnHandler in the background session. 457 var txnOp TxnOperator 458 var err error 459 if sharedTxnHandler != nil { 460 if !sharedTxnHandler.InActiveTxn() { 461 panic("shared txn is invalid") 462 } 463 txnOp = sharedTxnHandler.GetTxn() 464 } 465 txnHandler := InitTxnHandler(getGlobalPu().StorageEngine, connCtx, txnOp) 466 467 ses := &Session{ 468 feSessionImpl: feSessionImpl{ 469 proto: proto, 470 pool: mp, 471 txnHandler: txnHandler, 472 //TODO:fix database name after the catalog is ready 473 txnCompileCtx: InitTxnCompilerContext(proto.GetDatabaseName()), 474 gSysVars: gSysVars, 475 outputCallback: getDataFromPipeline, 476 timeZone: time.Local, 477 }, 478 errInfo: &errInfo{ 479 codes: make([]uint16, 0, MoDefaultErrorCount), 480 msgs: make([]string, 0, MoDefaultErrorCount), 481 maxCnt: MoDefaultErrorCount, 482 }, 483 cache: &privilegeCache{}, 484 blockIdx: 0, 485 planCache: newPlanCache(100), 486 startedAt: time.Now(), 487 connType: ConnTypeUnset, 488 489 timestampMap: map[TS]time.Time{}, 490 statsCache: plan2.NewStatsCache(), 491 } 492 if isNotBackgroundSession { 493 ses.sysVars = gSysVars.CopySysVarsToSession() 494 ses.userDefinedVars = make(map[string]*UserDefinedVar) 495 ses.prepareStmts = make(map[string]*PrepareStmt) 496 // For seq init values. 497 ses.seqCurValues = make(map[uint64]string) 498 ses.seqLastValue = new(string) 499 } 500 501 ses.buf = buffer.New() 502 ses.isNotBackgroundSession = isNotBackgroundSession 503 ses.sqlHelper = &SqlHelper{ses: ses} 504 ses.uuid, _ = uuid.NewV7() 505 if ses.pool == nil { 506 // If no mp, we create one for session. Use GuestMmuLimitation as cap. 507 // fixed pool size can be another param, or should be computed from cap, 508 // but here, too lazy, just use Mid. 509 // 510 // XXX MPOOL 511 // We don't have a way to close a session, so the only sane way of creating 512 // a mpool is to use NoFixed 513 ses.pool, err = mpool.NewMPool("pipeline-"+ses.GetUUIDString(), getGlobalPu().SV.GuestMmuLimitation, mpool.NoFixed) 514 if err != nil { 515 panic(err) 516 } 517 } 518 ses.proc = process.New( 519 context.TODO(), 520 ses.pool, 521 getGlobalPu().TxnClient, 522 nil, 523 getGlobalPu().FileService, 524 getGlobalPu().LockService, 525 getGlobalPu().QueryClient, 526 getGlobalPu().HAKeeperClient, 527 getGlobalPu().UdfService, 528 getGlobalAic()) 529 530 ses.proc.Lim.Size = getGlobalPu().SV.ProcessLimitationSize 531 ses.proc.Lim.BatchRows = getGlobalPu().SV.ProcessLimitationBatchRows 532 ses.proc.Lim.MaxMsgSize = getGlobalPu().SV.MaxMessageSize 533 ses.proc.Lim.PartitionRows = getGlobalPu().SV.ProcessLimitationPartitionRows 534 535 ses.proc.SetStmtProfile(&ses.stmtProfile) 536 // ses.proc.SetResolveVariableFunc(ses.txnCompileCtx.ResolveVariable) 537 538 runtime.SetFinalizer(ses, func(ss *Session) { 539 ss.Close() 540 }) 541 return ses 542 } 543 544 func (ses *Session) Close() { 545 ses.mu.Lock() 546 defer ses.mu.Unlock() 547 ses.feSessionImpl.Close() 548 ses.feSessionImpl.Clear() 549 ses.proto = nil 550 ses.mrs = nil 551 ses.data = nil 552 ses.ep = nil 553 if ses.txnHandler != nil { 554 ses.txnHandler.Close() 555 ses.txnHandler = nil 556 } 557 if ses.txnCompileCtx != nil { 558 ses.txnCompileCtx.execCtx = nil 559 ses.txnCompileCtx = nil 560 } 561 ses.sql = "" 562 ses.sysVars = nil 563 ses.userDefinedVars = nil 564 ses.gSysVars = nil 565 for _, stmt := range ses.prepareStmts { 566 stmt.Close() 567 } 568 ses.prepareStmts = nil 569 ses.allResultSet = nil 570 ses.tenant = nil 571 ses.priv = nil 572 ses.errInfo = nil 573 ses.cache = nil 574 ses.debugStr = "" 575 ses.tStmt = nil 576 ses.ast = nil 577 ses.rs = nil 578 ses.queryId = nil 579 ses.p = nil 580 ses.planCache = nil 581 ses.seqCurValues = nil 582 ses.seqLastValue = nil 583 if ses.sqlHelper != nil { 584 ses.sqlHelper.ses = nil 585 ses.sqlHelper = nil 586 } 587 ses.ClearStmtProfile() 588 // The mpool cleanup must be placed at the end, 589 // and you must wait for all resources to be cleaned up before you can delete the mpool 590 if ses.proc != nil { 591 ses.proc.FreeVectors() 592 bats := ses.proc.GetValueScanBatchs() 593 for _, bat := range bats { 594 bat.Clean(ses.proc.Mp()) 595 } 596 ses.proc = nil 597 } 598 for _, bat := range ses.resultBatches { 599 bat.Clean(ses.pool) 600 } 601 if ses.isNotBackgroundSession { 602 pool := ses.GetMemPool() 603 mpool.DeleteMPool(pool) 604 ses.SetMemPool(nil) 605 } 606 if ses.buf != nil { 607 ses.buf.Free() 608 ses.buf = nil 609 } 610 611 ses.timestampMap = nil 612 ses.upstream = nil 613 ses.rm = nil 614 ses.rt = nil 615 } 616 617 func (ses *Session) Clear() { 618 ses.feSessionImpl.Clear() 619 } 620 621 func (ses *Session) GetIncBlockIdx() int { 622 ses.blockIdx++ 623 return ses.blockIdx 624 } 625 626 func (ses *Session) ResetBlockIdx() { 627 ses.blockIdx = 0 628 } 629 630 func (ses *Session) IsBackgroundSession() bool { 631 ses.mu.Lock() 632 defer ses.mu.Unlock() 633 return !ses.isNotBackgroundSession 634 } 635 636 func (ses *Session) cachePlan(sql string, stmts []tree.Statement, plans []*plan.Plan) { 637 if len(sql) == 0 { 638 return 639 } 640 ses.mu.Lock() 641 defer ses.mu.Unlock() 642 ses.planCache.cache(sql, stmts, plans) 643 } 644 645 func (ses *Session) getCachedPlan(sql string) *cachedPlan { 646 if len(sql) == 0 { 647 return nil 648 } 649 ses.mu.Lock() 650 defer ses.mu.Unlock() 651 return ses.planCache.get(sql) 652 } 653 654 func (ses *Session) isCached(sql string) bool { 655 if len(sql) == 0 { 656 return false 657 } 658 ses.mu.Lock() 659 defer ses.mu.Unlock() 660 return ses.planCache.isCached(sql) 661 } 662 663 func (ses *Session) cleanCache() { 664 ses.mu.Lock() 665 defer ses.mu.Unlock() 666 ses.planCache.clean() 667 } 668 669 func (ses *Session) UpdateDebugString() { 670 ses.mu.Lock() 671 defer ses.mu.Unlock() 672 sb := bytes.Buffer{} 673 //option connection id , ip 674 if ses.proto != nil { 675 sb.WriteString(fmt.Sprintf("connectionId %d", ses.proto.ConnectionID())) 676 sb.WriteByte('|') 677 sb.WriteString(ses.proto.Peer()) 678 } 679 sb.WriteByte('|') 680 //account info 681 if ses.tenant != nil { 682 sb.WriteString(ses.tenant.String()) 683 } else { 684 acc := getDefaultAccount() 685 sb.WriteString(acc.String()) 686 } 687 sb.WriteByte('|') 688 //go routine id 689 if ses.rt != nil { 690 sb.WriteString(fmt.Sprintf("goRoutineId %d", ses.rt.getGoroutineId())) 691 sb.WriteByte('|') 692 } 693 //session id 694 sb.WriteString(ses.uuid.String()) 695 //upstream sessionid 696 if ses.upstream != nil { 697 sb.WriteByte('|') 698 sb.WriteString(ses.upstream.uuid.String()) 699 } 700 701 ses.debugStr = sb.String() 702 } 703 704 func (ses *Session) GetPrivilegeCache() *privilegeCache { 705 ses.mu.Lock() 706 defer ses.mu.Unlock() 707 return ses.cache 708 } 709 710 func (ses *Session) InvalidatePrivilegeCache() { 711 ses.mu.Lock() 712 defer ses.mu.Unlock() 713 ses.cache.invalidate() 714 } 715 716 // GetBackgroundExec generates a background executor 717 func (ses *Session) GetBackgroundExec(ctx context.Context) BackgroundExec { 718 return NewBackgroundExec( 719 ctx, 720 ses, 721 ses.GetMemPool()) 722 } 723 724 // GetShareTxnBackgroundExec returns a background executor running the sql in a shared transaction. 725 // newRawBatch denotes we need the raw batch instead of mysql result set. 726 func (ses *Session) GetShareTxnBackgroundExec(ctx context.Context, newRawBatch bool) BackgroundExec { 727 var txnOp TxnOperator 728 if ses.GetTxnHandler() != nil { 729 txnOp = ses.GetTxnHandler().GetTxn() 730 } 731 732 txnHandler := InitTxnHandler(getGlobalPu().StorageEngine, ses.GetTxnHandler().GetConnCtx(), txnOp) 733 var callback outputCallBackFunc 734 if newRawBatch { 735 callback = batchFetcher2 736 } else { 737 callback = fakeDataSetFetcher2 738 } 739 backSes := &backSession{ 740 feSessionImpl: feSessionImpl{ 741 pool: ses.pool, 742 proto: &FakeProtocol{}, 743 buf: buffer.New(), 744 stmtProfile: process.StmtProfile{}, 745 tenant: nil, 746 txnHandler: txnHandler, 747 txnCompileCtx: InitTxnCompilerContext(ses.proto.GetDatabaseName()), 748 mrs: nil, 749 outputCallback: callback, 750 allResultSet: nil, 751 resultBatches: nil, 752 derivedStmt: false, 753 gSysVars: GSysVariables, 754 label: make(map[string]string), 755 timeZone: time.Local, 756 }, 757 } 758 backSes.uuid, _ = uuid.NewV7() 759 bh := &backExec{ 760 backSes: backSes, 761 } 762 //the derived statement execute in a shared transaction in background session 763 bh.backSes.ReplaceDerivedStmt(true) 764 return bh 765 } 766 767 var GetRawBatchBackgroundExec = func(ctx context.Context, ses *Session) BackgroundExec { 768 return ses.GetRawBatchBackgroundExec(ctx) 769 } 770 771 func (ses *Session) GetRawBatchBackgroundExec(ctx context.Context) BackgroundExec { 772 txnHandler := InitTxnHandler(getGlobalPu().StorageEngine, ses.GetTxnHandler().GetConnCtx(), nil) 773 backSes := &backSession{ 774 feSessionImpl: feSessionImpl{ 775 pool: ses.GetMemPool(), 776 proto: &FakeProtocol{}, 777 buf: buffer.New(), 778 stmtProfile: process.StmtProfile{}, 779 tenant: nil, 780 txnHandler: txnHandler, 781 txnCompileCtx: InitTxnCompilerContext(""), 782 mrs: nil, 783 outputCallback: batchFetcher2, 784 allResultSet: nil, 785 resultBatches: nil, 786 derivedStmt: false, 787 gSysVars: GSysVariables, 788 label: make(map[string]string), 789 timeZone: time.Local, 790 }, 791 } 792 backSes.uuid, _ = uuid.NewV7() 793 bh := &backExec{ 794 backSes: backSes, 795 } 796 return bh 797 } 798 799 func (ses *Session) GetIsInternal() bool { 800 ses.mu.Lock() 801 defer ses.mu.Unlock() 802 return ses.isInternal 803 } 804 805 func (ses *Session) GetData() [][]interface{} { 806 ses.mu.Lock() 807 defer ses.mu.Unlock() 808 return ses.data 809 } 810 811 func (ses *Session) SetData(data [][]interface{}) { 812 ses.mu.Lock() 813 defer ses.mu.Unlock() 814 ses.data = data 815 } 816 817 func (ses *Session) AppendData(row []interface{}) { 818 ses.mu.Lock() 819 defer ses.mu.Unlock() 820 ses.data = append(ses.data, row) 821 } 822 823 func (ses *Session) InitExportConfig(ep *tree.ExportParam) { 824 ses.mu.Lock() 825 defer ses.mu.Unlock() 826 ses.ep = &ExportConfig{userConfig: ep} 827 } 828 829 func (ses *Session) GetExportConfig() *ExportConfig { 830 ses.mu.Lock() 831 defer ses.mu.Unlock() 832 return ses.ep 833 } 834 835 func (ses *Session) ClearExportParam() { 836 ses.mu.Lock() 837 defer ses.mu.Unlock() 838 ses.ep = nil 839 } 840 841 func (ses *Session) SetShowStmtType(sst ShowStatementType) { 842 ses.mu.Lock() 843 defer ses.mu.Unlock() 844 ses.showStmtType = sst 845 } 846 847 func (ses *Session) GetShowStmtType() ShowStatementType { 848 ses.mu.Lock() 849 defer ses.mu.Unlock() 850 return ses.showStmtType 851 } 852 853 func (ses *Session) GetOutputCallback(execCtx *ExecCtx) func(*batch.Batch) error { 854 ses.mu.Lock() 855 defer ses.mu.Unlock() 856 return func(bat *batch.Batch) error { 857 return ses.outputCallback(ses, execCtx, bat) 858 } 859 } 860 861 func (ses *Session) GetErrInfo() *errInfo { 862 ses.mu.Lock() 863 defer ses.mu.Unlock() 864 return ses.errInfo 865 } 866 867 func (ses *Session) GenNewStmtId() uint32 { 868 ses.mu.Lock() 869 defer ses.mu.Unlock() 870 ses.lastStmtId = ses.lastStmtId + 1 871 return ses.lastStmtId 872 } 873 874 func (ses *Session) SetLastStmtID(id uint32) { 875 ses.mu.Lock() 876 defer ses.mu.Unlock() 877 ses.lastStmtId = id 878 } 879 880 func (ses *Session) GetLastStmtId() uint32 { 881 ses.mu.Lock() 882 defer ses.mu.Unlock() 883 return ses.lastStmtId 884 } 885 886 func (ses *Session) SetLastInsertID(num uint64) { 887 ses.mu.Lock() 888 defer ses.mu.Unlock() 889 ses.lastInsertID = num 890 } 891 892 func (ses *Session) GetLastInsertID() uint64 { 893 ses.mu.Lock() 894 defer ses.mu.Unlock() 895 return ses.lastInsertID 896 } 897 898 func (ses *Session) SetCmd(cmd CommandType) { 899 ses.mu.Lock() 900 defer ses.mu.Unlock() 901 ses.cmd = cmd 902 } 903 904 func (ses *Session) GetCmd() CommandType { 905 ses.mu.Lock() 906 defer ses.mu.Unlock() 907 return ses.cmd 908 } 909 910 // GetTenantName return tenant name according to GetTenantInfo and stmt. 911 // 912 // With stmt = nil, should be only called in TxnHandler.NewTxn, TxnHandler.CommitTxn, TxnHandler.RollbackTxn 913 func (ses *Session) GetTenantNameWithStmt(stmt tree.Statement) string { 914 tenant := sysAccountName 915 if ses.GetTenantInfo() != nil && (stmt == nil || !IsPrepareStatement(stmt)) { 916 tenant = ses.GetTenantInfo().GetTenant() 917 } 918 return tenant 919 } 920 921 func (ses *Session) GetTenantName() string { 922 return ses.GetTenantNameWithStmt(nil) 923 } 924 925 func (ses *Session) SetPrepareStmt(ctx context.Context, name string, prepareStmt *PrepareStmt) error { 926 ses.mu.Lock() 927 defer ses.mu.Unlock() 928 if stmt, ok := ses.prepareStmts[name]; !ok { 929 if len(ses.prepareStmts) >= MaxPrepareNumberInOneSession { 930 return moerr.NewInvalidState(ctx, "too many prepared statement, max %d", MaxPrepareNumberInOneSession) 931 } 932 } else { 933 stmt.Close() 934 } 935 if prepareStmt != nil && prepareStmt.PreparePlan != nil { 936 isInsertValues, exprList := checkPlanIsInsertValues(ses.proc, 937 prepareStmt.PreparePlan.GetDcl().GetPrepare().GetPlan()) 938 if isInsertValues { 939 prepareStmt.proc = ses.proc 940 prepareStmt.exprList = exprList 941 } 942 } 943 ses.prepareStmts[name] = prepareStmt 944 945 return nil 946 } 947 948 func (ses *Session) GetPrepareStmt(ctx context.Context, name string) (*PrepareStmt, error) { 949 ses.mu.Lock() 950 defer ses.mu.Unlock() 951 if prepareStmt, ok := ses.prepareStmts[name]; ok { 952 return prepareStmt, nil 953 } 954 var connID uint32 955 if ses.proto != nil { 956 connID = ses.proto.ConnectionID() 957 } 958 logutil.Errorf("prepared statement '%s' does not exist on connection %d", name, connID) 959 return nil, moerr.NewInvalidState(ctx, "prepared statement '%s' does not exist", name) 960 } 961 962 func (ses *Session) GetPrepareStmts() []*PrepareStmt { 963 ses.mu.Lock() 964 defer ses.mu.Unlock() 965 ret := make([]*PrepareStmt, 0, len(ses.prepareStmts)) 966 for _, st := range ses.prepareStmts { 967 ret = append(ret, st) 968 } 969 return ret 970 } 971 972 func (ses *Session) RemovePrepareStmt(name string) { 973 ses.mu.Lock() 974 defer ses.mu.Unlock() 975 if stmt, ok := ses.prepareStmts[name]; ok { 976 stmt.Close() 977 } 978 delete(ses.prepareStmts, name) 979 } 980 981 func (ses *Session) SetSysVar(name string, value interface{}) { 982 ses.mu.Lock() 983 defer ses.mu.Unlock() 984 ses.sysVars[name] = value 985 } 986 987 func (ses *Session) GetSysVar(name string) interface{} { 988 ses.mu.Lock() 989 defer ses.mu.Unlock() 990 return ses.sysVars[name] 991 } 992 993 func (ses *Session) GetSysVars() map[string]interface{} { 994 ses.mu.Lock() 995 defer ses.mu.Unlock() 996 return ses.sysVars 997 } 998 999 // SetGlobalVar sets the value of system variable in global. 1000 // used by SET GLOBAL 1001 func (ses *Session) SetGlobalVar(ctx context.Context, name string, value interface{}) error { 1002 return ses.GetGlobalSysVars().SetGlobalSysVar(ctx, name, value) 1003 } 1004 1005 // GetGlobalVar gets this value of the system variable in global 1006 func (ses *Session) GetGlobalVar(ctx context.Context, name string) (interface{}, error) { 1007 gSysVars := ses.GetGlobalSysVars() 1008 if def, val, ok := gSysVars.GetGlobalSysVar(name); ok { 1009 if def.GetScope() == ScopeSession { 1010 //empty 1011 return nil, moerr.NewInternalError(ctx, errorSystemVariableSessionEmpty()) 1012 } 1013 return val, nil 1014 } 1015 return nil, moerr.NewInternalError(ctx, errorSystemVariableDoesNotExist()) 1016 } 1017 1018 // SetSessionVar sets the value of system variable in session 1019 func (ses *Session) SetSessionVar(ctx context.Context, name string, value interface{}) error { 1020 gSysVars := ses.GetGlobalSysVars() 1021 if def, _, ok := gSysVars.GetGlobalSysVar(name); ok { 1022 if def.GetScope() == ScopeGlobal { 1023 return moerr.NewInternalError(ctx, errorSystemVariableIsGlobal()) 1024 } 1025 //scope session & both 1026 if !def.GetDynamic() { 1027 return moerr.NewInternalError(ctx, errorSystemVariableIsReadOnly()) 1028 } 1029 1030 cv, err := def.GetType().Convert(value) 1031 if err != nil { 1032 errutil.ReportError(ctx, err) 1033 return err 1034 } 1035 1036 if def.UpdateSessVar == nil { 1037 ses.SetSysVar(def.GetName(), cv) 1038 } else { 1039 return def.UpdateSessVar(ctx, ses, ses.GetSysVars(), def.GetName(), cv) 1040 } 1041 } else { 1042 return moerr.NewInternalError(ctx, errorSystemVariableDoesNotExist()) 1043 } 1044 return nil 1045 } 1046 1047 // InitSetSessionVar sets the value of system variable in session when start a connection 1048 func (ses *Session) InitSetSessionVar(ctx context.Context, name string, value interface{}) error { 1049 gSysVars := ses.GetGlobalSysVars() 1050 if def, _, ok := gSysVars.GetGlobalSysVar(name); ok { 1051 cv, err := def.GetType().Convert(value) 1052 if err != nil { 1053 errutil.ReportError(ctx, moerr.NewInternalError(context.Background(), "init variable fail: variable %s convert to the system variable type %s failed, bad value %v", name, def.GetType().String(), value)) 1054 } 1055 1056 if def.UpdateSessVar == nil { 1057 ses.SetSysVar(def.GetName(), cv) 1058 } else { 1059 return def.UpdateSessVar(ctx, ses, ses.GetSysVars(), def.GetName(), cv) 1060 } 1061 } 1062 return nil 1063 } 1064 1065 // GetSessionVar gets this value of the system variable in session 1066 func (ses *Session) GetSessionVar(ctx context.Context, name string) (interface{}, error) { 1067 gSysVars := ses.GetGlobalSysVars() 1068 if def, gVal, ok := gSysVars.GetGlobalSysVar(name); ok { 1069 ciname := strings.ToLower(name) 1070 if def.GetScope() == ScopeGlobal { 1071 return gVal, nil 1072 } 1073 return ses.GetSysVar(ciname), nil 1074 } else { 1075 return nil, moerr.NewInternalError(ctx, errorSystemVariableDoesNotExist()) 1076 } 1077 } 1078 1079 func (ses *Session) CopyAllSessionVars() map[string]interface{} { 1080 ses.mu.Lock() 1081 defer ses.mu.Unlock() 1082 cp := make(map[string]interface{}) 1083 for k, v := range ses.sysVars { 1084 cp[k] = v 1085 } 1086 return cp 1087 } 1088 1089 // SetUserDefinedVar sets the user defined variable to the value in session 1090 func (ses *Session) SetUserDefinedVar(name string, value interface{}, sql string) error { 1091 ses.mu.Lock() 1092 defer ses.mu.Unlock() 1093 ses.userDefinedVars[strings.ToLower(name)] = &UserDefinedVar{Value: value, Sql: sql} 1094 return nil 1095 } 1096 1097 // GetUserDefinedVar gets value of the user defined variable 1098 func (ses *Session) GetUserDefinedVar(name string) (SystemVariableType, *UserDefinedVar, error) { 1099 ses.mu.Lock() 1100 defer ses.mu.Unlock() 1101 val, ok := ses.userDefinedVars[strings.ToLower(name)] 1102 if !ok { 1103 return SystemVariableNullType{}, nil, nil 1104 } 1105 return InitSystemVariableStringType(name), val, nil 1106 } 1107 1108 func (ses *Session) GetTxnInfo() string { 1109 txnH := ses.GetTxnHandler() 1110 if txnH == nil { 1111 return "" 1112 } 1113 txnOp := txnH.GetTxn() 1114 if txnOp == nil { 1115 return "" 1116 } 1117 meta := txnOp.Txn() 1118 return meta.DebugString() 1119 } 1120 1121 func (ses *Session) GetDatabaseName() string { 1122 return ses.GetMysqlProtocol().GetDatabaseName() 1123 } 1124 1125 func (ses *Session) SetDatabaseName(db string) { 1126 ses.GetMysqlProtocol().SetDatabaseName(db) 1127 ses.GetTxnCompileCtx().SetDatabase(db) 1128 } 1129 1130 func (ses *Session) DatabaseNameIsEmpty() bool { 1131 return len(ses.GetDatabaseName()) == 0 1132 } 1133 1134 func (ses *Session) SetUserName(uname string) { 1135 ses.GetMysqlProtocol().SetUserName(uname) 1136 } 1137 1138 func (ses *Session) GetConnectionID() uint32 { 1139 protocol := ses.GetMysqlProtocol() 1140 if protocol != nil { 1141 return ses.GetMysqlProtocol().ConnectionID() 1142 } 1143 return 0 1144 } 1145 1146 func (ses *Session) skipAuthForSpecialUser() bool { 1147 if ses.GetTenantInfo() != nil { 1148 ok, _, _ := isSpecialUser(ses.GetTenantInfo().GetUser()) 1149 return ok 1150 } 1151 return false 1152 } 1153 1154 // AuthenticateUser Verify the user's password, and if the login information contains the database name, verify if the database exists 1155 func (ses *Session) AuthenticateUser(ctx context.Context, userInput string, dbName string, authResponse []byte, salt []byte, checkPassword func(pwd []byte, salt []byte, auth []byte) bool) ([]byte, error) { 1156 var defaultRoleID int64 1157 var defaultRole string 1158 var tenant *TenantInfo 1159 var err error 1160 var rsset []ExecResult 1161 var tenantID int64 1162 var userID int64 1163 var pwd, accountStatus string 1164 var accountVersion uint64 1165 //var createVersion string 1166 var pwdBytes []byte 1167 var isSpecial bool 1168 var specialAccount *TenantInfo 1169 1170 //Get tenant info 1171 tenant, err = GetTenantInfo(ctx, userInput) 1172 if err != nil { 1173 return nil, err 1174 } 1175 1176 ses.SetTenantInfo(tenant) 1177 ses.UpdateDebugString() 1178 sessionInfo := ses.GetDebugString() 1179 1180 logDebugf(sessionInfo, "check special user") 1181 // check the special user for initilization 1182 isSpecial, pwdBytes, specialAccount = isSpecialUser(tenant.GetUser()) 1183 if isSpecial && specialAccount.IsMoAdminRole() { 1184 ses.SetTenantInfo(specialAccount) 1185 if len(ses.requestLabel) == 0 { 1186 ses.requestLabel = db_holder.GetLabelSelector() 1187 } 1188 return GetPassWord(HashPassWordWithByte(pwdBytes)) 1189 } 1190 1191 ses.SetTenantInfo(tenant) 1192 1193 //step1 : check tenant exists or not in SYS tenant context 1194 ses.timestampMap[TSCheckTenantStart] = time.Now() 1195 sysTenantCtx := defines.AttachAccount(ctx, uint32(sysAccountID), uint32(rootID), uint32(moAdminRoleID)) 1196 sqlForCheckTenant, err := getSqlForCheckTenant(sysTenantCtx, tenant.GetTenant()) 1197 if err != nil { 1198 return nil, err 1199 } 1200 mp := ses.GetMemPool() 1201 logDebugf(sessionInfo, "check tenant %s exists", tenant) 1202 rsset, err = executeSQLInBackgroundSession(sysTenantCtx, ses, mp, sqlForCheckTenant) 1203 if err != nil { 1204 return nil, err 1205 } 1206 if !execResultArrayHasData(rsset) { 1207 return nil, moerr.NewInternalError(sysTenantCtx, "there is no tenant %s", tenant.GetTenant()) 1208 } 1209 1210 //account id 1211 tenantID, err = rsset[0].GetInt64(sysTenantCtx, 0, 0) 1212 if err != nil { 1213 return nil, err 1214 } 1215 1216 //account status 1217 accountStatus, err = rsset[0].GetString(sysTenantCtx, 0, 2) 1218 if err != nil { 1219 return nil, err 1220 } 1221 1222 //account version 1223 accountVersion, err = rsset[0].GetUint64(sysTenantCtx, 0, 3) 1224 if err != nil { 1225 return nil, err 1226 } 1227 1228 if strings.ToLower(accountStatus) == tree.AccountStatusSuspend.String() { 1229 return nil, moerr.NewInternalError(sysTenantCtx, "Account %s is suspended", tenant.GetTenant()) 1230 } 1231 1232 if strings.ToLower(accountStatus) == tree.AccountStatusRestricted.String() { 1233 ses.getRoutine().setResricted(true) 1234 } else { 1235 ses.getRoutine().setResricted(false) 1236 } 1237 1238 tenant.SetTenantID(uint32(tenantID)) 1239 ses.timestampMap[TSCheckTenantEnd] = time.Now() 1240 v2.CheckTenantDurationHistogram.Observe(ses.timestampMap[TSCheckTenantEnd].Sub(ses.timestampMap[TSCheckTenantStart]).Seconds()) 1241 1242 //step2 : check user exists or not in general tenant. 1243 //step3 : get the password of the user 1244 1245 ses.timestampMap[TSCheckUserStart] = time.Now() 1246 tenantCtx := defines.AttachAccountId(ctx, uint32(tenantID)) 1247 1248 logDebugf(sessionInfo, "check user of %s exists", tenant) 1249 //Get the password of the user in an independent session 1250 sqlForPasswordOfUser, err := getSqlForPasswordOfUser(tenantCtx, tenant.GetUser()) 1251 if err != nil { 1252 return nil, err 1253 } 1254 rsset, err = executeSQLInBackgroundSession(tenantCtx, ses, mp, sqlForPasswordOfUser) 1255 if err != nil { 1256 return nil, err 1257 } 1258 if !execResultArrayHasData(rsset) { 1259 return nil, moerr.NewInternalError(tenantCtx, "there is no user %s", tenant.GetUser()) 1260 } 1261 1262 userID, err = rsset[0].GetInt64(tenantCtx, 0, 0) 1263 if err != nil { 1264 return nil, err 1265 } 1266 1267 pwd, err = rsset[0].GetString(tenantCtx, 0, 1) 1268 if err != nil { 1269 return nil, err 1270 } 1271 1272 //the default_role in the mo_user table. 1273 //the default_role is always valid. public or other valid role. 1274 defaultRoleID, err = rsset[0].GetInt64(tenantCtx, 0, 2) 1275 if err != nil { 1276 return nil, err 1277 } 1278 1279 tenant.SetUserID(uint32(userID)) 1280 tenant.SetDefaultRoleID(uint32(defaultRoleID)) 1281 ses.timestampMap[TSCheckUserEnd] = time.Now() 1282 v2.CheckUserDurationHistogram.Observe(ses.timestampMap[TSCheckUserEnd].Sub(ses.timestampMap[TSCheckUserStart]).Seconds()) 1283 1284 /* 1285 login case 1: tenant:user 1286 1.get the default_role of the user in mo_user 1287 1288 login case 2: tenant:user:role 1289 1.check the role has been granted to the user 1290 -yes: go on 1291 -no: error 1292 1293 */ 1294 //it denotes that there is no default role in the input 1295 if tenant.HasDefaultRole() { 1296 logDebugf(sessionInfo, "check default role of user %s.", tenant) 1297 //step4 : check role exists or not 1298 ses.timestampMap[TSCheckRoleStart] = time.Now() 1299 sqlForCheckRoleExists, err := getSqlForRoleIdOfRole(tenantCtx, tenant.GetDefaultRole()) 1300 if err != nil { 1301 return nil, err 1302 } 1303 rsset, err = executeSQLInBackgroundSession(tenantCtx, ses, mp, sqlForCheckRoleExists) 1304 if err != nil { 1305 return nil, err 1306 } 1307 1308 if !execResultArrayHasData(rsset) { 1309 return nil, moerr.NewInternalError(tenantCtx, "there is no role %s", tenant.GetDefaultRole()) 1310 } 1311 1312 logDebugf(sessionInfo, "check granted role of user %s.", tenant) 1313 //step4.2 : check the role has been granted to the user or not 1314 sqlForRoleOfUser, err := getSqlForRoleOfUser(tenantCtx, userID, tenant.GetDefaultRole()) 1315 if err != nil { 1316 return nil, err 1317 } 1318 rsset, err = executeSQLInBackgroundSession(tenantCtx, ses, mp, sqlForRoleOfUser) 1319 if err != nil { 1320 return nil, err 1321 } 1322 if !execResultArrayHasData(rsset) { 1323 return nil, moerr.NewInternalError(tenantCtx, "the role %s has not been granted to the user %s", 1324 tenant.GetDefaultRole(), tenant.GetUser()) 1325 } 1326 1327 defaultRoleID, err = rsset[0].GetInt64(tenantCtx, 0, 0) 1328 if err != nil { 1329 return nil, err 1330 } 1331 tenant.SetDefaultRoleID(uint32(defaultRoleID)) 1332 ses.timestampMap[TSCheckRoleEnd] = time.Now() 1333 v2.CheckRoleDurationHistogram.Observe(ses.timestampMap[TSCheckRoleEnd].Sub(ses.timestampMap[TSCheckRoleStart]).Seconds()) 1334 } else { 1335 ses.timestampMap[TSCheckRoleStart] = time.Now() 1336 logDebugf(sessionInfo, "check designated role of user %s.", tenant) 1337 //the get name of default_role from mo_role 1338 sql := getSqlForRoleNameOfRoleId(defaultRoleID) 1339 rsset, err = executeSQLInBackgroundSession(tenantCtx, ses, mp, sql) 1340 if err != nil { 1341 return nil, err 1342 } 1343 if !execResultArrayHasData(rsset) { 1344 return nil, moerr.NewInternalError(tenantCtx, "get the default role of the user %s failed", tenant.GetUser()) 1345 } 1346 1347 defaultRole, err = rsset[0].GetString(tenantCtx, 0, 0) 1348 if err != nil { 1349 return nil, err 1350 } 1351 tenant.SetDefaultRole(defaultRole) 1352 ses.timestampMap[TSCheckRoleEnd] = time.Now() 1353 v2.CheckRoleDurationHistogram.Observe(ses.timestampMap[TSCheckRoleEnd].Sub(ses.timestampMap[TSCheckRoleStart]).Seconds()) 1354 } 1355 //------------------------------------------------------------------------------------------------------------------ 1356 psw, err := GetPassWord(pwd) 1357 if err != nil { 1358 return nil, err 1359 } 1360 1361 // TO Check password 1362 if checkPassword(psw, salt, authResponse) { 1363 logDebugf(sessionInfo, "check password succeeded") 1364 ses.InitGlobalSystemVariables(tenantCtx) 1365 } else { 1366 return nil, moerr.NewInternalError(tenantCtx, "check password failed") 1367 } 1368 1369 // If the login information contains the database name, verify if the database exists 1370 if dbName != "" { 1371 ses.timestampMap[TSCheckDbNameStart] = time.Now() 1372 _, err = executeSQLInBackgroundSession(tenantCtx, ses, mp, "use "+dbName) 1373 if err != nil { 1374 return nil, err 1375 } 1376 logDebugf(sessionInfo, "check database name succeeded") 1377 ses.timestampMap[TSCheckDbNameEnd] = time.Now() 1378 v2.CheckDbNameDurationHistogram.Observe(ses.timestampMap[TSCheckDbNameEnd].Sub(ses.timestampMap[TSCheckDbNameStart]).Seconds()) 1379 } 1380 //------------------------------------------------------------------------------------------------------------------ 1381 // record the id :routine pair in RoutineManager 1382 ses.getRoutineManager().accountRoutine.recordRountine(tenantID, ses.getRoutine(), accountVersion) 1383 logInfo(ses, sessionInfo, tenant.String()) 1384 1385 return GetPassWord(pwd) 1386 } 1387 1388 func (ses *Session) MaybeUpgradeTenant(ctx context.Context, curVersion string, tenantID int64) error { 1389 // Get mo final version, which is based on the current code version 1390 finalVersion := ses.rm.baseService.GetFinalVersion() 1391 if versions.Compare(curVersion, finalVersion) <= 0 { 1392 return ses.rm.baseService.CheckTenantUpgrade(ctx, tenantID) 1393 } 1394 return nil 1395 } 1396 1397 func (ses *Session) UpgradeTenant(ctx context.Context, tenantName string, retryCount uint32, isALLAccount bool) error { 1398 // Get mo final version, which is based on the current code version 1399 return ses.rm.baseService.UpgradeTenant(ctx, tenantName, retryCount, isALLAccount) 1400 } 1401 1402 func (ses *Session) InitGlobalSystemVariables(ctx context.Context) error { 1403 var err error 1404 var rsset []ExecResult 1405 ses.timestampMap[TSInitGlobalSysVarStart] = time.Now() 1406 defer func() { 1407 ses.timestampMap[TSInitGlobalSysVarEnd] = time.Now() 1408 v2.InitGlobalSysVarDurationHistogram.Observe(ses.timestampMap[TSInitGlobalSysVarEnd].Sub(ses.timestampMap[TSInitGlobalSysVarStart]).Seconds()) 1409 }() 1410 1411 tenantInfo := ses.GetTenantInfo() 1412 // if is system account 1413 if tenantInfo.IsSysTenant() { 1414 sysTenantCtx := defines.AttachAccount(ctx, uint32(sysAccountID), uint32(rootID), uint32(moAdminRoleID)) 1415 1416 // get system variable from mo_mysql_compatibility mode 1417 sqlForGetVariables := getSystemVariablesWithAccount(sysAccountID) 1418 mp := ses.GetMemPool() 1419 1420 rsset, err = executeSQLInBackgroundSession( 1421 sysTenantCtx, 1422 ses, 1423 mp, 1424 sqlForGetVariables) 1425 if err != nil { 1426 return err 1427 } 1428 if execResultArrayHasData(rsset) { 1429 for i := uint64(0); i < rsset[0].GetRowCount(); i++ { 1430 variable_name, err := rsset[0].GetString(sysTenantCtx, i, 0) 1431 if err != nil { 1432 return err 1433 } 1434 variable_value, err := rsset[0].GetString(sysTenantCtx, i, 1) 1435 if err != nil { 1436 return err 1437 } 1438 1439 if sv, ok := gSysVarsDefs[variable_name]; ok { 1440 if !sv.GetDynamic() || (sv.Scope != ScopeGlobal && sv.Scope != ScopeBoth) { 1441 continue 1442 } 1443 val, err := sv.GetType().ConvertFromString(variable_value) 1444 if err != nil { 1445 errutil.ReportError(ctx, moerr.NewInternalError(context.Background(), "init variable fail: variable %s convert from string value to the system variable type %s failed, bad value %s", variable_name, sv.Type.String(), variable_value)) 1446 return err 1447 } 1448 err = ses.InitSetSessionVar(sysTenantCtx, variable_name, val) 1449 if err != nil { 1450 errutil.ReportError(ctx, moerr.NewInternalError(context.Background(), "init variable fail: variable %s convert from string value to the system variable type %s failed, bad value %s", variable_name, sv.Type.String(), variable_value)) 1451 } 1452 } 1453 } 1454 } else { 1455 return moerr.NewInternalError(sysTenantCtx, "there is no data in mo_mysql_compatibility_mode table for account %s", sysAccountName) 1456 } 1457 } else { 1458 tenantCtx := defines.AttachAccount(ctx, tenantInfo.GetTenantID(), tenantInfo.GetUserID(), uint32(accountAdminRoleID)) 1459 1460 // get system variable from mo_mysql_compatibility mode 1461 sqlForGetVariables := getSystemVariablesWithAccount(uint64(tenantInfo.GetTenantID())) 1462 mp := ses.GetMemPool() 1463 1464 rsset, err = executeSQLInBackgroundSession( 1465 tenantCtx, 1466 ses, 1467 mp, 1468 sqlForGetVariables) 1469 if err != nil { 1470 return err 1471 } 1472 if execResultArrayHasData(rsset) { 1473 for i := uint64(0); i < rsset[0].GetRowCount(); i++ { 1474 variable_name, err := rsset[0].GetString(tenantCtx, i, 0) 1475 if err != nil { 1476 return err 1477 } 1478 variable_value, err := rsset[0].GetString(tenantCtx, i, 1) 1479 if err != nil { 1480 return err 1481 } 1482 1483 if sv, ok := gSysVarsDefs[variable_name]; ok { 1484 if !sv.Dynamic || sv.GetScope() == ScopeSession { 1485 continue 1486 } 1487 val, err := sv.GetType().ConvertFromString(variable_value) 1488 if err != nil { 1489 return err 1490 } 1491 err = ses.InitSetSessionVar(tenantCtx, variable_name, val) 1492 if err != nil { 1493 return err 1494 } 1495 } 1496 } 1497 } else { 1498 return moerr.NewInternalError(tenantCtx, "there is no data in mo_mysql_compatibility_mode table for account %s", tenantInfo.GetTenant()) 1499 } 1500 } 1501 return err 1502 } 1503 1504 func (ses *Session) GetPrivilege() *privilege { 1505 ses.mu.Lock() 1506 defer ses.mu.Unlock() 1507 return ses.priv 1508 } 1509 1510 func (ses *Session) SetPrivilege(priv *privilege) { 1511 ses.mu.Lock() 1512 defer ses.mu.Unlock() 1513 ses.priv = priv 1514 } 1515 1516 func (ses *Session) SetFromRealUser(b bool) { 1517 ses.mu.Lock() 1518 defer ses.mu.Unlock() 1519 ses.fromRealUser = b 1520 } 1521 1522 func (ses *Session) GetFromRealUser() bool { 1523 ses.mu.Lock() 1524 defer ses.mu.Unlock() 1525 return ses.fromRealUser 1526 } 1527 1528 func changeVersion(ctx context.Context, ses *Session, db string) error { 1529 var err error 1530 if _, ok := bannedCatalogDatabases[db]; ok { 1531 return err 1532 } 1533 version, _ := GetVersionCompatibility(ctx, ses, db) 1534 if ses.GetTenantInfo() != nil { 1535 ses.GetTenantInfo().SetVersion(version) 1536 } 1537 return err 1538 } 1539 1540 // getCNLabels returns requested CN labels. 1541 func (ses *Session) getCNLabels() map[string]string { 1542 return ses.requestLabel 1543 } 1544 1545 // getSystemVariableValue get the system vaiables value from the mo_mysql_compatibility_mode table 1546 func (ses *Session) GetGlobalSystemVariableValue(ctx context.Context, varName string) (val interface{}, err error) { 1547 var sql string 1548 //var err error 1549 var erArray []ExecResult 1550 var accountId uint32 1551 var variableValue string 1552 // check the variable name isValid or not 1553 _, err = ses.GetGlobalVar(ctx, varName) 1554 if err != nil { 1555 return nil, err 1556 } 1557 1558 bh := ses.GetBackgroundExec(ctx) 1559 defer bh.Close() 1560 1561 err = bh.Exec(ctx, "begin;") 1562 defer func() { 1563 err = finishTxn(ctx, bh, err) 1564 }() 1565 if err != nil { 1566 return nil, err 1567 } 1568 if tenantInfo := ses.GetTenantInfo(); tenantInfo != nil { 1569 accountId = tenantInfo.GetTenantID() 1570 } 1571 sql = getSqlForGetSystemVariableValueWithAccount(uint64(accountId), varName) 1572 1573 bh.ClearExecResultSet() 1574 err = bh.Exec(ctx, sql) 1575 if err != nil { 1576 return nil, err 1577 } 1578 1579 erArray, err = getResultSet(ctx, bh) 1580 if err != nil { 1581 return nil, err 1582 } 1583 1584 if execResultArrayHasData(erArray) { 1585 variableValue, err = erArray[0].GetString(ctx, 0, 0) 1586 if err != nil { 1587 return nil, err 1588 } 1589 if sv, ok := gSysVarsDefs[varName]; ok { 1590 val, err = sv.GetType().ConvertFromString(variableValue) 1591 if err != nil { 1592 return nil, err 1593 } 1594 return val, nil 1595 } 1596 } 1597 1598 return nil, moerr.NewInternalError(ctx, "can not resolve global system variable %s", varName) 1599 } 1600 1601 func (ses *Session) SetNewResponse(category int, affectedRows uint64, cmd int, d interface{}, isLastStmt bool) *Response { 1602 // If the stmt has next stmt, should add SERVER_MORE_RESULTS_EXISTS to the server status. 1603 var resp *Response 1604 if !isLastStmt { 1605 resp = NewResponse(category, affectedRows, 0, 0, 1606 ses.GetTxnHandler().GetServerStatus()|SERVER_MORE_RESULTS_EXISTS, cmd, d) 1607 } else { 1608 resp = NewResponse(category, affectedRows, 0, 0, ses.GetTxnHandler().GetServerStatus(), cmd, d) 1609 } 1610 return resp 1611 } 1612 1613 // StatusSession implements the queryservice.Session interface. 1614 func (ses *Session) StatusSession() *status.Session { 1615 var ( 1616 accountName string 1617 userName string 1618 roleName string 1619 ) 1620 1621 accountName, userName, roleName = getUserProfile(ses.GetTenantInfo()) 1622 //if the query is processing, the end time is invalid. 1623 //we can not clear the session info under this condition. 1624 if !ses.GetQueryInProgress() { 1625 endAt := ses.GetQueryEnd() 1626 //if the current time is more than 3 second after the query end time, the session is timeout. 1627 //we clear the session statement info 1628 //for issue 11976 1629 if time.Since(endAt) > 3*time.Second { 1630 return &status.Session{ 1631 NodeID: ses.getRoutineManager().baseService.ID(), 1632 ConnID: ses.GetConnectionID(), 1633 SessionID: ses.GetUUIDString(), 1634 Account: accountName, 1635 User: userName, 1636 Host: ses.getRoutineManager().baseService.SQLAddress(), 1637 DB: ses.GetDatabaseName(), 1638 SessionStart: ses.GetSessionStart(), 1639 Command: "", 1640 Info: "", 1641 TxnID: uuid2Str(ses.GetTxnId()), 1642 StatementID: "", 1643 StatementType: "", 1644 QueryType: "", 1645 SQLSourceType: "", 1646 QueryStart: time.Time{}, 1647 ClientHost: ses.clientAddr, 1648 Role: roleName, 1649 FromProxy: ses.fromProxy, 1650 ProxyHost: ses.proxyAddr, 1651 } 1652 } 1653 } 1654 return &status.Session{ 1655 NodeID: ses.getRoutineManager().baseService.ID(), 1656 ConnID: ses.GetConnectionID(), 1657 SessionID: ses.GetUUIDString(), 1658 Account: accountName, 1659 User: userName, 1660 Host: ses.getRoutineManager().baseService.SQLAddress(), 1661 DB: ses.GetDatabaseName(), 1662 SessionStart: ses.GetSessionStart(), 1663 Command: ses.GetCmd().String(), 1664 Info: ses.GetSqlOfStmt(), 1665 TxnID: uuid2Str(ses.GetTxnId()), 1666 StatementID: ses.GetStmtId().String(), 1667 StatementType: ses.GetStmtType(), 1668 QueryType: ses.GetQueryType(), 1669 SQLSourceType: ses.GetSqlSourceType(), 1670 QueryStart: ses.GetQueryStart(), 1671 ClientHost: ses.clientAddr, 1672 Role: roleName, 1673 FromProxy: ses.fromProxy, 1674 ProxyHost: ses.proxyAddr, 1675 } 1676 } 1677 1678 // getStatusAfterTxnIsEnded 1679 // !!! only used after the txn is ended. 1680 // it may be called in the active txn. so, we 1681 func (ses *Session) getStatusAfterTxnIsEnded(ctx context.Context) uint16 { 1682 return extendStatus(ses.GetTxnHandler().GetServerStatus()) 1683 } 1684 1685 func uuid2Str(uid uuid.UUID) string { 1686 if bytes.Equal(uid[:], dumpUUID[:]) { 1687 return "" 1688 } 1689 return strings.ReplaceAll(uid.String(), "-", "") 1690 } 1691 1692 func (ses *Session) SetSessionRoutineStatus(status string) error { 1693 var err error 1694 if status == tree.AccountStatusRestricted.String() { 1695 ses.getRoutine().setResricted(true) 1696 } else if status == tree.AccountStatusSuspend.String() { 1697 ses.getRoutine().setResricted(false) 1698 } else if status == tree.AccountStatusOpen.String() { 1699 ses.getRoutine().setResricted(false) 1700 } else { 1701 err = moerr.NewInternalErrorNoCtx("SetSessionRoutineStatus have invalid status : %s", status) 1702 } 1703 return err 1704 } 1705 1706 func checkPlanIsInsertValues(proc *process.Process, 1707 p *plan.Plan) (bool, [][]colexec.ExpressionExecutor) { 1708 qry := p.GetQuery() 1709 if qry != nil { 1710 for _, node := range qry.Nodes { 1711 if node.NodeType == plan.Node_VALUE_SCAN && node.RowsetData != nil { 1712 exprList := make([][]colexec.ExpressionExecutor, len(node.RowsetData.Cols)) 1713 for i, col := range node.RowsetData.Cols { 1714 exprList[i] = make([]colexec.ExpressionExecutor, 0, len(col.Data)) 1715 for _, data := range col.Data { 1716 if data.Pos >= 0 { 1717 continue 1718 } 1719 expr, err := colexec.NewExpressionExecutor(proc, data.Expr) 1720 if err != nil { 1721 return false, nil 1722 } 1723 exprList[i] = append(exprList[i], expr) 1724 } 1725 } 1726 return true, exprList 1727 } 1728 } 1729 } 1730 return false, nil 1731 } 1732 1733 func commitAfterMigrate(ses *Session, err error) error { 1734 //if ses == nil { 1735 // logutil.Error("session is nil") 1736 // return moerr.NewInternalErrorNoCtx("session is nil") 1737 //} 1738 //txnHandler := ses.GetTxnHandler() 1739 //if txnHandler == nil { 1740 // logutil.Error("txn handler is nil") 1741 // return moerr.NewInternalErrorNoCtx("txn handler is nil") 1742 //} 1743 //if txnHandler.GetSession() == nil { 1744 // logutil.Error("ses in txn handler is nil") 1745 // return moerr.NewInternalErrorNoCtx("ses in txn handler is nil") 1746 //} 1747 //defer func() { 1748 // txnHandler.ClearServerStatus(SERVER_STATUS_IN_TRANS) 1749 // txnHandler.ClearOptionBits(OPTION_BEGIN) 1750 //}() 1751 //if err != nil { 1752 // if rErr := txnHandler.RollbackTxn(); rErr != nil { 1753 // logutil.Errorf("failed to rollback txn: %v", rErr) 1754 // } 1755 // return err 1756 //} else { 1757 // if cErr := txnHandler.CommitTxn(); cErr != nil { 1758 // logutil.Errorf("failed to commit txn: %v", cErr) 1759 // return cErr 1760 // } 1761 //} 1762 return nil 1763 } 1764 1765 type dbMigration struct { 1766 db string 1767 commitFn func(*Session, error) error 1768 } 1769 1770 func newDBMigration(db string) *dbMigration { 1771 return &dbMigration{ 1772 db: db, 1773 commitFn: commitAfterMigrate, 1774 } 1775 } 1776 1777 func (d *dbMigration) Migrate(ctx context.Context, ses *Session) error { 1778 if d.db == "" { 1779 return nil 1780 } 1781 tempExecCtx := &ExecCtx{ 1782 reqCtx: ctx, 1783 skipRespClient: true, 1784 ses: ses, 1785 } 1786 return doComQuery(ses, tempExecCtx, &UserInput{sql: "use " + d.db}) 1787 } 1788 1789 type prepareStmtMigration struct { 1790 name string 1791 sql string 1792 paramTypes []byte 1793 commitFn func(*Session, error) error 1794 } 1795 1796 func newPrepareStmtMigration(name string, sql string, paramTypes []byte) *prepareStmtMigration { 1797 return &prepareStmtMigration{ 1798 name: name, 1799 sql: sql, 1800 paramTypes: paramTypes, 1801 commitFn: commitAfterMigrate, 1802 } 1803 } 1804 1805 func (p *prepareStmtMigration) Migrate(ctx context.Context, ses *Session) error { 1806 if !strings.HasPrefix(strings.ToLower(p.sql), "prepare") { 1807 p.sql = fmt.Sprintf("prepare %s from %s", p.name, p.sql) 1808 } 1809 1810 tempExecCtx := &ExecCtx{ 1811 reqCtx: ctx, 1812 skipRespClient: true, 1813 ses: ses, 1814 executeParamTypes: p.paramTypes, 1815 } 1816 return doComQuery(ses, tempExecCtx, &UserInput{sql: p.sql}) 1817 } 1818 1819 func Migrate(ses *Session, req *query.MigrateConnToRequest) error { 1820 parameters := getGlobalPu().SV 1821 1822 //all offspring related to the request inherit the txnCtx 1823 cancelRequestCtx, cancelRequestFunc := context.WithTimeout(ses.GetTxnHandler().GetTxnCtx(), parameters.SessionTimeout.Duration) 1824 defer cancelRequestFunc() 1825 ses.UpdateDebugString() 1826 tenant := ses.GetTenantInfo() 1827 nodeCtx := cancelRequestCtx 1828 if ses.getRoutineManager() != nil && ses.getRoutineManager().baseService != nil { 1829 nodeCtx = context.WithValue(cancelRequestCtx, defines.NodeIDKey{}, ses.getRoutineManager().baseService.ID()) 1830 } 1831 ctx := defines.AttachAccount(nodeCtx, tenant.GetTenantID(), tenant.GetUserID(), tenant.GetDefaultRoleID()) 1832 1833 accountID, err := defines.GetAccountId(ctx) 1834 1835 if err != nil { 1836 logutil.Errorf("failed to get account ID: %v", err) 1837 return err 1838 } 1839 userID := defines.GetUserId(ctx) 1840 logutil.Infof("do migration on connection %d, db: %s, account id: %d, user id: %d", 1841 req.ConnID, req.DB, accountID, userID) 1842 1843 dbm := newDBMigration(req.DB) 1844 if err := dbm.Migrate(ctx, ses); err != nil { 1845 return err 1846 } 1847 1848 var maxStmtID uint32 1849 for _, p := range req.PrepareStmts { 1850 if p == nil { 1851 continue 1852 } 1853 pm := newPrepareStmtMigration(p.Name, p.SQL, p.ParamTypes) 1854 if err := pm.Migrate(ctx, ses); err != nil { 1855 return err 1856 } 1857 id := parsePrepareStmtID(p.Name) 1858 if id > maxStmtID { 1859 maxStmtID = id 1860 } 1861 } 1862 if maxStmtID > 0 { 1863 ses.SetLastStmtID(maxStmtID) 1864 } 1865 return nil 1866 }