126
126
* namespaceUser is the userid the path has been computed for.
127
127
*
128
128
* Note: all data pointed to by these List variables is in TopMemoryContext.
129
+ *
130
+ * activePathGeneration is incremented whenever the effective values of
131
+ * activeSearchPath/activeCreationNamespace/activeTempCreationPending change.
132
+ * This can be used to quickly detect whether any change has happened since
133
+ * a previous examination of the search path state.
129
134
*/
130
135
131
136
/* These variables define the actually active state: */
@@ -138,6 +143,9 @@ static Oid activeCreationNamespace = InvalidOid;
138
143
/* if true, activeCreationNamespace is wrong, it should be temp namespace */
139
144
static bool activeTempCreationPending = false;
140
145
146
+ /* current generation counter; make sure this is never zero */
147
+ static uint64 activePathGeneration = 1 ;
148
+
141
149
/* These variables are the values last derived from namespace_search_path: */
142
150
143
151
static List * baseSearchPath = NIL ;
@@ -3373,6 +3381,7 @@ GetOverrideSearchPath(MemoryContext context)
3373
3381
schemas = list_delete_first (schemas );
3374
3382
}
3375
3383
result -> schemas = schemas ;
3384
+ result -> generation = activePathGeneration ;
3376
3385
3377
3386
MemoryContextSwitchTo (oldcxt );
3378
3387
@@ -3393,12 +3402,18 @@ CopyOverrideSearchPath(OverrideSearchPath *path)
3393
3402
result -> schemas = list_copy (path -> schemas );
3394
3403
result -> addCatalog = path -> addCatalog ;
3395
3404
result -> addTemp = path -> addTemp ;
3405
+ result -> generation = path -> generation ;
3396
3406
3397
3407
return result ;
3398
3408
}
3399
3409
3400
3410
/*
3401
3411
* OverrideSearchPathMatchesCurrent - does path match current setting?
3412
+ *
3413
+ * This is tested over and over in some common code paths, and in the typical
3414
+ * scenario where the active search path seldom changes, it'll always succeed.
3415
+ * We make that case fast by keeping a generation counter that is advanced
3416
+ * whenever the active search path changes.
3402
3417
*/
3403
3418
bool
3404
3419
OverrideSearchPathMatchesCurrent (OverrideSearchPath * path )
@@ -3408,6 +3423,10 @@ OverrideSearchPathMatchesCurrent(OverrideSearchPath *path)
3408
3423
3409
3424
recomputeNamespacePath ();
3410
3425
3426
+ /* Quick out if already known equal to active path. */
3427
+ if (path -> generation == activePathGeneration )
3428
+ return true;
3429
+
3411
3430
/* We scan down the activeSearchPath to see if it matches the input. */
3412
3431
lc = list_head (activeSearchPath );
3413
3432
@@ -3440,6 +3459,13 @@ OverrideSearchPathMatchesCurrent(OverrideSearchPath *path)
3440
3459
}
3441
3460
if (lc )
3442
3461
return false;
3462
+
3463
+ /*
3464
+ * Update path->generation so that future tests will return quickly, so
3465
+ * long as the active search path doesn't change.
3466
+ */
3467
+ path -> generation = activePathGeneration ;
3468
+
3443
3469
return true;
3444
3470
}
3445
3471
@@ -3510,6 +3536,14 @@ PushOverrideSearchPath(OverrideSearchPath *newpath)
3510
3536
activeCreationNamespace = entry -> creationNamespace ;
3511
3537
activeTempCreationPending = false; /* XXX is this OK? */
3512
3538
3539
+ /*
3540
+ * We always increment activePathGeneration when pushing/popping an
3541
+ * override path. In current usage, these actions always change the
3542
+ * effective path state, so there's no value in checking to see if it
3543
+ * didn't change.
3544
+ */
3545
+ activePathGeneration ++ ;
3546
+
3513
3547
MemoryContextSwitchTo (oldcxt );
3514
3548
}
3515
3549
@@ -3551,6 +3585,9 @@ PopOverrideSearchPath(void)
3551
3585
activeCreationNamespace = baseCreationNamespace ;
3552
3586
activeTempCreationPending = baseTempCreationPending ;
3553
3587
}
3588
+
3589
+ /* As above, the generation always increments. */
3590
+ activePathGeneration ++ ;
3554
3591
}
3555
3592
3556
3593
@@ -3707,6 +3744,7 @@ recomputeNamespacePath(void)
3707
3744
ListCell * l ;
3708
3745
bool temp_missing ;
3709
3746
Oid firstNS ;
3747
+ bool pathChanged ;
3710
3748
MemoryContext oldcxt ;
3711
3749
3712
3750
/* Do nothing if an override search spec is active. */
@@ -3814,18 +3852,31 @@ recomputeNamespacePath(void)
3814
3852
oidlist = lcons_oid (myTempNamespace , oidlist );
3815
3853
3816
3854
/*
3817
- * Now that we've successfully built the new list of namespace OIDs, save
3818
- * it in permanent storage.
3855
+ * We want to detect the case where the effective value of the base search
3856
+ * path variables didn't change. As long as we're doing so, we can avoid
3857
+ * copying the OID list unncessarily.
3819
3858
*/
3820
- oldcxt = MemoryContextSwitchTo (TopMemoryContext );
3821
- newpath = list_copy (oidlist );
3822
- MemoryContextSwitchTo (oldcxt );
3859
+ if (baseCreationNamespace == firstNS &&
3860
+ baseTempCreationPending == temp_missing &&
3861
+ equal (oidlist , baseSearchPath ))
3862
+ {
3863
+ pathChanged = false;
3864
+ }
3865
+ else
3866
+ {
3867
+ pathChanged = true;
3868
+
3869
+ /* Must save OID list in permanent storage. */
3870
+ oldcxt = MemoryContextSwitchTo (TopMemoryContext );
3871
+ newpath = list_copy (oidlist );
3872
+ MemoryContextSwitchTo (oldcxt );
3823
3873
3824
- /* Now safe to assign to state variables. */
3825
- list_free (baseSearchPath );
3826
- baseSearchPath = newpath ;
3827
- baseCreationNamespace = firstNS ;
3828
- baseTempCreationPending = temp_missing ;
3874
+ /* Now safe to assign to state variables. */
3875
+ list_free (baseSearchPath );
3876
+ baseSearchPath = newpath ;
3877
+ baseCreationNamespace = firstNS ;
3878
+ baseTempCreationPending = temp_missing ;
3879
+ }
3829
3880
3830
3881
/* Mark the path valid. */
3831
3882
baseSearchPathValid = true;
@@ -3836,6 +3887,16 @@ recomputeNamespacePath(void)
3836
3887
activeCreationNamespace = baseCreationNamespace ;
3837
3888
activeTempCreationPending = baseTempCreationPending ;
3838
3889
3890
+ /*
3891
+ * Bump the generation only if something actually changed. (Notice that
3892
+ * what we compared to was the old state of the base path variables; so
3893
+ * this does not deal with the situation where we have just popped an
3894
+ * override path and restored the prior state of the base path. Instead
3895
+ * we rely on the override-popping logic to have bumped the generation.)
3896
+ */
3897
+ if (pathChanged )
3898
+ activePathGeneration ++ ;
3899
+
3839
3900
/* Clean up. */
3840
3901
pfree (rawname );
3841
3902
list_free (namelist );
@@ -4054,6 +4115,8 @@ AtEOXact_Namespace(bool isCommit, bool parallel)
4054
4115
activeSearchPath = baseSearchPath ;
4055
4116
activeCreationNamespace = baseCreationNamespace ;
4056
4117
activeTempCreationPending = baseTempCreationPending ;
4118
+ /* Always bump generation --- see note in recomputeNamespacePath */
4119
+ activePathGeneration ++ ;
4057
4120
}
4058
4121
}
4059
4122
@@ -4109,6 +4172,8 @@ AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid,
4109
4172
overrideStack = list_delete_first (overrideStack );
4110
4173
list_free (entry -> searchPath );
4111
4174
pfree (entry );
4175
+ /* Always bump generation --- see note in recomputeNamespacePath */
4176
+ activePathGeneration ++ ;
4112
4177
}
4113
4178
4114
4179
/* Activate the next level down. */
@@ -4118,13 +4183,25 @@ AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid,
4118
4183
activeSearchPath = entry -> searchPath ;
4119
4184
activeCreationNamespace = entry -> creationNamespace ;
4120
4185
activeTempCreationPending = false; /* XXX is this OK? */
4186
+
4187
+ /*
4188
+ * It's probably unnecessary to bump generation here, but this should
4189
+ * not be a performance-critical case, so better to be over-cautious.
4190
+ */
4191
+ activePathGeneration ++ ;
4121
4192
}
4122
4193
else
4123
4194
{
4124
4195
/* If not baseSearchPathValid, this is useless but harmless */
4125
4196
activeSearchPath = baseSearchPath ;
4126
4197
activeCreationNamespace = baseCreationNamespace ;
4127
4198
activeTempCreationPending = baseTempCreationPending ;
4199
+
4200
+ /*
4201
+ * If we popped an override stack entry, then we already bumped the
4202
+ * generation above. If we did not, then the above assignments did
4203
+ * nothing and we need not bump the generation.
4204
+ */
4128
4205
}
4129
4206
}
4130
4207
@@ -4264,6 +4341,7 @@ InitializeSearchPath(void)
4264
4341
activeSearchPath = baseSearchPath ;
4265
4342
activeCreationNamespace = baseCreationNamespace ;
4266
4343
activeTempCreationPending = baseTempCreationPending ;
4344
+ activePathGeneration ++ ; /* pro forma */
4267
4345
}
4268
4346
else
4269
4347
{
0 commit comments