LCOV - code coverage report
Current view: top level - src/backend/utils/misc - superuser.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 100.0 % 21 21
Test Date: 2026-03-03 04:14:52 Functions: 100.0 % 3 3
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * superuser.c
       4              :  *    The superuser() function.  Determines if user has superuser privilege.
       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_authid.rolsuper directly, so that the escape hatch built in for
       9              :  * the single-user case works.
      10              :  *
      11              :  *
      12              :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
      13              :  * Portions Copyright (c) 1994, Regents of the University of California
      14              :  *
      15              :  *
      16              :  * IDENTIFICATION
      17              :  *    src/backend/utils/misc/superuser.c
      18              :  *
      19              :  *-------------------------------------------------------------------------
      20              :  */
      21              : #include "postgres.h"
      22              : 
      23              : #include "access/htup_details.h"
      24              : #include "catalog/pg_authid.h"
      25              : #include "miscadmin.h"
      26              : #include "utils/inval.h"
      27              : #include "utils/syscache.h"
      28              : 
      29              : /*
      30              :  * In common cases the same roleid (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 roleid.  The cache can be flushed
      33              :  * at need by watching for cache update events on pg_authid.
      34              :  */
      35              : static Oid  last_roleid = InvalidOid;   /* InvalidOid == cache not valid */
      36              : static bool last_roleid_is_super = false;
      37              : static bool roleid_callback_registered = false;
      38              : 
      39              : static void RoleidCallback(Datum arg, SysCacheIdentifier cacheid,
      40              :                            uint32 hashvalue);
      41              : 
      42              : 
      43              : /*
      44              :  * The Postgres user running this command has Postgres superuser privileges
      45              :  */
      46              : bool
      47        65546 : superuser(void)
      48              : {
      49        65546 :     return superuser_arg(GetUserId());
      50              : }
      51              : 
      52              : 
      53              : /*
      54              :  * The specified role has Postgres superuser privileges
      55              :  */
      56              : bool
      57      3926483 : superuser_arg(Oid roleid)
      58              : {
      59              :     bool        result;
      60              :     HeapTuple   rtup;
      61              : 
      62              :     /* Quick out for cache hit */
      63      3926483 :     if (OidIsValid(last_roleid) && last_roleid == roleid)
      64      3706751 :         return last_roleid_is_super;
      65              : 
      66              :     /* Special escape path in case you deleted all your users. */
      67       219732 :     if (!IsUnderPostmaster && roleid == BOOTSTRAP_SUPERUSERID)
      68       185747 :         return true;
      69              : 
      70              :     /* OK, look up the information in pg_authid */
      71        33985 :     rtup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
      72        33985 :     if (HeapTupleIsValid(rtup))
      73              :     {
      74        33979 :         result = ((Form_pg_authid) GETSTRUCT(rtup))->rolsuper;
      75        33979 :         ReleaseSysCache(rtup);
      76              :     }
      77              :     else
      78              :     {
      79              :         /* Report "not superuser" for invalid roleids */
      80            6 :         result = false;
      81              :     }
      82              : 
      83              :     /* If first time through, set up callback for cache flushes */
      84        33985 :     if (!roleid_callback_registered)
      85              :     {
      86        16956 :         CacheRegisterSyscacheCallback(AUTHOID,
      87              :                                       RoleidCallback,
      88              :                                       (Datum) 0);
      89        16956 :         roleid_callback_registered = true;
      90              :     }
      91              : 
      92              :     /* Cache the result for next time */
      93        33985 :     last_roleid = roleid;
      94        33985 :     last_roleid_is_super = result;
      95              : 
      96        33985 :     return result;
      97              : }
      98              : 
      99              : /*
     100              :  * RoleidCallback
     101              :  *      Syscache inval callback function
     102              :  */
     103              : static void
     104        15147 : RoleidCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
     105              : {
     106              :     /* Invalidate our local cache in case role's superuserness changed */
     107        15147 :     last_roleid = InvalidOid;
     108        15147 : }
        

Generated by: LCOV version 2.0-1