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

     1  // Copyright 2015 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  	"strconv"
    16  
    17  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
    18  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
    19  	"github.com/cockroachdb/cockroach/pkg/sql/rowcontainer"
    20  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    22  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    23  	"github.com/cockroachdb/errors"
    24  )
    25  
    26  type valuesNode struct {
    27  	columns sqlbase.ResultColumns
    28  	tuples  [][]tree.TypedExpr
    29  
    30  	// specifiedInQuery is set if the valuesNode represents a literal
    31  	// relational expression that was present in the original SQL text,
    32  	// as opposed to e.g. a valuesNode resulting from the expansion of
    33  	// a vtable value generator. This changes distsql physical planning.
    34  	specifiedInQuery bool
    35  
    36  	valuesRun
    37  }
    38  
    39  // Values implements the VALUES clause.
    40  func (p *planner) Values(
    41  	ctx context.Context, origN tree.Statement, desiredTypes []*types.T,
    42  ) (planNode, error) {
    43  	v := &valuesNode{
    44  		specifiedInQuery: true,
    45  	}
    46  
    47  	// If we have names, extract them.
    48  	var n *tree.ValuesClause
    49  	switch t := origN.(type) {
    50  	case *tree.ValuesClauseWithNames:
    51  		n = &t.ValuesClause
    52  	case *tree.ValuesClause:
    53  		n = t
    54  	default:
    55  		return nil, errors.AssertionFailedf("unhandled case in values: %T %v", origN, origN)
    56  	}
    57  
    58  	if len(n.Rows) == 0 {
    59  		return v, nil
    60  	}
    61  
    62  	numCols := len(n.Rows[0])
    63  
    64  	v.tuples = make([][]tree.TypedExpr, 0, len(n.Rows))
    65  	tupleBuf := make([]tree.TypedExpr, len(n.Rows)*numCols)
    66  
    67  	v.columns = make(sqlbase.ResultColumns, 0, numCols)
    68  
    69  	// We need to save and restore the previous value of the field in
    70  	// semaCtx in case we are recursively called within a subquery
    71  	// context.
    72  	defer p.semaCtx.Properties.Restore(p.semaCtx.Properties)
    73  
    74  	// Ensure there are no special functions in the clause.
    75  	p.semaCtx.Properties.Require("VALUES", tree.RejectSpecial)
    76  
    77  	for num, tuple := range n.Rows {
    78  		if a, e := len(tuple), numCols; a != e {
    79  			return nil, newValuesListLenErr(e, a)
    80  		}
    81  
    82  		// Chop off prefix of tupleBuf and limit its capacity.
    83  		tupleRow := tupleBuf[:numCols:numCols]
    84  		tupleBuf = tupleBuf[numCols:]
    85  
    86  		for i, expr := range tuple {
    87  			desired := types.Any
    88  			if len(desiredTypes) > i {
    89  				desired = desiredTypes[i]
    90  			}
    91  
    92  			// Clear the properties so we can check them below.
    93  			typedExpr, err := p.analyzeExpr(ctx, expr, nil, tree.IndexedVarHelper{}, desired, false, "")
    94  			if err != nil {
    95  				return nil, err
    96  			}
    97  
    98  			typ := typedExpr.ResolvedType()
    99  			if num == 0 {
   100  				v.columns = append(v.columns, sqlbase.ResultColumn{Name: "column" + strconv.Itoa(i+1), Typ: typ})
   101  			} else if v.columns[i].Typ.Family() == types.UnknownFamily {
   102  				v.columns[i].Typ = typ
   103  			} else if typ.Family() != types.UnknownFamily && !typ.Equivalent(v.columns[i].Typ) {
   104  				return nil, pgerror.Newf(pgcode.DatatypeMismatch,
   105  					"VALUES types %s and %s cannot be matched", typ, v.columns[i].Typ)
   106  			}
   107  
   108  			tupleRow[i] = typedExpr
   109  		}
   110  		v.tuples = append(v.tuples, tupleRow)
   111  	}
   112  	return v, nil
   113  }
   114  
   115  func (p *planner) newContainerValuesNode(columns sqlbase.ResultColumns, capacity int) *valuesNode {
   116  	return &valuesNode{
   117  		columns: columns,
   118  		valuesRun: valuesRun{
   119  			rows: rowcontainer.NewRowContainer(
   120  				p.EvalContext().Mon.MakeBoundAccount(), sqlbase.ColTypeInfoFromResCols(columns), capacity,
   121  			),
   122  		},
   123  	}
   124  }
   125  
   126  // valuesRun is the run-time state of a valuesNode during local execution.
   127  type valuesRun struct {
   128  	rows    *rowcontainer.RowContainer
   129  	nextRow int // The index of the next row.
   130  }
   131  
   132  func (n *valuesNode) startExec(params runParams) error {
   133  	if n.rows != nil {
   134  		// n.rows was already created in newContainerValuesNode.
   135  		// Nothing to do here.
   136  		return nil
   137  	}
   138  
   139  	// This node is coming from a SQL query (as opposed to sortNode and
   140  	// others that create a valuesNode internally for storing results
   141  	// from other planNodes), so its expressions need evaluating.
   142  	// This may run subqueries.
   143  	n.rows = rowcontainer.NewRowContainer(
   144  		params.extendedEvalCtx.Mon.MakeBoundAccount(),
   145  		sqlbase.ColTypeInfoFromResCols(n.columns),
   146  		len(n.tuples),
   147  	)
   148  
   149  	row := make([]tree.Datum, len(n.columns))
   150  	for _, tupleRow := range n.tuples {
   151  		for i, typedExpr := range tupleRow {
   152  			var err error
   153  			row[i], err = typedExpr.Eval(params.EvalContext())
   154  			if err != nil {
   155  				return err
   156  			}
   157  		}
   158  		if _, err := n.rows.AddRow(params.ctx, row); err != nil {
   159  			return err
   160  		}
   161  	}
   162  
   163  	return nil
   164  }
   165  
   166  func (n *valuesNode) Next(runParams) (bool, error) {
   167  	if n.nextRow >= n.rows.Len() {
   168  		return false, nil
   169  	}
   170  	n.nextRow++
   171  	return true, nil
   172  }
   173  
   174  func (n *valuesNode) Values() tree.Datums {
   175  	return n.rows.At(n.nextRow - 1)
   176  }
   177  
   178  func (n *valuesNode) Close(ctx context.Context) {
   179  	if n.rows != nil {
   180  		n.rows.Close(ctx)
   181  		n.rows = nil
   182  	}
   183  }
   184  
   185  func newValuesListLenErr(exp, got int) error {
   186  	return pgerror.Newf(
   187  		pgcode.Syntax,
   188  		"VALUES lists must all be the same length, expected %d columns, found %d",
   189  		exp, got)
   190  }