copy.c 46.8 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * copy.c
4
 *		Implements the COPY utility command.
5
 *
Bruce Momjian's avatar
Bruce Momjian committed
6
 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
Bruce Momjian's avatar
Add:  
Bruce Momjian committed
7
 * Portions Copyright (c) 1994, Regents of the University of California
8 9 10
 *
 *
 * IDENTIFICATION
11
 *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.195 2003/04/22 00:08:06 tgl Exp $
12 13 14
 *
 *-------------------------------------------------------------------------
 */
15
#include "postgres.h"
16

Tom Lane's avatar
Tom Lane committed
17
#include <errno.h>
18
#include <unistd.h>
Bruce Momjian's avatar
Bruce Momjian committed
19
#include <sys/stat.h>
20

21
#include "access/genam.h"
Bruce Momjian's avatar
Bruce Momjian committed
22
#include "access/heapam.h"
23
#include "access/printtup.h"
24
#include "catalog/catname.h"
Bruce Momjian's avatar
Bruce Momjian committed
25
#include "catalog/index.h"
26
#include "catalog/namespace.h"
Bruce Momjian's avatar
Bruce Momjian committed
27
#include "catalog/pg_index.h"
28
#include "catalog/pg_shadow.h"
Bruce Momjian's avatar
Bruce Momjian committed
29
#include "catalog/pg_type.h"
30
#include "commands/copy.h"
31
#include "commands/trigger.h"
Bruce Momjian's avatar
Bruce Momjian committed
32
#include "executor/executor.h"
33
#include "libpq/libpq.h"
34
#include "libpq/pqformat.h"
35
#include "mb/pg_wchar.h"
Bruce Momjian's avatar
Bruce Momjian committed
36
#include "miscadmin.h"
37 38
#include "nodes/makefuncs.h"
#include "parser/parse_coerce.h"
39
#include "parser/parse_relation.h"
40
#include "rewrite/rewriteHandler.h"
41
#include "tcop/pquery.h"
42
#include "tcop/tcopprot.h"
Bruce Momjian's avatar
Bruce Momjian committed
43 44
#include "utils/acl.h"
#include "utils/builtins.h"
45
#include "utils/relcache.h"
46
#include "utils/lsyscache.h"
Bruce Momjian's avatar
Bruce Momjian committed
47
#include "utils/syscache.h"
48

49

50
#define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))
51
#define OCTVALUE(c) ((c) - '0')
52

53 54 55 56 57 58 59 60 61 62 63
/*
 * Represents the different source/dest cases we need to worry about at
 * the bottom level
 */
typedef enum CopyDest
{
	COPY_FILE,					/* to/from file */
	COPY_OLD_FE,				/* to/from frontend (old protocol) */
	COPY_NEW_FE					/* to/from frontend (new protocol) */
} CopyDest;

64 65 66
/*
 * Represents the type of data returned by CopyReadAttribute()
 */
Bruce Momjian's avatar
Bruce Momjian committed
67 68 69 70 71 72
typedef enum CopyReadResult
{
	NORMAL_ATTR,
	END_OF_LINE,
	END_OF_FILE
} CopyReadResult;
73

74 75 76 77 78 79 80 81 82 83 84 85
/*
 *	Represents the end-of-line terminator of the input
 */
typedef enum EolType
{
	EOL_UNKNOWN,
	EOL_NL,
	EOL_CR,
	EOL_CRNL
} EolType;


86
/* non-export function prototypes */
87
static void CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
88
				   char *delim, char *null_print);
89
static void CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
90
					 char *delim, char *null_print);
91
static Oid	GetInputFunction(Oid type);
92
static Oid	GetTypeElement(Oid type);
93 94
static char *CopyReadAttribute(const char *delim, CopyReadResult *result);
static void CopyAttributeOut(char *string, char *delim);
95
static List *CopyGetAttnums(Relation rel, List *attnamelist);
96

97
static const char BinarySignature[12] = "PGBCOPY\n\377\r\n\0";
98

99 100 101 102
/*
 * Static communication variables ... pretty grotty, but COPY has
 * never been reentrant...
 */
103
int			copy_lineno = 0;	/* exported for use by elog() -- dz */
104 105 106 107 108

static CopyDest copy_dest;
static FILE *copy_file;			/* if copy_dest == COPY_FILE */
static StringInfo copy_msgbuf;	/* if copy_dest == COPY_NEW_FE */
static bool fe_eof;				/* true if detected end of copy data */
109
static EolType eol_type;
110

111 112 113 114 115 116 117 118 119
/*
 * These static variables are used to avoid incurring overhead for each
 * attribute processed.  attribute_buf is reused on each CopyReadAttribute
 * call to hold the string being read in.  Under normal use it will soon
 * grow to a suitable size, and then we will avoid palloc/pfree overhead
 * for subsequent attributes.  Note that CopyReadAttribute returns a pointer
 * to attribute_buf's data buffer!
 * encoding, if needed, can be set once at the start of the copy operation.
 */
120 121
static StringInfoData attribute_buf;

122 123
static int	client_encoding;
static int	server_encoding;
124

Bruce Momjian's avatar
Bruce Momjian committed
125
/*
126 127
 * Internal communications functions
 */
128 129
static void SendCopyBegin(bool binary);
static void ReceiveCopyBegin(bool binary);
130
static void SendCopyEnd(bool binary);
131 132 133
static void CopySendData(void *databuf, int datasize);
static void CopySendString(const char *str);
static void CopySendChar(char c);
134
static void CopySendEndOfRow(bool binary);
135 136 137 138 139
static void CopyGetData(void *databuf, int datasize);
static int	CopyGetChar(void);
#define CopyGetEof()  (fe_eof)
static int	CopyPeekChar(void);
static void CopyDonePeek(int c, bool pickup);
140 141

/*
142 143
 * Send copy start/stop messages for frontend copies.  These have changed
 * in past protocol redesigns.
144
 */
145
static void
146
SendCopyBegin(bool binary)
Bruce Momjian's avatar
Bruce Momjian committed
147
{
148 149
	if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
	{
150 151 152 153 154 155
		/* new way */
		StringInfoData buf;

		pq_beginmessage(&buf, 'H');
		pq_sendbyte(&buf, binary ? 1 : 0);
		pq_endmessage(&buf);
156
		copy_dest = COPY_NEW_FE;
157
		copy_msgbuf = makeStringInfo();
158 159
	}
	else if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
160
	{
161 162 163 164 165
		/* old way */
		if (binary)
			elog(ERROR, "COPY BINARY is not supported to stdout or from stdin");
		pq_putemptymessage('H');
		/* grottiness needed for old COPY OUT protocol */
166 167
		pq_startcopyout();
		copy_dest = COPY_OLD_FE;
168
	}
Bruce Momjian's avatar
Bruce Momjian committed
169
	else
170
	{
171 172 173 174 175
		/* very old way */
		if (binary)
			elog(ERROR, "COPY BINARY is not supported to stdout or from stdin");
		pq_putemptymessage('B');
		/* grottiness needed for old COPY OUT protocol */
176 177
		pq_startcopyout();
		copy_dest = COPY_OLD_FE;
178
	}
179
}
Bruce Momjian's avatar
Bruce Momjian committed
180

181
static void
182
ReceiveCopyBegin(bool binary)
Bruce Momjian's avatar
Bruce Momjian committed
183
{
184 185
	if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
	{
186 187 188 189 190 191
		/* new way */
		StringInfoData buf;

		pq_beginmessage(&buf, 'G');
		pq_sendbyte(&buf, binary ? 1 : 0);
		pq_endmessage(&buf);
192 193 194 195 196
		copy_dest = COPY_NEW_FE;
		copy_msgbuf = makeStringInfo();
	}
	else if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
	{
197 198 199 200
		/* old way */
		if (binary)
			elog(ERROR, "COPY BINARY is not supported to stdout or from stdin");
		pq_putemptymessage('G');
201 202 203 204
		copy_dest = COPY_OLD_FE;
	}
	else
	{
205 206 207 208
		/* very old way */
		if (binary)
			elog(ERROR, "COPY BINARY is not supported to stdout or from stdin");
		pq_putemptymessage('D');
209 210 211 212
		copy_dest = COPY_OLD_FE;
	}
	/* We *must* flush here to ensure FE knows it can send. */
	pq_flush();
213 214
}

215
static void
216
SendCopyEnd(bool binary)
Bruce Momjian's avatar
Bruce Momjian committed
217
{
218
	if (copy_dest == COPY_NEW_FE)
219
	{
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
		if (binary)
		{
			/* Need to flush out file trailer word */
			CopySendEndOfRow(true);
		}
		else
		{
			/* Shouldn't have any unsent data */
			Assert(copy_msgbuf->len == 0);
		}
		/* Send Copy Done message */
		pq_putemptymessage('c');
	}
	else
	{
		/* The FE/BE protocol uses \n as newline for all platforms */
		CopySendData("\\.\n", 3);
		pq_endcopyout(false);
238
	}
239 240
}

