Fwd: PATCH: psql boolean display

Started by Pavel Stehuleover 13 years ago7 messages
#1Pavel Stehule
pavel.stehule@gmail.com
1 attachment(s)

---------- Forwarded message ----------
From: Pavel Stehule <pavel.stehule@gmail.com>
Date: 2012/9/1
Subject: PATCH: psql boolean display
To: Phil Sorber <phil@omniti.com>

Hello

I am looking to your patch:

I have only one note. I don't think so using any text for values
"true" and "false" is good idea. I don't see a sense of any special
texts like "foo", "bar" from your example.

More strict design is better - I wrote simple modification - it is
based on psql psets - and it add new configuration settings "boolstyle
[char|word]". A advantage of this design is consistency and possible
autocomplete support.

Regards

Pavel

postgres=> select true, false;
bool │ bool
──────┼──────
t │ f
(1 row)

postgres=> \pset boolstyle word
Bool output style is word.
postgres=> select true, false;
bool │ bool
──────┼───────
true │ false
(1 row)

Attachments:

boolstyle.diffapplication/octet-stream; name=boolstyle.diffDownload
*** a/src/bin/psql/command.c
--- b/src/bin/psql/command.c
***************
*** 2231,2236 **** do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
--- 2231,2261 ----
  				   get_line_style(&popt->topt)->name);
  	}
  
