fe-print.c

来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 747 行 · 第 1/2 页

C
747
字号
/*------------------------------------------------------------------------- * * fe-print.c *	  functions for pretty-printing query results * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions 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: /cvsroot/pgsql/src/interfaces/libpq/fe-print.c,v 1.48 2003/08/04 02:40:20 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres_fe.h"#include <signal.h>#ifdef WIN32#include "win32.h"#else#include <unistd.h>#include <sys/ioctl.h>#endif#ifdef HAVE_TERMIOS_H#include <termios.h>#else#ifndef WIN32#include <sys/termios.h>#endif#endif#include "libpq-fe.h"#include "libpq-int.h"#include "pqsignal.h"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 = strlen(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 ? 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			)		{			/*			 * 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 += 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, 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(p, res->client_encoding))			{				ch = *p;				if (!((ch >= '0' && ch <= '9') ||					  ch == '.' ||					  ch == 'E' ||					  ch == 'e' ||					  ch == ' ' ||					  ch == '-'))				{					fieldNotNum[j] = 1;					break;				}			}			/*			 * Above loop will believe E in first column is numeric; also,			 * we insist on a digit in the last column for a numeric. This			 * test is still not bulletproof but it handles most cases.			 */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?