Thread: Re: Variable substitution in psql backtick expansion

Re: Variable substitution in psql backtick expansion

From
Fabien COELHO
Date:
Bonjour Daniel,

> I think that users would rather have the option to just put
> an SQL expression behind \if.

Note that this is already available indirectly, as show in the 
documentation.
  SELECT some-boolean-expression AS okay \gset  \if :okay    \echo boolean expression was true  \else    \echo boolean
expressionwas false  \endif
 

-- 
Fabien.



Re: Variable substitution in psql backtick expansion

From
Pavel Stehule
Date:


2017-04-02 8:53 GMT+02:00 Fabien COELHO <coelho@cri.ensmp.fr>:

Bonjour Daniel,

I think that users would rather have the option to just put
an SQL expression behind \if.

Note that this is already available indirectly, as show in the documentation.

  SELECT some-boolean-expression AS okay \gset
  \if :okay
    \echo boolean expression was true
  \else
    \echo boolean expression was false
  \endif


For this case can be nice to have function that returns server version as number

some like version_num() .. 10000

comments?

Regards

Pavel
 
--
Fabien.



--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Re: Variable substitution in psql backtick expansion

From
Fabien COELHO
Date:
Hello Pavel,

> For this case can be nice to have function that returns server version 
> as number some like version_num() .. 10000

The server side information can be queried:

   SELECT current_setting(‘server_version_num’)
     AS server_version_num \gset
   -- 90602

However client side is not so clean:

   \echo :VERSION
   PostgreSQL 10devel on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609, 64-bit

Probably some :VERSION_NUM would make some sense. See attached PoC patch.
Would it make sense?

-- 
Fabien.
Attachment

Re: Variable substitution in psql backtick expansion

From
Fabien COELHO
Date:
> For this case can be nice to have function that returns server version as
> number
>
> some like version_num() .. 10000

Another possible trick to get out of a script which does not support \if,
relying on the fact that the unexpected command is simply ignored:
  -- exit version below 10  \if false    \echo 'script requires version 10 or better'    \q  \endif

Also possible but less informative on errors:
  \set ON_ERROR_STOP on  \if false \endif

-- 
Fabien.



Re: Variable substitution in psql backtick expansion

From
Pavel Stehule
Date:


2017-04-02 9:45 GMT+02:00 Fabien COELHO <coelho@cri.ensmp.fr>:

Hello Pavel,

For this case can be nice to have function that returns server version as number some like version_num() .. 10000

The server side information can be queried:

  SELECT current_setting(‘server_version_num’)
    AS server_version_num \gset
  -- 90602

However client side is not so clean:

  \echo :VERSION
  PostgreSQL 10devel on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609, 64-bit

Probably some :VERSION_NUM would make some sense. See attached PoC patch.
Would it make sense?

It has sense

Pavel 


--
Fabien.

Re: Variable substitution in psql backtick expansion

From
Pavel Stehule
Date:


2017-04-02 9:45 GMT+02:00 Fabien COELHO <coelho@cri.ensmp.fr>:

Hello Pavel,

For this case can be nice to have function that returns server version as number some like version_num() .. 10000

The server side information can be queried:

  SELECT current_setting(‘server_version_num’)
    AS server_version_num \gset
  -- 90602

However client side is not so clean:

  \echo :VERSION
  PostgreSQL 10devel on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609, 64-bit

Probably some :VERSION_NUM would make some sense. See attached PoC patch.
Would it make sense?

Maybe better name for you CLIENT_VERSION_NUM

Can be SERVER_VERSION_NUM taken from connection info?

Regards

Pavel
 


--
Fabien.

Re: Variable substitution in psql backtick expansion

From
Fabien COELHO
Date:
Hello Pavel,

>>   \echo :VERSION
>>   PostgreSQL 10devel on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu
>> 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609, 64-bit
>>
>> Probably some :VERSION_NUM would make some sense. See attached PoC patch.
>> Would it make sense?
>
> Maybe better name for you CLIENT_VERSION_NUM

If it was starting from nothing I would tend to agree with you, but there 
is already an existing :VERSION variable, so it seemed logical to keep on 
and create variants with the same prefix.

> Can be SERVER_VERSION_NUM taken from connection info?

Probably it could. It seems a little less straightforward than defining a 
client-side string at compile time. The information is displayed when the 
connection is established, so the information is there somewhere.
 psql (10devel, server 9.6.2)

-- 
Fabien.



Re: Variable substitution in psql backtick expansion

From
Fabien COELHO
Date:
> Can be SERVER_VERSION_NUM taken from connection info?

Here is a version with that, quite easy as well as the information was 
already there for other checks.

