github.com/matrixorigin/matrixone@v1.2.0/pkg/frontend/back_exec.go (about) 1 // Copyright 2022 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 "context" 19 "fmt" 20 "strings" 21 "time" 22 23 "github.com/matrixorigin/matrixone/pkg/pb/timestamp" 24 "github.com/matrixorigin/matrixone/pkg/sql/compile" 25 26 "github.com/google/uuid" 27 28 "github.com/matrixorigin/matrixone/pkg/common/buffer" 29 "github.com/matrixorigin/matrixone/pkg/common/moerr" 30 "github.com/matrixorigin/matrixone/pkg/common/mpool" 31 "github.com/matrixorigin/matrixone/pkg/container/batch" 32 "github.com/matrixorigin/matrixone/pkg/defines" 33 "github.com/matrixorigin/matrixone/pkg/logutil" 34 "github.com/matrixorigin/matrixone/pkg/pb/plan" 35 "github.com/matrixorigin/matrixone/pkg/sql/parsers" 36 "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect/mysql" 37 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 38 plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan" 39 "github.com/matrixorigin/matrixone/pkg/util/trace" 40 "github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace" 41 "github.com/matrixorigin/matrixone/pkg/vm/engine" 42 "github.com/matrixorigin/matrixone/pkg/vm/process" 43 ) 44 45 type backExec struct { 46 backSes *backSession 47 } 48 49 func (back *backExec) Close() { 50 back.Clear() 51 back.backSes.Close() 52 back.backSes.Clear() 53 back.backSes = nil 54 } 55 56 func (back *backExec) Exec(ctx context.Context, sql string) error { 57 if ctx == nil { 58 return moerr.NewInternalError(context.Background(), "context is nil") 59 } 60 _, err := defines.GetAccountId(ctx) 61 if err != nil { 62 return err 63 } 64 65 // For determine this is a background sql. 66 ctx = context.WithValue(ctx, defines.BgKey{}, true) 67 //logutil.Debugf("-->bh:%s", sql) 68 v, err := back.backSes.GetGlobalVar(ctx, "lower_case_table_names") 69 if err != nil { 70 return err 71 } 72 statements, err := mysql.Parse(ctx, sql, v.(int64), 0) 73 if err != nil { 74 return err 75 } 76 defer func() { 77 for _, stmt := range statements { 78 stmt.Free() 79 } 80 }() 81 if len(statements) > 1 { 82 return moerr.NewInternalError(ctx, "Exec() can run one statement at one time. but get '%d' statements now, sql = %s", len(statements), sql) 83 } 84 //share txn can not run transaction statement 85 if back.backSes.GetTxnHandler().IsShareTxn() { 86 for _, stmt := range statements { 87 switch stmt.(type) { 88 case *tree.BeginTransaction, *tree.CommitTransaction, *tree.RollbackTransaction: 89 return moerr.NewInternalError(ctx, "Exec() can not run transaction statement in share transaction, sql = %s", sql) 90 } 91 } 92 } 93 execCtx := ExecCtx{ 94 reqCtx: ctx, 95 ses: back.backSes, 96 } 97 return doComQueryInBack(back.backSes, &execCtx, &UserInput{sql: sql}) 98 } 99 100 func (back *backExec) ExecRestore(ctx context.Context, sql string, opAccount uint32, toAccount uint32) error { 101 if ctx == nil { 102 return moerr.NewInternalError(context.Background(), "context is nil") 103 } 104 _, err := defines.GetAccountId(ctx) 105 if err != nil { 106 return err 107 } 108 109 // For determine this is a background sql. 110 ctx = context.WithValue(ctx, defines.BgKey{}, true) 111 //logutil.Debugf("-->bh:%s", sql) 112 v, err := back.backSes.GetGlobalVar(ctx, "lower_case_table_names") 113 if err != nil { 114 return err 115 } 116 statements, err := mysql.Parse(ctx, sql, v.(int64), 0) 117 if err != nil { 118 return err 119 } 120 defer func() { 121 for _, stmt := range statements { 122 stmt.Free() 123 } 124 }() 125 if len(statements) > 1 { 126 return moerr.NewInternalError(ctx, "Exec() can run one statement at one time. but get '%d' statements now, sql = %s", len(statements), sql) 127 } 128 //share txn can not run transaction statement 129 if back.backSes.GetTxnHandler().IsShareTxn() { 130 for _, stmt := range statements { 131 switch stmt.(type) { 132 case *tree.BeginTransaction, *tree.CommitTransaction, *tree.RollbackTransaction: 133 return moerr.NewInternalError(ctx, "Exec() can not run transaction statement in share transaction, sql = %s", sql) 134 } 135 } 136 } 137 138 userInput := &UserInput{ 139 sql: sql, 140 isRestore: true, 141 opAccount: opAccount, 142 toAccount: toAccount, 143 } 144 145 execCtx := ExecCtx{ 146 reqCtx: ctx, 147 ses: back.backSes, 148 } 149 return doComQueryInBack(back.backSes, &execCtx, userInput) 150 } 151 152 func (back *backExec) ExecStmt(ctx context.Context, statement tree.Statement) error { 153 return nil 154 } 155 156 func (back *backExec) GetExecResultSet() []interface{} { 157 mrs := back.backSes.allResultSet 158 ret := make([]interface{}, len(mrs)) 159 for i, mr := range mrs { 160 ret[i] = mr 161 } 162 return ret 163 } 164 165 func (back *backExec) ClearExecResultSet() { 166 back.backSes.allResultSet = nil 167 } 168 169 func (back *backExec) GetExecResultBatches() []*batch.Batch { 170 return back.backSes.resultBatches 171 } 172 173 func (back *backExec) ClearExecResultBatches() { 174 back.backSes.resultBatches = nil 175 } 176 177 func (back *backExec) Clear() { 178 back.backSes.Clear() 179 } 180 181 // execute query 182 func doComQueryInBack(backSes *backSession, execCtx *ExecCtx, 183 input *UserInput) (retErr error) { 184 backSes.GetTxnCompileCtx().SetExecCtx(execCtx) 185 backSes.SetSql(input.getSql()) 186 //the ses.GetUserName returns the user_name with the account_name. 187 //here,we only need the user_name. 188 userNameOnly := rootName 189 proc := process.New( 190 execCtx.reqCtx, 191 backSes.pool, 192 getGlobalPu().TxnClient, 193 nil, 194 getGlobalPu().FileService, 195 getGlobalPu().LockService, 196 getGlobalPu().QueryClient, 197 getGlobalPu().HAKeeperClient, 198 getGlobalPu().UdfService, 199 getGlobalAic()) 200 proc.Id = backSes.getNextProcessId() 201 proc.Lim.Size = getGlobalPu().SV.ProcessLimitationSize 202 proc.Lim.BatchRows = getGlobalPu().SV.ProcessLimitationBatchRows 203 proc.Lim.MaxMsgSize = getGlobalPu().SV.MaxMessageSize 204 proc.Lim.PartitionRows = getGlobalPu().SV.ProcessLimitationPartitionRows 205 proc.SessionInfo = process.SessionInfo{ 206 User: backSes.proto.GetUserName(), 207 Host: getGlobalPu().SV.Host, 208 Database: backSes.proto.GetDatabaseName(), 209 Version: makeServerVersion(getGlobalPu(), serverVersion.Load().(string)), 210 TimeZone: backSes.GetTimeZone(), 211 StorageEngine: getGlobalPu().StorageEngine, 212 Buf: backSes.buf, 213 } 214 proc.SetStmtProfile(&backSes.stmtProfile) 215 proc.SetResolveVariableFunc(backSes.txnCompileCtx.ResolveVariable) 216 //!!!does not init sequence in the background exec 217 if backSes.tenant != nil { 218 proc.SessionInfo.Account = backSes.tenant.GetTenant() 219 proc.SessionInfo.AccountId = backSes.tenant.GetTenantID() 220 proc.SessionInfo.Role = backSes.tenant.GetDefaultRole() 221 proc.SessionInfo.RoleId = backSes.tenant.GetDefaultRoleID() 222 proc.SessionInfo.UserId = backSes.tenant.GetUserID() 223 224 if len(backSes.tenant.GetVersion()) != 0 { 225 proc.SessionInfo.Version = backSes.tenant.GetVersion() 226 } 227 userNameOnly = backSes.tenant.GetUser() 228 } else { 229 var accountId uint32 230 accountId, retErr = defines.GetAccountId(execCtx.reqCtx) 231 if retErr != nil { 232 return retErr 233 } 234 proc.SessionInfo.AccountId = accountId 235 proc.SessionInfo.UserId = defines.GetUserId(execCtx.reqCtx) 236 proc.SessionInfo.RoleId = defines.GetRoleId(execCtx.reqCtx) 237 } 238 var span trace.Span 239 execCtx.reqCtx, span = trace.Start(execCtx.reqCtx, "backExec.doComQueryInBack", 240 trace.WithKind(trace.SpanKindStatement)) 241 defer span.End() 242 execCtx.input = input 243 244 proc.SessionInfo.User = userNameOnly 245 cws, err := GetComputationWrapperInBack(execCtx, backSes.proto.GetDatabaseName(), 246 input, 247 backSes.proto.GetUserName(), 248 getGlobalPu().StorageEngine, 249 proc, backSes) 250 251 if err != nil { 252 retErr = err 253 if _, ok := err.(*moerr.Error); !ok { 254 retErr = moerr.NewParseError(execCtx.reqCtx, err.Error()) 255 } 256 return retErr 257 } 258 259 defer func() { 260 backSes.SetMysqlResultSet(nil) 261 }() 262 263 defer func() { 264 execCtx.stmt = nil 265 execCtx.cw = nil 266 execCtx.cws = nil 267 for i := 0; i < len(cws); i++ { 268 cws[i].Free() 269 } 270 }() 271 272 sqlRecord := parsers.HandleSqlForRecord(input.getSql()) 273 274 for i, cw := range cws { 275 backSes.mrs = &MysqlResultSet{} 276 stmt := cw.GetAst() 277 278 if insertStmt, ok := stmt.(*tree.Insert); ok && input.isRestore { 279 insertStmt.IsRestore = true 280 insertStmt.FromDataTenantID = input.opAccount 281 } 282 283 tenant := backSes.GetTenantNameWithStmt(stmt) 284 285 /* 286 if it is in an active or multi-statement transaction, we check the type of the statement. 287 Then we decide that if we can execute the statement. 288 289 If we check the active transaction, it will generate the case below. 290 case: 291 set autocommit = 0; <- no active transaction 292 <- no active transaction 293 drop table test1; <- no active transaction, no error 294 <- has active transaction 295 drop table test1; <- has active transaction, error 296 <- has active transaction 297 */ 298 if backSes.GetTxnHandler().InActiveTxn() { 299 err = canExecuteStatementInUncommittedTransaction(execCtx.reqCtx, backSes, stmt) 300 if err != nil { 301 return err 302 } 303 } 304 305 execCtx.stmt = stmt 306 execCtx.isLastStmt = i >= len(cws)-1 307 execCtx.tenant = tenant 308 execCtx.userName = userNameOnly 309 execCtx.sqlOfStmt = sqlRecord[i] 310 execCtx.cw = cw 311 execCtx.proc = proc 312 execCtx.ses = backSes 313 execCtx.cws = cws 314 err = executeStmtWithTxn(backSes, execCtx) 315 if err != nil { 316 return err 317 } 318 } // end of for 319 320 return nil 321 } 322 323 func executeStmtInBack(backSes *backSession, 324 execCtx *ExecCtx, 325 ) (err error) { 326 var cmpBegin time.Time 327 var ret interface{} 328 329 switch execCtx.stmt.StmtKind().ExecLocation() { 330 case tree.EXEC_IN_FRONTEND: 331 return execInFrontendInBack(backSes, execCtx) 332 case tree.EXEC_IN_ENGINE: 333 } 334 335 switch st := execCtx.stmt.(type) { 336 case *tree.CreateDatabase: 337 err = inputNameIsInvalid(execCtx.reqCtx, string(st.Name)) 338 if err != nil { 339 return 340 } 341 if st.SubscriptionOption != nil && backSes.tenant != nil && !backSes.tenant.IsAdminRole() { 342 err = moerr.NewInternalError(execCtx.reqCtx, "only admin can create subscription") 343 return 344 } 345 st.Sql = execCtx.sqlOfStmt 346 case *tree.DropDatabase: 347 err = inputNameIsInvalid(execCtx.reqCtx, string(st.Name)) 348 if err != nil { 349 return 350 } 351 // if the droped database is the same as the one in use, database must be reseted to empty. 352 if string(st.Name) == backSes.GetDatabaseName() { 353 backSes.SetDatabaseName("") 354 } 355 } 356 357 cmpBegin = time.Now() 358 359 if ret, err = execCtx.cw.Compile(execCtx, backSes.GetOutputCallback(execCtx)); err != nil { 360 return 361 } 362 363 defer func() { 364 if c, ok := ret.(*compile.Compile); ok { 365 c.Release() 366 } 367 }() 368 369 // cw.Compile may rewrite the stmt in the EXECUTE statement, we fetch the latest version 370 //need to check again. 371 execCtx.stmt = execCtx.cw.GetAst() 372 switch execCtx.stmt.StmtKind().ExecLocation() { 373 case tree.EXEC_IN_FRONTEND: 374 return execInFrontendInBack(backSes, execCtx) 375 case tree.EXEC_IN_ENGINE: 376 377 } 378 379 execCtx.runner = ret.(ComputationRunner) 380 381 // only log if build time is longer than 1s 382 if time.Since(cmpBegin) > time.Second { 383 logInfo(backSes, backSes.GetDebugString(), fmt.Sprintf("time of Exec.Build : %s", time.Since(cmpBegin).String())) 384 } 385 386 StmtKind := execCtx.stmt.StmtKind().OutputType() 387 switch StmtKind { 388 case tree.OUTPUT_RESULT_ROW: 389 err = executeResultRowStmtInBack(backSes, execCtx) 390 if err != nil { 391 return err 392 } 393 case tree.OUTPUT_STATUS: 394 err = executeStatusStmtInBack(backSes, execCtx) 395 if err != nil { 396 return err 397 } 398 case tree.OUTPUT_UNDEFINED: 399 isExecute := false 400 switch execCtx.stmt.(type) { 401 case *tree.Execute: 402 isExecute = true 403 } 404 if !isExecute { 405 return moerr.NewInternalError(execCtx.reqCtx, "need set result type for %s", execCtx.sqlOfStmt) 406 } 407 } 408 409 return 410 } 411 412 var GetComputationWrapperInBack = func(execCtx *ExecCtx, db string, input *UserInput, user string, eng engine.Engine, proc *process.Process, ses FeSession) ([]ComputationWrapper, error) { 413 var cw []ComputationWrapper = nil 414 415 var stmts []tree.Statement = nil 416 var cmdFieldStmt *InternalCmdFieldList 417 var err error 418 // if the input is an option ast, we should use it directly 419 if input.getStmt() != nil { 420 stmts = append(stmts, input.getStmt()) 421 } else if isCmdFieldListSql(input.getSql()) { 422 cmdFieldStmt, err = parseCmdFieldList(execCtx.reqCtx, input.getSql()) 423 if err != nil { 424 return nil, err 425 } 426 stmts = append(stmts, cmdFieldStmt) 427 } else { 428 stmts, err = parseSql(execCtx) 429 if err != nil { 430 return nil, err 431 } 432 } 433 434 for _, stmt := range stmts { 435 cw = append(cw, InitTxnComputationWrapper(ses, stmt, proc)) 436 } 437 return cw, nil 438 } 439 440 var NewBackgroundExec = func( 441 reqCtx context.Context, 442 upstream FeSession, 443 mp *mpool.MPool) BackgroundExec { 444 txnHandler := InitTxnHandler(getGlobalPu().StorageEngine, upstream.GetTxnHandler().GetConnCtx(), nil) 445 backSes := &backSession{ 446 feSessionImpl: feSessionImpl{ 447 pool: mp, 448 proto: &FakeProtocol{}, 449 buf: buffer.New(), 450 stmtProfile: process.StmtProfile{}, 451 tenant: nil, 452 txnHandler: txnHandler, 453 txnCompileCtx: InitTxnCompilerContext(""), 454 mrs: nil, 455 outputCallback: fakeDataSetFetcher2, 456 allResultSet: nil, 457 resultBatches: nil, 458 derivedStmt: false, 459 gSysVars: GSysVariables, 460 label: make(map[string]string), 461 timeZone: time.Local, 462 }, 463 } 464 backSes.uuid, _ = uuid.NewV7() 465 bh := &backExec{ 466 backSes: backSes, 467 } 468 469 return bh 470 } 471 472 // executeSQLInBackgroundSession executes the sql in an independent session and transaction. 473 // It sends nothing to the client. 474 func executeSQLInBackgroundSession(reqCtx context.Context, upstream *Session, mp *mpool.MPool, sql string) ([]ExecResult, error) { 475 bh := NewBackgroundExec(reqCtx, upstream, mp) 476 defer bh.Close() 477 logutil.Debugf("background exec sql:%v", sql) 478 err := bh.Exec(reqCtx, sql) 479 logutil.Debugf("background exec sql done") 480 if err != nil { 481 return nil, err 482 } 483 return getResultSet(reqCtx, bh) 484 } 485 486 // executeStmtInSameSession executes the statement in the same session. 487 // To be clear, only for the select statement derived from the set_var statement 488 // in an independent transaction 489 func executeStmtInSameSession(ctx context.Context, ses *Session, execCtx *ExecCtx, stmt tree.Statement) error { 490 switch stmt.(type) { 491 case *tree.Select, *tree.ParenSelect: 492 default: 493 return moerr.NewInternalError(ctx, "executeStmtInSameSession can not run non select statement in the same session") 494 } 495 496 if ses.GetTxnHandler() == nil { 497 panic("need txn handler 3") 498 } 499 500 prevDB := ses.GetDatabaseName() 501 prevOptionBits := ses.GetTxnHandler().GetOptionBits() 502 prevServerStatus := ses.GetTxnHandler().GetServerStatus() 503 //autocommit = on 504 ses.GetTxnHandler().setAutocommitOn() 505 //1. replace output callback by batchFetcher. 506 // the result batch will be saved in the session. 507 // you can get the result batch by calling GetResultBatches() 508 ses.SetOutputCallback(batchFetcher) 509 //2. replace protocol by FakeProtocol. 510 // Any response yielded during running query will be dropped by the FakeProtocol. 511 // The client will not receive any response from the FakeProtocol. 512 prevProto := ses.ReplaceProtocol(&FakeProtocol{}) 513 //3. replace the derived stmt 514 prevDerivedStmt := ses.ReplaceDerivedStmt(true) 515 // inherit database 516 ses.SetDatabaseName(prevDB) 517 proc := ses.GetTxnCompileCtx().GetProcess() 518 //restore normal protocol and output callback 519 defer func() { 520 ses.ReplaceDerivedStmt(prevDerivedStmt) 521 //@todo we need to improve: make one session, one proc, one txnOperator 522 p := ses.GetTxnCompileCtx().GetProcess() 523 p.FreeVectors() 524 execCtx.proc = proc 525 ses.GetTxnHandler().SetOptionBits(prevOptionBits) 526 ses.GetTxnHandler().SetServerStatus(prevServerStatus) 527 ses.SetOutputCallback(getDataFromPipeline) 528 ses.ReplaceProtocol(prevProto) 529 if ses.GetTxnHandler() == nil { 530 panic("need txn handler 4") 531 } 532 }() 533 logDebug(ses, ses.GetDebugString(), "query trace(ExecStmtInSameSession)", 534 logutil.ConnectionIdField(ses.GetConnectionID())) 535 //3. execute the statement 536 return doComQuery(ses, execCtx, &UserInput{stmt: stmt}) 537 } 538 539 // fakeDataSetFetcher2 gets the result set from the pipeline and save it in the session. 540 // It will not send the result to the client. 541 func fakeDataSetFetcher2(handle FeSession, execCtx *ExecCtx, dataSet *batch.Batch) error { 542 if handle == nil || dataSet == nil { 543 return nil 544 } 545 546 back := handle.(*backSession) 547 oq := newFakeOutputQueue(back.mrs) 548 err := fillResultSet(execCtx.reqCtx, oq, dataSet, back) 549 if err != nil { 550 return err 551 } 552 back.SetMysqlResultSetOfBackgroundTask(back.mrs) 553 return nil 554 } 555 556 func fillResultSet(ctx context.Context, oq outputPool, dataSet *batch.Batch, ses FeSession) error { 557 n := dataSet.RowCount() 558 for j := 0; j < n; j++ { //row index 559 //needCopyBytes = true. we need to copy the bytes from the batch.Batch 560 //to avoid the data being changed after the batch.Batch returned to the 561 //pipeline. 562 _, err := extractRowFromEveryVector(ctx, ses, dataSet, j, oq, true) 563 if err != nil { 564 return err 565 } 566 } 567 return oq.flush() 568 } 569 570 // batchFetcher2 gets the result batches from the pipeline and save the origin batches in the session. 571 // It will not send the result to the client. 572 func batchFetcher2(handle FeSession, _ *ExecCtx, dataSet *batch.Batch) error { 573 if handle == nil { 574 return nil 575 } 576 back := handle.(*backSession) 577 back.SaveResultSet() 578 if dataSet == nil { 579 return nil 580 } 581 return back.AppendResultBatch(dataSet) 582 } 583 584 // batchFetcher gets the result batches from the pipeline and save the origin batches in the session. 585 // It will not send the result to the client. 586 func batchFetcher(handle FeSession, _ *ExecCtx, dataSet *batch.Batch) error { 587 if handle == nil { 588 return nil 589 } 590 ses := handle.(*Session) 591 ses.SaveResultSet() 592 if dataSet == nil { 593 return nil 594 } 595 return ses.AppendResultBatch(dataSet) 596 } 597 598 // getResultSet extracts the result set 599 func getResultSet(ctx context.Context, bh BackgroundExec) ([]ExecResult, error) { 600 results := bh.GetExecResultSet() 601 rsset := make([]ExecResult, len(results)) 602 for i, value := range results { 603 if er, ok := value.(ExecResult); ok { 604 rsset[i] = er 605 } else { 606 return nil, moerr.NewInternalError(ctx, "it is not the type of result set") 607 } 608 } 609 return rsset, nil 610 } 611 612 type backSession struct { 613 feSessionImpl 614 } 615 616 func (backSes *backSession) getCachedPlan(sql string) *cachedPlan { 617 return nil 618 } 619 620 func (backSes *backSession) Close() { 621 backSes.feSessionImpl.Close() 622 } 623 624 func (backSes *backSession) Clear() { 625 backSes.feSessionImpl.Clear() 626 } 627 628 func (backSes *backSession) GetOutputCallback(execCtx *ExecCtx) func(*batch.Batch) error { 629 return func(bat *batch.Batch) error { 630 return backSes.outputCallback(backSes, execCtx, bat) 631 } 632 } 633 634 func (backSes *backSession) SetTStmt(stmt *motrace.StatementInfo) { 635 636 } 637 func (backSes *backSession) SendRows() int64 { 638 return 0 639 } 640 641 func (backSes *backSession) GetTxnInfo() string { 642 txnH := backSes.GetTxnHandler() 643 if txnH == nil { 644 return "" 645 } 646 txnOp := txnH.GetTxn() 647 if txnOp == nil { 648 return "" 649 } 650 meta := txnOp.Txn() 651 return meta.DebugString() 652 } 653 654 func (backSes *backSession) GetStmtInfo() *motrace.StatementInfo { 655 return nil 656 } 657 658 func (backSes *backSession) getNextProcessId() string { 659 /* 660 temporary method: 661 routineId + sqlCount 662 */ 663 routineId := backSes.GetMysqlProtocol().ConnectionID() 664 return fmt.Sprintf("%d%d", routineId, backSes.GetSqlCount()) 665 } 666 667 func (backSes *backSession) cleanCache() { 668 } 669 670 func (backSes *backSession) GetUpstream() FeSession { 671 return backSes.upstream 672 } 673 674 func (backSes *backSession) getCNLabels() map[string]string { 675 return backSes.label 676 } 677 678 func (backSes *backSession) SetData(i [][]interface{}) { 679 680 } 681 682 func (backSes *backSession) GetIsInternal() bool { 683 return false 684 } 685 686 func (backSes *backSession) SetPlan(plan *plan.Plan) { 687 } 688 689 func (backSes *backSession) GetRawBatchBackgroundExec(ctx context.Context) BackgroundExec { 690 //TODO implement me 691 panic("implement me") 692 } 693 694 func (backSes *backSession) GetConnectionID() uint32 { 695 return 0 696 } 697 698 func (backSes *backSession) getQueryId(internal bool) []string { 699 return nil 700 } 701 702 func (backSes *backSession) CopySeqToProc(proc *process.Process) { 703 704 } 705 706 func (backSes *backSession) GetSqlHelper() *SqlHelper { 707 return nil 708 } 709 710 func (backSes *backSession) GetProc() *process.Process { 711 return nil 712 } 713 714 func (backSes *backSession) GetLastInsertID() uint64 { 715 return 0 716 } 717 718 func (backSes *backSession) SetShowStmtType(statement ShowStatementType) { 719 } 720 721 func (backSes *backSession) RemovePrepareStmt(name string) { 722 723 } 724 725 func (backSes *backSession) CountPayload(i int) { 726 727 } 728 729 func (backSes *backSession) GetPrepareStmt(ctx context.Context, name string) (*PrepareStmt, error) { 730 return nil, moerr.NewInternalError(ctx, "do not support prepare in background exec") 731 } 732 733 func (backSes *backSession) IsBackgroundSession() bool { 734 return true 735 } 736 737 func (backSes *backSession) GetCmd() CommandType { 738 return COM_QUERY 739 } 740 741 func (backSes *backSession) SetNewResponse(category int, affectedRows uint64, cmd int, d interface{}, isLastStmt bool) *Response { 742 return nil 743 } 744 745 func (backSes *backSession) GetSqlOfStmt() string { 746 return "" 747 } 748 749 func (backSes *backSession) GetStmtId() uuid.UUID { 750 return [16]byte{} 751 } 752 753 // GetTenantName return tenant name according to GetTenantInfo and stmt. 754 // 755 // With stmt = nil, should be only called in TxnHandler.NewTxn, TxnHandler.CommitTxn, TxnHandler.RollbackTxn 756 func (backSes *backSession) GetTenantNameWithStmt(stmt tree.Statement) string { 757 tenant := sysAccountName 758 if backSes.GetTenantInfo() != nil && (stmt == nil || !IsPrepareStatement(stmt)) { 759 tenant = backSes.GetTenantInfo().GetTenant() 760 } 761 return tenant 762 } 763 764 func (backSes *backSession) GetTenantName() string { 765 return backSes.GetTenantNameWithStmt(nil) 766 } 767 768 func (backSes *backSession) GetFromRealUser() bool { 769 return false 770 } 771 772 func (backSes *backSession) GetDebugString() string { 773 return "" 774 } 775 776 func (backSes *backSession) GetUserDefinedVar(name string) (SystemVariableType, *UserDefinedVar, error) { 777 return nil, nil, moerr.NewInternalError(context.Background(), "do not support user defined var in background exec") 778 } 779 780 func (backSes *backSession) GetSessionVar(ctx context.Context, name string) (interface{}, error) { 781 switch strings.ToLower(name) { 782 case "autocommit": 783 return true, nil 784 } 785 return nil, nil 786 } 787 788 func (backSes *backSession) GetGlobalSystemVariableValue(ctx context.Context, name string) (interface{}, error) { 789 return nil, moerr.NewInternalError(ctx, "do not support system variable in background exec") 790 } 791 792 func (backSes *backSession) GetBackgroundExec(ctx context.Context) BackgroundExec { 793 return NewBackgroundExec( 794 ctx, 795 backSes, 796 backSes.GetMemPool()) 797 } 798 799 func (backSes *backSession) GetStorage() engine.Engine { 800 return getGlobalPu().StorageEngine 801 } 802 803 func (backSes *backSession) GetStatsCache() *plan2.StatsCache { 804 return nil 805 } 806 807 func (backSes *backSession) GetGlobalVar(ctx context.Context, name string) (interface{}, error) { 808 if def, val, ok := backSes.gSysVars.GetGlobalSysVar(name); ok { 809 if def.GetScope() == ScopeSession { 810 //empty 811 return nil, moerr.NewInternalError(ctx, errorSystemVariableSessionEmpty()) 812 } 813 return val, nil 814 } 815 return nil, moerr.NewInternalError(ctx, errorSystemVariableDoesNotExist()) 816 } 817 818 type SqlHelper struct { 819 ses *Session 820 } 821 822 func (sh *SqlHelper) GetCompilerContext() any { 823 return sh.ses.txnCompileCtx 824 } 825 826 func (sh *SqlHelper) GetSubscriptionMeta(dbName string) (*plan.SubscriptionMeta, error) { 827 return sh.ses.txnCompileCtx.GetSubscriptionMeta(dbName, plan2.Snapshot{TS: ×tamp.Timestamp{}}) 828 } 829 830 // Made for sequence func. nextval, setval. 831 func (sh *SqlHelper) ExecSql(sql string) (ret []interface{}, err error) { 832 var erArray []ExecResult 833 834 ctx := sh.ses.txnCompileCtx.execCtx.reqCtx 835 /* 836 if we run the transaction statement (BEGIN, ect) here , it creates an independent transaction. 837 if we do not run the transaction statement (BEGIN, ect) here, it runs the sql in the share transaction 838 and committed outside this function. 839 !!!NOTE: wen can not execute the transaction statement(BEGIN,COMMIT,ROLLBACK,START TRANSACTION ect) here. 840 */ 841 bh := sh.ses.GetShareTxnBackgroundExec(ctx, false) 842 defer bh.Close() 843 844 bh.ClearExecResultSet() 845 err = bh.Exec(ctx, sql) 846 if err != nil { 847 return nil, err 848 } 849 850 erArray, err = getResultSet(ctx, bh) 851 if err != nil { 852 return nil, err 853 } 854 855 if len(erArray) == 0 { 856 return nil, nil 857 } 858 859 return erArray[0].(*MysqlResultSet).Data[0], nil 860 }