název souboru pro \COPY z proměnné prostředí

11 views
Skip to first unread message

Jiří Fejfar

unread,
Apr 22, 2022, 4:26:40 AM4/22/22
to postgr...@googlegroups.com
Ahoj,

podle https://stackoverflow.com/a/18730455 používám kód, který vezme z proměnné prostředí název souboru a použije ho v příkazu COPY (SQL verze) viz https://gitlab.com/nfiesta/nfiesta_sdesign/-/blob/main/extension/sql/csv/create_csv.sql#L15.

V principu něco takového:

...
\set afile :outputdir '/a.csv'
COPY (SELECT * FROM a) TO :'afile';

jelikož mám problém s právy k zápisu souboru, potřeboval bych to samé udělat pro \COPY (psql verze) ale dostávám chyby:

\COPY (SELECT * FROM a) TO :afile;
to prostě zapíše do souboru s názvem :afile místo použití té proměnné

\COPY (SELECT * FROM a) TO :'afile';

psql:sql/csv/create_csv.sql:15: ERROR:  syntax error at or near "'afile'"
LINE 1: COPY  ( SELECT * FROM a) TO STDOUT 'afile' DELIMI...

díval jsem se na https://stackoverflow.com/a/51682445 ale stejně nevím, jak na to? Je někde zdokumentováno jak funguje přesně to \COPY?

Díky! J.

Pavel Stehule

unread,
Apr 22, 2022, 4:45:40 AM4/22/22
to PostgreSQL-cz
Ahoj

pá 22. 4. 2022 v 10:26 odesílatel Jiří Fejfar <juraf...@gmail.com> napsal:
tohle si myslim, ze najdes jedine ve zdrojacich psql ka. \copy je fakticky COPY FROM/TO stdin/stdout.

a dost mozna, ze tam bude jeste nejaka certovina, ze se pro i pro \copy pouziva SQL parser, ktery nerozezna psql promenne :-/

tady mne napadl takovy trik - pseudo dynamicke sql

\set file ~/xx
\set cmd '\\copy (select 1) to ':file
:cmd

Jinak je to v podstate buga psql, a zkus to fixnout. Jestli to pujde. Bylo by hezky, kdyby to fungovalo. Tam si myslim, ze bude nejaky problem ve volani externiho parseru

Pavel



 
Díky! J.

--
Tuto zprávu jste obdrželi, protože jste přihlášeni k odběru skupiny „PostgreSQL-cz“ ve Skupinách Google.
Chcete-li zrušit odběr skupiny a přestat dostávat e‑maily ze skupiny, zašlete e-mail na adresu postgresql-c...@googlegroups.com.
Chcete-li tuto diskusi zobrazit na webu, navštivte https://groups.google.com/d/msgid/postgresql-cz/CA%2B8wVNVre4t-Ff48dKGswfrOeRXDc41M0rrN1tv%3D9r1Zq8_%2BCg%40mail.gmail.com.

Jan Michálek

unread,
Apr 22, 2022, 4:46:02 AM4/22/22
to postgr...@googlegroups.com
\copy je záležitost psql, kdežto COPY se děje na servru, to \copy udělá v psql COPY FROM STDIN (to uvidíš v pg_stat_activity). Tj, budeš to ukládat pod svym uživatelem na stroji, kde ti běží psql, nikoliv na serveru, jako při použití copy, kde to běží ṕod uživatelem postgres. Já mám za to, že metacommandy nedovedou použít proměnné psql a tohle takhle na přímo udělat nejde. Tj musíš si upravit rovnou to sql, buď sedem, nebo přes eval, nebo použít HEREDOC.

Je;

pá 22. 4. 2022 v 10:26 odesílatel Jiří Fejfar <juraf...@gmail.com> napsal:
Ahoj,

