How to get permission to change run-time parameter? - postgresql

In this wonderful answer is proposed GUC-pattern to use run-time parameters to detect current user inside trigger (as one solution). It seemed to suit to me too. But problem is: when I declare the variable in postgresql.conf it is usable inside trigger and I can access it from queries, but can't change it:
# SET rkdb.current_user = 'xyzaaa';
ERROR: syntax error at or near "current_user"
LINE 1: SET rkdb.current_user = 'xyzaaa';
The error message is misleading, so I did not dig it a while, but now it seems this user (database owner) has no permissions to change params set in global configuration.
I can set any other params:
# SET jumala.kama = 24;
SET
And read it back:
# SHOW jumala.kama;
jumala.kama
-------------
24
(1 row)
I can't SHOW globally set params:
# SHOW rkdb.current_user;
ERROR: syntax error at or near "current_user"
LINE 1: SHOW rkdb.current_user;
^
but I can reach it with current_setting() function:
# select current_setting('rkdb.current_user');
current_setting
-----------------
www
(1 row)
So my guess is, my database owner does not have permissions to access this param. How could I:
set needed permissions?
or even better
set run-time params with database owner rights?

current_user is an SQL standard function, so your use of that name confuses the parser.
Either use a different name or surround it with double quotes like this:
rkdb."current_user"

Related

Grafana (V7) adding variable in table name

