OSDN Git Service

Add missing file from Tom Lane.
authorBruce Momjian <bruce@momjian.us>
Thu, 7 May 1998 14:52:52 +0000 (14:52 +0000)
committerBruce Momjian <bruce@momjian.us>
Thu, 7 May 1998 14:52:52 +0000 (14:52 +0000)
src/interfaces/libpq/fe-print.c [new file with mode: 0644]

diff --git a/src/interfaces/libpq/fe-print.c b/src/interfaces/libpq/fe-print.c
new file mode 100644 (file)
index 0000000..2ecccb8
--- /dev/null
@@ -0,0 +1,714 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe-print.c--
+ *       functions for pretty-printing query results
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * These functions were formerly part of fe-exec.c, but they
+ * didn't really belong there.
+ *
+ * IDENTIFICATION
+ *       $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-print.c,v 1.1 1998/05/07 14:52:52 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include "libpq/pqsignal.h"
+#include "libpq-fe.h"
+#ifndef HAVE_TERMIOS_H
+#include <sys/termios.h>
+#else
+#include <termios.h>
+#endif
+
+
+#ifdef TIOCGWINSZ
+static struct winsize screen_size;
+
+#else
+static struct winsize
+{
+       int                     ws_row;
+       int                     ws_col;
+}                      screen_size;
+
+#endif
+
+
+static void
+do_field(PQprintOpt *po, PGresult *res,
+                const int i, const int j, char *buf, const int fs_len,
+                char *fields[],
+                const int nFields, char *fieldNames[],
+                unsigned char fieldNotNum[], int fieldMax[],
+                const int fieldMaxLen, FILE *fout);
+static char *
+do_header(FILE *fout, PQprintOpt *po, const int nFields,
+                 int fieldMax[], char *fieldNames[], unsigned char fieldNotNum[],
+                 const int fs_len, PGresult *res);
+static void
+output_row(FILE *fout, 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);
+
+
+/*
+ * PQprint()
+ *
+ * Format results of a query for printing.
+ *
+ * PQprintOpt is a typedef (structure) that containes
+ * various flags and options. consult libpq-fe.h for
+ * details
+ *
+ * Obsoletes PQprintTuples.
+ */
+
+void
+PQprint(FILE *fout,
+               PGresult *res,
+               PQprintOpt *po)
+{
+       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;
+               char      **fieldNames;
+               int                     fieldMaxLen = 0;
+               int                     numFieldName;
+               int                     fs_len = strlen(po->fieldSep);
+               int                     total_line_length = 0;
+               int                     usePipe = 0;
+               char       *pagerenv;
+               char            buf[8192 * 2 + 1];
+
+               nTups = PQntuples(res);
+               if (!(fieldNames = (char **) calloc(nFields, sizeof(char *))))
+               {
+                       perror("calloc");
+                       exit(1);
+               }
+               if (!(fieldNotNum = (unsigned char *) calloc(nFields, 1)))
+               {
+                       perror("calloc");
+                       exit(1);
+               }
+               if (!(fieldMax = (int *) calloc(nFields, sizeof(int))))
+               {
+                       perror("calloc");
+                       exit(1);
+               }
+               for (numFieldName = 0;
+                        po->fieldName && po->fieldName[numFieldName];
+                        numFieldName++)
+                       ;
+               for (j = 0; j < nFields; j++)
+               {
+                       int                     len;
+                       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)))
+               {
+                       /* try to pipe to the pager program if possible */
+#ifdef TIOCGWINSZ
+                       if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 ||
+                               screen_size.ws_col == 0 ||
+                               screen_size.ws_row == 0)
+                       {
+#endif
+                               screen_size.ws_row = 24;
+                               screen_size.ws_col = 80;
+#ifdef TIOCGWINSZ
+                       }
+#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;
+                                       pqsignal(SIGPIPE, SIG_IGN);
+                               }
+                               else
+                                       fout = stdout;
+                       }
+               }
+
+               if (!po->expanded && (po->align || po->html3))
+               {
+                       if (!(fields = (char **) calloc(nFields * (nTups + 1), sizeof(char *))))
+                       {
+                               perror("calloc");
+                               exit(1);
+                       }
+               }
+               else if (po->header && !po->html3)
+               {
+                       if (po->expanded)
+                       {
+                               if (po->align)
+                                       fprintf(fout, "%-*s%s Value\n",
+                                                       fieldMaxLen - fs_len, "Field", po->fieldSep);
+                               else
+                                       fprintf(fout, "%s%sValue\n", "Field", po->fieldSep);
+                       }
+                       else
+                       {
+                               int                     len = 0;
+
+                               for (j = 0; j < nFields; j++)
+                               {
+                                       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, "<centre><h2>%s</h2></centre>\n", po->caption);
+                       else
+                               fprintf(fout,
+                                               "<centre><h2>"
+                                               "Query retrieved %d rows * %d fields"
+                                               "</h2></centre>\n",
+                                               nTups, nFields);
+               }
+               for (i = 0; i < nTups; i++)
+               {
+                       if (po->expanded)
+                       {
+                               if (po->html3)
+                                       fprintf(fout,
+                                                 "<table %s><caption align=high>%d</caption>\n",
+                                                       po->tableOpt ? po->tableOpt : "", i);
+                               else
+                                       fprintf(fout, "-- RECORD %d --\n", i);
+                       }
+                       for (j = 0; j < nFields; j++)
+                               do_field(po, res, i, j, buf, 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=high>%s</caption>\n",
+                                                               po->tableOpt ? po->tableOpt : "",
+                                                               po->caption);
+                                       else
+                                               fprintf(fout,
+                                                               "<table %s><caption align=high>"
+                                                               "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(fieldNames);
+               if (usePipe)
+               {
+                       pclose(fout);
+                       pqsignal(SIGPIPE, SIG_DFL);
+               }
+               if (po->html3 && !po->expanded)
+                       fputs("</table>\n", fout);
+       }
+}
+
+
+/*
+ * PQdisplayTuples()
+ * kept for backward compatibility
+ */
+
+void
+PQdisplayTuples(PGresult *res,
+                               FILE *fp,               /* where to send the output */
+                               int fillAlign,  /* pad the fields with spaces */
+                               const char *fieldSep,   /* field separator */
+                               int printHeader,/* display headers? */
+                               int quiet
+)
+{
+#define DEFAULT_FIELD_SEP " "
+
+       int                     i,
+                               j;
+       int                     nFields;
+       int                     nTuples;
+       int                     fLength[MAX_FIELDS];
+
+       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;
+
+       /* Zero the initial field lengths */
+       for (j = 0; j < nFields; j++)
+       {
+               fLength[j] = strlen(PQfname(res, j));
+       }
+       /* Find the max length of each field in the result */
+       /* will be somewhat time consuming for very large results */
+       if (fillAlign)
+       {
+               for (i = 0; i < nTuples; i++)
+               {
+                       for (j = 0; j < nFields; j++)
+                       {
+                               if (PQgetlength(res, i, j) > fLength[j])
+                                       fLength[j] = PQgetlength(res, i, j);
+                       }
+               }
+       }
+
+       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);
+}
+
+
+
+/*
+ * PQprintTuples()
+ *
+ * kept for backward compatibility
+ *
+ */
+void
+PQprintTuples(PGresult *res,
+                         FILE *fout,           /* output stream */
+                         int PrintAttNames,/* print attribute names or not */
+                         int TerseOutput,      /* delimiter bars or not? */
+                         int colWidth          /* width of column, if 0, use variable
+                                                                * width */
+)
+{
+       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 = malloc(width + 1);
+                       for (i = 0; i <= width; i++)
+                               tborder[i] = '-';
+                       tborder[i] = '\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++)
+                       {
+                               char       *pval = PQgetvalue(res, i, j);
+
+                               fprintf(fout, formatString,
+                                               TerseOutput ? "" : "|",
+                                               pval ? pval : "");
+                       }
+                       if (TerseOutput)
+                               fprintf(fout, "\n");
+                       else
+                               fprintf(fout, "|\n%s\n", tborder);
+               }
+       }
+}
+
+
+
+static void
+do_field(PQprintOpt *po, PGresult *res,
+                const int i, const int j, char *buf, const int fs_len,
+                char *fields[],
+                const int nFields, char *fieldNames[],
+                unsigned char fieldNotNum[], int fieldMax[],
+                const int fieldMaxLen, FILE *fout)
+{
+
+       char       *pval,
+                          *p,
+                          *o;
+       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)
+       {
+               for (p = pval, o = buf; *p; *(o++) = *(p++))
+               {
+                       if ((fs_len == 1 && (*p == *(po->fieldSep))) || *p == '\\' || *p == '\n')
+                               *(o++) = '\\';
+                       if (po->align && (*pval == 'E' || *pval == 'e' ||
+                                                         !((*p >= '0' && *p <= '9') ||
+                                                               *p == '.' ||
+                                                               *p == 'E' ||
+                                                               *p == 'e' ||
+                                                               *p == ' ' ||
+                                                               *p == '-')))
+                               fieldNotNum[j] = 1;
+               }
+               *o = '\0';
+               if (!po->expanded && (po->align || po->html3))
+               {
+                       int                     n = strlen(buf);
+
+                       if (n > fieldMax[j])
+                               fieldMax[j] = n;
+                       if (!(fields[i * nFields + j] = (char *) malloc(n + 1)))
+                       {
+                               perror("malloc");
+                               exit(1);
+                       }
+                       strcpy(fields[i * nFields + j], buf);
+               }
+               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",
+                                                       buf);
+                               else
+                               {
+                                       if (po->align)
+                                               fprintf(fout,
+                                                               "%-*s%s %s\n",
+                                               fieldMaxLen - fs_len, fieldNames[j], po->fieldSep,
+                                                               buf);
+                                       else
+                                               fprintf(fout, "%s%s%s\n", fieldNames[j], po->fieldSep, buf);
+                               }
+                       }
+                       else
+                       {
+                               if (!po->html3)
+                               {
+                                       fputs(buf, fout);
+                       efield:
+                                       if ((j + 1) < nFields)
+                                               fputs(po->fieldSep, fout);
+                                       else
+                                               fputc('\n', fout);
+                               }
+                       }
+               }
+       }
+}
+
+
+static char *
+do_header(FILE *fout, PQprintOpt *po, const int nFields, int fieldMax[],
+                 char *fieldNames[], unsigned char fieldNotNum[],
+                 const int fs_len, PGresult *res)
+{
+
+       int                     j;                              /* for loop index */
+       char       *border = NULL;
+
+       if (po->html3)
+               fputs("<tr>", fout);
+       else
+       {
+               int                     j;                      /* for loop index */
+               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)
+               {
+                       perror("malloc");
+                       exit(1);
+               }
+               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++)
+       {
+               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
+output_row(FILE *fout, PQprintOpt *po, const int nFields, char *fields[],
+                  unsigned char fieldNotNum[], int fieldMax[], char *border,
+                  const int row_index)
+{
+
+       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);
+}
+
+
+/* simply send out max-length number of filler characters to fp */
+
+static void
+fill(int length, int max, char filler, FILE *fp)
+{
+       int                     count;
+
+       count = max - length;
+       while (count-- >= 0)
+               putc(filler, fp);
+}