github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/distsql/server.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 distsql
    12  
    13  import (
    14  	"context"
    15  	"io"
    16  	"sync"
    17  	"time"
    18  
    19  	"github.com/cockroachdb/cockroach/pkg/gossip"
    20  	"github.com/cockroachdb/cockroach/pkg/kv"
    21  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    22  	"github.com/cockroachdb/cockroach/pkg/server/telemetry"
    23  	"github.com/cockroachdb/cockroach/pkg/sql/colflow"
    24  	"github.com/cockroachdb/cockroach/pkg/sql/execinfra"
    25  	"github.com/cockroachdb/cockroach/pkg/sql/execinfrapb"
    26  	"github.com/cockroachdb/cockroach/pkg/sql/flowinfra"
    27  	"github.com/cockroachdb/cockroach/pkg/sql/lex"
    28  	"github.com/cockroachdb/cockroach/pkg/sql/rowflow"
    29  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    30  	"github.com/cockroachdb/cockroach/pkg/sql/sessiondata"
    31  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    32  	"github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry"
    33  	"github.com/cockroachdb/cockroach/pkg/sql/sqlutil"
    34  	"github.com/cockroachdb/cockroach/pkg/util/contextutil"
    35  	"github.com/cockroachdb/cockroach/pkg/util/envutil"
    36  	"github.com/cockroachdb/cockroach/pkg/util/log"
    37  	"github.com/cockroachdb/cockroach/pkg/util/mon"
    38  	"github.com/cockroachdb/cockroach/pkg/util/timeutil"
    39  	"github.com/cockroachdb/cockroach/pkg/util/tracing"
    40  	"github.com/cockroachdb/errors"
    41  	"github.com/cockroachdb/logtags"
    42  	"github.com/opentracing/opentracing-go"
    43  )
    44  
    45  // minFlowDrainWait is the minimum amount of time a draining server allows for
    46  // any incoming flows to be registered. It acts as a grace period in which the
    47  // draining server waits for its gossiped draining state to be received by other
    48  // nodes.
    49  const minFlowDrainWait = 1 * time.Second
    50  
    51  // MultiTenancyIssueNo is the issue tracking DistSQL's Gossip and
    52  // NodeID dependencies.
    53  //
    54  // See https://github.com/cockroachdb/cockroach/issues/47900.
    55  const MultiTenancyIssueNo = 47900
    56  
    57  var noteworthyMemoryUsageBytes = envutil.EnvOrDefaultInt64("COCKROACH_NOTEWORTHY_DISTSQL_MEMORY_USAGE", 1024*1024 /* 1MB */)
    58  
    59  // ServerImpl implements the server for the distributed SQL APIs.
    60  type ServerImpl struct {
    61  	execinfra.ServerConfig
    62  	flowRegistry  *flowinfra.FlowRegistry
    63  	flowScheduler *flowinfra.FlowScheduler
    64  	memMonitor    mon.BytesMonitor
    65  	regexpCache   *tree.RegexpCache
    66  }
    67  
    68  var _ execinfrapb.DistSQLServer = &ServerImpl{}
    69  
    70  // NewServer instantiates a DistSQLServer.
    71  func NewServer(ctx context.Context, cfg execinfra.ServerConfig) *ServerImpl {
    72  	ds := &ServerImpl{
    73  		ServerConfig:  cfg,
    74  		regexpCache:   tree.NewRegexpCache(512),
    75  		flowRegistry:  flowinfra.NewFlowRegistry(cfg.NodeID.SQLInstanceID()),
    76  		flowScheduler: flowinfra.NewFlowScheduler(cfg.AmbientContext, cfg.Stopper, cfg.Settings, cfg.Metrics),
    77  		memMonitor: mon.MakeMonitor(
    78  			"distsql",
    79  			mon.MemoryResource,
    80  			cfg.Metrics.CurBytesCount,
    81  			cfg.Metrics.MaxBytesHist,
    82  			-1, /* increment: use default block size */
    83  			noteworthyMemoryUsageBytes,
    84  			cfg.Settings,
    85  		),
    86  	}
    87  	ds.memMonitor.Start(ctx, cfg.ParentMemoryMonitor, mon.BoundAccount{})
    88  	return ds
    89  }
    90  
    91  // Start launches workers for the server.
    92  func (ds *ServerImpl) Start() {
    93  	// Gossip the version info so that other nodes don't plan incompatible flows
    94  	// for us.
    95  	if g, ok := ds.ServerConfig.Gossip.Optional(MultiTenancyIssueNo); ok {
    96  		if nodeID, ok := ds.ServerConfig.NodeID.OptionalNodeID(); ok {
    97  			if err := g.AddInfoProto(
    98  				gossip.MakeDistSQLNodeVersionKey(nodeID),
    99  				&execinfrapb.DistSQLVersionGossipInfo{
   100  					Version:            execinfra.Version,
   101  					MinAcceptedVersion: execinfra.MinAcceptedVersion,
   102  				},
   103  				0, // ttl - no expiration
   104  			); err != nil {
   105  				panic(err)
   106  			}
   107  		}
   108  	}
   109  
   110  	if err := ds.setDraining(false); err != nil {
   111  		panic(err)
   112  	}
   113  
   114  	ds.flowScheduler.Start()
   115  }
   116  
   117  // Drain changes the node's draining state through gossip and drains the
   118  // server's flowRegistry. See flowRegistry.Drain for more details.
   119  func (ds *ServerImpl) Drain(
   120  	ctx context.Context, flowDrainWait time.Duration, reporter func(int, string),
   121  ) {
   122  	if err := ds.setDraining(true); err != nil {
   123  		log.Warningf(ctx, "unable to gossip distsql draining state: %s", err)
   124  	}
   125  
   126  	flowWait := flowDrainWait
   127  	minWait := minFlowDrainWait
   128  	if ds.ServerConfig.TestingKnobs.DrainFast {
   129  		flowWait = 0
   130  		minWait = 0
   131  	} else if g, ok := ds.Gossip.Optional(MultiTenancyIssueNo); !ok || len(g.Outgoing()) == 0 {
   132  		// If there is only one node in the cluster (us), there's no need to
   133  		// wait a minimum time for the draining state to be gossiped.
   134  		minWait = 0
   135  	}
   136  	ds.flowRegistry.Drain(flowWait, minWait, reporter)
   137  }
   138  
   139  // setDraining changes the node's draining state through gossip to the provided
   140  // state.
   141  func (ds *ServerImpl) setDraining(drain bool) error {
   142  	nodeID, ok := ds.ServerConfig.NodeID.OptionalNodeID()
   143  	if !ok {
   144  		// Ignore draining requests when running on behalf of a tenant.
   145  		// NB: intentionally swallow the error or the server will fatal.
   146  		_ = MultiTenancyIssueNo // related issue
   147  		return nil
   148  	}
   149  	if g, ok := ds.ServerConfig.Gossip.Optional(MultiTenancyIssueNo); ok {
   150  		return g.AddInfoProto(
   151  			gossip.MakeDistSQLDrainingKey(nodeID),
   152  			&execinfrapb.DistSQLDrainingInfo{
   153  				Draining: drain,
   154  			},
   155  			0, // ttl - no expiration
   156  		)
   157  	}
   158  	return nil
   159  }
   160  
   161  // FlowVerIsCompatible checks a flow's version is compatible with this node's
   162  // DistSQL version.
   163  func FlowVerIsCompatible(
   164  	flowVer, minAcceptedVersion, serverVersion execinfrapb.DistSQLVersion,
   165  ) bool {
   166  	return flowVer >= minAcceptedVersion && flowVer <= serverVersion
   167  }
   168  
   169  // setupFlow creates a Flow.
   170  //
   171  // Args:
   172  // localState: Specifies if the flow runs entirely on this node and, if it does,
   173  //   specifies the txn and other attributes.
   174  //
   175  // Note: unless an error is returned, the returned context contains a span that
   176  // must be finished through Flow.Cleanup.
   177  func (ds *ServerImpl) setupFlow(
   178  	ctx context.Context,
   179  	parentSpan opentracing.Span,
   180  	parentMonitor *mon.BytesMonitor,
   181  	req *execinfrapb.SetupFlowRequest,
   182  	syncFlowConsumer execinfra.RowReceiver,
   183  	localState LocalState,
   184  ) (context.Context, flowinfra.Flow, error) {
   185  	if !FlowVerIsCompatible(req.Version, execinfra.MinAcceptedVersion, execinfra.Version) {
   186  		err := errors.Errorf(
   187  			"version mismatch in flow request: %d; this node accepts %d through %d",
   188  			req.Version, execinfra.MinAcceptedVersion, execinfra.Version,
   189  		)
   190  		log.Warningf(ctx, "%v", err)
   191  		return ctx, nil, err
   192  	}
   193  
   194  	const opName = "flow"
   195  	var sp opentracing.Span
   196  	if parentSpan == nil {
   197  		sp = ds.Tracer.(*tracing.Tracer).StartRootSpan(
   198  			opName, logtags.FromContext(ctx), tracing.NonRecordableSpan)
   199  	} else if localState.IsLocal {
   200  		// If we're a local flow, we don't need a "follows from" relationship: we're
   201  		// going to run this flow synchronously.
   202  		// TODO(andrei): localState.IsLocal is not quite the right thing to use.
   203  		//  If that field is unset, we might still want to create a child span if
   204  		//  this flow is run synchronously.
   205  		sp = tracing.StartChildSpan(opName, parentSpan, logtags.FromContext(ctx), false /* separateRecording */)
   206  	} else {
   207  		// We use FollowsFrom because the flow's span outlives the SetupFlow request.
   208  		// TODO(andrei): We should use something more efficient than StartSpan; we
   209  		// should use AmbientContext.AnnotateCtxWithSpan() but that interface
   210  		// doesn't currently support FollowsFrom relationships.
   211  		sp = ds.Tracer.StartSpan(
   212  			opName,
   213  			opentracing.FollowsFrom(parentSpan.Context()),
   214  			tracing.LogTagsFromCtx(ctx),
   215  		)
   216  	}
   217  	// sp will be Finish()ed by Flow.Cleanup().
   218  	ctx = opentracing.ContextWithSpan(ctx, sp)
   219  
   220  	// The monitor opened here is closed in Flow.Cleanup().
   221  	monitor := mon.MakeMonitor(
   222  		"flow",
   223  		mon.MemoryResource,
   224  		ds.Metrics.CurBytesCount,
   225  		ds.Metrics.MaxBytesHist,
   226  		-1, /* use default block size */
   227  		noteworthyMemoryUsageBytes,
   228  		ds.Settings,
   229  	)
   230  	monitor.Start(ctx, parentMonitor, mon.BoundAccount{})
   231  
   232  	makeLeaf := func(req *execinfrapb.SetupFlowRequest) (*kv.Txn, error) {
   233  		tis := req.LeafTxnInputState
   234  		if tis == nil {
   235  			// This must be a flow running for some bulk-io operation that doesn't use
   236  			// a txn.
   237  			return nil, nil
   238  		}
   239  		if tis.Txn.Status != roachpb.PENDING {
   240  			return nil, errors.AssertionFailedf("cannot create flow in non-PENDING txn: %s",
   241  				tis.Txn)
   242  		}
   243  		// The flow will run in a LeafTxn because we do not want each distributed
   244  		// Txn to heartbeat the transaction.
   245  		return kv.NewLeafTxn(ctx, ds.DB, req.Flow.Gateway, tis), nil
   246  	}
   247  
   248  	var evalCtx *tree.EvalContext
   249  	var leafTxn *kv.Txn
   250  	if localState.EvalContext != nil {
   251  		evalCtx = localState.EvalContext
   252  		evalCtx.Mon = &monitor
   253  	} else {
   254  		if localState.IsLocal {
   255  			return nil, nil, errors.AssertionFailedf(
   256  				"EvalContext expected to be populated when IsLocal is set")
   257  		}
   258  
   259  		location, err := timeutil.TimeZoneStringToLocation(
   260  			req.EvalContext.Location,
   261  			timeutil.TimeZoneStringToLocationISO8601Standard,
   262  		)
   263  		if err != nil {
   264  			tracing.FinishSpan(sp)
   265  			return ctx, nil, err
   266  		}
   267  
   268  		var be lex.BytesEncodeFormat
   269  		switch req.EvalContext.BytesEncodeFormat {
   270  		case execinfrapb.BytesEncodeFormat_HEX:
   271  			be = lex.BytesEncodeHex
   272  		case execinfrapb.BytesEncodeFormat_ESCAPE:
   273  			be = lex.BytesEncodeEscape
   274  		case execinfrapb.BytesEncodeFormat_BASE64:
   275  			be = lex.BytesEncodeBase64
   276  		default:
   277  			return nil, nil, errors.AssertionFailedf("unknown byte encode format: %s",
   278  				errors.Safe(req.EvalContext.BytesEncodeFormat))
   279  		}
   280  		sd := &sessiondata.SessionData{
   281  			ApplicationName: req.EvalContext.ApplicationName,
   282  			Database:        req.EvalContext.Database,
   283  			User:            req.EvalContext.User,
   284  			SearchPath:      sessiondata.MakeSearchPath(req.EvalContext.SearchPath).WithTemporarySchemaName(req.EvalContext.TemporarySchemaName),
   285  			SequenceState:   sessiondata.NewSequenceState(),
   286  			DataConversion: sessiondata.DataConversionConfig{
   287  				Location:          location,
   288  				BytesEncodeFormat: be,
   289  				ExtraFloatDigits:  int(req.EvalContext.ExtraFloatDigits),
   290  			},
   291  			VectorizeMode: sessiondata.VectorizeExecMode(req.EvalContext.Vectorize),
   292  		}
   293  		ie := &lazyInternalExecutor{
   294  			newInternalExecutor: func() sqlutil.InternalExecutor {
   295  				return ds.SessionBoundInternalExecutorFactory(ctx, sd)
   296  			},
   297  		}
   298  
   299  		// It's important to populate evalCtx.Txn early. We'll write it again in the
   300  		// f.SetTxn() call below, but by then it will already have been captured by
   301  		// processors.
   302  		leafTxn, err = makeLeaf(req)
   303  		if err != nil {
   304  			return nil, nil, err
   305  		}
   306  		evalCtx = &tree.EvalContext{
   307  			Settings:    ds.ServerConfig.Settings,
   308  			SessionData: sd,
   309  			ClusterID:   ds.ServerConfig.ClusterID.Get(),
   310  			ClusterName: ds.ServerConfig.ClusterName,
   311  			NodeID:      ds.ServerConfig.NodeID,
   312  			Codec:       ds.ServerConfig.Codec,
   313  			ReCache:     ds.regexpCache,
   314  			Mon:         &monitor,
   315  			// Most processors will override this Context with their own context in
   316  			// ProcessorBase. StartInternal().
   317  			Context:            ctx,
   318  			Planner:            &sqlbase.DummyEvalPlanner{},
   319  			PrivilegedAccessor: &sqlbase.DummyPrivilegedAccessor{},
   320  			SessionAccessor:    &sqlbase.DummySessionAccessor{},
   321  			ClientNoticeSender: &sqlbase.DummyClientNoticeSender{},
   322  			Sequence:           &sqlbase.DummySequenceOperators{},
   323  			Tenant:             &sqlbase.DummyTenantOperator{},
   324  			InternalExecutor:   ie,
   325  			Txn:                leafTxn,
   326  		}
   327  		evalCtx.SetStmtTimestamp(timeutil.Unix(0 /* sec */, req.EvalContext.StmtTimestampNanos))
   328  		evalCtx.SetTxnTimestamp(timeutil.Unix(0 /* sec */, req.EvalContext.TxnTimestampNanos))
   329  		var haveSequences bool
   330  		for _, seq := range req.EvalContext.SeqState.Seqs {
   331  			evalCtx.SessionData.SequenceState.RecordValue(seq.SeqID, seq.LatestVal)
   332  			haveSequences = true
   333  		}
   334  		if haveSequences {
   335  			evalCtx.SessionData.SequenceState.SetLastSequenceIncremented(
   336  				*req.EvalContext.SeqState.LastSeqIncremented)
   337  		}
   338  	}
   339  
   340  	// TODO(radu): we should sanity check some of these fields.
   341  	flowCtx := execinfra.FlowCtx{
   342  		AmbientContext: ds.AmbientContext,
   343  		Cfg:            &ds.ServerConfig,
   344  		ID:             req.Flow.FlowID,
   345  		EvalCtx:        evalCtx,
   346  		NodeID:         ds.ServerConfig.NodeID,
   347  		TraceKV:        req.TraceKV,
   348  		Local:          localState.IsLocal,
   349  	}
   350  	// req always contains the desired vectorize mode, regardless of whether we
   351  	// have non-nil localState.EvalContext. We don't want to update EvalContext
   352  	// itself when the vectorize mode needs to be changed because we would need
   353  	// to restore the original value which can have data races under stress.
   354  	isVectorized := sessiondata.VectorizeExecMode(req.EvalContext.Vectorize) != sessiondata.VectorizeOff
   355  	f := newFlow(flowCtx, ds.flowRegistry, syncFlowConsumer, localState.LocalProcs, isVectorized)
   356  	opt := flowinfra.FuseNormally
   357  	if localState.IsLocal {
   358  		// If there's no remote flows, fuse everything. This is needed in order for
   359  		// us to be able to use the RootTxn for the flow 's execution; the RootTxn
   360  		// doesn't allow for concurrent operations. Local flows with mutations need
   361  		// to use the RootTxn.
   362  		opt = flowinfra.FuseAggressively
   363  	}
   364  
   365  	var err error
   366  	if ctx, err = f.Setup(ctx, &req.Flow, opt); err != nil {
   367  		log.Errorf(ctx, "error setting up flow: %s", err)
   368  		// Flow.Cleanup will not be called, so we have to close the memory monitor
   369  		// and finish the span manually.
   370  		monitor.Stop(ctx)
   371  		tracing.FinishSpan(sp)
   372  		ctx = opentracing.ContextWithSpan(ctx, nil)
   373  		return ctx, nil, err
   374  	}
   375  	if !f.IsLocal() {
   376  		flowCtx.AddLogTag("f", f.GetFlowCtx().ID.Short())
   377  		flowCtx.AnnotateCtx(ctx)
   378  		telemetry.Inc(sqltelemetry.DistSQLExecCounter)
   379  	}
   380  	if f.IsVectorized() {
   381  		telemetry.Inc(sqltelemetry.VecExecCounter)
   382  	}
   383  
   384  	// Figure out what txn the flow needs to run in, if any. For gateway flows
   385  	// that have no remote flows and also no concurrency, the txn comes from
   386  	// localState.Txn. Otherwise, we create a txn based on the request's
   387  	// LeafTxnInputState.
   388  	var txn *kv.Txn
   389  	if localState.IsLocal && !f.ConcurrentExecution() {
   390  		txn = localState.Txn
   391  	} else {
   392  		// If I haven't created the leaf already, do it now.
   393  		if leafTxn == nil {
   394  			var err error
   395  			leafTxn, err = makeLeaf(req)
   396  			if err != nil {
   397  				return nil, nil, err
   398  			}
   399  		}
   400  		txn = leafTxn
   401  	}
   402  	// TODO(andrei): We're about to overwrite f.EvalCtx.Txn, but the existing
   403  	// field has already been captured by various processors and operators that
   404  	// have already made a copy of the EvalCtx. In case this is not the gateway,
   405  	// we had already set the LeafTxn on the EvalCtx above, so it's OK. In case
   406  	// this is the gateway, if we're running with the RootTxn, then again it was
   407  	// set above so it's fine. If we're using a LeafTxn on the gateway, though,
   408  	// then the processors have erroneously captured the Root. See #41992.
   409  	f.SetTxn(txn)
   410  
   411  	return ctx, f, nil
   412  }
   413  
   414  func newFlow(
   415  	flowCtx execinfra.FlowCtx,
   416  	flowReg *flowinfra.FlowRegistry,
   417  	syncFlowConsumer execinfra.RowReceiver,
   418  	localProcessors []execinfra.LocalProcessor,
   419  	isVectorized bool,
   420  ) flowinfra.Flow {
   421  	base := flowinfra.NewFlowBase(flowCtx, flowReg, syncFlowConsumer, localProcessors)
   422  	if isVectorized {
   423  		return colflow.NewVectorizedFlow(base)
   424  	}
   425  	return rowflow.NewRowBasedFlow(base)
   426  }
   427  
   428  // SetupSyncFlow sets up a synchronous flow, connecting the sync response
   429  // output stream to the given RowReceiver. The flow is not started. The flow
   430  // will be associated with the given context.
   431  // Note: the returned context contains a span that must be finished through
   432  // Flow.Cleanup.
   433  func (ds *ServerImpl) SetupSyncFlow(
   434  	ctx context.Context,
   435  	parentMonitor *mon.BytesMonitor,
   436  	req *execinfrapb.SetupFlowRequest,
   437  	output execinfra.RowReceiver,
   438  ) (context.Context, flowinfra.Flow, error) {
   439  	ctx, f, err := ds.setupFlow(ds.AnnotateCtx(ctx), opentracing.SpanFromContext(ctx), parentMonitor,
   440  		req, output, LocalState{})
   441  	if err != nil {
   442  		return nil, nil, err
   443  	}
   444  	return ctx, f, err
   445  }
   446  
   447  // LocalState carries information that is required to set up a flow with wrapped
   448  // planNodes.
   449  type LocalState struct {
   450  	EvalContext *tree.EvalContext
   451  
   452  	// IsLocal is set if the flow is running on the gateway and there are no
   453  	// remote flows.
   454  	IsLocal bool
   455  
   456  	// Txn is filled in on the gateway only. It is the RootTxn that the query is running in.
   457  	// This will be used directly by the flow if the flow has no concurrency and IsLocal is set.
   458  	// If there is concurrency, a LeafTxn will be created.
   459  	Txn *kv.Txn
   460  
   461  	/////////////////////////////////////////////
   462  	// Fields below are empty if IsLocal == false
   463  	/////////////////////////////////////////////
   464  
   465  	// LocalProcs is an array of planNodeToRowSource processors. It's in order and
   466  	// will be indexed into by the RowSourceIdx field in LocalPlanNodeSpec.
   467  	LocalProcs []execinfra.LocalProcessor
   468  }
   469  
   470  // SetupLocalSyncFlow sets up a synchronous flow on the current (planning) node.
   471  // It's used by the gateway node to set up the flows local to it.
   472  // It's the same as SetupSyncFlow except it takes the localState.
   473  func (ds *ServerImpl) SetupLocalSyncFlow(
   474  	ctx context.Context,
   475  	parentMonitor *mon.BytesMonitor,
   476  	req *execinfrapb.SetupFlowRequest,
   477  	output execinfra.RowReceiver,
   478  	localState LocalState,
   479  ) (context.Context, flowinfra.Flow, error) {
   480  	ctx, f, err := ds.setupFlow(ctx, opentracing.SpanFromContext(ctx), parentMonitor, req, output,
   481  		localState)
   482  	if err != nil {
   483  		return nil, nil, err
   484  	}
   485  	return ctx, f, err
   486  }
   487  
   488  // RunSyncFlow is part of the DistSQLServer interface.
   489  func (ds *ServerImpl) RunSyncFlow(stream execinfrapb.DistSQL_RunSyncFlowServer) error {
   490  	// Set up the outgoing mailbox for the stream.
   491  	mbox := flowinfra.NewOutboxSyncFlowStream(stream)
   492  
   493  	firstMsg, err := stream.Recv()
   494  	if err != nil {
   495  		return err
   496  	}
   497  	if firstMsg.SetupFlowRequest == nil {
   498  		return errors.AssertionFailedf("first message in RunSyncFlow doesn't contain SetupFlowRequest")
   499  	}
   500  	req := firstMsg.SetupFlowRequest
   501  	ctx, f, err := ds.SetupSyncFlow(stream.Context(), &ds.memMonitor, req, mbox)
   502  	if err != nil {
   503  		return err
   504  	}
   505  	mbox.SetFlowCtx(f.GetFlowCtx())
   506  
   507  	if err := ds.Stopper.RunTask(ctx, "distsql.ServerImpl: sync flow", func(ctx context.Context) {
   508  		ctx, ctxCancel := contextutil.WithCancel(ctx)
   509  		defer ctxCancel()
   510  		f.AddStartable(mbox)
   511  		ds.Metrics.FlowStart()
   512  		if err := f.Run(ctx, func() {}); err != nil {
   513  			log.Fatalf(ctx, "unexpected error from syncFlow.Start(): %s "+
   514  				"The error should have gone to the consumer.", err)
   515  		}
   516  		f.Cleanup(ctx)
   517  		ds.Metrics.FlowStop()
   518  	}); err != nil {
   519  		return err
   520  	}
   521  	return mbox.Err()
   522  }
   523  
   524  // SetupFlow is part of the DistSQLServer interface.
   525  func (ds *ServerImpl) SetupFlow(
   526  	ctx context.Context, req *execinfrapb.SetupFlowRequest,
   527  ) (*execinfrapb.SimpleResponse, error) {
   528  	log.VEventf(ctx, 1, "received SetupFlow request from n%v for flow %v", req.Flow.Gateway, req.Flow.FlowID)
   529  	parentSpan := opentracing.SpanFromContext(ctx)
   530  
   531  	// Note: the passed context will be canceled when this RPC completes, so we
   532  	// can't associate it with the flow.
   533  	ctx = ds.AnnotateCtx(context.Background())
   534  	ctx, f, err := ds.setupFlow(ctx, parentSpan, &ds.memMonitor, req, nil /* syncFlowConsumer */, LocalState{})
   535  	if err == nil {
   536  		err = ds.flowScheduler.ScheduleFlow(ctx, f)
   537  	}
   538  	if err != nil {
   539  		// We return flow deployment errors in the response so that they are
   540  		// packaged correctly over the wire. If we return them directly to this
   541  		// function, they become part of an rpc error.
   542  		return &execinfrapb.SimpleResponse{Error: execinfrapb.NewError(ctx, err)}, nil
   543  	}
   544  	return &execinfrapb.SimpleResponse{}, nil
   545  }
   546  
   547  func (ds *ServerImpl) flowStreamInt(
   548  	ctx context.Context, stream execinfrapb.DistSQL_FlowStreamServer,
   549  ) error {
   550  	// Receive the first message.
   551  	msg, err := stream.Recv()
   552  	if err != nil {
   553  		if err == io.EOF {
   554  			return errors.AssertionFailedf("missing header message")
   555  		}
   556  		return err
   557  	}
   558  	if msg.Header == nil {
   559  		return errors.AssertionFailedf("no header in first message")
   560  	}
   561  	flowID := msg.Header.FlowID
   562  	streamID := msg.Header.StreamID
   563  	if log.V(1) {
   564  		log.Infof(ctx, "connecting inbound stream %s/%d", flowID.Short(), streamID)
   565  	}
   566  	f, streamStrategy, cleanup, err := ds.flowRegistry.ConnectInboundStream(
   567  		ctx, flowID, streamID, stream, flowinfra.SettingFlowStreamTimeout.Get(&ds.Settings.SV),
   568  	)
   569  	if err != nil {
   570  		return err
   571  	}
   572  	defer cleanup()
   573  	log.VEventf(ctx, 1, "connected inbound stream %s/%d", flowID.Short(), streamID)
   574  	return streamStrategy.Run(f.AnnotateCtx(ctx), stream, msg, f)
   575  }
   576  
   577  // FlowStream is part of the DistSQLServer interface.
   578  func (ds *ServerImpl) FlowStream(stream execinfrapb.DistSQL_FlowStreamServer) error {
   579  	ctx := ds.AnnotateCtx(stream.Context())
   580  	err := ds.flowStreamInt(ctx, stream)
   581  	if err != nil && log.V(2) {
   582  		// flowStreamInt may return an error during normal operation (e.g. a flow
   583  		// was canceled as part of a graceful teardown). Log this error at the INFO
   584  		// level behind a verbose flag for visibility.
   585  		log.Infof(ctx, "%v", err)
   586  	}
   587  	return err
   588  }
   589  
   590  // lazyInternalExecutor is a tree.InternalExecutor that initializes
   591  // itself only on the first call to QueryRow.
   592  type lazyInternalExecutor struct {
   593  	// Set when an internal executor has been initialized.
   594  	sqlutil.InternalExecutor
   595  
   596  	// Used for initializing the internal executor exactly once.
   597  	once sync.Once
   598  
   599  	// newInternalExecutor must be set when instantiating a lazyInternalExecutor,
   600  	// it provides an internal executor to use when necessary.
   601  	newInternalExecutor func() sqlutil.InternalExecutor
   602  }
   603  
   604  var _ sqlutil.InternalExecutor = &lazyInternalExecutor{}
   605  
   606  func (ie *lazyInternalExecutor) QueryRowEx(
   607  	ctx context.Context,
   608  	opName string,
   609  	txn *kv.Txn,
   610  	opts sqlbase.InternalExecutorSessionDataOverride,
   611  	stmt string,
   612  	qargs ...interface{},
   613  ) (tree.Datums, error) {
   614  	ie.once.Do(func() {
   615  		ie.InternalExecutor = ie.newInternalExecutor()
   616  	})
   617  	return ie.InternalExecutor.QueryRowEx(ctx, opName, txn, opts, stmt, qargs...)
   618  }
   619  
   620  func (ie *lazyInternalExecutor) QueryRow(
   621  	ctx context.Context, opName string, txn *kv.Txn, stmt string, qargs ...interface{},
   622  ) (tree.Datums, error) {
   623  	ie.once.Do(func() {
   624  		ie.InternalExecutor = ie.newInternalExecutor()
   625  	})
   626  	return ie.InternalExecutor.QueryRow(ctx, opName, txn, stmt, qargs...)
   627  }