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