PostgreSQL Source Code: src/interfaces/libpq/fe-print.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
18
19#include <signal.h>
20
21#ifdef WIN32
22#include "win32.h"
23#else
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
38
39
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);
46static 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);
49static 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);
52static void fill(int length, int max, char filler, FILE *fp);
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67void
69{
70 int nFields;
71
73
74 if (nFields > 0)
75 {
76 int i,
77 j;
78 int nTups;
79 int *fieldMax = NULL;
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(WIN32)
92 sigset_t osigset;
93 bool sigpipe_masked = false;
94 bool sigpipe_pending;
95#endif
96
97#ifdef TIOCGWINSZ
98 struct winsize screen_size;
99#else
100 struct winsize
101 {
102 int ws_row;
103 int ws_col;
104 } screen_size;
105#endif
106
108 fieldNames = (const char **) calloc(nFields, sizeof(char *));
109 fieldNotNum = (unsigned char *) calloc(nFields, 1);
110 fieldMax = (int *) calloc(nFields, sizeof(int));
111 if (!fieldNames || !fieldNotNum || !fieldMax)
112 {
114 goto exit;
115 }
116 for (numFieldName = 0;
118 numFieldName++)
119 ;
120 for (j = 0; j < nFields; j++)
121 {
123 const char *s = (j < numFieldName && po->fieldName[j][0]) ?
125
126 fieldNames[j] = s;
127 len = s ? strlen(s) : 0;
129 len += fs_len;
130 if (len > fieldMaxLen)
131 fieldMaxLen = len;
132 total_line_length += len;
133 }
134
135 total_line_length += nFields * strlen(po->fieldSep) + 1;
136
137 if (fout == NULL)
139 if (po->pager && fout == stdout && isatty(fileno(stdin)) &&
140 isatty(fileno(stdout)))
141 {
142
143
144
145
146#ifdef TIOCGWINSZ
147 if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 ||
148 screen_size.ws_col == 0 ||
149 screen_size.ws_row == 0)
150 {
151 screen_size.ws_row = 24;
152 screen_size.ws_col = 80;
153 }
154#else
155 screen_size.ws_row = 24;
156 screen_size.ws_col = 80;
157#endif
158
159
160
161
162
163
164
165 pagerenv = getenv("PAGER");
166
167 if (pagerenv != NULL &&
168 strspn(pagerenv, " \t\r\n") != strlen(pagerenv) &&
171 nTups * (nFields + 1) >= screen_size.ws_row) ||
173 nTups * (total_line_length / screen_size.ws_col + 1) *
174 (1 + (po->standard != 0)) >= screen_size.ws_row -
176 (total_line_length / screen_size.ws_col + 1) * 2
177 - (po->header != 0) * 2
178 )))
179 {
180 fflush(NULL);
181 fout = popen(pagerenv, "w");
182 if (fout)
183 {
184 usePipe = true;
185#ifndef WIN32
187 sigpipe_masked = true;
188#endif
189 }
190 else
192 }
193 }
194
196 {
197 fields = (char **) calloc((size_t) nTups + 1,
198 nFields * sizeof(char *));
199 if (!fields)
200 {
202 goto exit;
203 }
204 }
206 {
208 {
212 else
214 }
215 else
216 {
217 int len = 0;
218
219 for (j = 0; j < nFields; j++)
220 {
221 const char *s = fieldNames[j];
222
223 fputs(s, fout);
224 len += strlen(s) + fs_len;
225 if ((j + 1) < nFields)
227 }
228 fputc('\n', fout);
229 for (len -= fs_len; len--; fputc('-', fout));
230 fputc('\n', fout);
231 }
232 }
234 {
236 fprintf(fout, "
%s
\n", po->caption);237 else
239 "
"
240 "Query retrieved %d rows * %d fields"
241 "\n",
242 nTups, nFields);
243 }
244 for (i = 0; i < nTups; i++)
245 {
247 {
250 "<table %s><caption align=\"top\">%d\n",
252 else
254 }
255 for (j = 0; j < nFields; j++)
256 {
257 if ((po, res, i, j, fs_len, fields, nFields,
258 fieldNames, fieldNotNum,
259 fieldMax, fieldMaxLen, fout))
260 goto exit;
261 }
263 fputs("\n", fout);
264 }
266 {
268 {
270 {
273 "<table %s><caption align=\"top\">%s\n",
276 else
278 "<table %s><caption align=\"top\">"
279 "Retrieved %d rows * %d fields"
280 "\n",
282 }
283 else
285 }
287 border = do_header(fout, po, nFields, fieldMax, fieldNames,
288 fieldNotNum, fs_len, res);
289 for (i = 0; i < nTups; i++)
290 output_row(fout, po, nFields, fields,
291 fieldNotNum, fieldMax, border, i);
292 }
295 (PQntuples(res) == 1) ? "" : "s");
297 fputs("\n", fout);
298
299exit:
300 free(fieldMax);
301 free(fieldNotNum);
302 free(border);
303 if (fields)
304 {
305
306 size_t numfields = ((size_t) nTups + 1) * (size_t) nFields;
307
308 while (numfields-- > 0)
309 free(fields[numfields]);
310 free(fields);
311 }
312 free(fieldNames);
313 if (usePipe)
314 {
315#ifdef WIN32
316 _pclose(fout);
317#else
318 pclose(fout);
319
320
321 if (sigpipe_masked)
323#endif
324 }
325 }
326}
327
328
329static bool
331 const int i, const int j, const int fs_len,
332 char **fields,
333 const int nFields, char const **fieldNames,
334 unsigned char *fieldNotNum, int *fieldMax,
335 const int fieldMaxLen, FILE *fout)
336{
337 const char *pval,
338 *p;
339 int plen;
340 bool skipit;
341
344
345 if (plen < 1 || !pval || !*pval)
346 {
348 skipit = true;
349 else
350 {
351 skipit = false;
352 goto efield;
353 }
354 }
355 else
356 skipit = false;
357
358 if (!skipit)
359 {
360 if (po->align && !fieldNotNum[j])
361 {
362
363 char ch = '0';
364
366 {
367 ch = *p;
368 if (!((ch >= '0' && ch <= '9') ||
369 ch == '.' ||
370 ch == 'E' ||
371 ch == 'e' ||
372 ch == ' ' ||
373 ch == '-'))
374 {
375 fieldNotNum[j] = 1;
376 break;
377 }
378 }
379
380
381
382
383
384
385 if (*pval == 'E' || *pval == 'e' ||
386 !(ch >= '0' && ch <= '9'))
387 fieldNotNum[j] = 1;
388 }
389
391 {
392 if (plen > fieldMax[j])
393 fieldMax[j] = plen;
394 if (!(fields[i * nFields + j] = (char *) malloc(plen + 1)))
395 {
397 return false;
398 }
399 strcpy(fields[i * nFields + j], pval);
400 }
401 else
402 {
404 {
407 "
408 "<td align=\"%s\">%s\n",
409 fieldNames[j],
410 fieldNotNum[j] ? "left" : "right",
411 pval);
412 else
413 {
416 "%-*s%s %s\n",
417 fieldMaxLen - fs_len, fieldNames[j],
419 pval);
420 else
422 "%s%s%s\n",
423 fieldNames[j], po->fieldSep, pval);
424 }
425 }
426 else
427 {
429 {
430 fputs(pval, fout);
431 efield:
432 if ((j + 1) < nFields)
434 else
435 fputc('\n', fout);
436 }
437 }
438 }
439 }
440 return true;
441}
442
443
444static char *
446 const char **fieldNames, unsigned char *fieldNotNum,
447 const int fs_len, const PGresult *res)
448{
449 int j;
450 char *border = NULL;
451
453 fputs("
454 else
455 {
456 int tot = 0;
457 int n = 0;
458 char *p = NULL;
459
460 for (; n < nFields; n++)
461 tot += fieldMax[n] + fs_len + (po->standard ? 2 : 0);
463 tot += fs_len * 2 + 2;
464 border = malloc(tot + 1);
465 if (!border)
466 {
468 return NULL;
469 }
470 p = border;
472 {
474
475 while (*fs++)
476 *p++ = '+';
477 }
478 for (j = 0; j < nFields; j++)
479 {
481
482 for (len = fieldMax[j] + (po->standard ? 2 : 0); len--; *p++ = '-');
483 if (po->standard || (j + 1) < nFields)
484 {
486
487 while (*fs++)
488 *p++ = '+';
489 }
490 }
491 *p = '\0';
493 fprintf(fout, "%s\n", border);
494 }
497 for (j = 0; j < nFields; j++)
498 {
499 const char *s = PQfname(res, j);
500
502 {
503 fprintf(fout, "<th align=\"%s\">%s",
504 fieldNotNum[j] ? "left" : "right", fieldNames[j]);
505 }
506 else
507 {
508 int n = strlen(s);
509
510 if (n > fieldMax[j])
511 fieldMax[j] = n;
514 fieldNotNum[j] ? " %-*s " : " %*s ",
515 fieldMax[j], s);
516 else
517 fprintf(fout, fieldNotNum[j] ? "%-*s" : "%*s", fieldMax[j], s);
518 if (po->standard || (j + 1) < nFields)
520 }
521 }
523 fputs("\n", fout);
524 else
525 fprintf(fout, "\n%s\n", border);
526 return border;
527}
528
529
530static void
532 unsigned char *fieldNotNum, int *fieldMax, char *border,
533 const int row_index)
534{
535 int field_index;
536
538 fputs("
541 for (field_index = 0; field_index < nFields; field_index++)
542 {
543 char *p = fields[row_index * nFields + field_index];
544
546 fprintf(fout, "<td align=\"%s\">%s",
547 fieldNotNum[field_index] ? "left" : "right", p ? p : "");
548 else
549 {
551 fieldNotNum[field_index] ?
552 (po->standard ? " %-*s " : "%-*s") :
553 (po->standard ? " %*s " : "%*s"),
554 fieldMax[field_index],
555 p ? p : "");
556 if (po->standard || field_index + 1 < nFields)
558 }
559 }
561 fputs("", fout);
563 fprintf(fout, "\n%s", border);
564 fputc('\n', fout);
565}
566
567
568
569
570
571
572
573void
575 FILE *fp,
576 int fillAlign,
577 const char *fieldSep,
578 int printHeader,
579 int quiet
581{
582#define DEFAULT_FIELD_SEP " "
583
584 int i,
585 j;
586 int nFields;
587 int nTuples;
588 int *fLength = NULL;
589
590 if (fieldSep == NULL)
592
593
596
597 if (fp == NULL)
599
600
601
602 if (fillAlign)
603 {
604 fLength = (int *) malloc(nFields * sizeof(int));
605 if (!fLength)
606 {
608 return;
609 }
610
611 for (j = 0; j < nFields; j++)
612 {
613 fLength[j] = strlen(PQfname(res, j));
614 for (i = 0; i < nTuples; i++)
615 {
617
618 if (flen > fLength[j])
619 fLength[j] = flen;
620 }
621 }
622 }
623
624 if (printHeader)
625 {
626
627 for (i = 0; i < nFields; i++)
628 {
630 if (fillAlign)
631 fill(strlen(PQfname(res, i)), fLength[i], ' ', fp);
632 fputs(fieldSep, fp);
633 }
635
636
637 for (i = 0; i < nFields; i++)
638 {
639 if (fillAlign)
640 fill(0, fLength[i], '-', fp);
641 fputs(fieldSep, fp);
642 }
644 }
645
646
647 for (i = 0; i < nTuples; i++)
648 {
649 for (j = 0; j < nFields; j++)
650 {
652 if (fillAlign)
654 fputs(fieldSep, fp);
655 }
657 }
658
659 if (!quiet)
661 (PQntuples(res) == 1) ? "" : "s");
662
663 fflush(fp);
664
665 free(fLength);
666}
667
668
669
670void
672 FILE *fout,
673 int PrintAttNames,
674 int TerseOutput,
675 int colWidth
677{
678 int nFields;
679 int nTups;
680 int i,
681 j;
682 char formatString[80];
683 char *tborder = NULL;
684
687
688 if (colWidth > 0)
689 sprintf(formatString, "%%s %%-%ds", colWidth);
690 else
691 sprintf(formatString, "%%s %%s");
692
693 if (nFields > 0)
694 {
695
696 if (!TerseOutput)
697 {
698 int width;
699
700 width = nFields * 14;
701 tborder = (char *) malloc(width + 1);
702 if (!tborder)
703 {
705 return;
706 }
707 for (i = 0; i < width; i++)
708 tborder[i] = '-';
709 tborder[width] = '\0';
710 fprintf(fout, "%s\n", tborder);
711 }
712
713 for (i = 0; i < nFields; i++)
714 {
715 if (PrintAttNames)
716 {
717 fprintf(fout, formatString,
718 TerseOutput ? "" : "|",
720 }
721 }
722
723 if (PrintAttNames)
724 {
725 if (TerseOutput)
727 else
728 fprintf(fout, "|\n%s\n", tborder);
729 }
730
731 for (i = 0; i < nTups; i++)
732 {
733 for (j = 0; j < nFields; j++)
734 {
736
737 fprintf(fout, formatString,
738 TerseOutput ? "" : "|",
739 pval ? pval : "");
740 }
741 if (TerseOutput)
743 else
744 fprintf(fout, "|\n%s\n", tborder);
745 }
746 }
747
748 free(tborder);
749}
750
751
752
753
754static void
755fill(int length, int max, char filler, FILE *fp)
756{
757 int count;
758
759 count = max - length;
760 while (count-- >= 0)
761 putc(filler, fp);
762}
#define fprintf(file, fmt, msg)
int PQgetlength(const PGresult *res, int tup_num, int field_num)
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
int PQntuples(const PGresult *res)
char * PQfname(const PGresult *res, int field_num)
int PQnfields(const PGresult *res)
int PQmblenBounded(const char *s, int encoding)
void PQdisplayTuples(const PGresult *res, FILE *fp, int fillAlign, const char *fieldSep, int printHeader, int quiet)
static void fill(int length, int max, char filler, FILE *fp)
#define DEFAULT_FIELD_SEP
void PQprintTuples(const PGresult *res, FILE *fout, int PrintAttNames, int TerseOutput, int colWidth)
void PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
static char * do_header(FILE *fout, const PQprintOpt *po, const int nFields, int *fieldMax, const char **fieldNames, unsigned char *fieldNotNum, const int fs_len, const PGresult *res)
static 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)
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)
void pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
int pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)