Thread: psql: add \pset true/false

psql: add \pset true/false

From
Marko Tiikkaja
Date:
Hello hello,

Since the default t/f output for booleans is not very user friendly,
attached is a patch which enables you to do for example the following:

=# \pset true TRUE
Boolean TRUE display is "TRUE".
=# \pset false FALSE
Boolean FALSE display is "FALSE".
=# select true, false;
   bool | bool
------+-------
   TRUE | FALSE
(1 row)


(For anyone reviewing: I didn't touch the parts of describe.c which do
this for nullPrint:

   myopt.nullPrint = NULL;

since I thought it was dubious in the first place, and I don't think we
output booleans in the describe commands.)



.m

Attachment

Re: psql: add \pset true/false

From
Robert Haas
Date:
On Wed, Oct 28, 2015 at 10:03 AM, Marko Tiikkaja <marko@joh.to> wrote:
> Hello hello,
>
> Since the default t/f output for booleans is not very user friendly,
> attached is a patch which enables you to do for example the following:
>
> =# \pset true TRUE
> Boolean TRUE display is "TRUE".
> =# \pset false FALSE
> Boolean FALSE display is "FALSE".
> =# select true, false;
>   bool | bool
> ------+-------
>   TRUE | FALSE
> (1 row)
>
>
> (For anyone reviewing: I didn't touch the parts of describe.c which do this
> for nullPrint:
>
>   myopt.nullPrint = NULL;
>
> since I thought it was dubious in the first place, and I don't think we
> output booleans in the describe commands.)

-0 on this concept from me.  I'm not going to vigorously oppose it, but:

1. You can always do it in the query if you really want it.
2. If you're the sort of person liable to be confused by t/f, you
probably aren't in the target audience for psql anyway.
3. I really don't want to end up with a bunch of features of this type
for a variety of different data types.

But I just work here, and if others feel differently, so be it.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Re: psql: add \pset true/false

From
Greg Stark
Date:
On Wed, Oct 28, 2015 at 10:52 PM, Robert Haas <robertmhaas@gmail.com> wrote:
> 3. I really don't want to end up with a bunch of features of this type
> for a variety of different data types.

We already have \pset null which feels very similar. It's not like 'f'
and 't' are terribly common and probably different from how they
render in whatever driver the user's probably coding to.

On the other hand if their driver isn't mapping booleans to a native
data type and just providing the Postgres text output then then this
is only risking more confusion by presenting the user with a rendering
that's different from what they need to be expecting. IIRC this is the
case for the PHP driver for example.

-- 
greg



Re: psql: add \pset true/false

From
Andres Freund
Date:
On 2015-10-28 23:38:45 +0000, Greg Stark wrote:
> On Wed, Oct 28, 2015 at 10:52 PM, Robert Haas <robertmhaas@gmail.com> wrote:
> > 3. I really don't want to end up with a bunch of features of this type
> > for a variety of different data types.
> 
> We already have \pset null which feels very similar.

It's data type neutral, and there's no representation of NULL that's
definitely discernible from the corresponding string. So I don't see
those being the same.


This seems like opening a can of worms to me. Why not add formatting
options in psql for other data types?

- Andres



Re: psql: add \pset true/false

From
Marko Tiikkaja
Date:
On 10/28/15 11:52 PM, Robert Haas wrote:
> -0 on this concept from me.  I'm not going to vigorously oppose it, but:
>
> 1. You can always do it in the query if you really want it.

True, but not always practical.

> 2. If you're the sort of person liable to be confused by t/f, you
> probably aren't in the target audience for psql anyway.

Really?  The difference between t/f is that the vertical squiggle is 
flipped, THAT'S IT.  Consider:

t t f f f
f t f t f

Saying that I'm not target audience for not being able to see WTF is 
going on above I find offending.

> 3. I really don't want to end up with a bunch of features of this type
> for a variety of different data types.

Fine.  Then let's not add it for a different variety of data types.  But 
boolean is quite essential and it has a really small number of valid 
output values.


.m



Re: psql: add \pset true/false

From
Robert Haas
Date:
On Thu, Oct 29, 2015 at 1:32 AM, Marko Tiikkaja <marko@joh.to> wrote:
>> 2. If you're the sort of person liable to be confused by t/f, you
>> probably aren't in the target audience for psql anyway.
>
> Really?  The difference between t/f is that the vertical squiggle is
> flipped, THAT'S IT.  Consider:
>
> t t f f f
> f t f t f
>
> Saying that I'm not target audience for not being able to see WTF is going
> on above I find offending.

Sorry, no offense intended.  It's really just never happened to me
that I've had a problem with this, and I've been using psql for quite
a few years now.  I do agree that if you have a bunch of values in a
row it's more apt to be confusing than with just one, but they won't
normally be as closely spaced as you have them there, because psql
inserts spacing and borders and column headers are usually more than
one character.

But I don't really want to argue about this.  I respect your opinion,
and I've given you mine, and wherever we end up based on the opinions
of others is OK with me.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Re: psql: add \pset true/false

From
"Daniel Verite"
Date:
    Marko Tiikkaja wrote:

> Since the default t/f output for booleans is not very user friendly,
> attached is a patch which enables you to do for example the following:

Personally I think it would be worth having, but how about
booleans inside ROW() or composite types ?

test=> \pset true 1
Boolean TRUE display is "1".
test=> \pset false 0
Boolean FALSE display is "0".

test #1:

test=> select 't'::bool,'f'::bool;bool | bool
------+------1    | 0

test #2:

test=> select ('t'::bool,'f'::bool); row
-------(t,f)

test #3:

test=> create type abc as (a bool, b bool, c bool);
test=> select (true,false,true)::abc;  row
---------(t,f,t)


I understand that the patch translates t/f only if the output type
has the OID for bool, which is not the case in #2 or #3, but I guess
users would expect #2 to output (1,0) and #3 (1,0,1).


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



Re: psql: add \pset true/false

From
Marko Tiikkaja
Date:
On 10/29/15 11:51 AM, Daniel Verite wrote:
>     Marko Tiikkaja wrote:
>
>> Since the default t/f output for booleans is not very user friendly,
>> attached is a patch which enables you to do for example the following:
>
> Personally I think it would be worth having, but how about
> booleans inside ROW() or composite types ?

There's not enough information sent over to do that in the client.

Note that this works the same way as  \pset null  with  SELECT 
ROW(NULL), so I don't consider it a show stopper for the patch.


.m



Re: psql: add \pset true/false

From
Matthijs van der Vleuten
Date:
On 29 Oct 2015, at 08:50, Robert Haas <<a class="" href="mailto:robertmhaas@gmail.com">robertmhaas@gmail.com</a>>
wrote:<brclass="" /><blockquote class="" type="cite"><br class="" />On Thu, Oct 29, 2015 at 1:32 AM, Marko Tiikkaja
<<aclass="" href="mailto:marko@joh.to">marko@joh.to</a>> wrote:<br class="" /><blockquote class=""
type="cite"><blockquoteclass="" type="cite">2. If you're the sort of person liable to be confused by t/f, you<br
class=""/>probably aren't in the target audience for psql anyway.<br class="" /></blockquote><br class="" />Really?
 Thedifference between t/f is that the vertical squiggle is<br class="" />flipped, THAT'S IT.  Consider:<br class=""
