⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 common.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * psql - the PostgreSQL interactive terminal * * Copyright (c) 2000-2003, PostgreSQL Global Development Group * * $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.76.2.1 2003/11/12 22:55:42 tgl Exp $ */#include "postgres_fe.h"#include "common.h"#include <ctype.h>#ifndef HAVE_STRDUP#include <strdup.h>#endif#include <signal.h>#ifndef WIN32#include <sys/time.h>#include <unistd.h>				/* for write() */#include <setjmp.h>#else#include <io.h>					/* for _write() */#include <win32.h>#include <sys/timeb.h>			/* for _ftime() */#endif#include "libpq-fe.h"#include "pqsignal.h"#include "settings.h"#include "variables.h"#include "command.h"#include "copy.h"#include "prompt.h"#include "print.h"#include "mainloop.h"#include "mb/pg_wchar.h"/* Workarounds for Windows *//* Probably to be moved up the source tree in the future, perhaps to be replaced by * more specific checks like configure-style HAVE_GETTIMEOFDAY macros. */#ifndef WIN32typedef struct timeval TimevalStruct;#define GETTIMEOFDAY(T) gettimeofday(T, NULL)#define DIFF_MSEC(T, U) \	((((int) ((T)->tv_sec - (U)->tv_sec)) * 1000000.0 + \	  ((int) ((T)->tv_usec - (U)->tv_usec))) / 1000.0)#elsetypedef struct _timeb TimevalStruct;#define GETTIMEOFDAY(T) _ftime(T)#define DIFF_MSEC(T, U) \	(((T)->time - (U)->time) * 1000.0 + \	 ((T)->millitm - (U)->millitm))#endifextern bool prompt_state;static bool is_transact_command(const char *query);/* * "Safe" wrapper around strdup() */char *xstrdup(const char *string){	char	   *tmp;	if (!string)	{		fprintf(stderr, gettext("%s: xstrdup: cannot duplicate null pointer (internal error)\n"),				pset.progname);		exit(EXIT_FAILURE);	}	tmp = strdup(string);	if (!tmp)	{		psql_error("out of memory\n");		exit(EXIT_FAILURE);	}	return tmp;}/* * setQFout * -- handler for -o command line option and \o command * * Tries to open file fname (or pipe if fname starts with '|') * and stores the file handle in pset) * Upon failure, sets stdout and returns false. */boolsetQFout(const char *fname){	bool		status = true;	/* Close old file/pipe */	if (pset.queryFout && pset.queryFout != stdout && pset.queryFout != stderr)	{		if (pset.queryFoutPipe)			pclose(pset.queryFout);		else			fclose(pset.queryFout);	}	/* If no filename, set stdout */	if (!fname || fname[0] == '\0')	{		pset.queryFout = stdout;		pset.queryFoutPipe = false;	}	else if (*fname == '|')	{		pset.queryFout = popen(fname + 1, "w");		pset.queryFoutPipe = true;	}	else	{		pset.queryFout = fopen(fname, "w");		pset.queryFoutPipe = false;	}	if (!(pset.queryFout))	{		psql_error("%s: %s\n", fname, strerror(errno));		pset.queryFout = stdout;		pset.queryFoutPipe = false;		status = false;	}	/* Direct signals */#ifndef WIN32	pqsignal(SIGPIPE, pset.queryFoutPipe ? SIG_IGN : SIG_DFL);#endif	return status;}/* * Error reporting for scripts. Errors should look like *	 psql:filename:lineno: message * */voidpsql_error(const char *fmt,...){	va_list		ap;	fflush(stdout);	if (pset.queryFout != stdout)		fflush(pset.queryFout);	if (pset.inputfile)		fprintf(stderr, "%s:%s:%u: ", pset.progname, pset.inputfile, pset.lineno);	va_start(ap, fmt);	vfprintf(stderr, gettext(fmt), ap);	va_end(ap);}/* * for backend Notice messages (INFO, WARNING, etc) */voidNoticeProcessor(void *arg, const char *message){	(void) arg;					/* not used */	psql_error("%s", message);}/* * Code to support query cancellation * * Before we start a query, we enable a SIGINT signal catcher that sends a * cancel request to the backend. Note that sending the cancel directly from * the signal handler is safe because PQrequestCancel() is written to make it * so. We use write() to print to stdout because it's better to use simple * facilities in a signal handler. */static PGconn *volatile cancelConn = NULL;volatile bool cancel_pressed = false;#ifndef WIN32#define write_stderr(String) write(fileno(stderr), String, strlen(String))voidhandle_sigint(SIGNAL_ARGS){	int			save_errno = errno;	/* Don't muck around if prompting for a password. */	if (prompt_state)		return;	if (cancelConn == NULL)		siglongjmp(main_loop_jmp, 1);	cancel_pressed = true;	if (PQrequestCancel(cancelConn))		write_stderr("Cancel request sent\n");	else	{		write_stderr("Could not send cancel request: ");		write_stderr(PQerrorMessage(cancelConn));	}	errno = save_errno;			/* just in case the write changed it */}#endif   /* not WIN32 *//* ConnectionUp * * Returns whether our backend connection is still there. */static boolConnectionUp(){	return PQstatus(pset.db) != CONNECTION_BAD;}/* CheckConnection * * Verify that we still have a good connection to the backend, and if not, * see if it can be restored. * * Returns true if either the connection was still there, or it could be * restored successfully; false otherwise.	If, however, there was no * connection and the session is non-interactive, this will exit the program * with a code of EXIT_BADCONN. */static boolCheckConnection(void){	bool		OK;	OK = ConnectionUp();	if (!OK)	{		if (!pset.cur_cmd_interactive)		{			psql_error("connection to server was lost\n");			exit(EXIT_BADCONN);		}		fputs(gettext("The connection to the server was lost. Attempting reset: "), stderr);		PQreset(pset.db);		OK = ConnectionUp();		if (!OK)		{			fputs(gettext("Failed.\n"), stderr);			PQfinish(pset.db);			pset.db = NULL;			ResetCancelConn();			UnsyncVariables();		}		else			fputs(gettext("Succeeded.\n"), stderr);	}	return OK;}/* * SetCancelConn * * Set cancelConn to point to the current database connection. */static voidSetCancelConn(void){	cancelConn = pset.db;}/* * ResetCancelConn * * Set cancelConn to NULL.	I don't know what this means exactly, but it saves * having to export the variable. */voidResetCancelConn(void){	cancelConn = NULL;}/* * AcceptResult * * Checks whether a result is valid, giving an error message if necessary; * resets cancelConn as needed, and ensures that the connection to the backend * is still up. * * Returns true for valid result, false for error state. */static boolAcceptResult(const PGresult *result){	bool		OK = true;	ResetCancelConn();	if (!result)		OK = false;	else		switch (PQresultStatus(result))		{			case PGRES_COMMAND_OK:			case PGRES_TUPLES_OK:			case PGRES_EMPTY_QUERY:			case PGRES_COPY_IN:				/* Fine, do nothing */				break;			case PGRES_COPY_OUT:				/* keep cancel connection for copy out state */				SetCancelConn();				break;			default:				OK = false;				break;		}	if (!OK)	{		psql_error("%s", PQerrorMessage(pset.db));		CheckConnection();	}	return OK;}/* * PSQLexec * * This is the way to send "backdoor" queries (those not directly entered * by the user). It is subject to -E but not -e. * * In autocommit-off mode, a new transaction block is started if start_xact * is true; nothing special is done when start_xact is false.  Typically, * start_xact = false is used for SELECTs and explicit BEGIN/COMMIT commands. * * Note: we don't bother to check PQclientEncoding; it is assumed that no * caller uses this path to issue "SET CLIENT_ENCODING". */PGresult *PSQLexec(const char *query, bool start_xact){	PGresult   *res;	int			echo_hidden;	if (!pset.db)	{		psql_error("You are currently not connected to a database.\n");		return NULL;	}	echo_hidden = SwitchVariable(pset.vars, "ECHO_HIDDEN", "noexec", NULL);	if (echo_hidden != VAR_NOTSET)	{		printf("********* QUERY **********\n"			   "%s\n"			   "**************************\n\n", query);		fflush(stdout);		if (echo_hidden == 1)	/* noexec? */			return NULL;	}	SetCancelConn();	if (start_xact && PQtransactionStatus(pset.db) == PQTRANS_IDLE &&		!GetVariableBool(pset.vars, "AUTOCOMMIT"))	{		res = PQexec(pset.db, "BEGIN");		if (PQresultStatus(res) != PGRES_COMMAND_OK)		{			psql_error("%s", PQerrorMessage(pset.db));			PQclear(res);			ResetCancelConn();			return NULL;

⌨️ 快捷键说明

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