--
Tuto zprávu jste obdrželi, protože jste přihlášeni k odběru skupiny „PostgreSQL-cz“ ve Skupinách Google.
Chcete-li zrušit odběr skupiny a přestat dostávat e‑maily ze skupiny, zašlete e-mail na adresu postgresql-c...@googlegroups.com.
Chcete-li tuto diskusi zobrazit na webu, navštivte https://groups.google.com/d/msgid/postgresql-cz/CA%2B8wVNVre4t-Ff48dKGswfrOeRXDc41M0rrN1tv%3D9r1Zq8_%2BCg%40mail.gmail.com.


--
Jelen
Starší čeledín datovýho chlíva

Jan Michálek

unread,
Apr 22, 2022, 5:00:41 AM4/22/22
to postgr...@googlegroups.com
Nojo, máš pravdu. Já myslel, že to \echo je výjimka

postgres=# \set t /tmp/x
postgres=# SELECT 'nazdar' \g :'t'
'/tmp/x': No such file or directory
postgres=# SELECT 'nazdar' \g :t
postgres=# \! cat :t
cat: ':t': No such file or directory
postgres=# \! cat /tmp/x
┌──────────┐
│ ?column? │
╞══════════╡
│ nazdar   │
└──────────┘
(1 row)

postgres=# \set t /tmp
postgres=# \cd :t
postgres=# \! pwd
/tmp
postgres=#

pá 22. 4. 2022 v 10:52 odesílatel Pavel Stehule <pavel....@gmail.com> napsal:


pá 22. 4. 2022 v 10:46 odesílatel Jan Michálek <godzil...@gmail.com> napsal:
\copy je záležitost psql, kdežto COPY se děje na servru, to \copy udělá v psql COPY FROM STDIN (to uvidíš v pg_stat_activity). Tj, budeš to ukládat pod svym uživatelem na stroji, kde ti běží psql, nikoliv na serveru, jako při použití copy, kde to běží ṕod uživatelem postgres. Já mám za to, že metacommandy nedovedou použít proměnné psql a tohle takhle na přímo udělat nejde. Tj musíš si upravit rovnou to sql, buď sedem, nebo přes eval, nebo použít HEREDOC.

matacommandy umi pouzivat promenne psql, jen je pruser nebo omezeni (castecne z duvodu bezpecnosti), ze evaluace psql promennych neni rekurzivni

(2022-04-22 10:39:53) postgres=# \set var 'Pavel'
(2022-04-22 10:48:59) postgres=# \echo :var
Pavel

\copy zavola hlavni parser, a transformuje \copy na COPY. problem je, ze ten hlavni parser nezna psql promenne - syntax :xxx neni SQL a parsuje se postupne - neni to tak, ze by se parsoval cely radek a pak by se zavolal treba sql parser uz na radku se substituovanymi parametry - coz je mozna v tomhle pripade chyba



 

--
Tuto zprávu jste obdrželi, protože jste přihlášeni k odběru skupiny „PostgreSQL-cz“ ve Skupinách Google.
Chcete-li zrušit odběr skupiny a přestat dostávat e‑maily ze skupiny, zašlete e-mail na adresu postgresql-c...@googlegroups.com.

Jiří Fejfar

unread,
Apr 22, 2022, 5:44:23 AM4/22/22
to postgr...@googlegroups.com
On Fri, 22 Apr 2022 at 10:45, Pavel Stehule <pavel....@gmail.com> wrote:
Ahoj

pá 22. 4. 2022 v 10:26 odesílatel Jiří Fejfar <juraf...@gmail.com> napsal:
Ahoj,

podle https://stackoverflow.com/a/18730455 používám kód, který vezme z proměnné prostředí název souboru a použije ho v příkazu COPY (SQL verze) viz https://gitlab.com/nfiesta/nfiesta_sdesign/-/blob/main/extension/sql/csv/create_csv.sql#L15.

V principu něco takového:

...
\set afile :outputdir '/a.csv'
COPY (SELECT * FROM a) TO :'afile';

