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