241
/*----------
242 243 244
 * CopySendData sends output data to the destination (file or frontend)
 * CopySendString does the same for null-terminated strings
 * CopySendChar does the same for single characters
245
 * CopySendEndOfRow does the appropriate thing at end of each data row
246 247
 *
 * NB: no data conversion is applied by these functions
248
 *----------
249
 */
250
static void
251
CopySendData(void *databuf, int datasize)
Bruce Momjian's avatar
Bruce Momjian committed
252
{
253
	switch (copy_dest)
254
	{
255 256 257 258 259 260 261
		case COPY_FILE:
			fwrite(databuf, datasize, 1, copy_file);
			if (ferror(copy_file))
				elog(ERROR, "CopySendData: %m");
			break;
		case COPY_OLD_FE:
			if (pq_putbytes((char *) databuf, datasize))
262 263 264 265
			{
				/* no hope of recovering connection sync, so FATAL */
				elog(FATAL, "CopySendData: connection lost");
			}
266 267
			break;
		case COPY_NEW_FE:
268
			appendBinaryStringInfo(copy_msgbuf, (char *) databuf, datasize);
269
			break;
270
	}
271 272
}

273 274 275 276 277 278 279 280 281 282 283 284
static void
CopySendString(const char *str)
{
	CopySendData((void *) str, strlen(str));
}

static void
CopySendChar(char c)
{
	CopySendData(&c, 1);
}

285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
static void
CopySendEndOfRow(bool binary)
{
	switch (copy_dest)
	{
		case COPY_FILE:
			if (!binary)
			{
				/* Default line termination depends on platform */
#ifndef WIN32
				CopySendChar('\n');
#else
				CopySendString("\r\n");
#endif
			}
			break;
		case COPY_OLD_FE:
			/* The FE/BE protocol uses \n as newline for all platforms */
			if (!binary)
				CopySendChar('\n');
			break;
		case COPY_NEW_FE:
			/* The FE/BE protocol uses \n as newline for all platforms */
			if (!binary)
				CopySendChar('\n');
			/* Dump the accumulated row as one CopyData message */
			(void) pq_putmessage('d', copy_msgbuf->data, copy_msgbuf->len);
			/* Reset copy_msgbuf to empty */
			copy_msgbuf->len = 0;
			copy_msgbuf->data[0] = '\0';
			break;
	}
}

319 320 321 322 323 324 325 326 327 328 329 330 331 332
/*
 * CopyGetData reads data from the source (file or frontend)
 * CopyGetChar does the same for single characters
 *
 * CopyGetEof checks if EOF was detected by previous Get operation.
 *
 * Note: when copying from the frontend, we expect a proper EOF mark per
 * protocol; if the frontend simply drops the connection, we raise error.
 * It seems unwise to allow the COPY IN to complete normally in that case.
 *
 * NB: no data conversion is applied by these functions
 */
static void
CopyGetData(void *databuf, int datasize)
Bruce Momjian's avatar
Bruce Momjian committed
333
{
334
	switch (copy_dest)
Bruce Momjian's avatar
Bruce Momjian committed
335
	{
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
		case COPY_FILE:
			fread(databuf, datasize, 1, copy_file);
			if (feof(copy_file))
				fe_eof = true;
			break;
		case COPY_OLD_FE:
			if (pq_getbytes((char *) databuf, datasize))
			{
				/* Only a \. terminator is legal EOF in old protocol */
				elog(ERROR, "unexpected EOF on client connection");
			}
			break;
		case COPY_NEW_FE:
			while (datasize > 0 && !fe_eof)
			{
				int		avail;
Bruce Momjian's avatar
Bruce Momjian committed
352

353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
				while (copy_msgbuf->cursor >= copy_msgbuf->len)
				{
					/* Try to receive another message */
					int			mtype;

					mtype = pq_getbyte();
					if (mtype == EOF)
						elog(ERROR, "unexpected EOF on client connection");
					if (pq_getmessage(copy_msgbuf, 0))
						elog(ERROR, "unexpected EOF on client connection");
					switch (mtype)
					{
						case 'd': /* CopyData */
							break;
						case 'c': /* CopyDone */
							/* COPY IN correctly terminated by frontend */
							fe_eof = true;
							return;
						case 'f': /* CopyFail */
							elog(ERROR, "COPY IN failed: %s",
								 pq_getmsgstring(copy_msgbuf));
							break;
						default:
							elog(ERROR, "unexpected message type %c during COPY IN",
								 mtype);
							break;
					}
				}
				avail = copy_msgbuf->len - copy_msgbuf->cursor;
				if (avail > datasize)
					avail = datasize;
				pq_copymsgbytes(copy_msgbuf, databuf, avail);
				databuf = (void *) ((char *) databuf + avail);
				datasize =- avail;
			}
			break;
Bruce Momjian's avatar
Bruce Momjian committed
389
	}
390 391
}

392
static int
393
CopyGetChar(void)
Bruce Momjian's avatar
Bruce Momjian committed
394
{
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
	int		ch;

	switch (copy_dest)
	{
		case COPY_FILE:
			ch = getc(copy_file);
			break;
		case COPY_OLD_FE:
			ch = pq_getbyte();
			if (ch == EOF)
			{
				/* Only a \. terminator is legal EOF in old protocol */
				elog(ERROR, "unexpected EOF on client connection");
			}
			break;
		case COPY_NEW_FE:
		{
			unsigned char	cc;

			CopyGetData(&cc, 1);
			if (fe_eof)
				ch = EOF;
			else
				ch = cc;
			break;
		}
		default:
			ch = EOF;
			break;
	}
	if (ch == EOF)
		fe_eof = true;
	return ch;
428 429 430 431
}

/*
 * CopyPeekChar reads a byte in "peekable" mode.
432
 *
433
 * after each call to CopyPeekChar, a call to CopyDonePeek _must_
434
 * follow, unless EOF was returned.
435 436 437
 *
 * CopyDonePeek will either take the peeked char off the stream
 * (if pickup is true) or leave it on the stream (if pickup is false).
438
 */
439
static int
440
CopyPeekChar(void)
Bruce Momjian's avatar
Bruce Momjian committed
441
{
442 443 444
	int		ch;

	switch (copy_dest)
445
	{
446 447 448 449 450 451 452 453 454 455 456 457 458 459
		case COPY_FILE:
			ch = getc(copy_file);
			break;
		case COPY_OLD_FE:
			ch = pq_peekbyte();
			if (ch == EOF)
			{
				/* Only a \. terminator is legal EOF in old protocol */
				elog(ERROR, "unexpected EOF on client connection");
			}
			break;
		case COPY_NEW_FE:
		{
			unsigned char	cc;
460

461 462 463 464 465 466 467 468 469 470
			CopyGetData(&cc, 1);
			if (fe_eof)
				ch = EOF;
			else
				ch = cc;
			break;
		}
		default:
			ch = EOF;
			break;
471
	}
472 473 474
	if (ch == EOF)
		fe_eof = true;
	return ch;
475 476
}

477
static void
478
CopyDonePeek(int c, bool pickup)
Bruce Momjian's avatar
Bruce Momjian committed
479
{
480 481 482
	if (fe_eof)
		return;					/* can't unget an EOF */
	switch (copy_dest)
Bruce Momjian's avatar
Bruce Momjian committed
483
	{
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
		case COPY_FILE:
			if (!pickup) 
			{
				/* We don't want to pick it up - so put it back in there */
				ungetc(c, copy_file);
			}
			/* If we wanted to pick it up, it's already done */
			break;
		case COPY_OLD_FE:
			if (pickup)
			{
				/* We want to pick it up */
				(void) pq_getbyte();
			}
			/* If we didn't want to pick it up, just leave it where it sits */
			break;
		case COPY_NEW_FE:
			if (!pickup)
			{
				/* We don't want to pick it up - so put it back in there */
				copy_msgbuf->cursor--;
			}
			/* If we wanted to pick it up, it's already done */
			break;
Bruce Momjian's avatar
Bruce Momjian committed
508
	}
509
}
Bruce Momjian's avatar
Bruce Momjian committed
510

511 512


513
/*
514
 *	 DoCopy executes the SQL COPY statement.
515
 *
516
 * Either unload or reload contents of table <relation>, depending on <from>.
517 518 519
 * (<from> = TRUE means we are inserting into the table.)
 *
 * If <pipe> is false, transfer is between the table and the file named
520 521
 * <filename>.	Otherwise, transfer is between the table and our regular
 * input/output stream. The latter could be either stdin/stdout or a
522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
 * 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.
 *
 * Iff <oids>, unload or reload the format that includes OID information.
 * On input, we accept OIDs whether or not the table has an OID column,
 * but silently drop them if it does not.  On output, we report an error
 * if the user asks for OIDs in a table that has none (not providing an
 * OID column might seem friendlier, but could seriously confuse programs).
 *
 * If in the text format, delimit columns with delimiter <delim> and print
 * NULL values as <null_print>.
 *
 * When loading in the text format from an input stream (as opposed to
537
 * a file), recognize a "." on a line by itself as EOF. Also recognize
538 539 540 541 542 543 544 545
 * 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.
 *
 * 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 table.
546
 */