jelikož mám problém s právy k zápisu souboru, potřeboval bych to samé udělat pro \COPY (psql verze) ale dostávám chyby:

\COPY (SELECT * FROM a) TO :afile;
to prostě zapíše do souboru s názvem :afile místo použití té proměnné

\COPY (SELECT * FROM a) TO :'afile';

psql:sql/csv/create_csv.sql:15: ERROR:  syntax error at or near "'afile'"
LINE 1: COPY  ( SELECT * FROM a) TO STDOUT 'afile' DELIMI...

díval jsem se na https://stackoverflow.com/a/51682445 ale stejně nevím, jak na to? Je někde zdokumentováno jak funguje přesně to \COPY?


tohle si myslim, ze najdes jedine ve zdrojacich psql ka. \copy je fakticky COPY FROM/TO stdin/stdout.

a dost mozna, ze tam bude jeste nejaka certovina, ze se pro i pro \copy pouziva SQL parser, ktery nerozezna psql promenne :-/

tady mne napadl takovy trik - pseudo dynamicke sql

\set file ~/xx
\set cmd '\\copy (select 1) to ':file
:cmd

jo, toto funguje, ale nevím zase jak tam dostat ten DELIMITER a CVS HEADER :-) zkoušel jsem to přilepit třeba v dalším \set ale nejede to... nerozumím ještě tomu kde je problém, v těch parserech
 
Jinak je to v podstate buga psql, a zkus to fixnout. Jestli to pujde. Bylo by hezky, kdyby to fungovalo. Tam si myslim, ze bude nejaky problem ve volani externiho parseru

no fixnutí nevím :-) ale zkusím to popsat do hackers mailinglistu

Pavel

J



 
Díky! J.

--
Tuto zprávu jste obdrželi, protože jste přihlášeni k odběru skupiny „PostgreSQL-cz“ ve Skupinách Google.
Chcete-li zrušit odběr skupiny a přestat dostávat e‑maily ze skupiny, zašlete e-mail na adresu postgresql-c...@googlegroups.com.
Chcete-li tuto diskusi zobrazit na webu, navštivte https://groups.google.com/d/msgid/postgresql-cz/CA%2B8wVNVre4t-Ff48dKGswfrOeRXDc41M0rrN1tv%3D9r1Zq8_%2BCg%40mail.gmail.com.

--
Tuto zprávu jste obdrželi, protože jste přihlášeni k odběru skupiny „PostgreSQL-cz“ ve Skupinách Google.
Chcete-li zrušit odběr skupiny a přestat dostávat e‑maily ze skupiny, zašlete e-mail na adresu postgresql-c...@googlegroups.com.

Jiří Fejfar

unread,
Apr 22, 2022, 5:54:04 AM4/22/22
to postgr...@googlegroups.com
On Fri, 22 Apr 2022 at 11:44, Jiří Fejfar <juraf...@gmail.com> wrote:

On Fri, 22 Apr 2022 at 10:45, Pavel Stehule <pavel....@gmail.com> wrote:
Ahoj

pá 22. 4. 2022 v 10:26 odesílatel Jiří Fejfar <juraf...@gmail.com> napsal:
Ahoj,

podle https://stackoverflow.com/a/18730455 používám kód, který vezme z proměnné prostředí název souboru a použije ho v příkazu COPY (SQL verze) viz https://gitlab.com/nfiesta/nfiesta_sdesign/-/blob/main/extension/sql/csv/create_csv.sql#L15.

V principu něco takového:

...
\set afile :outputdir '/a.csv'
COPY (SELECT * FROM a) TO :'afile';

jelikož mám problém s právy k zápisu souboru, potřeboval bych to samé udělat pro \COPY (psql verze) ale dostávám chyby:

\COPY (SELECT * FROM a) TO :afile;
to prostě zapíše do souboru s názvem :afile místo použití té proměnné

\COPY (SELECT * FROM a) TO :'afile';

