How to include files relative to the current executing script in psql? - postgresql

I have a PostgreSQL script (say, MAIN.sql in ~/sql/) which has lines like
\i components/helper-functions.sql
This include works fine if the $PWD is the same as the directory of my script (~/sql/), but if it is not, it looks for the included file relative to the $PWD instead of relative to MAIN.sql.
So if I call the script from ~/, it would look for ~/components/helper-functions.sql and not for ~/sql/components/helper-functions.sql.
I think a new \ir directive is going to be included in 9.2 for exactly this problem, but I'm running 8.3

Pass the directory name in as a psql variable and use that to assemble the absolute path to included files, e.g.,
$ cat ./tmp/foo.sql
\echo 'This is foo.'
\set abs_bar_sql :DIR '/bar.sql'
\i :abs_bar_sql
$ cat ./tmp/bar.sql
\echo 'This is bar.'
$ psql -f ./tmp/foo.sql -v DIR=$PWD/tmp
This is foo.
This is bar.
It's not pretty, but that's why \ir is being added after all.

Related

What "*#" means after executint a command in PostgreSql 10 on Windows 7?

I'm using PostgreSQL on Windows 7 through the command line. I want to import the content of different CSV files into a newly created table.
After executing the command the database name appeared like:
database=#
Now appears like
database*# after executing:
type directory/*.csv | psql -c 'COPY sch.trips(value1, value2) from stdin CSV HEADER';
What does *# mean?
Thanks
This answer is for Linux and as such doesn't answer OP's question for Windows. I'll leave it up anyway for anyone that comes across this in the future.
You accidentally started a block comment with your type directory/*.csv. type doesn't do what you think it does. From the bash built-ins:
With no options, indicate how each name would be interpreted if used as a command name.
Try doing cat instead:
cat directory/*.csv | psql -c 'COPY sch.trips(value1, value2) from stdin CSV HEADER';
If this gives you issues because each CSV has its own header, you can also do:
for file in directory/*.csv; do cat "$file" | psql -c 'COPY sch.trips(value1, value2) from stdin CSV HEADER'; done
Type Command
The type built-in command in Bash is a way of viewing command interpreter results. For example, using it with ssh:
$ type ssh
ssh is /usr/bin/ssh
This indicates how ssh would be interpreted when you run ssh as a command in the current Bash environment. This is useful for things like aliases. As an example for this, ll is usually an alias to ls -l. Here's what my Bash environment had for ll:
$ type ll
ll is aliased to `ls -l --color=auto'
For you, when you pipe the result of this command to psql, it encounters the /* in the input and assumes it's a block comment, which is what the database*# prompt means (the * indicates it's waiting for the comment close pattern, */).
Cat Command
cat is for concatenating multiple files together. By default, it writes to standard out, so cat directory/*.csv will write each CSV file to standard out one after another. However, piping this means that each CSV's header will also be piped mid-stream of the copy. This may not be desirable, so:
For Loop
We can use for to loop over each file and individually import it. The version I have above, for file in directory/*.csv, will properly handle files with spaces. Properly formatted:
for file in directory/*; do
cat "$file" | psql -c 'COPY sch.trips(value1, value2) from stdin CSV HEADER'
done
References
PostgreSQL 10 Comments Documentation (postgresql.org)
type built-in Manual page (mankier.com)
cat Manual page (mankier.com)
Bash looping tutorial (tldp.org)

Wrong copy command output with postgres

I'm trying to use the copy command to copy the content of a file into a database.
One of the lines have this:
CCc1ccc(cc1)C(=O)/N=c\1/n(ccs1)C
and when i insert this normally into database there is no errors.
But when i'm trying to use the following command, this line is not insert correctly.
cat smile_test.txt | psql -c "copy testzincsmile(smile) from stdout" teste
This i what i get (it is wrong):
CCc1ccc(cc1)C(=O)/N=c/n(ccs1)C
What's wrong here?
Thank you :)
copy expects a specific input format and cannot just be used to read random text from a file into a field.
See the manual.
The specific issue you're hitting is probably a backslash being interpreted as an escape by the default copy in/out format.
I figure out how to do this:
This is my answer:
cat smile_test.txt | sed '1d; s/\\/\\\\/g' | psql -c "copy testzincsmile(smile) from stdout" teste

Convert Perl Script to Executable file packaging YAML file in executable used by perl script

I have small perl script test.pl. This perl script uses input as YAML file database.yml
To convert these perl script into executable, I run following command shown below.
pp -o -x teste.exe test.pl.
It creates executable but when i try to run this executable it throws error that database.yml file not found in that directory.
How can i ensure that executable includes YAML file while creating the exe of perl script?
Note :- I am using perl verison 5.8 in Unix.
By using the -a switch :
pp -a database.yml -o -x teste.exe test.pl
From pp documentation :
-a, --addfile=FILE|DIR
Add an extra file into the package. If the file is a directory, recursively add all files inside that directory, with links turned into actual files.
By default, files are placed under "/" inside the package with their original names. You may override this by appending the target filename after a ";", like this:
% pp -a "old_filename.txt;new_filename.txt"
% pp -a "old_dirname;new_dirname"
You may specify "-a" multiple times.

Postgres COPY command to tail a file?

I want to use to copy command to copy data into postgres; while there other processes are simultaneously writing into the CSV file.
Is something like this possible? Take the stdout from tail and pipe into the stdin of postgres.
COPY targetTable ( column1, column2 )
FROM `tail -f 'path/to/data.csv'`
WITH CSV
Assuming PostgreSQL 9.3 or better, there's the possibility of copying from a program output with:
COPY FROM PROGRAM 'command'
From the doc:
PROGRAM
A command to execute. In COPY FROM, the input is read from standard
output of the command, and in COPY TO, the output is written to the
standard input of the command.
This may be what you need except for the fact that tail -f being a never-ending command by design, it's not obvious how you plan for the COPY to ever finish. Presumably you'd need to replace tail -f by a more elaborate script with some exit condition.
you can also do COPY FROM STDIN;
example:
tail -f datafile.csv | psql -tc "COPY table from STDIN" database

Does perl's -i with no argument create a backup file on Cygwin?

I have a bug report from a reliable person that on Cygwin and Perl 5.14.2, using perl's -i switch with no value creates a .bak backup file. It shouldn't according to the documentation in perlrun:
If no extension is supplied, no backup is made and the current
file is overwritten.
I don't have access to Cygwin at the moment. Does anyone else see this behavior? Can you explain it? Is is something about creating the backup file, which should only be a temporary file, and failing to remove it?
Here's the steps I suggest to recreate it. Remember, this is for Cygwin:
Create and change into empty directory
Create a text file in that directory. The contents are not important
Run perl -p -i -e 's/perl/Perl/g' filename
Check for a .bak file when you are done
Save the answers for an explanation of what might be happening if you find that backup file. Upvoting a prior comment for "Yes I see that" or "No, can't reproduce it" can be an informal poll.
perldoc perlcygwin sayeth (edited for clarity):
Because of Windows-ish restrictions, inplace editing of files with perl -i
must create a
backup of each file being edited. Therefore Perl adds the suffix .bak automatically — as
though invoked with perl -i.bak— if
you use perl -i with no explicit backup extension.
Arguably this information should be in perlport also.
Yes. For example:
# show we're in cygwin
% uname -a
CYGWIN_NT-6.1-WOW64 xzodin 1.7.15(0.260/5/3) 2012-05-09 10:25 i686 Cygwin
# show that directory is empty
% ls
# create a file
% touch foo
# invoke 'perl -pi' (but do nothing)
% perl -pi -e "" foo
# show that a backup file with extension '.bak' is created.
% ls
foo foo.bak