Header And Logo

PostgreSQL
| The world's most advanced open source database.

Defines | Functions

fe-print.c File Reference

#include "postgres_fe.h"
#include <signal.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/termios.h>
#include "libpq-fe.h"
#include "libpq-int.h"
Include dependency graph for fe-print.c:

Go to the source code of this file.

Defines

#define DEFAULT_FIELD_SEP   " "

Functions

static void do_field (const PQprintOpt *po, const PGresult *res, const int i, const int j, const int fs_len, char **fields, const int nFields, const char **fieldNames, unsigned char *fieldNotNum, int *fieldMax, const int fieldMaxLen, FILE *fout)
static char * do_header (FILE *fout, const PQprintOpt *po, const int nFields, int *fieldMax, const char **fieldNames, unsigned char *fieldNotNum, const int fs_len, const PGresult *res)
static void output_row (FILE *fout, const PQprintOpt *po, const int nFields, char **fields, unsigned char *fieldNotNum, int *fieldMax, char *border, const int row_index)
static void fill (int length, int max, char filler, FILE *fp)
void PQprint (FILE *fout, const PGresult *res, const PQprintOpt *po)
void PQdisplayTuples (const PGresult *res, FILE *fp, int fillAlign, const char *fieldSep, int printHeader, int quiet)
void PQprintTuples (const PGresult *res, FILE *fout, int PrintAttNames, int TerseOutput, int colWidth)

Define Documentation

#define DEFAULT_FIELD_SEP   " "

Function Documentation

static void do_field ( const PQprintOpt po,
const PGresult res,
const int  i,
const int  j,
const int  fs_len,
char **  fields,
const int  nFields,
const char **  fieldNames,
unsigned char *  fieldNotNum,
int *  fieldMax,
const int  fieldMaxLen,
FILE *  fout 
) [static]

Definition at line 325 of file fe-print.c.

References _PQprintOpt::align, pg_result::client_encoding, _PQprintOpt::expanded, _PQprintOpt::fieldSep, _PQprintOpt::html3, libpq_gettext, malloc, PQgetlength(), PQgetvalue(), and PQmblen().

Referenced by PQprint().

{

    const char *pval,
               *p;
    int         plen;
    bool        skipit;

    plen = PQgetlength(res, i, j);
    pval = PQgetvalue(res, i, j);

    if (plen < 1 || !pval || !*pval)
    {
        if (po->align || po->expanded)
            skipit = true;
        else
        {
            skipit = false;
            goto efield;
        }
    }
    else
        skipit = false;

    if (!skipit)
    {
        if (po->align && !fieldNotNum[j])
        {
            /* Detect whether field contains non-numeric data */
            char        ch = '0';

            for (p = pval; *p; p += PQmblen(p, res->client_encoding))
            {
                ch = *p;
                if (!((ch >= '0' && ch <= '9') ||
                      ch == '.' ||
                      ch == 'E' ||
                      ch == 'e' ||
                      ch == ' ' ||
                      ch == '-'))
                {
                    fieldNotNum[j] = 1;
                    break;
                }
            }

            /*
             * Above loop will believe E in first column is numeric; also, we
             * insist on a digit in the last column for a numeric. This test
             * is still not bulletproof but it handles most cases.
             */
            if (*pval == 'E' || *pval == 'e' ||
                !(ch >= '0' && ch <= '9'))
                fieldNotNum[j] = 1;
        }

        if (!po->expanded && (po->align || po->html3))
        {
            if (plen > fieldMax[j])
                fieldMax[j] = plen;
            if (!(fields[i * nFields + j] = (char *) malloc(plen + 1)))
            {
                fprintf(stderr, libpq_gettext("out of memory\n"));
                abort();
            }
            strcpy(fields[i * nFields + j], pval);
        }
        else
        {
            if (po->expanded)
            {
                if (po->html3)
                    fprintf(fout,
                            "<tr><td align=\"left\"><b>%s</b></td>"
                            "<td align=\"%s\">%s</td></tr>\n",
                            fieldNames[j],
                            fieldNotNum[j] ? "left" : "right",
                            pval);
                else
                {
                    if (po->align)
                        fprintf(fout,
                                "%-*s%s %s\n",
                                fieldMaxLen - fs_len, fieldNames[j],
                                po->fieldSep,
                                pval);
                    else
                        fprintf(fout,
                                "%s%s%s\n",
                                fieldNames[j], po->fieldSep, pval);
                }
            }
            else
            {
                if (!po->html3)
                {
                    fputs(pval, fout);
            efield:
                    if ((j + 1) < nFields)
                        fputs(po->fieldSep, fout);
                    else
                        fputc('\n', fout);
                }
            }
        }
    }
}

static char * do_header ( FILE *  fout,
const PQprintOpt po,
const int  nFields,
int *  fieldMax,
const char **  fieldNames,
unsigned char *  fieldNotNum,
const int  fs_len,
const PGresult res 
) [static]

Definition at line 440 of file fe-print.c.

References _PQprintOpt::fieldSep, _PQprintOpt::html3, libpq_gettext, malloc, PQfname(), and _PQprintOpt::standard.

Referenced by PQprint().

{

    int         j;              /* for loop index */
    char       *border = NULL;

    if (po->html3)
        fputs("<tr>", fout);
    else
    {
        int         tot = 0;
        int         n = 0;
        char       *p = NULL;

        for (; n < nFields; n++)
            tot += fieldMax[n] + fs_len + (po->standard ? 2 : 0);
        if (po->standard)
            tot += fs_len * 2 + 2;
        border = malloc(tot + 1);
        if (!border)
        {
            fprintf(stderr, libpq_gettext("out of memory\n"));
            abort();
        }
        p = border;
        if (po->standard)
        {
            char       *fs = po->fieldSep;

            while (*fs++)
                *p++ = '+';
        }
        for (j = 0; j < nFields; j++)
        {
            int         len;

            for (len = fieldMax[j] + (po->standard ? 2 : 0); len--; *p++ = '-');
            if (po->standard || (j + 1) < nFields)
            {
                char       *fs = po->fieldSep;

                while (*fs++)
                    *p++ = '+';
            }
        }
        *p = '\0';
        if (po->standard)
            fprintf(fout, "%s\n", border);
    }
    if (po->standard)
        fputs(po->fieldSep, fout);
    for (j = 0; j < nFields; j++)
    {
        const char *s = PQfname(res, j);

        if (po->html3)
        {
            fprintf(fout, "<th align=\"%s\">%s</th>",
                    fieldNotNum[j] ? "left" : "right", fieldNames[j]);
        }
        else
        {
            int         n = strlen(s);

            if (n > fieldMax[j])
                fieldMax[j] = n;
            if (po->standard)
                fprintf(fout,
                        fieldNotNum[j] ? " %-*s " : " %*s ",
                        fieldMax[j], s);
            else
                fprintf(fout, fieldNotNum[j] ? "%-*s" : "%*s", fieldMax[j], s);
            if (po->standard || (j + 1) < nFields)
                fputs(po->fieldSep, fout);
        }
    }
    if (po->html3)
        fputs("</tr>\n", fout);
    else
        fprintf(fout, "\n%s\n", border);
    return border;
}

static void fill ( int  length,
int  max,
char  filler,
FILE *  fp 
) [static]

Definition at line 756 of file fe-print.c.

Referenced by PQdisplayTuples().

{
    int         count;

    count = max - length;
    while (count-- >= 0)
        putc(filler, fp);
}

static void output_row ( FILE *  fout,
const PQprintOpt po,
const int  nFields,
char **  fields,
unsigned char *  fieldNotNum,
int *  fieldMax,
char *  border,
const int  row_index 
) [static]

Definition at line 527 of file fe-print.c.

References _PQprintOpt::fieldSep, free, _PQprintOpt::html3, and _PQprintOpt::standard.

Referenced by PQprint().

{

    int         field_index;    /* for loop index */

    if (po->html3)
        fputs("<tr>", fout);
    else if (po->standard)
        fputs(po->fieldSep, fout);
    for (field_index = 0; field_index < nFields; field_index++)
    {
        char       *p = fields[row_index * nFields + field_index];

        if (po->html3)
            fprintf(fout, "<td align=\"%s\">%s</td>",
                    fieldNotNum[field_index] ? "left" : "right", p ? p : "");
        else
        {
            fprintf(fout,
                    fieldNotNum[field_index] ?
                    (po->standard ? " %-*s " : "%-*s") :
                    (po->standard ? " %*s " : "%*s"),
                    fieldMax[field_index],
                    p ? p : "");
            if (po->standard || field_index + 1 < nFields)
                fputs(po->fieldSep, fout);
        }
        if (p)
            free(p);
    }
    if (po->html3)
        fputs("</tr>", fout);
    else if (po->standard)
        fprintf(fout, "\n%s", border);
    fputc('\n', fout);
}