psql:sql/csv/create_csv.sql:15: ERROR:  syntax error at or near "'afile'"
LINE 1: COPY  ( SELECT * FROM a) TO STDOUT 'afile' DELIMI...

díval jsem se na https://stackoverflow.com/a/51682445 ale stejně nevím, jak na to? Je někde zdokumentováno jak funguje přesně to \COPY?


tohle si myslim, ze najdes jedine ve zdrojacich psql ka. \copy je fakticky COPY FROM/TO stdin/stdout.

a dost mozna, ze tam bude jeste nejaka certovina, ze se pro i pro \copy pouziva SQL parser, ktery nerozezna psql promenne :-/

tady mne napadl takovy trik - pseudo dynamicke sql

\set file ~/xx
\set cmd '\\copy (select 1) to ':file
:cmd

jo, toto funguje, ale nevím zase jak tam dostat ten DELIMITER a CVS HEADER :-) zkoušel jsem to přilepit třeba v dalším \set ale nejede to... nerozumím ještě tomu kde je problém, v těch parserech

už to mám :-)

\set srcdir `echo $SRC_DIR`

CREATE OR REPLACE TEMPORARY VIEW v_countries AS (
        select
                label as country,
                description as comment
        from sdesign.c_country
        order by label, description);

\set afile :srcdir '/sql/csv/countries.csv'

\set cmd_part '\\copy (SELECT * FROM v_countries) to ':afile

select :'cmd_part' as cmd_part;

\set cmd :cmd_part ' DELIMITER '','' CSV HEADER'

select :'cmd' as cmd;

:cmd


                                                           cmd_part
------------------------------------------------------------------------------------------------------------------------------
 \copy (SELECT * FROM v_countries) to /home/fejfar-local/repo/nfiesta_pg/deps/nfiesta_sdesign/extension/sql/csv/countries.csv
(1 row)

                                                                          cmd
-------------------------------------------------------------------------------------------------------------------------------------------------------
 \copy (SELECT * FROM v_countries) to /home/fejfar-local/repo/nfiesta_pg/deps/nfiesta_sdesign/extension/sql/csv/countries.csv DELIMITER ',' CSV HEADER
(1 row)

Jiří Fejfar

unread,
Apr 22, 2022, 5:58:03 AM4/22/22
to postgr...@googlegroups.com
jde to ají na jednom řádku...

\set cmd '\\copy (SELECT * FROM v_countries) to ':afile ' DELIMITER '','' CSV HEADER' 

chyběla mi tam mezera před DELIMITER

Adam Konrád

unread,
Apr 22, 2022, 11:40:19 AM4/22/22
to PostgreSQL-cz
V minulosti jsem COPY úspěšně použil. Možná váš problém jde obejít právě přes přesměrování ze stdin. Vaši proměnnou prostředí můžete zkusit použít jako vstupní parametr procesu jehož výstup přesměrujete do stdin psql.

COPY <tabulka> (<sloupec>, ...) FROM STDIN WITH(NULL \'\')

Jiří Fejfar

unread,
Apr 25, 2022, 4:28:20 AM4/25/22
to postgr...@googlegroups.com
On Fri, 22 Apr 2022 at 11:44, Jiří Fejfar <juraf...@gmail.com> wrote:

Jiří Fejfar

unread,
Apr 25, 2022, 9:37:49 AM4/25/22
to postgr...@googlegroups.com
Tak podle toho, co píší chování odpovídá dokumentaci https://www.postgresql.org/docs/12/app-psql.html

The syntax of this command is similar to that of the SQL COPY command. All options other than the data source/destination are as specified for COPY. Because of this, special parsing rules apply to the \copy meta-command. Unlike most other meta-commands, the entire remainder of the line is always taken to be the arguments of \copy, and neither variable interpolation nor backquote expansion are performed in the arguments.

zkusím ještě tu variantu SQL COPY ... TO STDOUT command and terminate it with \g filename
Reply all
Reply to author
Forward
0 new messages