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;

128 fieldMax[j] = len;

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 (do\_field(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 "<td align=\"left\">%s"

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("", fout);

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("", fout);

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)