I have not updated "help.c" because the initial VERSION was not presented 
there in the first place.

-- 
Fabien.
Attachment

Re: Variable substitution in psql backtick expansion

From
Fabien COELHO
Date:
>> Can be SERVER_VERSION_NUM taken from connection info?
>
> Here is a version with that, quite easy as well as the information was 
> already there for other checks.
>
> I have not updated "help.c" because the initial VERSION was not presented 
> there in the first place.

Here is a v3 to fix the documentation example. Sorry for the noise.

-- 
Fabien.
Attachment

Re: Variable substitution in psql backtick expansion

From
"Daniel Verite"
Date:
    Fabien COELHO wrote:

> Note that this is already available indirectly, as show in the
> documentation.
>
>   SELECT some-boolean-expression AS okay \gset
>   \if :okay
>     \echo boolean expression was true
>   \else
>     \echo boolean expression was false
>   \endif

Yes, the question was whether we leave it as that for v10,
or if it's worth a last-minute improvement for usability,
assuming it's doable, similarly to what $subject does to backtick
expansion for external evaluation.


Best regards,
--
Daniel Vérité
PostgreSQL-powered mailer: http://www.manitou-mail.org
Twitter: @DanielVerite



Re: Variable substitution in psql backtick expansion

From
Fabien COELHO
Date:
Hello Daniel,

>>   SELECT some-boolean-expression AS okay \gset
>>   \if :okay
>
> Yes, the question was whether we leave it as that for v10,
> or if it's worth a last-minute improvement for usability,
> assuming it's doable, similarly to what $subject does to backtick
> expansion for external evaluation.

My 0.02 € about server-side expressions: ISTM that there is nothing 
obvious/easy to do to include these:
 - how would it work, both with \set ... and \if ...?
 - should it be just simple expressions or may it allow complex   queries?
 - how would error detection and handling work from a script?
 - should it have some kind of continuation, as expressions are   likely to be longer than a constant?
 - how would they interact with possible client-side expressions?
   (on this point, I think that client-side is NOT needed for "psql".    It makes sense for "pgbench" in a benchmarking
contextwhere the    client must interact with the server in some special meaningful    way, but for simple scripting
theperformance requirement and    logic is not the same, so server-side could be enough).
 

Basically quite a few questions which would not find an instantaneous 
answer and associated patch.

However I agree with you that there may be minimal usability things to add 
before 10, similar to Tom's backtick variable substitution.

Having some access to the client version as suggested by Pavel looks like 
a good idea for the kind of script which may rely on conditionals...

Maybe other things, not sure what, though. Maybe other client settings
could be exported as variables, but the version looks like the main which 
is currently missing.

Maybe a way to know what is the client current status? eg in transaction,
transaction has aborted, things like that?

-- 
Fabien.

Re: Variable substitution in psql backtick expansion

From
Pavel Stehule
Date:


2017-04-02 13:13 GMT+02:00 Fabien COELHO <coelho@cri.ensmp.fr>:

Hello Pavel,

  \echo :VERSION
  PostgreSQL 10devel on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu
5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609, 64-bit

Probably some :VERSION_NUM would make some sense. See attached PoC patch.
Would it make sense?

Maybe better name for you CLIENT_VERSION_NUM

If it was starting from nothing I would tend to agree with you, but there is already an existing :VERSION variable, so it seemed logical to keep on and create variants with the same prefix.

you have true - so VERSION_NUM should be client side version
 


Can be SERVER_VERSION_NUM taken from connection info?

Probably it could. It seems a little less straightforward than defining a client-side string at compile time. The information is displayed when the connection is established, so the information is there somewhere.

