Thread: Enhancement to psql command, feedback.
I just wanted to throw this out to the users before I made a complete fool of myself by formally requesting it. But I would like what I hope would be a minor change (enhancement) to the psql command. If you look on this page, https://wiki.postgresql.org/wiki/Shared_Database_Hosting ,
you will see a number of example which look like:
psql -U postgres template1 -f - << EOT REVOKE ALL ON DATABASE template1 FROM public; REVOKE ALL ON SCHEMA public FROM public; GRANT ALL ON SCHEMA public TO postgres; CREATE LANGUAGE plpgsql; EOT
To me this looks similar to a UNIX shell script. Now, going sideways for a second, if someone wanted to create a "self contained" awk script. It would look something like:
#!/bin/awk -f
... awk code ...
When a user executes the above from the command line, the UNIX system runs the program in the first "magic" line as if the user had entered "/bin/awk -f ..." where the ... is replaced by the name of the file executed followed by the rest of the command line parameters.
I think it would be nice if psql would do the same, mainly for "consistency" with other UNIX scripting languages, such as python, perl, & gawk.
The example above would then become:
#!/bin/psql -U postgres template1 -f REVOKE ALL ON DATABASE template1 FROM public; REVOKE ALL ON SCHEMA public FROM public; GRANT ALL ON SCHEMA public TO postgres; CREATE LANGUAGE plpgsql;Does this seem reasonable to others? When I actually try the following as a "script", I get an error.
=== transcript ===
$ls -l ./x.psql; cat ./x.psql; ./x.psql
-rwxr-xr-x. 1 joarmc joarmc 40 May 9 02:55 ./x.psql
#!/usr/bin/psql -f
select * from table;
psql:./x.psql:2: ERROR: syntax error at or near "#!/"
LINE 1: #!/usr/bin/psql -f
^
-rwxr-xr-x. 1 joarmc joarmc 40 May 9 02:55 ./x.psql
#!/usr/bin/psql -f
select * from table;
psql:./x.psql:2: ERROR: syntax error at or near "#!/"
LINE 1: #!/usr/bin/psql -f
^
I have not looked at the source yet, but it seems that it would be "easy" to implement if psql would simply ignore the first line of any file referenced via the "-f" parameter if it started with "#!" or maybe even just "#". I'm not suggesting ignoring _every_ line that start with that "magic", just the first.
We all have skeletons in our closet.
Mine are so old, they have osteoporosis.
Maranatha! <><
John McKown
John McKown
2018-05-09 9:59 GMT+02:00 John McKown <john.archie.mckown@gmail.com>:
I just wanted to throw this out to the users before I made a complete fool of myself by formally requesting it. But I would like what I hope would be a minor change (enhancement) to the psql command. If you look on this page, https://wiki.postgresql.org/wiki/Shared_Database_ Hosting , you will see a number of example which look like:psql -U postgres template1 -f - << EOT REVOKE ALL ON DATABASE template1 FROM public; REVOKE ALL ON SCHEMA public FROM public; GRANT ALL ON SCHEMA public TO postgres; CREATE LANGUAGE plpgsql; EOTTo me this looks similar to a UNIX shell script. Now, going sideways for a second, if someone wanted to create a "self contained" awk script. It would look something like:#!/bin/awk -f... awk code ...When a user executes the above from the command line, the UNIX system runs the program in the first "magic" line as if the user had entered "/bin/awk -f ..." where the ... is replaced by the name of the file executed followed by the rest of the command line parameters.I think it would be nice if psql would do the same, mainly for "consistency" with other UNIX scripting languages, such as python, perl, & gawk.
These languages has defined # as line comment. It is not true for SQL.
Regards
Pavel
The example above would then become:#!/bin/psql -U postgres template1 -f REVOKE ALL ON DATABASE template1 FROM public; REVOKE ALL ON SCHEMA public FROM public; GRANT ALL ON SCHEMA public TO postgres; CREATE LANGUAGE plpgsql;Does this seem reasonable to others? When I actually try the following as a "script", I get an error.
=== transcript ===$ls -l ./x.psql; cat ./x.psql; ./x.psql
-rwxr-xr-x. 1 joarmc joarmc 40 May 9 02:55 ./x.psql
#!/usr/bin/psql -f
select * from table;
psql:./x.psql:2: ERROR: syntax error at or near "#!/"
LINE 1: #!/usr/bin/psql -f
^I have not looked at the source yet, but it seems that it would be "easy" to implement if psql would simply ignore the first line of any file referenced via the "-f" parameter if it started with "#!" or maybe even just "#". I'm not suggesting ignoring _every_ line that start with that "magic", just the first.--We all have skeletons in our closet.Mine are so old, they have osteoporosis.Maranatha! <><
John McKown
On Wed, May 9, 2018 at 3:05 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:
2018-05-09 9:59 GMT+02:00 John McKown <john.archie.mckown@gmail.com>: I just wanted to throw this out to the users before I made a complete fool of myself by formally requesting it. But I would like what I hope would be a minor change (enhancement) to the psql command. If you look on this page, https://wiki.postgresql.org/wiki/Shared_Database_Hosti ng , you will see a number of example which look like:psql -U postgres template1 -f - << EOT REVOKE ALL ON DATABASE template1 FROM public; REVOKE ALL ON SCHEMA public FROM public; GRANT ALL ON SCHEMA public TO postgres; CREATE LANGUAGE plpgsql; EOTTo me this looks similar to a UNIX shell script. Now, going sideways for a second, if someone wanted to create a "self contained" awk script. It would look something like:#!/bin/awk -f... awk code ...When a user executes the above from the command line, the UNIX system runs the program in the first "magic" line as if the user had entered "/bin/awk -f ..." where the ... is replaced by the name of the file executed followed by the rest of the command line parameters.I think it would be nice if psql would do the same, mainly for "consistency" with other UNIX scripting languages, such as python, perl, & gawk.These languages has defined # as line comment. It is not true for SQL.
For fun, not because I've put considerable thought into it:
#!/usr/bin/psql --enable-hash-comment -f
...
-m
On 05/09/2018 02:59 AM, John McKown wrote:
Because it is a Unix shell script. The "<< EOT" is part of a heredoc, which is designed to keep everything in one place instead of needing a second file for the SQL commands.
https://en.wikipedia.org/wiki/Here_document
(The concept is as old as computing. Anyone who's worked on mainframes or proprietary minicomputers from DEC will instantly recognize it.)
I just wanted to throw this out to the users before I made a complete fool of myself by formally requesting it. But I would like what I hope would be a minor change (enhancement) to the psql command. If you look on this page, https://wiki.postgresql.org/wiki/Shared_Database_Hosting ,you will see a number of example which look like:psql -U postgres template1 -f - << EOT REVOKE ALL ON DATABASE template1 FROM public; REVOKE ALL ON SCHEMA public FROM public; GRANT ALL ON SCHEMA public TO postgres; CREATE LANGUAGE plpgsql; EOTTo me this looks similar to a UNIX shell script.
Because it is a Unix shell script. The "<< EOT" is part of a heredoc, which is designed to keep everything in one place instead of needing a second file for the SQL commands.
https://en.wikipedia.org/wiki/Here_document
(The concept is as old as computing. Anyone who's worked on mainframes or proprietary minicomputers from DEC will instantly recognize it.)
--
Angular momentum makes the world go 'round.
Angular momentum makes the world go 'round.
2018-05-09 9:59 GMT+02:00 John McKown <john.archie.mckown@gmail.com>: I just wanted to throw this out to the users before I made a complete fool of myself by formally requesting it. But I would like what I hope would be a minor change (enhancement) to the psql command. If you look on this page, https://wiki.postgresql.org/wiki/Shared_Database_Hosti ng , you will see a number of example which look like:psql -U postgres template1 -f - << EOT REVOKE ALL ON DATABASE template1 FROM public; REVOKE ALL ON SCHEMA public FROM public; GRANT ALL ON SCHEMA public TO postgres; CREATE LANGUAGE plpgsql; EOTTo me this looks similar to a UNIX shell script. Now, going sideways for a second, if someone wanted to create a "self contained" awk script. It would look something like:#!/bin/awk -f... awk code ...When a user executes the above from the command line, the UNIX system runs the program in the first "magic" line as if the user had entered "/bin/awk -f ..." where the ... is replaced by the name of the file executed followed by the rest of the command line parameters.I think it would be nice if psql would do the same, mainly for "consistency" with other UNIX scripting languages, such as python, perl, & gawk.These languages has defined # as line comment. It is not true for SQL.
Thanks, that looks like a "NO" vote to me.
RegardsPavel
We all have skeletons in our closet.
Mine are so old, they have osteoporosis.
Maranatha! <><
John McKown
John McKown
On 05/09/2018 02:59 AM, John McKown wrote:I just wanted to throw this out to the users before I made a complete fool of myself by formally requesting it. But I would like what I hope would be a minor change (enhancement) to the psql command. If you look on this page, https://wiki.postgresql.org/wiki/Shared_Database_ Hosting , you will see a number of example which look like:psql -U postgres template1 -f - << EOT REVOKE ALL ON DATABASE template1 FROM public; REVOKE ALL ON SCHEMA public FROM public; GRANT ALL ON SCHEMA public TO postgres; CREATE LANGUAGE plpgsql; EOTTo me this looks similar to a UNIX shell script.
Because it is a Unix shell script. The "<< EOT" is part of a heredoc, which is designed to keep everything in one place instead of needing a second file for the SQL commands.
https://en.wikipedia.org/wiki/Here_document
(The concept is as old as computing. Anyone who's worked on mainframes or proprietary minicomputers from DEC will instantly recognize it.)
Yes, I use HERE docs in my shell scripts. I was just, sort of, wanting to avoid that by making a "slight" change to the psql program to ignore the first (and only the first) line of any file referenced via a "-f". This is NOT any kind of critical necessity. I just think it would be "nice" simply because _I_ have a habit of use the "magic" #! at the start of the first like in order to have other "languages" (such as python, perl, gawk), be invoked with the script file name as a parameter. One reason to avoid a HERE doc is from what I've learned about how BASH at least implements them. The BASH shell sees the HERE document and copies it into a "temporary" disk file. It then opens this file and supplies that file descriptor to whatever is being fed the HERE document as input. So, in effect, using a HERE document, at least in BASH, does a lot more I/O to the disk system.
Again, this is just a discussion point. And I'm quite willing to admit defeat if most people don't think that it is worth the effort.
--
Angular momentum makes the world go 'round.
We all have skeletons in our closet.
Mine are so old, they have osteoporosis.
Maranatha! <><
John McKown
John McKown
Greetings, * John McKown (john.archie.mckown@gmail.com) wrote: > Again, this is just a discussion point. And I'm quite willing to admit > defeat if most people don't think that it is worth the effort. For my 2c, at least, I do think it'd be kind of neat to have, but we'd need a fool-proof way to realize that's how we're being called and, ideally, that would be something we could detect without having to have special flags for psql which anyone writing such a script would have to be aware of. Do you know if there's a way to detect that we're being called this way..? Thanks! Stephen
Attachment
Again, this is just a discussion point. And I'm quite willing to admit defeat if most people don't think that it is worth the effort.
-1, at least per the example. I would not want "-U postgres" inside the file. I tend to rely on service entries, not environment variables, and wouldn't want to hard-code them either. While psql has grown more flow-control capabilities recently it is, in most cases, a support language for me, not a main entry point. Shell scripts merge the per-instance run-time environment I need with the behavior the script provides - merging that I find I need more often than not and don't miss the added overhead in the few cases where it is unnecessary.
David J.
Again, this is just a discussion point. And I'm quite willing to admit defeat if most people don't think that it is worth the effort.-1, at least per the example. I would not want "-U postgres" inside the file. I tend to rely on service entries, not environment variables, and wouldn't want to hard-code them either. While psql has grown more flow-control capabilities recently it is, in most cases, a support language for me, not a main entry point. Shell scripts merge the per-instance run-time environment I need with the behavior the script provides - merging that I find I need more often than not and don't miss the added overhead in the few cases where it is unnecessary.David J.
I agree. I wouldn't want the -U inside a "regular" shell script either. As a minor example, consider the following _almost_ equivalent scripts.
$ cat psql-script.sh
#!/bin/sh
psql "$@" -f - <<EOT
select * from table;
EOF
$ cat psql-script.sql
#!/usr/bin/psql -f -
select * from table
$ chmod 755 psql-script.{sh,sql}
$ ./psql-script.sh -U postgres -d somedb -h remote-host.com
$ ./psql-script.sql -U postgres -d somedb -h remote-host.com
These are _almost_ equivalent. The first execution shown after the chmod is effectively:
psql -U postgres -d somedb -h remote-host.com -f - <<EOT
select * from table;
EOT
The second is effectively:
/usr/bin/psql -f ./psql-script.sql -U postgres -d somedb -h remote-host.com
The only difference is whether the -f is "at the front" or "at the end" of the "generated" command which is actually sent to the exec() function. In reality, from what the BASH maintainer has said, the first script is a bit like:
file=$(mktemp) # generate a temporary file name
{ cat <<EOT
select * from table;
EOT
} >${file}
psql -U postgres -d somedb -h remote-host.com -f ${file}
It just that the HERE document doesn't actually create the ${file} variable. I have NO idea how other shell implement HERE documents.
However, in the second case, the "magic" first line causes psql, at present, to report an error and abort. This is why I'd like to modify how the file referenced via the -f argument is processed. That is, the first line of any file referenced & executed via the -f argument will be ignored if and only if it starts with a shebang (#!). If the first line of the file does not start with a shebang, it is processed normally as are all subsequent lines.
If I get the energy & time, I'll give a look at the actual source. If it is within my, admitted limited, ability to generate a patch to implement what I'm thinking of, I'll post it over on the development forum.
We all have skeletons in our closet.
Mine are so old, they have osteoporosis.
Maranatha! <><
John McKown
John McKown
Greetings,
* John McKown (john.archie.mckown@gmail.com) wrote:
> Again, this is just a discussion point. And I'm quite willing to admit
> defeat if most people don't think that it is worth the effort.
For my 2c, at least, I do think it'd be kind of neat to have, but we'd
need a fool-proof way to realize that's how we're being called and,
ideally, that would be something we could detect without having to have
special flags for psql which anyone writing such a script would have to
be aware of.
I probably should have taken a good look at how the psql code actually handles the "-f" argument. Unfortunately, I've been very "time poor" recently due to some medical work which, along with "real" work, keeps me away from the house for about 15 hrs a day, except for weekends which I used to try to recover.
Do you know if there's a way to detect that we're being called this
way..?
Thanks!
Stephen
We all have skeletons in our closet.
Mine are so old, they have osteoporosis.
Maranatha! <><
John McKown
John McKown
However, in the second case, the "magic" first line causes psql, at present, to report an error and abort. This is why I'd like to modify how the file referenced via the -f argument is processed. That is, the first line of any file referenced & executed via the -f argument will be ignored if and only if it starts with a shebang (#!). If the first line of the file does not start with a shebang, it is processed normally as are all subsequent lines.
Don't forget the \i and \ir meta commands.
David J.
Stephen Frost <sfrost@snowman.net> writes: > Greetings, > * John McKown (john.archie.mckown@gmail.com) wrote: >> Again, this is just a discussion point. And I'm quite willing to admit >> defeat if most people don't think that it is worth the effort. > For my 2c, at least, I do think it'd be kind of neat to have, but we'd > need a fool-proof way to realize that's how we're being called and, > ideally, that would be something we could detect without having to have > special flags for psql which anyone writing such a script would have to > be aware of. > Do you know if there's a way to detect that we're being called this > way..? Actually, I'd say that's exactly what *not* to do. It's generally important that a script act the same whether or not it was invoked with a shortcut. For instance, just because you had one of these magic lines at the top, you'd not want it to not work if called via \include. So my take on it is that this is a request to ignore the first line if it starts with "#!" (and yes, I'd insist on checking both characters). I do not see that as noticeably more dangerous than the existing kluge to ignore a UTF BOM character at the start of the file. The concerns about whether psql would get invoked with a desirable set of options if you tried to do this seem more worrisome, but if that does work out usefully, I think this is a reasonable proposal. regards, tom lane
On Wed, 9 May 2018 at 04:00, John McKown <john.archie.mckown@gmail.com> wrote: > To me this looks similar to a UNIX shell script. Now, going sideways for a second, if someone wanted to create a "self contained" awk script. It would look something like: > #!/bin/awk -f > ... awk code ... I have found it convenient when Lisp implementations (that use ; as the comment indicator, and where # tends to mean something quite different) have provided something like this. I'd quite like it if I could start a script with #!psql or similar and have it be, yes, indeed, directly executable via psql. There are several complications that leap out at me... 1. Would want to run the apropos psql It's a common thing in Perl to have an idiom where a suitable script prefix goes off and finds the appropriate Perl instance. It's possible to have multiple versions of psql, it would be kinda nice if the script could choose the right one to run. But that could easily be trying too hard. 2. Specifying database connection parameters Making use of PGDATABASE and other environment parameters is well and good; it would also be a fine thing for something in the first line to be able to specify values. Thus, something like... #!psql -d postgresql://postgres@localhost:5432/some_db_name The not-so-nice is that perhaps that first line provides some defaults, and one could override slices of that via PGDATABASE/PGHOST/PGUSER/... What overrides what is an excellent question, and perhaps a horrible bikeshedding debate. 3. Nesting is a funny thing; I'm not sure if \i should simply ignore the first line if it begins with #!, or if it should become a "subshell" perhaps in another psql session. In effect, is \i like a C #include (ergo, perhaps strip leading line beginning with #!), or is it a separate psql session, with separate connection/transaction? I imagine it's more like #include, but both seem potentially useful. There's certainly a danger of bikeshedding. -- When confronted by a difficult problem, solve it by reducing it to the question, "How would the Lone Ranger handle this?"
On Wed, 9 May 2018 at 04:00, John McKown <john.archie.mckown@gmail.com>
wrote:
> To me this looks similar to a UNIX shell script. Now, going sideways for
a second, if someone wanted to create a "self contained" awk script. It
would look something like:
> #!/bin/awk -f
> ... awk code ...
I have found it convenient when Lisp implementations (that use ; as the
comment indicator, and where # tends to mean something quite different)
have provided something like this.
I'd quite like it if I could start a script with
#!psql
or similar and have it be, yes, indeed, directly executable via psql.
There are several complications that leap out at me...
Frankly, none of those are complications. For all the areas of concern you described the decision for desired behavior has already been made. They seem to limit the extent to which a shebang would be useful...
1. O/S PATH determines what a bare "psql" invocation finds
2. arguments override environment variables
3. \i means include, no transaction semantics
And trying harder for #1 doesn't seem worthwhile - or maybe is a feature in its own right. Something like:
--@ client-version >= 9.6
--@ server-version >= 9.4
If those comments are found in a file psql is evaluating it should error out if the condition doesn't match. That should apply regardless of invocation method.
David J.
On Wed, 2018-05-09 at 08:36 -0500, John McKown wrote: > On Wed, May 9, 2018 at 3:05 AM, Pavel Stehule > <pavel.stehule@gmail.com> wrote: > > These languages has defined # as line comment. It is not true for > > SQL. > > Thanks, that looks like a "NO" vote to me. > Not necessarily. There are other languages which don't use "#" for comments, but ignore a first line when it starts with "#" or when you add a specific command line option. -- Jan Claeys
The whole point of "#!" working in shell is that the two-bytes (a) mark the file as executable by a specific shell command and (b) are a shell comment. One fairly simple fix that would make annotating here scripts and the like simpler for shell(ish) execution would be simply ignoring all text from "\n#" to the first "\n", which would allow the #! to function as a comment -- just as it does in the shell. Another way to do it would be adding a '#' command to psql, similar to '\', that accepts a one-line directive and ignores it entirely. This would use the existing framework for detecting the context of '\' as a command, just with a different magic char. -- Steven Lembark 1505 National Ave Workhorse Computing Rockford, IL 61103 lembark@wrkhors.com +1 888 359 3508
On Thu, May 10, 2018 at 4:46 PM, Steven Lembark <lembark@wrkhors.com> wrote: > The whole point of "#!" working in shell is that the two-bytes > (a) mark the file as executable by a specific shell command and > (b) are a shell comment. Shebang is an unix-ism. It is not part of the shell. The shell just execs whatever you tell it to. In a simple way, in unix when a file is marked executable the loader is called to load and execute it. The loader first looks at the start of the file to try to determine what it is ( it does not use the 'extension' for this as MSDOS and friends ). If it is one of the several formats binary formats, like elf or a.out, it understands it loads and executes. If it is the magic sequence "#!" it tries to search for another executable ( NOT A SHELL COMMAND, this works even if you zap all the shells in your computer ) and recursively invokes it ( this is done by execve(2) in my linux machine, and described in its manual page ). No shell involved: folarte:~/tmp$ type cat cat is /bin/cat folarte:~/tmp$ echo -e '#!/bin/cat\nHello there\nGood bye then' > xx folarte:~/tmp$ chmod +x xx folarte:~/tmp$ ./xx #!/bin/cat Hello there Good bye then folarte:~/tmp$ perl -e 'exec("./xx")' #!/bin/cat Hello there Good bye then You can try other ways to call execv*, nothing magical in the perl way, just avoiding the shell ( which has an exec builtin command, with different behaviour from typing a command name, which does fork, wait in the parent, execv in the child ). Francisco Olarte.