Postgres: if-else condition depending on prompt, in .sql file called via \i - postgresql

With Postgres 10.10, here is what I am trying to accomplish. I want to have a test.sql script file (executed by \i /path/test.sql) whose code execution depends on what the user inputs after an initial prompt.
For instance, with code below I would like some text to be echoed and a table to be created, but the echoed text and the table name should depend on the text passed by the user as input to a prompt:
\prompt 'What is your favourite color?' answer
IF ('blue' = :answer) THEN
\echo 'It is blue! :) '
CREATE TABLE blue;
ELSE
\echo 'It is something else. :( '
CREATE TABLE :answer;
END IF;
However, a few errors prevent that from working:
myuser=# \i /home/myuser/test.sql
What is your favourite color?red
It is blue! :)
psql:/home/myuser/test.sql:4: ERROR: syntax error at or near "IF"
LINE 1: IF ('blue' = red) THEN
^
It is something else. :(
psql:/home/myuser/test.sql:7: ERROR: syntax error at or near "ELSE"
LINE 1: ELSE
^
psql:/home/myuser/test.sql:8: ERROR: syntax error at or near "IF"
LINE 1: END IF;
^
myuser=#
Notice that this is not the same as asked in https://dba.stackexchange.com/questions/207666/how-do-i-use-the-input-from-a-prompt-in-a-conditional-if. Also, I tried adapting it to follow the answer in Postgres syntax error at or near "IF", but then I just get more errors, starting with "syntax error at or near 'DO'".
Is there a way for me to accomplish this task? That is, every time an user executes the test.sql file with \i, the user is prompted and the execution of the code within the file branches depending on the text that the user inputed via prompt?

Something like this:
SELECT :'answer' = 'blue' AS isblue \gset
\if :isblue
...
\endif

Related

Why am I getting an error near semi colon (:)?

I have no idea but this is throwing an error i think it is on line "set #al = 2020". I have read the documentation and not seeming to translate over.
begin
declare #al int;
set #al = 2020;
exec dbo.get_egus_trdg_desk_rpt_no_clrg_broker(#al int);
end
Error message:
SQL Error [102] [42000]: Incorrect syntax near ';'.
You do not need to use ';' after every line of code. I can successfully generate the following script in SQL Server 2019.
Sample Output

PostgreSQL script control structures

I have an sql script which copies data from a file:
--myscript.sql
\set file :dir 'data.csv'
copy data from :'file' csv;
and execute it with psql providing the dir variable
psql -v dir="D:\data\" -f myscript.sql
now I would like the copy command executed only if some other variable is let, e.g. -v doit=
Are there any script control structures available for this? Looking for something like
$if :{?doit}
copy data from :'file' csv;
$endif;
Have tried to wrap it by an anonymous block
do '
begin
if ':{?doit}' then
copy data from :'file' csv;
end if;
end';
But it gives the error
Error: syntax error (approximate position "TRUE")
LINE 3: if 'TRUE' then
^
Answering my own question.
There were two issues there
psql variables cannot be directly substituted in do statements
This can be solved by putting a psql variable into a server setting as suggested here
the copy command does not accept any functions for the file path name, so the first solution won't work here.
I ended up formating the do block like this
select format('
begin
if ''%s''=''t'' then
copy rates from ''%s'' csv header delimiter E''\t'';
end if;
end;',:{?doit},:'file') as do \gset
do :'do';
The format function lets us use a multiline string. The resulting string is then assigned to a new varialbe with the help of \gset and feed it to do.
Note: The format function formats 'TRUE' as 't', so we have to treat it as such.
Thanks to #Mark for the directions.

what does caret do in postgresql?

I'm playing hackthebox machine's and current one has a postgresql db in place. The query breaks with ' and appeas as follows:
ERROR: unterminated quoted string at or near "'" LINE 1: Select * from
cars where name ilike '%test'%' ^
I understand that % is being used to search within the query string for the characters provided but, What is ^ used for?
Bold highlights my test query
All my searches yielded resulst regarding regexes and caret signaling the start of the string. Plus other result about using cli or something like that.
Can anybody tell me what is it doing at the end of the query?
Your are looking for the use of the caret specifically within error messages.
If I run this query:
psql -c " Select * from cars where name ilike '%test'%'"
This is what I get, preserving line breaks and spaces:
ERROR: unterminated quoted string at or near "'"
LINE 1: Select * from cars where name ilike '%test'%'
^
The caret points to where on the previous line the error occurred. In this case, that is where the opening quote mark that never got closed was located.
If you are using a tool which malformats your error messages, you should consider changing to one that does not or otherwise figuring out how to fix it.

setting variables using \set in psql

I am trying to set the variable in psql console that contains JSON.
I do it like this
mydb=# \set cfg '{"base":"some url","remoteIP":"ip"}';
Then I am trying to invoke query and pass this variable
mydb=# select exec_search(:'cfg','Field');
However instead of execution if turns into this
mydb'#
And when press enter or try to add quote I cannot execute the query. I have to quit the terminal.
mydb'#
mydb'#
mydb'# '
mydb(#
What is the problem?
Your first mistake is the semicolon at the end of the \set command.
psql commands (commands that start with a backslash) are not terminated by semicolon, but by the end of the line.
So you end up with an extra semicolon in the variable, which will result in invalid JSON.
I cannot reproduce your second problem with the data from your question. You get this prompt if you enter a line with unbalanced single quotes.
To get out of that, press Ctrl+C.

Is there a way to have Postgres tell you what a syntax error was in addition to what it is at/near?

I've tried setting 'log_min_error_statement' equal to debug5 in postgresql.conf but I'm still getting the standard "PostgreSQL said: syntax error at or near "AS"" error message in both the console and the postgresql log.
If PostgreSQL knew what the error was it'd tell you, at least in most cases.
If it just says "Syntax error at or near ..." it doesn't know what you meant, and can't guess what's wrong. It's a parse error. It could offer a (very long) list of suggestions, but that'd make error messages absurdly verbose, like:
postgres=# SELECT AS fred ORDER BY 1;
ERROR: syntax error at or near "AS"
LINE 1: SELECT AS fred ORDER BY 1;
Yup, that's a syntax error, because it doesn't make sense on any level. What's wrong with it? How do you succinctly describe that? How does a parser even tell what's wrong?
postgres=# SELECT AS fred ORDER BY 1;
ERROR: syntax error at or near "AS"
LINE 1: SELECT AS fred ORDER BY 1;
HINT: typo?
HINT: Did you use a reserved keyword as an identifier without "quoting" it? Like "AS"?
HINT: Did you leave out the value before the AS keyword?
HINT: ... endless possibilities ...
Occasionally a parser can guess something you might've done wrong. PostgreSQL's parser tries to tell you when it can, e.g.
psql -c "SELECT 'openquote";
ERROR: unterminated quoted string at or near "'openquote"
LINE 1: SELECT 'openquote