vitess.io/vitess@v0.16.2/go/vt/vtgate/engine/primitive.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package engine 18 19 import ( 20 "context" 21 22 "vitess.io/vitess/go/mysql/collations" 23 "vitess.io/vitess/go/sqltypes" 24 "vitess.io/vitess/go/vt/key" 25 "vitess.io/vitess/go/vt/sqlparser" 26 "vitess.io/vitess/go/vt/srvtopo" 27 "vitess.io/vitess/go/vt/vtgate/vindexes" 28 29 binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" 30 querypb "vitess.io/vitess/go/vt/proto/query" 31 vtgatepb "vitess.io/vitess/go/vt/proto/vtgate" 32 ) 33 34 const ( 35 // SeqVarName is a reserved bind var name for sequence values. 36 SeqVarName = "__seq" 37 // ListVarName is a reserved bind var name for list vars. 38 // This is used for sending different IN clause values 39 // to different shards. 40 ListVarName = "__vals" 41 ) 42 43 type ( 44 // VCursor defines the interface the engine will use 45 // to execute routes. 46 VCursor interface { 47 GetKeyspace() string 48 // MaxMemoryRows returns the maxMemoryRows flag value. 49 MaxMemoryRows() int 50 51 // ExceedsMaxMemoryRows returns a boolean indicating whether 52 // the maxMemoryRows value has been exceeded. Returns false 53 // if the max memory rows override directive is set to true 54 ExceedsMaxMemoryRows(numRows int) bool 55 56 // V3 functions. 57 Execute(ctx context.Context, method string, query string, bindVars map[string]*querypb.BindVariable, rollbackOnError bool, co vtgatepb.CommitOrder) (*sqltypes.Result, error) 58 AutocommitApproval() bool 59 60 // Execute the given primitive 61 ExecutePrimitive(ctx context.Context, primitive Primitive, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) 62 // Execute the given primitive in a new autocommit session 63 ExecutePrimitiveStandalone(ctx context.Context, primitive Primitive, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) 64 65 // Execute the given primitive 66 StreamExecutePrimitive(ctx context.Context, primitive Primitive, bindVars map[string]*querypb.BindVariable, wantfields bool, callback func(*sqltypes.Result) error) error 67 // Execute the given primitive in a new autocommit session 68 StreamExecutePrimitiveStandalone(ctx context.Context, primitive Primitive, bindVars map[string]*querypb.BindVariable, wantfields bool, callback func(result *sqltypes.Result) error) error 69 70 // Shard-level functions. 71 ExecuteMultiShard(ctx context.Context, primitive Primitive, rss []*srvtopo.ResolvedShard, queries []*querypb.BoundQuery, rollbackOnError, canAutocommit bool) (*sqltypes.Result, []error) 72 ExecuteStandalone(ctx context.Context, primitive Primitive, query string, bindVars map[string]*querypb.BindVariable, rs *srvtopo.ResolvedShard) (*sqltypes.Result, error) 73 StreamExecuteMulti(ctx context.Context, primitive Primitive, query string, rss []*srvtopo.ResolvedShard, bindVars []map[string]*querypb.BindVariable, rollbackOnError bool, autocommit bool, callback func(reply *sqltypes.Result) error) []error 74 75 // Keyspace ID level functions. 76 ExecuteKeyspaceID(ctx context.Context, keyspace string, ksid []byte, query string, bindVars map[string]*querypb.BindVariable, rollbackOnError, autocommit bool) (*sqltypes.Result, error) 77 78 // Resolver methods, from key.Destination to srvtopo.ResolvedShard. 79 // Will replace all of the Topo functions. 80 ResolveDestinations(ctx context.Context, keyspace string, ids []*querypb.Value, destinations []key.Destination) ([]*srvtopo.ResolvedShard, [][]*querypb.Value, error) 81 82 ResolveDestinationsMultiCol(ctx context.Context, keyspace string, ids [][]sqltypes.Value, destinations []key.Destination) ([]*srvtopo.ResolvedShard, [][][]sqltypes.Value, error) 83 84 ExecuteVSchema(ctx context.Context, keyspace string, vschemaDDL *sqlparser.AlterVschema) error 85 86 Session() SessionActions 87 88 ConnCollation() collations.ID 89 90 ExecuteLock(ctx context.Context, rs *srvtopo.ResolvedShard, query *querypb.BoundQuery, lockFuncType sqlparser.LockingFuncType) (*sqltypes.Result, error) 91 92 InTransactionAndIsDML() bool 93 94 LookupRowLockShardSession() vtgatepb.CommitOrder 95 96 FindRoutedTable(tablename sqlparser.TableName) (*vindexes.Table, error) 97 98 // GetDBDDLPlugin gets the configured plugin for DROP/CREATE DATABASE 99 GetDBDDLPluginName() string 100 101 // KeyspaceAvailable returns true when a keyspace is visible from vtgate 102 KeyspaceAvailable(ks string) bool 103 104 MessageStream(ctx context.Context, rss []*srvtopo.ResolvedShard, tableName string, callback func(*sqltypes.Result) error) error 105 106 VStream(ctx context.Context, rss []*srvtopo.ResolvedShard, filter *binlogdatapb.Filter, gtid string, callback func(evs []*binlogdatapb.VEvent) error) error 107 108 // ShowExec takes in show command and use executor to execute the query, they are used when topo access is involved. 109 ShowExec(ctx context.Context, command sqlparser.ShowCommandType, filter *sqlparser.ShowFilter) (*sqltypes.Result, error) 110 // SetExec takes in k,v pair and use executor to set them in topo metadata. 111 SetExec(ctx context.Context, name string, value string) error 112 113 // CanUseSetVar returns true if system_settings can use SET_VAR hint. 114 CanUseSetVar() bool 115 116 // ReleaseLock releases all the held advisory locks. 117 ReleaseLock(ctx context.Context) error 118 } 119 120 // SessionActions gives primitives ability to interact with the session state 121 SessionActions interface { 122 // RecordWarning stores the given warning in the current session 123 RecordWarning(warning *querypb.QueryWarning) 124 125 SetTarget(target string) error 126 127 SetUDV(key string, value any) error 128 129 SetSysVar(name string, expr string) 130 131 // NeedsReservedConn marks this session as needing a dedicated connection to underlying database 132 NeedsReservedConn() 133 134 // InReservedConn provides whether this session is using reserved connection 135 InReservedConn() bool 136 137 // ShardSession returns shard info about open connections 138 ShardSession() []*srvtopo.ResolvedShard 139 140 SetAutocommit(ctx context.Context, autocommit bool) error 141 SetClientFoundRows(context.Context, bool) error 142 SetSkipQueryPlanCache(context.Context, bool) error 143 SetSQLSelectLimit(int64) error 144 SetTransactionMode(vtgatepb.TransactionMode) 145 SetWorkload(querypb.ExecuteOptions_Workload) 146 SetPlannerVersion(querypb.ExecuteOptions_PlannerVersion) 147 SetConsolidator(querypb.ExecuteOptions_Consolidator) 148 SetFoundRows(uint64) 149 150 SetDDLStrategy(string) 151 GetDDLStrategy() string 152 153 GetSessionUUID() string 154 155 SetSessionEnableSystemSettings(context.Context, bool) error 156 GetSessionEnableSystemSettings() bool 157 158 GetSystemVariables(func(k string, v string)) 159 HasSystemVariables() bool 160 161 // SetReadAfterWriteGTID sets the GTID that the user expects a replica to have caught up with before answering a query 162 SetReadAfterWriteGTID(string) 163 SetReadAfterWriteTimeout(float64) 164 SetSessionTrackGTIDs(bool) 165 166 // HasCreatedTempTable will mark the session as having created temp tables 167 HasCreatedTempTable() 168 GetWarnings() []*querypb.QueryWarning 169 170 // AnyAdvisoryLockTaken returns true of any advisory lock is taken 171 AnyAdvisoryLockTaken() bool 172 // AddAdvisoryLock adds advisory lock to the session 173 AddAdvisoryLock(name string) 174 // RemoveAdvisoryLock removes advisory lock from the session 175 RemoveAdvisoryLock(name string) 176 177 // VExplainLogging enables logging of all interactions to the tablets so 178 // VEXPLAIN QUERIES/ALL can report what's being done 179 VExplainLogging() 180 181 // GetVExplainLogs retrieves the vttablet interaction logs 182 GetVExplainLogs() []ExecuteEntry 183 184 // SetCommitOrder sets the commit order for the shard session in respect of the type of vindex lookup. 185 // This is used to select the right shard session to perform the vindex lookup query. 186 SetCommitOrder(co vtgatepb.CommitOrder) 187 188 // GetQueryTimeout gets the query timeout and takes in the query timeout from comments 189 GetQueryTimeout(queryTimeoutFromComment int) int 190 191 // SetQueryTimeout sets the query timeout 192 SetQueryTimeout(queryTimeout int64) 193 194 // InTransaction returns true if the session has already opened transaction or 195 // will start a transaction on the query execution. 196 InTransaction() bool 197 } 198 199 // Match is used to check if a Primitive matches 200 Match func(node Primitive) bool 201 202 // Primitive is the building block of the engine execution plan. They form a tree structure, where the leaves typically 203 // issue queries to one or more vttablet. 204 // During execution, the Primitive's pass Result objects up the tree structure, until reaching the root, 205 // and its result is passed to the client. 206 Primitive interface { 207 RouteType() string 208 GetKeyspaceName() string 209 GetTableName() string 210 GetFields(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable) (*sqltypes.Result, error) 211 NeedsTransaction() bool 212 213 TryExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) 214 TryStreamExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool, callback func(*sqltypes.Result) error) error 215 216 // Inputs is a slice containing the inputs to this Primitive 217 Inputs() []Primitive 218 219 // description is the description, sans the inputs, of this Primitive. 220 // to get the plan description with all children, use PrimitiveToPlanDescription() 221 description() PrimitiveDescription 222 } 223 224 // noInputs default implementation for Primitives that are leaves 225 noInputs struct{} 226 227 // noTxNeeded is a default implementation for Primitives that don't need transaction handling 228 noTxNeeded struct{} 229 230 // txNeeded is a default implementation for Primitives that need transaction handling 231 txNeeded struct{} 232 233 // Gen4Comparer interfaces all Primitive used to compare Gen4 with other planners (V3, MySQL, ...). 234 Gen4Comparer interface { 235 Primitive 236 GetGen4Primitive() Primitive 237 } 238 ) 239 240 // Find will return the first Primitive that matches the evaluate function. If no match is found, nil will be returned 241 func Find(isMatch Match, start Primitive) Primitive { 242 if isMatch(start) { 243 return start 244 } 245 for _, input := range start.Inputs() { 246 result := Find(isMatch, input) 247 if result != nil { 248 return result 249 } 250 } 251 return nil 252 } 253 254 // Exists traverses recursively down the Primitive tree structure, and returns true when Match returns true 255 func Exists(m Match, p Primitive) bool { 256 return Find(m, p) != nil 257 } 258 259 // Inputs implements no inputs 260 func (noInputs) Inputs() []Primitive { 261 return nil 262 } 263 264 func (noTxNeeded) NeedsTransaction() bool { 265 return false 266 } 267 268 func (txNeeded) NeedsTransaction() bool { 269 return true 270 }