22 *
33 * superuser.c
44 * The superuser() function. Determines if user has superuser privilege.
5- * Also, a function to check for the owner (datdba) of a database.
5+ *
6+ * All code should use either of these two functions to find out
7+ * whether a given user is a superuser, rather than examining
8+ * pg_shadow.usesuper directly, so that the escape hatch built in for
9+ * the single-user case works.
610 *
711 *
812 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
913 * Portions Copyright (c) 1994, Regents of the University of California
1014 *
1115 *
1216 * IDENTIFICATION
13- * $PostgreSQL: pgsql/src/backend/utils/misc/superuser.c,v 1.30 2004/12/31 22:02:45 pgsql Exp $
17+ * $PostgreSQL: pgsql/src/backend/utils/misc/superuser.c,v 1.31 2005/05/29 20:38:06 tgl Exp $
1418 *
1519 *-------------------------------------------------------------------------
1620 */
1721#include "postgres.h"
1822
19- #include "access/heapam.h"
2023#include "catalog/pg_shadow.h"
21- #include "commands/dbcommands .h"
24+ #include "utils/inval .h"
2225#include "utils/syscache.h"
2326#include "miscadmin.h"
2427
2528
29+ /*
30+ * In common cases the same userid (ie, the session or current ID) will
31+ * be queried repeatedly. So we maintain a simple one-entry cache for
32+ * the status of the last requested userid. The cache can be flushed
33+ * at need by watching for cache update events on pg_shadow.
34+ */
35+ static AclId last_userid = 0 ; /* 0 == cache not valid */
36+ static bool last_userid_is_super = false;
37+ static bool userid_callback_registered = false;
38+
39+ static void UseridCallback (Datum arg , Oid relid );
40+
41+
2642/*
2743 * The Postgres user running this command has Postgres superuser privileges
28- *
29- * All code should use either of these two functions to find out
30- * whether a given user is a superuser, rather than evaluating
31- * pg_shadow.usesuper directly, so that the escape hatch built in for
32- * the single-user case works.
3344 */
3445bool
3546superuser (void )
@@ -38,16 +49,24 @@ superuser(void)
3849}
3950
4051
52+ /*
53+ * The specified userid has Postgres superuser privileges
54+ */
4155bool
4256superuser_arg (AclId userid )
4357{
44- bool result = false ;
58+ bool result ;
4559 HeapTuple utup ;
4660
61+ /* Quick out for cache hit */
62+ if (AclIdIsValid (last_userid ) && last_userid == userid )
63+ return last_userid_is_super ;
64+
4765 /* Special escape path in case you deleted all your users. */
4866 if (!IsUnderPostmaster && userid == BOOTSTRAP_USESYSID )
4967 return true;
5068
69+ /* OK, look up the information in pg_shadow */
5170 utup = SearchSysCache (SHADOWSYSID ,
5271 Int32GetDatum (userid ),
5372 0 , 0 , 0 );
@@ -56,5 +75,35 @@ superuser_arg(AclId userid)
5675 result = ((Form_pg_shadow ) GETSTRUCT (utup ))-> usesuper ;
5776 ReleaseSysCache (utup );
5877 }
78+ else
79+ {
80+ /* Report "not superuser" for invalid userids */
81+ result = false;
82+ }
83+
84+ /* If first time through, set up callback for cache flushes */
85+ if (!userid_callback_registered )
86+ {
87+ CacheRegisterSyscacheCallback (SHADOWSYSID ,
88+ UseridCallback ,
89+ (Datum ) 0 );
90+ userid_callback_registered = true;
91+ }
92+
93+ /* Cache the result for next time */
94+ last_userid = userid ;
95+ last_userid_is_super = result ;
96+
5997 return result ;
6098}
99+
100+ /*
101+ * UseridCallback
102+ * Syscache inval callback function
103+ */
104+ static void
105+ UseridCallback (Datum arg , Oid relid )
106+ {
107+ /* Invalidate our local cache in case user's superuserness changed */
108+ last_userid = 0 ;
109+ }
0 commit comments