/><brclass="" />t t f f f<br class="" />f t f t f<br class="" /><br class="" />Saying that I'm not target audience for
notbeing able to see WTF is going<br class="" />on above I find offending.<br class="" /></blockquote><br class=""
/>Sorry,no offense intended.  It's really just never happened to me<br class="" />that I've had a problem with this,
andI've been using psql for quite<br class="" />a few years now.  I do agree that if you have a bunch of values in a<br
class=""/>row it's more apt to be confusing than with just one, but they won't<br class="" />normally be as closely
spacedas you have them there, because psql<br class="" />inserts spacing and borders and column headers are usually
morethan<br class="" />one character.</blockquote><br class="" /><div class="">I have had exactly this situation a week
ago.I was testing the output of an algorithm that is supposed to have exactly one true value per input id.</div><div
class=""><brclass="" /></div><div class="">In the first screenshot, psql_true_false_off.png, you see the output of psql
unpatched.Notice how there’s barely any obvious difference between ’t’ and ‘f’. It’s hard to verify that the supposed
outputis correct. There’s also some column with all-false values, I would need to carefully examine all the f and t
charactersto find that.</div><div class=""><br class="" /></div><div class="">In the second screenshot,
psql_true_false_on.png,I applied Marko’s patch and set a colorful emoji character as the display string for true and
false.Now it’s relatively easy to verify that there’s exactly one true value. In addition, it’s hard to miss that the
firstcolumn is always false (for this particular range). I wasn’t looking for that, but this presentation made it
strikinglyobvious. In the first screenshot, it would remain hidden. (Did you notice the two columns there that have all
falsevalues?)</div><div class=""><br class="" /></div><div class="">I’ve been testing Marko’s patch for a few months
now,and I’ve found it helps a lot in recognizing booleans in many contexts.</div><div class=""><br class=""
/></div><divclass=""><img apple-height="yes" apple-inline="yes" apple-width="yes" class="" height="832"
id="D3552283-D39E-4810-8425-B73B5B6136BC"src="cid:CDF92331-5D9B-4473-ABDA-F47E9FAA2330@hitc" width="778" /></div><div
class=""><brclass="" /></div><div class=""><img apple-height="yes" apple-inline="yes" apple-width="yes" class=""
height="832"id="767F0557-0991-4C89-8F97-F9CB1A89D6C7" src="cid:F9813FE9-7841-4D30-BA0B-57D638A44A11@hitc" width="760"
/></div><divclass=""><br class="" /></div> 

Re: psql: add \pset true/false

From
Tom Lane
Date:
Marko Tiikkaja <marko@joh.to> writes:
> On 10/29/15 11:51 AM, Daniel Verite wrote:
>> Personally I think it would be worth having, but how about
>> booleans inside ROW() or composite types ?

> There's not enough information sent over to do that in the client.
> Note that this works the same way as  \pset null  with  SELECT 
> ROW(NULL), so I don't consider it a show stopper for the patch.

The problem with that argument is that \pset null is already a kluge
(but at least a datatype-independent one).  Now you've added a datatype
specific kluge of the same ilk.  It might be useful, it might be short,
but that doesn't make it not a kluge.

The really key argument that hasn't been addressed here is why does such
a behavior belong in psql, rather than elsewhere?  Surely legibility
problems aren't unique to psql users.  Moreover, there are exactly
parallel facilities for other datatypes on the server side: think
DateStyle or bytea_output.  So if you were trying to follow precedent
rather than invent a kluge, you'd have submitted a patch to create a GUC
that changes the output of boolout().

Now, that would create a debate about backwards compatibility and whether
making bool output more readable was worth possibly breaking some
applications, but I do not think this patch should escape scrutiny for the
same issue.  There are plenty of people with shell scripts that look at
psql output, which might get broken by careless use of this \pset.
        regards, tom lane



Re: psql: add \pset true/false

From
Michael Paquier
Date:
On Thu, Oct 29, 2015 at 10:50 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Marko Tiikkaja <marko@joh.to> writes:
>> On 10/29/15 11:51 AM, Daniel Verite wrote:
>>> Personally I think it would be worth having, but how about
>>> booleans inside ROW() or composite types ?
>
>> There's not enough information sent over to do that in the client.
>> Note that this works the same way as  \pset null  with  SELECT
>> ROW(NULL), so I don't consider it a show stopper for the patch.
>
> The problem with that argument is that \pset null is already a kluge
> (but at least a datatype-independent one).  Now you've added a datatype
> specific kluge of the same ilk.  It might be useful, it might be short,
> but that doesn't make it not a kluge.

FWIW, I am -1 on the concept of enforcing output values for particular
datatypes because that's not the job of psql, and it is easy to do
that at query level (no comment about the existing \pset NULL stuff).

