2

I'm trying to set a custom option in a stored procedure, but it is storing the variable name and not contents of the variable.

CREATE OR REPLACE FUNCTION set_user(_user_id bigint, is_local boolean default true) returns void AS $$
BEGIN
  SET my.user_id TO _user_id;
END;
$$ LANGUAGE PLPGSQL;

select set_user(1);
select current_setting('my.user_id');
 current_setting 
-----------------
 _user_id   
(1 row)

I expect current_setting to return 1, not the string value "_user_id".

Kamil Gosciminski
  • 16,547
  • 8
  • 49
  • 72
Krut
  • 4,112
  • 3
  • 34
  • 42
  • There is already a function for this: `set_config()`: http://www.postgresql.org/docs/current/static/functions-admin.html#FUNCTIONS-ADMIN-SET –  Mar 29 '16 at 19:57
  • @a_horse_with_no_name I tried `set_config()` but it only works with text – Krut Mar 29 '16 at 21:05
  • I'm rather certain that custom variables (`my.user_id`) are also stored as text. I can't find a reference for that however –  Mar 29 '16 at 21:13
  • @a_horse_with_no_name http://www.postgresql.org/docs/current/static/config-setting.html It seems logical they would be all text in the actual config file, however I'm using custom options which seem to hold their type – Krut Mar 29 '16 at 21:19
  • `SET my.user_id TO 1;` followed by `show my.user_id;` returns a text column so I would say they do not preserve their type –  Mar 29 '16 at 21:22

1 Answers1

2

First solution

Syntax for SET is:

SET [ SESSION | LOCAL ] configuration_parameter { TO | = } { value |'value' | DEFAULT }

where value is the new value for a given configuration_parameter.

In order to assign a value stored in _user_id variable, you need to generate a dynamic command and then EXECUTE it.

This would be the way to do that:

CREATE OR REPLACE FUNCTION set_user(_user_id bigint, is_local boolean default true) 
RETURNS void 
LANGUAGE PLPGSQL
AS $$
BEGIN
  EXECUTE 'SET my.user_id TO ' || quote_nullable(_user_id);
END;
$$;

Attaching SQL Fiddle link for testing purposes.

Note:

  • quote_nullable() function would return NULL if the input argument is null. It may not be necessary in your case.

Second solution

You could also achieve the same thing with [`set_config()`][4] function as @a_horse_with_no_name noted. Your function would then look like that:
CREATE OR REPLACE FUNCTION set_user(_user_id bigint, is_local boolean default true) 
RETURNS void 
LANGUAGE PLPGSQL
AS $$
BEGIN
  PERFORM set_config('my.user_id', _user_id::TEXT, false);
END;
$$;

Attaching SQL Fiddle link for testing purposes.

Note:

  • You have to explicitly cast the second argument to a varchar type
  • PERFORM is used to evaluate an expression and discard the result since it's not needed
  • You could use quote_nullable() function here as well
Randall
  • 2,859
  • 1
  • 21
  • 24
Kamil Gosciminski
  • 16,547
  • 8
  • 49
  • 72
  • 1
    Another option is to simply use `set_config()`: http://www.postgresql.org/docs/current/static/functions-admin.html#FUNCTIONS-ADMIN-SET –  Mar 29 '16 at 19:58
  • you don't need PL/pgSQL for that. A plain SQL function will be faster. –  Mar 29 '16 at 20:09
  • Are you sure that these statements are available in plain SQL functions? – Kamil Gosciminski Mar 29 '16 at 20:11
  • Absolutely. It's a "normal" SQL function. You can call it anywhere you can write SQL statements, including other SQL functions. –  Mar 29 '16 at 20:13
  • I've tried it myself, and it yields errors at `EXECUTE` and at `PERFORM` respectively for both solutions. I believe they are not available in plain SQL function. – Kamil Gosciminski Mar 29 '16 at 20:44
  • Well `perform` indeed is only available in PL/pgSQL. But can simply put a `select set_config('my.user_id', _user_id::TEXT, false);` into a SQL function. >ou have to change the return type from `void` to `text` though. http://sqlfiddle.com/#!15/a7cde/1 –  Mar 29 '16 at 20:47
  • I agree, just wanted to keep it as it was in OP question (return type). – Kamil Gosciminski Mar 29 '16 at 20:52
  • 1
    `set_config` is ok as long as you are only dealing with text values, then you can drop the `::text` cast and support nulls better, etc. – Krut Mar 29 '16 at 21:15