github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/internal.go (about) 1 // Copyright 2016 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package sql 12 13 import ( 14 "context" 15 "math" 16 "strings" 17 "sync" 18 19 "github.com/cockroachdb/cockroach/pkg/kv" 20 "github.com/cockroachdb/cockroach/pkg/security" 21 "github.com/cockroachdb/cockroach/pkg/settings/cluster" 22 "github.com/cockroachdb/cockroach/pkg/sql/catalog/descs" 23 "github.com/cockroachdb/cockroach/pkg/sql/parser" 24 "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgwirebase" 25 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 26 "github.com/cockroachdb/cockroach/pkg/sql/sessiondata" 27 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 28 "github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry" 29 "github.com/cockroachdb/cockroach/pkg/sql/sqlutil" 30 "github.com/cockroachdb/cockroach/pkg/util/mon" 31 "github.com/cockroachdb/cockroach/pkg/util/timeutil" 32 "github.com/cockroachdb/cockroach/pkg/util/tracing" 33 "github.com/cockroachdb/errors" 34 "github.com/cockroachdb/logtags" 35 ) 36 37 var _ sqlutil.InternalExecutor = &InternalExecutor{} 38 39 // InternalExecutor can be used internally by code modules to execute SQL 40 // statements without needing to open a SQL connection. 41 // 42 // InternalExecutor can execute one statement at a time. As of 03/2018, it 43 // doesn't offer a session interface for maintaining session state or for 44 // running explicit SQL transactions. However, it supports running SQL 45 // statements inside a higher-lever (KV) txn and inheriting session variables 46 // from another session. 47 // 48 // Methods not otherwise specified are safe for concurrent execution. 49 type InternalExecutor struct { 50 s *Server 51 52 // mon is the monitor used by all queries executed through the 53 // InternalExecutor. 54 mon *mon.BytesMonitor 55 56 // memMetrics is the memory metrics that queries executed through the 57 // InternalExecutor will contribute to. 58 memMetrics MemoryMetrics 59 60 // sessionData, if not nil, represents the session variables used by 61 // statements executed on this internalExecutor. Note that queries executed by 62 // the executor will run on copies of this data. 63 sessionData *sessiondata.SessionData 64 65 // The internal executor uses its own Collection. A Collection 66 // is a schema cache for each transaction and contains data like the schema 67 // modified by a transaction. Occasionally an internal executor is called 68 // within the context of a transaction that has modified the schema, the 69 // internal executor should see the modified schema. This interface allows 70 // the internal executor to modify its Collection to match the 71 // Collection of the parent executor. 72 tcModifier descs.ModifiedCollectionCopier 73 } 74 75 // MakeInternalExecutor creates an InternalExecutor. 76 func MakeInternalExecutor( 77 ctx context.Context, s *Server, memMetrics MemoryMetrics, settings *cluster.Settings, 78 ) InternalExecutor { 79 monitor := mon.MakeUnlimitedMonitor( 80 ctx, 81 "internal SQL executor", 82 mon.MemoryResource, 83 memMetrics.CurBytesCount, 84 memMetrics.MaxBytesHist, 85 math.MaxInt64, /* noteworthy */ 86 settings, 87 ) 88 return InternalExecutor{ 89 s: s, 90 mon: &monitor, 91 memMetrics: memMetrics, 92 } 93 } 94 95 // SetSessionData binds the session variables that will be used by queries 96 // performed through this executor from now on. 97 // 98 // SetSessionData cannot be called concurently with query execution. 99 func (ie *InternalExecutor) SetSessionData(sessionData *sessiondata.SessionData) { 100 ie.s.populateMinimalSessionData(sessionData) 101 ie.sessionData = sessionData 102 } 103 104 // initConnEx creates a connExecutor and runs it on a separate goroutine. It 105 // returns a StmtBuf into which commands can be pushed and a WaitGroup that will 106 // be signaled when connEx.run() returns. 107 // 108 // If txn is not nil, the statement will be executed in the respective txn. 109 // 110 // sd will constitute the executor's session state. 111 func (ie *InternalExecutor) initConnEx( 112 ctx context.Context, 113 txn *kv.Txn, 114 sd *sessiondata.SessionData, 115 syncCallback func([]resWithPos), 116 errCallback func(error), 117 ) (*StmtBuf, *sync.WaitGroup, error) { 118 clientComm := &internalClientComm{ 119 sync: syncCallback, 120 // init lastDelivered below the position of the first result (0). 121 lastDelivered: -1, 122 } 123 124 // When the connEx is serving an internal executor, it can inherit the 125 // application name from an outer session. This happens e.g. during ::regproc 126 // casts and built-in functions that use SQL internally. In that case, we do 127 // not want to record statistics against the outer application name directly; 128 // instead we want to use a separate bucket. However we will still want to 129 // have separate buckets for different applications so that we can measure 130 // their respective "pressure" on internal queries. Hence the choice here to 131 // add the delegate prefix to the current app name. 132 var appStatsBucketName string 133 if !strings.HasPrefix(sd.ApplicationName, sqlbase.InternalAppNamePrefix) { 134 appStatsBucketName = sqlbase.DelegatedAppNamePrefix + sd.ApplicationName 135 } else { 136 // If this is already an "internal app", don't put more prefix. 137 appStatsBucketName = sd.ApplicationName 138 } 139 appStats := ie.s.sqlStats.getStatsForApplication(appStatsBucketName) 140 141 stmtBuf := NewStmtBuf() 142 var ex *connExecutor 143 if txn == nil { 144 ex = ie.s.newConnExecutor( 145 ctx, 146 sd, 147 nil, /* sdDefaults */ 148 stmtBuf, 149 clientComm, 150 ie.memMetrics, 151 &ie.s.InternalMetrics, 152 appStats, 153 ) 154 } else { 155 ex = ie.s.newConnExecutorWithTxn( 156 ctx, 157 sd, 158 nil, /* sdDefaults */ 159 stmtBuf, 160 clientComm, 161 ie.mon, 162 ie.memMetrics, 163 &ie.s.InternalMetrics, 164 txn, 165 ie.tcModifier, 166 appStats, 167 ) 168 } 169 ex.executorType = executorTypeInternal 170 171 var wg sync.WaitGroup 172 wg.Add(1) 173 go func() { 174 if err := ex.run(ctx, ie.mon, mon.BoundAccount{} /*reserved*/, nil /* cancel */); err != nil { 175 sqltelemetry.RecordError(ctx, err, &ex.server.cfg.Settings.SV) 176 errCallback(err) 177 } 178 closeMode := normalClose 179 if txn != nil { 180 closeMode = externalTxnClose 181 } 182 ex.close(ctx, closeMode) 183 wg.Done() 184 }() 185 return stmtBuf, &wg, nil 186 } 187 188 // Query executes the supplied SQL statement and returns the resulting rows. 189 // If no user has been previously set through SetSessionData, the statement is 190 // executed as the root user. 191 // 192 // If txn is not nil, the statement will be executed in the respective txn. 193 // 194 // Query is deprecated because it may transparently execute a query as root. Use 195 // QueryEx instead. 196 func (ie *InternalExecutor) Query( 197 ctx context.Context, opName string, txn *kv.Txn, stmt string, qargs ...interface{}, 198 ) ([]tree.Datums, error) { 199 return ie.QueryEx(ctx, opName, txn, ie.maybeRootSessionDataOverride(opName), stmt, qargs...) 200 } 201 202 // QueryEx is like Query, but allows the caller to override some session data 203 // fields (e.g. the user). 204 // 205 // The fields set in session that are set override the respective fields if they 206 // have previously been set through SetSessionData(). 207 func (ie *InternalExecutor) QueryEx( 208 ctx context.Context, 209 opName string, 210 txn *kv.Txn, 211 session sqlbase.InternalExecutorSessionDataOverride, 212 stmt string, 213 qargs ...interface{}, 214 ) ([]tree.Datums, error) { 215 datums, _, err := ie.queryInternal(ctx, opName, txn, session, stmt, qargs...) 216 return datums, err 217 } 218 219 // QueryWithCols is like QueryEx, but it also returns the computed ResultColumns 220 // of the input query. 221 func (ie *InternalExecutor) QueryWithCols( 222 ctx context.Context, 223 opName string, 224 txn *kv.Txn, 225 session sqlbase.InternalExecutorSessionDataOverride, 226 stmt string, 227 qargs ...interface{}, 228 ) ([]tree.Datums, sqlbase.ResultColumns, error) { 229 return ie.queryInternal(ctx, opName, txn, session, stmt, qargs...) 230 } 231 232 func (ie *InternalExecutor) queryInternal( 233 ctx context.Context, 234 opName string, 235 txn *kv.Txn, 236 sessionDataOverride sqlbase.InternalExecutorSessionDataOverride, 237 stmt string, 238 qargs ...interface{}, 239 ) ([]tree.Datums, sqlbase.ResultColumns, error) { 240 res, err := ie.execInternal(ctx, opName, txn, sessionDataOverride, stmt, qargs...) 241 if err != nil { 242 return nil, nil, err 243 } 244 return res.rows, res.cols, res.err 245 } 246 247 // QueryRow is like Query, except it returns a single row, or nil if not row is 248 // found, or an error if more that one row is returned. 249 // 250 // QueryRow is deprecated (like Query). Use QueryRowEx() instead. 251 func (ie *InternalExecutor) QueryRow( 252 ctx context.Context, opName string, txn *kv.Txn, stmt string, qargs ...interface{}, 253 ) (tree.Datums, error) { 254 return ie.QueryRowEx(ctx, opName, txn, ie.maybeRootSessionDataOverride(opName), stmt, qargs...) 255 } 256 257 // QueryRowEx is like QueryRow, but allows the caller to override some session data 258 // fields (e.g. the user). 259 // 260 // The fields set in session that are set override the respective fields if they 261 // have previously been set through SetSessionData(). 262 func (ie *InternalExecutor) QueryRowEx( 263 ctx context.Context, 264 opName string, 265 txn *kv.Txn, 266 session sqlbase.InternalExecutorSessionDataOverride, 267 stmt string, 268 qargs ...interface{}, 269 ) (tree.Datums, error) { 270 rows, err := ie.QueryEx(ctx, opName, txn, session, stmt, qargs...) 271 if err != nil { 272 return nil, err 273 } 274 switch len(rows) { 275 case 0: 276 return nil, nil 277 case 1: 278 return rows[0], nil 279 default: 280 return nil, &tree.MultipleResultsError{SQL: stmt} 281 } 282 } 283 284 // Exec executes the supplied SQL statement and returns the number of rows 285 // affected (not like the results; see Query()). If no user has been previously 286 // set through SetSessionData, the statement is executed as the root user. 287 // 288 // If txn is not nil, the statement will be executed in the respective txn. 289 // 290 // Exec is deprecated because it may transparently execute a query as root. Use 291 // ExecEx instead. 292 func (ie *InternalExecutor) Exec( 293 ctx context.Context, opName string, txn *kv.Txn, stmt string, qargs ...interface{}, 294 ) (int, error) { 295 return ie.ExecEx(ctx, opName, txn, ie.maybeRootSessionDataOverride(opName), stmt, qargs...) 296 } 297 298 // ExecEx is like Exec, but allows the caller to override some session data 299 // fields (e.g. the user). 300 // 301 // The fields set in session that are set override the respective fields if they 302 // have previously been set through SetSessionData(). 303 func (ie *InternalExecutor) ExecEx( 304 ctx context.Context, 305 opName string, 306 txn *kv.Txn, 307 session sqlbase.InternalExecutorSessionDataOverride, 308 stmt string, 309 qargs ...interface{}, 310 ) (int, error) { 311 res, err := ie.execInternal(ctx, opName, txn, session, stmt, qargs...) 312 if err != nil { 313 return 0, err 314 } 315 return res.rowsAffected, res.err 316 } 317 318 type result struct { 319 rows []tree.Datums 320 rowsAffected int 321 cols sqlbase.ResultColumns 322 err error 323 } 324 325 // applyOverrides overrides the respective fields from sd for all the fields set on o. 326 func applyOverrides(o sqlbase.InternalExecutorSessionDataOverride, sd *sessiondata.SessionData) { 327 if o.User != "" { 328 sd.User = o.User 329 } 330 if o.Database != "" { 331 sd.Database = o.Database 332 } 333 if o.ApplicationName != "" { 334 sd.ApplicationName = o.ApplicationName 335 } 336 if o.SearchPath != nil { 337 sd.SearchPath = *o.SearchPath 338 } 339 } 340 341 func (ie *InternalExecutor) maybeRootSessionDataOverride( 342 opName string, 343 ) sqlbase.InternalExecutorSessionDataOverride { 344 if ie.sessionData == nil { 345 return sqlbase.InternalExecutorSessionDataOverride{ 346 User: security.RootUser, 347 ApplicationName: sqlbase.InternalAppNamePrefix + "-" + opName, 348 } 349 } 350 o := sqlbase.InternalExecutorSessionDataOverride{} 351 if ie.sessionData.User == "" { 352 o.User = security.RootUser 353 } 354 if ie.sessionData.ApplicationName == "" { 355 o.ApplicationName = sqlbase.InternalAppNamePrefix + "-" + opName 356 } 357 return o 358 } 359 360 // execInternal executes a statement. 361 // 362 // sessionDataOverride can be used to control select fields in the executor's 363 // session data. It overrides what has been previously set through 364 // SetSessionData(), if anything. 365 func (ie *InternalExecutor) execInternal( 366 ctx context.Context, 367 opName string, 368 txn *kv.Txn, 369 sessionDataOverride sqlbase.InternalExecutorSessionDataOverride, 370 stmt string, 371 qargs ...interface{}, 372 ) (retRes result, retErr error) { 373 ctx = logtags.AddTag(ctx, "intExec", opName) 374 375 var sd *sessiondata.SessionData 376 if ie.sessionData != nil { 377 // TODO(andrei): Properly clone (deep copy) ie.sessionData. 378 sdCopy := *ie.sessionData 379 sd = &sdCopy 380 } else { 381 sd = ie.s.newSessionData(SessionArgs{}) 382 } 383 applyOverrides(sessionDataOverride, sd) 384 if sd.User == "" { 385 return result{}, errors.AssertionFailedf("no user specified for internal query") 386 } 387 if sd.ApplicationName == "" { 388 sd.ApplicationName = sqlbase.InternalAppNamePrefix + "-" + opName 389 } 390 391 defer func() { 392 // We wrap errors with the opName, but not if they're retriable - in that 393 // case we need to leave the error intact so that it can be retried at a 394 // higher level. 395 // 396 // TODO(knz): track the callers and check whether opName could be turned 397 // into a type safe for reporting. 398 if retErr != nil && !errIsRetriable(retErr) { 399 retErr = errors.Wrapf(retErr, "%s", opName) 400 } 401 if retRes.err != nil && !errIsRetriable(retRes.err) { 402 retRes.err = errors.Wrapf(retRes.err, "%s", opName) 403 } 404 }() 405 406 ctx, sp := tracing.EnsureChildSpan(ctx, ie.s.cfg.AmbientCtx.Tracer, opName) 407 defer sp.Finish() 408 409 timeReceived := timeutil.Now() 410 parseStart := timeReceived 411 parsed, err := parser.ParseOne(stmt) 412 if err != nil { 413 return result{}, err 414 } 415 parseEnd := timeutil.Now() 416 417 // resPos will be set to the position of the command that represents the 418 // statement we care about before that command is sent for execution. 419 var resPos CmdPos 420 421 resCh := make(chan result) 422 var resultsReceived bool 423 syncCallback := func(results []resWithPos) { 424 resultsReceived = true 425 for _, res := range results { 426 if res.pos == resPos { 427 resCh <- result{rows: res.rows, rowsAffected: res.RowsAffected(), cols: res.cols, err: res.Err()} 428 return 429 } 430 if res.err != nil { 431 // If we encounter an error, there's no point in looking further; the 432 // rest of the commands in the batch have been skipped. 433 resCh <- result{err: res.Err()} 434 return 435 } 436 } 437 resCh <- result{err: errors.AssertionFailedf("missing result for pos: %d and no previous error", resPos)} 438 } 439 errCallback := func(err error) { 440 if resultsReceived { 441 return 442 } 443 resCh <- result{err: err} 444 } 445 stmtBuf, wg, err := ie.initConnEx(ctx, txn, sd, syncCallback, errCallback) 446 if err != nil { 447 return result{}, err 448 } 449 450 // Transforms the args to datums. The datum types will be passed as type hints 451 // to the PrepareStmt command. 452 datums, err := golangFillQueryArguments(qargs...) 453 if err != nil { 454 return result{}, err 455 } 456 typeHints := make(tree.PlaceholderTypes, len(datums)) 457 for i, d := range datums { 458 // Arg numbers start from 1. 459 typeHints[tree.PlaceholderIdx(i)] = d.ResolvedType() 460 } 461 if len(qargs) == 0 { 462 resPos = 0 463 if err := stmtBuf.Push( 464 ctx, 465 ExecStmt{ 466 Statement: parsed, 467 TimeReceived: timeReceived, 468 ParseStart: parseStart, 469 ParseEnd: parseEnd, 470 }); err != nil { 471 return result{}, err 472 } 473 } else { 474 resPos = 2 475 if err := stmtBuf.Push( 476 ctx, 477 PrepareStmt{ 478 Statement: parsed, 479 ParseStart: parseStart, 480 ParseEnd: parseEnd, 481 TypeHints: typeHints, 482 }, 483 ); err != nil { 484 return result{}, err 485 } 486 487 if err := stmtBuf.Push(ctx, BindStmt{internalArgs: datums}); err != nil { 488 return result{}, err 489 } 490 491 if err := stmtBuf.Push(ctx, ExecPortal{TimeReceived: timeReceived}); err != nil { 492 return result{}, err 493 } 494 } 495 if err := stmtBuf.Push(ctx, Sync{}); err != nil { 496 return result{}, err 497 } 498 499 res := <-resCh 500 stmtBuf.Close() 501 wg.Wait() 502 return res, nil 503 } 504 505 // internalClientComm is an implementation of ClientComm used by the 506 // InternalExecutor. Result rows are buffered in memory. 507 type internalClientComm struct { 508 // results will contain the results of the commands executed by an 509 // InternalExecutor. 510 results []resWithPos 511 512 lastDelivered CmdPos 513 514 // sync, if set, is called whenever a Sync is executed. It returns all the 515 // results since the previous Sync. 516 sync func([]resWithPos) 517 } 518 519 type resWithPos struct { 520 *bufferedCommandResult 521 pos CmdPos 522 } 523 524 // CreateStatementResult is part of the ClientComm interface. 525 func (icc *internalClientComm) CreateStatementResult( 526 _ tree.Statement, 527 _ RowDescOpt, 528 pos CmdPos, 529 _ []pgwirebase.FormatCode, 530 _ sessiondata.DataConversionConfig, 531 _ int, 532 _ string, 533 _ bool, 534 ) CommandResult { 535 return icc.createRes(pos, nil /* onClose */) 536 } 537 538 // createRes creates a result. onClose, if not nil, is called when the result is 539 // closed. 540 func (icc *internalClientComm) createRes(pos CmdPos, onClose func(error)) *bufferedCommandResult { 541 res := &bufferedCommandResult{ 542 closeCallback: func(res *bufferedCommandResult, typ resCloseType, err error) { 543 if typ == discarded { 544 return 545 } 546 icc.results = append(icc.results, resWithPos{bufferedCommandResult: res, pos: pos}) 547 if onClose != nil { 548 onClose(err) 549 } 550 }, 551 } 552 return res 553 } 554 555 // CreatePrepareResult is part of the ClientComm interface. 556 func (icc *internalClientComm) CreatePrepareResult(pos CmdPos) ParseResult { 557 return icc.createRes(pos, nil /* onClose */) 558 } 559 560 // CreateBindResult is part of the ClientComm interface. 561 func (icc *internalClientComm) CreateBindResult(pos CmdPos) BindResult { 562 return icc.createRes(pos, nil /* onClose */) 563 } 564 565 // CreateSyncResult is part of the ClientComm interface. 566 // 567 // The returned SyncResult will call the sync callback when its closed. 568 func (icc *internalClientComm) CreateSyncResult(pos CmdPos) SyncResult { 569 return icc.createRes(pos, func(err error) { 570 results := make([]resWithPos, len(icc.results)) 571 copy(results, icc.results) 572 icc.results = icc.results[:0] 573 icc.sync(results) 574 icc.lastDelivered = pos 575 } /* onClose */) 576 } 577 578 // LockCommunication is part of the ClientComm interface. 579 func (icc *internalClientComm) LockCommunication() ClientLock { 580 return &noopClientLock{ 581 clientComm: icc, 582 } 583 } 584 585 // Flush is part of the ClientComm interface. 586 func (icc *internalClientComm) Flush(pos CmdPos) error { 587 return nil 588 } 589 590 // CreateDescribeResult is part of the ClientComm interface. 591 func (icc *internalClientComm) CreateDescribeResult(pos CmdPos) DescribeResult { 592 return icc.createRes(pos, nil /* onClose */) 593 } 594 595 // CreateDeleteResult is part of the ClientComm interface. 596 func (icc *internalClientComm) CreateDeleteResult(pos CmdPos) DeleteResult { 597 panic("unimplemented") 598 } 599 600 // CreateFlushResult is part of the ClientComm interface. 601 func (icc *internalClientComm) CreateFlushResult(pos CmdPos) FlushResult { 602 panic("unimplemented") 603 } 604 605 // CreateErrorResult is part of the ClientComm interface. 606 func (icc *internalClientComm) CreateErrorResult(pos CmdPos) ErrorResult { 607 panic("unimplemented") 608 } 609 610 // CreateEmptyQueryResult is part of the ClientComm interface. 611 func (icc *internalClientComm) CreateEmptyQueryResult(pos CmdPos) EmptyQueryResult { 612 panic("unimplemented") 613 } 614 615 // CreateCopyInResult is part of the ClientComm interface. 616 func (icc *internalClientComm) CreateCopyInResult(pos CmdPos) CopyInResult { 617 panic("unimplemented") 618 } 619 620 // CreateDrainResult is part of the ClientComm interface. 621 func (icc *internalClientComm) CreateDrainResult(pos CmdPos) DrainResult { 622 panic("unimplemented") 623 } 624 625 // noopClientLock is an implementation of ClientLock that says that no results 626 // have been communicated to the client. 627 type noopClientLock struct { 628 clientComm *internalClientComm 629 } 630 631 // Close is part of the ClientLock interface. 632 func (ncl *noopClientLock) Close() {} 633 634 // ClientPos is part of the ClientLock interface. 635 func (ncl *noopClientLock) ClientPos() CmdPos { 636 return ncl.clientComm.lastDelivered 637 } 638 639 // RTrim is part of the ClientLock interface. 640 func (ncl *noopClientLock) RTrim(_ context.Context, pos CmdPos) { 641 var i int 642 var r resWithPos 643 for i, r = range ncl.clientComm.results { 644 if r.pos >= pos { 645 break 646 } 647 } 648 ncl.clientComm.results = ncl.clientComm.results[:i] 649 }