+    fprintf(output, _("  true               set the string to be
prined in place of a TRUE value\n"));
+    fprintf(output, _("  false              set the string to be
prined in place of a FALSE value\n"));
s/prined/printed/
-- 
Michael



Re: psql: add \pset true/false

From
Marko Tiikkaja
Date:
On 11/12/15 1:50 PM, Michael Paquier wrote:
> FWIW, I am -1 on the concept of enforcing output values for particular
> datatypes because that's not the job of psql

In my view, the job of psql is to make working with a postgres database 
easy for us human beings.  That means (among other things) formatting 
and aligning query output for readability.  I don't see how reformatting 
unreadable boolean values meant for computers is that big of a stretch.


.m



Re: psql: add \pset true/false

From
Brendan Jurd
Date:
On Fri, 30 Oct 2015 at 00:51 Tom Lane <tgl@sss.pgh.pa.us> wrote:
The really key argument that hasn't been addressed here is why does such
a behavior belong in psql, rather than elsewhere?  Surely legibility
problems aren't unique to psql users.  Moreover, there are exactly
parallel facilities for other datatypes on the server side: think
DateStyle or bytea_output.  So if you were trying to follow precedent
rather than invent a kluge, you'd have submitted a patch to create a GUC
that changes the output of boolout().

I find Tom's analogy to datestyle and bytea_output convincing.

+1 for a GUC that changes the behaviour of boolout.

And also +1 for doing anything at all to improve on the t/f output.  Those glyphs are way too similar to each other.

I think U+2713 and U+2717 (✓ and ✗) are the obvious choices for a boolean, but if we have a GUC we can set this to taste.

Cheers,
BJ

Re: psql: add \pset true/false

From
Vik Fearing
Date:
On 10/28/2015 10:03 AM, Marko Tiikkaja wrote:
> Hello hello,
> 
> Since the default t/f output for booleans is not very user friendly,
> attached is a patch which enables you to do for example the following:
> 
> =# \pset true TRUE
> Boolean TRUE display is "TRUE".
> =# \pset false FALSE
> Boolean FALSE display is "FALSE".
> =# select true, false;
>   bool | bool
> ------+-------
>   TRUE | FALSE
> (1 row)

I think the battle is already lost, but I'm casting my vote in favor of
this patch anyway.
-- 
Vik Fearing                                          +33 6 46 75 15 36
http://2ndQuadrant.fr     PostgreSQL : Expertise, Formation et Support



Re: psql: add \pset true/false

From
Matthijs van der Vleuten
Date:

On 12 Nov 2015, at 14:21, Brendan Jurd <direvus@gmail.com> wrote:

On Fri, 30 Oct 2015 at 00:51 Tom Lane <tgl@sss.pgh.pa.us> wrote:
The really key argument that hasn't been addressed here is why does such
a behavior belong in psql, rather than elsewhere?  Surely legibility
problems aren't unique to psql users.  Moreover, there are exactly
parallel facilities for other datatypes on the server side: think
DateStyle or bytea_output.  So if you were trying to follow precedent
rather than invent a kluge, you'd have submitted a patch to create a GUC
that changes the output of boolout().

I find Tom's analogy to datestyle and bytea_output convincing.

+1 for a GUC that changes the behaviour of boolout.

-1 for changing boolout(). It will break anything that receives boolean values from the server. How a client is going to display values (of any type) is logic that should belong in the client, not in the protocol.

Re: psql: add \pset true/false

From
Vik Fearing
Date:
On 11/12/2015 05:41 PM, Matthijs van der Vleuten wrote:
> 
>> On 12 Nov 2015, at 14:21, Brendan Jurd <direvus@gmail.com> wrote:
>>
>> On Fri, 30 Oct 2015 at 00:51 Tom Lane <tgl@sss.pgh.pa.us <mailto:tgl@sss.pgh.pa.us>> wrote:
>> The really key argument that hasn't been addressed here is why does such
>> a behavior belong in psql, rather than elsewhere?  Surely legibility
>> problems aren't unique to psql users.  Moreover, there are exactly
>> parallel facilities for other datatypes on the server side: think
>> DateStyle or bytea_output.  So if you were trying to follow precedent
>> rather than invent a kluge, you'd have submitted a patch to create a GUC
>> that changes the output of boolout().
>>
>> I find Tom's analogy to datestyle and bytea_output convincing.
>>
>> +1 for a GUC that changes the behaviour of boolout. 
> 
> -1 for changing boolout(). It will break anything that receives boolean values from the server. How a client is going
todisplay values (of any type) is logic that should belong in the client, not in the protocol.
 

I fully agree.  This is something I feel should happen in the client.
-- 
Vik Fearing                                          +33 6 46 75 15 36
http://2ndQuadrant.fr     PostgreSQL : Expertise, Formation et Support



Re: psql: add \pset true/false

From
Pavel Stehule
Date:


2015-11-12 17:41 GMT+01:00 Matthijs van der Vleuten <matthijs@zr40.nl>:

On 12 Nov 2015, at 14:21, Brendan Jurd <direvus@gmail.com> wrote:

On Fri, 30 Oct 2015 at 00:51 Tom Lane <tgl@sss.pgh.pa.us> wrote:
The really key argument that hasn't been addressed here is why does such
a behavior belong in psql, rather than elsewhere?  Surely legibility
problems aren't unique to psql users.  Moreover, there are exactly
parallel facilities for other datatypes on the server side: think
DateStyle or bytea_output.  So if you were trying to follow precedent
rather than invent a kluge, you'd have submitted a patch to create a GUC
that changes the output of boolout().

I find Tom's analogy to datestyle and bytea_output convincing.

+1 for a GUC that changes the behaviour of boolout.

-1 for changing boolout(). It will break anything that receives boolean values from the server. How a client is going to display values (of any type) is logic that should belong in the client, not in the protocol.

This is not fully valid, because transformation from binary to text is processed on server side. And client side transformation is easy only for scalar values.

Regards

Pavel

Re: psql: add \pset true/false

From
"Daniel Verite"
Date:
    Matthijs van der Vleuten wrote:

> -1 for changing boolout(). It will break anything that receives
> boolean values from the server.

Not if the default output is still 't' or 'f' like now.
Nobody seems to suggest a gratuitous compatibility break.

>  How a client is going to display values (of any
> type) is logic that should belong in the client, not in the protocol.

Maybe in general, but consider two problems here:

#1: postgres type extensibility implies that clients
display values from types they know nothing about.
It makes sense that they just use the text representation
that comes from the server, unless they have a specific
reason not to.

#2: in the case of built-in types, like boolean, it's not sufficient
to change how the base type gets displayed.
With Marko's patch, array[true,false]  is still displayed as {t,f}
when setting aternatives through the proposed \pset
feature. Same problem inside composite types as mentioned
upthread.

The issue with the patch's approach is that it falls short of
identifying bools in all situations, so the results are inconsistent.
Solving that in psql is hard or possibly irrealistic, because
the reliance on the text representation for complex types goes deep.

By contrast, making the server-side representation configurable seems
easier. Plus it might be of interest for other consumers of resultsets,
outside of psql.

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



Re: psql: add \pset true/false

From
"David G. Johnston"
Date:
On Thu, Oct 29, 2015 at 5:28 AM, Matthijs van der Vleuten <matthijs@zr40.nl> wrote:
I have had exactly this situation a week ago. I was testing the output of an algorithm that is supposed to have exactly one true value per input id.

​If this is particularly important I would add something like (and(col1, col2, col3, ...) = true) and/or NULLIF((not(col1)::int + not(col2)::int ..., 0) to the grid and check/test those instead of visually scanning the output.

​If the pretty presentation is destined for final output I'd say you really want to output text and write a function so that the logic is embedded in the query and not a side-effect of a specific environment.

David J.​


Re: psql: add \pset true/false

From
"David G. Johnston"
Date:
On Thu, Oct 29, 2015 at 6:50 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
Marko Tiikkaja <marko@joh.to> writes:
> On 10/29/15 11:51 AM, Daniel Verite wrote:
>> Personally I think it would be worth having, but how about
>> booleans inside ROW() or composite types ?

> There's not enough information sent over to do that in the client.
> Note that this works the same way as  \pset null  with  SELECT
> ROW(NULL), so I don't consider it a show stopper for the patch.

The problem with that argument is that \pset null is already a kluge
(but at least a datatype-independent one).  Now you've added a datatype
specific kluge of the same ilk.  It might be useful, it might be short,
but that doesn't make it not a kluge.

The really key argument that hasn't been addressed here is why does such
a behavior belong in psql, rather than elsewhere?  Surely legibility
problems aren't unique to psql users.  Moreover, there are exactly
parallel facilities for other datatypes on the server side: think
DateStyle

​Which provides a finite set of possible values.
 
or bytea_output. 

​Wasn't this added mostly for performance as opposed to dealing with "locale/style" considerations?​

So if you were trying to follow precedent
rather than invent a kluge, you'd have submitted a patch to create a GUC
that changes the output of boolout().


​I'm leaning toward doing this in the client if its offered at all.  An unobtrusive usability enhancement - even if limited to non-embedded situations - that seems like little effort for a measurable gain.

​David J.

Re: psql: add \pset true/false

From
"David G. Johnston"
Date:
On Thu, Nov 12, 2015 at 1:04 PM, David G. Johnston <david.g.johnston@gmail.com> wrote:
On Thu, Oct 29, 2015 at 6:50 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
Marko Tiikkaja <marko@joh.to> writes:
> On 10/29/15 11:51 AM, Daniel Verite wrote:
>> Personally I think it would be worth having, but how about
>> booleans inside ROW() or composite types ?

> There's not enough information sent over to do that in the client.
> Note that this works the same way as  \pset null  with  SELECT
> ROW(NULL), so I don't consider it a show stopper for the patch.

The problem with that argument is that \pset null is already a kluge
(but at least a datatype-independent one).  Now you've added a datatype
specific kluge of the same ilk.  It might be useful, it might be short,
but that doesn't make it not a kluge.

The really key argument that hasn't been addressed here is why does such
a behavior belong in psql, rather than elsewhere?  Surely legibility
problems aren't unique to psql users.  Moreover, there are exactly
parallel facilities for other datatypes on the server side: think
DateStyle

​Which provides a finite set of possible values.
 
or bytea_output. 

​Wasn't this added mostly for performance as opposed to dealing with "locale/style" considerations?​

So if you were trying to follow precedent
rather than invent a kluge, you'd have submitted a patch to create a GUC
that changes the output of boolout().


​I'm leaning toward doing this in the client if its offered at all.  An unobtrusive usability enhancement - even if limited to non-embedded situations - that seems like little effort for a measurable gain.


​That said whatever is done really wants to be able to interact with at least "psql \copy" but probably "SQL COPY" as well...again even if just non-composite outputs.

David J.​
 

Re: psql: add \pset true/false

From
Peter Eisentraut
Date:
On 10/29/15 9:50 AM, Tom Lane wrote:
> The really key argument that hasn't been addressed here is why does such
> a behavior belong in psql, rather than elsewhere?

Because it is the job of the client to mangle the data so that it suits
the purposes of the client.  What comes over the wire is part of the
protocol, not part of the client display.  Language drivers do this sort
of mangling all the time.

> Surely legibility problems aren't unique to psql users.

But the way to deal with it is specific to psql.  In a graphical
environment you might want a checkbox instead, say.  Different clients
will have different requirements and preferences.

> Moreover, there are exactly
> parallel facilities for other datatypes on the server side: think
> DateStyle or bytea_output.

Surely DateStyle is legacy, and bytea_output was actually a performance
feature.  And clients will still mangle either type into their own formats.

Plus we already have \pset numericlocale as a similar feature in psql.




Re: psql: add \pset true/false

From
Tom Lane
Date:
Peter Eisentraut <peter_e@gmx.net> writes:
> Plus we already have \pset numericlocale as a similar feature in psql.

But \pset numericlocale is also a crock.  It doesn't affect COPY output
for instance, and its ability to identify which data types it should apply
to is really shaky.  And it's virtually unused, as demonstrated by the
fact that serious bugs in it went undetected for many years (cf 4778a0bda,
77130fc14).  That's a really poor advertisement for the usefulness of the
proposed feature.
        regards, tom lane



Re: psql: add \pset true/false

From
Jim Nasby
Date:
On 11/12/15 3:09 PM, Tom Lane wrote:
> Peter Eisentraut <peter_e@gmx.net> writes:
>> Plus we already have \pset numericlocale as a similar feature in psql.
>
> But \pset numericlocale is also a crock.  It doesn't affect COPY output
> for instance, and its ability to identify which data types it should apply
> to is really shaky.  And it's virtually unused, as demonstrated by the
> fact that serious bugs in it went undetected for many years (cf 4778a0bda,
> 77130fc14).  That's a really poor advertisement for the usefulness of the
> proposed feature.

My $0.02 is that something that's type-specific belongs with the type, 
not with clients.

As to the argument about displaying a check or an X, why should that 
capability only exist for boolean types? For example, why not allow psql 
to convert a numeric value into a bar of varying sizes? I've frequently 
emulated that with something like SELECT repeat( '*', blah * 30 / 
max_of_blah ). I'm sure there's other examples people could think of.
-- 
Jim Nasby, Data Architect, Blue Treble Consulting, Austin TX
Experts in Analytics, Data Architecture and PostgreSQL
Data in Trouble? Get it in Treble! http://BlueTreble.com



Re: psql: add \pset true/false

From
Peter Eisentraut
Date:
On 11/12/15 4:09 PM, Tom Lane wrote:
> Peter Eisentraut <peter_e@gmx.net> writes:
>> Plus we already have \pset numericlocale as a similar feature in psql.
> 
> But \pset numericlocale is also a crock.  It doesn't affect COPY output
> for instance, and its ability to identify which data types it should apply
> to is really shaky.  And it's virtually unused, as demonstrated by the
> fact that serious bugs in it went undetected for many years (cf 4778a0bda,
> 77130fc14).  That's a really poor advertisement for the usefulness of the
> proposed feature.

Just because people don't find much use for a feature doesn't mean it's
wrong in principle.

Clearly, people occasionally want to change how a data type displays in
psql.  We could implement this in the server.  But then we put a burden
on all non-psql clients to begin all their connections with a growing
number of RESET foo_display calls, and that's not very efficient.  I
think it's up to each client to figure out how to display stuff and to
customize it if necessary.



Re: psql: add \pset true/false

From
Peter Eisentraut
Date:
On 11/15/15 3:20 PM, Jim Nasby wrote:
> As to the argument about displaying a check or an X, why should that
> capability only exist for boolean types? For example, why not allow psql
> to convert a numeric value into a bar of varying sizes? I've frequently
> emulated that with something like SELECT repeat( '*', blah * 30 /
> max_of_blah ). I'm sure there's other examples people could think of.

Well, why not?  The question there is only how many marginal features
you want to stuff into psql, not whether it's the right place to stuff them.



Re: psql: add \pset true/false

From
Peter Geoghegan
Date:
On Thu, Nov 12, 2015 at 1:09 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Peter Eisentraut <peter_e@gmx.net> writes:
>> Plus we already have \pset numericlocale as a similar feature in psql.
>
> But \pset numericlocale is also a crock.  It doesn't affect COPY output
> for instance, and its ability to identify which data types it should apply
> to is really shaky.  And it's virtually unused, as demonstrated by the
> fact that serious bugs in it went undetected for many years (cf 4778a0bda,
> 77130fc14).  That's a really poor advertisement for the usefulness of the
> proposed feature.

FWIW, I didn't realize that we had "\pset numericlocale" until about a
year ago. I now use it all the time, and find it very useful.

-- 
Peter Geoghegan



Re: psql: add \pset true/false

From
Michael Paquier
Date:
On Mon, Nov 16, 2015 at 10:43 AM, Peter Geoghegan <pg@heroku.com> wrote:
> On Thu, Nov 12, 2015 at 1:09 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> Peter Eisentraut <peter_e@gmx.net> writes:
>>> Plus we already have \pset numericlocale as a similar feature in psql.
>>
>> But \pset numericlocale is also a crock.  It doesn't affect COPY output
>> for instance, and its ability to identify which data types it should apply
>> to is really shaky.  And it's virtually unused, as demonstrated by the
>> fact that serious bugs in it went undetected for many years (cf 4778a0bda,
>> 77130fc14).  That's a really poor advertisement for the usefulness of the
>> proposed feature.
>
> FWIW, I didn't realize that we had "\pset numericlocale" until about a
> year ago. I now use it all the time, and find it very useful.

So, looking at this thread, here is the current status:
- Tom Lane: -1
- Michael Paquier: -1
- Peter Geoghegan: +1?
- Peter Eisentraut: +1
- the author: surely +1.
Any other opinions? Feel free to correct this list if needed, and then
let's try to move on on a consensus if need be to decide the destiny
of this patch.
Regards,
-- 
Michael



Re: psql: add \pset true/false

From
"Daniel Verite"
Date:
    Michael Paquier wrote:

> So, looking at this thread, here is the current status:
> - Tom Lane: -1
> - Michael Paquier: -1
> - Peter Geoghegan: +1?
> - Peter Eisentraut: +1
> - the author: surely +1.
> Any other opinions? Feel free to correct this list if needed, and then
> let's try to move on on a consensus if need be to decide the destiny
> of this patch.

In the positive case, the doc should warn somehow about the setting
not being effective when the boolean is inside:
- a field of ROW() type
- an array
- \copy or COPY output
- a field of composite type

(personally this list of exceptions makes me side with the "-1" team).


Other than that,  minor typos to fix (s/prined/printed):

+    fprintf(output, _("  true        set the string to be prined
in place of a TRUE value\n"));
+    fprintf(output, _("  false        set the string to be prined
in place of a FALSE value\n"));



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



Re: psql: add \pset true/false

From
Jim Nasby
Date:
On 11/15/15 7:37 PM, Peter Eisentraut wrote:
> On 11/15/15 3:20 PM, Jim Nasby wrote:
>> As to the argument about displaying a check or an X, why should that
>> capability only exist for boolean types? For example, why not allow psql
>> to convert a numeric value into a bar of varying sizes? I've frequently
>> emulated that with something like SELECT repeat( '*', blah * 30 /
>> max_of_blah ). I'm sure there's other examples people could think of.
>
> Well, why not?  The question there is only how many marginal features
> you want to stuff into psql, not whether it's the right place to stuff them.

I was more thinking it would be nice to be able to temporarily 
over-ride/wrap what an output function is doing. AFAIK that would allow 
this to work everywhere (row(), copy, etc). I don't know of any remotely 
practical way to do that, though.
-- 
Jim Nasby, Data Architect, Blue Treble Consulting, Austin TX
Experts in Analytics, Data Architecture and PostgreSQL
Data in Trouble? Get it in Treble! http://BlueTreble.com



Re: psql: add \pset true/false

From
Michael Paquier
Date:
On Thu, Dec 3, 2015 at 3:10 AM, Jim Nasby <Jim.Nasby@bluetreble.com> wrote:
> On 11/15/15 7:37 PM, Peter Eisentraut wrote:
>>
>> On 11/15/15 3:20 PM, Jim Nasby wrote:
>>>
>>> As to the argument about displaying a check or an X, why should that
>>> capability only exist for boolean types? For example, why not allow psql
>>> to convert a numeric value into a bar of varying sizes? I've frequently
>>> emulated that with something like SELECT repeat( '*', blah * 30 /
>>> max_of_blah ). I'm sure there's other examples people could think of.
>>
>>
>> Well, why not?  The question there is only how many marginal features
>> you want to stuff into psql, not whether it's the right place to stuff
>> them.
>
>
> I was more thinking it would be nice to be able to temporarily
> over-ride/wrap what an output function is doing. AFAIK that would allow this
> to work everywhere (row(), copy, etc). I don't know of any remotely
> practical way to do that, though.

You can basically do that with a custom data type and at worse a
custom GUC, no? It does not seem worth bothering the backend with an
extra layer to manage the output of a data type.
-- 
Michael



Re: psql: add \pset true/false

From
Kyotaro HORIGUCHI
Date:
Hello,

At Thu, 3 Dec 2015 09:24:35 +0900, Michael Paquier <michael.paquier@gmail.com> wrote in
<CAB7nPqTTZXaiVj0_FWvp8hPLLD_yDa8cnS4iuy_HgSOgFz09HA@mail.gmail.com>
> On Thu, Dec 3, 2015 at 3:10 AM, Jim Nasby <Jim.Nasby@bluetreble.com> wrote:
> > On 11/15/15 7:37 PM, Peter Eisentraut wrote:
> > I was more thinking it would be nice to be able to temporarily
> > over-ride/wrap what an output function is doing. AFAIK that would allow this
> > to work everywhere (row(), copy, etc). I don't know of any remotely
> > practical way to do that, though.
> 
> You can basically do that with a custom data type and at worse a
> custom GUC, no? It does not seem worth bothering the backend with an
> extra layer to manage the output of a data type.

How about plugins on psql side? Calling hooked function in
printQuery could do that on psql. Impact on psql itself is
minimized. (Of course code for loading is omitted in the below
but it would also small...)

> --- a/src/bin/psql/print.c
> @@ -3210,6 +3210,10 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
>        else
>        {
>          cell = PQgetvalue(result, r, c);
> +        if (outputplugin)
> +          char *cell = outputplugin(cell, PQftype(result, c),
> +                                    &mustfree);
>          if (cont.aligns[c] == 'r' && opt->topt.numericLocale)
>          {
>            cell = format_numeric_locale(cell);



One problem of this is who wants to do this must write a
program. But someone might write general purpose plugin.


=$ loadlib 'outputhook.so';
=$ select 't'::bool;bool 
------X
(1 row)

=== outputhook.so
char *
outputhook(char *origcell, type, bool *mustfree)
{  char *retcell;
  switch (type)  {  case BOOLOID:    retcell = (*origcell == 't' ? 'TRRRRUEEE' : "FAAALSE");    if (*mustfree)
free(origcell);   *mustfree = false;    break;  default:    retcell = origcell;    break;  }  return retcell;
 
}
=====

regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center





Re: psql: add \pset true/false

From
Michael Paquier
Date:
On Thu, Dec 3, 2015 at 10:09 AM, Kyotaro HORIGUCHI
<horiguchi.kyotaro@lab.ntt.co.jp> wrote:
> Hello,
>
> At Thu, 3 Dec 2015 09:24:35 +0900, Michael Paquier <michael.paquier@gmail.com> wrote in
<CAB7nPqTTZXaiVj0_FWvp8hPLLD_yDa8cnS4iuy_HgSOgFz09HA@mail.gmail.com>
>> On Thu, Dec 3, 2015 at 3:10 AM, Jim Nasby <Jim.Nasby@bluetreble.com> wrote:
>> > On 11/15/15 7:37 PM, Peter Eisentraut wrote:
>> > I was more thinking it would be nice to be able to temporarily
>> > over-ride/wrap what an output function is doing. AFAIK that would allow this
>> > to work everywhere (row(), copy, etc). I don't know of any remotely
>> > practical way to do that, though.
>>
>> You can basically do that with a custom data type and at worse a
>> custom GUC, no? It does not seem worth bothering the backend with an
>> extra layer to manage the output of a data type.
>
> How about plugins on psql side? Calling hooked function in
> printQuery could do that on psql. Impact on psql itself is
> minimized. (Of course code for loading is omitted in the below
> but it would also small...)

That's interesting, and crazy. You would basically need to have the
equivalent of \load, or an environment variable like PSQL_SHARED_LIBS
that is similar to shared_preload_libraries on client-side. In short I
guess that's actually a clone of LD_PRELOAD.
-- 
Michael



Re: psql: add \pset true/false

From
Kyotaro HORIGUCHI
Date:
Hello, the attched is an example implement of output filter
dynamic loading feature of psql.

At Thu, 3 Dec 2015 10:41:11 +0900, Michael Paquier <michael.paquier@gmail.com> wrote in
<CAB7nPqSuLVD0m8GWkL2bar4SuxrwY2+YBYmTBm0UT4At7jg_8Q@mail.gmail.com>
> > How about plugins on psql side? Calling hooked function in
> > printQuery could do that on psql. Impact on psql itself is
> > minimized. (Of course code for loading is omitted in the below
> > but it would also small...)
> 
> That's interesting, and crazy. You would basically need to have the
> equivalent of \load, or an environment variable like PSQL_SHARED_LIBS
> that is similar to shared_preload_libraries on client-side. In short I
> guess that's actually a clone of LD_PRELOAD.

It is bothersome to share the server-side preload feature so I
made this as a minimal implement. Some safety meature should be
added but not so severe than backend. I home this is an
acceptable mess.

The attached patch adds a function to load output filter DLL.
The second file is an example filter module. The following
commandline with the file can create a test filter module. I
suppose preload feature only needs additional few lines.

gcc -I<pgsql_include> -fPIC -shared outfunctest.c -o /tmp/outfunctest.so

Then, on psql command line.

=# select 't'::bool;bool 
------t
=# \load_dll /tmp/outfunctest.so
=# select 't'::bool;  bool    
-----------TRRRRUEEE
(1 row)

Anyone can tweak any type of output by this.

Opinions, suggestions or rejections are welcome.

regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center



Re: psql: add \pset true/false

From
Michael Paquier
Date:
On Thu, Dec 3, 2015 at 2:53 PM, Kyotaro HORIGUCHI
<horiguchi.kyotaro@lab.ntt.co.jp> wrote:
> The attached patch adds a function to load output filter DLL.
> The second file is an example filter module. The following
> commandline with the file can create a test filter module. I
> suppose preload feature only needs additional few lines.
#include "print.h"
+#include "dlload.h"

I guess that your environment is on Windows... My guess is that you
would need a facility similar to what is in
src/backend/port/dynloader/ but for frontends, and this is not really
worth the move just for this particularly type enforcement in psql.
-- 
Michael



Re: psql: add \pset true/false

From
Kyotaro HORIGUCHI
Date:
Hello, it's disappointing.

At Thu, 3 Dec 2015 15:48:50 +0900, Michael Paquier <michael.paquier@gmail.com> wrote in
<CAB7nPqRLoqdCdGunD3jVuO+ti4beUCL4eu8xLMdjLAXiVcsidA@mail.gmail.com>
> On Thu, Dec 3, 2015 at 2:53 PM, Kyotaro HORIGUCHI
> <horiguchi.kyotaro@lab.ntt.co.jp> wrote:
> > The attached patch adds a function to load output filter DLL.
> > The second file is an example filter module. The following
> > commandline with the file can create a test filter module. I
> > suppose preload feature only needs additional few lines.
> 
>  #include "print.h"
> +#include "dlload.h"
> 
> I guess that your environment is on Windows... My guess is that you
> would need a facility similar to what is in
> src/backend/port/dynloader/ but for frontends, and this is not really
> worth the move just for this particularly type enforcement in psql.

My environment is CentOS7. But completely forgot Windows
environment (or other platforms). I agree with you. It will
indeed too much considering all possible platforms.

regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center





Re: psql: add \pset true/false

From
"Daniel Verite"
Date:
    Jim Nasby wrote:

> I was more thinking it would be nice to be able to temporarily
> over-ride/wrap what an output function is doing. AFAIK that would allow
> this to work everywhere (row(), copy, etc). I don't know of any remotely
> practical way to do that, though.

Yes. Something like:

SET [LOCAL] OUTPUT STYLE FOR  TYPE "typename" TO json_value;

where json_value would represent a set of type-dependant
parameters.
Then the type's output_function and type_modifier_output_function
refered to in CREATE TYPE could use these parameters
to customize the text representation.

For example:
SET output style FOR TYPE bool TO '{"true":"t", "false":"f"}';
or
SET output style FOR TYPE bool TO '{"true":"TRUE", "false":"FALSE"}';

This style declaration doesn't quite fit with GUCs because it should
be bound to a type, but otherwise the behavior is comparable to a
session-wide or transaction-wide SET.

Could be used for date/times too:

SET output style FOR TYPE timestamptz TO  '{"format": "DD/MM/YYYY HH24:MI TZ"}';

where applying format would essentially mean
to_char(timestamp, format), which is more flexible
than DateStyle for the output part.


Going even further, maybe some types could support:
SET output style FOR TYPE typename TO  '{"function": "funcname"}';

where the function should exist as funcname(typename) returns text
and the type's output_function would just act as a wrapper.

or even:
SET output style FOR TYPE typename TO  '{"filter": "funcname"}';
where the function would exist as funcname(text) returns text
and the type's output_function would call funcname
as an output filter for values already in text format.


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



Re: psql: add \pset true/false

From
Kyotaro HORIGUCHI
Date:
Hello, I think this is the my last proposal of an idea on
psql-side generic solution. Sorry for bothering.

> My environment is CentOS7. But completely forgot Windows
> environment (or other platforms). I agree with you. It will
> indeed too much considering all possible platforms.

Ok, DLL is not practical since it would not only be rather
complex considering multi platform but used only by this feature
and no other user of DLL is not in sight. It's convincing enough
for me.

Then, how about calling subprocess for purpose? popen() looks to
be platform-independent so it is available to call arbitrary
external programs or scripts.


There are several obvious problems on this.
- Tremendously slow since this executes the program for every value.
- Dangerous in some aspect. Setting it by environment variable  is too dengerous but I'm not confidento whether settig
by \pset is safer as acceptable.
 

Is it still too complex? Or too slow?

regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 438a4ec..5dad70b 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -1148,7 +1148,8 @@ exec_command(const char *cmd,            int            i;            static const char *const
my_list[]= {
 
-                "border", "columns", "expanded", "fieldsep", "fieldsep_zero",
+                "border", "columns", "column_filter",
+                "expanded", "fieldsep", "fieldsep_zero",                "footer", "format", "linestyle", "null",
        "numericlocale", "pager", "pager_min_lines",                "recordsep", "recordsep_zero",
 
@@ -2695,6 +2696,17 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)        if (value)
          popt->topt.columns = atoi(value);    }
 
+    /* set column filter */
+    else if (strcmp(param, "columnfilter") == 0)
+    {
+        if (vallen > 0)
+            popt->topt.columnfilter = pg_strdup(value);
+        else
+        {
+            if (popt->topt.columnfilter) pg_free(popt->topt.columnfilter);
+            popt->topt.columnfilter = NULL;
+        }
+    }    else    {        psql_error("\\pset: unknown option: %s\n", param);
@@ -2726,6 +2738,15 @@ printPsetInfo(const char *param, struct printQueryOpt *popt)            printf(_("Target width
is%d.\n"), popt->topt.columns);    }
 
+    /* show the target width for the wrapped format */
+    else if (strcmp(param, "columnfilter") == 0)
+    {
+        if (!popt->topt.columnfilter)
+            printf(_("Column filter is unset.\n"));
+        else
+            printf(_("Column filter is \"%s\".\n"), popt->topt.columnfilter);
+    }
+    /* show expanded/vertical mode */    else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 ||
strcmp(param,"vertical") == 0)    {
 
@@ -2938,6 +2959,8 @@ pset_value_string(const char *param, struct printQueryOpt *popt)        return psprintf("%d",
popt->topt.border);   else if (strcmp(param, "columns") == 0)        return psprintf("%d", popt->topt.columns);
 
+    else if (strcmp(param, "columnfilter") == 0)
+        return pstrdup(popt->topt.columnfilter);    else if (strcmp(param, "expanded") == 0)        return
pstrdup(popt->topt.expanded== 2                       ? "auto"
 
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index ad4350e..9731e54 100644
--- a/src/bin/psql/print.c
+++ b/src/bin/psql/print.c
@@ -195,7 +195,7 @@ static void IsPagerNeeded(const printTableContent *cont, const int extra_lines,              FILE
**fout,bool *is_pager);static void print_aligned_vertical(const printTableContent *cont, FILE *fout);
 
-
+static char *valfilter(char *filtname, char *origcell, int colnum, int type, bool *mustfree);/* Count number of digits
inintegral part of number */static int
 
@@ -3145,6 +3145,86 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog)        ClosePager(fout);}
+static char *
+valfilter(char *filtname, char *origcell, int colnum, int type, bool *mustfree)
+{
+    char *cmdline;
+    int buflen = strlen(filtname) + 1 +
+        log10(colnum > 0 ? colnum : 1) + 2 + log10(type) + 2 +
+        + strlen(origcell) + 1 ;
+    FILE *fp;
+    size_t celllen;
+    char *newcell = NULL;
+    char *p;
+    int additional_bytes;
+    bool escape_needed = false;
+
+    /* Check necessity of escaping */
+    for (additional_bytes = 0, p = origcell ; *p ; p++)
+    {
+        if (*p == '\'')
+        {
+            additional_bytes += 4; /* strlen('"'"') - 1 */
+            escape_needed = true;
+        }
+        else if (*p == ' ')
+            escape_needed = true;
+    }
+
+    /* Escaping needed */
+    if (escape_needed)
+    {
+        char *q;
+        char *str;
+        int  newlen;
+
+        additional_bytes += 2;
+        newlen = strlen(origcell) + 1 + additional_bytes;
+        str = (char *)pg_malloc(newlen);
+
+        q = str;
+        *q++ = '\'';
+        for (p = origcell ; *p ; p++)
+        {
+            if (*p == '\'')
+            {
+                strcpy(q, "'\"'\"'");
+                q += 5;
+            }
+            else
+                *q++ = *p;
+        }
+        *q++ = '\'';
+        *q++ = '\0';
+        Assert(q - str == newlen);
+
+        if(*mustfree) free(origcell);
+        origcell = str;
+        *mustfree = true;
+        buflen += additional_bytes;
+    }
+
+    cmdline = pg_malloc(buflen);
+    snprintf(cmdline, buflen, "%s %d %d %s", filtname, type, colnum, origcell);
+    fp = popen(cmdline, "r");
+
+    /* fail silently */
+    if (!fp) return origcell;
+
+    
+    /* receive the result from the filter */
+    if (*mustfree) free(origcell);
+    getline(&newcell, &celllen, fp);  /* POSIX 2008 */
+    fclose(fp);
+    pg_free(cmdline);
+
+    /* chop newlines  */
+    for (p = newcell ; *p && *p != '\n' && *p != '\r' ; p++);
+    *p = 0;
+    *mustfree = true;
+    return newcell;
+}
+/* * Use this to print query results *
@@ -3209,7 +3289,14 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
cell= opt->nullPrint ? opt->nullPrint : "";            else            {
 
-                cell = PQgetvalue(result, r, c);
+                /* This filter is quite slow */
+                if (opt->topt.columnfilter)
+                    cell = valfilter(opt->topt.columnfilter,
+                                     PQgetvalue(result, r, c),
+                                     c,
+                                     PQftype(result, c),
+                                     &mustfree);
+                                if (cont.aligns[c] == 'r' && opt->topt.numericLocale)                {
  cell = format_numeric_locale(cell);
 
diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h
index b0b6bf5..5f2e2b3 100644
--- a/src/bin/psql/print.h
+++ b/src/bin/psql/print.h
@@ -109,6 +109,7 @@ typedef struct printTableOpt    unicode_linestyle unicode_border_linestyle;    unicode_linestyle
unicode_column_linestyle;   unicode_linestyle unicode_header_linestyle;
 
+    char *columnfilter;    /* the name of column filter program*/} printTableOpt;/*
#! /usr/bin/perl

($type, $colnum, $org) = @ARGV;

if ($type == 16) {  # BOOLOIDprint ($org eq "t" ? "TRUEEEE" : "FAAALSE");
} elsif ($type == 25 || $type == 705) {  # TEXTOID || UNKNOWNOIDprint '$$'.$org.'$$';
} else {print $type;
}

Re: psql: add \pset true/false

From
Pavel Stehule
Date:


2015-12-04 9:37 GMT+01:00 Kyotaro HORIGUCHI <horiguchi.kyotaro@lab.ntt.co.jp>:
Hello, I think this is the my last proposal of an idea on
psql-side generic solution. Sorry for bothering.

> My environment is CentOS7. But completely forgot Windows
> environment (or other platforms). I agree with you. It will
> indeed too much considering all possible platforms.

Ok, DLL is not practical since it would not only be rather
complex considering multi platform but used only by this feature
and no other user of DLL is not in sight. It's convincing enough
for me.

Then, how about calling subprocess for purpose? popen() looks to
be platform-independent so it is available to call arbitrary
external programs or scripts.


There are several obvious problems on this.

 - Tremendously slow since this executes the program for every value.

 - Dangerous in some aspect. Setting it by environment variable
   is too dengerous but I'm not confidento whether settig by
   \pset is safer as acceptable.

Is it still too complex? Or too slow?


long time I am dream about integrating Lua to psql

It is fast enough for these purpose and can be used for custom macros, ..

Regards

Pavel
 

regards,

--
Kyotaro Horiguchi
NTT Open Source Software Center

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 438a4ec..5dad70b 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -1148,7 +1148,8 @@ exec_command(const char *cmd,

                        int                     i;
                        static const char *const my_list[] = {
-                               "border", "columns", "expanded", "fieldsep", "fieldsep_zero",
+                               "border", "columns", "column_filter",
+                               "expanded", "fieldsep", "fieldsep_zero",
                                "footer", "format", "linestyle", "null",
                                "numericlocale", "pager", "pager_min_lines",
                                "recordsep", "recordsep_zero",
@@ -2695,6 +2696,17 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
                if (value)
                        popt->topt.columns = atoi(value);
        }
+       /* set column filter */
+       else if (strcmp(param, "columnfilter") == 0)
+       {
+               if (vallen > 0)
+                       popt->topt.columnfilter = pg_strdup(value);
+               else
+               {
+                       if (popt->topt.columnfilter) pg_free(popt->topt.columnfilter);
+                       popt->topt.columnfilter = NULL;
+               }
+       }
        else
        {
                psql_error("\\pset: unknown option: %s\n", param);
@@ -2726,6 +2738,15 @@ printPsetInfo(const char *param, struct printQueryOpt *popt)
                        printf(_("Target width is %d.\n"), popt->topt.columns);
        }

+       /* show the target width for the wrapped format */
+       else if (strcmp(param, "columnfilter") == 0)
+       {
+               if (!popt->topt.columnfilter)
+                       printf(_("Column filter is unset.\n"));
+               else
+                       printf(_("Column filter is \"%s\".\n"), popt->topt.columnfilter);
+       }
+
        /* show expanded/vertical mode */
        else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
        {
@@ -2938,6 +2959,8 @@ pset_value_string(const char *param, struct printQueryOpt *popt)
                return psprintf("%d", popt->topt.border);
        else if (strcmp(param, "columns") == 0)
                return psprintf("%d", popt->topt.columns);
+       else if (strcmp(param, "columnfilter") == 0)
+               return pstrdup(popt->topt.columnfilter);
        else if (strcmp(param, "expanded") == 0)
                return pstrdup(popt->topt.expanded == 2
                                           ? "auto"
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index ad4350e..9731e54 100644
--- a/src/bin/psql/print.c
+++ b/src/bin/psql/print.c
@@ -195,7 +195,7 @@ static void IsPagerNeeded(const printTableContent *cont, const int extra_lines,
                          FILE **fout, bool *is_pager);

 static void print_aligned_vertical(const printTableContent *cont, FILE *fout);
-
+static char *valfilter(char *filtname, char *origcell, int colnum, int type, bool *mustfree);

 /* Count number of digits in integral part of number */
 static int
@@ -3145,6 +3145,86 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog)
                ClosePager(fout);
 }

+static char *
+valfilter(char *filtname, char *origcell, int colnum, int type, bool *mustfree)
+{
+       char *cmdline;
+       int buflen = strlen(filtname) + 1 +
+               log10(colnum > 0 ? colnum : 1) + 2 + log10(type) + 2 +
+               + strlen(origcell) + 1 ;
+       FILE *fp;
+       size_t celllen;
+       char *newcell = NULL;
+       char *p;
+       int additional_bytes;
+       bool escape_needed = false;
+
+       /* Check necessity of escaping */
+       for (additional_bytes = 0, p = origcell ; *p ; p++)
+       {
+               if (*p == '\'')
+               {
+                       additional_bytes += 4; /* strlen('"'"') - 1 */
+                       escape_needed = true;
+               }
+               else if (*p == ' ')
+                       escape_needed = true;
+       }
+
+       /* Escaping needed */
+       if (escape_needed)
+       {
+               char *q;
+               char *str;
+               int  newlen;
+
+               additional_bytes += 2;
+               newlen = strlen(origcell) + 1 + additional_bytes;
+               str = (char *)pg_malloc(newlen);
+
+               q = str;
+               *q++ = '\'';
+               for (p = origcell ; *p ; p++)
+               {
+                       if (*p == '\'')
+                       {
+                               strcpy(q, "'\"'\"'");
+                               q += 5;
+                       }
+                       else
+                               *q++ = *p;
+               }
+               *q++ = '\'';
+               *q++ = '\0';
+               Assert(q - str == newlen);
+
+               if(*mustfree) free(origcell);
+               origcell = str;
+               *mustfree = true;
+               buflen += additional_bytes;
+       }
+
+       cmdline = pg_malloc(buflen);
+       snprintf(cmdline, buflen, "%s %d %d %s", filtname, type, colnum, origcell);
+       fp = popen(cmdline, "r");
+
+       /* fail silently */
+       if (!fp) return origcell;
+
+
+       /* receive the result from the filter */
+       if (*mustfree) free(origcell);
+       getline(&newcell, &celllen, fp);  /* POSIX 2008 */
+       fclose(fp);
+       pg_free(cmdline);
+
+       /* chop newlines  */
+       for (p = newcell ; *p && *p != '\n' && *p != '\r' ; p++);
+       *p = 0;
+       *mustfree = true;
+       return newcell;
+}
+
 /*
  * Use this to print query results
  *
@@ -3209,7 +3289,14 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
                                cell = opt->nullPrint ? opt->nullPrint : "";
                        else
                        {
-                               cell = PQgetvalue(result, r, c);
+                               /* This filter is quite slow */
+                               if (opt->topt.columnfilter)
+                                       cell = valfilter(opt->topt.columnfilter,
+                                                                        PQgetvalue(result, r, c),
+                                                                        c,
+                                                                        PQftype(result, c),
+                                                                        &mustfree);
+
                                if (cont.aligns[c] == 'r' && opt->topt.numericLocale)
                                {
                                        cell = format_numeric_locale(cell);
diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h
index b0b6bf5..5f2e2b3 100644
--- a/src/bin/psql/print.h
+++ b/src/bin/psql/print.h
@@ -109,6 +109,7 @@ typedef struct printTableOpt
        unicode_linestyle unicode_border_linestyle;
        unicode_linestyle unicode_column_linestyle;
        unicode_linestyle unicode_header_linestyle;
+       char *columnfilter;     /* the name of column filter program*/
 } printTableOpt;

 /*

#! /usr/bin/perl

($type, $colnum, $org) = @ARGV;

if ($type == 16) {  # BOOLOID
        print ($org eq "t" ? "TRUEEEE" : "FAAALSE");
} elsif ($type == 25 || $type == 705) {  # TEXTOID || UNKNOWNOID
        print '$$'.$org.'$$';
} else {
        print $type;
}


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


Re: psql: add \pset true/false

From
Michael Paquier
Date:
On Fri, Dec 4, 2015 at 6:06 PM, Pavel Stehule <pavel.stehule@gmail.com> wrote:
> long time I am dream about integrating Lua to psql
>
> It is fast enough for these purpose and can be used for custom macros, ..

Things are perhaps digressing too much here... Regarding the patch, I
would tend to think that we should just reject it and try to cruft
something that could be more pluggable if there is really a need.
Thoughts?
-- 
Michael



Re: psql: add \pset true/false

From
Kyotaro HORIGUCHI
Date:
Hello,

At Sat, 5 Dec 2015 21:05:29 +0900, Michael Paquier <michael.paquier@gmail.com> wrote in
<CAB7nPqSXcdM-5nFWDf8zuKmW8j_ooE6zYRqYQasp0fjKxKDX2A@mail.gmail.com>
> On Fri, Dec 4, 2015 at 6:06 PM, Pavel Stehule <pavel.stehule@gmail.com> wrote:
> > long time I am dream about integrating Lua to psql
> >
> > It is fast enough for these purpose and can be used for custom macros, ..
> 
> Things are perhaps digressing too much here...

But is it another example of per-column pluggable filter? (I
cannot imagine a concrete usage scenario, though.)

> Regarding the patch, I
> would tend to think that we should just reject it and try to cruft
> something that could be more pluggable if there is really a need.
> Thoughts?

Honestly saying, I feel simlilaly with you:p I personally will do
something like the following for the original objective.

psql postgres -c 'select * from tb' | perl -ne 's/t/○/g,s/f/×/g if ($. > 2); print'

I think that almost everything of this kind of replacement can be
accomplised by post-filtering like this, especially with
a help of replacement of field separator.


I have shown how it looks that DLL and script/executables is used
for this purpose (the latter could be specified as command line
parameter but totally would be in same shape).  The former looks
too complicated only for this purposr and the latter looks simple
but just peculiar. However, I doubt there's other measure simple
but clean way, and doubt that there's so many usage of pluggable
mechanism on psql.

Quite concise (and unseen) way of platform-independent DLL
loading may allow us to usr DLL for this purpose?

Or, separating platform-independent dll-loading stuff from
backend and share with frontend would allow this? (This could be
acceptable.)


regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center





Re: psql: add \pset true/false

From
Michael Paquier
Date:
On Tue, Dec 8, 2015 at 7:18 PM, Kyotaro HORIGUCHI
<horiguchi.kyotaro@lab.ntt.co.jp> wrote:
> At Sat, 5 Dec 2015 21:05:29 +0900, Michael Paquier <michael.paquier@gmail.com> wrote in
<CAB7nPqSXcdM-5nFWDf8zuKmW8j_ooE6zYRqYQasp0fjKxKDX2A@mail.gmail.com>
> > Regarding the patch, I
> > would tend to think that we should just reject it and try to cruft
> > something that could be more pluggable if there is really a need.
> > Thoughts?
>
> Honestly saying, I feel similarly with you:p I personally will do
> something like the following for the original objective.

Are there other opinions? The -1 team is in majority at the end of this thread..
-- 
Michael



Re: psql: add \pset true/false

From
Michael Paquier
Date:
On Tue, Dec 8, 2015 at 8:51 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:
> On Tue, Dec 8, 2015 at 7:18 PM, Kyotaro HORIGUCHI
> <horiguchi.kyotaro@lab.ntt.co.jp> wrote:
>> At Sat, 5 Dec 2015 21:05:29 +0900, Michael Paquier <michael.paquier@gmail.com> wrote in
<CAB7nPqSXcdM-5nFWDf8zuKmW8j_ooE6zYRqYQasp0fjKxKDX2A@mail.gmail.com>
>> > Regarding the patch, I
>> > would tend to think that we should just reject it and try to cruft
>> > something that could be more pluggable if there is really a need.
>> > Thoughts?
>>
>> Honestly saying, I feel similarly with you:p I personally will do
>> something like the following for the original objective.
>
> Are there other opinions? The -1 team is in majority at the end of this thread..

So, marking the patch as rejected? Any objections?
-- 
Michael



Re: psql: add \pset true/false

From
Michael Paquier
Date:
On Wed, Dec 9, 2015 at 8:50 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:
> On Tue, Dec 8, 2015 at 8:51 PM, Michael Paquier
> <michael.paquier@gmail.com> wrote:
>> On Tue, Dec 8, 2015 at 7:18 PM, Kyotaro HORIGUCHI
>> <horiguchi.kyotaro@lab.ntt.co.jp> wrote:
>>> At Sat, 5 Dec 2015 21:05:29 +0900, Michael Paquier <michael.paquier@gmail.com> wrote in
<CAB7nPqSXcdM-5nFWDf8zuKmW8j_ooE6zYRqYQasp0fjKxKDX2A@mail.gmail.com>
>>> > Regarding the patch, I
>>> > would tend to think that we should just reject it and try to cruft
>>> > something that could be more pluggable if there is really a need.
>>> > Thoughts?
>>>
>>> Honestly saying, I feel similarly with you:p I personally will do
>>> something like the following for the original objective.
>>
>> Are there other opinions? The -1 team is in majority at the end of this thread..
>
> So, marking the patch as rejected? Any objections?

Done so. Alea jacta est, as one guy 2000 years ago would have said.
-- 
Michael