diff options
Diffstat (limited to 'src/backend/catalog/namespace.c')
| -rw-r--r-- | src/backend/catalog/namespace.c | 98 |
1 files changed, 88 insertions, 10 deletions
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index 5ff78248e0..2ec23016fe 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -126,6 +126,11 @@ * namespaceUser is the userid the path has been computed for. * * Note: all data pointed to by these List variables is in TopMemoryContext. + * + * activePathGeneration is incremented whenever the effective values of + * activeSearchPath/activeCreationNamespace/activeTempCreationPending change. + * This can be used to quickly detect whether any change has happened since + * a previous examination of the search path state. */ /* These variables define the actually active state: */ @@ -138,6 +143,9 @@ static Oid activeCreationNamespace = InvalidOid; /* if true, activeCreationNamespace is wrong, it should be temp namespace */ static bool activeTempCreationPending = false; +/* current generation counter; make sure this is never zero */ +static uint64 activePathGeneration = 1; + /* These variables are the values last derived from namespace_search_path: */ static List *baseSearchPath = NIL; @@ -3373,6 +3381,7 @@ GetOverrideSearchPath(MemoryContext context) schemas = list_delete_first(schemas); } result->schemas = schemas; + result->generation = activePathGeneration; MemoryContextSwitchTo(oldcxt); @@ -3393,12 +3402,18 @@ CopyOverrideSearchPath(OverrideSearchPath *path) result->schemas = list_copy(path->schemas); result->addCatalog = path->addCatalog; result->addTemp = path->addTemp; + result->generation = path->generation; return result; } /* * OverrideSearchPathMatchesCurrent - does path match current setting? + * + * This is tested over and over in some common code paths, and in the typical + * scenario where the active search path seldom changes, it'll always succeed. + * We make that case fast by keeping a generation counter that is advanced + * whenever the active search path changes. */ bool OverrideSearchPathMatchesCurrent(OverrideSearchPath *path) @@ -3408,6 +3423,10 @@ OverrideSearchPathMatchesCurrent(OverrideSearchPath *path) recomputeNamespacePath(); + /* Quick out if already known equal to active path. */ + if (path->generation == activePathGeneration) + return true; + /* We scan down the activeSearchPath to see if it matches the input. */ lc = list_head(activeSearchPath); @@ -3440,6 +3459,13 @@ OverrideSearchPathMatchesCurrent(OverrideSearchPath *path) } if (lc) return false; + + /* + * Update path->generation so that future tests will return quickly, so + * long as the active search path doesn't change. + */ + path->generation = activePathGeneration; + return true; } @@ -3510,6 +3536,14 @@ PushOverrideSearchPath(OverrideSearchPath *newpath) activeCreationNamespace = entry->creationNamespace; activeTempCreationPending = false; /* XXX is this OK? */ + /* + * We always increment activePathGeneration when pushing/popping an + * override path. In current usage, these actions always change the + * effective path state, so there's no value in checking to see if it + * didn't change. + */ + activePathGeneration++; + MemoryContextSwitchTo(oldcxt); } @@ -3551,6 +3585,9 @@ PopOverrideSearchPath(void) activeCreationNamespace = baseCreationNamespace; activeTempCreationPending = baseTempCreationPending; } + + /* As above, the generation always increments. */ + activePathGeneration++; } @@ -3707,6 +3744,7 @@ recomputeNamespacePath(void) ListCell *l; bool temp_missing; Oid firstNS; + bool pathChanged; MemoryContext oldcxt; /* Do nothing if an override search spec is active. */ @@ -3814,18 +3852,31 @@ recomputeNamespacePath(void) oidlist = lcons_oid(myTempNamespace, oidlist); /* - * Now that we've successfully built the new list of namespace OIDs, save - * it in permanent storage. + * We want to detect the case where the effective value of the base search + * path variables didn't change. As long as we're doing so, we can avoid + * copying the OID list unncessarily. */ - oldcxt = MemoryContextSwitchTo(TopMemoryContext); - newpath = list_copy(oidlist); - MemoryContextSwitchTo(oldcxt); + if (baseCreationNamespace == firstNS && + baseTempCreationPending == temp_missing && + equal(oidlist, baseSearchPath)) + { + pathChanged = false; + } + else + { + pathChanged = true; + + /* Must save OID list in permanent storage. */ + oldcxt = MemoryContextSwitchTo(TopMemoryContext); + newpath = list_copy(oidlist); + MemoryContextSwitchTo(oldcxt); - /* Now safe to assign to state variables. */ - list_free(baseSearchPath); - baseSearchPath = newpath; - baseCreationNamespace = firstNS; - baseTempCreationPending = temp_missing; + /* Now safe to assign to state variables. */ + list_free(baseSearchPath); + baseSearchPath = newpath; + baseCreationNamespace = firstNS; + baseTempCreationPending = temp_missing; + } /* Mark the path valid. */ baseSearchPathValid = true; @@ -3836,6 +3887,16 @@ recomputeNamespacePath(void) activeCreationNamespace = baseCreationNamespace; activeTempCreationPending = baseTempCreationPending; + /* + * Bump the generation only if something actually changed. (Notice that + * what we compared to was the old state of the base path variables; so + * this does not deal with the situation where we have just popped an + * override path and restored the prior state of the base path. Instead + * we rely on the override-popping logic to have bumped the generation.) + */ + if (pathChanged) + activePathGeneration++; + /* Clean up. */ pfree(rawname); list_free(namelist); @@ -4054,6 +4115,8 @@ AtEOXact_Namespace(bool isCommit, bool parallel) activeSearchPath = baseSearchPath; activeCreationNamespace = baseCreationNamespace; activeTempCreationPending = baseTempCreationPending; + /* Always bump generation --- see note in recomputeNamespacePath */ + activePathGeneration++; } } @@ -4109,6 +4172,8 @@ AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid, overrideStack = list_delete_first(overrideStack); list_free(entry->searchPath); pfree(entry); + /* Always bump generation --- see note in recomputeNamespacePath */ + activePathGeneration++; } /* Activate the next level down. */ @@ -4118,6 +4183,12 @@ AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid, activeSearchPath = entry->searchPath; activeCreationNamespace = entry->creationNamespace; activeTempCreationPending = false; /* XXX is this OK? */ + + /* + * It's probably unnecessary to bump generation here, but this should + * not be a performance-critical case, so better to be over-cautious. + */ + activePathGeneration++; } else { @@ -4125,6 +4196,12 @@ AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid, activeSearchPath = baseSearchPath; activeCreationNamespace = baseCreationNamespace; activeTempCreationPending = baseTempCreationPending; + + /* + * If we popped an override stack entry, then we already bumped the + * generation above. If we did not, then the above assignments did + * nothing and we need not bump the generation. + */ } } @@ -4264,6 +4341,7 @@ InitializeSearchPath(void) activeSearchPath = baseSearchPath; activeCreationNamespace = baseCreationNamespace; activeTempCreationPending = baseTempCreationPending; + activePathGeneration++; /* pro forma */ } else { |