547
void
548
DoCopy(const CopyStmt *stmt)
549
{
Bruce Momjian's avatar
Bruce Momjian committed
550 551 552 553 554 555 556 557 558 559 560
	RangeVar   *relation = stmt->relation;
	char	   *filename = stmt->filename;
	bool		is_from = stmt->is_from;
	bool		pipe = (stmt->filename == NULL);
	List	   *option;
	List	   *attnamelist = stmt->attlist;
	List	   *attnumlist;
	bool		binary = false;
	bool		oids = false;
	char	   *delim = NULL;
	char	   *null_print = NULL;
561
	Relation	rel;
562
	AclMode		required_access = (is_from ? ACL_INSERT : ACL_SELECT);
563
	AclResult	aclresult;
564

565 566 567 568 569
	/* Extract options from the statement node tree */
	foreach(option, stmt->options)
	{
		DefElem    *defel = (DefElem *) lfirst(option);

Bruce Momjian's avatar
Bruce Momjian committed
570 571
		/* XXX: Should we bother checking for doubled options? */

572 573
		if (strcmp(defel->defname, "binary") == 0)
		{
Bruce Momjian's avatar
Bruce Momjian committed
574
			if (binary)
575
				elog(ERROR, "COPY: BINARY option appears more than once");
Bruce Momjian's avatar
Bruce Momjian committed
576 577

			binary = intVal(defel->arg);
578 579 580
		}
		else if (strcmp(defel->defname, "oids") == 0)
		{
Bruce Momjian's avatar
Bruce Momjian committed
581
			if (oids)
582
				elog(ERROR, "COPY: OIDS option appears more than once");
Bruce Momjian's avatar
Bruce Momjian committed
583 584

			oids = intVal(defel->arg);
585 586 587
		}
		else if (strcmp(defel->defname, "delimiter") == 0)
		{
Bruce Momjian's avatar
Bruce Momjian committed
588
			if (delim)
589
				elog(ERROR, "COPY: DELIMITER string may only be defined once in query");
Bruce Momjian's avatar
Bruce Momjian committed
590 591

			delim = strVal(defel->arg);
592 593 594
		}
		else if (strcmp(defel->defname, "null") == 0)
		{
Bruce Momjian's avatar
Bruce Momjian committed
595
			if (null_print)
596
				elog(ERROR, "COPY: NULL representation may only be defined once in query");
Bruce Momjian's avatar
Bruce Momjian committed
597 598

			null_print = strVal(defel->arg);
599 600 601 602 603 604
		}
		else
			elog(ERROR, "COPY: option \"%s\" not recognized",
				 defel->defname);
	}

Bruce Momjian's avatar
Bruce Momjian committed
605
	if (binary && delim)
606 607
		elog(ERROR, "You can not specify the DELIMITER in BINARY mode.");

Bruce Momjian's avatar
Bruce Momjian committed
608
	if (binary && null_print)
609
		elog(ERROR, "You can not specify NULL in BINARY mode.");
Bruce Momjian's avatar
Bruce Momjian committed
610 611 612 613 614 615 616

	/* Set defaults */
	if (!delim)
		delim = "\t";

	if (!null_print)
		null_print = "\\N";
Bruce Momjian's avatar
Bruce Momjian committed
617

618 619 620
	/*
	 * Open and lock the relation, using the appropriate lock type.
	 */
621
	rel = heap_openrv(relation, (is_from ? RowExclusiveLock : AccessShareLock));
622

623 624 625 626
	/* check read-only transaction */
	if (XactReadOnly && !is_from && !isTempNamespace(RelationGetNamespace(rel)))
		elog(ERROR, "transaction is read-only");

627 628 629 630
	/* Check permissions. */
	aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
								  required_access);
	if (aclresult != ACLCHECK_OK)
631
		aclcheck_error(aclresult, RelationGetRelationName(rel));
632
	if (!pipe && !superuser())
633
		elog(ERROR, "You must have Postgres superuser privilege to do a COPY "
634 635
			 "directly to or from a file.  Anyone can COPY to stdout or "
			 "from stdin.  Psql's \\copy command also works for anyone.");
636

637 638 639 640 641 642
	/*
	 * Presently, only single-character delimiter strings are supported.
	 */
	if (strlen(delim) != 1)
		elog(ERROR, "COPY delimiter must be a single character");

Bruce Momjian's avatar
Bruce Momjian committed
643 644 645 646 647 648 649
	/*
	 * Don't allow COPY w/ OIDs to or from a table without them
	 */
	if (oids && !rel->rd_rel->relhasoids)
		elog(ERROR, "COPY: table \"%s\" does not have OIDs",
			 RelationGetRelationName(rel));

650 651 652 653 654
	/*
	 * Generate or convert list of attributes to process
	 */
	attnumlist = CopyGetAttnums(rel, attnamelist);

655 656 657 658
	/*
	 * Set up variables to avoid per-attribute overhead.
	 */
	initStringInfo(&attribute_buf);
659

660 661
	client_encoding = pg_get_client_encoding();
	server_encoding = GetDatabaseEncoding();
662

663 664 665 666 667
	copy_dest = COPY_FILE;		/* default */
	copy_file = NULL;
	copy_msgbuf = NULL;
	fe_eof = false;

668
	if (is_from)
669
	{							/* copy from file to database */
670 671 672
		if (rel->rd_rel->relkind != RELKIND_RELATION)
		{
			if (rel->rd_rel->relkind == RELKIND_VIEW)
673 674
				elog(ERROR, "You cannot copy view %s",
					 RelationGetRelationName(rel));
675
			else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
676 677
				elog(ERROR, "You cannot change sequence relation %s",
					 RelationGetRelationName(rel));
678
			else
679 680
				elog(ERROR, "You cannot copy object %s",
					 RelationGetRelationName(rel));
681
		}
682 683 684
		if (pipe)
		{
			if (IsUnderPostmaster)
685
				ReceiveCopyBegin(binary);
686
			else
687
				copy_file = stdin;
688 689 690
		}
		else
		{
691 692
			struct stat st;

693
			copy_file = AllocateFile(filename, PG_BINARY_R);
694

695
			if (copy_file == NULL)
696 697 698
				elog(ERROR, "COPY command, running in backend with "
					 "effective uid %d, could not open file '%s' for "
					 "reading.  Errno = %s (%d).",
699
					 (int) geteuid(), filename, strerror(errno), errno);
700

701
			fstat(fileno(copy_file), &st);
702 703
			if (S_ISDIR(st.st_mode))
			{
704
				FreeFile(copy_file);
705
				elog(ERROR, "COPY: %s is a directory", filename);
706
			}
707
		}
708
		CopyFrom(rel, attnumlist, binary, oids, delim, null_print);
709 710 711
	}
	else
	{							/* copy from database to file */
712 713 714
		if (rel->rd_rel->relkind != RELKIND_RELATION)
		{
			if (rel->rd_rel->relkind == RELKIND_VIEW)
715 716
				elog(ERROR, "You cannot copy view %s",
					 RelationGetRelationName(rel));
717
			else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
718 719
				elog(ERROR, "You cannot copy sequence %s",
					 RelationGetRelationName(rel));
720
			else
721 722
				elog(ERROR, "You cannot copy object %s",
					 RelationGetRelationName(rel));
723
		}
724 725 726
		if (pipe)
		{
			if (IsUnderPostmaster)
727
				SendCopyBegin(binary);
728
			else
729
				copy_file = stdout;
730 731 732
		}
		else
		{
733
			mode_t		oumask; /* Pre-existing umask value */
734
			struct stat st;
735

736
			/*
737 738
			 * Prevent write to relative path ... too easy to shoot
			 * oneself in the foot by overwriting a database file ...
739
			 */
740
			if (!is_absolute_path(filename))
741
				elog(ERROR, "Relative path not allowed for server side"
742
					 " COPY command");
743

744
			oumask = umask((mode_t) 022);
745
			copy_file = AllocateFile(filename, PG_BINARY_W);
746
			umask(oumask);
747

748
			if (copy_file == NULL)
749 750 751
				elog(ERROR, "COPY command, running in backend with "
					 "effective uid %d, could not open file '%s' for "
					 "writing.  Errno = %s (%d).",
752
					 (int) geteuid(), filename, strerror(errno), errno);
753
			fstat(fileno(copy_file), &st);
754 755
			if (S_ISDIR(st.st_mode))
			{
756
				FreeFile(copy_file);
757
				elog(ERROR, "COPY: %s is a directory", filename);
758
			}
759
		}
760
		CopyTo(rel, attnumlist, binary, oids, delim, null_print);
761 762 763
	}

	if (!pipe)
