diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2011-10-05 20:44:16 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2011-10-05 20:44:16 -0400 |
commit | ba6f629326be365a3124dc80aa5d303e2b0bf46b (patch) | |
tree | f103794eff5aa9bdfc893e178520a62a826eacab /src/backend/utils/adt/ri_triggers.c | |
parent | 3919ad864d7040361fd4b44719acaa1ec0f87bbd (diff) | |
download | postgresql-ba6f629326be365a3124dc80aa5d303e2b0bf46b.tar.gz postgresql-ba6f629326be365a3124dc80aa5d303e2b0bf46b.zip |
Improve and simplify CREATE EXTENSION's management of GUC variables.
CREATE EXTENSION needs to transiently set search_path, as well as
client_min_messages and log_min_messages. We were doing this by the
expedient of saving the current string value of each variable, doing a
SET LOCAL, and then doing another SET LOCAL with the previous value at
the end of the command. This is a bit expensive though, and it also fails
badly if there is anything funny about the existing search_path value,
as seen in a recent report from Roger Niederland. Fortunately, there's a
much better way, which is to piggyback on the GUC infrastructure previously
developed for functions with SET options. We just open a new GUC nesting
level, do our assignments with GUC_ACTION_SAVE, and then close the nesting
level when done. This automatically restores the prior settings without a
re-parsing pass, so (in principle anyway) there can't be an error. And
guc.c still takes care of cleanup in event of an error abort.
The CREATE EXTENSION code for this was modeled on some much older code in
ri_triggers.c, which I also changed to use the better method, even though
there wasn't really much risk of failure there. Also improve the comments
in guc.c to reflect this additional usage.
Diffstat (limited to 'src/backend/utils/adt/ri_triggers.c')
-rw-r--r-- | src/backend/utils/adt/ri_triggers.c | 20 |
1 files changed, 9 insertions, 11 deletions
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index b913e85b31d..522a540c0c3 100644 --- a/src/backend/utils/adt/ri_triggers.c +++ b/src/backend/utils/adt/ri_triggers.c @@ -2633,7 +2633,7 @@ RI_Initial_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel) RangeTblEntry *fkrte; const char *sep; int i; - int old_work_mem; + int save_nestlevel; char workmembuf[32]; int spi_result; SPIPlanPtr qplan; @@ -2772,14 +2772,16 @@ RI_Initial_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel) * this seems to meet the criteria for being considered a "maintenance" * operation, and accordingly we use maintenance_work_mem. * - * We do the equivalent of "SET LOCAL work_mem" so that transaction abort - * will restore the old value if we lose control due to an error. + * We use the equivalent of a function SET option to allow the setting to + * persist for exactly the duration of the check query. guc.c also takes + * care of undoing the setting on error. */ - old_work_mem = work_mem; + save_nestlevel = NewGUCNestLevel(); + snprintf(workmembuf, sizeof(workmembuf), "%d", maintenance_work_mem); (void) set_config_option("work_mem", workmembuf, PGC_USERSET, PGC_S_SESSION, - GUC_ACTION_LOCAL, true, 0); + GUC_ACTION_SAVE, true, 0); if (SPI_connect() != SPI_OK_CONNECT) elog(ERROR, "SPI_connect failed"); @@ -2862,13 +2864,9 @@ RI_Initial_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel) elog(ERROR, "SPI_finish failed"); /* - * Restore work_mem for the remainder of the current transaction. This is - * another SET LOCAL, so it won't affect the session value. + * Restore work_mem. */ - snprintf(workmembuf, sizeof(workmembuf), "%d", old_work_mem); - (void) set_config_option("work_mem", workmembuf, - PGC_USERSET, PGC_S_SESSION, - GUC_ACTION_LOCAL, true, 0); + AtEOXact_GUC(true, save_nestlevel); return true; } |