How can I ask user to enter the input in PostgresSQL/plpgsql? - sql

Hi I want to take input from user in my
DO BEGIN and END block...
I tried to use /prompt inside but it doesnt work.
Do we have any other way that we can use it inside function or block in postgres?

Important note: PLpgSQL is server side only language - there is not any possibility do any user interactivity operation. You have to collect input on client side before start of PLpgSQL code, and user input push there as parameters.
DO statement is server side statement, so you cannot do any interactive action there.
DO statement doesn't support parameters so it is not easy push any parameters inside DO statement, but is possible with custom configuration variables:
\prompt 'enter some text: ' psqlvar
\o /dev/null
select set_config('psql.psqlvar', :'psqlvar', false);
\o
do $$
DECLARE var text = current_setting('psql.psqlvar');
BEGIN
RAISE NOTICE 'entered text is: %', var;
END;
$$;
The function set_config is used to moving a content of client variable :psqlvar to server side - session variable psql.psqlvar. The content of this server side variable is taken by function current_setting.
You have to separate in your mind server side and client side content. The DO statement is evaluated on server side. The psql \prompt command is evaluated on client side.

As bad ideas go, asking for user input in a stored procedure is up there with using usernames as session identifiers. This is a really, really bad idea. Yes there are ways in some environmnets to do this. But just because you can does not mean you should. For example I have heard of people using pl/python to make a network connection back to the client computer and ask for more information. However, this is frankly DailyWTF territory. It also assumes a protocol and listener on the client to ask for this request and therefore doesn't work from pgadmin.
Now, DO creates an anonymous function without arguments and immediately executes it. This seems to be where your real problem is.
Your best solution is to just create an actual function with arguments and accept the input there. Then it can be used anywhere. And you can re-use, modify security, etc. This sounds like it is exactly what you need.
Failing that you could preprocess your do block before you send it.
Your best design where you want to reuse PL/PGSQL code with inputs is to use a function (see CREATE FUNCTION) instead of DO (note you can put these in another schema if that is a concern).

Related

Is it possible to split an exit block into multiple enter blocks in Anylogic using a set of parameters that can be optimised?

I want to be able to split activity across a number of sites, but I want that split to be determined by an optimisation experiment so I need a way of splitting activity in the exit and sending it to the respective enter blocks. I'd welcome any advice on how to set up my exit block to do this. I recognise I'll need a variable per option.
I know I can do it with a SelectOut block, but I may need a large number of options and so this doesn't work.
I've added the enter blocks into a collection and I can route agents to a particular enter block, but the optimisation engine can't use agent level parameters.
Create a function f_getEnterBlockToUse that takes as an argument your agent and returns an Enter block (select the return type "Other" and then write Enter in the code field).
Now, you can write any sophisticated code in there yourself to select which block to be chosen.
In the Exit block, you only call the function f_getEnterBlockToUse(agent).take(agent). This will send your agent to your desired enter block

Pentaho PDI unable to use parameter in transformation

Using Pentaho PDI 8.3.0
I am unable to use a parameter in a REST call within a transformation. What I've done is:
Create a transformation and given it a parameter called PAGE_NR with default value 1
Create a job
Call the transformation with parameter PAGE_NR = 1
In the transformation, set up a GET request to a REST API.
In the URL field, setup the call like http://myurl.com/foo/bar?page=${PAGE_NR}
When I call this from either SoapUI or a browser it works but it always breaks when running the job. It does not seem to translate this parameter into the value, but instead passes it exactly like mentioned above.
I need this parameter because of calling the same URL but with different results. I don't know the amount of pages up front but take care of that logic later in said transformation.
Working on Linux btw. I have tried different variations of calling the parameter but nothing seems to work.
With the information given in the comments, I am willing to make an educated guess:
The REST Client step does not perform variable substitution on the URL if it comes from a field in the stream. What you can do is insert a Calculator step before the REST step with the operation "Variable substitution on string A" with your URL field as Field A.
This should give you the desired URL with page number.

parameters FDquery delphi does not work

