github.com/matrixorigin/matrixone@v1.2.0/pkg/frontend/types.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 "io" 20 "time" 21 22 "github.com/fagongzi/goetty/v2/buf" 23 "github.com/google/uuid" 24 25 "github.com/matrixorigin/matrixone/pkg/common/buffer" 26 "github.com/matrixorigin/matrixone/pkg/common/mpool" 27 "github.com/matrixorigin/matrixone/pkg/config" 28 "github.com/matrixorigin/matrixone/pkg/pb/timestamp" 29 "github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace" 30 "github.com/matrixorigin/matrixone/pkg/vm/process" 31 32 "github.com/matrixorigin/matrixone/pkg/container/batch" 33 "github.com/matrixorigin/matrixone/pkg/container/types" 34 "github.com/matrixorigin/matrixone/pkg/container/vector" 35 "github.com/matrixorigin/matrixone/pkg/pb/plan" 36 "github.com/matrixorigin/matrixone/pkg/sql/colexec" 37 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 38 plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan" 39 "github.com/matrixorigin/matrixone/pkg/txn/client" 40 "github.com/matrixorigin/matrixone/pkg/util" 41 ) 42 43 const ( 44 DefaultRpcBufferSize = 1 << 10 45 ) 46 47 type ( 48 TxnOperator = client.TxnOperator 49 TxnClient = client.TxnClient 50 TxnOption = client.TxnOption 51 ) 52 53 type ComputationRunner interface { 54 Run(ts uint64) (*util.RunResult, error) 55 } 56 57 // ComputationWrapper is the wrapper of the computation 58 type ComputationWrapper interface { 59 ComputationRunner 60 GetAst() tree.Statement 61 62 GetProcess() *process.Process 63 64 GetColumns(ctx context.Context) ([]interface{}, error) 65 66 Compile(any any, fill func(*batch.Batch) error) (interface{}, error) 67 68 GetUUID() []byte 69 70 RecordExecPlan(ctx context.Context) error 71 72 GetLoadTag() bool 73 74 GetServerStatus() uint16 75 Clear() 76 Plan() *plan.Plan 77 ResetPlanAndStmt(stmt tree.Statement) 78 Free() 79 } 80 81 type ColumnInfo interface { 82 GetName() string 83 84 GetType() types.T 85 } 86 87 var _ ColumnInfo = &engineColumnInfo{} 88 89 type TableInfo interface { 90 GetColumns() 91 } 92 93 type engineColumnInfo struct { 94 name string 95 typ types.Type 96 } 97 98 func (ec *engineColumnInfo) GetName() string { 99 return ec.name 100 } 101 102 func (ec *engineColumnInfo) GetType() types.T { 103 return ec.typ.Oid 104 } 105 106 type PrepareStmt struct { 107 Name string 108 Sql string 109 PreparePlan *plan.Plan 110 PrepareStmt tree.Statement 111 ParamTypes []byte 112 IsInsertValues bool 113 InsertBat *batch.Batch 114 proc *process.Process 115 116 exprList [][]colexec.ExpressionExecutor 117 118 params *vector.Vector 119 getFromSendLongData map[int]struct{} 120 } 121 122 /* 123 Disguise the COMMAND CMD_FIELD_LIST as sql query. 124 */ 125 const ( 126 cmdFieldListSql = "__++__internal_cmd_field_list" 127 cmdFieldListSqlLen = len(cmdFieldListSql) 128 cloudUserTag = "cloud_user" 129 cloudNoUserTag = "cloud_nonuser" 130 saveResultTag = "save_result" 131 ) 132 133 var _ tree.Statement = &InternalCmdFieldList{} 134 135 // InternalCmdFieldList the CMD_FIELD_LIST statement 136 type InternalCmdFieldList struct { 137 tableName string 138 } 139 140 // Free implements tree.Statement. 141 func (icfl *InternalCmdFieldList) Free() { 142 } 143 144 func (icfl *InternalCmdFieldList) String() string { 145 return makeCmdFieldListSql(icfl.tableName) 146 } 147 148 func (icfl *InternalCmdFieldList) Format(ctx *tree.FmtCtx) { 149 ctx.WriteString(makeCmdFieldListSql(icfl.tableName)) 150 } 151 152 func (icfl *InternalCmdFieldList) StmtKind() tree.StmtKind { 153 return tree.MakeStmtKind(tree.OUTPUT_STATUS, tree.RESP_BY_SITUATION, tree.EXEC_IN_FRONTEND) 154 } 155 156 func (icfl *InternalCmdFieldList) GetStatementType() string { return "InternalCmd" } 157 func (icfl *InternalCmdFieldList) GetQueryType() string { return tree.QueryTypeDQL } 158 159 // ExecResult is the result interface of the execution 160 type ExecResult interface { 161 GetRowCount() uint64 162 163 GetString(ctx context.Context, rindex, cindex uint64) (string, error) 164 165 GetUint64(ctx context.Context, rindex, cindex uint64) (uint64, error) 166 167 GetInt64(ctx context.Context, rindex, cindex uint64) (int64, error) 168 } 169 170 func execResultArrayHasData(arr []ExecResult) bool { 171 return len(arr) != 0 && arr[0].GetRowCount() != 0 172 } 173 174 // BackgroundExec executes the sql in background session without network output. 175 type BackgroundExec interface { 176 Close() 177 Exec(context.Context, string) error 178 ExecRestore(context.Context, string, uint32, uint32) error 179 ExecStmt(context.Context, tree.Statement) error 180 GetExecResultSet() []interface{} 181 ClearExecResultSet() 182 183 GetExecResultBatches() []*batch.Batch 184 ClearExecResultBatches() 185 Clear() 186 } 187 188 var _ BackgroundExec = &backExec{} 189 190 type unknownStatementType struct { 191 tree.StatementType 192 } 193 194 func (unknownStatementType) GetStatementType() string { return "Unknown" } 195 func (unknownStatementType) GetQueryType() string { return tree.QueryTypeOth } 196 197 func getStatementType(stmt tree.Statement) tree.StatementType { 198 switch stmt.(type) { 199 case tree.StatementType: 200 return stmt 201 default: 202 return unknownStatementType{} 203 } 204 } 205 206 // TableInfoCache tableInfos of a database 207 //type TableInfoCache struct { 208 // db string 209 // tableInfos map[string][]ColumnInfo 210 //} 211 212 // outputPool outputs the data 213 type outputPool interface { 214 resetLineStr() 215 216 reset() 217 218 getEmptyRow() ([]interface{}, error) 219 220 flush() error 221 } 222 223 func (prepareStmt *PrepareStmt) Close() { 224 if prepareStmt.params != nil { 225 prepareStmt.params.Free(prepareStmt.proc.Mp()) 226 } 227 if prepareStmt.InsertBat != nil { 228 prepareStmt.InsertBat.SetCnt(1) 229 prepareStmt.InsertBat.Clean(prepareStmt.proc.Mp()) 230 prepareStmt.InsertBat = nil 231 } 232 if prepareStmt.exprList != nil { 233 for _, exprs := range prepareStmt.exprList { 234 for _, expr := range exprs { 235 expr.Free() 236 } 237 } 238 } 239 if prepareStmt.PrepareStmt != nil { 240 prepareStmt.PrepareStmt.Free() 241 } 242 } 243 244 var _ buf.Allocator = &SessionAllocator{} 245 246 type SessionAllocator struct { 247 mp *mpool.MPool 248 } 249 250 func NewSessionAllocator(pu *config.ParameterUnit) *SessionAllocator { 251 pool, err := mpool.NewMPool("frontend-goetty-pool-cn-level", pu.SV.GuestMmuLimitation, mpool.NoFixed) 252 if err != nil { 253 panic(err) 254 } 255 ret := &SessionAllocator{mp: pool} 256 return ret 257 } 258 259 func (s *SessionAllocator) Alloc(capacity int) []byte { 260 alloc, err := s.mp.Alloc(capacity) 261 if err != nil { 262 panic(err) 263 } 264 return alloc 265 } 266 267 func (s SessionAllocator) Free(bs []byte) { 268 s.mp.Free(bs) 269 } 270 271 var _ FeSession = &Session{} 272 var _ FeSession = &backSession{} 273 274 type FeSession interface { 275 GetTimeZone() *time.Location 276 GetStatsCache() *plan2.StatsCache 277 GetUserName() string 278 GetSql() string 279 GetAccountId() uint32 280 GetTenantInfo() *TenantInfo 281 GetBackgroundExec(ctx context.Context) BackgroundExec 282 GetRawBatchBackgroundExec(ctx context.Context) BackgroundExec 283 GetGlobalSystemVariableValue(ctx context.Context, name string) (interface{}, error) 284 GetSessionVar(ctx context.Context, name string) (interface{}, error) 285 GetUserDefinedVar(name string) (SystemVariableType, *UserDefinedVar, error) 286 GetDebugString() string 287 GetFromRealUser() bool 288 getLastCommitTS() timestamp.Timestamp 289 GetTenantName() string 290 SetTxnId(i []byte) 291 GetTxnId() uuid.UUID 292 GetStmtId() uuid.UUID 293 GetSqlOfStmt() string 294 updateLastCommitTS(ts timestamp.Timestamp) 295 GetMysqlProtocol() MysqlProtocol 296 GetTxnHandler() *TxnHandler 297 GetDatabaseName() string 298 SetDatabaseName(db string) 299 GetMysqlResultSet() *MysqlResultSet 300 GetGlobalVar(ctx context.Context, name string) (interface{}, error) 301 SetNewResponse(category int, affectedRows uint64, cmd int, d interface{}, isLastStmt bool) *Response 302 GetTxnCompileCtx() *TxnCompilerContext 303 GetCmd() CommandType 304 IsBackgroundSession() bool 305 GetPrepareStmt(ctx context.Context, name string) (*PrepareStmt, error) 306 CountPayload(i int) 307 RemovePrepareStmt(name string) 308 SetShowStmtType(statement ShowStatementType) 309 SetSql(sql string) 310 GetMemPool() *mpool.MPool 311 GetProc() *process.Process 312 GetLastInsertID() uint64 313 GetSqlHelper() *SqlHelper 314 GetBuffer() *buffer.Buffer 315 GetStmtProfile() *process.StmtProfile 316 CopySeqToProc(proc *process.Process) 317 getQueryId(internal bool) []string 318 SetMysqlResultSet(mrs *MysqlResultSet) 319 GetConnectionID() uint32 320 IsDerivedStmt() bool 321 SetAccountId(uint32) 322 SetPlan(plan *plan.Plan) 323 SetData([][]interface{}) 324 GetIsInternal() bool 325 getCNLabels() map[string]string 326 GetUpstream() FeSession 327 cleanCache() 328 getNextProcessId() string 329 GetSqlCount() uint64 330 addSqlCount(a uint64) 331 GetStmtInfo() *motrace.StatementInfo 332 GetTxnInfo() string 333 GetUUID() []byte 334 SendRows() int64 335 SetTStmt(stmt *motrace.StatementInfo) 336 GetUUIDString() string 337 DisableTrace() bool 338 Close() 339 Clear() 340 getCachedPlan(sql string) *cachedPlan 341 } 342 343 type ExecCtx struct { 344 reqCtx context.Context 345 prepareStmt *PrepareStmt 346 runResult *util.RunResult 347 //stmt will be replaced by the Execute 348 stmt tree.Statement 349 //isLastStmt : true denotes the last statement in the query 350 isLastStmt bool 351 // tenant name 352 tenant string 353 userName string 354 sqlOfStmt string 355 cw ComputationWrapper 356 runner ComputationRunner 357 loadLocalWriter *io.PipeWriter 358 proc *process.Process 359 proto MysqlProtocol 360 ses FeSession 361 txnOpt FeTxnOption 362 cws []ComputationWrapper 363 input *UserInput 364 //In the session migration, skip the response to the client 365 skipRespClient bool 366 //In the session migration, executeParamTypes for the EXECUTE stmt should be migrated 367 //from the old session to the new session. 368 executeParamTypes []byte 369 } 370 371 // outputCallBackFunc is the callback function to send the result to the client. 372 // parameters: 373 // 374 // FeSession 375 // ExecCtx 376 // batch.Batch 377 type outputCallBackFunc func(FeSession, *ExecCtx, *batch.Batch) error 378 379 // TODO: shared component among the session implmentation 380 type feSessionImpl struct { 381 pool *mpool.MPool 382 proto MysqlProtocol 383 buf *buffer.Buffer 384 stmtProfile process.StmtProfile 385 tenant *TenantInfo 386 txnHandler *TxnHandler 387 txnCompileCtx *TxnCompilerContext 388 mrs *MysqlResultSet 389 //it gets the result set from the pipeline and send it to the client 390 outputCallback outputCallBackFunc 391 392 //all the result set of executing the sql in background task 393 allResultSet []*MysqlResultSet 394 rs *plan.ResultColDef 395 396 // result batches of executing the sql in background task 397 // set by func batchFetcher 398 resultBatches []*batch.Batch 399 400 //derivedStmt denotes the sql or statement that derived from the user input statement. 401 //a new internal statement derived from the statement the user input and executed during 402 // the execution of it in the same transaction. 403 // 404 //For instance 405 // select nextval('seq_15') 406 // nextval internally will derive two sql (a select and an update). the two sql are executed 407 // in the same transaction. 408 derivedStmt bool 409 410 gSysVars *GlobalSystemVariables 411 // when starting a transaction in session, the snapshot ts of the transaction 412 // is to get a TN push to CN to get the maximum commitTS. but there is a problem, 413 // when the last transaction ends and the next one starts, it is possible that the 414 // log of the last transaction has not been pushed to CN, we need to wait until at 415 // least the commit of the last transaction log of the previous transaction arrives. 416 lastCommitTS timestamp.Timestamp 417 upstream *Session 418 sql string 419 accountId uint32 420 label map[string]string 421 timeZone *time.Location 422 423 sqlCount uint64 424 uuid uuid.UUID 425 debugStr string 426 disableTrace bool 427 } 428 429 func (ses *feSessionImpl) Close() { 430 ses.proto = nil 431 ses.mrs = nil 432 if ses.txnHandler != nil { 433 ses.txnHandler = nil 434 } 435 if ses.txnCompileCtx != nil { 436 ses.txnCompileCtx.execCtx = nil 437 ses.txnCompileCtx.snapshot = nil 438 ses.txnCompileCtx.views = nil 439 ses.txnCompileCtx = nil 440 } 441 ses.sql = "" 442 ses.gSysVars = nil 443 ses.allResultSet = nil 444 ses.tenant = nil 445 ses.debugStr = "" 446 ses.rs = nil 447 ses.ClearStmtProfile() 448 for _, bat := range ses.resultBatches { 449 bat.Clean(ses.pool) 450 } 451 if ses.buf != nil { 452 ses.buf.Free() 453 ses.buf = nil 454 } 455 ses.upstream = nil 456 } 457 458 func (ses *feSessionImpl) Clear() { 459 if ses == nil { 460 return 461 } 462 ses.ClearAllMysqlResultSet() 463 ses.ClearResultBatches() 464 } 465 466 func (ses *feSessionImpl) SetDatabaseName(db string) { 467 ses.proto.SetDatabaseName(db) 468 ses.txnCompileCtx.SetDatabase(db) 469 } 470 471 func (ses *feSessionImpl) GetDatabaseName() string { 472 return ses.proto.GetDatabaseName() 473 } 474 475 func (ses *feSessionImpl) GetUserName() string { 476 return ses.proto.GetUserName() 477 } 478 479 func (ses *feSessionImpl) DisableTrace() bool { 480 return ses.disableTrace 481 } 482 483 func (ses *feSessionImpl) SetMemPool(mp *mpool.MPool) { 484 ses.pool = mp 485 } 486 487 func (ses *feSessionImpl) GetMemPool() *mpool.MPool { 488 return ses.pool 489 } 490 491 func (ses *feSessionImpl) GetMysqlProtocol() MysqlProtocol { 492 return ses.proto 493 } 494 495 func (ses *feSessionImpl) ReplaceProtocol(proto MysqlProtocol) MysqlProtocol { 496 old := ses.proto 497 ses.proto = proto 498 return old 499 } 500 501 func (ses *feSessionImpl) GetBuffer() *buffer.Buffer { 502 return ses.buf 503 } 504 505 func (ses *feSessionImpl) GetStmtProfile() *process.StmtProfile { 506 return &ses.stmtProfile 507 } 508 509 func (ses *feSessionImpl) ClearStmtProfile() { 510 ses.stmtProfile.Clear() 511 } 512 513 func (ses *feSessionImpl) SetTxnId(id []byte) { 514 ses.stmtProfile.SetTxnId(id) 515 } 516 517 func (ses *feSessionImpl) GetTxnId() uuid.UUID { 518 return ses.stmtProfile.GetTxnId() 519 } 520 521 func (ses *feSessionImpl) SetStmtId(id uuid.UUID) { 522 ses.stmtProfile.SetStmtId(id) 523 } 524 525 func (ses *feSessionImpl) GetStmtId() uuid.UUID { 526 return ses.stmtProfile.GetStmtId() 527 } 528 529 func (ses *feSessionImpl) SetStmtType(st string) { 530 ses.stmtProfile.SetStmtType(st) 531 } 532 533 func (ses *feSessionImpl) GetStmtType() string { 534 return ses.stmtProfile.GetStmtType() 535 } 536 537 func (ses *feSessionImpl) SetQueryType(qt string) { 538 ses.stmtProfile.SetQueryType(qt) 539 } 540 541 func (ses *feSessionImpl) GetQueryType() string { 542 return ses.stmtProfile.GetQueryType() 543 } 544 545 func (ses *feSessionImpl) SetSqlSourceType(st string) { 546 ses.stmtProfile.SetSqlSourceType(st) 547 } 548 549 func (ses *feSessionImpl) GetSqlSourceType() string { 550 return ses.stmtProfile.GetSqlSourceType() 551 } 552 553 func (ses *feSessionImpl) SetQueryStart(t time.Time) { 554 ses.stmtProfile.SetQueryStart(t) 555 } 556 557 func (ses *feSessionImpl) GetQueryStart() time.Time { 558 return ses.stmtProfile.GetQueryStart() 559 } 560 561 func (ses *feSessionImpl) SetSqlOfStmt(sot string) { 562 ses.stmtProfile.SetSqlOfStmt(sot) 563 } 564 565 func (ses *feSessionImpl) GetSqlOfStmt() string { 566 return ses.stmtProfile.GetSqlOfStmt() 567 } 568 569 func (ses *feSessionImpl) GetTenantInfo() *TenantInfo { 570 return ses.tenant 571 } 572 573 func (ses *feSessionImpl) SetTenantInfo(ti *TenantInfo) { 574 ses.tenant = ti 575 } 576 577 func (ses *feSessionImpl) GetTxnHandler() *TxnHandler { 578 return ses.txnHandler 579 } 580 581 func (ses *feSessionImpl) GetTxnCompileCtx() *TxnCompilerContext { 582 return ses.txnCompileCtx 583 } 584 585 func (ses *feSessionImpl) SetMysqlResultSet(mrs *MysqlResultSet) { 586 ses.mrs = mrs 587 } 588 589 func (ses *feSessionImpl) GetMysqlResultSet() *MysqlResultSet { 590 return ses.mrs 591 } 592 593 func (ses *feSessionImpl) SetOutputCallback(callback outputCallBackFunc) { 594 ses.outputCallback = callback 595 } 596 597 func (ses *feSessionImpl) SetMysqlResultSetOfBackgroundTask(mrs *MysqlResultSet) { 598 if len(ses.allResultSet) == 0 { 599 ses.allResultSet = append(ses.allResultSet, mrs) 600 } 601 } 602 603 func (ses *feSessionImpl) GetAllMysqlResultSet() []*MysqlResultSet { 604 return ses.allResultSet 605 } 606 607 func (ses *feSessionImpl) ClearAllMysqlResultSet() { 608 if ses.allResultSet != nil { 609 ses.allResultSet = ses.allResultSet[:0] 610 } 611 } 612 613 func (ses *feSessionImpl) SaveResultSet() { 614 if len(ses.allResultSet) == 0 && ses.mrs != nil { 615 ses.allResultSet = []*MysqlResultSet{ses.mrs} 616 } 617 } 618 619 func (ses *feSessionImpl) IsDerivedStmt() bool { 620 return ses.derivedStmt 621 } 622 623 // ReplaceDerivedStmt sets the derivedStmt and returns the previous value. 624 // if b is true, executing a derived statement. 625 func (ses *feSessionImpl) ReplaceDerivedStmt(b bool) bool { 626 prev := ses.derivedStmt 627 ses.derivedStmt = b 628 return prev 629 } 630 631 func (ses *feSessionImpl) updateLastCommitTS(lastCommitTS timestamp.Timestamp) { 632 if lastCommitTS.Greater(ses.lastCommitTS) { 633 ses.lastCommitTS = lastCommitTS 634 } 635 if ses.upstream != nil { 636 ses.upstream.updateLastCommitTS(lastCommitTS) 637 } 638 } 639 640 func (ses *feSessionImpl) getLastCommitTS() timestamp.Timestamp { 641 minTS := ses.lastCommitTS 642 if ses.upstream != nil { 643 v := ses.upstream.getLastCommitTS() 644 if v.Greater(minTS) { 645 minTS = v 646 } 647 } 648 return minTS 649 } 650 651 func (ses *feSessionImpl) GetUpstream() FeSession { 652 return ses.upstream 653 } 654 655 // ClearResultBatches does not call Batch.Clear(). 656 func (ses *feSessionImpl) ClearResultBatches() { 657 ses.resultBatches = nil 658 } 659 660 func (ses *feSessionImpl) GetResultBatches() []*batch.Batch { 661 return ses.resultBatches 662 } 663 664 func (ses *feSessionImpl) AppendResultBatch(bat *batch.Batch) error { 665 copied, err := bat.Dup(ses.pool) 666 if err != nil { 667 return err 668 } 669 ses.resultBatches = append(ses.resultBatches, copied) 670 return nil 671 } 672 673 func (ses *feSessionImpl) GetGlobalSysVars() *GlobalSystemVariables { 674 return ses.gSysVars 675 } 676 677 func (ses *feSessionImpl) SetSql(sql string) { 678 ses.sql = sql 679 } 680 681 func (ses *feSessionImpl) GetSql() string { 682 return ses.sql 683 } 684 685 func (ses *feSessionImpl) GetAccountId() uint32 { 686 return ses.accountId 687 } 688 689 func (ses *feSessionImpl) SetAccountId(u uint32) { 690 ses.accountId = u 691 } 692 693 func (ses *feSessionImpl) SetTimeZone(loc *time.Location) { 694 ses.timeZone = loc 695 } 696 697 func (ses *feSessionImpl) GetTimeZone() *time.Location { 698 return ses.timeZone 699 } 700 701 func (ses *feSessionImpl) GetSqlCount() uint64 { 702 return ses.sqlCount 703 } 704 705 func (ses *feSessionImpl) addSqlCount(a uint64) { 706 ses.sqlCount += a 707 } 708 709 func (ses *feSessionImpl) GetUUID() []byte { 710 return ses.uuid[:] 711 } 712 713 func (ses *feSessionImpl) GetUUIDString() string { 714 return ses.uuid.String() 715 } 716 717 func (ses *Session) GetDebugString() string { 718 ses.mu.Lock() 719 defer ses.mu.Unlock() 720 return ses.debugStr 721 }