764 765
		FreeFile(copy_file);
	else if (IsUnderPostmaster && !is_from)
766
		SendCopyEnd(binary);
767
	pfree(attribute_buf.data);
768

769
	/*
770 771 772 773
	 * Close the relation.	If reading, we can release the AccessShareLock
	 * we got; if writing, we should hold the lock until end of
	 * transaction to ensure that updates will be committed before lock is
	 * released.
774
	 */
775
	heap_close(rel, (is_from ? NoLock : AccessShareLock));
776 777
}

778

779 780 781
/*
 * Copy from relation TO file.
 */
782
static void
783
CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
784
	   char *delim, char *null_print)
785
{
786
	HeapTuple	tuple;
787
	TupleDesc	tupDesc;
788
	HeapScanDesc scandesc;
789 790
	int			num_phys_attrs;
	int			attr_count;
791
	Form_pg_attribute *attr;
792
	FmgrInfo   *out_functions;
793
	Oid		   *elements;
794
	bool	   *isvarlena;
795
	int16		fld_size;
796
	char	   *string;
797
	Snapshot	mySnapshot;
Bruce Momjian's avatar
Bruce Momjian committed
798
	List	   *cur;
799 800
	MemoryContext oldcontext;
	MemoryContext mycontext;
801

802
	tupDesc = rel->rd_att;
803 804 805
	attr = tupDesc->attrs;
	num_phys_attrs = tupDesc->natts;
	attr_count = length(attnumlist);
806

807
	/*
808 809
	 * Get info about the columns we need to process.
	 *
Bruce Momjian's avatar
Bruce Momjian committed
810
	 * For binary copy we really only need isvarlena, but compute it all...
811
	 */
812 813 814 815
	out_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
	elements = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
	isvarlena = (bool *) palloc(num_phys_attrs * sizeof(bool));
	foreach(cur, attnumlist)
816
	{
Bruce Momjian's avatar
Bruce Momjian committed
817
		int			attnum = lfirsti(cur);
818 819
		Oid			out_func_oid;

Bruce Momjian's avatar
Bruce Momjian committed
820 821 822
		if (!getTypeOutputInfo(attr[attnum - 1]->atttypid,
							   &out_func_oid, &elements[attnum - 1],
							   &isvarlena[attnum - 1]))
823
			elog(ERROR, "COPY: couldn't lookup info for type %u",
Bruce Momjian's avatar
Bruce Momjian committed
824 825 826
				 attr[attnum - 1]->atttypid);
		fmgr_info(out_func_oid, &out_functions[attnum - 1]);
		if (binary && attr[attnum - 1]->attlen == -2)
827
			elog(ERROR, "COPY BINARY: cstring not supported");
828
	}
829

830 831 832 833 834 835 836 837 838 839 840 841
	/*
	 * Create a temporary memory context that we can reset once per row
	 * to recover palloc'd memory.  This avoids any problems with leaks
	 * inside datatype output routines, and should be faster than retail
	 * pfree's anyway.  (We don't need a whole econtext as CopyFrom does.)
	 */
	mycontext = AllocSetContextCreate(CurrentMemoryContext,
									  "COPY TO",
									  ALLOCSET_DEFAULT_MINSIZE,
									  ALLOCSET_DEFAULT_INITSIZE,
									  ALLOCSET_DEFAULT_MAXSIZE);

842
	if (binary)
843
	{
844 845 846 847
		/* Generate header for a binary copy */
		int32		tmp;

		/* Signature */
848
		CopySendData((char *) BinarySignature, 12);
849 850
		/* Integer layout field */
		tmp = 0x01020304;
851
		CopySendData(&tmp, sizeof(int32));
852 853 854 855
		/* Flags field */
		tmp = 0;
		if (oids)
			tmp |= (1 << 16);
856
		CopySendData(&tmp, sizeof(int32));
857 858
		/* No header extension */
		tmp = 0;
859
		CopySendData(&tmp, sizeof(int32));
860
	}
861

862 863 864
	mySnapshot = CopyQuerySnapshot();

	scandesc = heap_beginscan(rel, mySnapshot, 0, NULL);
865

866
	while ((tuple = heap_getnext(scandesc, ForwardScanDirection)) != NULL)
867
	{
868 869
		bool		need_delim = false;

870
		CHECK_FOR_INTERRUPTS();
871

872 873 874
		MemoryContextReset(mycontext);
		oldcontext = MemoryContextSwitchTo(mycontext);

875 876 877
		if (binary)
		{
			/* Binary per-tuple header */
878
			int16		fld_count = attr_count;
879

880
			CopySendData(&fld_count, sizeof(int16));
881 882 883
			/* Send OID if wanted --- note fld_count doesn't include it */
			if (oids)
			{
Bruce Momjian's avatar
Bruce Momjian committed
884
				Oid			oid = HeapTupleGetOid(tuple);
885

886
				fld_size = sizeof(Oid);
887 888
				CopySendData(&fld_size, sizeof(int16));
				CopySendData(&oid, sizeof(Oid));
889 890 891
			}
		}
		else
892
		{
893 894 895 896
			/* Text format has no per-tuple header, but send OID if wanted */
			if (oids)
			{
				string = DatumGetCString(DirectFunctionCall1(oidout,
Bruce Momjian's avatar
Bruce Momjian committed
897
							  ObjectIdGetDatum(HeapTupleGetOid(tuple))));
898
				CopySendString(string);
899 900
				need_delim = true;
			}
901 902
		}

903
		foreach(cur, attnumlist)
904
		{
Bruce Momjian's avatar
Bruce Momjian committed
905
			int			attnum = lfirsti(cur);
906
			Datum		value;
907 908
			bool		isnull;

909
			value = heap_getattr(tuple, attnum, tupDesc, &isnull);
910

911 912 913
			if (!binary)
			{
				if (need_delim)
914
					CopySendChar(delim[0]);
915 916 917
				need_delim = true;
			}

918
			if (isnull)
919
			{
920
				if (!binary)
921
				{
922
					CopySendString(null_print);		/* null indicator */
923
				}
924
				else
925
				{
926
					fld_size = 0;		/* null marker */
927
					CopySendData(&fld_size, sizeof(int16));
928
				}
929 930 931 932
			}
			else
			{
				if (!binary)
933
				{
Bruce Momjian's avatar
Bruce Momjian committed
934
					string = DatumGetCString(FunctionCall3(&out_functions[attnum - 1],
935
														   value,
Bruce Momjian's avatar
Bruce Momjian committed
936 937
								  ObjectIdGetDatum(elements[attnum - 1]),
							Int32GetDatum(attr[attnum - 1]->atttypmod)));
938
					CopyAttributeOut(string, delim);
939
				}
940 941
				else
				{
Bruce Momjian's avatar
Bruce Momjian committed
942
					fld_size = attr[attnum - 1]->attlen;
943
					CopySendData(&fld_size, sizeof(int16));
Bruce Momjian's avatar
Bruce Momjian committed
944
					if (isvarlena[attnum - 1])
945 946 947
					{
						/* varlena */
						Assert(fld_size == -1);
948 949 950 951

						/* If we have a toasted datum, detoast it */
						value = PointerGetDatum(PG_DETOAST_DATUM(value));

952
						CopySendData(DatumGetPointer(value),
953
									 VARSIZE(value));
954
					}
Bruce Momjian's avatar
Bruce Momjian committed
955
					else if (!attr[attnum - 1]->attbyval)
956 957 958 959
					{
						/* fixed-length pass-by-reference */
						Assert(fld_size > 0);
						CopySendData(DatumGetPointer(value),
960
									 fld_size);
961 962 963 964 965 966 967
					}
					else
					{
						/* pass-by-value */
						Datum		datumBuf;

						/*
968 969 970
						 * We need this horsing around because we don't
						 * know how shorter data values are aligned within
						 * a Datum.
971 972 973
						 */
						store_att_byval(&datumBuf, value, fld_size);
						CopySendData(&datumBuf,
974
									 fld_size);
975 976
					}
				}
977
			}
978 979
		}

980
		CopySendEndOfRow(binary);
981 982

		MemoryContextSwitchTo(oldcontext);
983
	}
984

985
	heap_endscan(scandesc);
986

987 988 989
	if (binary)
	{
		/* Generate trailer for a binary copy */
990
		int16		fld_count = -1;
991

992
		CopySendData(&fld_count, sizeof(int16));
993 994
	}

995 996
	MemoryContextDelete(mycontext);

997 998 999
	pfree(out_functions);
	pfree(elements);
	pfree(isvarlena);
1000 1001
}

1002 1003 1004 1005

/*
 * Copy FROM file to relation.
 */
1006
static void
Bruce Momjian's avatar
Bruce Momjian committed
1007
CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
1008
		 char *delim, char *null_print)
1009
{
1010
	HeapTuple	tuple;
1011
	TupleDesc	tupDesc;
1012
	Form_pg_attribute *attr;
Bruce Momjian's avatar
Bruce Momjian committed
1013 1014 1015
	AttrNumber	num_phys_attrs,
				attr_count,
				num_defaults;
1016
	FmgrInfo   *in_functions;
1017
	Oid		   *elements;
1018
	ExprState **constraintexprs;
1019
	bool		hasConstraints = false;
1020
	int			i;
1021
	List	   *cur;
1022 1023
	Oid			in_func_oid;
	Datum	   *values;
1024
	char	   *nulls;
1025
	bool		done = false;
1026
	ResultRelInfo *resultRelInfo;
1027
	EState	   *estate = CreateExecutorState(); /* for ExecConstraints() */
1028
	TupleTable	tupleTable;
1029
	TupleTableSlot *slot;
1030
	bool		file_has_oids;
1031
	int		   *defmap;
1032
	ExprState **defexprs;		/* array of default att expressions */
Bruce Momjian's avatar
Bruce Momjian committed
1033
	ExprContext *econtext;		/* used for ExecEvalExpr for default atts */
1034
	MemoryContext oldcontext = CurrentMemoryContext;
1035

1036
	tupDesc = RelationGetDescr(rel);
1037
	attr = tupDesc->attrs;
1038 1039 1040
	num_phys_attrs = tupDesc->natts;
	attr_count = length(attnumlist);
	num_defaults = 0;
1041 1042

	/*
1043
	 * We need a ResultRelInfo so we can use the regular executor's
1044 1045
	 * index-entry-making machinery.  (There used to be a huge amount of
	 * code here that basically duplicated execUtils.c ...)
1046
	 */
1047
	resultRelInfo = makeNode(ResultRelInfo);
1048
	resultRelInfo->ri_RangeTableIndex = 1;		/* dummy */
1049
	resultRelInfo->ri_RelationDesc = rel;
1050
	resultRelInfo->ri_TrigDesc = CopyTriggerDesc(rel->trigdesc);
1051

1052
	ExecOpenIndices(resultRelInfo);
1053

1054 1055 1056
	estate->es_result_relations = resultRelInfo;
	estate->es_num_result_relations = 1;
	estate->es_result_relation_info = resultRelInfo;
1057 1058 1059 1060

	/* Set up a dummy tuple table too */
	tupleTable = ExecCreateTupleTable(1);
	slot = ExecAllocTableSlot(tupleTable);
1061
	ExecSetSlotDescriptor(slot, tupDesc, false);
1062

1063 1064
	econtext = GetPerTupleExprContext(estate);

1065
	/*
1066 1067 1068 1069
	 * Pick up the required catalog information for each attribute in the
	 * relation, including the input function, the element type (to pass
	 * to the input function), and info about defaults and constraints.
	 * (We don't actually use the input function if it's a binary copy.)
1070 1071 1072
	 */
	in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
	elements = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
1073
	defmap = (int *) palloc(num_phys_attrs * sizeof(int));
1074 1075
	defexprs = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *));
	constraintexprs = (ExprState **) palloc0(num_phys_attrs * sizeof(ExprState *));
1076 1077

	for (i = 0; i < num_phys_attrs; i++)
1078
	{
1079 1080 1081
		/* We don't need info for dropped attributes */
		if (attr[i]->attisdropped)
			continue;
Bruce Momjian's avatar
Bruce Momjian committed
1082

1083
		/* Fetch the input function */
1084 1085 1086
		in_func_oid = (Oid) GetInputFunction(attr[i]->atttypid);
		fmgr_info(in_func_oid, &in_functions[i]);
		elements[i] = GetTypeElement(attr[i]->atttypid);
Bruce Momjian's avatar
Bruce Momjian committed
1087

1088
		/* Get default info if needed */
1089
		if (intMember(i + 1, attnumlist))
1090
		{
1091 1092 1093 1094 1095 1096 1097 1098
			/* attribute is to be copied */
			if (binary && attr[i]->attlen == -2)
				elog(ERROR, "COPY BINARY: cstring not supported");
		}
		else
		{
			/* attribute is NOT to be copied */
			/* use default value if one exists */
1099 1100 1101
			Node   *defexpr = build_column_default(rel, i + 1);

			if (defexpr != NULL)
Bruce Momjian's avatar
Bruce Momjian committed
1102
			{
1103 1104
				defexprs[num_defaults] = ExecPrepareExpr((Expr *) defexpr,
														 estate);
1105 1106
				defmap[num_defaults] = i;
				num_defaults++;
1107
			}
1108
		}
1109

1110
		/* If it's a domain type, set up to check domain constraints */
1111 1112
		if (get_typtype(attr[i]->atttypid) == 'd')
		{
1113
			Param	   *prm;
1114 1115 1116 1117 1118 1119
			Node	   *node;

			/*
			 * Easiest way to do this is to use parse_coerce.c to set up
			 * an expression that checks the constraints.  (At present,
			 * the expression might contain a length-coercion-function call
1120
			 * and/or CoerceToDomain nodes.)  The bottom of the expression
1121
			 * is a Param node so that we can fill in the actual datum during
1122 1123
			 * the data input loop.
			 */
1124 1125 1126
			prm = makeNode(Param);
			prm->paramkind = PARAM_EXEC;
			prm->paramid = 0;
1127
			prm->paramtype = getBaseType(attr[i]->atttypid);
1128

1129 1130 1131 1132
			node = coerce_to_domain((Node *) prm,
									prm->paramtype,
									attr[i]->atttypid,
									COERCE_IMPLICIT_CAST);
1133

1134 1135 1136
			constraintexprs[i] = ExecPrepareExpr((Expr *) node,
												 estate);
			hasConstraints = true;
1137
		}
1138 1139
	}

1140 1141 1142 1143 1144 1145 1146 1147 1148
	/*
	 * Check BEFORE STATEMENT insertion triggers. It's debateable
	 * whether we should do this for COPY, since it's not really an
	 * "INSERT" statement as such. However, executing these triggers
	 * maintains consistency with the EACH ROW triggers that we already
	 * fire on COPY.
	 */
	ExecBSInsertTriggers(estate, resultRelInfo);

1149 1150
	if (!binary)
	{
1151
		file_has_oids = oids;	/* must rely on user to tell us this... */
1152 1153 1154
	}
	else
	{
1155 1156 1157 1158 1159
		/* Read and verify binary header */
		char		readSig[12];
		int32		tmp;

		/* Signature */
1160
		CopyGetData(readSig, 12);
1161
		if (CopyGetEof() || memcmp(readSig, BinarySignature, 12) != 0)
1162 1163
			elog(ERROR, "COPY BINARY: file signature not recognized");
		/* Integer layout field */
1164 1165
		CopyGetData(&tmp, sizeof(int32));
		if (CopyGetEof() || tmp != 0x01020304)
1166 1167
			elog(ERROR, "COPY BINARY: incompatible integer layout");
		/* Flags field */
1168 1169
		CopyGetData(&tmp, sizeof(int32));
		if (CopyGetEof())
1170 1171
			elog(ERROR, "COPY BINARY: bogus file header (missing flags)");
		file_has_oids = (tmp & (1 << 16)) != 0;
1172
		tmp &= ~(1 << 16);
1173 1174 1175
		if ((tmp >> 16) != 0)
			elog(ERROR, "COPY BINARY: unrecognized critical flags in header");
		/* Header extension length */
1176 1177
		CopyGetData(&tmp, sizeof(int32));
		if (CopyGetEof() || tmp < 0)
1178 1179 1180 1181
			elog(ERROR, "COPY BINARY: bogus file header (missing length)");
		/* Skip extension header, if present */
		while (tmp-- > 0)
		{
1182 1183
			CopyGetData(readSig, 1);
			if (CopyGetEof())
1184 1185
				elog(ERROR, "COPY BINARY: bogus file header (wrong length)");
		}
1186 1187
	}

1188 1189
	values = (Datum *) palloc(num_phys_attrs * sizeof(Datum));
	nulls = (char *) palloc(num_phys_attrs * sizeof(char));
1190

1191
	/* Initialize static variables */
1192
	copy_lineno = 0;
1193
	eol_type = EOL_UNKNOWN;
1194 1195
	fe_eof = false;

1196 1197 1198 1199 1200
	/* Make room for a PARAM_EXEC value for domain constraint checks */
	if (hasConstraints)
		econtext->ecxt_param_exec_vals = (ParamExecData *)
			palloc0(sizeof(ParamExecData));

1201 1202
	while (!done)
	{
Bruce Momjian's avatar
Bruce Momjian committed
1203 1204
		bool		skip_tuple;
		Oid			loaded_oid = InvalidOid;
Bruce Momjian's avatar
Bruce Momjian committed
1205

1206
		CHECK_FOR_INTERRUPTS();
1207

1208
		copy_lineno++;
Bruce Momjian's avatar
Bruce Momjian committed
1209

1210
		/* Reset the per-tuple exprcontext */
1211 1212
		ResetPerTupleExprContext(estate);

1213
		/* Switch into its memory context */
1214 1215
		MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));

