1

is there any way for me to create a json file from postgres table

as i did create using

 copy to

but when i create in a postgres function to be scheduled, it is unable to capture the parameters as the file name

copy  v_originaltext to '/var/lib/postgresql/sftp/smrptesting1.json';

1 Answer 1

1

You could likely accomplish what you're looking to do in a couple of different ways, though both would require you to GRANT a combination of pg_write_server_files and/or pg_execute_server_program to the executing role/user.

Method 1: Using Dynamic SQL (with pg_write_server_files)

Here, you'd extrapolate upon your initial plan of using the COPY command, changing

COPY v_originaltext to '/var/lib/postgresql/sftp/smrptesting1.json';

to instead DECLARE a SQL string variable (v_sql) within the function block that you'd then EXECUTE, i.e. something like

CREATE OR REPLACE FUNCTION json_putter(_parameters TEXT)
RETURNS VOID
LANGUAGE plpgsql
AS $function$
DECLARE
    v_sql TEXT DEFAULT NULL;
    v_originaltext JSONB;
    v_filename TEXT;
BEGIN
    -- < ... code to populate v_originaltext here ... >
    v_filename := '/var/lib/postgresql/sftp/' || _parameters || '.json';
    v_sql := 'COPY $1 TO $2';
    
    EXECUTE v_sql USING v_originaltext, v_filename;

-- or, alternatively, with literal single quotes:

    v_sql := 'COPY (SELECT v_originaltext) TO ' || CHR(39) || v_filename || CHR(39);
    EXECUTE v_sql;
END
$function$

which will build up the COPY statement as if you were manually running from the client.

Method 2: Using server-side psql command (with pg_execute_server_program)

You can output the json directly from the psql command, and redirect the stdout to a file descriptor that you generate from the parameters.

To implement this, you'd probably want to create two atomic functions for simplicity's sake:

  • One that acts as a wrapper to generate the value of v_originaltext [e.g. fx_originaltext(_parameters => text)]
  • One that will run a generic command via psql using the COPY ... FROM PROGRAM utility and consumes the stdout with a temp table or similar:

--

CREATE OR REPLACE FUNCTION psql_runner(_function TEXT, _parameters TEXT)

RETURNS VOID
LANGUAGE plpgsql
AS $function$
DECLARE
    v_filename TEXT;
BEGIN
    v_filename := '/var/lib/postgresql/sftp/' || _parameters || '.json';
    CREATE TEMP TABLE _out ( stdout text );
    COPY _out FROM PROGRAM ('psql -tq -c "SELECT ' || _function || '(_parameters :=' || quote_literal(_parameters) || ') " > ' || v_filename);
END
$function$

Notably, the second method requires a larger scope of privileges, and depending on which version of postgres you're using, may need to execute the COPY as dynamic SQL as in the first method.

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

1 Comment

thank u so much, sorry for the late reply

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.