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

📄 pg_backup_archiver.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
	/*	 * On Windows, we need to use binary mode to read/write non-text archive	 * formats.  Force stdin/stdout into binary mode if that is what we are	 * using.	 */#ifdef WIN32	if (fmt != archNull &&		(AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0))	{		if (mode == archModeWrite)			setmode(fileno(stdout), O_BINARY);		else			setmode(fileno(stdin), O_BINARY);	}#endif#if 0	write_msg(modulename, "archive format is %d\n", fmt);#endif	if (fmt == archUnknown)		AH->format = _discoverArchiveFormat(AH);	else		AH->format = fmt;	switch (AH->format)	{		case archCustom:			InitArchiveFmt_Custom(AH);			break;		case archFiles:			InitArchiveFmt_Files(AH);			break;		case archNull:			InitArchiveFmt_Null(AH);			break;		case archTar:			InitArchiveFmt_Tar(AH);			break;		default:			die_horribly(AH, modulename, "unrecognized file format \"%d\"\n", fmt);	}	/* sql error handling */	AH->public.exit_on_error = true;	AH->public.n_errors = 0;	return AH;}voidWriteDataChunks(ArchiveHandle *AH){	TocEntry   *te = AH->toc->next;	StartDataPtr startPtr;	EndDataPtr	endPtr;	while (te != AH->toc)	{		if (te->dataDumper != NULL)		{			AH->currToc = te;			/* printf("Writing data for %d (%x)\n", te->id, te); */			if (strcmp(te->desc, "BLOBS") == 0)			{				startPtr = AH->StartBlobsPtr;				endPtr = AH->EndBlobsPtr;			}			else			{				startPtr = AH->StartDataPtr;				endPtr = AH->EndDataPtr;			}			if (startPtr != NULL)				(*startPtr) (AH, te);			/*			 * printf("Dumper arg for %d is %x\n", te->id, te->dataDumperArg);			 */			/*			 * The user-provided DataDumper routine needs to call			 * AH->WriteData			 */			(*te->dataDumper) ((Archive *) AH, te->dataDumperArg);			if (endPtr != NULL)				(*endPtr) (AH, te);			AH->currToc = NULL;		}		te = te->next;	}}voidWriteToc(ArchiveHandle *AH){	TocEntry   *te;	char		workbuf[32];	int			i;	/* printf("%d TOC Entries to save\n", AH->tocCount); */	WriteInt(AH, AH->tocCount);	for (te = AH->toc->next; te != AH->toc; te = te->next)	{		WriteInt(AH, te->dumpId);		WriteInt(AH, te->dataDumper ? 1 : 0);		/* OID is recorded as a string for historical reasons */		sprintf(workbuf, "%u", te->catalogId.tableoid);		WriteStr(AH, workbuf);		sprintf(workbuf, "%u", te->catalogId.oid);		WriteStr(AH, workbuf);		WriteStr(AH, te->tag);		WriteStr(AH, te->desc);		WriteStr(AH, te->defn);		WriteStr(AH, te->dropStmt);		WriteStr(AH, te->copyStmt);		WriteStr(AH, te->namespace);		WriteStr(AH, te->tablespace);		WriteStr(AH, te->owner);		WriteStr(AH, te->withOids ? "true" : "false");		/* Dump list of dependencies */		for (i = 0; i < te->nDeps; i++)		{			sprintf(workbuf, "%d", te->dependencies[i]);			WriteStr(AH, workbuf);		}		WriteStr(AH, NULL);		/* Terminate List */		if (AH->WriteExtraTocPtr)			(*AH->WriteExtraTocPtr) (AH, te);	}}voidReadToc(ArchiveHandle *AH){	int			i;	char	   *tmp;	DumpId	   *deps;	int			depIdx;	int			depSize;	TocEntry   *te = AH->toc->next;	AH->tocCount = ReadInt(AH);	AH->maxDumpId = 0;	for (i = 0; i < AH->tocCount; i++)	{		te = (TocEntry *) calloc(1, sizeof(TocEntry));		te->dumpId = ReadInt(AH);		if (te->dumpId > AH->maxDumpId)			AH->maxDumpId = te->dumpId;		/* Sanity check */		if (te->dumpId <= 0)			die_horribly(AH, modulename,					   "entry ID %d out of range -- perhaps a corrupt TOC\n",						 te->dumpId);		te->hadDumper = ReadInt(AH);		if (AH->version >= K_VERS_1_8)		{			tmp = ReadStr(AH);			sscanf(tmp, "%u", &te->catalogId.tableoid);			free(tmp);		}		else			te->catalogId.tableoid = InvalidOid;		tmp = ReadStr(AH);		sscanf(tmp, "%u", &te->catalogId.oid);		free(tmp);		te->tag = ReadStr(AH);		te->desc = ReadStr(AH);		te->defn = ReadStr(AH);		te->dropStmt = ReadStr(AH);		if (AH->version >= K_VERS_1_3)			te->copyStmt = ReadStr(AH);		if (AH->version >= K_VERS_1_6)			te->namespace = ReadStr(AH);		if (AH->version >= K_VERS_1_10)			te->tablespace = ReadStr(AH);		te->owner = ReadStr(AH);		if (AH->version >= K_VERS_1_9)		{			if (strcmp(ReadStr(AH), "true") == 0)				te->withOids = true;			else				te->withOids = false;		}		else			te->withOids = true;		/* Read TOC entry dependencies */		if (AH->version >= K_VERS_1_5)		{			depSize = 100;			deps = (DumpId *) malloc(sizeof(DumpId) * depSize);			depIdx = 0;			for (;;)			{				tmp = ReadStr(AH);				if (!tmp)					break;		/* end of list */				if (depIdx >= depSize)				{					depSize *= 2;					deps = (DumpId *) realloc(deps, sizeof(DumpId) * depSize);				}				sscanf(tmp, "%d", &deps[depIdx]);				free(tmp);				depIdx++;			}			if (depIdx > 0)		/* We have a non-null entry */			{				deps = (DumpId *) realloc(deps, sizeof(DumpId) * depIdx);				te->dependencies = deps;				te->nDeps = depIdx;			}			else			{				free(deps);				te->dependencies = NULL;				te->nDeps = 0;			}		}		else		{			te->dependencies = NULL;			te->nDeps = 0;		}		if (AH->ReadExtraTocPtr)			(*AH->ReadExtraTocPtr) (AH, te);		ahlog(AH, 3, "read TOC entry %d (ID %d) for %s %s\n",			  i, te->dumpId, te->desc, te->tag);		te->prev = AH->toc->prev;		AH->toc->prev->next = te;		AH->toc->prev = te;		te->next = AH->toc;	}}static teReqs_tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls){	teReqs		res = REQ_ALL;	/* ENCODING objects are dumped specially, so always reject here */	if (strcmp(te->desc, "ENCODING") == 0)		return 0;	/* If it's an ACL, maybe ignore it */	if ((!include_acls || ropt->aclsSkip) && strcmp(te->desc, "ACL") == 0)		return 0;	if (!ropt->create && strcmp(te->desc, "DATABASE") == 0)		return 0;	/* Check options for selective dump/restore */	if (ropt->schemaNames)	{		/* If no namespace is specified, it means all. */		if (!te->namespace)			return 0;		if (strcmp(ropt->schemaNames, te->namespace) != 0)			return 0;	}	if (ropt->selTypes)	{		if (strcmp(te->desc, "TABLE") == 0 ||			strcmp(te->desc, "TABLE DATA") == 0)		{			if (!ropt->selTable)				return 0;			if (ropt->tableNames && strcmp(ropt->tableNames, te->tag) != 0)				return 0;		}		else if (strcmp(te->desc, "INDEX") == 0)		{			if (!ropt->selIndex)				return 0;			if (ropt->indexNames && strcmp(ropt->indexNames, te->tag) != 0)				return 0;		}		else if (strcmp(te->desc, "FUNCTION") == 0)		{			if (!ropt->selFunction)				return 0;			if (ropt->functionNames && strcmp(ropt->functionNames, te->tag) != 0)				return 0;		}		else if (strcmp(te->desc, "TRIGGER") == 0)		{			if (!ropt->selTrigger)				return 0;			if (ropt->triggerNames && strcmp(ropt->triggerNames, te->tag) != 0)				return 0;		}		else			return 0;	}	/*	 * Check if we had a dataDumper. Indicates if the entry is schema or data	 */	if (!te->hadDumper)	{		/*		 * Special Case: If 'SEQUENCE SET' then it is considered a data entry		 */		if (strcmp(te->desc, "SEQUENCE SET") == 0)			res = res & REQ_DATA;		else			res = res & ~REQ_DATA;	}	/*	 * Special case: <Init> type with <Max OID> tag; this is obsolete and we	 * always ignore it.	 */	if ((strcmp(te->desc, "<Init>") == 0) && (strcmp(te->tag, "Max OID") == 0))		return 0;	/* Mask it if we only want schema */	if (ropt->schemaOnly)		res = res & REQ_SCHEMA;	/* Mask it we only want data */	if (ropt->dataOnly)		res = res & REQ_DATA;	/* Mask it if we don't have a schema contribution */	if (!te->defn || strlen(te->defn) == 0)		res = res & ~REQ_SCHEMA;	/* Finally, if we used a list, limit based on that as well */	if (ropt->limitToList && !ropt->idWanted[te->dumpId - 1])		return 0;	return res;}/* * Issue SET commands for parameters that we want to have set the same way * at all times during execution of a restore script. */static void_doSetFixedOutputState(ArchiveHandle *AH){	TocEntry   *te;	/* If we have an encoding setting, emit that */	te = AH->toc->next;	while (te != AH->toc)	{		if (strcmp(te->desc, "ENCODING") == 0)		{			ahprintf(AH, "%s", te->defn);			break;		}		te = te->next;	}	/* Make sure function checking is disabled */	ahprintf(AH, "SET check_function_bodies = false;\n");	/* Avoid annoying notices etc */	ahprintf(AH, "SET client_min_messages = warning;\n");	ahprintf(AH, "\n");}/* * Issue a SET SESSION AUTHORIZATION command.  Caller is responsible * for updating state if appropriate.  If user is NULL or an empty string, * the specification DEFAULT will be used. */static void_doSetSessionAuth(ArchiveHandle *AH, const char *user){	PQExpBuffer cmd = createPQExpBuffer();	appendPQExpBuffer(cmd, "SET SESSION AUTHORIZATION ");	/*	 * SQL requires a string literal here.	Might as well be correct.	 */	if (user && *user)		appendStringLiteral(cmd, user, false);	else		appendPQExpBuffer(cmd, "DEFAULT");	appendPQExpBuffer(cmd, ";");	if (RestoringToDB(AH))	{		PGresult   *res;		res = PQexec(AH->connection, cmd->data);		if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)			/* NOT warn_or_die_horribly... use -O instead to skip this. */			die_horribly(AH, modulename, "could not set session user to \"%s\": %s",						 user, PQerrorMessage(AH->connection));		PQclear(res);	}	else		ahprintf(AH, "%s\n\n", cmd->data);	destroyPQExpBuffer(cmd);}/* * Issue a SET default_with_oids command.  Caller is responsible * for updating state if appropriate. */static void_doSetWithOids(ArchiveHandle *AH, const bool withOids){	PQExpBuffer cmd = createPQExpBuffer();	appendPQExpBuffer(cmd, "SET default_with_oids = %s;", withOids ?					  "true" : "false");	if (RestoringToDB(AH))	{		PGresult   *res;		res = PQexec(AH->connection, cmd->data);		if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)			warn_or_die_horribly(AH, modulename,								 "could not set default_with_oids: %s",								 PQerrorMessage(AH->connection));		PQclear(res);	}	else		ahprintf(AH, "%s\n\n", cmd->data);	destroyPQExpBuffer(cmd);}/* * Issue the commands to connect to the specified database. * * If we're currently restoring right into a database, this will * actually establish a connection. Otherwise it puts a \connect into * the script output. * * NULL dbname implies reconnecting to the current DB (pretty useless). */static void_reconnectToDB(ArchiveHandle *AH, const char *dbname){	if (RestoringToDB(AH))		ReconnectToServer(AH, dbname, NULL);	else	{		PQExpBuffer qry = createPQExpBuffer();		appendPQExpBuffer(qry, "\\connect %s\n\n",						  dbname ? fmtId(dbname) : "-");		ahprintf(AH, "%s", qry->data);		destroyPQExpBuffer(qry);	}	/*	 * NOTE: currUser keeps track of what the imaginary session user in our	 * script is.  It's now effectively reset to the original userID.	 */	if (AH->currUser)		free(AH->currUser);	AH->currUser = strdup("");	/* don't assume we still know the output schema */	if (AH->currSchema)		free(AH->currSchema);	AH->currSchema = strdup("");	AH->currWithOids = -1;	/* re-establish fixed state */	_doSetFixedOutputState(AH);}/* * Become the specified user, and update state to avoid redundant commands * * NULL or empty argument is taken to mean restoring the session default */static void_becomeUser(ArchiveHandle *AH, const char *user){	if (!user)		user = "";				/* avoid null pointers */	if (AH->currUser && strcmp(AH->currUser, user) == 0)		return;					/* no need to do anything */	_doSetSessionAuth(AH, user);	/*	 * NOTE: currUser keeps track of what the imaginary session user in our	 * script is	 */

⌨️ 快捷键说明

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