📄 pqprint.c
字号:
/*Portions Copyright (c) 1996-2002, The PostgreSQL Global Development Group Portions Copyright (c) 1994, The Regents of the University of CaliforniaPortions Copyright (c) 2003-2004, David MusePermission to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without a written agreement is hereby granted, provided that the above copyright notice and this paragraph and the following two paragraphs appear in all copies. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.*/#include <pqdefinitions.h>#include <rudiments/charstring.h>#ifdef WIN32#include "win32.h"#else// for isatty()#include <unistd.h>#endifextern "C" {typedef struct _PQprintOpt { char header; char align; char standard; char html3; char expanded; char pager; char *fieldSep; char *tableOpt; char *caption; char **fieldName;} PQprintOpt;// Haha! I stole these straight out of the postgresql source/*PostgreSQL is Copyright © 1996-2002 by the PostgreSQL Global Development Groupand is distributed under the terms of the license of the University ofCalifornia below.Postgres95 is Copyright © 1994-5 by the Regents of the University of California.Permission to use, copy, modify, and distribute this software and itsdocumentation for any purpose, without fee, and without a written agreement ishereby granted, provided that the above copyright notice and this paragraph andthe following two paragraphs appear in all copies.IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FORDIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOSTPROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IFTHE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR APARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS-IS" BASIS, ANDTHE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */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);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 void output_row(FILE *fout, const 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 * * This function should probably be removed sometime since psql * doesn't use it anymore. It is unclear to what extend this is used * by external clients, however. */voidPQprint(FILE *fout, const PGresult *res, const 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; const char **fieldNames; int fieldMaxLen = 0; int numFieldName; int fs_len = charstring::length(po->fieldSep); int total_line_length = 0; int usePipe = 0; //pqsigfunc oldsigpipehandler = NULL; char *pagerenv;#ifdef TIOCGWINSZ struct winsize screen_size;#else struct winsize { int ws_row; int ws_col; } screen_size;#endif nTups = PQntuples(res); if (!(fieldNames = (const 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; const char *s = (j < numFieldName && po->fieldName[j][0]) ? po->fieldName[j] : PQfname(res, j); fieldNames[j] = s; len = s ? charstring::length(s) : 0; fieldMax[j] = len; len += fs_len; if (len > fieldMaxLen) fieldMaxLen = len; total_line_length += len; } total_line_length += nFields * charstring::length(po->fieldSep) + 1; if (fout == NULL) fout = stdout; if (po->pager && fout == stdout#ifndef WIN32 && isatty(fileno(stdin)) && isatty(fileno(stdout))#endif ) { /* * If we think there'll be more than one screen of output, try * to pipe to the pager program. *//*#ifdef TIOCGWINSZ if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 || screen_size.ws_col == 0 || screen_size.ws_row == 0) { screen_size.ws_row = 24; screen_size.ws_col = 80; }#else*/ screen_size.ws_row = 24; screen_size.ws_col = 80;//#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++) { const char *s = fieldNames[j]; fputs(s, fout); len += charstring::length(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, 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((void *) fieldNames); if (usePipe) {#ifdef WIN32 _pclose(fout);#else pclose(fout); //pqsignal(SIGPIPE, oldsigpipehandler);#endif } if (po->html3 && !po->expanded) fputs("</table>\n", fout); }}static voiddo_field(const PQprintOpt *po, const PGresult *res, const int i, const int j, const int fs_len, char **fields, const int nFields, char const ** fieldNames, unsigned char *fieldNotNum, int *fieldMax, const int fieldMaxLen, FILE *fout){ const char *pval, *p; int plen; bool skipit; plen = PQgetlength(res, i, j); pval = PQgetvalue(res, i, j); if (plen < 1 || !pval || !*pval) { if (po->align || po->expanded) skipit = true; else { skipit = false; goto efield; } } else skipit = false; if (!skipit) { if (po->align && !fieldNotNum[j]) { /* Detect whether field contains non-numeric data */ char ch = '0'; for (p = pval; *p; p += PQmblen((unsigned char *)p, PQclientEncoding(res->parent))) { ch = *p; if (!((ch >= '0' && ch <= '9') || ch == '.' || ch == 'E' || ch == 'e' || ch == ' ' ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -