github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/execinfrapb/data.go (about)

     1  // Copyright 2018 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 execinfrapb
    12  
    13  import (
    14  	"context"
    15  	"fmt"
    16  	"sync"
    17  
    18  	"github.com/cockroachdb/cockroach/pkg/keys"
    19  	"github.com/cockroachdb/cockroach/pkg/kv"
    20  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver"
    22  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    23  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    24  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    25  	"github.com/cockroachdb/cockroach/pkg/util/encoding"
    26  	"github.com/cockroachdb/cockroach/pkg/util/tracing"
    27  	"github.com/cockroachdb/errors"
    28  	"github.com/cockroachdb/logtags"
    29  )
    30  
    31  // ConvertToColumnOrdering converts an Ordering type (as defined in data.proto)
    32  // to a sqlbase.ColumnOrdering type.
    33  func ConvertToColumnOrdering(specOrdering Ordering) sqlbase.ColumnOrdering {
    34  	ordering := make(sqlbase.ColumnOrdering, len(specOrdering.Columns))
    35  	for i, c := range specOrdering.Columns {
    36  		ordering[i].ColIdx = int(c.ColIdx)
    37  		if c.Direction == Ordering_Column_ASC {
    38  			ordering[i].Direction = encoding.Ascending
    39  		} else {
    40  			ordering[i].Direction = encoding.Descending
    41  		}
    42  	}
    43  	return ordering
    44  }
    45  
    46  // ConvertToSpecOrdering converts a sqlbase.ColumnOrdering type
    47  // to an Ordering type (as defined in data.proto).
    48  func ConvertToSpecOrdering(columnOrdering sqlbase.ColumnOrdering) Ordering {
    49  	return ConvertToMappedSpecOrdering(columnOrdering, nil)
    50  }
    51  
    52  // ConvertToMappedSpecOrdering converts a sqlbase.ColumnOrdering type
    53  // to an Ordering type (as defined in data.proto), using the column
    54  // indices contained in planToStreamColMap.
    55  func ConvertToMappedSpecOrdering(
    56  	columnOrdering sqlbase.ColumnOrdering, planToStreamColMap []int,
    57  ) Ordering {
    58  	specOrdering := Ordering{}
    59  	specOrdering.Columns = make([]Ordering_Column, len(columnOrdering))
    60  	for i, c := range columnOrdering {
    61  		colIdx := c.ColIdx
    62  		if planToStreamColMap != nil {
    63  			colIdx = planToStreamColMap[c.ColIdx]
    64  			if colIdx == -1 {
    65  				panic(fmt.Sprintf("column %d in sort ordering not available", c.ColIdx))
    66  			}
    67  		}
    68  		specOrdering.Columns[i].ColIdx = uint32(colIdx)
    69  		if c.Direction == encoding.Ascending {
    70  			specOrdering.Columns[i].Direction = Ordering_Column_ASC
    71  		} else {
    72  			specOrdering.Columns[i].Direction = Ordering_Column_DESC
    73  		}
    74  	}
    75  	return specOrdering
    76  }
    77  
    78  // DistSQLTypeResolver implements tree.ResolvableTypeReference for accessing
    79  // type information during DistSQL query evaluation.
    80  type DistSQLTypeResolver struct {
    81  	EvalContext *tree.EvalContext
    82  	// TODO (rohany): This struct should locally cache id -> types.T here
    83  	//  so that repeated lookups do not incur additional KV operations.
    84  }
    85  
    86  // ResolveType implements tree.ResolvableTypeReference.
    87  func (tr *DistSQLTypeResolver) ResolveType(
    88  	context.Context, *tree.UnresolvedObjectName,
    89  ) (*types.T, error) {
    90  	return nil, errors.AssertionFailedf("cannot resolve types in DistSQL by name")
    91  }
    92  
    93  func makeTypeLookupFunc(
    94  	ctx context.Context, txn *kv.Txn, codec keys.SQLCodec,
    95  ) sqlbase.TypeLookupFunc {
    96  	return func(id sqlbase.ID) (*tree.TypeName, *sqlbase.TypeDescriptor, error) {
    97  		return resolver.ResolveTypeDescByID(ctx, txn, codec, id)
    98  	}
    99  }
   100  
   101  // ResolveTypeByID implements tree.ResolvableTypeReference.
   102  func (tr *DistSQLTypeResolver) ResolveTypeByID(ctx context.Context, id uint32) (*types.T, error) {
   103  	// TODO (rohany): This should eventually look into the set of cached type
   104  	//  descriptors before attempting to access it here.
   105  	lookup := makeTypeLookupFunc(ctx, tr.EvalContext.Txn, tr.EvalContext.Codec)
   106  	name, typDesc, err := lookup(sqlbase.ID(id))
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  	return typDesc.MakeTypesT(name, lookup)
   111  }
   112  
   113  // HydrateTypeSlice hydrates all user defined types in an input slice of types.
   114  func HydrateTypeSlice(evalCtx *tree.EvalContext, typs []*types.T) error {
   115  	// TODO (rohany): This should eventually look into the set of cached type
   116  	//  descriptors before attempting to access it here.
   117  	lookup := makeTypeLookupFunc(evalCtx.Context, evalCtx.Txn, evalCtx.Codec)
   118  	for _, t := range typs {
   119  		if t.UserDefined() {
   120  			name, typDesc, err := lookup(sqlbase.ID(t.StableTypeID()))
   121  			if err != nil {
   122  				return err
   123  			}
   124  			if err := typDesc.HydrateTypeInfoWithName(t, name, lookup); err != nil {
   125  				return err
   126  			}
   127  		}
   128  	}
   129  	return nil
   130  }
   131  
   132  // ExprFmtCtxBase produces a FmtCtx used for serializing expressions; a proper
   133  // IndexedVar formatting function needs to be added on. It replaces placeholders
   134  // with their values.
   135  func ExprFmtCtxBase(evalCtx *tree.EvalContext) *tree.FmtCtx {
   136  	fmtCtx := tree.NewFmtCtx(tree.FmtCheckEquivalence)
   137  	fmtCtx.SetPlaceholderFormat(
   138  		func(fmtCtx *tree.FmtCtx, p *tree.Placeholder) {
   139  			d, err := p.Eval(evalCtx)
   140  			if err != nil {
   141  				panic(fmt.Sprintf("failed to serialize placeholder: %s", err))
   142  			}
   143  			d.Format(fmtCtx)
   144  		})
   145  	return fmtCtx
   146  }
   147  
   148  // Expression is the representation of a SQL expression.
   149  // See data.proto for the corresponding proto definition. Its automatic type
   150  // declaration is suppressed in the proto via the typedecl=false option, so that
   151  // we can add the LocalExpr field which is not serialized. It never needs to be
   152  // serialized because we only use it in the case where we know we won't need to
   153  // send it, as a proto, to another machine.
   154  type Expression struct {
   155  	// Version is unused.
   156  	Version string
   157  
   158  	// Expr, if present, is the string representation of this expression.
   159  	// SQL expressions are passed as a string, with ordinal references
   160  	// (@1, @2, @3 ..) used for "input" variables.
   161  	Expr string
   162  
   163  	// LocalExpr is an unserialized field that's used to pass expressions to local
   164  	// flows without serializing/deserializing them.
   165  	LocalExpr tree.TypedExpr
   166  }
   167  
   168  // Empty returns true if the expression has neither an Expr nor LocalExpr.
   169  func (e *Expression) Empty() bool {
   170  	return e.Expr == "" && e.LocalExpr == nil
   171  }
   172  
   173  // String implements the Stringer interface.
   174  func (e Expression) String() string {
   175  	if e.LocalExpr != nil {
   176  		ctx := tree.NewFmtCtx(tree.FmtCheckEquivalence)
   177  		ctx.FormatNode(e.LocalExpr)
   178  		return ctx.CloseAndGetString()
   179  	}
   180  	if e.Expr != "" {
   181  		return e.Expr
   182  	}
   183  	return "none"
   184  }
   185  
   186  // String implements fmt.Stringer.
   187  func (e *Error) String() string {
   188  	if err := e.ErrorDetail(context.TODO()); err != nil {
   189  		return err.Error()
   190  	}
   191  	return "<nil>"
   192  }
   193  
   194  // NewError creates an Error from an error, to be sent on the wire. It will
   195  // recognize certain errors and marshall them accordingly, and everything
   196  // unrecognized is turned into a PGError with code "internal".
   197  func NewError(ctx context.Context, err error) *Error {
   198  	resErr := &Error{}
   199  
   200  	// Encode the full error to the best of our ability.
   201  	// This field is ignored by 19.1 nodes and prior.
   202  	ctx = logtags.AddTag(ctx, "sent-error", nil)
   203  	fullError := errors.EncodeError(ctx, errors.WithContextTags(err, ctx))
   204  	resErr.FullError = &fullError
   205  
   206  	return resErr
   207  }
   208  
   209  // ErrorDetail returns the payload as a Go error.
   210  func (e *Error) ErrorDetail(ctx context.Context) (err error) {
   211  	if e == nil {
   212  		return nil
   213  	}
   214  	defer func() {
   215  		ctx = logtags.AddTag(ctx, "received-error", nil)
   216  		err = errors.WithContextTags(err, ctx)
   217  	}()
   218  
   219  	if e.FullError != nil {
   220  		// If there's a 19.2-forward full error, decode and use that.
   221  		// This will reveal a fully causable detailed error structure.
   222  		return errors.DecodeError(ctx, *e.FullError)
   223  	}
   224  
   225  	// We're receiving an error we don't know about. It's all right,
   226  	// it's still an error, just one we didn't expect. Let it go
   227  	// through. We'll pick it up in reporting.
   228  	return errors.AssertionFailedf("unknown error from remote node")
   229  }
   230  
   231  // ProducerMetadata represents a metadata record flowing through a DistSQL flow.
   232  type ProducerMetadata struct {
   233  	// Only one of these fields will be set. If this ever changes, note that
   234  	// there're consumers out there that extract the error and, if there is one,
   235  	// forward it in isolation and drop the rest of the record.
   236  	Ranges []roachpb.RangeInfo
   237  	// TODO(vivek): change to type Error
   238  	Err error
   239  	// TraceData is sent if snowball tracing is enabled.
   240  	TraceData []tracing.RecordedSpan
   241  	// LeafTxnFinalState contains the final state of the LeafTxn to be
   242  	// sent from leaf flows to the RootTxn held by the flow's ultimate
   243  	// receiver.
   244  	LeafTxnFinalState *roachpb.LeafTxnFinalState
   245  	// RowNum corresponds to a row produced by a "source" processor that takes no
   246  	// inputs. It is used in tests to verify that all metadata is forwarded
   247  	// exactly once to the receiver on the gateway node.
   248  	RowNum *RemoteProducerMetadata_RowNum
   249  	// SamplerProgress contains incremental progress information from the sampler
   250  	// processor.
   251  	SamplerProgress *RemoteProducerMetadata_SamplerProgress
   252  	// BulkProcessorProgress contains incremental progress information from a bulk
   253  	// operation processor (backfiller, import, etc).
   254  	BulkProcessorProgress *RemoteProducerMetadata_BulkProcessorProgress
   255  	// Metrics contains information about goodput of the node.
   256  	Metrics *RemoteProducerMetadata_Metrics
   257  }
   258  
   259  var (
   260  	// TODO(yuzefovich): use this pool in other places apart from metrics
   261  	// collection.
   262  	// producerMetadataPool is a pool of producer metadata objects.
   263  	producerMetadataPool = sync.Pool{
   264  		New: func() interface{} {
   265  			return &ProducerMetadata{}
   266  		},
   267  	}
   268  
   269  	// rpmMetricsPool is a pool of metadata used to propagate metrics.
   270  	rpmMetricsPool = sync.Pool{
   271  		New: func() interface{} {
   272  			return &RemoteProducerMetadata_Metrics{}
   273  		},
   274  	}
   275  )
   276  
   277  // Release is part of Releasable interface.
   278  func (meta *ProducerMetadata) Release() {
   279  	*meta = ProducerMetadata{}
   280  	producerMetadataPool.Put(meta)
   281  }
   282  
   283  // Release is part of Releasable interface. Note that although this meta is
   284  // only used together with a ProducerMetadata that comes from another pool, we
   285  // do not combine two Release methods into one because two objects have a
   286  // different lifetime.
   287  func (meta *RemoteProducerMetadata_Metrics) Release() {
   288  	*meta = RemoteProducerMetadata_Metrics{}
   289  	rpmMetricsPool.Put(meta)
   290  }
   291  
   292  // GetProducerMeta returns a producer metadata object from the pool.
   293  func GetProducerMeta() *ProducerMetadata {
   294  	return producerMetadataPool.Get().(*ProducerMetadata)
   295  }
   296  
   297  // GetMetricsMeta returns a metadata object from the pool of metrics metadata.
   298  func GetMetricsMeta() *RemoteProducerMetadata_Metrics {
   299  	return rpmMetricsPool.Get().(*RemoteProducerMetadata_Metrics)
   300  }
   301  
   302  // RemoteProducerMetaToLocalMeta converts a RemoteProducerMetadata struct to
   303  // ProducerMetadata and returns whether the conversion was successful or not.
   304  func RemoteProducerMetaToLocalMeta(
   305  	ctx context.Context, rpm RemoteProducerMetadata,
   306  ) (ProducerMetadata, bool) {
   307  	meta := GetProducerMeta()
   308  	switch v := rpm.Value.(type) {
   309  	case *RemoteProducerMetadata_RangeInfo:
   310  		meta.Ranges = v.RangeInfo.RangeInfo
   311  	case *RemoteProducerMetadata_TraceData_:
   312  		meta.TraceData = v.TraceData.CollectedSpans
   313  	case *RemoteProducerMetadata_LeafTxnFinalState:
   314  		meta.LeafTxnFinalState = v.LeafTxnFinalState
   315  	case *RemoteProducerMetadata_RowNum_:
   316  		meta.RowNum = v.RowNum
   317  	case *RemoteProducerMetadata_SamplerProgress_:
   318  		meta.SamplerProgress = v.SamplerProgress
   319  	case *RemoteProducerMetadata_BulkProcessorProgress_:
   320  		meta.BulkProcessorProgress = v.BulkProcessorProgress
   321  	case *RemoteProducerMetadata_Error:
   322  		meta.Err = v.Error.ErrorDetail(ctx)
   323  	case *RemoteProducerMetadata_Metrics_:
   324  		meta.Metrics = v.Metrics
   325  	default:
   326  		return *meta, false
   327  	}
   328  	return *meta, true
   329  }
   330  
   331  // LocalMetaToRemoteProducerMeta converts a ProducerMetadata struct to
   332  // RemoteProducerMetadata.
   333  func LocalMetaToRemoteProducerMeta(
   334  	ctx context.Context, meta ProducerMetadata,
   335  ) RemoteProducerMetadata {
   336  	var rpm RemoteProducerMetadata
   337  	if meta.Ranges != nil {
   338  		rpm.Value = &RemoteProducerMetadata_RangeInfo{
   339  			RangeInfo: &RemoteProducerMetadata_RangeInfos{
   340  				RangeInfo: meta.Ranges,
   341  			},
   342  		}
   343  	} else if meta.TraceData != nil {
   344  		rpm.Value = &RemoteProducerMetadata_TraceData_{
   345  			TraceData: &RemoteProducerMetadata_TraceData{
   346  				CollectedSpans: meta.TraceData,
   347  			},
   348  		}
   349  	} else if meta.LeafTxnFinalState != nil {
   350  		rpm.Value = &RemoteProducerMetadata_LeafTxnFinalState{
   351  			LeafTxnFinalState: meta.LeafTxnFinalState,
   352  		}
   353  	} else if meta.RowNum != nil {
   354  		rpm.Value = &RemoteProducerMetadata_RowNum_{
   355  			RowNum: meta.RowNum,
   356  		}
   357  	} else if meta.SamplerProgress != nil {
   358  		rpm.Value = &RemoteProducerMetadata_SamplerProgress_{
   359  			SamplerProgress: meta.SamplerProgress,
   360  		}
   361  	} else if meta.BulkProcessorProgress != nil {
   362  		rpm.Value = &RemoteProducerMetadata_BulkProcessorProgress_{
   363  			BulkProcessorProgress: meta.BulkProcessorProgress,
   364  		}
   365  	} else if meta.Metrics != nil {
   366  		rpm.Value = &RemoteProducerMetadata_Metrics_{
   367  			Metrics: meta.Metrics,
   368  		}
   369  	} else {
   370  		rpm.Value = &RemoteProducerMetadata_Error{
   371  			Error: NewError(ctx, meta.Err),
   372  		}
   373  	}
   374  	return rpm
   375  }
   376  
   377  // MetadataSource is an interface implemented by processors and columnar
   378  // operators that can produce metadata.
   379  type MetadataSource interface {
   380  	// DrainMeta returns all the metadata produced by the processor or operator.
   381  	// It will be called exactly once, usually, when the processor or operator
   382  	// has finished doing its computations.
   383  	// Implementers can choose what to do on subsequent calls (if such occur).
   384  	// TODO(yuzefovich): modify the contract to require returning nil on all
   385  	// calls after the first one.
   386  	DrainMeta(context.Context) []ProducerMetadata
   387  }