2

I need to write a file to disk from postgres that has character string of a backslash immediately followed by a forward slash \/

Code similar to this has not worked:

drop table if exists test;
create temporary table test (linetext text);
insert into test values ('\/\/foo foo foo\/bar\/bar');
copy (select linetext from test) to '/filepath/postproductionscript.sh';

The above code yields \\/\\/foo foo foo\\/bar\\/bar ... it inserts an extra backslash.

When you view the temp table, the string is correctly viewed as \/\/, so I am not sure where or when the text is changed into \\/\\/

I've tried doubling the \, variations of E before the string, and quote_literal() without luck.

I have note found a solution here Postgres Manual

Running Postgres 9.2, encoded UTF-8.

2

2 Answers 2

2

The problem is that COPY is not intended to write out plain-text files. It is intended to write out files that can be read back by COPY. And the semi-internal encoding that it uses does some backslash escaping.

For what you want to do, you need to write some custom code. Either use a normal client library to read the query results and write them to a file, or, if you want to do it in-server, use something like PL/Perl or PL/Python.

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

1 Comment

You're probably right, and that is an answer I didn't want to hear. Barring other ideas, I'll probably code the long way around the issue...I'll put the backslash portions of code into a separate shell script, and I'll have postgres generate a call and pass a variable to that script. That seems to be the cleanest approach at the moment. [I wish there was a Postgres module for writing plain text files] Thanks.
0

The \ excaping is only recognised if the stringliteral is prefixed with E , otherwise the standard_conforming_strings setting (or the like) is respected (ANSI-SQL has a different way of string escaping, probably stemming from COBOL;-).

drop table if exists test;
create temporary table test (linetext text);
insert into test values ( E'\/\/foo foo foo\/bar\/bar');
copy (select linetext from test) to '/tmp/postproductionscript.sh';

UPATE: an ugly hack is to use .csv format and still use \t as delimter. The #!/bin/sh as a shebang headerline should be consdered a feature

       -- without a header line
drop table if exists test;
create temporary table test (linetext text);
insert into test values ( '\/\/foo foo foo\/bar\/bar');
copy (select linetext AS "#linetext" from test) to '/tmp/postproductionscript_c.sh'
        WITH CSV
        DELIMITER E'\t'
        ;
        -- with a shebang header line
drop table if exists test;
create temporary table test (linetext text);
insert into test values ( '\/\/foo foo foo\/bar\/bar');
copy (select linetext AS "#/bin/sh" from test) to '/tmp/postproductionscript_h.sh'
        WITH CSV
        HEADER
        DELIMITER E'\t'
        ;

4 Comments

Thanks. I tried that code, no luck, at least in my configuration. It yielded //foo foo foo/bar/bar.
But you do want both the backslash and the slash in the string? What is the original string ?(I suppose the values() thing is just for demonstration purposes)
Thanks. I'll give it a look. I kept trying with your code suggestion.. and the results never worked, sometimes they were unexpected. I think Peter is right.. COPY is doing things inside for it's own purposes. I'll explore the CSV idea.
COPY is an ugly beast, mostly caused by the need for backward compatibility. Would have been better to create a new NCOPY command with a more orthogonal syntax.

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.