i have the following delphi code:
FDQuery1.SQL.Clear;
FDQuery1.SQL.Add('SELECT * FROM :Tablename');
FDQuery1.ParamByName('Tablename').AsString := 'tasks';
ShowMessage(FDQuery1.sql.Text);
FDQuery1.Open;
(coppied from this link: http://www.delphigroups.info/2/da/237634.html)
it does not work because the parameter is not filled but stays the same.
does somebody know why it is not filled?
Because you cannot use parameters for table name substitution in SQL commands in general. You are lucky enough here though, FireDAC supports preprocessor macros to parametrize table names in SQL commands. So you can write for example this (note that if you want to see the command as you did in your code, it must be after macro preprocessing, that is e.g. after calling Prepare):
FDQuery1.SQL.Text := 'SELECT * FROM &TableName';
FDQuery1.MacroByName('TableName').AsIdentifier := 'tasks';
FDQuery1.Open;
For details about this kind of macros, see the substitution variables topic.

How to execute SQL Script which may or may not return data?

This is an extension of an old question of mine where the answer wasn't quite what I was asking. What I'm doing is executing SQL Script on an MS SQL Server database. This script may or may not return any recordsets. The problem is that the way that ADO components work, at least to my knowledge, I can only explicitly request one or the other.
If I know a query will return data, I use TADOQuery.Open
If I know a query will not return data, I use TADOConnection.Execute
If I don't know whether query will return data or not... ???
How can I execute any query and read the response to determine whether it has any recordsets or not so I can read that recordset?
What I've tried:
Calling TADOQuery.Open, but raises exception if there's no recordset
Calling TADOQuery.ExecSql, but never returns any data
Calling TADOConnection.Execute, but never returns any data
Using Option 3 and reverting to Option 1 on exceptions, but this is double the work (script files over 38,000 lines) and kinda nasty.
Using TADOCommand.Execute, but keeps raising "Parameter object is improperly defined. Inconsistent or incomplete information was provided" on creating some stored procedures (which otherwise don't happen when using TADOConnection.Execute).
Calling TADOConnection.Execute overload which returns _Recordset, but then the TADOConnection.Errors returns empty (and I depend on this).
Just as some background, the purpose is to implement something like the SQL Query tool in the SQL Server Management Studio. It allows you to execute any SQL script, and if it returns any recordsets, it displays them, otherwise it just displays output messages. The tool I'm working on automatically breaks SQL Script at GO statements, and executes each individual block separately. Some of those blocks might return data, and others might not. It's already obvious that I cannot make this determination prior to execution, so I'm looking for a way to go ahead with the execution and observe the result. TADOConnection.Execute provides some useful information, including the Errors (or output messages).
As of now, the only option I have is to supply an option in the user interface to allow the user to choose which type of execution to use - but this is what I'm trying to eliminate.
EDIT
The TADOCommand.Execute method is the closest to what I want. However, it fails on some bits of script which otherwise work perfectly fine using TADOConnection.Execute. See #5 above in "What I've tried". I almost wrote that as my answer, until I found this error happens on almost everything.
EDIT
After posting my answer below, I then came to learn that the Errors property no longer returns anything when I use this other overload of Execute. See #6 above in "What I've tried".
Calling...
ADOConnection1.Execute('select * from something', cmdText, []);
...does not return anything in ADOConnection1.Errors, whereas...
var
R: Integer;
begin
ADOConnection1.Execute('select * from something', R);
...does return messages in ADOConnection1.Errors, which is what I need, but yet, doesn't return any recordsets.
EDIT: Not the right solution
I discovered my solution finally after digging even deeper. The answer is to use the TADOConnection.Execute() overload which supports returning the recordset:
function TADOConnection.Execute(const CommandText: WideString;
const CommandType: TCommandType = cmdText;
const ExecuteOptions: TExecuteOptions = []): _Recordset;
Then, just assign the resulting _Recordset to the Recordset property of supported dataset components.
var
RS: _Recordset;
begin
RS := ADOConnection1.Execute('select * from something', cmdText, []);
if Assigned(RS) then begin
ADODataset1.Recordset:= RS;
...
end;
end;
The downside is that you cannot use the other overload which supports returning the RowsAffected. Also, nothing is returned in the Errors property of the TADOConnection when using this overload version of Execute, whereas the other one does. But that other doesn't return a recordset.

Protecting against SQL injection in python

I have some code in Python that sets a char(80) value in an sqlite DB.
The string is obtained directly from the user through a text input field and sent back to the server with a POST method in a JSON structure.
On the server side I currently pass the string to a method calling the SQL UPDATE operation.
It works, but I'm aware it is not safe at all.
I expect that the client side is unsafe anyway, so any protection is to be put on the server side. What can I do to secure the UPDATE operation agains SQL injection ?
A function that would "quote" the text so that it can't confuse the SQL parser is what I'm looking for. I expect such function exist but couldn't find it.
Edit:
Here is my current code setting the char field name label:
def setLabel( self, userId, refId, label ):
self._db.cursor().execute( """
UPDATE items SET label = ? WHERE userId IS ? AND refId IS ?""", ( label, userId, refId) )
self._db.commit()
From the documentation:
con.execute("insert into person(firstname) values (?)", ("Joe",))
This escapes "Joe", so what you want is
con.execute("insert into person(firstname) values (?)", (firstname_from_client,))
The DB-API's .execute() supports parameter substitution which will take care of escaping for you, its mentioned near the top of the docs; http://docs.python.org/library/sqlite3.html above Never do this -- insecure.
Noooo... USE BIND VARIABLES! That's what they're there for. See this
Another name for the technique is parameterized sql (I think "bind variables" may be the name used with Oracle specifically).