void PQdisplayTuples ( const PGresult res,
FILE *  fp,
int  fillAlign,
const char *  fieldSep,
int  printHeader,
int  quiet 
)

Definition at line 573 of file fe-print.c.

References fill(), free, i, libpq_gettext, malloc, NULL, PQfname(), PQgetlength(), PQgetvalue(), PQnfields(), and PQntuples().

{
#define DEFAULT_FIELD_SEP " "

    int         i,
                j;
    int         nFields;
    int         nTuples;
    int        *fLength = NULL;

    if (fieldSep == NULL)
        fieldSep = DEFAULT_FIELD_SEP;

    /* Get some useful info about the results */
    nFields = PQnfields(res);
    nTuples = PQntuples(res);

    if (fp == NULL)
        fp = stdout;

    /* Figure the field lengths to align to */
    /* will be somewhat time consuming for very large results */
    if (fillAlign)
    {
        fLength = (int *) malloc(nFields * sizeof(int));
        if (!fLength)
        {
            fprintf(stderr, libpq_gettext("out of memory\n"));
            abort();
        }

        for (j = 0; j < nFields; j++)
        {
            fLength[j] = strlen(PQfname(res, j));
            for (i = 0; i < nTuples; i++)
            {
                int         flen = PQgetlength(res, i, j);

                if (flen > fLength[j])
                    fLength[j] = flen;
            }
        }
    }

    if (printHeader)
    {
        /* first, print out the attribute names */
        for (i = 0; i < nFields; i++)
        {
            fputs(PQfname(res, i), fp);
            if (fillAlign)
                fill(strlen(PQfname(res, i)), fLength[i], ' ', fp);
            fputs(fieldSep, fp);
        }
        fprintf(fp, "\n");

        /* Underline the attribute names */
        for (i = 0; i < nFields; i++)
        {
            if (fillAlign)
                fill(0, fLength[i], '-', fp);
            fputs(fieldSep, fp);
        }
        fprintf(fp, "\n");
    }

    /* next, print out the instances */
    for (i = 0; i < nTuples; i++)
    {
        for (j = 0; j < nFields; j++)
        {
            fprintf(fp, "%s", PQgetvalue(res, i, j));
            if (fillAlign)
                fill(strlen(PQgetvalue(res, i, j)), fLength[j], ' ', fp);
            fputs(fieldSep, fp);
        }
        fprintf(fp, "\n");
    }

    if (!quiet)
        fprintf(fp, "\nQuery returned %d row%s.\n", PQntuples(res),
                (PQntuples(res) == 1) ? "" : "s");

    fflush(fp);

    if (fLength)
        free(fLength);
}

void PQprint ( FILE *  fout,
const PGresult res,
const PQprintOpt po 
)

Definition at line 68 of file fe-print.c.

References _PQprintOpt::align, calloc, _PQprintOpt::caption, do_field(), do_header(), _PQprintOpt::expanded, _PQprintOpt::fieldName, _PQprintOpt::fieldSep, free, _PQprintOpt::header, _PQprintOpt::html3, i, libpq_gettext, NULL, output_row(), _PQprintOpt::pager, PQfname(), PQnfields(), PQntuples(), pqsignal(), SIG_IGN, SIGPIPE, _PQprintOpt::standard, and _PQprintOpt::tableOpt.

