📄 fe-print.c
字号:
/*------------------------------------------------------------------------- * * fe-print.c * functions for pretty-printing query results * * Copyright (c) 1994, Regents of the University of California * * These functions were formerly part of fe-exec.c, but they * didn't really belong there. * * IDENTIFICATION * $Header: /usr/local/cvsroot/pgsql/src/interfaces/libpq/fe-print.c,v 1.23 1999/05/25 16:15:13 momjian Exp $ * *------------------------------------------------------------------------- */#include "libpq-fe.h"#include "libpq-int.h"#include "postgres.h"#include "pqsignal.h"#ifdef WIN32#include "win32.h"#else#if !defined(NO_UNISTD_H)#include <unistd.h>#endif#include <sys/ioctl.h>#ifndef HAVE_TERMIOS_H#include <sys/termios.h>#else#include <termios.h>#endif#endif /* WIN32 */#include <stdlib.h>#include <signal.h>#include <string.h>#ifdef MULTIBYTE#include "mb/pg_wchar.h"#endif#ifdef TIOCGWINSZstatic struct winsize screen_size;#elsestatic struct winsize{ int ws_row; int ws_col;} screen_size;#endifstatic void do_field(PQprintOpt *po, PGresult *res, const int i, const int j, char *buf, const int fs_len, char **fields, const int nFields, char **fieldNames, unsigned char *fieldNotNum, int *fieldMax, const int fieldMaxLen, FILE *fout);static char *do_header(FILE *fout, PQprintOpt *po, const int nFields, int *fieldMax, char **fieldNames, unsigned char *fieldNotNum, const int fs_len, PGresult *res);static void output_row(FILE *fout, PQprintOpt *po, const int nFields, char **fields, unsigned char *fieldNotNum, int *fieldMax, char *border, const int row_index);static void fill(int length, int max, char filler, FILE *fp);/* * PQprint() * * Format results of a query for printing. * * PQprintOpt is a typedef (structure) that containes * various flags and options. consult libpq-fe.h for * details * * Obsoletes PQprintTuples. */voidPQprint(FILE *fout, PGresult *res, PQprintOpt *po){ int nFields; nFields = PQnfields(res); if (nFields > 0) { /* only print rows with at least 1 field. */ int i, j; int nTups; int *fieldMax = NULL; /* in case we don't use them */ unsigned char *fieldNotNum = NULL; char *border = NULL; char **fields = NULL; char **fieldNames; int fieldMaxLen = 0; int numFieldName; int fs_len = strlen(po->fieldSep); int total_line_length = 0; int usePipe = 0; pqsigfunc oldsigpipehandler = NULL; char *pagerenv; char buf[MAX_QUERY_SIZE + 1]; nTups = PQntuples(res); if (!(fieldNames = (char **) calloc(nFields, sizeof(char *)))) { perror("calloc"); exit(1); } if (!(fieldNotNum = (unsigned char *) calloc(nFields, 1))) { perror("calloc"); exit(1); } if (!(fieldMax = (int *) calloc(nFields, sizeof(int)))) { perror("calloc"); exit(1); } for (numFieldName = 0; po->fieldName && po->fieldName[numFieldName]; numFieldName++) ; for (j = 0; j < nFields; j++) { int len; char *s = (j < numFieldName && po->fieldName[j][0]) ? po->fieldName[j] : PQfname(res, j); fieldNames[j] = s; len = s ? strlen(s) : 0; fieldMax[j] = len; len += fs_len; if (len > fieldMaxLen) fieldMaxLen = len; total_line_length += len; } total_line_length += nFields * strlen(po->fieldSep) + 1; if (fout == NULL) fout = stdout; if (po->pager && fout == stdout#ifndef WIN32 && isatty(fileno(stdin)) && isatty(fileno(stdout))#endif ) { /* try to pipe to the pager program if possible */#ifdef TIOCGWINSZ if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 || screen_size.ws_col == 0 || screen_size.ws_row == 0) {#endif screen_size.ws_row = 24; screen_size.ws_col = 80;#ifdef TIOCGWINSZ }#endif pagerenv = getenv("PAGER"); if (pagerenv != NULL && pagerenv[0] != '\0' && !po->html3 && ((po->expanded && nTups * (nFields + 1) >= screen_size.ws_row) || (!po->expanded && nTups * (total_line_length / screen_size.ws_col + 1) * (1 + (po->standard != 0)) >= screen_size.ws_row - (po->header != 0) * (total_line_length / screen_size.ws_col + 1) * 2 - (po->header != 0) * 2 /* row count and newline */ ))) {#ifdef WIN32 fout = _popen(pagerenv, "w");#else fout = popen(pagerenv, "w");#endif if (fout) { usePipe = 1;#ifndef WIN32 oldsigpipehandler = pqsignal(SIGPIPE, SIG_IGN);#endif } else fout = stdout; } } if (!po->expanded && (po->align || po->html3)) { if (!(fields = (char **) calloc(nFields * (nTups + 1), sizeof(char *)))) { perror("calloc"); exit(1); } } else if (po->header && !po->html3) { if (po->expanded) { if (po->align) fprintf(fout, "%-*s%s Value\n", fieldMaxLen - fs_len, "Field", po->fieldSep); else fprintf(fout, "%s%sValue\n", "Field", po->fieldSep); } else { int len = 0; for (j = 0; j < nFields; j++) { char *s = fieldNames[j]; fputs(s, fout); len += strlen(s) + fs_len; if ((j + 1) < nFields) fputs(po->fieldSep, fout); } fputc('\n', fout); for (len -= fs_len; len--; fputc('-', fout)); fputc('\n', fout); } } if (po->expanded && po->html3) { if (po->caption) fprintf(fout, "<centre><h2>%s</h2></centre>\n", po->caption); else fprintf(fout, "<centre><h2>" "Query retrieved %d rows * %d fields" "</h2></centre>\n", nTups, nFields); } for (i = 0; i < nTups; i++) { if (po->expanded) { if (po->html3) fprintf(fout, "<table %s><caption align=high>%d</caption>\n", po->tableOpt ? po->tableOpt : "", i); else fprintf(fout, "-- RECORD %d --\n", i); } for (j = 0; j < nFields; j++) do_field(po, res, i, j, buf, fs_len, fields, nFields, fieldNames, fieldNotNum, fieldMax, fieldMaxLen, fout); if (po->html3 && po->expanded) fputs("</table>\n", fout); } if (!po->expanded && (po->align || po->html3)) { if (po->html3) { if (po->header) { if (po->caption) fprintf(fout, "<table %s><caption align=high>%s</caption>\n", po->tableOpt ? po->tableOpt : "", po->caption); else fprintf(fout, "<table %s><caption align=high>" "Retrieved %d rows * %d fields" "</caption>\n", po->tableOpt ? po->tableOpt : "", nTups, nFields); } else fprintf(fout, "<table %s>", po->tableOpt ? po->tableOpt : ""); } if (po->header) border = do_header(fout, po, nFields, fieldMax, fieldNames, fieldNotNum, fs_len, res); for (i = 0; i < nTups; i++) output_row(fout, po, nFields, fields, fieldNotNum, fieldMax, border, i); free(fields); if (border) free(border); } if (po->header && !po->html3) fprintf(fout, "(%d row%s)\n\n", PQntuples(res), (PQntuples(res) == 1) ? "" : "s"); free(fieldMax); free(fieldNotNum); free(fieldNames); if (usePipe) {#ifdef WIN32 _pclose(fout);#else pclose(fout); pqsignal(SIGPIPE, oldsigpipehandler);#endif } if (po->html3 && !po->expanded) fputs("</table>\n", fout); }}/* * PQdisplayTuples() * kept for backward compatibility */voidPQdisplayTuples(PGresult *res, FILE *fp, /* where to send the output */ int fillAlign, /* pad the fields with spaces */ const char *fieldSep, /* field separator */ int printHeader,/* display headers? */ int quiet){#define DEFAULT_FIELD_SEP " " int i, j; int nFields; int nTuples; int fLength[MAX_FIELDS]; if (fieldSep == NULL) fieldSep = DEFAULT_FIELD_SEP; /* Get some useful info about the results */ nFields = PQnfields(res); nTuples = PQntuples(res); if (fp == NULL) fp = stdout; /* Zero the initial field lengths */ for (j = 0; j < nFields; j++) fLength[j] = strlen(PQfname(res, j)); /* Find the max length of each field in the result */ /* will be somewhat time consuming for very large results */ if (fillAlign) { for (i = 0; i < nTuples; i++) { for (j = 0; j < nFields; j++) { if (PQgetlength(res, i, j) > fLength[j]) fLength[j] = PQgetlength(res, i, j); } } } if (printHeader) { /* first, print out the attribute names */ for (i = 0; i < nFields; i++) { fputs(PQfname(res, i), fp); if (fillAlign) fill(strlen(PQfname(res, i)), fLength[i], ' ', fp); fputs(fieldSep, fp); } fprintf(fp, "\n"); /* Underline the attribute names */ for (i = 0; i < nFields; i++) { if (fillAlign) fill(0, fLength[i], '-', fp); fputs(fieldSep, fp); } fprintf(fp, "\n"); } /* next, print out the instances */ for (i = 0; i < nTuples; i++) { for (j = 0; j < nFields; j++) { fprintf(fp, "%s", PQgetvalue(res, i, j)); if (fillAlign) fill(strlen(PQgetvalue(res, i, j)), fLength[j], ' ', fp); fputs(fieldSep, fp); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -