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

📄 copy.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
/*------------------------------------------------------------------------- * * copy.c * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/commands/copy.c,v 1.81 1999/07/03 00:32:39 momjian Exp $ * *------------------------------------------------------------------------- */#include <string.h>#include <unistd.h>#include <postgres.h>#include <access/heapam.h>#include <tcop/dest.h>#include <fmgr.h>#include <miscadmin.h>#include <utils/builtins.h>#include <utils/acl.h>#include <sys/stat.h>#include <catalog/pg_index.h>#include <utils/syscache.h>#include <utils/memutils.h>#include <executor/executor.h>#include <access/transam.h>#include <catalog/index.h>#include <access/genam.h>#include <catalog/pg_type.h>#include <catalog/catname.h>#include <catalog/pg_shadow.h>#include <commands/copy.h>#include "commands/trigger.h"#include <storage/fd.h>#include <libpq/libpq.h>#ifdef MULTIBYTE#include "mb/pg_wchar.h"#endif#define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))#define VALUE(c) ((c) - '0')/* non-export function prototypes */static void CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim);static void CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim);static Oid	GetOutputFunction(Oid type);static Oid	GetTypeElement(Oid type);static Oid	GetInputFunction(Oid type);static Oid	IsTypeByVal(Oid type);static void GetIndexRelations(Oid main_relation_oid,				  int *n_indices,				  Relation **index_rels);#ifdef COPY_PATCHstatic void CopyReadNewline(FILE *fp, int *newline);static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline);#elsestatic char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim);#endifstatic void CopyAttributeOut(FILE *fp, char *string, char *delim, int is_array);static int	CountTuples(Relation relation);static int	lineno;/* * Internal communications functions */static void CopySendData(void *databuf, int datasize, FILE *fp);static void CopySendString(char *str, FILE *fp);static void CopySendChar(char c, FILE *fp);static void CopyGetData(void *databuf, int datasize, FILE *fp);static int	CopyGetChar(FILE *fp);static int	CopyGetEof(FILE *fp);static int	CopyPeekChar(FILE *fp);static void CopyDonePeek(FILE *fp, int c, int pickup);/* * CopySendData sends output data either to the file *	specified by fp or, if fp is NULL, using the standard *	backend->frontend functions * * CopySendString does the same for null-terminated strings * CopySendChar does the same for single characters * * NB: no data conversion is applied by these functions */static voidCopySendData(void *databuf, int datasize, FILE *fp){	if (!fp)		pq_putbytes((char *) databuf, datasize);	else		fwrite(databuf, datasize, 1, fp);}static voidCopySendString(char *str, FILE *fp){	CopySendData(str, strlen(str), fp);}static voidCopySendChar(char c, FILE *fp){	CopySendData(&c, 1, fp);}/* * CopyGetData reads output data either from the file *	specified by fp or, if fp is NULL, using the standard *	backend->frontend functions * * CopyGetChar does the same for single characters * CopyGetEof checks if it's EOF on the input * * NB: no data conversion is applied by these functions */static voidCopyGetData(void *databuf, int datasize, FILE *fp){	if (!fp)		pq_getbytes((char *) databuf, datasize);	else		fread(databuf, datasize, 1, fp);}static intCopyGetChar(FILE *fp){	if (!fp)	{		unsigned char ch;		if (pq_getbytes((char *) &ch, 1))			return EOF;		return ch;	}	else		return getc(fp);}static intCopyGetEof(FILE *fp){	if (!fp)		return 0;				/* Never return EOF when talking to								 * frontend ? */	else		return feof(fp);}/* * CopyPeekChar reads a byte in "peekable" mode. * after each call to CopyPeekChar, a call to CopyDonePeek _must_ * follow. * CopyDonePeek will either take the peeked char off the steam * (if pickup is != 0) or leave it on the stream (if pickup == 0) */static intCopyPeekChar(FILE *fp){	if (!fp)		return pq_peekbyte();	else		return getc(fp);}static voidCopyDonePeek(FILE *fp, int c, int pickup){	if (!fp)	{		if (pickup)		{			/*			 * We want to pick it up - just receive again into dummy			 * buffer			 */			char		c;			pq_getbytes(&c, 1);		}		/* If we didn't want to pick it up, just leave it where it sits */	}	else	{		if (!pickup)		{			/* We don't want to pick it up - so put it back in there */			ungetc(c, fp);		}		/* If we wanted to pick it up, it's already there */	}}/* *	 DoCopy executes a the SQL COPY statement. */voidDoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,	   char *filename, char *delim){/*----------------------------------------------------------------------------  Either unload or reload contents of class <relname>, depending on <from>.  If <pipe> is false, transfer is between the class and the file named  <filename>.  Otherwise, transfer is between the class and our regular  input/output stream.	The latter could be either stdin/stdout or a  socket, depending on whether we're running under Postmaster control.  Iff <binary>, unload or reload in the binary format, as opposed to the  more wasteful but more robust and portable text format.  If in the text format, delimit columns with delimiter <delim>.  When loading in the text format from an input stream (as opposed to  a file), recognize a "." on a line by itself as EOF.	Also recognize  a stream EOF.  When unloading in the text format to an output stream,  write a "." on a line by itself at the end of the data.  Iff <oids>, unload or reload the format that includes OID information.  Do not allow a Postgres user without superuser privilege to read from  or write to a file.  Do not allow the copy if user doesn't have proper permission to access  the class.----------------------------------------------------------------------------*/	FILE	   *fp;	Relation	rel;	extern char *UserName;		/* defined in global.c */	const AclMode required_access = from ? ACL_WR : ACL_RD;	int			result;	rel = heap_openr(relname);	if (rel == NULL)		elog(ERROR, "COPY command failed.  Class %s "			 "does not exist.", relname);	result = pg_aclcheck(relname, UserName, required_access);	if (result != ACLCHECK_OK)		elog(ERROR, "%s: %s", relname, aclcheck_error_strings[result]);	/* Above should not return */	else if (!superuser() && !pipe)		elog(ERROR, "You must have Postgres superuser privilege to do a COPY "			 "directly to or from a file.  Anyone can COPY to stdout or "			 "from stdin.  Psql's \\copy command also works for anyone.");	/* Above should not return. */	else	{		if (from)		{						/* copy from file to database */			if (rel->rd_rel->relkind == RELKIND_SEQUENCE)				elog(ERROR, "You can't change sequence relation %s", relname);			if (pipe)			{				if (IsUnderPostmaster)				{					ReceiveCopyBegin();					fp = NULL;				}				else					fp = stdin;			}			else			{#ifndef __CYGWIN32__				fp = AllocateFile(filename, "r");#else				fp = AllocateFile(filename, "rb");#endif				if (fp == NULL)					elog(ERROR, "COPY command, running in backend with "						 "effective uid %d, could not open file '%s' for "						 "reading.  Errno = %s (%d).",						 geteuid(), filename, strerror(errno), errno);			}			CopyFrom(rel, binary, oids, fp, delim);		}		else		{						/* copy from database to file */			if (pipe)			{				if (IsUnderPostmaster)				{					SendCopyBegin();					pq_startcopyout();					fp = NULL;				}				else					fp = stdout;			}			else			{				mode_t		oumask;		/* Pre-existing umask value */				oumask = umask((mode_t) 0);#ifndef __CYGWIN32__				fp = AllocateFile(filename, "w");#else				fp = AllocateFile(filename, "wb");#endif				umask(oumask);				if (fp == NULL)					elog(ERROR, "COPY command, running in backend with "						 "effective uid %d, could not open file '%s' for "						 "writing.  Errno = %s (%d).",						 geteuid(), filename, strerror(errno), errno);			}			CopyTo(rel, binary, oids, fp, delim);		}		if (!pipe)		{			FreeFile(fp);		}		else if (!from)		{			if (!binary)				CopySendData("\\.\n", 3, fp);			if (IsUnderPostmaster)				pq_endcopyout(false);		}	}}static voidCopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim){	HeapTuple	tuple;	HeapScanDesc scandesc;	int32		attr_count,				i;	Form_pg_attribute *attr;	FmgrInfo   *out_functions;	Oid			out_func_oid;	Oid		   *elements;	int32	   *typmod;	Datum		value;	bool		isnull;			/* The attribute we are copying is null */	char	   *nulls;	/*	 * <nulls> is a (dynamically allocated) array with one character per	 * attribute in the instance being copied.	nulls[I-1] is 'n' if	 * Attribute Number I is null, and ' ' otherwise.	 *	 * <nulls> is meaningful only if we are doing a binary copy.	 */	char	   *string;	int32		ntuples;	TupleDesc	tupDesc;	scandesc = heap_beginscan(rel, 0, QuerySnapshot, 0, NULL);	attr_count = rel->rd_att->natts;	attr = rel->rd_att->attrs;	tupDesc = rel->rd_att;	if (!binary)	{		out_functions = (FmgrInfo *) palloc(attr_count * sizeof(FmgrInfo));		elements = (Oid *) palloc(attr_count * sizeof(Oid));		typmod = (int32 *) palloc(attr_count * sizeof(int32));		for (i = 0; i < attr_count; i++)		{			out_func_oid = (Oid) GetOutputFunction(attr[i]->atttypid);			fmgr_info(out_func_oid, &out_functions[i]);			elements[i] = GetTypeElement(attr[i]->atttypid);			typmod[i] = attr[i]->atttypmod;		}		nulls = NULL;			/* meaningless, but compiler doesn't know								 * that */	}	else	{		elements = NULL;		typmod = NULL;		out_functions = NULL;		nulls = (char *) palloc(attr_count);		for (i = 0; i < attr_count; i++)			nulls[i] = ' ';		/* XXX expensive */		ntuples = CountTuples(rel);		CopySendData(&ntuples, sizeof(int32), fp);	}	while (HeapTupleIsValid(tuple = heap_getnext(scandesc, 0)))	{		if (oids && !binary)		{			CopySendString(oidout(tuple->t_data->t_oid), fp);			CopySendChar(delim[0], fp);		}		for (i = 0; i < attr_count; i++)		{			value = heap_getattr(tuple, i + 1, tupDesc, &isnull);			if (!binary)			{				if (!isnull)				{					string = (char *) (*fmgr_faddr(&out_functions[i]))						(value, elements[i], typmod[i]);					CopyAttributeOut(fp, string, delim, attr[i]->attnelems);					pfree(string);				}				else					CopySendString("\\N", fp);	/* null indicator */				if (i == attr_count - 1)					CopySendChar('\n', fp);				else				{					/*					 * when copying out, only use the first char of the					 * delim string					 */					CopySendChar(delim[0], fp);				}			}			else			{				/*				 * only interesting thing heap_getattr tells us in this				 * case is if we have a null attribute or not.				 */				if (isnull)					nulls[i] = 'n';			}		}		if (binary)

⌨️ 快捷键说明

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