github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/sem/tree/placeholders.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 tree
    12  
    13  import (
    14  	"bytes"
    15  	"fmt"
    16  	"math"
    17  
    18  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
    19  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
    20  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    21  	"github.com/cockroachdb/errors"
    22  )
    23  
    24  // PlaceholderIdx is the 0-based index of a placeholder. Placeholder "$1"
    25  // has PlaceholderIdx=0.
    26  type PlaceholderIdx uint16
    27  
    28  // MaxPlaceholderIdx is the maximum allowed value of a PlaceholderIdx.
    29  // The pgwire protocol is limited to 2^16 placeholders, so we limit the IDs to
    30  // this range as well.
    31  const MaxPlaceholderIdx = math.MaxUint16
    32  
    33  // String returns the index as a placeholder string representation ($1, $2 etc).
    34  func (idx PlaceholderIdx) String() string {
    35  	return fmt.Sprintf("$%d", idx+1)
    36  }
    37  
    38  // PlaceholderTypes stores placeholder types (or type hints), one per
    39  // PlaceholderIdx.  The slice is always pre-allocated to the number of
    40  // placeholders in the statement. Entries that don't yet have a type are nil.
    41  type PlaceholderTypes []*types.T
    42  
    43  // Equals returns true if two PlaceholderTypes contain the same types.
    44  func (pt PlaceholderTypes) Equals(other PlaceholderTypes) bool {
    45  	if len(pt) != len(other) {
    46  		return false
    47  	}
    48  	for i, t := range pt {
    49  		switch {
    50  		case t == nil && other[i] == nil:
    51  		case t == nil || other[i] == nil:
    52  			return false
    53  		case !t.Equivalent(other[i]):
    54  			return false
    55  		}
    56  	}
    57  	return true
    58  }
    59  
    60  // AssertAllSet verifies that all types have been set and returns an error
    61  // otherwise.
    62  func (pt PlaceholderTypes) AssertAllSet() error {
    63  	for i := range pt {
    64  		if pt[i] == nil {
    65  			return placeholderTypeAmbiguityError(PlaceholderIdx(i))
    66  		}
    67  	}
    68  	return nil
    69  }
    70  
    71  // QueryArguments stores query arguments, one per PlaceholderIdx.
    72  //
    73  // A nil value represents a NULL argument.
    74  type QueryArguments []TypedExpr
    75  
    76  func (qa QueryArguments) String() string {
    77  	if len(qa) == 0 {
    78  		return "{}"
    79  	}
    80  	var buf bytes.Buffer
    81  	buf.WriteByte('{')
    82  	sep := ""
    83  	for k, v := range qa {
    84  		fmt.Fprintf(&buf, "%s%s:%q", sep, PlaceholderIdx(k), v)
    85  		sep = ", "
    86  	}
    87  	buf.WriteByte('}')
    88  	return buf.String()
    89  }
    90  
    91  // PlaceholderTypesInfo encapsulates typing information for placeholders.
    92  type PlaceholderTypesInfo struct {
    93  	// TypeHints contains the initially set type hints for each placeholder if
    94  	// present. It is not changed during query type checking.
    95  	TypeHints PlaceholderTypes
    96  	// Types contains the final types set for each placeholder after type
    97  	// checking.
    98  	Types PlaceholderTypes
    99  }
   100  
   101  // Type returns the known type of a placeholder. If there is no known type yet
   102  // but there is a type hint, returns the type hint.
   103  func (p *PlaceholderTypesInfo) Type(idx PlaceholderIdx) (_ *types.T, ok bool) {
   104  	t := p.Types[idx]
   105  	if t == nil && len(p.TypeHints) >= int(idx) {
   106  		t = p.TypeHints[idx]
   107  	}
   108  	return t, (t != nil)
   109  }
   110  
   111  // ValueType returns the type of the value that must be supplied for a placeholder.
   112  // This is the type hint given by the client if there is one, or the placeholder
   113  // type if there isn't one. This can differ from Type(idx) when a client hint is
   114  // overridden (see Placeholder.Eval).
   115  func (p *PlaceholderTypesInfo) ValueType(idx PlaceholderIdx) (_ *types.T, ok bool) {
   116  	var t *types.T
   117  	if len(p.TypeHints) >= int(idx) {
   118  		t = p.TypeHints[idx]
   119  	}
   120  	if t == nil {
   121  		t = p.Types[idx]
   122  	}
   123  	return t, (t != nil)
   124  }
   125  
   126  // SetType assigns a known type to a placeholder.
   127  // Reports an error if another type was previously assigned.
   128  func (p *PlaceholderTypesInfo) SetType(idx PlaceholderIdx, typ *types.T) error {
   129  	if t := p.Types[idx]; t != nil {
   130  		if !typ.Equivalent(t) {
   131  			return pgerror.Newf(
   132  				pgcode.DatatypeMismatch,
   133  				"placeholder %s already has type %s, cannot assign %s", idx, t, typ)
   134  		}
   135  		return nil
   136  	}
   137  	p.Types[idx] = typ
   138  	return nil
   139  }
   140  
   141  // PlaceholderInfo defines the interface to SQL placeholders.
   142  type PlaceholderInfo struct {
   143  	PlaceholderTypesInfo
   144  
   145  	Values QueryArguments
   146  }
   147  
   148  // Init initializes a PlaceholderInfo structure appropriate for the given number
   149  // of placeholders, and with the given (optional) type hints.
   150  func (p *PlaceholderInfo) Init(numPlaceholders int, typeHints PlaceholderTypes) error {
   151  	p.Types = make(PlaceholderTypes, numPlaceholders)
   152  	if typeHints == nil {
   153  		p.TypeHints = make(PlaceholderTypes, numPlaceholders)
   154  	} else {
   155  		if err := checkPlaceholderArity(len(typeHints), numPlaceholders); err != nil {
   156  			return err
   157  		}
   158  		p.TypeHints = typeHints
   159  	}
   160  	p.Values = nil
   161  	return nil
   162  }
   163  
   164  // Assign resets the PlaceholderInfo to the contents of src.
   165  // If src is nil, a new structure is initialized.
   166  func (p *PlaceholderInfo) Assign(src *PlaceholderInfo, numPlaceholders int) error {
   167  	if src != nil {
   168  		if err := checkPlaceholderArity(len(src.Types), numPlaceholders); err != nil {
   169  			return err
   170  		}
   171  		*p = *src
   172  		return nil
   173  	}
   174  	return p.Init(numPlaceholders, nil /* typeHints */)
   175  }
   176  
   177  func checkPlaceholderArity(numTypes, numPlaceholders int) error {
   178  	if numTypes > numPlaceholders {
   179  		return errors.AssertionFailedf(
   180  			"unexpected placeholder types: got %d, expected %d",
   181  			numTypes, numPlaceholders)
   182  	} else if numTypes < numPlaceholders {
   183  		return pgerror.Newf(pgcode.UndefinedParameter,
   184  			"could not find types for all placeholders: got %d, expected %d",
   185  			numTypes, numPlaceholders)
   186  	}
   187  	return nil
   188  }
   189  
   190  // Value returns the known value of a placeholder.  Returns false in
   191  // the 2nd value if the placeholder does not have a value.
   192  func (p *PlaceholderInfo) Value(idx PlaceholderIdx) (TypedExpr, bool) {
   193  	if len(p.Values) <= int(idx) || p.Values[idx] == nil {
   194  		return nil, false
   195  	}
   196  	return p.Values[idx], true
   197  }
   198  
   199  // IsUnresolvedPlaceholder returns whether expr is an unresolved placeholder. In
   200  // other words, it returns whether the provided expression is a placeholder
   201  // expression or a placeholder expression within nested parentheses, and if so,
   202  // whether the placeholder's type remains unset in the PlaceholderInfo.
   203  func (p *PlaceholderInfo) IsUnresolvedPlaceholder(expr Expr) bool {
   204  	if t, ok := StripParens(expr).(*Placeholder); ok {
   205  		_, res := p.Type(t.Idx)
   206  		return !res
   207  	}
   208  	return false
   209  }