LCOV - code coverage report
Current view: top level - src/interfaces/libpq - fe-print.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 440 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 7 0
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 0.0 % 345 0

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * fe-print.c
       4                 :             :  *        functions for pretty-printing query results
       5                 :             :  *
       6                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :             :  *
       9                 :             :  * These functions were formerly part of fe-exec.c, but they
      10                 :             :  * didn't really belong there.
      11                 :             :  *
      12                 :             :  * IDENTIFICATION
      13                 :             :  *        src/interfaces/libpq/fe-print.c
      14                 :             :  *
      15                 :             :  *-------------------------------------------------------------------------
      16                 :             :  */
      17                 :             : #include "postgres_fe.h"
      18                 :             : 
      19                 :             : #include <signal.h>
      20                 :             : 
      21                 :             : #ifdef WIN32
      22                 :             : #include "win32.h"
      23                 :             : #else
      24                 :             : #include <unistd.h>
      25                 :             : #include <sys/ioctl.h>
      26                 :             : #endif
      27                 :             : 
      28                 :             : #ifdef HAVE_TERMIOS_H
      29                 :             : #include <termios.h>
      30                 :             : #else
      31                 :             : #ifndef WIN32
      32                 :             : #include <sys/termios.h>
      33                 :             : #endif
      34                 :             : #endif
      35                 :             : 
      36                 :             : #include "common/int.h"
      37                 :             : #include "libpq-fe.h"
      38                 :             : #include "libpq-int.h"
      39                 :             : 
      40                 :             : 
      41                 :             : static bool do_field(const PQprintOpt *po, const PGresult *res,
      42                 :             :                                          const int i, const int j, const int fs_len,
      43                 :             :                                          char **fields,
      44                 :             :                                          const int nFields, const char **fieldNames,
      45                 :             :                                          unsigned char *fieldNotNum, int *fieldMax,
      46                 :             :                                          const int fieldMaxLen, FILE *fout);
      47                 :             : static char *do_header(FILE *fout, const PQprintOpt *po, const int nFields,
      48                 :             :                                            int *fieldMax, const char **fieldNames, unsigned char *fieldNotNum,
      49                 :             :                                            const int fs_len, const PGresult *res);
      50                 :             : static void output_row(FILE *fout, const PQprintOpt *po, const int nFields, char **fields,
      51                 :             :                                            unsigned char *fieldNotNum, int *fieldMax, char *border,
      52                 :             :                                            const int row_index);
      53                 :             : static void fill(int length, int max, char filler, FILE *fp);
      54                 :             : 
      55                 :             : /*
      56                 :             :  * PQprint()
      57                 :             :  *
      58                 :             :  * Format results of a query for printing.
      59                 :             :  *
      60                 :             :  * PQprintOpt is a typedef (structure) that contains
      61                 :             :  * various flags and options. consult libpq-fe.h for
      62                 :             :  * details
      63                 :             :  *
      64                 :             :  * This function should probably be removed sometime since psql
      65                 :             :  * doesn't use it anymore. It is unclear to what extent this is used
      66                 :             :  * by external clients, however.
      67                 :             :  */
      68                 :             : void
      69                 :           0 : PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
      70                 :             : {
      71                 :           0 :         int                     nFields;
      72                 :             : 
      73                 :           0 :         nFields = PQnfields(res);
      74                 :             : 
      75         [ #  # ]:           0 :         if (nFields > 0)
      76                 :             :         {                                                       /* only print rows with at least 1 field.  */
      77                 :           0 :                 int                     i,
      78                 :             :                                         j;
      79                 :           0 :                 int                     nTups;
      80                 :           0 :                 int                *fieldMax = NULL;    /* in case we don't use them */
      81                 :           0 :                 unsigned char *fieldNotNum = NULL;
      82                 :           0 :                 char       *border = NULL;
      83                 :           0 :                 char      **fields = NULL;
      84                 :           0 :                 const char **fieldNames = NULL;
      85                 :           0 :                 int                     fieldMaxLen = 0;
      86                 :           0 :                 int                     numFieldName;
      87                 :           0 :                 int                     fs_len = strlen(po->fieldSep);
      88                 :           0 :                 int                     total_line_length = 0;
      89                 :           0 :                 bool            usePipe = false;
      90                 :           0 :                 char       *pagerenv;
      91                 :             : 
      92                 :             : #if !defined(WIN32)
      93                 :           0 :                 sigset_t        osigset;
      94                 :           0 :                 bool            sigpipe_masked = false;
      95                 :           0 :                 bool            sigpipe_pending;
      96                 :             : #endif
      97                 :             : 
      98                 :             : #ifdef TIOCGWINSZ
      99                 :           0 :                 struct winsize screen_size;
     100                 :             : #else
     101                 :             :                 struct winsize
     102                 :             :                 {
     103                 :             :                         int                     ws_row;
     104                 :             :                         int                     ws_col;
     105                 :             :                 }                       screen_size;
     106                 :             : #endif
     107                 :             : 
     108                 :             :                 /*
     109                 :             :                  * Quick sanity check on po->fieldSep, since we make heavy use of int
     110                 :             :                  * math throughout.
     111                 :             :                  */
     112         [ #  # ]:           0 :                 if (fs_len < strlen(po->fieldSep))
     113                 :             :                 {
     114                 :           0 :                         fprintf(stderr, libpq_gettext("overlong field separator\n"));
     115                 :           0 :                         goto exit;
     116                 :             :                 }
     117                 :             : 
     118                 :           0 :                 nTups = PQntuples(res);
     119                 :           0 :                 fieldNames = (const char **) calloc(nFields, sizeof(char *));
     120                 :           0 :                 fieldNotNum = (unsigned char *) calloc(nFields, 1);
     121                 :           0 :                 fieldMax = (int *) calloc(nFields, sizeof(int));
     122   [ #  #  #  #  :           0 :                 if (!fieldNames || !fieldNotNum || !fieldMax)
                   #  # ]
     123                 :             :                 {
     124                 :           0 :                         fprintf(stderr, libpq_gettext("out of memory\n"));
     125                 :           0 :                         goto exit;
     126                 :             :                 }
     127         [ #  # ]:           0 :                 for (numFieldName = 0;
     128         [ #  # ]:           0 :                          po->fieldName && po->fieldName[numFieldName];
     129                 :           0 :                          numFieldName++)
     130                 :             :                         ;
     131         [ #  # ]:           0 :                 for (j = 0; j < nFields; j++)
     132                 :             :                 {
     133                 :           0 :                         int                     len;
     134   [ #  #  #  # ]:           0 :                         const char *s = (j < numFieldName && po->fieldName[j][0]) ?
     135                 :           0 :                                 po->fieldName[j] : PQfname(res, j);
     136                 :             : 
     137                 :           0 :                         fieldNames[j] = s;
     138         [ #  # ]:           0 :                         len = s ? strlen(s) : 0;
     139                 :           0 :                         fieldMax[j] = len;
     140                 :           0 :                         len += fs_len;
     141         [ #  # ]:           0 :                         if (len > fieldMaxLen)
     142                 :           0 :                                 fieldMaxLen = len;
     143                 :           0 :                         total_line_length += len;
     144                 :           0 :                 }
     145                 :             : 
     146                 :           0 :                 total_line_length += nFields * strlen(po->fieldSep) + 1;
     147                 :             : 
     148         [ #  # ]:           0 :                 if (fout == NULL)
     149                 :           0 :                         fout = stdout;
     150   [ #  #  #  #  :           0 :                 if (po->pager && fout == stdout && isatty(fileno(stdin)) &&
             #  #  #  # ]
     151                 :           0 :                         isatty(fileno(stdout)))
     152                 :             :                 {
     153                 :             :                         /*
     154                 :             :                          * If we think there'll be more than one screen of output, try to
     155                 :             :                          * pipe to the pager program.
     156                 :             :                          */
     157                 :             : #ifdef TIOCGWINSZ
     158         [ #  # ]:           0 :                         if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 ||
     159   [ #  #  #  # ]:           0 :                                 screen_size.ws_col == 0 ||
     160                 :           0 :                                 screen_size.ws_row == 0)
     161                 :             :                         {
     162                 :           0 :                                 screen_size.ws_row = 24;
     163                 :           0 :                                 screen_size.ws_col = 80;
     164                 :           0 :                         }
     165                 :             : #else
     166                 :             :                         screen_size.ws_row = 24;
     167                 :             :                         screen_size.ws_col = 80;
     168                 :             : #endif
     169                 :             : 
     170                 :             :                         /*
     171                 :             :                          * Since this function is no longer used by psql, we don't examine
     172                 :             :                          * PSQL_PAGER.  It's possible that the hypothetical external users
     173                 :             :                          * of the function would like that to happen, but in the name of
     174                 :             :                          * backwards compatibility, we'll stick to just examining PAGER.
     175                 :             :                          */
     176                 :           0 :                         pagerenv = getenv("PAGER");
     177                 :             :                         /* if PAGER is unset, empty or all-white-space, don't use pager */
     178         [ #  # ]:           0 :                         if (pagerenv != NULL &&
     179         [ #  # ]:           0 :                                 strspn(pagerenv, " \t\r\n") != strlen(pagerenv) &&
     180         [ #  # ]:           0 :                                 !po->html3 &&
     181         [ #  # ]:           0 :                                 ((po->expanded &&
     182         [ #  # ]:           0 :                                   nTups * (nFields + 1) >= screen_size.ws_row) ||
     183         [ #  # ]:           0 :                                  (!po->expanded &&
     184                 :           0 :                                   nTups * (total_line_length / screen_size.ws_col + 1) *
     185                 :           0 :                                   (1 + (po->standard != 0)) >= screen_size.ws_row -
     186                 :           0 :                                   (po->header != 0) *
     187                 :           0 :                                   (total_line_length / screen_size.ws_col + 1) * 2
     188                 :           0 :                                   - (po->header != 0) * 2    /* row count and newline */
     189                 :             :                                   )))
     190                 :             :                         {
     191                 :           0 :                                 fflush(NULL);
     192                 :           0 :                                 fout = popen(pagerenv, "w");
     193         [ #  # ]:           0 :                                 if (fout)
     194                 :             :                                 {
     195                 :           0 :                                         usePipe = true;
     196                 :             : #ifndef WIN32
     197         [ #  # ]:           0 :                                         if (pq_block_sigpipe(&osigset, &sigpipe_pending) == 0)
     198                 :           0 :                                                 sigpipe_masked = true;
     199                 :             : #endif                                                  /* WIN32 */
     200                 :           0 :                                 }
     201                 :             :                                 else
     202                 :           0 :                                         fout = stdout;
     203                 :           0 :                         }
     204                 :           0 :                 }
     205                 :             : 
     206   [ #  #  #  #  :           0 :                 if (!po->expanded && (po->align || po->html3))
                   #  # ]
     207                 :             :                 {
     208                 :           0 :                         fields = (char **) calloc((size_t) nTups + 1,
     209                 :           0 :                                                                           nFields * sizeof(char *));
     210         [ #  # ]:           0 :                         if (!fields)
     211                 :             :                         {
     212                 :           0 :                                 fprintf(stderr, libpq_gettext("out of memory\n"));
     213                 :           0 :                                 goto exit;
     214                 :             :                         }
     215                 :           0 :                 }
     216   [ #  #  #  # ]:           0 :                 else if (po->header && !po->html3)
     217                 :             :                 {
     218         [ #  # ]:           0 :                         if (po->expanded)
     219                 :             :                         {
     220         [ #  # ]:           0 :                                 if (po->align)
     221                 :           0 :                                         fprintf(fout, libpq_gettext("%-*s%s Value\n"),
     222                 :           0 :                                                         fieldMaxLen - fs_len, libpq_gettext("Field"), po->fieldSep);
     223                 :             :                                 else
     224                 :           0 :                                         fprintf(fout, libpq_gettext("%s%sValue\n"), libpq_gettext("Field"), po->fieldSep);
     225                 :           0 :                         }
     226                 :             :                         else
     227                 :             :                         {
     228                 :           0 :                                 int                     len = 0;
     229                 :             : 
     230         [ #  # ]:           0 :                                 for (j = 0; j < nFields; j++)
     231                 :             :                                 {
     232                 :           0 :                                         const char *s = fieldNames[j];
     233                 :             : 
     234                 :           0 :                                         fputs(s, fout);
     235                 :           0 :                                         len += strlen(s) + fs_len;
     236         [ #  # ]:           0 :                                         if ((j + 1) < nFields)
     237                 :           0 :                                                 fputs(po->fieldSep, fout);
     238                 :           0 :                                 }
     239                 :           0 :                                 fputc('\n', fout);
     240         [ #  # ]:           0 :                                 for (len -= fs_len; len--; fputc('-', fout));
     241                 :           0 :                                 fputc('\n', fout);
     242                 :           0 :                         }
     243                 :           0 :                 }
     244   [ #  #  #  # ]:           0 :                 if (po->expanded && po->html3)
     245                 :             :                 {
     246         [ #  # ]:           0 :                         if (po->caption)
     247                 :           0 :                                 fprintf(fout, "<center><h2>%s</h2></center>\n", po->caption);
     248                 :             :                         else
     249                 :           0 :                                 fprintf(fout,
     250                 :             :                                                 "<center><h2>"
     251                 :             :                                                 "Query retrieved %d rows * %d fields"
     252                 :             :                                                 "</h2></center>\n",
     253                 :           0 :                                                 nTups, nFields);
     254                 :           0 :                 }
     255         [ #  # ]:           0 :                 for (i = 0; i < nTups; i++)
     256                 :             :                 {
     257         [ #  # ]:           0 :                         if (po->expanded)
     258                 :             :                         {
     259         [ #  # ]:           0 :                                 if (po->html3)
     260                 :           0 :                                         fprintf(fout,
     261                 :             :                                                         "<table %s><caption align=\"top\">%d</caption>\n",
     262         [ #  # ]:           0 :                                                         po->tableOpt ? po->tableOpt : "", i);
     263                 :             :                                 else
     264                 :           0 :                                         fprintf(fout, libpq_gettext("-- RECORD %d --\n"), i);
     265                 :           0 :                         }
     266         [ #  # ]:           0 :                         for (j = 0; j < nFields; j++)
     267                 :             :                         {
     268   [ #  #  #  # ]:           0 :                                 if (!do_field(po, res, i, j, fs_len, fields, nFields,
     269                 :           0 :                                                           fieldNames, fieldNotNum,
     270                 :           0 :                                                           fieldMax, fieldMaxLen, fout))
     271                 :           0 :                                         goto exit;
     272                 :           0 :                         }
     273   [ #  #  #  # ]:           0 :                         if (po->html3 && po->expanded)
     274                 :           0 :                                 fputs("</table>\n", fout);
     275                 :           0 :                 }
     276   [ #  #  #  #  :           0 :                 if (!po->expanded && (po->align || po->html3))
                   #  # ]
     277                 :             :                 {
     278         [ #  # ]:           0 :                         if (po->html3)
     279                 :             :                         {
     280         [ #  # ]:           0 :                                 if (po->header)
     281                 :             :                                 {
     282         [ #  # ]:           0 :                                         if (po->caption)
     283                 :           0 :                                                 fprintf(fout,
     284                 :             :                                                                 "<table %s><caption align=\"top\">%s</caption>\n",
     285         [ #  # ]:           0 :                                                                 po->tableOpt ? po->tableOpt : "",
     286                 :           0 :                                                                 po->caption);
     287                 :             :                                         else
     288                 :           0 :                                                 fprintf(fout,
     289                 :             :                                                                 "<table %s><caption align=\"top\">"
     290                 :             :                                                                 "Retrieved %d rows * %d fields"
     291                 :             :                                                                 "</caption>\n",
     292         [ #  # ]:           0 :                                                                 po->tableOpt ? po->tableOpt : "", nTups, nFields);
     293                 :           0 :                                 }
     294                 :             :                                 else
     295         [ #  # ]:           0 :                                         fprintf(fout, "<table %s>", po->tableOpt ? po->tableOpt : "");
     296                 :           0 :                         }
     297         [ #  # ]:           0 :                         if (po->header)
     298                 :           0 :                                 border = do_header(fout, po, nFields, fieldMax, fieldNames,
     299                 :           0 :                                                                    fieldNotNum, fs_len, res);
     300         [ #  # ]:           0 :                         for (i = 0; i < nTups; i++)
     301                 :           0 :                                 output_row(fout, po, nFields, fields,
     302                 :           0 :                                                    fieldNotNum, fieldMax, border, i);
     303                 :           0 :                 }
     304   [ #  #  #  # ]:           0 :                 if (po->header && !po->html3)
     305                 :           0 :                         fprintf(fout, "(%d row%s)\n\n", PQntuples(res),
     306                 :           0 :                                         (PQntuples(res) == 1) ? "" : "s");
     307   [ #  #  #  # ]:           0 :                 if (po->html3 && !po->expanded)
     308                 :           0 :                         fputs("</table>\n", fout);
     309                 :             : 
     310                 :             : exit:
     311                 :           0 :                 free(fieldMax);
     312                 :           0 :                 free(fieldNotNum);
     313                 :           0 :                 free(border);
     314         [ #  # ]:           0 :                 if (fields)
     315                 :             :                 {
     316                 :             :                         /* if calloc succeeded, this shouldn't overflow size_t */
     317                 :           0 :                         size_t          numfields = ((size_t) nTups + 1) * (size_t) nFields;
     318                 :             : 
     319         [ #  # ]:           0 :                         while (numfields-- > 0)
     320                 :           0 :                                 free(fields[numfields]);
     321                 :           0 :                         free(fields);
     322                 :           0 :                 }
     323                 :           0 :                 free(fieldNames);
     324         [ #  # ]:           0 :                 if (usePipe)
     325                 :             :                 {
     326                 :             : #ifdef WIN32
     327                 :             :                         _pclose(fout);
     328                 :             : #else
     329                 :           0 :                         pclose(fout);
     330                 :             : 
     331                 :             :                         /* we can't easily verify if EPIPE occurred, so say it did */
     332         [ #  # ]:           0 :                         if (sigpipe_masked)
     333                 :           0 :                                 pq_reset_sigpipe(&osigset, sigpipe_pending, true);
     334                 :             : #endif                                                  /* WIN32 */
     335                 :           0 :                 }
     336                 :           0 :         }
     337                 :           0 : }
     338                 :             : 
     339                 :             : 
     340                 :             : static bool
     341                 :           0 : do_field(const PQprintOpt *po, const PGresult *res,
     342                 :             :                  const int i, const int j, const int fs_len,
     343                 :             :                  char **fields,
     344                 :             :                  const int nFields, char const **fieldNames,
     345                 :             :                  unsigned char *fieldNotNum, int *fieldMax,
     346                 :             :                  const int fieldMaxLen, FILE *fout)
     347                 :             : {
     348                 :           0 :         const char *pval,
     349                 :             :                            *p;
     350                 :           0 :         int                     plen;
     351                 :           0 :         bool            skipit;
     352                 :             : 
     353                 :           0 :         plen = PQgetlength(res, i, j);
     354                 :           0 :         pval = PQgetvalue(res, i, j);
     355                 :             : 
     356   [ #  #  #  #  :           0 :         if (plen < 1 || !pval || !*pval)
                   #  # ]
     357                 :             :         {
     358   [ #  #  #  # ]:           0 :                 if (po->align || po->expanded)
     359                 :           0 :                         skipit = true;
     360                 :             :                 else
     361                 :             :                 {
     362                 :           0 :                         skipit = false;
     363                 :           0 :                         goto efield;
     364                 :             :                 }
     365                 :           0 :         }
     366                 :             :         else
     367                 :           0 :                 skipit = false;
     368                 :             : 
     369         [ #  # ]:           0 :         if (!skipit)
     370                 :             :         {
     371   [ #  #  #  # ]:           0 :                 if (po->align && !fieldNotNum[j])
     372                 :             :                 {
     373                 :             :                         /* Detect whether field contains non-numeric data */
     374                 :           0 :                         char            ch = '0';
     375                 :             : 
     376         [ #  # ]:           0 :                         for (p = pval; *p; p += PQmblenBounded(p, res->client_encoding))
     377                 :             :                         {
     378                 :           0 :                                 ch = *p;
     379   [ #  #  #  # ]:           0 :                                 if (!((ch >= '0' && ch <= '9') ||
     380         [ #  # ]:           0 :                                           ch == '.' ||
     381         [ #  # ]:           0 :                                           ch == 'E' ||
     382         [ #  # ]:           0 :                                           ch == 'e' ||
     383         [ #  # ]:           0 :                                           ch == ' ' ||
     384                 :           0 :                                           ch == '-'))
     385                 :             :                                 {
     386                 :           0 :                                         fieldNotNum[j] = 1;
     387                 :           0 :                                         break;
     388                 :             :                                 }
     389                 :           0 :                         }
     390                 :             : 
     391                 :             :                         /*
     392                 :             :                          * Above loop will believe E in first column is numeric; also, we
     393                 :             :                          * insist on a digit in the last column for a numeric. This test
     394                 :             :                          * is still not bulletproof but it handles most cases.
     395                 :             :                          */
     396   [ #  #  #  #  :           0 :                         if (*pval == 'E' || *pval == 'e' ||
                   #  # ]
     397         [ #  # ]:           0 :                                 !(ch >= '0' && ch <= '9'))
     398                 :           0 :                                 fieldNotNum[j] = 1;
     399                 :           0 :                 }
     400                 :             : 
     401   [ #  #  #  #  :           0 :                 if (!po->expanded && (po->align || po->html3))
                   #  # ]
     402                 :             :                 {
     403         [ #  # ]:           0 :                         if (plen > fieldMax[j])
     404                 :           0 :                                 fieldMax[j] = plen;
     405         [ #  # ]:           0 :                         if (!(fields[i * nFields + j] = (char *) malloc((size_t) plen + 1)))
     406                 :             :                         {
     407                 :           0 :                                 fprintf(stderr, libpq_gettext("out of memory\n"));
     408                 :           0 :                                 return false;
     409                 :             :                         }
     410                 :           0 :                         strcpy(fields[i * nFields + j], pval);
     411                 :           0 :                 }
     412                 :             :                 else
     413                 :             :                 {
     414         [ #  # ]:           0 :                         if (po->expanded)
     415                 :             :                         {
     416         [ #  # ]:           0 :                                 if (po->html3)
     417                 :           0 :                                         fprintf(fout,
     418                 :             :                                                         "<tr><td align=\"left\"><b>%s</b></td>"
     419                 :             :                                                         "<td align=\"%s\">%s</td></tr>\n",
     420                 :           0 :                                                         fieldNames[j],
     421                 :           0 :                                                         fieldNotNum[j] ? "left" : "right",
     422                 :           0 :                                                         pval);
     423                 :             :                                 else
     424                 :             :                                 {
     425         [ #  # ]:           0 :                                         if (po->align)
     426                 :           0 :                                                 fprintf(fout,
     427                 :             :                                                                 "%-*s%s %s\n",
     428                 :           0 :                                                                 fieldMaxLen - fs_len, fieldNames[j],
     429                 :           0 :                                                                 po->fieldSep,
     430                 :           0 :                                                                 pval);
     431                 :             :                                         else
     432                 :           0 :                                                 fprintf(fout,
     433                 :             :                                                                 "%s%s%s\n",
     434                 :           0 :                                                                 fieldNames[j], po->fieldSep, pval);
     435                 :             :                                 }
     436                 :           0 :                         }
     437                 :             :                         else
     438                 :             :                         {
     439         [ #  # ]:           0 :                                 if (!po->html3)
     440                 :             :                                 {
     441                 :           0 :                                         fputs(pval, fout);
     442                 :             :                         efield:
     443         [ #  # ]:           0 :                                         if ((j + 1) < nFields)
     444                 :           0 :                                                 fputs(po->fieldSep, fout);
     445                 :             :                                         else
     446                 :           0 :                                                 fputc('\n', fout);
     447                 :           0 :                                 }
     448                 :             :                         }
     449                 :             :                 }
     450                 :           0 :         }
     451                 :           0 :         return true;
     452                 :           0 : }
     453                 :             : 
     454                 :             : 
     455                 :             : static char *
     456                 :           0 : do_header(FILE *fout, const PQprintOpt *po, const int nFields, int *fieldMax,
     457                 :             :                   const char **fieldNames, unsigned char *fieldNotNum,
     458                 :             :                   const int fs_len, const PGresult *res)
     459                 :             : {
     460                 :           0 :         int                     j;                              /* for loop index */
     461                 :           0 :         char       *border = NULL;
     462                 :             : 
     463         [ #  # ]:           0 :         if (po->html3)
     464                 :           0 :                 fputs("<tr>", fout);
     465                 :             :         else
     466                 :             :         {
     467                 :           0 :                 size_t          tot = 0;
     468                 :           0 :                 int                     n = 0;
     469                 :           0 :                 char       *p = NULL;
     470                 :             : 
     471                 :             :                 /* Calculate the border size, checking for overflow. */
     472         [ #  # ]:           0 :                 for (; n < nFields; n++)
     473                 :             :                 {
     474                 :             :                         /* Field plus separator, plus 2 extra '-' in standard format. */
     475         [ #  # ]:           0 :                         if (pg_add_size_overflow(tot, fieldMax[n], &tot) ||
     476   [ #  #  #  # ]:           0 :                                 pg_add_size_overflow(tot, fs_len, &tot) ||
     477         [ #  # ]:           0 :                                 (po->standard && pg_add_size_overflow(tot, 2, &tot)))
     478                 :           0 :                                 goto overflow;
     479                 :           0 :                 }
     480         [ #  # ]:           0 :                 if (po->standard)
     481                 :             :                 {
     482                 :             :                         /* An extra separator at the front and back. */
     483         [ #  # ]:           0 :                         if (pg_add_size_overflow(tot, fs_len, &tot) ||
     484   [ #  #  #  # ]:           0 :                                 pg_add_size_overflow(tot, fs_len, &tot) ||
     485                 :           0 :                                 pg_add_size_overflow(tot, 2, &tot))
     486                 :           0 :                                 goto overflow;
     487                 :           0 :                 }
     488         [ #  # ]:           0 :                 if (pg_add_size_overflow(tot, 1, &tot)) /* terminator */
     489                 :           0 :                         goto overflow;
     490                 :             : 
     491                 :           0 :                 border = malloc(tot);
     492         [ #  # ]:           0 :                 if (!border)
     493                 :             :                 {
     494                 :           0 :                         fprintf(stderr, libpq_gettext("out of memory\n"));
     495                 :           0 :                         return NULL;
     496                 :             :                 }
     497                 :           0 :                 p = border;
     498         [ #  # ]:           0 :                 if (po->standard)
     499                 :             :                 {
     500                 :           0 :                         char       *fs = po->fieldSep;
     501                 :             : 
     502         [ #  # ]:           0 :                         while (*fs++)
     503                 :           0 :                                 *p++ = '+';
     504                 :           0 :                 }
     505         [ #  # ]:           0 :                 for (j = 0; j < nFields; j++)
     506                 :             :                 {
     507                 :           0 :                         int                     len;
     508                 :             : 
     509         [ #  # ]:           0 :                         for (len = fieldMax[j] + (po->standard ? 2 : 0); len--; *p++ = '-');
     510   [ #  #  #  # ]:           0 :                         if (po->standard || (j + 1) < nFields)
     511                 :             :                         {
     512                 :           0 :                                 char       *fs = po->fieldSep;
     513                 :             : 
     514         [ #  # ]:           0 :                                 while (*fs++)
     515                 :           0 :                                         *p++ = '+';
     516                 :           0 :                         }
     517                 :           0 :                 }
     518                 :           0 :                 *p = '\0';
     519         [ #  # ]:           0 :                 if (po->standard)
     520                 :           0 :                         fprintf(fout, "%s\n", border);
     521      [ #  #  # ]:           0 :         }
     522         [ #  # ]:           0 :         if (po->standard)
     523                 :           0 :                 fputs(po->fieldSep, fout);
     524         [ #  # ]:           0 :         for (j = 0; j < nFields; j++)
     525                 :             :         {
     526                 :           0 :                 const char *s = PQfname(res, j);
     527                 :             : 
     528         [ #  # ]:           0 :                 if (po->html3)
     529                 :             :                 {
     530                 :           0 :                         fprintf(fout, "<th align=\"%s\">%s</th>",
     531                 :           0 :                                         fieldNotNum[j] ? "left" : "right", fieldNames[j]);
     532                 :           0 :                 }
     533                 :             :                 else
     534                 :             :                 {
     535                 :           0 :                         int                     n = strlen(s);
     536                 :             : 
     537         [ #  # ]:           0 :                         if (n > fieldMax[j])
     538                 :           0 :                                 fieldMax[j] = n;
     539         [ #  # ]:           0 :                         if (po->standard)
     540                 :           0 :                                 fprintf(fout,
     541                 :           0 :                                                 fieldNotNum[j] ? " %-*s " : " %*s ",
     542                 :           0 :                                                 fieldMax[j], s);
     543                 :             :                         else
     544                 :           0 :                                 fprintf(fout, fieldNotNum[j] ? "%-*s" : "%*s", fieldMax[j], s);
     545   [ #  #  #  # ]:           0 :                         if (po->standard || (j + 1) < nFields)
     546                 :           0 :                                 fputs(po->fieldSep, fout);
     547                 :           0 :                 }
     548                 :           0 :         }
     549         [ #  # ]:           0 :         if (po->html3)
     550                 :           0 :                 fputs("</tr>\n", fout);
     551                 :             :         else
     552                 :           0 :                 fprintf(fout, "\n%s\n", border);
     553                 :           0 :         return border;
     554                 :             : 
     555                 :             : overflow:
     556                 :           0 :         fprintf(stderr, libpq_gettext("header size exceeds the maximum allowed\n"));
     557                 :           0 :         return NULL;
     558                 :           0 : }
     559                 :             : 
     560                 :             : 
     561                 :             : static void
     562                 :           0 : output_row(FILE *fout, const PQprintOpt *po, const int nFields, char **fields,
     563                 :             :                    unsigned char *fieldNotNum, int *fieldMax, char *border,
     564                 :             :                    const int row_index)
     565                 :             : {
     566                 :           0 :         int                     field_index;    /* for loop index */
     567                 :             : 
     568         [ #  # ]:           0 :         if (po->html3)
     569                 :           0 :                 fputs("<tr>", fout);
     570         [ #  # ]:           0 :         else if (po->standard)
     571                 :           0 :                 fputs(po->fieldSep, fout);
     572         [ #  # ]:           0 :         for (field_index = 0; field_index < nFields; field_index++)
     573                 :             :         {
     574                 :           0 :                 char       *p = fields[row_index * nFields + field_index];
     575                 :             : 
     576         [ #  # ]:           0 :                 if (po->html3)
     577                 :           0 :                         fprintf(fout, "<td align=\"%s\">%s</td>",
     578         [ #  # ]:           0 :                                         fieldNotNum[field_index] ? "left" : "right", p ? p : "");
     579                 :             :                 else
     580                 :             :                 {
     581                 :           0 :                         fprintf(fout,
     582         [ #  # ]:           0 :                                         fieldNotNum[field_index] ?
     583                 :           0 :                                         (po->standard ? " %-*s " : "%-*s") :
     584                 :           0 :                                         (po->standard ? " %*s " : "%*s"),
     585                 :           0 :                                         fieldMax[field_index],
     586         [ #  # ]:           0 :                                         p ? p : "");
     587   [ #  #  #  # ]:           0 :                         if (po->standard || field_index + 1 < nFields)
     588                 :           0 :                                 fputs(po->fieldSep, fout);
     589                 :             :                 }
     590                 :           0 :         }
     591         [ #  # ]:           0 :         if (po->html3)
     592                 :           0 :                 fputs("</tr>", fout);
     593         [ #  # ]:           0 :         else if (po->standard)
     594                 :           0 :                 fprintf(fout, "\n%s", border);
     595                 :           0 :         fputc('\n', fout);
     596                 :           0 : }
     597                 :             : 
     598                 :             : 
     599                 :             : 
     600                 :             : /*
     601                 :             :  * really old printing routines
     602                 :             :  */
     603                 :             : 
     604                 :             : void
     605                 :           0 : PQdisplayTuples(const PGresult *res,
     606                 :             :                                 FILE *fp,               /* where to send the output */
     607                 :             :                                 int fillAlign,  /* pad the fields with spaces */
     608                 :             :                                 const char *fieldSep,   /* field separator */
     609                 :             :                                 int printHeader,        /* display headers? */
     610                 :             :                                 int quiet
     611                 :             : )
     612                 :             : {
     613                 :             : #define DEFAULT_FIELD_SEP " "
     614                 :             : 
     615                 :           0 :         int                     i,
     616                 :             :                                 j;
     617                 :           0 :         int                     nFields;
     618                 :           0 :         int                     nTuples;
     619                 :           0 :         int                *fLength = NULL;
     620                 :             : 
     621         [ #  # ]:           0 :         if (fieldSep == NULL)
     622                 :           0 :                 fieldSep = DEFAULT_FIELD_SEP;
     623                 :             : 
     624                 :             :         /* Get some useful info about the results */
     625                 :           0 :         nFields = PQnfields(res);
     626                 :           0 :         nTuples = PQntuples(res);
     627                 :             : 
     628         [ #  # ]:           0 :         if (fp == NULL)
     629                 :           0 :                 fp = stdout;
     630                 :             : 
     631                 :             :         /* Figure the field lengths to align to */
     632                 :             :         /* will be somewhat time consuming for very large results */
     633         [ #  # ]:           0 :         if (fillAlign)
     634                 :             :         {
     635                 :           0 :                 fLength = (int *) malloc(nFields * sizeof(int));
     636         [ #  # ]:           0 :                 if (!fLength)
     637                 :             :                 {
     638                 :           0 :                         fprintf(stderr, libpq_gettext("out of memory\n"));
     639                 :           0 :                         return;
     640                 :             :                 }
     641                 :             : 
     642         [ #  # ]:           0 :                 for (j = 0; j < nFields; j++)
     643                 :             :                 {
     644                 :           0 :                         fLength[j] = strlen(PQfname(res, j));
     645         [ #  # ]:           0 :                         for (i = 0; i < nTuples; i++)
     646                 :             :                         {
     647                 :           0 :                                 int                     flen = PQgetlength(res, i, j);
     648                 :             : 
     649         [ #  # ]:           0 :                                 if (flen > fLength[j])
     650                 :           0 :                                         fLength[j] = flen;
     651                 :           0 :                         }
     652                 :           0 :                 }
     653                 :           0 :         }
     654                 :             : 
     655         [ #  # ]:           0 :         if (printHeader)
     656                 :             :         {
     657                 :             :                 /* first, print out the attribute names */
     658         [ #  # ]:           0 :                 for (i = 0; i < nFields; i++)
     659                 :             :                 {
     660                 :           0 :                         fputs(PQfname(res, i), fp);
     661         [ #  # ]:           0 :                         if (fillAlign)
     662                 :           0 :                                 fill(strlen(PQfname(res, i)), fLength[i], ' ', fp);
     663                 :           0 :                         fputs(fieldSep, fp);
     664                 :           0 :                 }
     665                 :           0 :                 fprintf(fp, "\n");
     666                 :             : 
     667                 :             :                 /* Underline the attribute names */
     668         [ #  # ]:           0 :                 for (i = 0; i < nFields; i++)
     669                 :             :                 {
     670         [ #  # ]:           0 :                         if (fillAlign)
     671                 :           0 :                                 fill(0, fLength[i], '-', fp);
     672                 :           0 :                         fputs(fieldSep, fp);
     673                 :           0 :                 }
     674                 :           0 :                 fprintf(fp, "\n");
     675                 :           0 :         }
     676                 :             : 
     677                 :             :         /* next, print out the instances */
     678         [ #  # ]:           0 :         for (i = 0; i < nTuples; i++)
     679                 :             :         {
     680         [ #  # ]:           0 :                 for (j = 0; j < nFields; j++)
     681                 :             :                 {
     682                 :           0 :                         fprintf(fp, "%s", PQgetvalue(res, i, j));
     683         [ #  # ]:           0 :                         if (fillAlign)
     684                 :           0 :                                 fill(strlen(PQgetvalue(res, i, j)), fLength[j], ' ', fp);
     685                 :           0 :                         fputs(fieldSep, fp);
     686                 :           0 :                 }
     687                 :           0 :                 fprintf(fp, "\n");
     688                 :           0 :         }
     689                 :             : 
     690         [ #  # ]:           0 :         if (!quiet)
     691                 :           0 :                 fprintf(fp, "\nQuery returned %d row%s.\n", PQntuples(res),
     692                 :           0 :                                 (PQntuples(res) == 1) ? "" : "s");
     693                 :             : 
     694                 :           0 :         fflush(fp);
     695                 :             : 
     696                 :           0 :         free(fLength);
     697         [ #  # ]:           0 : }
     698                 :             : 
     699                 :             : 
     700                 :             : 
     701                 :             : void
     702                 :           0 : PQprintTuples(const PGresult *res,
     703                 :             :                           FILE *fout,           /* output stream */
     704                 :             :                           int PrintAttNames,    /* print attribute names or not */
     705                 :             :                           int TerseOutput,      /* delimiter bars or not? */
     706                 :             :                           int colWidth          /* width of column, if 0, use variable width */
     707                 :             : )
     708                 :             : {
     709                 :           0 :         int                     nFields;
     710                 :           0 :         int                     nTups;
     711                 :           0 :         int                     i,
     712                 :             :                                 j;
     713                 :           0 :         char            formatString[80];
     714                 :           0 :         char       *tborder = NULL;
     715                 :             : 
     716                 :           0 :         nFields = PQnfields(res);
     717                 :           0 :         nTups = PQntuples(res);
     718                 :             : 
     719         [ #  # ]:           0 :         if (colWidth > 0)
     720                 :           0 :                 sprintf(formatString, "%%s %%-%ds", colWidth);
     721                 :             :         else
     722                 :           0 :                 sprintf(formatString, "%%s %%s");
     723                 :             : 
     724         [ #  # ]:           0 :         if (nFields > 0)
     725                 :             :         {                                                       /* only print rows with at least 1 field.  */
     726                 :             : 
     727         [ #  # ]:           0 :                 if (!TerseOutput)
     728                 :             :                 {
     729                 :           0 :                         int                     width;
     730                 :             : 
     731                 :           0 :                         width = nFields * 14;
     732                 :           0 :                         tborder = (char *) malloc(width + 1);
     733         [ #  # ]:           0 :                         if (!tborder)
     734                 :             :                         {
     735                 :           0 :                                 fprintf(stderr, libpq_gettext("out of memory\n"));
     736                 :           0 :                                 return;
     737                 :             :                         }
     738         [ #  # ]:           0 :                         for (i = 0; i < width; i++)
     739                 :           0 :                                 tborder[i] = '-';
     740                 :           0 :                         tborder[width] = '\0';
     741                 :           0 :                         fprintf(fout, "%s\n", tborder);
     742         [ #  # ]:           0 :                 }
     743                 :             : 
     744         [ #  # ]:           0 :                 for (i = 0; i < nFields; i++)
     745                 :             :                 {
     746         [ #  # ]:           0 :                         if (PrintAttNames)
     747                 :             :                         {
     748                 :           0 :                                 fprintf(fout, formatString,
     749                 :           0 :                                                 TerseOutput ? "" : "|",
     750                 :           0 :                                                 PQfname(res, i));
     751                 :           0 :                         }
     752                 :           0 :                 }
     753                 :             : 
     754         [ #  # ]:           0 :                 if (PrintAttNames)
     755                 :             :                 {
     756         [ #  # ]:           0 :                         if (TerseOutput)
     757                 :           0 :                                 fprintf(fout, "\n");
     758                 :             :                         else
     759                 :           0 :                                 fprintf(fout, "|\n%s\n", tborder);
     760                 :           0 :                 }
     761                 :             : 
     762         [ #  # ]:           0 :                 for (i = 0; i < nTups; i++)
     763                 :             :                 {
     764         [ #  # ]:           0 :                         for (j = 0; j < nFields; j++)
     765                 :             :                         {
     766                 :           0 :                                 const char *pval = PQgetvalue(res, i, j);
     767                 :             : 
     768                 :           0 :                                 fprintf(fout, formatString,
     769                 :           0 :                                                 TerseOutput ? "" : "|",
     770         [ #  # ]:           0 :                                                 pval ? pval : "");
     771                 :           0 :                         }
     772         [ #  # ]:           0 :                         if (TerseOutput)
     773                 :           0 :                                 fprintf(fout, "\n");
     774                 :             :                         else
     775                 :           0 :                                 fprintf(fout, "|\n%s\n", tborder);
     776                 :           0 :                 }
     777                 :           0 :         }
     778                 :             : 
     779                 :           0 :         free(tborder);
     780         [ #  # ]:           0 : }
     781                 :             : 
     782                 :             : 
     783                 :             : /* simply send out max-length number of filler characters to fp */
     784                 :             : 
     785                 :             : static void
     786                 :           0 : fill(int length, int max, char filler, FILE *fp)
     787                 :             : {
     788                 :           0 :         int                     count;
     789                 :             : 
     790                 :           0 :         count = max - length;
     791         [ #  # ]:           0 :         while (count-- >= 0)
     792                 :           0 :                 putc(filler, fp);
     793                 :           0 : }
        

Generated by: LCOV version 2.3.2-1