1216
		/* Initialize all values for row to NULL */
1217 1218
		MemSet(values, 0, num_phys_attrs * sizeof(Datum));
		MemSet(nulls, 'n', num_phys_attrs * sizeof(char));
1219

1220 1221
		if (!binary)
		{
Bruce Momjian's avatar
Bruce Momjian committed
1222 1223
			CopyReadResult result = NORMAL_ATTR;
			char	   *string;
1224

1225
			if (file_has_oids)
1226
			{
1227
				string = CopyReadAttribute(delim, &result);
Bruce Momjian's avatar
Bruce Momjian committed
1228

1229 1230 1231 1232 1233 1234 1235 1236 1237
				if (result == END_OF_FILE && *string == '\0')
				{
					/* EOF at start of line: all is well */
					done = true;
					break;
				}

				if (strcmp(string, null_print) == 0)
					elog(ERROR, "NULL Oid");
1238 1239
				else
				{
1240
					loaded_oid = DatumGetObjectId(DirectFunctionCall1(oidin,
1241
											   CStringGetDatum(string)));
1242
					if (loaded_oid == InvalidOid)
1243
						elog(ERROR, "Invalid Oid");
1244 1245
				}
			}
Bruce Momjian's avatar
Bruce Momjian committed
1246

1247 1248
			/*
			 * Loop to read the user attributes on the line.
1249
			 */
1250
			foreach(cur, attnumlist)
1251
			{
Bruce Momjian's avatar
Bruce Momjian committed
1252 1253
				int			attnum = lfirsti(cur);
				int			m = attnum - 1;
1254 1255 1256 1257 1258 1259 1260 1261

				/*
				 * If prior attr on this line was ended by newline or EOF,
				 * complain.
				 */
				if (result != NORMAL_ATTR)
					elog(ERROR, "Missing data for column \"%s\"",
						 NameStr(attr[m]->attname));
1262

1263
				string = CopyReadAttribute(delim, &result);
Bruce Momjian's avatar
Bruce Momjian committed
1264

1265 1266 1267 1268 1269 1270 1271
				if (result == END_OF_FILE && *string == '\0' &&
					cur == attnumlist && !file_has_oids)
				{
					/* EOF at start of line: all is well */
					done = true;
					break;		/* out of per-attr loop */
				}
Bruce Momjian's avatar
Bruce Momjian committed
1272

1273
				if (strcmp(string, null_print) == 0)
Bruce Momjian's avatar
Bruce Momjian committed
1274 1275
				{
					/* we read an SQL NULL, no need to do anything */
1276 1277 1278
				}
				else
				{
1279
					values[m] = FunctionCall3(&in_functions[m],
Bruce Momjian's avatar
Bruce Momjian committed
1280
											  CStringGetDatum(string),
Bruce Momjian's avatar
Bruce Momjian committed
1281 1282
										   ObjectIdGetDatum(elements[m]),
									  Int32GetDatum(attr[m]->atttypmod));
1283
					nulls[m] = ' ';
1284 1285
				}
			}
Bruce Momjian's avatar
Bruce Momjian committed
1286

1287 1288 1289 1290 1291 1292
			if (done)
				break;			/* out of per-row loop */

			/* Complain if there are more fields on the input line */
			if (result == NORMAL_ATTR)
				elog(ERROR, "Extra data after last expected column");
Bruce Momjian's avatar
Bruce Momjian committed
1293

1294
			/*
1295 1296 1297
			 * If we got some data on the line, but it was ended by EOF,
			 * process the line normally but set flag to exit the loop
			 * when we return to the top.
1298
			 */
1299 1300
			if (result == END_OF_FILE)
				done = true;
1301 1302
		}
		else
1303 1304
		{
			/* binary */
1305 1306
			int16		fld_count,
						fld_size;
1307

1308 1309
			CopyGetData(&fld_count, sizeof(int16));
			if (CopyGetEof() || fld_count == -1)
1310
			{
1311 1312 1313 1314 1315 1316 1317 1318 1319 1320
				done = true;
				break;
			}

			if (fld_count != attr_count)
				elog(ERROR, "COPY BINARY: tuple field count is %d, expected %d",
					 (int) fld_count, attr_count);

			if (file_has_oids)
			{
1321 1322
				CopyGetData(&fld_size, sizeof(int16));
				if (CopyGetEof())
1323 1324 1325 1326
					elog(ERROR, "COPY BINARY: unexpected EOF");
				if (fld_size != (int16) sizeof(Oid))
					elog(ERROR, "COPY BINARY: sizeof(Oid) is %d, expected %d",
						 (int) fld_size, (int) sizeof(Oid));
1327 1328
				CopyGetData(&loaded_oid, sizeof(Oid));
				if (CopyGetEof())
1329 1330 1331 1332
					elog(ERROR, "COPY BINARY: unexpected EOF");
				if (loaded_oid == InvalidOid)
					elog(ERROR, "COPY BINARY: Invalid Oid");
			}
1333

1334 1335 1336
			i = 0;
			foreach(cur, attnumlist)
			{
Bruce Momjian's avatar
Bruce Momjian committed
1337
				int			attnum = lfirsti(cur);
1338
				int			m = attnum - 1;
1339 1340 1341

				i++;

1342 1343
				CopyGetData(&fld_size, sizeof(int16));
				if (CopyGetEof())
1344 1345 1346
					elog(ERROR, "COPY BINARY: unexpected EOF");
				if (fld_size == 0)
					continue;	/* it's NULL; nulls[attnum-1] already set */
1347
				if (fld_size != attr[m]->attlen)
1348
					elog(ERROR, "COPY BINARY: sizeof(field %d) is %d, expected %d",
1349
					  i, (int) fld_size, (int) attr[m]->attlen);
1350
				if (fld_size == -1)
1351
				{
1352 1353 1354 1355
					/* varlena field */
					int32		varlena_size;
					Pointer		varlena_ptr;

1356 1357
					CopyGetData(&varlena_size, sizeof(int32));
					if (CopyGetEof())
1358
						elog(ERROR, "COPY BINARY: unexpected EOF");
1359 1360 1361 1362 1363
					if (varlena_size < (int32) sizeof(int32))
						elog(ERROR, "COPY BINARY: bogus varlena length");
					varlena_ptr = (Pointer) palloc(varlena_size);
					VARATT_SIZEP(varlena_ptr) = varlena_size;
					CopyGetData(VARDATA(varlena_ptr),
1364 1365
								varlena_size - sizeof(int32));
					if (CopyGetEof())
1366
						elog(ERROR, "COPY BINARY: unexpected EOF");
1367
					values[m] = PointerGetDatum(varlena_ptr);
1368
				}
1369
				else if (!attr[m]->attbyval)
1370
				{
1371 1372 1373 1374 1375
					/* fixed-length pass-by-reference */
					Pointer		refval_ptr;

					Assert(fld_size > 0);
					refval_ptr = (Pointer) palloc(fld_size);
1376 1377
					CopyGetData(refval_ptr, fld_size);
					if (CopyGetEof())
1378
						elog(ERROR, "COPY BINARY: unexpected EOF");
1379
					values[m] = PointerGetDatum(refval_ptr);
1380 1381 1382 1383 1384
				}
				else
				{
					/* pass-by-value */
					Datum		datumBuf;
1385

1386
					/*
Bruce Momjian's avatar
Bruce Momjian committed
1387 1388
					 * We need this horsing around because we don't know
					 * how shorter data values are aligned within a Datum.
1389 1390
					 */
					Assert(fld_size > 0 && fld_size <= sizeof(Datum));
1391 1392
					CopyGetData(&datumBuf, fld_size);
					if (CopyGetEof())
1393
						elog(ERROR, "COPY BINARY: unexpected EOF");
1394
					values[m] = fetch_att(&datumBuf, true, fld_size);
1395
				}
1396

1397 1398 1399 1400
				nulls[m] = ' ';
			}
		}

1401
		/*
Bruce Momjian's avatar
Bruce Momjian committed
1402 1403 1404
		 * Now compute and insert any defaults available for the columns
		 * not provided by the input data.	Anything not processed here or
		 * above will remain NULL.
1405 1406 1407
		 */
		for (i = 0; i < num_defaults; i++)
		{
Bruce Momjian's avatar
Bruce Momjian committed
1408
			bool		isnull;
1409

1410 1411 1412 1413 1414 1415
			values[defmap[i]] = ExecEvalExpr(defexprs[i], econtext,
											 &isnull, NULL);
			if (!isnull)
				nulls[defmap[i]] = ' ';
		}

