HiveBrain v1.2.0
Get Started
← Back to all entries
patternsqlModerate

Fastest way to get current user's OID in Postgres?

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
postgresoiduserwaygetfastestcurrent

Problem

I am thinking of storing the user's OID in the "owner" column of a table, so I don't have to do anything if they change their username.

I understand one can use pg_has_role() with OIDs, so that's good.

Is there a fast and easy way to get the current user's OID without just matching it against one of the system tables?

Solution

The fastest way I know of is a lookup in the system catalog view pg_roles:

SELECT * FROM pg_roles WHERE rolname = 'postgres';


Strictly speaking, it would be even slightly faster to use the underlying table pg_authid, but access to it is restricted to superusers for good reasons.

There is no object identifier type like there is for tables or types, which would allow a simple cast like 'mytable'::regclass.

OIDs are not stable across a dump / restore cycle. So, the OID is no good for the use case!

In some databases I have a separate login table with a serial primary key that I use for similar purposes. Maintained manually. And functions using it are prepared to occasionally not find a user in this table. A very basic and fast table:

CREATE TABLE users.login (
  login_id serial PRIMARY KEY  -- or even smallserial?
, username text NOT NULL UNIQUE
);


To create new users I use a PL/pgSQL function that creates the new user in the system and enters it into my table at the same time. And I use this login_id in many places. For instance I keep track of who made the last change to a row in most tables. I use this simple function:

CREATE OR REPLACE FUNCTION public.f_login_id()
  RETURNS int
  LANGUAGE sql STABLE AS
$func$
SELECT COALESCE((SELECT login_id FROM users.login
                 WHERE  username = session_user::text), 0::int);
$func$;


No foreign key constraints, to keep things fast and simple. Obviously, I don't need strict referential integrity.

Code Snippets

SELECT * FROM pg_roles WHERE rolname = 'postgres';
CREATE TABLE users.login (
  login_id serial PRIMARY KEY  -- or even smallserial?
, username text NOT NULL UNIQUE
);
CREATE OR REPLACE FUNCTION public.f_login_id()
  RETURNS int
  LANGUAGE sql STABLE AS
$func$
SELECT COALESCE((SELECT login_id FROM users.login
                 WHERE  username = session_user::text), 0::int);
$func$;

Context

StackExchange Database Administrators Q#56481, answer score: 13

Revisions (0)

No revisions yet.