+ 	/* set boolean output style */
+ 	else if (strcmp(param, "boolstyle") == 0)
+ 	{
+ 		if (!value)
+ 			;
+ 		else if (pg_strncasecmp("char", value, vallen) == 0)
+ 			popt->topt.bool_style = PRINT_BOOL_CHAR;
+ 		else if (pg_strncasecmp("word", value, vallen) == 0)
+ 			popt->topt.bool_style = PRINT_BOOL_WORD;
+ 		else
+ 		{
+ 			psql_error("\\pset: allowed bool styles are char, word\n");
+ 			return false;
+ 		}
+ 
+ 		if (!quiet)
+ 		{
+ 			if (popt->topt.bool_style == PRINT_BOOL_CHAR)
+ 				printf(_("Bool output style is char.\n"));
+ 			else if (popt->topt.bool_style == PRINT_BOOL_WORD)
+ 				printf(_("Bool output style is word.\n"));
+ 		}
+ 
+ 	}
+ 
  	/* set border style/width */
  	else if (strcmp(param, "border") == 0)
  	{
*** a/src/bin/psql/describe.c
--- b/src/bin/psql/describe.c
***************
*** 22,27 ****
--- 22,29 ----
  #include "settings.h"
  #include "variables.h"
  
+ #include "catalog/pg_type.h"
+ 
  
  static bool describeOneTableDetails(const char *schemaname,
  						const char *relationname,
***************
*** 1408,1414 **** describeOneTableDetails(const char *schemaname,
  	printTableInitialized = true;
  
  	for (i = 0; i < cols; i++)
! 		printTableAddHeader(&cont, headers[i], true, 'l');
  
  	/* Check if table is a view */
  	if (tableinfo.relkind == 'v' && verbose)
--- 1410,1416 ----
  	printTableInitialized = true;
  
  	for (i = 0; i < cols; i++)
! 		printTableAddHeader(&cont, headers[i], true, 'l', TEXTOID);
  
  	/* Check if table is a view */
  	if (tableinfo.relkind == 'v' && verbose)
***************
*** 2422,2433 **** describeRoles(const char *pattern, bool verbose)
  
  	printTableInit(&cont, &myopt, _("List of roles"), ncols, nrows);
  
! 	printTableAddHeader(&cont, gettext_noop("Role name"), true, align);
! 	printTableAddHeader(&cont, gettext_noop("Attributes"), true, align);
! 	printTableAddHeader(&cont, gettext_noop("Member of"), true, align);
  
  	if (verbose && pset.sversion >= 80200)
! 		printTableAddHeader(&cont, gettext_noop("Description"), true, align);
  
  	for (i = 0; i < nrows; i++)
  	{
--- 2424,2435 ----
  
  	printTableInit(&cont, &myopt, _("List of roles"), ncols, nrows);
  
! 	printTableAddHeader(&cont, gettext_noop("Role name"), true, align, TEXTOID);
! 	printTableAddHeader(&cont, gettext_noop("Attributes"), true, align, TEXTOID);
! 	printTableAddHeader(&cont, gettext_noop("Member of"), true, align, TEXTOID);
  
  	if (verbose && pset.sversion >= 80200)
! 		printTableAddHeader(&cont, gettext_noop("Description"), true, align, TEXTOID);
  
  	for (i = 0; i < nrows; i++)
  	{
*** a/src/bin/psql/print.c
--- b/src/bin/psql/print.c
***************
*** 2149,2154 **** printTableInit(printTableContent *const content, const printTableOpt *opt,
--- 2149,2158 ----
  	content->footer = content->footers;
  	content->align = content->aligns;
  	content->cellsadded = 0;
+ 
+ 	content->ftypes = pg_local_calloc(ncolumns + 1,
+ 									  sizeof(*content->ftype));
+ 	content->ftype = content->ftypes;
  }
  
  /*
***************
*** 2165,2171 **** printTableInit(printTableContent *const content, const printTableOpt *opt,
   */
  void
  printTableAddHeader(printTableContent *const content, char *header,
! 					const bool translate, const char align)
  {
  #ifndef ENABLE_NLS
  	(void) translate;			/* unused parameter */
--- 2169,2175 ----
   */
  void
  printTableAddHeader(printTableContent *const content, char *header,
! 					const bool translate, const char align, const Oid ftype)
  {
  #ifndef ENABLE_NLS
  	(void) translate;			/* unused parameter */
***************
*** 2189,2194 **** printTableAddHeader(printTableContent *const content, char *header,
--- 2193,2201 ----
  
  	*content->align = align;
  	content->align++;
+ 
+ 	*content->ftype = ftype;
+ 	content->ftype++;
  }
  
  /*
***************
*** 2443,2448 **** printTable(const printTableContent *cont, FILE *fout, FILE *flog)
--- 2450,2485 ----
  }
  
  /*
+  * formating value - value must not be null
+  */
+ static char *
+ format_value(printTableContent *cont, int col, const printQueryOpt *opt,
+ 			    char *value, bool *mustfree)
+ {
+ 	char *result;
+ 
+ 	*mustfree = false;
+ 
+ 	/* format any numeric value */
+ 	if (cont->aligns[col] == 'r' && opt->topt.numericLocale)
+ 	{
+ 		*mustfree = true;
+ 		result =  format_numeric_locale(value);
+ 	}
+ 
+ 	/* format boolean value */
+ 	else if (cont->ftypes[col] == BOOLOID && opt->topt.bool_style == PRINT_BOOL_WORD)
+ 	{
+ 		result =  (strcmp(value, "t") == 0) ? "true" : "false";
+ 	}
+ 	else
+ 		result = value;
+ 
+ 	return result;
+ }
+ 
+ 
+ /*
   * Use this to print query results
   *
   * It calls printTable with all the things set straight.
***************
*** 2486,2492 **** printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
  		}
  
  		printTableAddHeader(&cont, PQfname(result, i),
! 							opt->translate_header, align);
  	}
  
  	/* set cells */
--- 2523,2529 ----
  		}
  
  		printTableAddHeader(&cont, PQfname(result, i),
! 							opt->translate_header, align, ftype);
  	}
  
  	/* set cells */
***************
*** 2495,2514 **** printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
  		for (c = 0; c < cont.ncolumns; c++)
  		{
  			char	   *cell;
- 			bool		mustfree = false;
  			bool		translate;
  
  			if (PQgetisnull(result, r, c))
  				cell = opt->nullPrint ? opt->nullPrint : "";
  			else
! 			{
! 				cell = PQgetvalue(result, r, c);
! 				if (cont.aligns[c] == 'r' && opt->topt.numericLocale)
! 				{
! 					cell = format_numeric_locale(cell);
! 					mustfree = true;
! 				}
! 			}
  
  			translate = (opt->translate_columns && opt->translate_columns[c]);
  			printTableAddCell(&cont, cell, translate, mustfree);
--- 2532,2545 ----
  		for (c = 0; c < cont.ncolumns; c++)
  		{
  			char	   *cell;
  			bool		translate;
+ 			bool		mustfree;
  
  			if (PQgetisnull(result, r, c))
  				cell = opt->nullPrint ? opt->nullPrint : "";
  			else
! 				cell = format_value(&cont, c, opt,
! 							PQgetvalue(result, r, c), &mustfree);
  
  			translate = (opt->translate_columns && opt->translate_columns[c]);
  			printTableAddCell(&cont, cell, translate, mustfree);
*** a/src/bin/psql/print.h
--- b/src/bin/psql/print.h
***************
*** 23,28 **** enum printFormat
--- 23,34 ----
  	/* add your favourite output format here ... */
  };
  
+ enum boolStyle
+ {
+ 	PRINT_BOOL_CHAR,
+ 	PRINT_BOOL_WORD
+ };
+ 
  typedef struct printTextLineFormat
  {
  	/* Line drawing characters to be used in various contexts */
***************
*** 88,93 **** typedef struct printTableOpt
--- 94,100 ----
  	bool		default_footer; /* allow "(xx rows)" default footer */
  	unsigned long prior_records;	/* start offset for record counters */
  	const printTextFormat *line_style;	/* line style (NULL for default) */
+ 	enum boolStyle bool_style;	/* style of boolean output */
  	struct separator fieldSep;	/* field separator for unaligned text mode */
  	struct separator recordSep; /* record separator for unaligned text mode */
  	bool		numericLocale;	/* locale-aware numeric units separator and
***************
*** 133,138 **** typedef struct printTableContent
--- 140,147 ----
  	char	   *aligns;			/* Array of alignment specifiers; 'l' or 'r',
  								 * one per column */
  	char	   *align;			/* Pointer to the last added alignment */
+ 	Oid *ftypes;			/* Array of type oids */
+ 	Oid *ftype;			/* Pointer to the last added */
  } printTableContent;
  
  typedef struct printQueryOpt
***************
*** 162,168 **** extern void printTableInit(printTableContent *const content,
  			   const printTableOpt *opt, const char *title,
  			   const int ncolumns, const int nrows);
  extern void printTableAddHeader(printTableContent *const content,
! 					char *header, const bool translate, const char align);
  extern void printTableAddCell(printTableContent *const content,
  				  char *cell, const bool translate, const bool mustfree);
  extern void printTableAddFooter(printTableContent *const content,
--- 171,178 ----
  			   const printTableOpt *opt, const char *title,
  			   const int ncolumns, const int nrows);
  extern void printTableAddHeader(printTableContent *const content,
! 					char *header, const bool translate, const char align,
! 					const Oid ftype);
  extern void printTableAddCell(printTableContent *const content,
  				  char *cell, const bool translate, const bool mustfree);
  extern void printTableAddFooter(printTableContent *const content,
*** a/src/bin/psql/startup.c
--- b/src/bin/psql/startup.c
***************
*** 130,135 **** main(int argc, char *argv[])
--- 130,136 ----
  	pset.popt.topt.start_table = true;
  	pset.popt.topt.stop_table = true;
  	pset.popt.topt.default_footer = true;
+ 	pset.popt.topt.bool_style = PRINT_BOOL_CHAR;
  	/* We must get COLUMNS here before readline() sets it */
  	pset.popt.topt.env_columns = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0;
  
*** a/src/bin/psql/tab-complete.c
--- b/src/bin/psql/tab-complete.c
***************
*** 3091,3097 **** psql_completion(char *text, int start, int end)
  		static const char *const my_list[] =
  		{"format", "border", "expanded",
  			"null", "fieldsep", "tuples_only", "title", "tableattr",
! 		"linestyle", "pager", "recordsep", NULL};
  
  		COMPLETE_WITH_LIST_CS(my_list);
  	}
--- 3091,3097 ----
  		static const char *const my_list[] =
  		{"format", "border", "expanded",
  			"null", "fieldsep", "tuples_only", "title", "tableattr",
! 		"linestyle", "pager", "recordsep", "boolstyle",  NULL};
  
  		COMPLETE_WITH_LIST_CS(my_list);
  	}
***************
*** 3112,3117 **** psql_completion(char *text, int start, int end)
--- 3112,3124 ----
  
  			COMPLETE_WITH_LIST_CS(my_list);
  		}
+ 		else if (strcmp(prev_wd, "boolstyle") == 0)
+ 		{
+ 			static const char *const my_list[] =
+ 			{"char", "word", NULL};
+ 
+ 			COMPLETE_WITH_LIST_CS(my_list);
+ 		}
  	}
  	else if (strcmp(prev_wd, "\\set") == 0)
  	{
#2Phil Sorber
phil@omniti.com
In reply to: Pavel Stehule (#1)
Re: Fwd: PATCH: psql boolean display

On Sun, Sep 2, 2012 at 1:13 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

---------- Forwarded message ----------
From: Pavel Stehule <pavel.stehule@gmail.com>
Date: 2012/9/1
Subject: PATCH: psql boolean display
To: Phil Sorber <phil@omniti.com>

Hello

I am looking to your patch:

I have only one note. I don't think so using any text for values
"true" and "false" is good idea. I don't see a sense of any special
texts like "foo", "bar" from your example.

More strict design is better - I wrote simple modification - it is
based on psql psets - and it add new configuration settings "boolstyle
[char|word]". A advantage of this design is consistency and possible
autocomplete support.

Regards

Pavel

postgres=> select true, false;
bool │ bool
──────┼──────
t │ f
(1 row)

postgres=> \pset boolstyle word
Bool output style is word.
postgres=> select true, false;
bool │ bool
──────┼───────
true │ false
(1 row)

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

What you are proposing sounds like it would be better suited to a
server side GUC. Based on the discussion in the thread that said
true/false was the SQL standard and we were doing it incorrectly as
t/f but could not change for legacy reasons. We could even change the
default but give users a way to revert to the old behavior. Similar to
the bytea_output GUC. Maybe add the GUC for 9.3 but not change the
default behavior until 10.0.

What my patch was intended to do was let the end user set boolean
output to any arbitrary values. While foo/bar is pretty useless, it
was meant to reinforce that it was capable of any arbitrary value. I
can think of a decent list of other output an end user might want,
such as:

true/false
yes/no
y/n
on/off
1/0
enabled/disabled

Plus the different capitalized forms.

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Phil Sorber (#2)
Re: Fwd: PATCH: psql boolean display

Phil Sorber <phil@omniti.com> writes:

What my patch was intended to do was let the end user set boolean
output to any arbitrary values. While foo/bar is pretty useless, it
was meant to reinforce that it was capable of any arbitrary value. I
can think of a decent list of other output an end user might want,
such as:

true/false
yes/no
y/n
on/off
1/0
enabled/disabled

Plus the different capitalized forms.

I can readily see that people might want boolean columns displayed in
such ways in custom applications. I'm less convinced that there is much
use for it in psql, though. In the big scheme of things, psql is a
rather low-level tool, designed for DBAs and SQL programmers. I'd get
quite upset if psql failed to tell me the truth about what was in a
table I was looking at --- and a feature like this comes pretty close
to not telling the truth, especially if it kicks in on a column I
wasn't expecting it to.

On the whole I think this sort of substitution belongs in a
user-written-application layer of software, not in any of the tools
we supply.

regards, tom lane

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Tom Lane (#3)
Re: Fwd: PATCH: psql boolean display

I wrote:

Phil Sorber <phil@omniti.com> writes:

What my patch was intended to do was let the end user set boolean
output to any arbitrary values. While foo/bar is pretty useless, it
was meant to reinforce that it was capable of any arbitrary value. I
can think of a decent list of other output an end user might want,
such as:

true/false
yes/no
y/n
on/off
1/0
enabled/disabled

Plus the different capitalized forms.

I can readily see that people might want boolean columns displayed in
such ways in custom applications. I'm less convinced that there is much
use for it in psql, though.

BTW, another point that your list brings to mind is that somebody who
wants something like this would very possibly want different displays
for different columns. The proposed feature, being one-size-fits-all
for "boolean", couldn't handle that.

What would make a lot more sense in my mind would be to label columns
*in the database* to show how they ought to be displayed.

One conceivable method is to make a collection of domains over bool,
and drive the display off the particular domain used. However we lack
some infrastructure that would be needed for this (in particular, I'm
pretty sure the PQftype data delivered to the client identifies the
underlying type and not the domain).

Another approach is to make a collection of enum types, in which case
you don't need any client-side support at all. I experimented with
this method a bit, and it seems workable:

regression=# create type mybool as enum ('no', 'yes');
CREATE TYPE
regression=# create function bool(mybool) returns bool as
$$ select $1 = 'yes'::mybool $$ language sql immutable;
CREATE FUNCTION
regression=# create cast (mybool as bool) with function bool(mybool) as assignment;
CREATE CAST
regression=# create table mb(f1 mybool);
CREATE TABLE
regression=# insert into mb values('no'),('yes');
INSERT 0 2
regression=# select * from mb where f1;
f1
-----
yes
(1 row)

regression=# select * from mb where f1 = 'yes';
f1
-----
yes
(1 row)

I tried making the cast be implicit, but that caused problems with
ambiguous operators, so assignment seems to be the best you can do here.

A variant of this is to build casts in the other direction
(bool::mybool), declare columns in the database as regular bool,
and apply the casts in queries when you want columns displayed in a
particular way. This might be the best solution if the desired
display is at all context-dependent.

regards, tom lane

#5Pavel Stehule
pavel.stehule@gmail.com
In reply to: Phil Sorber (#2)
Re: Fwd: PATCH: psql boolean display

2012/9/2 Phil Sorber <phil@omniti.com>:

On Sun, Sep 2, 2012 at 1:13 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

---------- Forwarded message ----------
From: Pavel Stehule <pavel.stehule@gmail.com>
Date: 2012/9/1
Subject: PATCH: psql boolean display
To: Phil Sorber <phil@omniti.com>

Hello

I am looking to your patch:

I have only one note. I don't think so using any text for values
"true" and "false" is good idea. I don't see a sense of any special
texts like "foo", "bar" from your example.

More strict design is better - I wrote simple modification - it is
based on psql psets - and it add new configuration settings "boolstyle
[char|word]". A advantage of this design is consistency and possible
autocomplete support.

Regards

Pavel

postgres=> select true, false;
bool │ bool
──────┼──────
t │ f
(1 row)

postgres=> \pset boolstyle word
Bool output style is word.
postgres=> select true, false;
bool │ bool
──────┼───────
true │ false
(1 row)

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

What you are proposing sounds like it would be better suited to a
server side GUC. Based on the discussion in the thread that said
true/false was the SQL standard and we were doing it incorrectly as
t/f but could not change for legacy reasons. We could even change the
default but give users a way to revert to the old behavior. Similar to
the bytea_output GUC. Maybe add the GUC for 9.3 but not change the
default behavior until 10.0.

What my patch was intended to do was let the end user set boolean
output to any arbitrary values. While foo/bar is pretty useless, it
was meant to reinforce that it was capable of any arbitrary value. I
can think of a decent list of other output an end user might want,
such as:

true/false
yes/no
y/n
on/off
1/0
enabled/disabled

Plus the different capitalized forms.

If you have these different requests, then you can use enums - or you
can use own formatting function. There is relative strong
recommendation don't use implicit formatting based on database
configuration from application and inside application use explicit
formatting anywhere. I don't thing so using GUC for boolean datatype
is good idea.

Using just chars 't' and 'f' is unlucky design, that must be respected
due compatibility reasons. You don't need to solve it usually, because
transformation from chars to words can do application or database
driver - so I understand this as client issue - psql issue in this
case. And I really don't see any sense for unlimited bool output - in
simple tool like psql. It can be nice to fix issue with chars, because
chars are not too pronounced, but we don't need to supply enums.

Regards

Pavel

#6Pavel Stehule
pavel.stehule@gmail.com
In reply to: Tom Lane (#4)
Re: Fwd: PATCH: psql boolean display

2012/9/2 Tom Lane <tgl@sss.pgh.pa.us>:

I wrote:

Phil Sorber <phil@omniti.com> writes:

What my patch was intended to do was let the end user set boolean
output to any arbitrary values. While foo/bar is pretty useless, it
was meant to reinforce that it was capable of any arbitrary value. I
can think of a decent list of other output an end user might want,
such as:

true/false
yes/no
y/n
on/off
1/0
enabled/disabled

Plus the different capitalized forms.

I can readily see that people might want boolean columns displayed in
such ways in custom applications. I'm less convinced that there is much
use for it in psql, though.

BTW, another point that your list brings to mind is that somebody who
wants something like this would very possibly want different displays
for different columns. The proposed feature, being one-size-fits-all
for "boolean", couldn't handle that.

I proposed just more cleaner and more conventional boolean output in
psql - nothing more. We can write formatting functions, CASE, we can
use enums.

What would make a lot more sense in my mind would be to label columns
*in the database* to show how they ought to be displayed.

One conceivable method is to make a collection of domains over bool,
and drive the display off the particular domain used. However we lack
some infrastructure that would be needed for this (in particular, I'm
pretty sure the PQftype data delivered to the client identifies the
underlying type and not the domain).

Another approach is to make a collection of enum types, in which case
you don't need any client-side support at all. I experimented with
this method a bit, and it seems workable:

regression=# create type mybool as enum ('no', 'yes');
CREATE TYPE
regression=# create function bool(mybool) returns bool as
$$ select $1 = 'yes'::mybool $$ language sql immutable;
CREATE FUNCTION
regression=# create cast (mybool as bool) with function bool(mybool) as assignment;
CREATE CAST
regression=# create table mb(f1 mybool);
CREATE TABLE
regression=# insert into mb values('no'),('yes');
INSERT 0 2
regression=# select * from mb where f1;
f1
-----
yes
(1 row)

regression=# select * from mb where f1 = 'yes';
f1
-----
yes
(1 row)

I tried making the cast be implicit, but that caused problems with
ambiguous operators, so assignment seems to be the best you can do here.

A variant of this is to build casts in the other direction
(bool::mybool), declare columns in the database as regular bool,
and apply the casts in queries when you want columns displayed in a
particular way. This might be the best solution if the desired
display is at all context-dependent.

When I worked on PSM I required possibility to simple specification
expected datatype out of SQL statement - some like enhancing
parametrised queries - with fourth parameter - expected types.

Then somebody can set expected type for some column simply - out of
query - and transformation can be fast. It should be used for
unsupported date formats and similar tasks.

Regards

Pavel

Show quoted text

regards, tom lane

#7Heikki Linnakangas
hlinnakangas@vmware.com
In reply to: Pavel Stehule (#6)
Re: Fwd: PATCH: psql boolean display

It doesn't look like this patch is going anywhere. I agree with Tom's
comments that we need to think how this works for all datatypes, not
just booleans. And a simple substitution of values isn't enough; an
application might want to output all integers in hex, for example. A
custom domain in the server is one way to implement that, or you can
check the datatype in the application and act accordingly. It doesn't
belong in psql, so I'll mark this as rejected in the commitfest app.

On 02.09.2012 19:47, Pavel Stehule wrote:

2012/9/2 Tom Lane<tgl@sss.pgh.pa.us>:

I wrote:

Phil Sorber<phil@omniti.com> writes:

What my patch was intended to do was let the end user set boolean
output to any arbitrary values. While foo/bar is pretty useless, it
was meant to reinforce that it was capable of any arbitrary value. I
can think of a decent list of other output an end user might want,
such as:

true/false
yes/no
y/n
on/off
1/0
enabled/disabled

Plus the different capitalized forms.

I can readily see that people might want boolean columns displayed in
such ways in custom applications. I'm less convinced that there is much
use for it in psql, though.

BTW, another point that your list brings to mind is that somebody who
wants something like this would very possibly want different displays
for different columns. The proposed feature, being one-size-fits-all
for "boolean", couldn't handle that.

I proposed just more cleaner and more conventional boolean output in
psql - nothing more. We can write formatting functions, CASE, we can
use enums.

What would make a lot more sense in my mind would be to label columns
*in the database* to show how they ought to be displayed.

One conceivable method is to make a collection of domains over bool,
and drive the display off the particular domain used. However we lack
some infrastructure that would be needed for this (in particular, I'm
pretty sure the PQftype data delivered to the client identifies the
underlying type and not the domain).

Another approach is to make a collection of enum types, in which case
you don't need any client-side support at all. I experimented with
this method a bit, and it seems workable:

regression=# create type mybool as enum ('no', 'yes');
CREATE TYPE
regression=# create function bool(mybool) returns bool as
$$ select $1 = 'yes'::mybool $$ language sql immutable;
CREATE FUNCTION
regression=# create cast (mybool as bool) with function bool(mybool) as assignment;
CREATE CAST
regression=# create table mb(f1 mybool);
CREATE TABLE
regression=# insert into mb values('no'),('yes');
INSERT 0 2
regression=# select * from mb where f1;
f1
-----
yes
(1 row)

regression=# select * from mb where f1 = 'yes';
f1
-----
yes
(1 row)

I tried making the cast be implicit, but that caused problems with
ambiguous operators, so assignment seems to be the best you can do here.

A variant of this is to build casts in the other direction
(bool::mybool), declare columns in the database as regular bool,
and apply the casts in queries when you want columns displayed in a
particular way. This might be the best solution if the desired
display is at all context-dependent.

When I worked on PSM I required possibility to simple specification
expected datatype out of SQL statement - some like enhancing
parametrised queries - with fourth parameter - expected types.

Then somebody can set expected type for some column simply - out of
query - and transformation can be fast. It should be used for
unsupported date formats and similar tasks.

Regards

Pavel

regards, tom lane

--
- Heikki