{
    int         nFields;

    nFields = PQnfields(res);

    if (nFields > 0)
    {                           /* only print rows with at least 1 field.  */
        int         i,
                    j;
        int         nTups;
        int        *fieldMax = NULL;    /* in case we don't use them */
        unsigned char *fieldNotNum = NULL;
        char       *border = NULL;
        char      **fields = NULL;
        const char **fieldNames;
        int         fieldMaxLen = 0;
        int         numFieldName;
        int         fs_len = strlen(po->fieldSep);
        int         total_line_length = 0;
        int         usePipe = 0;
        char       *pagerenv;

#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
        sigset_t    osigset;
        bool        sigpipe_masked = false;
        bool        sigpipe_pending;
#endif
#if !defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
        pqsigfunc   oldsigpipehandler = NULL;
#endif

#ifdef TIOCGWINSZ
        struct winsize screen_size;
#else
        struct winsize
        {
            int         ws_row;
            int         ws_col;
        }           screen_size;
#endif

        nTups = PQntuples(res);
        if (!(fieldNames = (const char **) calloc(nFields, sizeof(char *))))
        {
            fprintf(stderr, libpq_gettext("out of memory\n"));
            abort();
        }
        if (!(fieldNotNum = (unsigned char *) calloc(nFields, 1)))
        {
            fprintf(stderr, libpq_gettext("out of memory\n"));
            abort();
        }
        if (!(fieldMax = (int *) calloc(nFields, sizeof(int))))
        {
            fprintf(stderr, libpq_gettext("out of memory\n"));
            abort();
        }
        for (numFieldName = 0;
             po->fieldName && po->fieldName[numFieldName];
             numFieldName++)
            ;
        for (j = 0; j < nFields; j++)
        {
            int         len;
            const char *s = (j < numFieldName && po->fieldName[j][0]) ?
            po->fieldName[j] : PQfname(res, j);

            fieldNames[j] = s;
            len = s ? strlen(s) : 0;
            fieldMax[j] = len;
            len += fs_len;
            if (len > fieldMaxLen)
                fieldMaxLen = len;
            total_line_length += len;
        }

        total_line_length += nFields * strlen(po->fieldSep) + 1;

        if (fout == NULL)
            fout = stdout;
        if (po->pager && fout == stdout && isatty(fileno(stdin)) &&
            isatty(fileno(stdout)))
        {
            /*
             * If we think there'll be more than one screen of output, try to
             * pipe to the pager program.
             */
#ifdef TIOCGWINSZ
            if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 ||
                screen_size.ws_col == 0 ||
                screen_size.ws_row == 0)
            {
                screen_size.ws_row = 24;
                screen_size.ws_col = 80;
            }
#else
            screen_size.ws_row = 24;
            screen_size.ws_col = 80;
#endif
            pagerenv = getenv("PAGER");
            if (pagerenv != NULL &&
                pagerenv[0] != '\0' &&
                !po->html3 &&
                ((po->expanded &&
                  nTups * (nFields + 1) >= screen_size.ws_row) ||
                 (!po->expanded &&
                  nTups * (total_line_length / screen_size.ws_col + 1) *
                  (1 + (po->standard != 0)) >= screen_size.ws_row -
                  (po->header != 0) *
                  (total_line_length / screen_size.ws_col + 1) * 2
                  - (po->header != 0) * 2       /* row count and newline */
                  )))
            {
                fout = popen(pagerenv, "w");
                if (fout)
                {
                    usePipe = 1;
#ifndef WIN32
#ifdef ENABLE_THREAD_SAFETY
                    if (pq_block_sigpipe(&osigset, &sigpipe_pending) == 0)
                        sigpipe_masked = true;
#else
                    oldsigpipehandler = pqsignal(SIGPIPE, SIG_IGN);
#endif   /* ENABLE_THREAD_SAFETY */
#endif   /* WIN32 */
                }
                else
                    fout = stdout;
            }
        }

        if (!po->expanded && (po->align || po->html3))
        {
            if (!(fields = (char **) calloc(nFields * (nTups + 1), sizeof(char *))))
            {
                fprintf(stderr, libpq_gettext("out of memory\n"));
                abort();
            }
        }
        else if (po->header && !po->html3)
        {
            if (po->expanded)
            {
                if (po->align)
                    fprintf(fout, libpq_gettext("%-*s%s Value\n"),
                            fieldMaxLen - fs_len, libpq_gettext("Field"), po->fieldSep);
                else
                    fprintf(fout, libpq_gettext("%s%sValue\n"), libpq_gettext("Field"), po->fieldSep);
            }
            else
            {
                int         len = 0;

                for (j = 0; j < nFields; j++)
                {
                    const char *s = fieldNames[j];

                    fputs(s, fout);
                    len += strlen(s) + fs_len;
                    if ((j + 1) < nFields)
                        fputs(po->fieldSep, fout);
                }
                fputc('\n', fout);
                for (len -= fs_len; len--; fputc('-', fout));
                fputc('\n', fout);
            }
        }
        if (po->expanded && po->html3)
        {
            if (po->caption)
                fprintf(fout, "<center><h2>%s</h2></center>\n", po->caption);
            else
                fprintf(fout,
                        "<center><h2>"
                        "Query retrieved %d rows * %d fields"
                        "</h2></center>\n",
                        nTups, nFields);
        }
        for (i = 0; i < nTups; i++)
        {
            if (po->expanded)
            {
                if (po->html3)
                    fprintf(fout,
                            "<table %s><caption align=\"top\">%d</caption>\n",
                            po->tableOpt ? po->tableOpt : "", i);
                else
                    fprintf(fout, libpq_gettext("-- RECORD %d --\n"), i);
            }
            for (j = 0; j < nFields; j++)
                do_field(po, res, i, j, fs_len, fields, nFields,
                         fieldNames, fieldNotNum,
                         fieldMax, fieldMaxLen, fout);
            if (po->html3 && po->expanded)
                fputs("</table>\n", fout);
        }
        if (!po->expanded && (po->align || po->html3))
        {
            if (po->html3)
            {
                if (po->header)
                {
                    if (po->caption)
                        fprintf(fout,
                           "<table %s><caption align=\"top\">%s</caption>\n",
                                po->tableOpt ? po->tableOpt : "",
                                po->caption);
                    else
                        fprintf(fout,
                                "<table %s><caption align=\"top\">"
                                "Retrieved %d rows * %d fields"
                                "</caption>\n",
                           po->tableOpt ? po->tableOpt : "", nTups, nFields);
                }
                else
                    fprintf(fout, "<table %s>", po->tableOpt ? po->tableOpt : "");
            }
            if (po->header)
                border = do_header(fout, po, nFields, fieldMax, fieldNames,
                                   fieldNotNum, fs_len, res);
            for (i = 0; i < nTups; i++)
                output_row(fout, po, nFields, fields,
                           fieldNotNum, fieldMax, border, i);
            free(fields);
            if (border)
                free(border);
        }
        if (po->header && !po->html3)
            fprintf(fout, "(%d row%s)\n\n", PQntuples(res),
                    (PQntuples(res) == 1) ? "" : "s");
        free(fieldMax);
        free(fieldNotNum);
        free((void *) fieldNames);
        if (usePipe)
        {
#ifdef WIN32
            _pclose(fout);
#else
            pclose(fout);

#ifdef ENABLE_THREAD_SAFETY
            /* we can't easily verify if EPIPE occurred, so say it did */
            if (sigpipe_masked)
                pq_reset_sigpipe(&osigset, sigpipe_pending, true);
#else
            pqsignal(SIGPIPE, oldsigpipehandler);
#endif   /* ENABLE_THREAD_SAFETY */
#endif   /* WIN32 */
        }
        if (po->html3 && !po->expanded)
            fputs("</table>\n", fout);
    }
}