I need to be able to use variables in table names - I basically have the same set of tables used for different types of data, so I would like to just have one dashboard and swapping between all types instead of always having to set up multiple identical dashboards.
My query is something like:
select * from table_$variable_name;
Where my list of possible variable is something like cat, dog, bird
I can seem to make this work, if I only put the variable as shown above I get the following error
Error 1146: Table 'table_$variable_name' doesn't exist
If I enclose it in curly brackets, I get this error instead.
Error 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '{bird}' at line 1
(i.e. with the selected variable actually being visible this time)
I'm not sure if the issue is having underscores in the table names, I tried putting underscores around my variables too to check and I had no luck with that.
Another thing I tried was gradually adding on to the table name, so e.g.
select * from table_$variable;
Still returns an error, but I can see the table name starting to form correctly
Error 1146: Table 'table_bird_' doesn't exist
However, as soon as I add another underscore, the variable is not picked up abymore
```Error 1146: Table 'table_$variable_' doesn't exist``
I'm sure it's something silly I am missing in the syntax of the query - anyone has any suggestions?
Using this https://grafana.com/docs/grafana/latest/variables/templates-and-variables/ for reference
As #arturomp suggests, use
${var:raw}
At least in my case, this was the solution that worked.
I found double square brackets work. e.g.
Rather than
select * from table_$variable_name;
use
select * from table_[[variable_name]];

How to unset (remove,not reset) a custom config parameter?

I am using set_config to set some context on the session (i.e user context).
Once I set the context for a parameter - I can't seem to get rid of it. RESET/SET param TO DEFAULT will empty the value but not remove it altogether.
select current_setting('my.test1'); -- SQL Error [42704]: ERROR: unrecognized configuration parameter "my.test1"
select set_config('my.test1','123',false);
select current_setting('my.test1'); -- returns 123
set my.test1 to default; --same as reset my.test1
select current_setting('my.test1'); --returns an empty string rather than an exception
How to remove it (raise exception again) ?
I am catching 42704 but it won't be thrown if I just "reset" it.
p.s I assume pg_reload_conf might help - but it seems too aggressive for this simple task.
Thanks.
The answer is that you cannot (in postgres 10), if you are in the same session.
Those empty parameters ONLY go away if you exit the session and open a new session. pg_reload_conf() has no effect on the custom variables that have been set in a session, or local to a transaction, and doesn't work to remove the parameter. They just stay as '' ... empty string.
For me this is a very legitimate question and issue also ...
i have been finding the same behaviour with custom ( ie name_one.name_two ) configuration parameters, whilst i've been developing a configuration setting wrapper to overlay into individual schemas.
Once the parameter has been set locally with eg set_config ( _name_ , _value_ , TRUE ) OR at session level with set_config ( _name_ , _value_ , FALSE) ... it is not removed if set to NULL or UNSET or to DEFAULT ... there is no way around this i have found, after testing and testing and questioning my own perception of my slightly nested functions and scoping ... and so my only answer has been to alter one of my pure SQL language functions to PLPGSQL and make a test for the particlular parameter that i was relying on as being not existing, because my call that allows missing_ok : current_setting ( '_pre._global_int_' , TRUE )does not return NULL if at some point earlier in any transaction in the session it has been set locally or not locally !!!
It had been frustrating me also, and i was very happy to find that this question had already been asked, and so here i give the answer :
it cannot be done in the same session in PG 10
( i have not tried it yet in 11 or 12 or 13 )
UPDATE :
i just found this answer, https://stackoverflow.com/a/50929568/14653862, of Laurenz Albe, which also says that in the same session you cannot

SQL variables and the IF statement

I am using T-SQL in SQLCMD mode in SSMS to run various subfile from one file, and the principle file (princ.sql) is where I need to declared and set a variable #MyInteger and run a subfile:
DECLARE #MyInteger INT
SET #MyInteger = 20
:setvar path "your absolute file path here"
:r $(path)\"query.sql"
:r $(path)\"uses Myingteger too.sql"
This works fine; as a minimal example, consider query.sql and 'uses MyInteger too.sql' to have the same one line
SELECT #MyInteger
and i do get back two instances of 20.
My trouble is that I would like to be able to run query.sql on its own using a locally defined variable #SubMyInteger.
My ideal situation for query.sql is
IF #MyInteger is declared
SET #SubMyInteger = #MyInteger
ELSE
SET #SubMyInteger = 90
SELECT #SubMyInteger
Then when I run query.sql, #MyInteger would not have been declared, so #SubMyInteger would be assigned 90, and 90 would be returned. I would also get back two 20s as before if i ran princ.sql
For the IF statement, I have so far tried two things:
IF OBJECT_ID('#MyInteger') IS NOT NULL
and
IF #MyInteger IS NOT NULL
I get the error
Must declare scalar variable "#MyInteger".
If I try declaring #MyInteger and then run princ.sql, I get the error
The variable '#MyInteger' has already been declared.
even if the declare statement is conditioned with an IF.
Is there a way to achieve what I want here?
Thanks

How can I turnoff case sensitive matching from Vertica ? Either Globally or session wise

Can I turn case-sensitive data handling from Vertica off session wise . I want it to be dependent on user who may either want to keep it case-sensitive or otherwise !
Also Is there any key to be modified while logging in to mark the session on for Unicode data handling ?
There are indeed ways. I did not test them fully, so there might be corner cases I am not aware of. The keyword you are looking for is collation. You specifically want to update the colstrength keyword and you want a value of 1 I believe (case and accents are ignored).
You can do it in a few ways:
vsql-only : \locale en_US#colstrength=1
from anywhere including via ODBC/JDBC statements: SET LOCALE TO 'en_US#colstrength=1';
by overriding the Locale value in your DSN (not tested) usually in /etc/odbc.ini for odbc
To show the effect, here is an example, first with the default, then after changing the locale:
\locale
en_US#collation=binary
select 'me' = 'ME';
?column?
----------
f
(1 row)
SET LOCALE TO 'en_US#colstrength=1';
\locale
en_US#colstrength=1
select 'me' = 'ME';
?column?
----------
t
(1 row)
I am pretty sure there is more to it, but this should get you started.

Setting application_name on Postgres/SQLAlchemy

Looking at the output of select * from pg_stat_activity;, I see a column called application_name, described here.
I see psql sets this value correctly (to psql...), but my application code (psycopg2/SQLAlchemy) leaves it blank.
I'd like to set this to something useful, like web.1, web.2, etc, so I could later on correlate what I see in pg_stat_activity with what I see in my application logs.
I couldn't find how to set this field using SQLAlchemy (and if push comes to shove - even with raw sql; I'm using PostgresSQL 9.1.7 on Heroku, if that matters).
Am I missing something obvious?
the answer to this is a combination of:
http://initd.org/psycopg/docs/module.html#psycopg2.connect
Any other connection parameter supported by the client library/server can be passed either in the connection string or as keywords. The PostgreSQL documentation contains the complete list of the supported parameters. Also note that the same parameters can be passed to the client library using environment variables.
where the variable we need is:
http://www.postgresql.org/docs/current/static/runtime-config-logging.html#GUC-APPLICATION-NAME
The application_name can be any string of less than NAMEDATALEN characters (64 characters in a standard build). It is typically set by an application upon connection to the server. The name will be displayed in the pg_stat_activity view and included in CSV log entries. It can also be included in regular log entries via the log_line_prefix parameter. Only printable ASCII characters may be used in the application_name value. Other characters will be replaced with question marks (?).
combined with :
http://docs.sqlalchemy.org/en/rel_0_8/core/engines.html#custom-dbapi-args
String-based arguments can be passed directly from the URL string as query arguments: (example...) create_engine() also takes an argument connect_args which is an additional dictionary that will be passed to connect(). This can be used when arguments of a type other than string are required, and SQLAlchemy’s database connector has no type conversion logic present for that parameter
from that we get:
e = create_engine("postgresql://scott:tiger#localhost/test?application_name=myapp")
or:
e = create_engine("postgresql://scott:tiger#localhost/test",
connect_args={"application_name":"myapp"})
If you're using asyncpg driver, you should use
conn = await asyncpg.connect(server_settings={'application_name': 'foo'})
src - https://github.com/MagicStack/asyncpg/issues/204#issuecomment-333917251