1416 1417 1418 1419 1420
		/*
		 * Next apply any domain constraints
		 */
		if (hasConstraints)
		{
1421 1422
			ParamExecData *prmdata = &econtext->ecxt_param_exec_vals[0];

1423 1424
			for (i = 0; i < num_phys_attrs; i++)
			{
1425
				ExprState  *exprstate = constraintexprs[i];
1426 1427
				bool		isnull;

1428
				if (exprstate == NULL)
1429 1430
					continue;	/* no constraint for this attr */

1431 1432 1433
				/* Insert current row's value into the Param value */
				prmdata->value = values[i];
				prmdata->isnull = (nulls[i] == 'n');
1434 1435 1436 1437 1438 1439

				/*
				 * Execute the constraint expression.  Allow the expression
				 * to replace the value (consider e.g. a timestamp precision
				 * restriction).
				 */
1440
				values[i] = ExecEvalExpr(exprstate, econtext,
1441 1442 1443 1444 1445
										 &isnull, NULL);
				nulls[i] = isnull ? 'n' : ' ';
			}
		}

1446 1447 1448
		/*
		 * And now we can form the input tuple.
		 */
1449
		tuple = heap_formtuple(tupDesc, values, nulls);
Bruce Momjian's avatar
Bruce Momjian committed
1450

1451
		if (oids && file_has_oids)
1452
			HeapTupleSetOid(tuple, loaded_oid);
1453

1454 1455 1456 1457 1458
		/*
		 * Triggers and stuff need to be invoked in query context.
		 */
		MemoryContextSwitchTo(oldcontext);

1459
		skip_tuple = false;
1460

1461
		/* BEFORE ROW INSERT Triggers */
1462 1463
		if (resultRelInfo->ri_TrigDesc &&
			resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)
1464
		{
1465
			HeapTuple	newtuple;
1466

1467
			newtuple = ExecBRInsertTriggers(estate, resultRelInfo, tuple);
1468 1469 1470 1471 1472

			if (newtuple == NULL)		/* "do nothing" */
				skip_tuple = true;
			else if (newtuple != tuple) /* modified by Trigger(s) */
			{
1473
				heap_freetuple(tuple);
1474 1475 1476 1477 1478 1479
				tuple = newtuple;
			}
		}

		if (!skip_tuple)
		{
1480
			/* Place tuple in tuple slot */
1481 1482
			ExecStoreTuple(tuple, slot, InvalidBuffer, false);

1483
			/*
1484
			 * Check the constraints of the tuple
1485 1486
			 */
			if (rel->rd_att->constr)
1487
				ExecConstraints("CopyFrom", resultRelInfo, slot, estate);
1488

1489
			/*
1490 1491
			 * OK, store the tuple and create index entries for it
			 */
1492
			simple_heap_insert(rel, tuple);
1493

1494
			if (resultRelInfo->ri_NumIndices > 0)
1495 1496
				ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);

1497
			/* AFTER ROW INSERT Triggers */
1498
			ExecARInsertTriggers(estate, resultRelInfo, tuple);
1499 1500
		}
	}
1501 1502 1503 1504

	/*
	 * Done, clean up
	 */
1505
	copy_lineno = 0;
1506

1507 1508
	MemoryContextSwitchTo(oldcontext);

1509 1510 1511 1512 1513
	/*
	 * Execute AFTER STATEMENT insertion triggers
	 */
	ExecASInsertTriggers(estate, resultRelInfo);

1514
	pfree(values);
Bruce Momjian's avatar
Bruce Momjian committed
1515
	pfree(nulls);
Bruce Momjian's avatar
Bruce Momjian committed
1516

1517
	if (!binary)
Bruce Momjian's avatar
Bruce Momjian committed
1518
	{
1519
		pfree(in_functions);
Bruce Momjian's avatar
Bruce Momjian committed
1520 1521
		pfree(elements);
	}
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
1522

1523
	ExecDropTupleTable(tupleTable, true);
1524

1525
	ExecCloseIndices(resultRelInfo);
1526 1527

	FreeExecutorState(estate);
1528
}
1529 1530


1531
static Oid
1532
GetInputFunction(Oid type)
1533
{
1534
	HeapTuple	typeTuple;
1535 1536 1537 1538 1539 1540 1541 1542 1543 1544
	Oid			result;

	typeTuple = SearchSysCache(TYPEOID,
							   ObjectIdGetDatum(type),
							   0, 0, 0);
	if (!HeapTupleIsValid(typeTuple))
		elog(ERROR, "GetInputFunction: Cache lookup of type %u failed", type);
	result = ((Form_pg_type) GETSTRUCT(typeTuple))->typinput;
	ReleaseSysCache(typeTuple);
	return result;
1545 1546
}

1547
static Oid
1548
GetTypeElement(Oid type)
1549
{
1550
	HeapTuple	typeTuple;
1551 1552 1553 1554 1555 1556 1557 1558 1559 1560
	Oid			result;

	typeTuple = SearchSysCache(TYPEOID,
							   ObjectIdGetDatum(type),
							   0, 0, 0);
	if (!HeapTupleIsValid(typeTuple))
		elog(ERROR, "GetTypeElement: Cache lookup of type %u failed", type);
	result = ((Form_pg_type) GETSTRUCT(typeTuple))->typelem;
	ReleaseSysCache(typeTuple);
	return result;
1561 1562 1563
}

/*
1564 1565
 * Read the value of a single attribute.
 *
1566 1567 1568
 * *result is set to indicate what terminated the read:
 *		NORMAL_ATTR:	column delimiter
 *		END_OF_LINE:	newline
1569
 *		END_OF_FILE:	EOF indicator
1570
 * In all cases, the string read up to the terminator is returned.
Bruce Momjian's avatar
Bruce Momjian committed
1571 1572 1573 1574
 *
 * Note: This function does not care about SQL NULL values -- it
 * is the caller's responsibility to check if the returned string
 * matches what the user specified for the SQL NULL value.
1575
 *
Bruce Momjian's avatar
Bruce Momjian committed
1576
 * delim is the column delimiter string.
1577 1578
 */

