What I am trying to do is to copy subset of DB table datas from X environment to local file storage. I am tryin to execute psql command with Java Runtime but it fails
this.psqlExportDataFile = "psql postgresql://dburl -o /Users/Shared/CopyDB/project.csv -c \"COPY (SELECT * FROM gls.project where id in (112371,148904,1652068)) TO STDOUT(FORMAT csv, DELIMITER ',', NULL 'null')'\"";
Process process = runtime.exec(psqlExportDataFile);
System.out.println(new String(toByteArray(process.getErrorStream())));
But it normally works when I am running it within shell.
The error output is:
ERROR: unterminated quoted identifier at or near ""COPY"
LINE 1: "COPY
^
What could be the issue?
You incorrectly think that 'typing on the command line' (
cmd.exe, or/bin/bash, or whatever your terminal is) is identical to 'starting a process'. Not so.Your shell does lots of stuff. It takes that string you type and processes it in many, many ways. It results in running a command, sure (here, firing up
psql.exeor/bin/psqlor whatnot, and passing certain arguments to that process). But it'sbash/cmd.exethat e.g. applies quotes, space-splitting, and all that jazz.Java's process builder isn't
cmd.exeand isn't/bin/bash. It does almost nothing except space-splitting. You want to take control of it, so stop usingRuntime.exec()and useProcessBuilderinstead, and that whole 'quotes around an argument' thing isn't how ProcessBuilder works in the first place. It's bash/cmd that decided: To pass more than 1 arg, put spaces in between, and then solved the dilemma of "What if I want to pass a single argument that, itself, contains spaces" with: "Ah, well, then, um, put quotes around it?".Java's processbuilder picked a different, simpler solution: Pass each argument as.. 1 argument:
and then run that/