#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"
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 DEFAULT_FIELD_SEP " " |
| 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);
}
1.7.1