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