1579
static char *
1580
CopyReadAttribute(const char *delim, CopyReadResult *result)
1581
{
1582
	int			c;
1583
	int			delimc = (unsigned char) delim[0];
1584 1585
	int			mblen;
	unsigned char s[2];
1586
	char	   *cvt;
1587 1588
	int			j;

1589
	s[1] = 0;
1590

1591 1592 1593 1594
	/* reset attribute_buf to empty */
	attribute_buf.len = 0;
	attribute_buf.data[0] = '\0';

1595
	/* set default status */
Bruce Momjian's avatar
Bruce Momjian committed
1596
	*result = NORMAL_ATTR;
1597 1598

	for (;;)
1599
	{
1600
		c = CopyGetChar();
1601
		if (c == EOF)
Bruce Momjian's avatar
Bruce Momjian committed
1602 1603
		{
			*result = END_OF_FILE;
1604
			goto copy_eof;
Bruce Momjian's avatar
Bruce Momjian committed
1605
		}
1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634
		if (c == '\r')
		{
			if (eol_type == EOL_NL)
				elog(ERROR, "CopyReadAttribute: Literal carriage return data value\n"
							"found in input that has newline termination; use \\r");

			/*	Check for \r\n on first line, _and_ handle \r\n. */
			if (copy_lineno == 1 || eol_type == EOL_CRNL)
			{
				int c2 = CopyPeekChar();
				if (c2 == '\n')
				{
					CopyDonePeek(c2, true);		/* eat newline */
					eol_type = EOL_CRNL;
				}
				else
				{
					/* found \r, but no \n */
					if (eol_type == EOL_CRNL)
						elog(ERROR, "CopyReadAttribute: Literal carriage return data value\n"
									"found in input that has carriage return/newline termination; use \\r");
					/* if we got here, it is the first line and we didn't get \n, so put it back */
					CopyDonePeek(c2, false);
					eol_type = EOL_CR;
				}
			}
			*result = END_OF_LINE;
			break;
		}
1635 1636
		if (c == '\n')
		{
1637 1638 1639 1640 1641 1642 1643
			if (eol_type == EOL_CRNL)
				elog(ERROR, "CopyReadAttribute: Literal newline data value found in input\n"
							"that has carriage return/newline termination; use \\n");
			if (eol_type == EOL_CR)
				elog(ERROR, "CopyReadAttribute: Literal newline data value found in input\n"
							"that has carriage return termination; use \\n");
			eol_type = EOL_NL;
Bruce Momjian's avatar
Bruce Momjian committed
1644
			*result = END_OF_LINE;
1645 1646
			break;
		}
1647
		if (c == delimc)
1648
			break;
1649
		if (c == '\\')
1650
		{
1651
			c = CopyGetChar();
1652
			if (c == EOF)
Bruce Momjian's avatar
Bruce Momjian committed
1653 1654
			{
				*result = END_OF_FILE;
1655
				goto copy_eof;
Bruce Momjian's avatar
Bruce Momjian committed
1656
			}
1657 1658
			switch (c)
			{
1659 1660 1661 1662 1663 1664 1665 1666
				case '0':
				case '1':
				case '2':
				case '3':
				case '4':
				case '5':
				case '6':
				case '7':
1667
					{
1668 1669
						int			val;

1670
						val = OCTVALUE(c);
1671
						c = CopyPeekChar();
1672 1673
						if (ISOCTAL(c))
						{
1674
							val = (val << 3) + OCTVALUE(c);
1675 1676
							CopyDonePeek(c, true /* pick up */ );
							c = CopyPeekChar();
Bruce Momjian's avatar
Bruce Momjian committed
1677 1678
							if (ISOCTAL(c))
							{
1679
								val = (val << 3) + OCTVALUE(c);
1680
								CopyDonePeek(c, true /* pick up */ );
1681
							}
1682 1683
							else
							{
1684
								if (c == EOF)
Bruce Momjian's avatar
Bruce Momjian committed
1685 1686
								{
									*result = END_OF_FILE;
1687
									goto copy_eof;
Bruce Momjian's avatar
Bruce Momjian committed
1688
								}
1689
								CopyDonePeek(c, false /* put back */ );
1690
							}
1691 1692 1693
						}
						else
						{
1694
							if (c == EOF)
Bruce Momjian's avatar
Bruce Momjian committed
1695 1696
							{
								*result = END_OF_FILE;
1697
								goto copy_eof;
Bruce Momjian's avatar
Bruce Momjian committed
1698
							}
1699
							CopyDonePeek(c, false /* put back */ );
1700
						}
1701
						c = val & 0377;
1702
					}
1703
					break;
1704 1705 1706 1707 1708 1709 1710 1711 1712 1713

					/*
					 * This is a special hack to parse `\N' as
					 * <backslash-N> rather then just 'N' to provide
					 * compatibility with the default NULL output. -- pe
					 */
				case 'N':
					appendStringInfoCharMacro(&attribute_buf, '\\');
					c = 'N';
					break;
1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732
				case 'b':
					c = '\b';
					break;
				case 'f':
					c = '\f';
					break;
				case 'n':
					c = '\n';
					break;
				case 'r':
					c = '\r';
					break;
				case 't':
					c = '\t';
					break;
				case 'v':
					c = '\v';
					break;
				case '.':
1733 1734 1735 1736 1737 1738 1739 1740
					if (eol_type == EOL_CRNL)
					{
						c = CopyGetChar();
						if (c == '\n')
							elog(ERROR, "CopyReadAttribute: end-of-copy termination does not match previous input");
						if (c != '\r')
							elog(ERROR, "CopyReadAttribute: end-of-copy marker corrupt");
					}
1741
					c = CopyGetChar();
1742 1743 1744 1745 1746
					if (c != '\r' && c != '\n')
						elog(ERROR, "CopyReadAttribute: end-of-copy marker corrupt");
					if (((eol_type == EOL_NL || eol_type == EOL_CRNL) && c != '\n') ||
					    (eol_type == EOL_CR && c != '\r'))
						elog(ERROR, "CopyReadAttribute: end-of-copy termination does not match previous input");
1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758
					/*
					 * In protocol version 3, we should ignore anything after
					 * \. up to the protocol end of copy data.  (XXX maybe
					 * better not to treat \. as special?)
					 */
					if (copy_dest == COPY_NEW_FE)
					{
						while (c != EOF)
						{
							c = CopyGetChar();
						}
					}
Bruce Momjian's avatar
Bruce Momjian committed
1759
					*result = END_OF_FILE;
1760
					goto copy_eof;
1761 1762
			}
		}
1763
		appendStringInfoCharMacro(&attribute_buf, c);
1764

1765
		/* XXX shouldn't this be done even when encoding is the same? */
1766
		if (client_encoding != server_encoding)
1767
		{
1768 1769 1770 1771 1772
			/* get additional bytes of the char, if any */
			s[0] = c;
			mblen = pg_encoding_mblen(client_encoding, s);
			for (j = 1; j < mblen; j++)
			{
1773
				c = CopyGetChar();
1774
				if (c == EOF)
Bruce Momjian's avatar
Bruce Momjian committed
1775 1776
				{
					*result = END_OF_FILE;
1777
					goto copy_eof;
Bruce Momjian's avatar
Bruce Momjian committed
1778
				}
1779 1780
				appendStringInfoCharMacro(&attribute_buf, c);
			}
1781
		}
1782
	}
1783

1784 1785
copy_eof:

1786
	if (client_encoding != server_encoding)
1787
	{
1788 1789 1790 1791 1792 1793 1794 1795 1796
		cvt = (char *) pg_client_to_server((unsigned char *) attribute_buf.data,
										   attribute_buf.len);
		if (cvt != attribute_buf.data)
		{
			/* transfer converted data back to attribute_buf */
			attribute_buf.len = 0;
			attribute_buf.data[0] = '\0';
			appendBinaryStringInfo(&attribute_buf, cvt, strlen(cvt));
		}
1797
	}
1798

1799
	return attribute_buf.data;
1800 1801
}

1802
static void
1803
CopyAttributeOut(char *server_string, char *delim)
1804
{
1805
	char	   *string;
1806
	char		c;
1807 1808
	char		delimc = delim[0];
	bool		same_encoding;
1809
	int			mblen;
1810
	int			i;
1811

1812 1813
	same_encoding = (server_encoding == client_encoding);
	if (!same_encoding)
1814 1815 1816 1817
		string = (char *) pg_server_to_client((unsigned char *) server_string,
											  strlen(server_string));
	else
		string = server_string;
1818

1819
	for (; (c = *string) != '\0'; string += mblen)
1820
	{
1821
		mblen = 1;
1822

1823 1824 1825
		switch (c)
		{
			case '\b':
1826
				CopySendString("\\b");
1827 1828
				break;
			case '\f':
1829
				CopySendString("\\f");
1830 1831
				break;
			case '\n':
1832
				CopySendString("\\n");
1833 1834
				break;
			case '\r':
1835
				CopySendString("\\r");
1836 1837
				break;
			case '\t':
1838
				CopySendString("\\t");
1839 1840
				break;
			case '\v':
1841
				CopySendString("\\v");
1842 1843
				break;
			case '\\':
1844
				CopySendString("\\\\");
1845 1846 1847
				break;
			default:
				if (c == delimc)
1848 1849
					CopySendChar('\\');
				CopySendChar(c);
1850

1851 1852 1853 1854 1855
				/*
				 * We can skip pg_encoding_mblen() overhead when encoding
				 * is same, because in valid backend encodings, extra
				 * bytes of a multibyte character never look like ASCII.
				 */
1856 1857 1858 1859 1860
				if (!same_encoding)
				{
					/* send additional bytes of the char, if any */
					mblen = pg_encoding_mblen(client_encoding, string);
					for (i = 1; i < mblen; i++)
1861
						CopySendChar(string[i]);
1862 1863 1864
				}
				break;
		}
1865
	}
1866
}
1867 1868

/*
1869 1870 1871 1872 1873
 * CopyGetAttnums - build an integer list of attnums to be copied
 *
 * The input attnamelist is either the user-specified column list,
 * or NIL if there was none (in which case we want all the non-dropped
 * columns).
1874
 */
1875 1876
static List *
CopyGetAttnums(Relation rel, List *attnamelist)
1877
{
Bruce Momjian's avatar
Bruce Momjian committed
1878
	List	   *attnums = NIL;
Bruce Momjian's avatar
Bruce Momjian committed
1879

1880
	if (attnamelist == NIL)
Bruce Momjian's avatar
Bruce Momjian committed
1881
	{
1882
		/* Generate default column list */
Bruce Momjian's avatar
Bruce Momjian committed
1883
		TupleDesc	tupDesc = RelationGetDescr(rel);
1884
		Form_pg_attribute *attr = tupDesc->attrs;
Bruce Momjian's avatar
Bruce Momjian committed
1885
		int			attr_count = tupDesc->natts;
1886
		int			i;
Bruce Momjian's avatar
Bruce Momjian committed
1887 1888 1889

		for (i = 0; i < attr_count; i++)
		{
1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901
			if (attr[i]->attisdropped)
				continue;
			attnums = lappendi(attnums, i + 1);
		}
	}
	else
	{
		/* Validate the user-supplied list and extract attnums */
		List	   *l;

		foreach(l, attnamelist)
		{
1902
			char	   *name = strVal(lfirst(l));
1903 1904 1905 1906 1907 1908 1909 1910 1911
			int			attnum;

			/* Lookup column name, elog on failure */
			/* Note we disallow system columns here */
			attnum = attnameAttNum(rel, name, false);
			/* Check for duplicates */
			if (intMember(attnum, attnums))
				elog(ERROR, "Attribute \"%s\" specified more than once", name);
			attnums = lappendi(attnums, attnum);
Bruce Momjian's avatar
Bruce Momjian committed
1912 1913
		}
	}
1914

1915 1916
	return attnums;
}