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

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) || ';')

Related

SQL0628N with MODIFIES SQL DATA when creating a table function

I am trying to encapsulate the functionality from this sample code here, inside a Table-Function.
I can run the sample alone without any problem.
But when I create a table function, just with a single call to OPEN_CURSOR , I receive SQL0577N
CREATE FUNCTION ROW_CHECKSUM
( IN sSchema VARCHAR(128) ,
IN sTable VARCHAR(128) ,
IN sColumnList VARCHAR(1024) ,
IN sWhere VARCHAR(1023),
IN iRows INTEGER
)
RETURNS TABLE (ROW_PK_VALUES VARCHAR(3000), CHECKSUM INTEGER )
LANGUAGE SQL
SPECIFIC ROW_CHECKSUM
--NO EXTERNAL ACTION
--MODIFIES SQL DATA
--NOT DETERMINISTIC
BEGIN
DECLARE iCheckSum INTEGER ;
DECLARE sKyes VARCHAR(1024) ;
DECLARE iCursor INTEGER;
DECLARE sQuery VARCHAR(32000) ;
SET sQuery = 'SELECT ' || sColumnList || ' FROM "' || sSchema || '"."' || sTable || '" WHERE ' || sWhere || ' FETCH FIRST ' || TO_CHAR(iRows) || ' ONLY' ;
CALL DBMS_SQL.OPEN_CURSOR(iCursor);
--CALL DBMS_SQL.PARSE(iCursor, sQuery, DBMS_SQL.native) ;
--PIPE (sKeys, iCheckSum) ;
--PIPE ('abcd', 1234) ;
RETURN ;
END
----
SQL0577N User defined routine "DB2ADMIN.ROW_CHECKSUM" (specific name "")
attempted to modify data but was not defined as MODIFIES SQL DATA. LINE
NUMBER=33. SQLSTATE=38002
it seems, OPEN_CURSOR demands to have the MODIFY SQL DATA specified.. ok.. let's go!
But, when I specify it, then I get the following error, instead:
SQL0628N Multiple or conflicting keywords involving the "MODIFIES SQL DATA"
clause are present. LINE NUMBER=33. SQLSTATE=42613
The error details for -628 error is too generic and does not help me to determine what's really going on here.
I need to perform dynamic SQL queries using DBMS_SQL module, and return the result set using PIPE , like this other sample here.
I have been reading spread documentations the entire day.. and so far was not able to determine exactly what rule I am violating.
Also, found some inconsistencies on documentation, which I don't understand:
This page, says:
SQL table functions cannot contain compiled compound statements.
While, the Rules from RETURN statement says the opposite, and matches with PIPE sample code:
In an SQL table function using a compound SQL (compiled) statement, an expression, NULL, or fullselectcannot be specified. Rows are returned from the function using the PIPE statement and the RETURN statement is required as the last statement to execute when the function exits (SQLSTATE 2F005).
Appreciate any help!
Look at the note about the MODIFIES SQL DATA in the CREATE FUNCTION statement description:
4 Valid only for compiled scalar function definition and an inlined
table function definition.
But you can't use PIPE in an inlined function.
So, you want to use different functionalities, which can't be used together.
The inconsistency you found in the documentation is not related to you problem.

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.

Use CREATE USER in Postgres by passing password in variable

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.

cursor.query( 'select * from %s;', ('thistable',) ) throws syntax error 1064: ...near ' 'thistable' ' at

MySQLdb: cursor.query( 'select * from %s;', ('thistable',) )
should end up as: 'select * from thistable'
actually ends up as: "select * from 'thistable' "
the db natually throws syntax error: ...near ' 'thistable' ' at ...
It behaves as though the data converter is including the string's quotes as part of the string, ie the string is " 'thistable' " instead of 'thistable'. Any and all help with this is deeply appreciated. One thing I did notice in my questing is that the script's charset is utf8, while the db server and db are latin1. Could this be my problem?
OS: os X Sierra
python: 3.6
MySQL: 5.3.6
mysql-connector-c: 6.1.11
There's a difference between building dynamic SQL and building parameterized queries.
In general, parameterized queries let you plug in values for comparison/input, but not database objects. So, your application code assumes that %s is a quoted literal, not an database object.
If you need to dynamically add in database objects (tables, columns, procedure names, etc.), you will probably need to build the query string first, with placeholders (like %s) for actual parameters you need to pass in.
In this case, ypercubeᵀᴹ's suggestion to simply use the string 'select * from thistable' directly. If you needed to run the same query against multiple tables, loop through the list of table, building the string like:
queryString = 'SELECT * FROM ' + currTable

postgres coldfusion concatenation of string inside cfquery tag

<cfquery name="LOCAL.qrySelEvents" datasource="#variables.datasourceSettings.getDatasourceName()#" result="LOCAL.qryData" >
SELECT evt_id,
acnt_dba_name,
form_id,
'#application.portals.data[request.applicationName].profileRootPath#form/index.cfm'
|| CHAR(63)
|| 'PKformID= '
|| #preserveSingleQuotes(LOCAL.formIdSql)# AS primaryFormURL,
FROM events
</cfquery>
I have to concat #application.portals.data[request.applicationName].profileRootPath#form/index.cfm with char(32) and PKformID= ' || #preserveSingleQuotes(LOCAL.formIdSql)#. I have used the || operator of postgres. But it is giving me an error:
ERROR: syntax error at or near "||"
Can you please help me in this?
The last line of your select clause has a comma at the end.
OK, as well as the error message, if you have ROBUST EXCEPTION HANDLING switched on (it's in CFAdmin), you should get back the SQL that CF was passing to the server. This should show you where the syntax error is in your SQL. You should also always post this info in your question, so even if you can't see the problem, someone else might be able to.
Now I suspect it's because this:
#preserveSingleQuotes(LOCAL.formIdSql)#
needs to be treated as a string (which it is), in which case you'll need to quote it for the DB to see it as a string. IE:
'#preserveSingleQuotes(LOCAL.formIdSql)#'
Given there is no DB-centric references in that whole value:
`'#application.portals.data[request.applicationName].profileRootPath#form/index.cfm' || CHAR(63) || 'PKformID= ' || '#preserveSingleQuotes(LOCAL.formIdSql)#'`
I question why you need to include it in your SELECT query. You're basically just passing the value to the SQL server, and just getting it back again afterwards. So I suspect something is amiss here. What are you actually trying to do here?
Ya finally got the answer of this , CHAR(63) is creating problem in this as in Sql-server CHAR is a function which gives Character from ASCII and in postgresql CHR() function is available in order to give character from ASCII. So , new Query is :
<cfquery name="LOCAL.qrySelEvents" datasource="#variables.datasourceSettings.getDatasourceName()#" result="LOCAL.qryData" >
SELECT evt_id,
acnt_dba_name,
form_id,
'#application.portals.data[request.applicationName].profileRootPath#form/index.cfm'
|| CHR(63)
|| 'PKformID= '
|| #preserveSingleQuotes(LOCAL.formIdSql)# AS primaryFormURL
FROM events
</cfquery>
Thanks for all your support.