It is not too hard

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 94a3cfce90..d1ae81646f 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -3320,16 +3320,21 @@ checkWin32Codepage(void)
 void
 SyncVariables(void)
 {
+   char        buffer[100];
+
    /* get stuff from connection */
    pset.encoding = PQclientEncoding(pset.db);
    pset.popt.topt.encoding = pset.encoding;
    pset.sversion = PQserverVersion(pset.db);
 
+   snprintf(buffer, 100, "%d", pset.sversion);
+
    SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
    SetVariable(pset.vars, "USER", PQuser(pset.db));
    SetVariable(pset.vars, "HOST", PQhost(pset.db));
    SetVariable(pset.vars, "PORT", PQport(pset.db));
    SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
+   SetVariable(pset.vars, "SVERSION_NUM", buffer);
 
    /* send stuff to it, too */
    PQsetErrorVerbosity(pset.db, pset.verbosity);

Regards

Pavel
 

 psql (10devel, server 9.6.2)

--
Fabien.

Re: Variable substitution in psql backtick expansion

From
Corey Huinker
Date:
On Sun, Apr 2, 2017 at 11:16 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:


2017-04-02 13:13 GMT+02:00 Fabien COELHO <coelho@cri.ensmp.fr>:

Hello Pavel,

  \echo :VERSION
  PostgreSQL 10devel on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu
5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609, 64-bit

Probably some :VERSION_NUM would make some sense. See attached PoC patch.
Would it make sense?

Maybe better name for you CLIENT_VERSION_NUM

If it was starting from nothing I would tend to agree with you, but there is already an existing :VERSION variable, so it seemed logical to keep on and create variants with the same prefix.

you have true - so VERSION_NUM should be client side version
 


Can be SERVER_VERSION_NUM taken from connection info?

Probably it could. It seems a little less straightforward than defining a client-side string at compile time. The information is displayed when the connection is established, so the information is there somewhere.

It is not too hard

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 94a3cfce90..d1ae81646f 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -3320,16 +3320,21 @@ checkWin32Codepage(void)
 void
 SyncVariables(void)
 {
+   char        buffer[100];
+
    /* get stuff from connection */
    pset.encoding = PQclientEncoding(pset.db);
    pset.popt.topt.encoding = pset.encoding;
    pset.sversion = PQserverVersion(pset.db);
 
+   snprintf(buffer, 100, "%d", pset.sversion);
+
    SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
    SetVariable(pset.vars, "USER", PQuser(pset.db));
    SetVariable(pset.vars, "HOST", PQhost(pset.db));
    SetVariable(pset.vars, "PORT", PQport(pset.db));
    SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
+   SetVariable(pset.vars, "SVERSION_NUM", buffer);
 
    /* send stuff to it, too */
    PQsetErrorVerbosity(pset.db, pset.verbosity);

Regards

Pavel
 

 psql (10devel, server 9.6.2)

--
Fabien.



I'm anxious to help with these patches, but they seem a bit of a moving target. Happy to jump in and review as soon as we've settled on what should be done.


Re: Variable substitution in psql backtick expansion

From
Fabien COELHO
Date:
Hello Corey,

> I'm anxious to help with these patches, but they seem a bit of a moving
> target. Happy to jump in and review as soon as we've settled on what should
> be done.

The "v3" I sent basically adds both client & server version numbers in 
client-side variables, basically same code as suggested by Pavel for the 
server version, and some documentation.

The questions are:
 - which version should be provided (10.0 100000 ...)
 - how should they be named?
   In v3 there is VERSION{,_NAME,_NUM} for client and   SERVER_VERSION_{NUM,NAME} or SVERSION_NUM suggested   by Pavel
forserver.
 
 - how desirable/useful is it to have this in 10?
   Despite that this was not submitted in the relevant CF...   I created an entry in the July one, but this is for 11.

-- 
Fabien.



Re: Variable substitution in psql backtick expansion

From
Corey Huinker
Date:
On Sun, Apr 2, 2017 at 12:29 PM, Fabien COELHO <coelho@cri.ensmp.fr> wrote:

Hello Corey,

I'm anxious to help with these patches, but they seem a bit of a moving
target. Happy to jump in and review as soon as we've settled on what should
be done.

The "v3" I sent basically adds both client & server version numbers in client-side variables, basically same code as suggested by Pavel for the server version, and some documentation.

patch applies via patch -p1

Works as advertised.
# \echo SERVER_VERSION_NAME
SERVER_VERSION_NAME
# \echo :SERVER_VERSION_NAME
10.0
# \echo :SERVER_VERSION_NUM
100000
# \echo :VERSION_NUM
100000

The new documentation is clear, and accurately reflects current name style.

Looking at #define STRINGIFY(), I got curious where else STRINGIFY was used:

$ git grep STRINGIFY
src/bin/psql/startup.c:#define STRINGIFY2(symbol) #symbol
src/bin/psql/startup.c:#define STRINGIFY(symbol) STRINGIFY2(symbol)
src/bin/psql/startup.c: SetVariable(pset.vars, "VERSION_NUM", STRINGIFY(PG_VERSION_NUM));
src/tools/msvc/Solution.pm:s{PG_VERSION_STR "[^"]+"}{__STRINGIFY(x) #x\n#define __STRINGIFY2(z) __STRINGIFY(z)\n#define PG_VERSION_STR "PostgreSQL $self->{strver}$extraver, compiled by Visual C++ build " __STRINGIFY2(_MSC_VER) ", $bits-bit"};

Without digging too deep, it seems like the redefinition wouldn't be harmful, but it might make sense to not use the name STRINGIFY() if only to avoid confusion with Solution.pm.



The questions are:

 - which version should be provided (10.0 100000 ...)

A fixed length string without decimals seems best for the multitude of tools that will want to manipulate that data.

 
 - how should they be named?

   In v3 there is VERSION{,_NAME,_NUM} for client and
   SERVER_VERSION_{NUM,NAME} or SVERSION_NUM suggested
   by Pavel for server.

SERVER_VERSION_* is good.
VERSION_* is ok. Would CLIENT_VERSION_* or PSQL_VERSION_* be better?
 
 - how desirable/useful is it to have this in 10?

Extensions and extension-ish packages will love the _NUM vars. The sooner the better.

There's a lesser need for the _NAME vars.

Re: Variable substitution in psql backtick expansion

From
Tom Lane
Date:
Corey Huinker <corey.huinker@gmail.com> writes:
> Looking at #define STRINGIFY(), I got curious where else STRINGIFY was used:
> Without digging too deep, it seems like the redefinition wouldn't be
> harmful, but it might make sense to not use the name STRINGIFY() if only to
> avoid confusion with Solution.pm.

More to the point, we already have that.  See c.h:

#define CppAsString(identifier) #identifier
#define CppAsString2(x)            CppAsString(x)
        regards, tom lane



Re: Variable substitution in psql backtick expansion

From
Fabien COELHO
Date:
> src/tools/msvc/Solution.pm:s{PG_VERSION_STR "[^"]+"}{__STRINGIFY(x)
> #x\n#define __STRINGIFY2(z) __STRINGIFY(z)\n#define PG_VERSION_STR
> "PostgreSQL $self->{strver}$extraver, compiled by Visual C++ build "
> __STRINGIFY2(_MSC_VER) ", $bits-bit"};

Well, this is the same hack.

> Without digging too deep, it seems like the redefinition wouldn't be
> harmful, but it might make sense to not use the name STRINGIFY() if only to
> avoid confusion with Solution.pm.

It is the usual name for these macro. What would you suggest?

>>  - how desirable/useful is it to have this in 10?
>
> Extensions and extension-ish packages will love the _NUM vars.

Hmmmm. I'm afraid pg extension scripts (for CREATE EXTENSION) are not 
executed through psql, but server side directly, so there is not much 
backslash-command support.

> There's a lesser need for the _NAME vars.

I put them more for error reporting, eg:
  \if :VERSION_NUM < 110000    \echo :VERSION_NAME is not supported, should be at least 11.0    \q  \endif

-- 
Fabien.



Re: Variable substitution in psql backtick expansion

From
Fabien COELHO
Date:
> More to the point, we already have that.  See c.h:
>
> #define CppAsString(identifier) #identifier
> #define CppAsString2(x)            CppAsString(x)

Thanks for the pointer. I grepped for them without success. Here is a v4.

-- 
Fabien
Attachment

Re: Variable substitution in psql backtick expansion

From
Tom Lane
Date:
Fabien COELHO <coelho@cri.ensmp.fr> writes:
>>> - how desirable/useful is it to have this in 10?

>> Extensions and extension-ish packages will love the _NUM vars.

> Hmmmm. I'm afraid pg extension scripts (for CREATE EXTENSION) are not 
> executed through psql, but server side directly, so there is not much 
> backslash-command support.

Yeah.

>> There's a lesser need for the _NAME vars.

> I put them more for error reporting, eg:

>    \if :VERSION_NUM < 110000
>      \echo :VERSION_NAME is not supported, should be at least 11.0
>      \q
>    \endif

I kinda feel like we're getting ahead of ourselves here, in that
the above is not going to do what you want until we have some kind
of expression eval capability built into psql.  You pointed out that
"\if false" can be used to reject pre-v10 psqls, but what about
rejecting v10?  ISTM that if we leave this out until there's something
that can do something useful with it, then something along the lines of

\if false -- pre-v10, complain and die
\endif
\if not defined VERSION_NUM -- pre-v11, complain and die
\endif

would do the trick.  Of course, there are probably other ways to
do that, but my point is that you haven't made a case why we need
to put this in now rather than later.
        regards, tom lane



Re: Variable substitution in psql backtick expansion

From
Fabien COELHO
Date:
Hello Tom,

> about version numbers [...] Of course, there are probably other ways to 
> do that, but my point is that you haven't made a case why we need to put 
> this in now rather than later.

Indeed, I have not. What about having the ability to test for minor 
versions?
  \if false    -- pre 10.0    \q  \endif  SELECT :VERSION_NUM < 100002 AS minor_not_ok \gset  \if :minor_not_ok
\echoscript requires at least pg 10.2    \q  \endif
 

Otherwise it will wait for next CF. Note that the patch is pretty minor 
and straightforward, no need to spend much time on it.

-- 
Fabien.