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 }