MCPcopy
hub / github.com/pingcap/tidb / NewPlanCacheKey

Function NewPlanCacheKey

pkg/planner/core/plan_cache_utils.go:257–415  ·  view source on GitHub ↗

NewPlanCacheKey creates the plan cache key for this statement. Note: lastUpdatedSchemaVersion will only be set in the case of rc or for update read in order to differentiate the cache key. In other cases, it will be 0. All information that might affect the plan should be considered in this function.

(sctx sessionctx.Context, stmt *PlanCacheStmt)

Source from the content-addressed store, hash-verified

255// differentiate the cache key. In other cases, it will be 0.
256// All information that might affect the plan should be considered in this function.
257func NewPlanCacheKey(sctx sessionctx.Context, stmt *PlanCacheStmt) (key, binding string, cacheable bool, reason string, err error) {
258 binding, ignored := bindinfo.MatchSQLBindingForPlanCache(sctx, stmt.PreparedAst.Stmt, &stmt.BindingInfo)
259 if ignored {
260 return "", binding, false, "ignore plan cache by binding", nil
261 }
262
263 // In rc or for update read, we need the latest schema version to decide whether we need to
264 // rebuild the plan. So we set this value in rc or for update read. In other cases, let it be 0.
265 var latestSchemaVersion int64
266 if sctx.GetSessionVars().IsIsolation(ast.ReadCommitted) || stmt.ForUpdateRead {
267 // In Rc or ForUpdateRead, we should check if the information schema has been changed since
268 // last time. If it changed, we should rebuild the plan. Here, we use a different and more
269 // up-to-date schema version which can lead plan cache miss and thus, the plan will be rebuilt.
270 latestSchemaVersion = domain.GetDomain(sctx).InfoSchema().SchemaMetaVersion()
271 }
272
273 // rebuild key to exclude kv.TiFlash when stmt is not read only
274 vars := sctx.GetSessionVars()
275 if _, isolationReadContainTiFlash := vars.IsolationReadEngines[kv.TiFlash]; isolationReadContainTiFlash && !IsReadOnly(stmt.PreparedAst.Stmt, vars) {
276 delete(vars.IsolationReadEngines, kv.TiFlash)
277 defer func() {
278 vars.IsolationReadEngines[kv.TiFlash] = struct{}{}
279 }()
280 }
281
282 if stmt.StmtText == "" {
283 return "", "", false, "", errors.New("no statement text")
284 }
285 if stmt.SchemaVersion == 0 && !intest.InTest {
286 return "", "", false, "", errors.New("Schema version uninitialized")
287 }
288 stmtDB := stmt.StmtDB
289 if stmtDB == "" {
290 stmtDB = vars.CurrentDB
291 }
292 timezoneOffset := 0
293 if vars.TimeZone != nil {
294 _, timezoneOffset = time.Now().In(vars.TimeZone).Zone()
295 }
296 connCharset, connCollation := vars.GetCharsetInfo()
297
298 // not allow to share the same plan among different users for safety.
299 var userName, hostName string
300 if sctx.GetSessionVars().User != nil { // might be nil if in test
301 userName = sctx.GetSessionVars().User.AuthUsername
302 hostName = sctx.GetSessionVars().User.AuthHostname
303 }
304
305 // the user might switch the prune mode dynamically
306 pruneMode := sctx.GetSessionVars().PartitionPruneMode.Load()
307
308 hash := make([]byte, 0, len(stmt.StmtText)*2) // TODO: a Pool for this
309 hash = append(hash, hack.Slice(userName)...)
310 hash = append(hash, hack.Slice(hostName)...)
311 hash = append(hash, hack.Slice(stmtDB)...)
312 hash = append(hash, hack.Slice(stmt.StmtText)...)
313 hash = codec.EncodeInt(hash, stmt.SchemaVersion)
314 hash = hashInt64Uint64Map(hash, stmt.RelateVersion)

Callers 2

CloseMethod · 0.92
GetPlanFromPlanCacheFunction · 0.85

Calls 15

GetDomainFunction · 0.92
SliceFunction · 0.92
EncodeIntFunction · 0.92
EncodeUintFunction · 0.92
GetGlobalConfigFunction · 0.92
hashInt64Uint64MapFunction · 0.85
bool2ByteFunction · 0.85
IsIsolationMethod · 0.80
InfoSchemaMethod · 0.80

Tested by

no test coverage detected