On 2026-Jun-19, David G. Johnston wrote: > Looked a bit closer at printQuery this time; disliking that the if > condition has an awareness of the implementation of > printQueryOptDisplayValue since it lists !isnull and ftype != BOOLOID > explicitly. > > How about not touching print.c at all with this patch, moving the > printQueryOptDisplayValue into crosstabview.c and leaving printQuery alone > since it is already correct?
That was my reaction also, so I produced this POC patch. I think print.h needs some more work, and that'd be only for 20. -- Álvaro Herrera 48°01'N 7°57'E — https://www.EnterpriseDB.com/ "La libertad es como el dinero; el que no la sabe emplear la pierde" (Alvarez)
>From 95489222b9bf42b7b063ccecf5da58dd8caafa60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Herrera?= <[email protected]> Date: Fri, 19 Jun 2026 16:37:14 +0200 Subject: [PATCH] fix crosstabview for true/false print --- src/bin/psql/crosstabview.c | 28 +++++++++++++++------ src/test/regress/expected/psql_crosstab.out | 15 +++++++++++ src/test/regress/sql/psql_crosstab.sql | 10 ++++++++ 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index 111e8823bdb..dddef624a06 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -7,6 +7,8 @@ */ #include "postgres_fe.h" +#include "catalog/pg_type_d.h" + #include "common.h" #include "common/int.h" #include "common/logging.h" @@ -288,6 +290,7 @@ printCrosstab(const PGresult *result, { printQueryOpt popt = pset.popt; printTableContent cont; + Oid data_ftype = PQftype(result, field_for_data); int i, rn; char col_align; @@ -317,7 +320,7 @@ printCrosstab(const PGresult *result, /* * The display alignment depends on its PQftype(). */ - col_align = column_type_alignment(PQftype(result, field_for_data)); + col_align = column_type_alignment(data_ftype); for (i = 0; i < num_columns; i++) { @@ -335,10 +338,10 @@ printCrosstab(const PGresult *result, for (i = 0; i < num_rows; i++) { int k = piv_rows[i].rank; + int idx = k * (num_columns + 1); - cont.cells[k * (num_columns + 1)] = piv_rows[i].name ? - piv_rows[i].name : - (popt.nullPrint ? popt.nullPrint : ""); + cont.cells[idx] = piv_rows[i].name ? + piv_rows[i].name : (popt.nullPrint ? popt.nullPrint : ""); } cont.cellsadded = num_rows * (num_columns + 1); @@ -401,9 +404,20 @@ printCrosstab(const PGresult *result, goto error; } - cont.cells[idx] = !PQgetisnull(result, rn, field_for_data) ? - PQgetvalue(result, rn, field_for_data) : - (popt.nullPrint ? popt.nullPrint : ""); + if (PQgetisnull(result, rn, field_for_data)) + cont.cells[idx] = (popt.nullPrint ? popt.nullPrint : ""); + else if (data_ftype == BOOLOID) + { + char *value; + + value = PQgetvalue(result, rn, field_for_data); + if (value[0] == 't') + cont.cells[idx] = popt.truePrint ? popt.truePrint : "t"; + else + cont.cells[idx] = popt.falsePrint ? popt.falsePrint : "f"; + } + else + cont.cells[idx] = PQgetvalue(result, rn, field_for_data); } } diff --git a/src/test/regress/expected/psql_crosstab.out b/src/test/regress/expected/psql_crosstab.out index e09e3310165..f2307dbf910 100644 --- a/src/test/regress/expected/psql_crosstab.out +++ b/src/test/regress/expected/psql_crosstab.out @@ -137,6 +137,21 @@ GROUP BY v, h ORDER BY h,v (3 rows) \pset null '' +-- boolean display +\pset display_true 'true' +\pset display_false 'false' +SELECT false as row_key, true as col_key, true as val +UNION ALL +SELECT true, false, false + \crosstabview row_key col_key val + row_key | t | f +---------+------+------- + f | true | + t | | false +(2 rows) + +\pset display_true 't' +\pset display_false 'f' -- refer to columns by position SELECT v,h,string_agg(i::text, E'\n'), string_agg(c, E'\n') FROM ctv_data GROUP BY v, h ORDER BY h,v diff --git a/src/test/regress/sql/psql_crosstab.sql b/src/test/regress/sql/psql_crosstab.sql index 5a4511389de..00b395d7168 100644 --- a/src/test/regress/sql/psql_crosstab.sql +++ b/src/test/regress/sql/psql_crosstab.sql @@ -69,6 +69,16 @@ GROUP BY v, h ORDER BY h,v \crosstabview v h i \pset null '' +-- boolean display +\pset display_true 'true' +\pset display_false 'false' +SELECT false as row_key, true as col_key, true as val +UNION ALL +SELECT true, false, false + \crosstabview row_key col_key val +\pset display_true 't' +\pset display_false 'f' + -- refer to columns by position SELECT v,h,string_agg(i::text, E'\n'), string_agg(c, E'\n') FROM ctv_data GROUP BY v, h ORDER BY h,v -- 2.47.3
