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

📄 pg_backup_db.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * pg_backup_db.c * *	Implements the basic DB functions used by the archiver. * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.66.2.2 2006/02/09 18:28:35 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 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 bool _isIdentChar(unsigned char c);static bool _isDQChar(unsigned char c, bool atStart);#define DB_MAX_ERR_STMT 128static 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.remoteVersionStr = strdup(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 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(newdbname, PQdb(AH->connection)) == 0 &&		strcmp(newusername, PQuser(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),							PQnoPasswordSupplied) == 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",						newdb, 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));			PQfinish(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), PQnoPasswordSupplied) == 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){	PGconn	   *conn = AH->connection;	PGresult   *res;	char		errStmt[DB_MAX_ERR_STMT];	/* 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)		{			AH->pgCopyIn = true;		}		else		{			strncpy(errStmt, qry->data, DB_MAX_ERR_STMT);			if (errStmt[DB_MAX_ERR_STMT - 1] != '\0')			{				errStmt[DB_MAX_ERR_STMT - 4] = '.';				errStmt[DB_MAX_ERR_STMT - 3] = '.';				errStmt[DB_MAX_ERR_STMT - 2] = '.';				errStmt[DB_MAX_ERR_STMT - 1] = '\0';			}			warn_or_die_horribly(AH, modulename, "%s: %s    Command was: %s\n",								 desc, PQerrorMessage(AH->connection),								 errStmt);		}	}	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 */		{

⌨️ 快捷键说明

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