]> granicus.if.org Git - postgresql/blob - src/backend/commands/copy.c
Preliminary code cleanup in elog(). Split out some code into utility
[postgresql] / src / backend / commands / copy.c
1 /*-------------------------------------------------------------------------
2  *
3  * copy.c
4  *
5  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
6  * Portions Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.139 2001/06/08 21:16:48 petere Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15
16 #include <unistd.h>
17 #include <sys/stat.h>
18
19 #include "access/genam.h"
20 #include "access/heapam.h"
21 #include "access/printtup.h"
22 #include "catalog/catname.h"
23 #include "catalog/index.h"
24 #include "catalog/pg_index.h"
25 #include "catalog/pg_shadow.h"
26 #include "catalog/pg_type.h"
27 #include "commands/copy.h"
28 #include "commands/trigger.h"
29 #include "executor/executor.h"
30 #include "libpq/libpq.h"
31 #include "miscadmin.h"
32 #include "tcop/pquery.h"
33 #include "tcop/tcopprot.h"
34 #include "utils/acl.h"
35 #include "utils/builtins.h"
36 #include "utils/relcache.h"
37 #include "utils/syscache.h"
38
39 #ifdef MULTIBYTE
40 #include "mb/pg_wchar.h"
41 #endif
42
43 #define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))
44 #define VALUE(c) ((c) - '0')
45
46
47 /* non-export function prototypes */
48 static void CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null_print);
49 static void CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null_print);
50 static Oid      GetInputFunction(Oid type);
51 static Oid      GetTypeElement(Oid type);
52 static void CopyReadNewline(FILE *fp, int *newline);
53 static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_print);
54 static void CopyAttributeOut(FILE *fp, char *string, char *delim);
55
56 static const char BinarySignature[12] = "PGBCOPY\n\377\r\n\0";
57
58 /*
59  * Static communication variables ... pretty grotty, but COPY has
60  * never been reentrant...
61  */
62 int                     copy_lineno = 0;        /* exported for use by elog() -- dz */
63 static bool fe_eof;
64
65 /*
66  * These static variables are used to avoid incurring overhead for each
67  * attribute processed.  attribute_buf is reused on each CopyReadAttribute
68  * call to hold the string being read in.  Under normal use it will soon
69  * grow to a suitable size, and then we will avoid palloc/pfree overhead
70  * for subsequent attributes.  Note that CopyReadAttribute returns a pointer
71  * to attribute_buf's data buffer!
72  * encoding, if needed, can be set once at the start of the copy operation.
73  */
74 static StringInfoData attribute_buf;
75
76 #ifdef MULTIBYTE
77 static int      client_encoding;
78 static int      server_encoding;
79
80 #endif
81
82
83 /*
84  * Internal communications functions
85  */
86 static void CopySendData(void *databuf, int datasize, FILE *fp);
87 static void CopySendString(char *str, FILE *fp);
88 static void CopySendChar(char c, FILE *fp);
89 static void CopyGetData(void *databuf, int datasize, FILE *fp);
90 static int      CopyGetChar(FILE *fp);
91 static int      CopyGetEof(FILE *fp);
92 static int      CopyPeekChar(FILE *fp);
93 static void CopyDonePeek(FILE *fp, int c, int pickup);
94
95 /*
96  * CopySendData sends output data either to the file
97  *      specified by fp or, if fp is NULL, using the standard
98  *      backend->frontend functions
99  *
100  * CopySendString does the same for null-terminated strings
101  * CopySendChar does the same for single characters
102  *
103  * NB: no data conversion is applied by these functions
104  */
105 static void
106 CopySendData(void *databuf, int datasize, FILE *fp)
107 {
108         if (!fp)
109         {
110                 if (pq_putbytes((char *) databuf, datasize))
111                         fe_eof = true;
112         }
113         else
114         {
115                 fwrite(databuf, datasize, 1, fp);
116                 if (ferror(fp))
117                         elog(ERROR, "CopySendData: %m");
118         }
119 }
120
121 static void
122 CopySendString(char *str, FILE *fp)
123 {
124         CopySendData(str, strlen(str), fp);
125 }
126
127 static void
128 CopySendChar(char c, FILE *fp)
129 {
130         CopySendData(&c, 1, fp);
131 }
132
133 /*
134  * CopyGetData reads output data either from the file
135  *      specified by fp or, if fp is NULL, using the standard
136  *      backend->frontend functions
137  *
138  * CopyGetChar does the same for single characters
139  * CopyGetEof checks if it's EOF on the input (or, check for EOF result
140  *              from CopyGetChar)
141  *
142  * NB: no data conversion is applied by these functions
143  */
144 static void
145 CopyGetData(void *databuf, int datasize, FILE *fp)
146 {
147         if (!fp)
148         {
149                 if (pq_getbytes((char *) databuf, datasize))
150                         fe_eof = true;
151         }
152         else
153                 fread(databuf, datasize, 1, fp);
154 }
155
156 static int
157 CopyGetChar(FILE *fp)
158 {
159         if (!fp)
160         {
161                 unsigned char ch;
162
163                 if (pq_getbytes((char *) &ch, 1))
164                 {
165                         fe_eof = true;
166                         return EOF;
167                 }
168                 return ch;
169         }
170         else
171                 return getc(fp);
172 }
173
174 static int
175 CopyGetEof(FILE *fp)
176 {
177         if (!fp)
178                 return fe_eof;
179         else
180                 return feof(fp);
181 }
182
183 /*
184  * CopyPeekChar reads a byte in "peekable" mode.
185  * after each call to CopyPeekChar, a call to CopyDonePeek _must_
186  * follow, unless EOF was returned.
187  * CopyDonePeek will either take the peeked char off the steam
188  * (if pickup is != 0) or leave it on the stream (if pickup == 0)
189  */
190 static int
191 CopyPeekChar(FILE *fp)
192 {
193         if (!fp)
194         {
195                 int                     ch = pq_peekbyte();
196
197                 if (ch == EOF)
198                         fe_eof = true;
199                 return ch;
200         }
201         else
202                 return getc(fp);
203 }
204
205 static void
206 CopyDonePeek(FILE *fp, int c, int pickup)
207 {
208         if (!fp)
209         {
210                 if (pickup)
211                 {
212
213                         /*
214                          * We want to pick it up - just receive again into dummy
215                          * buffer
216                          */
217                         char            c;
218
219                         pq_getbytes(&c, 1);
220                 }
221                 /* If we didn't want to pick it up, just leave it where it sits */
222         }
223         else
224         {
225                 if (!pickup)
226                 {
227                         /* We don't want to pick it up - so put it back in there */
228                         ungetc(c, fp);
229                 }
230                 /* If we wanted to pick it up, it's already there */
231         }
232 }
233
234
235
236 /*
237  *       DoCopy executes the SQL COPY statement.
238  */
239
240 void
241 DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
242            char *filename, char *delim, char *null_print)
243 {
244 /*----------------------------------------------------------------------------
245   Either unload or reload contents of class <relname>, depending on <from>.
246
247   If <pipe> is false, transfer is between the class and the file named
248   <filename>.  Otherwise, transfer is between the class and our regular
249   input/output stream.  The latter could be either stdin/stdout or a
250   socket, depending on whether we're running under Postmaster control.
251
252   Iff <binary>, unload or reload in the binary format, as opposed to the
253   more wasteful but more robust and portable text format.
254
255   If in the text format, delimit columns with delimiter <delim> and print
256   NULL values as <null_print>.
257
258   When loading in the text format from an input stream (as opposed to
259   a file), recognize a "." on a line by itself as EOF.  Also recognize
260   a stream EOF.  When unloading in the text format to an output stream,
261   write a "." on a line by itself at the end of the data.
262
263   Iff <oids>, unload or reload the format that includes OID information.
264
265   Do not allow a Postgres user without superuser privilege to read from
266   or write to a file.
267
268   Do not allow the copy if user doesn't have proper permission to access
269   the class.
270 ----------------------------------------------------------------------------*/
271
272         FILE       *fp;
273         Relation        rel;
274         const AclMode required_access = from ? ACL_INSERT : ACL_SELECT;
275         int                     result;
276
277         /*
278          * Open and lock the relation, using the appropriate lock type.
279          */
280         rel = heap_openr(relname, (from ? RowExclusiveLock : AccessShareLock));
281
282         result = pg_aclcheck(relname, GetUserId(), required_access);
283         if (result != ACLCHECK_OK)
284                 elog(ERROR, "%s: %s", relname, aclcheck_error_strings[result]);
285         if (!pipe && !superuser())
286                 elog(ERROR, "You must have Postgres superuser privilege to do a COPY "
287                          "directly to or from a file.  Anyone can COPY to stdout or "
288                          "from stdin.  Psql's \\copy command also works for anyone.");
289
290         /*
291          * This restriction is unfortunate, but necessary until the frontend
292          * COPY protocol is redesigned to be binary-safe...
293          */
294         if (pipe && binary)
295                 elog(ERROR, "COPY BINARY is not supported to stdout or from stdin");
296
297         /*
298          * Set up variables to avoid per-attribute overhead.
299          */
300         initStringInfo(&attribute_buf);
301 #ifdef MULTIBYTE
302         client_encoding = pg_get_client_encoding();
303         server_encoding = GetDatabaseEncoding();
304 #endif
305
306         if (from)
307         {                                                       /* copy from file to database */
308                 if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
309                         elog(ERROR, "You cannot change sequence relation %s", relname);
310                 if (pipe)
311                 {
312                         if (IsUnderPostmaster)
313                         {
314                                 ReceiveCopyBegin();
315                                 fp = NULL;
316                         }
317                         else
318                                 fp = stdin;
319                 }
320                 else
321                 {
322                         fp = AllocateFile(filename, PG_BINARY_R);
323                         if (fp == NULL)
324                                 elog(ERROR, "COPY command, running in backend with "
325                                          "effective uid %d, could not open file '%s' for "
326                                          "reading.  Errno = %s (%d).",
327                                          (int) geteuid(), filename, strerror(errno), errno);
328                 }
329                 CopyFrom(rel, binary, oids, fp, delim, null_print);
330         }
331         else
332         {                                                       /* copy from database to file */
333                 if (pipe)
334                 {
335                         if (IsUnderPostmaster)
336                         {
337                                 SendCopyBegin();
338                                 pq_startcopyout();
339                                 fp = NULL;
340                         }
341                         else
342                                 fp = stdout;
343                 }
344                 else
345                 {
346                         mode_t          oumask; /* Pre-existing umask value */
347
348                         /*
349                          * Prevent write to relative path ... too easy to shoot
350                          * oneself in the foot by overwriting a database file ...
351                          */
352                         if (filename[0] != '/')
353                                 elog(ERROR, "Relative path not allowed for server side"
354                                          " COPY command.");
355
356                         oumask = umask((mode_t) 022);
357                         fp = AllocateFile(filename, PG_BINARY_W);
358                         umask(oumask);
359
360                         if (fp == NULL)
361                                 elog(ERROR, "COPY command, running in backend with "
362                                          "effective uid %d, could not open file '%s' for "
363                                          "writing.  Errno = %s (%d).",
364                                          (int) geteuid(), filename, strerror(errno), errno);
365                 }
366                 CopyTo(rel, binary, oids, fp, delim, null_print);
367         }
368
369         if (!pipe)
370                 FreeFile(fp);
371         else if (!from)
372         {
373                 if (!binary)
374                         CopySendData("\\.\n", 3, fp);
375                 if (IsUnderPostmaster)
376                         pq_endcopyout(false);
377         }
378         pfree(attribute_buf.data);
379
380         /*
381          * Close the relation.  If reading, we can release the AccessShareLock
382          * we got; if writing, we should hold the lock until end of
383          * transaction to ensure that updates will be committed before lock is
384          * released.
385          */
386         heap_close(rel, (from ? NoLock : AccessShareLock));
387 }
388
389
390 /*
391  * Copy from relation TO file.
392  */
393 static void
394 CopyTo(Relation rel, bool binary, bool oids, FILE *fp,
395            char *delim, char *null_print)
396 {
397         HeapTuple       tuple;
398         TupleDesc       tupDesc;
399         HeapScanDesc scandesc;
400         int                     attr_count,
401                                 i;
402         Form_pg_attribute *attr;
403         FmgrInfo   *out_functions;
404         Oid                *elements;
405         bool       *isvarlena;
406         int16           fld_size;
407         char       *string;
408
409         tupDesc = rel->rd_att;
410         attr_count = rel->rd_att->natts;
411         attr = rel->rd_att->attrs;
412
413         /*
414          * For binary copy we really only need isvarlena, but compute it
415          * all...
416          */
417         out_functions = (FmgrInfo *) palloc(attr_count * sizeof(FmgrInfo));
418         elements = (Oid *) palloc(attr_count * sizeof(Oid));
419         isvarlena = (bool *) palloc(attr_count * sizeof(bool));
420         for (i = 0; i < attr_count; i++)
421         {
422                 Oid                     out_func_oid;
423
424                 if (!getTypeOutputInfo(attr[i]->atttypid,
425                                                          &out_func_oid, &elements[i], &isvarlena[i]))
426                         elog(ERROR, "COPY: couldn't lookup info for type %u",
427                                  attr[i]->atttypid);
428                 fmgr_info(out_func_oid, &out_functions[i]);
429         }
430
431         if (binary)
432         {
433                 /* Generate header for a binary copy */
434                 int32           tmp;
435
436                 /* Signature */
437                 CopySendData((char *) BinarySignature, 12, fp);
438                 /* Integer layout field */
439                 tmp = 0x01020304;
440                 CopySendData(&tmp, sizeof(int32), fp);
441                 /* Flags field */
442                 tmp = 0;
443                 if (oids)
444                         tmp |= (1 << 16);
445                 CopySendData(&tmp, sizeof(int32), fp);
446                 /* No header extension */
447                 tmp = 0;
448                 CopySendData(&tmp, sizeof(int32), fp);
449         }
450
451         scandesc = heap_beginscan(rel, 0, QuerySnapshot, 0, NULL);
452
453         while (HeapTupleIsValid(tuple = heap_getnext(scandesc, 0)))
454         {
455                 bool            need_delim = false;
456
457                 CHECK_FOR_INTERRUPTS();
458
459                 if (binary)
460                 {
461                         /* Binary per-tuple header */
462                         int16           fld_count = attr_count;
463
464                         CopySendData(&fld_count, sizeof(int16), fp);
465                         /* Send OID if wanted --- note fld_count doesn't include it */
466                         if (oids)
467                         {
468                                 fld_size = sizeof(Oid);
469                                 CopySendData(&fld_size, sizeof(int16), fp);
470                                 CopySendData(&tuple->t_data->t_oid, sizeof(Oid), fp);
471                         }
472                 }
473                 else
474                 {
475                         /* Text format has no per-tuple header, but send OID if wanted */
476                         if (oids)
477                         {
478                                 string = DatumGetCString(DirectFunctionCall1(oidout,
479                                                                 ObjectIdGetDatum(tuple->t_data->t_oid)));
480                                 CopySendString(string, fp);
481                                 pfree(string);
482                                 need_delim = true;
483                         }
484                 }
485
486                 for (i = 0; i < attr_count; i++)
487                 {
488                         Datum           origvalue,
489                                                 value;
490                         bool            isnull;
491
492                         origvalue = heap_getattr(tuple, i + 1, tupDesc, &isnull);
493
494                         if (!binary)
495                         {
496                                 if (need_delim)
497                                         CopySendChar(delim[0], fp);
498                                 need_delim = true;
499                         }
500
501                         if (isnull)
502                         {
503                                 if (!binary)
504                                 {
505                                         CopySendString(null_print, fp);         /* null indicator */
506                                 }
507                                 else
508                                 {
509                                         fld_size = 0;           /* null marker */
510                                         CopySendData(&fld_size, sizeof(int16), fp);
511                                 }
512                         }
513                         else
514                         {
515
516                                 /*
517                                  * If we have a toasted datum, forcibly detoast it to
518                                  * avoid memory leakage inside the type's output routine
519                                  * (or for binary case, becase we must output untoasted
520                                  * value).
521                                  */
522                                 if (isvarlena[i])
523                                         value = PointerGetDatum(PG_DETOAST_DATUM(origvalue));
524                                 else
525                                         value = origvalue;
526
527                                 if (!binary)
528                                 {
529                                         string = DatumGetCString(FunctionCall3(&out_functions[i],
530                                                                                                                    value,
531                                                                                    ObjectIdGetDatum(elements[i]),
532                                                                          Int32GetDatum(attr[i]->atttypmod)));
533                                         CopyAttributeOut(fp, string, delim);
534                                         pfree(string);
535                                 }
536                                 else
537                                 {
538                                         fld_size = attr[i]->attlen;
539                                         CopySendData(&fld_size, sizeof(int16), fp);
540                                         if (isvarlena[i])
541                                         {
542                                                 /* varlena */
543                                                 Assert(fld_size == -1);
544                                                 CopySendData(DatumGetPointer(value),
545                                                                          VARSIZE(value),
546                                                                          fp);
547                                         }
548                                         else if (!attr[i]->attbyval)
549                                         {
550                                                 /* fixed-length pass-by-reference */
551                                                 Assert(fld_size > 0);
552                                                 CopySendData(DatumGetPointer(value),
553                                                                          fld_size,
554                                                                          fp);
555                                         }
556                                         else
557                                         {
558                                                 /* pass-by-value */
559                                                 Datum           datumBuf;
560
561                                                 /*
562                                                  * We need this horsing around because we don't
563                                                  * know how shorter data values are aligned within
564                                                  * a Datum.
565                                                  */
566                                                 store_att_byval(&datumBuf, value, fld_size);
567                                                 CopySendData(&datumBuf,
568                                                                          fld_size,
569                                                                          fp);
570                                         }
571                                 }
572
573                                 /* Clean up detoasted copy, if any */
574                                 if (value != origvalue)
575                                         pfree(DatumGetPointer(value));
576                         }
577                 }
578
579                 if (!binary)
580                         CopySendChar('\n', fp);
581         }
582
583         heap_endscan(scandesc);
584
585         if (binary)
586         {
587                 /* Generate trailer for a binary copy */
588                 int16           fld_count = -1;
589
590                 CopySendData(&fld_count, sizeof(int16), fp);
591         }
592
593         pfree(out_functions);
594         pfree(elements);
595         pfree(isvarlena);
596 }
597
598
599 /*
600  * Copy FROM file to relation.
601  */
602 static void
603 CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
604                  char *delim, char *null_print)
605 {
606         HeapTuple       tuple;
607         TupleDesc       tupDesc;
608         Form_pg_attribute *attr;
609         AttrNumber      attr_count;
610         FmgrInfo   *in_functions;
611         Oid                *elements;
612         int                     i;
613         Oid                     in_func_oid;
614         Datum      *values;
615         char       *nulls;
616         bool            isnull;
617         int                     done = 0;
618         char       *string;
619         ResultRelInfo *resultRelInfo;
620         EState     *estate = CreateExecutorState(); /* for ExecConstraints() */
621         TupleTable      tupleTable;
622         TupleTableSlot *slot;
623         Oid                     loaded_oid = InvalidOid;
624         bool            skip_tuple = false;
625         bool            file_has_oids;
626
627         tupDesc = RelationGetDescr(rel);
628         attr = tupDesc->attrs;
629         attr_count = tupDesc->natts;
630
631         /*
632          * We need a ResultRelInfo so we can use the regular executor's
633          * index-entry-making machinery.  (There used to be a huge amount of
634          * code here that basically duplicated execUtils.c ...)
635          */
636         resultRelInfo = makeNode(ResultRelInfo);
637         resultRelInfo->ri_RangeTableIndex = 1;          /* dummy */
638         resultRelInfo->ri_RelationDesc = rel;
639         resultRelInfo->ri_TrigDesc = rel->trigdesc;
640
641         ExecOpenIndices(resultRelInfo);
642
643         estate->es_result_relations = resultRelInfo;
644         estate->es_num_result_relations = 1;
645         estate->es_result_relation_info = resultRelInfo;
646
647         /* Set up a dummy tuple table too */
648         tupleTable = ExecCreateTupleTable(1);
649         slot = ExecAllocTableSlot(tupleTable);
650         ExecSetSlotDescriptor(slot, tupDesc, false);
651
652         if (!binary)
653         {
654                 in_functions = (FmgrInfo *) palloc(attr_count * sizeof(FmgrInfo));
655                 elements = (Oid *) palloc(attr_count * sizeof(Oid));
656                 for (i = 0; i < attr_count; i++)
657                 {
658                         in_func_oid = (Oid) GetInputFunction(attr[i]->atttypid);
659                         fmgr_info(in_func_oid, &in_functions[i]);
660                         elements[i] = GetTypeElement(attr[i]->atttypid);
661                 }
662                 file_has_oids = oids;   /* must rely on user to tell us this... */
663         }
664         else
665         {
666                 /* Read and verify binary header */
667                 char            readSig[12];
668                 int32           tmp;
669
670                 /* Signature */
671                 CopyGetData(readSig, 12, fp);
672                 if (CopyGetEof(fp) ||
673                         memcmp(readSig, BinarySignature, 12) != 0)
674                         elog(ERROR, "COPY BINARY: file signature not recognized");
675                 /* Integer layout field */
676                 CopyGetData(&tmp, sizeof(int32), fp);
677                 if (CopyGetEof(fp) ||
678                         tmp != 0x01020304)
679                         elog(ERROR, "COPY BINARY: incompatible integer layout");
680                 /* Flags field */
681                 CopyGetData(&tmp, sizeof(int32), fp);
682                 if (CopyGetEof(fp))
683                         elog(ERROR, "COPY BINARY: bogus file header (missing flags)");
684                 file_has_oids = (tmp & (1 << 16)) != 0;
685                 tmp &= ~(1 << 16);
686                 if ((tmp >> 16) != 0)
687                         elog(ERROR, "COPY BINARY: unrecognized critical flags in header");
688                 /* Header extension length */
689                 CopyGetData(&tmp, sizeof(int32), fp);
690                 if (CopyGetEof(fp) ||
691                         tmp < 0)
692                         elog(ERROR, "COPY BINARY: bogus file header (missing length)");
693                 /* Skip extension header, if present */
694                 while (tmp-- > 0)
695                 {
696                         CopyGetData(readSig, 1, fp);
697                         if (CopyGetEof(fp))
698                                 elog(ERROR, "COPY BINARY: bogus file header (wrong length)");
699                 }
700
701                 in_functions = NULL;
702                 elements = NULL;
703         }
704
705         values = (Datum *) palloc(attr_count * sizeof(Datum));
706         nulls = (char *) palloc(attr_count * sizeof(char));
707
708         copy_lineno = 0;
709         fe_eof = false;
710
711         while (!done)
712         {
713                 CHECK_FOR_INTERRUPTS();
714
715                 copy_lineno++;
716
717                 /* Reset the per-output-tuple exprcontext */
718                 ResetPerTupleExprContext(estate);
719
720                 /* Initialize all values for row to NULL */
721                 MemSet(values, 0, attr_count * sizeof(Datum));
722                 MemSet(nulls, 'n', attr_count * sizeof(char));
723
724                 if (!binary)
725                 {
726                         int                     newline = 0;
727
728                         if (file_has_oids)
729                         {
730                                 string = CopyReadAttribute(fp, &isnull, delim,
731                                                                                    &newline, null_print);
732                                 if (isnull)
733                                         elog(ERROR, "COPY TEXT: NULL Oid");
734                                 else if (string == NULL)
735                                         done = 1;       /* end of file */
736                                 else
737                                 {
738                                         loaded_oid = DatumGetObjectId(DirectFunctionCall1(oidin,
739                                                                                            CStringGetDatum(string)));
740                                         if (loaded_oid == InvalidOid)
741                                                 elog(ERROR, "COPY TEXT: Invalid Oid");
742                                 }
743                         }
744
745                         for (i = 0; i < attr_count && !done; i++)
746                         {
747                                 string = CopyReadAttribute(fp, &isnull, delim,
748                                                                                    &newline, null_print);
749                                 if (isnull)
750                                 {
751                                         /* already set values[i] and nulls[i] */
752                                 }
753                                 else if (string == NULL)
754                                         done = 1;       /* end of file */
755                                 else
756                                 {
757                                         values[i] = FunctionCall3(&in_functions[i],
758                                                                                           CStringGetDatum(string),
759                                                                                    ObjectIdGetDatum(elements[i]),
760                                                                           Int32GetDatum(attr[i]->atttypmod));
761                                         nulls[i] = ' ';
762                                 }
763                         }
764                         if (!done)
765                                 CopyReadNewline(fp, &newline);
766                 }
767                 else
768                 {                                               /* binary */
769                         int16           fld_count,
770                                                 fld_size;
771
772                         CopyGetData(&fld_count, sizeof(int16), fp);
773                         if (CopyGetEof(fp) ||
774                                 fld_count == -1)
775                                 done = 1;
776                         else
777                         {
778                                 if (fld_count <= 0 || fld_count > attr_count)
779                                         elog(ERROR, "COPY BINARY: tuple field count is %d, expected %d",
780                                                  (int) fld_count, attr_count);
781
782                                 if (file_has_oids)
783                                 {
784                                         CopyGetData(&fld_size, sizeof(int16), fp);
785                                         if (CopyGetEof(fp))
786                                                 elog(ERROR, "COPY BINARY: unexpected EOF");
787                                         if (fld_size != (int16) sizeof(Oid))
788                                                 elog(ERROR, "COPY BINARY: sizeof(Oid) is %d, expected %d",
789                                                          (int) fld_size, (int) sizeof(Oid));
790                                         CopyGetData(&loaded_oid, sizeof(Oid), fp);
791                                         if (CopyGetEof(fp))
792                                                 elog(ERROR, "COPY BINARY: unexpected EOF");
793                                         if (loaded_oid == InvalidOid)
794                                                 elog(ERROR, "COPY BINARY: Invalid Oid");
795                                 }
796
797                                 for (i = 0; i < (int) fld_count; i++)
798                                 {
799                                         CopyGetData(&fld_size, sizeof(int16), fp);
800                                         if (CopyGetEof(fp))
801                                                 elog(ERROR, "COPY BINARY: unexpected EOF");
802                                         if (fld_size == 0)
803                                                 continue;               /* it's NULL; nulls[i] already set */
804                                         if (fld_size != attr[i]->attlen)
805                                                 elog(ERROR, "COPY BINARY: sizeof(field %d) is %d, expected %d",
806                                                    i + 1, (int) fld_size, (int) attr[i]->attlen);
807                                         if (fld_size == -1)
808                                         {
809                                                 /* varlena field */
810                                                 int32           varlena_size;
811                                                 Pointer         varlena_ptr;
812
813                                                 CopyGetData(&varlena_size, sizeof(int32), fp);
814                                                 if (CopyGetEof(fp))
815                                                         elog(ERROR, "COPY BINARY: unexpected EOF");
816                                                 if (varlena_size < (int32) sizeof(int32))
817                                                         elog(ERROR, "COPY BINARY: bogus varlena length");
818                                                 varlena_ptr = (Pointer) palloc(varlena_size);
819                                                 VARATT_SIZEP(varlena_ptr) = varlena_size;
820                                                 CopyGetData(VARDATA(varlena_ptr),
821                                                                         varlena_size - sizeof(int32),
822                                                                         fp);
823                                                 if (CopyGetEof(fp))
824                                                         elog(ERROR, "COPY BINARY: unexpected EOF");
825                                                 values[i] = PointerGetDatum(varlena_ptr);
826                                         }
827                                         else if (!attr[i]->attbyval)
828                                         {
829                                                 /* fixed-length pass-by-reference */
830                                                 Pointer         refval_ptr;
831
832                                                 Assert(fld_size > 0);
833                                                 refval_ptr = (Pointer) palloc(fld_size);
834                                                 CopyGetData(refval_ptr, fld_size, fp);
835                                                 if (CopyGetEof(fp))
836                                                         elog(ERROR, "COPY BINARY: unexpected EOF");
837                                                 values[i] = PointerGetDatum(refval_ptr);
838                                         }
839                                         else
840                                         {
841                                                 /* pass-by-value */
842                                                 Datum           datumBuf;
843
844                                                 /*
845                                                  * We need this horsing around because we don't
846                                                  * know how shorter data values are aligned within
847                                                  * a Datum.
848                                                  */
849                                                 Assert(fld_size > 0 && fld_size <= sizeof(Datum));
850                                                 CopyGetData(&datumBuf, fld_size, fp);
851                                                 if (CopyGetEof(fp))
852                                                         elog(ERROR, "COPY BINARY: unexpected EOF");
853                                                 values[i] = fetch_att(&datumBuf, true, fld_size);
854                                         }
855
856                                         nulls[i] = ' ';
857                                 }
858                         }
859                 }
860
861                 if (done)
862                         break;
863
864                 tuple = heap_formtuple(tupDesc, values, nulls);
865
866                 if (oids && file_has_oids)
867                         tuple->t_data->t_oid = loaded_oid;
868
869                 skip_tuple = false;
870
871                 /* BEFORE ROW INSERT Triggers */
872                 if (resultRelInfo->ri_TrigDesc &&
873                         resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)
874                 {
875                         HeapTuple       newtuple;
876
877                         newtuple = ExecBRInsertTriggers(estate, resultRelInfo, tuple);
878
879                         if (newtuple == NULL)           /* "do nothing" */
880                                 skip_tuple = true;
881                         else if (newtuple != tuple) /* modified by Trigger(s) */
882                         {
883                                 heap_freetuple(tuple);
884                                 tuple = newtuple;
885                         }
886                 }
887
888                 if (!skip_tuple)
889                 {
890                         ExecStoreTuple(tuple, slot, InvalidBuffer, false);
891
892                         /*
893                          * Check the constraints of the tuple
894                          */
895                         if (rel->rd_att->constr)
896                                 ExecConstraints("CopyFrom", resultRelInfo, slot, estate);
897
898                         /*
899                          * OK, store the tuple and create index entries for it
900                          */
901                         heap_insert(rel, tuple);
902
903                         if (resultRelInfo->ri_NumIndices > 0)
904                                 ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
905
906                         /* AFTER ROW INSERT Triggers */
907                         if (resultRelInfo->ri_TrigDesc)
908                                 ExecARInsertTriggers(estate, resultRelInfo, tuple);
909                 }
910
911                 for (i = 0; i < attr_count; i++)
912                 {
913                         if (!attr[i]->attbyval && nulls[i] != 'n')
914                                 pfree(DatumGetPointer(values[i]));
915                 }
916
917                 heap_freetuple(tuple);
918         }
919
920         /*
921          * Done, clean up
922          */
923         copy_lineno = 0;
924
925         pfree(values);
926         pfree(nulls);
927
928         if (!binary)
929         {
930                 pfree(in_functions);
931                 pfree(elements);
932         }
933
934         ExecDropTupleTable(tupleTable, true);
935
936         ExecCloseIndices(resultRelInfo);
937 }
938
939
940 static Oid
941 GetInputFunction(Oid type)
942 {
943         HeapTuple       typeTuple;
944         Oid                     result;
945
946         typeTuple = SearchSysCache(TYPEOID,
947                                                            ObjectIdGetDatum(type),
948                                                            0, 0, 0);
949         if (!HeapTupleIsValid(typeTuple))
950                 elog(ERROR, "GetInputFunction: Cache lookup of type %u failed", type);
951         result = ((Form_pg_type) GETSTRUCT(typeTuple))->typinput;
952         ReleaseSysCache(typeTuple);
953         return result;
954 }
955
956 static Oid
957 GetTypeElement(Oid type)
958 {
959         HeapTuple       typeTuple;
960         Oid                     result;
961
962         typeTuple = SearchSysCache(TYPEOID,
963                                                            ObjectIdGetDatum(type),
964                                                            0, 0, 0);
965         if (!HeapTupleIsValid(typeTuple))
966                 elog(ERROR, "GetTypeElement: Cache lookup of type %u failed", type);
967         result = ((Form_pg_type) GETSTRUCT(typeTuple))->typelem;
968         ReleaseSysCache(typeTuple);
969         return result;
970 }
971
972
973 /*
974  * Reads input from fp until an end of line is seen.
975  */
976
977 static void
978 CopyReadNewline(FILE *fp, int *newline)
979 {
980         if (!*newline)
981         {
982                 elog(NOTICE, "CopyReadNewline: extra fields ignored");
983                 while (!CopyGetEof(fp) && (CopyGetChar(fp) != '\n'));
984         }
985         *newline = 0;
986 }
987
988 /*
989  * Read the value of a single attribute.
990  *
991  * Result is either a string, or NULL (if EOF or a null attribute).
992  * Note that the caller should not pfree the string!
993  *
994  * *isnull is set true if a null attribute, else false.
995  * delim is the string of acceptable delimiter characters(s).
996  * *newline remembers whether we've seen a newline ending this tuple.
997  * null_print says how NULL values are represented
998  */
999
1000 static char *
1001 CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_print)
1002 {
1003         int                     c;
1004
1005 #ifdef MULTIBYTE
1006         int                     mblen;
1007         unsigned char s[2];
1008         char       *cvt;
1009         int                     j;
1010
1011         s[1] = 0;
1012 #endif
1013
1014         /* reset attribute_buf to empty */
1015         attribute_buf.len = 0;
1016         attribute_buf.data[0] = '\0';
1017
1018         /* if last delimiter was a newline return a NULL attribute */
1019         if (*newline)
1020         {
1021                 *isnull = (bool) true;
1022                 return NULL;
1023         }
1024
1025         *isnull = (bool) false;         /* set default */
1026
1027         for (;;)
1028         {
1029                 c = CopyGetChar(fp);
1030                 if (c == EOF)
1031                         goto endOfFile;
1032                 if (c == '\n')
1033                 {
1034                         *newline = 1;
1035                         break;
1036                 }
1037                 if (strchr(delim, c))
1038                         break;
1039                 if (c == '\\')
1040                 {
1041                         c = CopyGetChar(fp);
1042                         if (c == EOF)
1043                                 goto endOfFile;
1044                         switch (c)
1045                         {
1046                                 case '0':
1047                                 case '1':
1048                                 case '2':
1049                                 case '3':
1050                                 case '4':
1051                                 case '5':
1052                                 case '6':
1053                                 case '7':
1054                                         {
1055                                                 int                     val;
1056
1057                                                 val = VALUE(c);
1058                                                 c = CopyPeekChar(fp);
1059                                                 if (ISOCTAL(c))
1060                                                 {
1061                                                         val = (val << 3) + VALUE(c);
1062                                                         CopyDonePeek(fp, c, 1);         /* Pick up the
1063                                                                                                                  * character! */
1064                                                         c = CopyPeekChar(fp);
1065                                                         if (ISOCTAL(c))
1066                                                         {
1067                                                                 CopyDonePeek(fp, c, 1); /* pick up! */
1068                                                                 val = (val << 3) + VALUE(c);
1069                                                         }
1070                                                         else
1071                                                         {
1072                                                                 if (c == EOF)
1073                                                                         goto endOfFile;
1074                                                                 CopyDonePeek(fp, c, 0); /* Return to stream! */
1075                                                         }
1076                                                 }
1077                                                 else
1078                                                 {
1079                                                         if (c == EOF)
1080                                                                 goto endOfFile;
1081                                                         CopyDonePeek(fp, c, 0);         /* Return to stream! */
1082                                                 }
1083                                                 c = val & 0377;
1084                                         }
1085                                         break;
1086
1087                                         /*
1088                                          * This is a special hack to parse `\N' as
1089                                          * <backslash-N> rather then just 'N' to provide
1090                                          * compatibility with the default NULL output. -- pe
1091                                          */
1092                                 case 'N':
1093                                         appendStringInfoCharMacro(&attribute_buf, '\\');
1094                                         c = 'N';
1095                                         break;
1096                                 case 'b':
1097                                         c = '\b';
1098                                         break;
1099                                 case 'f':
1100                                         c = '\f';
1101                                         break;
1102                                 case 'n':
1103                                         c = '\n';
1104                                         break;
1105                                 case 'r':
1106                                         c = '\r';
1107                                         break;
1108                                 case 't':
1109                                         c = '\t';
1110                                         break;
1111                                 case 'v':
1112                                         c = '\v';
1113                                         break;
1114                                 case '.':
1115                                         c = CopyGetChar(fp);
1116                                         if (c != '\n')
1117                                                 elog(ERROR, "CopyReadAttribute: end of record marker corrupted");
1118                                         goto endOfFile;
1119                         }
1120                 }
1121                 appendStringInfoCharMacro(&attribute_buf, c);
1122 #ifdef MULTIBYTE
1123                 if (client_encoding != server_encoding)
1124                 {
1125                         /* get additional bytes of the char, if any */
1126                         s[0] = c;
1127                         mblen = pg_encoding_mblen(client_encoding, s);
1128                         for (j = 1; j < mblen; j++)
1129                         {
1130                                 c = CopyGetChar(fp);
1131                                 if (c == EOF)
1132                                         goto endOfFile;
1133                                 appendStringInfoCharMacro(&attribute_buf, c);
1134                         }
1135                 }
1136 #endif
1137         }
1138
1139 #ifdef MULTIBYTE
1140         if (client_encoding != server_encoding)
1141         {
1142                 cvt = (char *) pg_client_to_server((unsigned char *) attribute_buf.data,
1143                                                                                    attribute_buf.len);
1144                 if (cvt != attribute_buf.data)
1145                 {
1146                         /* transfer converted data back to attribute_buf */
1147                         attribute_buf.len = 0;
1148                         attribute_buf.data[0] = '\0';
1149                         appendBinaryStringInfo(&attribute_buf, cvt, strlen(cvt));
1150                         pfree(cvt);
1151                 }
1152         }
1153 #endif
1154
1155         if (strcmp(attribute_buf.data, null_print) == 0)
1156                 *isnull = true;
1157
1158         return attribute_buf.data;
1159
1160 endOfFile:
1161         return NULL;
1162 }
1163
1164 static void
1165 CopyAttributeOut(FILE *fp, char *server_string, char *delim)
1166 {
1167         char       *string;
1168         char            c;
1169
1170 #ifdef MULTIBYTE
1171         char       *string_start;
1172         int                     mblen;
1173         int                     i;
1174
1175 #endif
1176
1177 #ifdef MULTIBYTE
1178         if (client_encoding != server_encoding)
1179         {
1180                 string = (char *) pg_server_to_client((unsigned char *) server_string,
1181                                                                                           strlen(server_string));
1182                 string_start = string;
1183         }
1184         else
1185         {
1186                 string = server_string;
1187                 string_start = NULL;    /* unused, but keep compiler quiet */
1188         }
1189 #else
1190         string = server_string;
1191 #endif
1192
1193 #ifdef MULTIBYTE
1194         for (; (mblen = (server_encoding == client_encoding ? 1 : pg_encoding_mblen(client_encoding, string))) &&
1195                  ((c = *string) != '\0'); string += mblen)
1196 #else
1197         for (; (c = *string) != '\0'; string++)
1198 #endif
1199         {
1200                 if (c == delim[0] || c == '\n' || c == '\\')
1201                         CopySendChar('\\', fp);
1202 #ifdef MULTIBYTE
1203                 for (i = 0; i < mblen; i++)
1204                         CopySendChar(*(string + i), fp);
1205 #else
1206                 CopySendChar(c, fp);
1207 #endif
1208         }
1209
1210 #ifdef MULTIBYTE
1211         if (client_encoding != server_encoding)
1212                 pfree(string_start);    /* pfree pg_server_to_client result */
1213 #endif
1214 }