Re: printTable API (was: Show INHERIT in \du) - Mailing list pgsql-patches

From Brendan Jurd
Subject Re: printTable API (was: Show INHERIT in \du)
Date
Msg-id 37ed240d0804120112w60c80089obd3a8c8ac72505f8@mail.gmail.com
Whole thread Raw
Responses Re: printTable API (was: Show INHERIT in \du)
List pgsql-patches
On Sun, Mar 30, 2008 at 9:39 AM, Brendan Jurd <direvus@gmail.com> wrote:
> On 25/03/2008, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>  > "Brendan Jurd" <direvus@gmail.com> writes:
>  >  > This makes me wonder whether print.c could offer something a bit more
>  >  > helpful to callers wishing to DIY a table; we could have a
>  >  > table-building struct with methods like addHeader and addCell.
>  >
>  > Once you have two occurrences of a pattern, it's reasonable to assume
>  >  there will be more later.  +1 for building a little bit of infrastructure.
>  >
>
>  Per the above discussion, I'm looking at creating a nice API in
>  print.c for callers wishing to build their own psql output table.
>
>  Currently, if you want to build your own table you need to implement
>  your own local version of the logic in printQuery.
>  describeOneTableDetails is the only place this happens right now, but
>  due to some localisation issues it looks like my \du patch will have
>  to build its table manually as well.
>

I'd like to submit my first version of this patch for review.  I have
introduced a new struct in print.h called printTableContent, which is
used to compose the contents of a psql table.  The methods exposed for
this struct are as follows:

void printTableInit(printTableContent *const content, const char *title,
            const int ncolumns, const int nrows);

void printTableAddHeader(printTableContent *const content, const char *header,
            const int encoding, const bool translate, const char align);

void printTableAddCell(printTableContent *const content, const char *cell,
            const int encoding, const bool translate);

void printTableAddFooter(printTableContent *const content, const char *footer);

void printTableSetFooter(printTableContent *const content, const char *footer);

void printTableCleanUp(printTableContent *const content);

-= Notes

The column headers and cells are implemented as simple arrays of
pointers to existing strings.  It's necessary for the calling site to
ensure that these strings survive at least until the table has been
printed.  That's usually not a problem since the headers and cells
tend to be inside a PGresult.

Footers are a bit different.  I've implemented them as a very
primitive singly-linked list which copies its contents with strdup.  A
lot of the complexity in the pre-patch describeOneTableDetails comes
from the fact that it needs to know the number of footers in advance.
The singly-linked list allows callers to incrementally add an
arbitrary number of footers, and doesn't require them to preserve the
strings, which is nice when you're working with a temporary
PQExpBuffer to produce a footer.

-= QA

Not having written much C, I'm concerned about memory management
errors.  But I've run my own tests with describeOneTableDetails on
tables with every kind of footer there is, and put the patch through
valgrind, and I haven't encountered any segfaults or memory leaks.

Both the serial and parallel regression tests passed perfectly.

-= Documentation

None required as far as I can tell, aside from code comments.

-= Patch tracking

I'll add this to the May CommitFest wiki page myself -- Bruce, you
don't need to do anything at all! =)

Looking forward to your comments.

Cheers,
BJ

Attachment

pgsql-patches by date:

Previous
From: "Brendan Jurd"
Date:
Subject: Re: Reference by output in : \d
Next
From: Andrew Chernow
Date:
Subject: Re: libpq patch for pqtypes hook api and PGresult creation