Use CREATE USER in Postgres by passing password in variable - postgresql

I have the following function in PostgreSQL:
create function test_createuser(username varchar, userpassword varchar) returns void as $$
begin
CREATE USER username WITH PASSWORD userpassword;
end;
$$ language plpgsql;
However this gives the following error:
syntax error at or near "userpassword"
The function compiles if I place instead a literal string as the password, such as 'mypassword'.
Is there a way to call create user and pass the password from a variable?

You'll have to use dynamic SQL:
EXECUTE format('CREATE USER %I PASSWORD %L', username, userpassword);

I still got the same parse error using the EXECUTE method (ERROR: syntax error at or near "2" - Note: the password starts with a "2").
Instead I added string quotation marks when I read the password from the environment variable.
\set psqluser `echo "$PSQL_USER"`
\set psqlpassword `echo "'$PSQL_PASSWORD'"` -- Add the quotations '' for the password already here
CREATE USER :psqluser WITH ENCRYPTED PASSWORD :psqlpassword;
I don't know if it is good practice, but it works.

Related

How to choose column in sql select using variable in Qt

I am writing a function that will take a string variable and work with a column with the name of this variable, but i can't figure out how to write variable in select
I tried this where test is QString variable with value company, but it didnt work like if there was company without variable
QString test = "company";
QSqlQuery password = db->exec("SELECT password FROM '"+test+"'");
Worked with deleted '' of the variable.
QSqlQuery password = db->exec("SELECT password FROM "+test+"");

How to pass 'User Password' as parameter in function?

I'm trying to create users with a Function in Postgres. PostGres does not allow me to set a user's password with a parameter.
I've tried casting the parameter to all kinds of different types. Quoting literal on it. Nothing works.
Code:
CREATE OR REPLACE FUNCTION
userlogic_add_user(user_password text)
ALTER USER user_name WITH user_password;
The error msg I receive is Syntax related. But it has something to do with user_password.
The entire code obviously looks a bit different, but these are the parts of interest.
I guess you can always try executing a dynamic command:
EXECUTE ('ALTER USER ' || quote_ident(user_name) || ' WITH PASSWORD ' || quote_ident(user_password) || ';')

PostgreSQL: Parameter substitution for LISTEN?

Common sense dictates that SQL query strings should never be assembled by hand. Thus, all database interfaces offer parameter substitution, and all users use it, without exceptions.*
I'm using PostgreSQL v10.5, nodejs v8.12.0, node-postgres 7.6.1.
Parameter substitution works as expected for SELECT statements:
> await db.query("select from users where id = 'mic'");
(success, 1 row returned)
> await db.query("select from users where id = $1", ["mic"]);
(success, 1 row returned)
But it doesn't work for LISTEN statements:
> await db.query("listen topicname");
(success)
> await db.query("listen $1", ["topicname"]);
(error: syntax error at or near "$1")
The name of the topic I want to listen to is dynamic. It is coming from semi-trustworthy sources, which should not be user-controllable. But why go against all established best practice and take any chances?
Unfortunately, from my tests I fear that PostgreSQL simply can't do parameter substitution for LISTEN queries.
Is there any solution or workaround for this?
*) This statement may only be true in some utopic future society.
I don't have enough reputation to comment on the answer, but the proposed solution doesn't work for me.
Using %L results in a quoted string, which causes the following error:
ERROR: syntax error at or near "'topic'"
The %I format should be used instead (SQL identifier, this is documented for table and column names, but it also works for the channel name,). You can also use the quote_ident function. See the documentation on creating dynamic queries here.
The following PL/pgSQL function works for us:
CREATE OR REPLACE FUNCTION listenForChannel(
channel_ TEXT
) RETURNS VOID AS $$
BEGIN
EXECUTE format('LISTEN %I', channel_);
END
$$ LANGUAGE PLPGSQL;
You are right that this cannot be done in PostgreSQL.
As a workaround, write a PL/pgSQL function that uses dynamic SQL like this:
EXECUTE format('LISTEN %L', topicname);
The format function escapes strings properly; in this case, the %L format that produces a properly quoted string Literal is the appropriate one.

Can't call Postgresql function which should return text value

I have a little problem when calling a Postgresql function in Delphi with FireDAC.
The Postgresql function has the following definition:
CREATE OR REPLACE FUNCTION public."pgpDecryptMe" (
todecode text
)
RETURNS text AS
$body$
DECLARE
PGPPrivate TEXT;
BEGIN
...
So it expects a "text" value and returns a "text" value.
I can call it with a long text parameter (over 900 character) and it returns the correct value in any sql admin tool without any problems.
select "pgpDecryptMe"('c1c04c030...a378624e6a659a20765') as Decrypt
But calling it in Delphi with the following code:
PGQuery.SQL.Text := 'select "pgpDecryptMe"(:test) as testvalue';
PGQuery.ParamByName('test').AsString := 'c1c04c030...a378624e6a659a20765';
PGQuery.Open();
Gives me the following error message:
[FireDAC][DatS]-2. Object [id] is not found
I googled and searched here but can't find any solution for the problem.
It is probably something very small I can't see :-(
I am working with Delphi XE7 and PostgreSQL 9.3
Ok, now I got it working.
It looks like it needed an additional index field name which doesn't really make sense because it just returned one value...
So it worked when I changed my code to the following:
PGQuery.SQL.Text := 'select "pgpDecryptMe"(:test) as testvalue';
PGQuery.ParamByName('test').AsString := 'c1c04c030...a378624e6a659a20765';
PGQuery.IndexFieldNames := 'testvalue';
PGQuery.Open();

Function argument not interpreted inside body

I am trying to create a PL/pgSQL function in PostgreSQL 9.3.6, but there is weird behavior when using the passed argument inside function body. Here is the 'very simple' function:
CREATE OR REPLACE FUNCTION myschema.test (myarg text) RETURNS text AS $$
DECLARE
entity text;
buffer text;
BEGIN
CREATE ROLE myarg;
RETURN myarg;
END;
$$ LANGUAGE plpgsql;
So, if for instance myarg equals 'test':
A role named 'myarg' is created (WRONG)
'test' is returned (CORRECT)
I searched for hours why this could be and no clue... security parameter? Why is myarg not interpreted for creating roles?
Testing with phpPgAdmin through sql files if this has any impact.
You should use:
EXECUTE FORMAT('CREATE ROLE %I', myarg);
Here you can find an explanation (especially read Craig's answer).
As Erwin stated (thanks), %I is safer than %s. Anyway, myarg should be verified before the function call. Try for example
SELECT myschema.test('something; stupid; here;')