0

I have a function with a static output that works. (Postgres v.10) This returns the Amount of users per Server.

Here is the code:

CREATE OR REPLACE FUNCTION public.test()
 RETURNS SETOF record
 LANGUAGE plpgsql
AS $function$
DECLARE
    var_req TEXT;
    var_error text;
    rec_key record;
    cur_key CURSOR FOR Select s.srv,s.host,s.port from public.connections() s where s.online = true;
BEGIN
open cur_key;
loop
   fetch cur_key into rec_key;
   EXIT WHEN NOT FOUND;

var_req := 
'Select * from dblink(
''host=' || rec_key.host || '
port=' || rec_key.port || '
user=**
password=**
dbname=mydb'',
''
select '''''|| rec_key.srv ||''''' as srv ,count (*) as total from users '') as (srv varchar,total integer)
';
return query execute var_req;  
end loop;
close cur_key;
END 
$function$
; 

Output =

srv      total
rp1       50
sr2       41
xy        100

To be able to use reuse this query i want to move out the sql part so that i can pass it as parameter.

CREATE OR REPLACE FUNCTION public.test2(text)
 RETURNS SETOF record
 LANGUAGE plpgsql
AS $function$
DECLARE
    var_req TEXT;
    var_error text;
    rec_key record;
    cur_key CURSOR FOR Select s.srv,s.host,s.port from public.connections() s where s.online = true;
BEGIN
open cur_key;
loop
   fetch cur_key into rec_key;
   EXIT WHEN NOT FOUND;

var_req := 
'Select * from dblink(
''host=' || rec_key.host || '
port=' || rec_key.port || '
user=**
password=**
dbname=**'',
''
' || $1 || '
';
return query execute var_req;  
end loop;
close cur_key;
END 
$function$
;

Now when i try to make exact the same query with the dynamic function i don't get it to work. Like this i am pretty close to my goal but instead of using what's inside the rec_key.srv variable it returns '''''|| rec_key.srv ||''''' :(

select * from public.test2('select ''''''''''''|| rec_key.srv ||'''''''''''' as srv ,count (*) as total from users '') as (srv varchar,total integer)') as (srv varchar,total integer)

Output =

            srv                   total
'''''|| rec_key.srv ||'''''        50
'''''|| rec_key.srv ||'''''        41
'''''|| rec_key.srv ||'''''        100

Can someone explain me how i can call what's inside the variable rec_key.srv with the new function?

2
  • Strong advice to use the format() function to build the dynamic query. Commented Mar 23, 2022 at 12:33
  • @wildplasser can you please show how i can implement that in my code and why should i use that? Commented Mar 23, 2022 at 13:31

1 Answer 1

1

Boils down to just this: (!)

SELECT s.srv, t.*
FROM   public.connections() s
     , dblink('host=' || s.host || ' port=' || s.port || ' user=** password=** dbname=**'
            , 'SELECT count(*) FROM users') AS t(total integer);

No wrapper function, no dynamic SQL, no cursor.
Just execute dblink() in an implicit CROSS JOIN LATERAL.

I also added srv to the result like you have in your first function. No need to pipe that through dblink.

See:

Passing arbitrary queries is open to SQL injection. Be sure to understand possible implications and only execute it with trusted input. See:

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you so much for taking your time and help me! Had to take away srv text, to make it work though. Now it works like a charm. SELECT s.srv, t.* FROM public.connections() s , dblink('host=' || s.host || ' port=' || s.port || ' user=** password=** dbname=**' , 'SELECT count(*) FROM users') AS t(total integer);
@user2210516 Yes, that was left over from before I broke out srv. Fixed now.
I don't really understand that how i know how i can change the s.host, and s.port with thoose $ symbol. would this work? SELECT s.srv, t.* FROM public.connections() s , dblink('host=' || 1$ || ' port=' || 2$ || ' user=** password=** dbname=**' , 'SELECT count(*) FROM users') AS t(total integer);
@user2210516 No $ here. You might be thinking of my other answer? stackoverflow.com/a/71656813/939860

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.