Skip to content

Commit c7f0275

Browse files
committed
Fix some inappropriately-disallowed uses of ALTER ROLE/DATABASE SET.
Most GUC check hooks that inspect database state have special checks that prevent them from throwing hard errors for state-dependent issues when source == PGC_S_TEST. This allows, for example, "ALTER DATABASE d SET default_text_search_config = foo" when the "foo" configuration hasn't been created yet. Without this, we have problems during dump/reload or pg_upgrade, because pg_dump has no idea about possible dependencies of GUC values and can't ensure a safe restore ordering. However, check_role() and check_session_authorization() hadn't gotten the memo about that, and would throw hard errors anyway. It's not entirely clear what is the use-case for "ALTER ROLE x SET role = y", but we've now heard two independent complaints about that bollixing an upgrade, so apparently some people are doing it. Hence, fix these two functions to act more like other check hooks with similar needs. (But I did not change their insistence on being inside a transaction, as it's still not apparent that setting either GUC from the configuration file would be wise.) Also fix check_temp_buffers, which had a different form of the disease of making state-dependent checks without any exception for PGC_S_TEST. A cursory survey of other GUC check hooks did not find any more issues of this ilk. (There are a lot of interdependencies among PGC_POSTMASTER and PGC_SIGHUP GUCs, which may be a bad idea, but they're not relevant to the immediate concern because they can't be set via ALTER ROLE/DATABASE.) Per reports from Charlie Hornsby and Nathan Bossart. Back-patch to all supported branches. Discussion: https://postgr.es/m/HE1P189MB0523B31598B0C772C908088DB7709@HE1P189MB0523.EURP189.PROD.OUTLOOK.COM Discussion: https://postgr.es/m/20160711223641.1426.86096@wrigleys.postgresql.org
1 parent 22f2a98 commit c7f0275

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

src/backend/commands/variable.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,17 @@ check_session_authorization(char **newval, void **extra, GucSource source)
819819
roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(*newval));
820820
if (!HeapTupleIsValid(roleTup))
821821
{
822+
/*
823+
* When source == PGC_S_TEST, we don't throw a hard error for a
824+
* nonexistent user name, only a NOTICE. See comments in guc.h.
825+
*/
826+
if (source == PGC_S_TEST)
827+
{
828+
ereport(NOTICE,
829+
(errcode(ERRCODE_UNDEFINED_OBJECT),
830+
errmsg("role \"%s\" does not exist", *newval)));
831+
return true;
832+
}
822833
GUC_check_errmsg("role \"%s\" does not exist", *newval);
823834
return false;
824835
}
@@ -887,10 +898,23 @@ check_role(char **newval, void **extra, GucSource source)
887898
return false;
888899
}
889900

901+
/*
902+
* When source == PGC_S_TEST, we don't throw a hard error for a
903+
* nonexistent user name or insufficient privileges, only a NOTICE.
904+
* See comments in guc.h.
905+
*/
906+
890907
/* Look up the username */
891908
roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(*newval));
892909
if (!HeapTupleIsValid(roleTup))
893910
{
911+
if (source == PGC_S_TEST)
912+
{
913+
ereport(NOTICE,
914+
(errcode(ERRCODE_UNDEFINED_OBJECT),
915+
errmsg("role \"%s\" does not exist", *newval)));
916+
return true;
917+
}
894918
GUC_check_errmsg("role \"%s\" does not exist", *newval);
895919
return false;
896920
}
@@ -908,6 +932,14 @@ check_role(char **newval, void **extra, GucSource source)
908932
if (!InitializingParallelWorker &&
909933
!is_member_of_role(GetSessionUserId(), roleid))
910934
{
935+
if (source == PGC_S_TEST)
936+
{
937+
ereport(NOTICE,
938+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
939+
errmsg("permission will be denied to set role \"%s\"",
940+
*newval)));
941+
return true;
942+
}
911943
GUC_check_errcode(ERRCODE_INSUFFICIENT_PRIVILEGE);
912944
GUC_check_errmsg("permission denied to set role \"%s\"",
913945
*newval);

src/backend/utils/misc/guc.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10518,8 +10518,9 @@ check_temp_buffers(int *newval, void **extra, GucSource source)
1051810518
{
1051910519
/*
1052010520
* Once local buffers have been initialized, it's too late to change this.
10521+
* However, if this is only a test call, allow it.
1052110522
*/
10522-
if (NLocBuffer && NLocBuffer != *newval)
10523+
if (source != PGC_S_TEST && NLocBuffer && NLocBuffer != *newval)
1052310524
{
1052410525
GUC_check_errdetail("\"temp_buffers\" cannot be changed after any temporary tables have been accessed in the session.");
1052510526
return false;

0 commit comments

Comments
 (0)