void PQprintTuples ( const PGresult res,
FILE *  fout,
int  PrintAttNames,
int  TerseOutput,
int  colWidth 
)

Definition at line 671 of file fe-print.c.

References free, i, libpq_gettext, malloc, PQfname(), PQgetvalue(), PQnfields(), and PQntuples().

{
    int         nFields;
    int         nTups;
    int         i,
                j;
    char        formatString[80];
    char       *tborder = NULL;

    nFields = PQnfields(res);
    nTups = PQntuples(res);

    if (colWidth > 0)
        sprintf(formatString, "%%s %%-%ds", colWidth);
    else
        sprintf(formatString, "%%s %%s");

    if (nFields > 0)
    {                           /* only print rows with at least 1 field.  */

        if (!TerseOutput)
        {
            int         width;

            width = nFields * 14;
            tborder = (char *) malloc(width + 1);
            if (!tborder)
            {
                fprintf(stderr, libpq_gettext("out of memory\n"));
                abort();
            }
            for (i = 0; i < width; i++)
                tborder[i] = '-';
            tborder[width] = '\0';
            fprintf(fout, "%s\n", tborder);
        }

        for (i = 0; i < nFields; i++)
        {
            if (PrintAttNames)
            {
                fprintf(fout, formatString,
                        TerseOutput ? "" : "|",
                        PQfname(res, i));
            }
        }

        if (PrintAttNames)
        {
            if (TerseOutput)
                fprintf(fout, "\n");
            else
                fprintf(fout, "|\n%s\n", tborder);
        }

        for (i = 0; i < nTups; i++)
        {
            for (j = 0; j < nFields; j++)
            {
                const char *pval = PQgetvalue(res, i, j);

                fprintf(fout, formatString,
                        TerseOutput ? "" : "|",
                        pval ? pval : "");
            }
            if (TerseOutput)
                fprintf(fout, "\n");
            else
                fprintf(fout, "|\n%s\n", tborder);
        }
    }

    if (tborder)
        free(tborder);
}