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

📄 pg_backup_db.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * pg_backup_db.c * *	Implements the basic DB functions used by the archiver. * * IDENTIFICATION *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.50 2003/10/03 20:10:59 tgl Exp $ * *------------------------------------------------------------------------- */#include "pg_backup.h"#include "pg_backup_archiver.h"#include "pg_backup_db.h"#include "dumputils.h"#include <unistd.h>#include <ctype.h>#ifdef HAVE_TERMIOS_H#include <termios.h>#endif#include "libpq-fe.h"#include "libpq/libpq-fs.h"#ifndef HAVE_STRDUP#include "strdup.h"#endifstatic const char *modulename = gettext_noop("archiver (db)");static void _check_database_version(ArchiveHandle *AH, bool ignoreVersion);static PGconn *_connectDB(ArchiveHandle *AH, const char *newdbname, const char *newUser);static int	_executeSqlCommand(ArchiveHandle *AH, PGconn *conn, PQExpBuffer qry, char *desc);static void notice_processor(void *arg, const char *message);static char *_sendSQLLine(ArchiveHandle *AH, char *qry, char *eos);static char *_sendCopyLine(ArchiveHandle *AH, char *qry, char *eos);static int_parse_version(ArchiveHandle *AH, const char *versionString){	int			v;	v = parse_version(versionString);	if (v < 0)		die_horribly(AH, modulename, "could not parse version string \"%s\"\n", versionString);	return v;}static void_check_database_version(ArchiveHandle *AH, bool ignoreVersion){	int			myversion;	const char *remoteversion_str;	int			remoteversion;	myversion = _parse_version(AH, PG_VERSION);	remoteversion_str = PQparameterStatus(AH->connection, "server_version");	if (!remoteversion_str)		die_horribly(AH, modulename, "could not get server_version from libpq\n");	remoteversion = _parse_version(AH, remoteversion_str);	AH->public.remoteVersion = remoteversion;	if (myversion != remoteversion		&& (remoteversion < AH->public.minRemoteVersion ||			remoteversion > AH->public.maxRemoteVersion))	{		write_msg(NULL, "server version: %s; %s version: %s\n",				  remoteversion_str, progname, PG_VERSION);		if (ignoreVersion)			write_msg(NULL, "proceeding despite version mismatch\n");		else			die_horribly(AH, NULL, "aborting because of version mismatch  (Use the -i option to proceed anyway.)\n");	}}/* * Reconnect to the server.  If dbname is not NULL, use that database, * else the one associated with the archive handle.  If username is * not NULL, use that user name, else the one from the handle.	If * both the database and the user and match the existing connection * already, nothing will be done. * * Returns 1 in any case. */intReconnectToServer(ArchiveHandle *AH, const char *dbname, const char *username){	PGconn	   *newConn;	const char *newdbname;	const char *newusername;	if (!dbname)		newdbname = PQdb(AH->connection);	else		newdbname = dbname;	if (!username)		newusername = PQuser(AH->connection);	else		newusername = username;	/* Let's see if the request is already satisfied */	if (strcmp(newusername, PQuser(AH->connection)) == 0		&& strcmp(newdbname, PQdb(AH->connection)) == 0)		return 1;	newConn = _connectDB(AH, newdbname, newusername);	PQfinish(AH->connection);	AH->connection = newConn;	return 1;}/* * Connect to the db again. */static PGconn *_connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser){	int			need_pass;	PGconn	   *newConn;	char	   *password = NULL;	int			badPwd = 0;	int			noPwd = 0;	char	   *newdb;	char	   *newuser;	if (!reqdb)		newdb = PQdb(AH->connection);	else		newdb = (char *) reqdb;	if (!requser || (strlen(requser) == 0))		newuser = PQuser(AH->connection);	else		newuser = (char *) requser;	ahlog(AH, 1, "connecting to database \"%s\" as user \"%s\"\n", newdb, newuser);	if (AH->requirePassword)	{		password = simple_prompt("Password: ", 100, false);		if (password == NULL)			die_horribly(AH, modulename, "out of memory\n");	}	do	{		need_pass = false;		newConn = PQsetdbLogin(PQhost(AH->connection), PQport(AH->connection),							   NULL, NULL, newdb,							   newuser, password);		if (!newConn)			die_horribly(AH, modulename, "failed to reconnect to database\n");		if (PQstatus(newConn) == CONNECTION_BAD)		{			noPwd = (strcmp(PQerrorMessage(newConn),							"fe_sendauth: no password supplied\n") == 0);			badPwd = (strncmp(PQerrorMessage(newConn),					"Password authentication failed for user", 39) == 0);			if (noPwd || badPwd)			{				if (badPwd)					fprintf(stderr, "Password incorrect\n");				fprintf(stderr, "Connecting to %s as %s\n",						PQdb(AH->connection), newuser);				need_pass = true;				if (password)					free(password);				password = simple_prompt("Password: ", 100, false);			}			else				die_horribly(AH, modulename, "could not reconnect to database: %s",							 PQerrorMessage(newConn));		}	} while (need_pass);	if (password)		free(password);	/* check for version mismatch */	_check_database_version(AH, true);	PQsetNoticeProcessor(newConn, notice_processor, NULL);	return newConn;}/* * Make a database connection with the given parameters.  The * connection handle is returned, the parameters are stored in AHX. * An interactive password prompt is automatically issued if required. */PGconn *ConnectDatabase(Archive *AHX,				const char *dbname,				const char *pghost,				const char *pgport,				const char *username,				const int reqPwd,				const int ignoreVersion){	ArchiveHandle *AH = (ArchiveHandle *) AHX;	char	   *password = NULL;	bool		need_pass = false;	if (AH->connection)		die_horribly(AH, modulename, "already connected to a database\n");	if (reqPwd)	{		password = simple_prompt("Password: ", 100, false);		if (password == NULL)			die_horribly(AH, modulename, "out of memory\n");		AH->requirePassword = true;	}	else		AH->requirePassword = false;	/*	 * Start the connection.  Loop until we have a password if requested	 * by backend.	 */	do	{		need_pass = false;		AH->connection = PQsetdbLogin(pghost, pgport, NULL, NULL,									  dbname, username, password);		if (!AH->connection)			die_horribly(AH, modulename, "failed to connect to database\n");		if (PQstatus(AH->connection) == CONNECTION_BAD &&			strcmp(PQerrorMessage(AH->connection), "fe_sendauth: no password supplied\n") == 0 &&			!feof(stdin))		{			PQfinish(AH->connection);			need_pass = true;			free(password);			password = NULL;			password = simple_prompt("Password: ", 100, false);		}	} while (need_pass);	if (password)		free(password);	/* check to see that the backend connection was successfully made */	if (PQstatus(AH->connection) == CONNECTION_BAD)		die_horribly(AH, modulename, "connection to database \"%s\" failed: %s",				   PQdb(AH->connection), PQerrorMessage(AH->connection));	/* check for version mismatch */	_check_database_version(AH, ignoreVersion);	PQsetNoticeProcessor(AH->connection, notice_processor, NULL);	return AH->connection;}static voidnotice_processor(void *arg, const char *message){	write_msg(NULL, "%s", message);}/* Public interface *//* Convenience function to send a query. Monitors result to handle COPY statements */intExecuteSqlCommand(ArchiveHandle *AH, PQExpBuffer qry, char *desc, bool use_blob){	if (use_blob)		return _executeSqlCommand(AH, AH->blobConnection, qry, desc);	else		return _executeSqlCommand(AH, AH->connection, qry, desc);}/* * Handle command execution. This is used to execute a command on more than one connection, * but the 'pgCopyIn' setting assumes the COPY commands are ONLY executed on the primary * setting...an error will be raised otherwise. */static int_executeSqlCommand(ArchiveHandle *AH, PGconn *conn, PQExpBuffer qry, char *desc){	PGresult   *res;	/* fprintf(stderr, "Executing: '%s'\n\n", qry->data); */	res = PQexec(conn, qry->data);	if (!res)		die_horribly(AH, modulename, "%s: no result from server\n", desc);	if (PQresultStatus(res) != PGRES_COMMAND_OK && PQresultStatus(res) != PGRES_TUPLES_OK)	{		if (PQresultStatus(res) == PGRES_COPY_IN)		{			if (conn != AH->connection)				die_horribly(AH, modulename, "COPY command executed in non-primary connection\n");			AH->pgCopyIn = 1;		}		else			die_horribly(AH, modulename, "%s: %s",						 desc, PQerrorMessage(AH->connection));	}	PQclear(res);	return strlen(qry->data);}/* * Used by ExecuteSqlCommandBuf to send one buffered line when running a COPY command. */static char *_sendCopyLine(ArchiveHandle *AH, char *qry, char *eos){	size_t		loc;			/* Location of next newline */	int			pos = 0;		/* Current position */	int			sPos = 0;		/* Last pos of a slash char */	int			isEnd = 0;	/* loop to find unquoted newline ending the line of COPY data */	for (;;)	{		loc = strcspn(&qry[pos], "\n") + pos;		/* If no match, then wait */		if (loc >= (eos - qry)) /* None found */		{			appendBinaryPQExpBuffer(AH->pgCopyBuf, qry, (eos - qry));			return eos;		}		/*		 * fprintf(stderr, "Found cr at %d, prev char was %c, next was		 * %c\n", loc, qry[loc-1], qry[loc+1]);		 */		/* Count the number of preceding slashes */		sPos = loc;		while (sPos > 0 && qry[sPos - 1] == '\\')			sPos--;		sPos = loc - sPos;		/*		 * If an odd number of preceding slashes, then \n was escaped so		 * set the next search pos, and loop (if any left).		 */		if ((sPos & 1) == 1)		{			/* fprintf(stderr, "cr was escaped\n"); */			pos = loc + 1;			if (pos >= (eos - qry))			{				appendBinaryPQExpBuffer(AH->pgCopyBuf, qry, (eos - qry));				return eos;			}		}		else			break;

⌨️ 快捷键说明

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