PostgreSQL Source Code  git master
copyfromparse.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <unistd.h>
#include <sys/stat.h>
#include "commands/copy.h"
#include "commands/copyfrom_internal.h"
#include "commands/progress.h"
#include "executor/executor.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "port/pg_bswap.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/rel.h"
Include dependency graph for copyfromparse.c:

Go to the source code of this file.

Macros

#define ISOCTAL(c)   (((c) >= '0') && ((c) <= '7'))
 
#define OCTVALUE(c)   ((c) - '0')
 
#define IF_NEED_REFILL_AND_NOT_EOF_CONTINUE(extralen)
 
#define IF_NEED_REFILL_AND_EOF_BREAK(extralen)
 
#define REFILL_LINEBUF
 
#define NO_END_OF_COPY_GOTO
 

Functions

static bool CopyReadLine (CopyFromState cstate)
 
static bool CopyReadLineText (CopyFromState cstate)
 
static int CopyReadAttributesText (CopyFromState cstate)
 
static int CopyReadAttributesCSV (CopyFromState cstate)
 
static Datum CopyReadBinaryAttribute (CopyFromState cstate, FmgrInfo *flinfo, Oid typioparam, int32 typmod, bool *isnull)
 
static int CopyGetData (CopyFromState cstate, void *databuf, int minread, int maxread)
 
static bool CopyGetInt32 (CopyFromState cstate, int32 *val)
 
static bool CopyGetInt16 (CopyFromState cstate, int16 *val)
 
static void CopyLoadInputBuf (CopyFromState cstate)
 
static int CopyReadBinaryData (CopyFromState cstate, char *dest, int nbytes)
 
void ReceiveCopyBegin (CopyFromState cstate)
 
void ReceiveCopyBinaryHeader (CopyFromState cstate)
 
static void CopyConvertBuf (CopyFromState cstate)
 
static void CopyConversionError (CopyFromState cstate)
 
static void CopyLoadRawBuf (CopyFromState cstate)
 
bool NextCopyFromRawFields (CopyFromState cstate, char ***fields, int *nfields)
 
bool NextCopyFrom (CopyFromState cstate, ExprContext *econtext, Datum *values, bool *nulls)
 
static int GetDecimalFromHex (char hex)
 

Variables

static const char BinarySignature [11] = "PGCOPY\n\377\r\n\0"
 

Macro Definition Documentation

◆ IF_NEED_REFILL_AND_EOF_BREAK

#define IF_NEED_REFILL_AND_EOF_BREAK (   extralen)
Value:
if (1) \
{ \
if (input_buf_ptr + (extralen) >= copy_buf_len && hit_eof) \
{ \
if (extralen) \
input_buf_ptr = copy_buf_len; /* consume the partial character */ \
/* backslash just before EOF, treat as data char */ \
result = true; \
break; \
} \
} else ((void) 0)

Definition at line 110 of file copyfromparse.c.

◆ IF_NEED_REFILL_AND_NOT_EOF_CONTINUE

#define IF_NEED_REFILL_AND_NOT_EOF_CONTINUE (   extralen)
Value:
if (1) \
{ \
if (input_buf_ptr + (extralen) >= copy_buf_len && !hit_eof) \
{ \
input_buf_ptr = prev_raw_ptr; /* undo fetch */ \
need_data = true; \
continue; \
} \
} else ((void) 0)

Definition at line 98 of file copyfromparse.c.

◆ ISOCTAL

#define ISOCTAL (   c)    (((c) >= '0') && ((c) <= '7'))

Definition at line 79 of file copyfromparse.c.

◆ NO_END_OF_COPY_GOTO

#define NO_END_OF_COPY_GOTO
Value:
if (1) \
{ \
input_buf_ptr = prev_raw_ptr + 1; \
goto not_end_of_copy; \
} else ((void) 0)

Definition at line 140 of file copyfromparse.c.

◆ OCTVALUE

#define OCTVALUE (   c)    ((c) - '0')

Definition at line 80 of file copyfromparse.c.

◆ REFILL_LINEBUF

#define REFILL_LINEBUF
Value:
if (1) \
{ \
if (input_buf_ptr > cstate->input_buf_index) \
{ \
appendBinaryStringInfo(&cstate->line_buf, \
cstate->input_buf + cstate->input_buf_index, \
input_buf_ptr - cstate->input_buf_index); \
cstate->input_buf_index = input_buf_ptr; \
} \
} else ((void) 0)

Definition at line 127 of file copyfromparse.c.

Function Documentation

◆ CopyConversionError()

static void CopyConversionError ( CopyFromState  cstate)
static

Definition at line 533 of file copyfromparse.c.

534 {
535  Assert(cstate->raw_buf_len > 0);
536  Assert(cstate->input_reached_error);
537 
538  if (!cstate->need_transcoding)
539  {
540  /*
541  * Everything up to input_buf_len was successfully verified, and
542  * input_buf_len points to the invalid or incomplete character.
543  */
545  cstate->raw_buf + cstate->input_buf_len,
546  cstate->raw_buf_len - cstate->input_buf_len);
547  }
548  else
549  {
550  /*
551  * raw_buf_index points to the invalid or untranslatable character. We
552  * let the conversion routine report the error, because it can provide
553  * a more specific error message than we could here. An earlier call
554  * to the conversion routine in CopyConvertBuf() detected that there
555  * is an error, now we call the conversion routine again with
556  * noError=false, to have it throw the error.
557  */
558  unsigned char *src;
559  int srclen;
560  unsigned char *dst;
561  int dstlen;
562 
563  src = (unsigned char *) cstate->raw_buf + cstate->raw_buf_index;
564  srclen = cstate->raw_buf_len - cstate->raw_buf_index;
565  dst = (unsigned char *) cstate->input_buf + cstate->input_buf_len;
566  dstlen = INPUT_BUF_SIZE - cstate->input_buf_len + 1;
567 
569  cstate->file_encoding,
571  src, srclen,
572  dst, dstlen,
573  false);
574 
575  /*
576  * The conversion routine should have reported an error, so this
577  * should not be reached.
578  */
579  elog(ERROR, "encoding conversion failed without error");
580  }
581 }
#define INPUT_BUF_SIZE
#define ERROR
Definition: elog.h:35
Assert(fmt[strlen(fmt) - 1] !='\n')
int GetDatabaseEncoding(void)
Definition: mbutils.c:1210
int pg_do_encoding_conversion_buf(Oid proc, int src_encoding, int dest_encoding, unsigned char *src, int srclen, unsigned char *dest, int destlen, bool noError)
Definition: mbutils.c:469
void report_invalid_encoding(int encoding, const char *mbstr, int len)
Definition: mbutils.c:1647

References Assert(), CopyFromStateData::conversion_proc, elog(), ERROR, CopyFromStateData::file_encoding, GetDatabaseEncoding(), CopyFromStateData::input_buf, CopyFromStateData::input_buf_len, INPUT_BUF_SIZE, CopyFromStateData::input_reached_error, CopyFromStateData::need_transcoding, pg_do_encoding_conversion_buf(), CopyFromStateData::raw_buf, CopyFromStateData::raw_buf_index, CopyFromStateData::raw_buf_len, and report_invalid_encoding().

Referenced by CopyLoadInputBuf().

◆ CopyConvertBuf()

static void CopyConvertBuf ( CopyFromState  cstate)
static

Definition at line 400 of file copyfromparse.c.

401 {
402  /*
403  * If the file and server encoding are the same, no encoding conversion is
404  * required. However, we still need to verify that the input is valid for
405  * the encoding.
406  */
407  if (!cstate->need_transcoding)
408  {
409  /*
410  * When conversion is not required, input_buf and raw_buf are the
411  * same. raw_buf_len is the total number of bytes in the buffer, and
412  * input_buf_len tracks how many of those bytes have already been
413  * verified.
414  */
415  int preverifiedlen = cstate->input_buf_len;
416  int unverifiedlen = cstate->raw_buf_len - cstate->input_buf_len;
417  int nverified;
418 
419  if (unverifiedlen == 0)
420  {
421  /*
422  * If no more raw data is coming, report the EOF to the caller.
423  */
424  if (cstate->raw_reached_eof)
425  cstate->input_reached_eof = true;
426  return;
427  }
428 
429  /*
430  * Verify the new data, including any residual unverified bytes from
431  * previous round.
432  */
433  nverified = pg_encoding_verifymbstr(cstate->file_encoding,
434  cstate->raw_buf + preverifiedlen,
435  unverifiedlen);
436  if (nverified == 0)
437  {
438  /*
439  * Could not verify anything.
440  *
441  * If there is no more raw input data coming, it means that there
442  * was an incomplete multi-byte sequence at the end. Also, if
443  * there's "enough" input left, we should be able to verify at
444  * least one character, and a failure to do so means that we've
445  * hit an invalid byte sequence.
446  */
447  if (cstate->raw_reached_eof || unverifiedlen >= pg_encoding_max_length(cstate->file_encoding))
448  cstate->input_reached_error = true;
449  return;
450  }
451  cstate->input_buf_len += nverified;
452  }
453  else
454  {
455  /*
456  * Encoding conversion is needed.
457  */
458  int nbytes;
459  unsigned char *src;
460  int srclen;
461  unsigned char *dst;
462  int dstlen;
463  int convertedlen;
464 
465  if (RAW_BUF_BYTES(cstate) == 0)
466  {
467  /*
468  * If no more raw data is coming, report the EOF to the caller.
469  */
470  if (cstate->raw_reached_eof)
471  cstate->input_reached_eof = true;
472  return;
473  }
474 
475  /*
476  * First, copy down any unprocessed data.
477  */
478  nbytes = INPUT_BUF_BYTES(cstate);
479  if (nbytes > 0 && cstate->input_buf_index > 0)
480  memmove(cstate->input_buf, cstate->input_buf + cstate->input_buf_index,
481  nbytes);
482  cstate->input_buf_index = 0;
483  cstate->input_buf_len = nbytes;
484  cstate->input_buf[nbytes] = '\0';
485 
486  src = (unsigned char *) cstate->raw_buf + cstate->raw_buf_index;
487  srclen = cstate->raw_buf_len - cstate->raw_buf_index;
488  dst = (unsigned char *) cstate->input_buf + cstate->input_buf_len;
489  dstlen = INPUT_BUF_SIZE - cstate->input_buf_len + 1;
490 
491  /*
492  * Do the conversion. This might stop short, if there is an invalid
493  * byte sequence in the input. We'll convert as much as we can in
494  * that case.
495  *
496  * Note: Even if we hit an invalid byte sequence, we don't report the
497  * error until all the valid bytes have been consumed. The input
498  * might contain an end-of-input marker (\.), and we don't want to
499  * report an error if the invalid byte sequence is after the
500  * end-of-input marker. We might unnecessarily convert some data
501  * after the end-of-input marker as long as it's valid for the
502  * encoding, but that's harmless.
503  */
504  convertedlen = pg_do_encoding_conversion_buf(cstate->conversion_proc,
505  cstate->file_encoding,
507  src, srclen,
508  dst, dstlen,
509  true);
510  if (convertedlen == 0)
511  {
512  /*
513  * Could not convert anything. If there is no more raw input data
514  * coming, it means that there was an incomplete multi-byte
515  * sequence at the end. Also, if there is plenty of input left,
516  * we should be able to convert at least one character, so a
517  * failure to do so must mean that we've hit a byte sequence
518  * that's invalid.
519  */
520  if (cstate->raw_reached_eof || srclen >= MAX_CONVERSION_INPUT_LENGTH)
521  cstate->input_reached_error = true;
522  return;
523  }
524  cstate->raw_buf_index += convertedlen;
525  cstate->input_buf_len += strlen((char *) dst);
526  }
527 }
#define RAW_BUF_BYTES(cstate)
#define INPUT_BUF_BYTES(cstate)
#define MAX_CONVERSION_INPUT_LENGTH
Definition: pg_wchar.h:320
int pg_encoding_verifymbstr(int encoding, const char *mbstr, int len)
Definition: wchar.c:2177
int pg_encoding_max_length(int encoding)
Definition: wchar.c:2188

References CopyFromStateData::conversion_proc, CopyFromStateData::file_encoding, GetDatabaseEncoding(), CopyFromStateData::input_buf, INPUT_BUF_BYTES, CopyFromStateData::input_buf_index, CopyFromStateData::input_buf_len, INPUT_BUF_SIZE, CopyFromStateData::input_reached_eof, CopyFromStateData::input_reached_error, MAX_CONVERSION_INPUT_LENGTH, CopyFromStateData::need_transcoding, pg_do_encoding_conversion_buf(), pg_encoding_max_length(), pg_encoding_verifymbstr(), CopyFromStateData::raw_buf, RAW_BUF_BYTES, CopyFromStateData::raw_buf_index, CopyFromStateData::raw_buf_len, and CopyFromStateData::raw_reached_eof.

Referenced by CopyLoadInputBuf().

◆ CopyGetData()

static int CopyGetData ( CopyFromState  cstate,
void *  databuf,
int  minread,
int  maxread 
)
static

Definition at line 245 of file copyfromparse.c.

246 {
247  int bytesread = 0;
248 
249  switch (cstate->copy_src)
250  {
251  case COPY_FILE:
252  bytesread = fread(databuf, 1, maxread, cstate->copy_file);
253  if (ferror(cstate->copy_file))
254  ereport(ERROR,
256  errmsg("could not read from COPY file: %m")));
257  if (bytesread == 0)
258  cstate->raw_reached_eof = true;
259  break;
260  case COPY_FRONTEND:
261  while (maxread > 0 && bytesread < minread && !cstate->raw_reached_eof)
262  {
263  int avail;
264 
265  while (cstate->fe_msgbuf->cursor >= cstate->fe_msgbuf->len)
266  {
267  /* Try to receive another message */
268  int mtype;
269  int maxmsglen;
270 
271  readmessage:
273  pq_startmsgread();
274  mtype = pq_getbyte();
275  if (mtype == EOF)
276  ereport(ERROR,
277  (errcode(ERRCODE_CONNECTION_FAILURE),
278  errmsg("unexpected EOF on client connection with an open transaction")));
279  /* Validate message type and set packet size limit */
280  switch (mtype)
281  {
282  case 'd': /* CopyData */
283  maxmsglen = PQ_LARGE_MESSAGE_LIMIT;
284  break;
285  case 'c': /* CopyDone */
286  case 'f': /* CopyFail */
287  case 'H': /* Flush */
288  case 'S': /* Sync */
289  maxmsglen = PQ_SMALL_MESSAGE_LIMIT;
290  break;
291  default:
292  ereport(ERROR,
293  (errcode(ERRCODE_PROTOCOL_VIOLATION),
294  errmsg("unexpected message type 0x%02X during COPY from stdin",
295  mtype)));
296  maxmsglen = 0; /* keep compiler quiet */
297  break;
298  }
299  /* Now collect the message body */
300  if (pq_getmessage(cstate->fe_msgbuf, maxmsglen))
301  ereport(ERROR,
302  (errcode(ERRCODE_CONNECTION_FAILURE),
303  errmsg("unexpected EOF on client connection with an open transaction")));
305  /* ... and process it */
306  switch (mtype)
307  {
308  case 'd': /* CopyData */
309  break;
310  case 'c': /* CopyDone */
311  /* COPY IN correctly terminated by frontend */
312  cstate->raw_reached_eof = true;
313  return bytesread;
314  case 'f': /* CopyFail */
315  ereport(ERROR,
316  (errcode(ERRCODE_QUERY_CANCELED),
317  errmsg("COPY from stdin failed: %s",
318  pq_getmsgstring(cstate->fe_msgbuf))));
319  break;
320  case 'H': /* Flush */
321  case 'S': /* Sync */
322 
323  /*
324  * Ignore Flush/Sync for the convenience of client
325  * libraries (such as libpq) that may send those
326  * without noticing that the command they just
327  * sent was COPY.
328  */
329  goto readmessage;
330  default:
331  Assert(false); /* NOT REACHED */
332  }
333  }
334  avail = cstate->fe_msgbuf->len - cstate->fe_msgbuf->cursor;
335  if (avail > maxread)
336  avail = maxread;
337  pq_copymsgbytes(cstate->fe_msgbuf, databuf, avail);
338  databuf = (void *) ((char *) databuf + avail);
339  maxread -= avail;
340  bytesread += avail;
341  }
342  break;
343  case COPY_CALLBACK:
344  bytesread = cstate->data_source_cb(databuf, minread, maxread);
345  break;
346  }
347 
348  return bytesread;
349 }
@ COPY_FILE
Definition: copyto.c:52
@ COPY_CALLBACK
Definition: copyto.c:54
@ COPY_FRONTEND
Definition: copyto.c:53
int errcode_for_file_access(void)
Definition: elog.c:718
int errcode(int sqlerrcode)
Definition: elog.c:695
int errmsg(const char *fmt,...)
Definition: elog.c:906
#define ereport(elevel,...)
Definition: elog.h:145
#define PQ_SMALL_MESSAGE_LIMIT
Definition: libpq.h:30
#define PQ_LARGE_MESSAGE_LIMIT
Definition: libpq.h:31
#define HOLD_CANCEL_INTERRUPTS()
Definition: miscadmin.h:140
#define RESUME_CANCEL_INTERRUPTS()
Definition: miscadmin.h:142
int pq_getmessage(StringInfo s, int maxlen)
Definition: pqcomm.c:1202
int pq_getbyte(void)
Definition: pqcomm.c:970
void pq_startmsgread(void)
Definition: pqcomm.c:1140
const char * pq_getmsgstring(StringInfo msg)
Definition: pqformat.c:581
void pq_copymsgbytes(StringInfo msg, char *buf, int datalen)
Definition: pqformat.c:530
copy_data_source_cb data_source_cb

References Assert(), COPY_CALLBACK, COPY_FILE, CopyFromStateData::copy_file, COPY_FRONTEND, CopyFromStateData::copy_src, StringInfoData::cursor, CopyFromStateData::data_source_cb, ereport, errcode(), errcode_for_file_access(), errmsg(), ERROR, CopyFromStateData::fe_msgbuf, HOLD_CANCEL_INTERRUPTS, StringInfoData::len, pq_copymsgbytes(), pq_getbyte(), pq_getmessage(), pq_getmsgstring(), PQ_LARGE_MESSAGE_LIMIT, PQ_SMALL_MESSAGE_LIMIT, pq_startmsgread(), CopyFromStateData::raw_reached_eof, and RESUME_CANCEL_INTERRUPTS.

Referenced by CopyLoadRawBuf(), and CopyReadLine().

◆ CopyGetInt16()

static bool CopyGetInt16 ( CopyFromState  cstate,
int16 val 
)
inlinestatic

Definition at line 379 of file copyfromparse.c.

380 {
381  uint16 buf;
382 
383  if (CopyReadBinaryData(cstate, (char *) &buf, sizeof(buf)) != sizeof(buf))
384  {
385  *val = 0; /* suppress compiler warning */
386  return false;
387  }
388  *val = (int16) pg_ntoh16(buf);
389  return true;
390 }
unsigned short uint16
Definition: c.h:441
signed short int16
Definition: c.h:429
static int CopyReadBinaryData(CopyFromState cstate, char *dest, int nbytes)
long val
Definition: informix.c:664
#define pg_ntoh16(x)
Definition: pg_bswap.h:124
static char * buf
Definition: pg_test_fsync.c:67

References buf, CopyReadBinaryData(), pg_ntoh16, and val.

Referenced by NextCopyFrom().

◆ CopyGetInt32()

static bool CopyGetInt32 ( CopyFromState  cstate,
int32 val 
)
inlinestatic

Definition at line 362 of file copyfromparse.c.

363 {
364  uint32 buf;
365 
366  if (CopyReadBinaryData(cstate, (char *) &buf, sizeof(buf)) != sizeof(buf))
367  {
368  *val = 0; /* suppress compiler warning */
369  return false;
370  }
371  *val = (int32) pg_ntoh32(buf);
372  return true;
373 }
unsigned int uint32
Definition: c.h:442
signed int int32
Definition: c.h:430
#define pg_ntoh32(x)
Definition: pg_bswap.h:125

References buf, CopyReadBinaryData(), pg_ntoh32, and val.

Referenced by CopyReadBinaryAttribute(), and ReceiveCopyBinaryHeader().

◆ CopyLoadInputBuf()

static void CopyLoadInputBuf ( CopyFromState  cstate)
static

Definition at line 650 of file copyfromparse.c.

651 {
652  int nbytes = INPUT_BUF_BYTES(cstate);
653 
654  /*
655  * The caller has updated input_buf_index to indicate how much of the
656  * input has been consumed and isn't needed anymore. If input_buf is the
657  * same physical area as raw_buf, update raw_buf_index accordingly.
658  */
659  if (cstate->raw_buf == cstate->input_buf)
660  {
661  Assert(!cstate->need_transcoding);
662  Assert(cstate->input_buf_index >= cstate->raw_buf_index);
663  cstate->raw_buf_index = cstate->input_buf_index;
664  }
665 
666  for (;;)
667  {
668  /* If we now have some unconverted data, try to convert it */
669  CopyConvertBuf(cstate);
670 
671  /* If we now have some more input bytes ready, return them */
672  if (INPUT_BUF_BYTES(cstate) > nbytes)
673  return;
674 
675  /*
676  * If we reached an invalid byte sequence, or we're at an incomplete
677  * multi-byte character but there is no more raw input data, report
678  * conversion error.
679  */
680  if (cstate->input_reached_error)
681  CopyConversionError(cstate);
682 
683  /* no more input, and everything has been converted */
684  if (cstate->input_reached_eof)
685  break;
686 
687  /* Try to load more raw data */
688  Assert(!cstate->raw_reached_eof);
689  CopyLoadRawBuf(cstate);
690  }
691 }
static void CopyConversionError(CopyFromState cstate)
static void CopyLoadRawBuf(CopyFromState cstate)
static void CopyConvertBuf(CopyFromState cstate)

References Assert(), CopyConversionError(), CopyConvertBuf(), CopyLoadRawBuf(), CopyFromStateData::input_buf, INPUT_BUF_BYTES, CopyFromStateData::input_buf_index, CopyFromStateData::input_reached_eof, CopyFromStateData::input_reached_error, CopyFromStateData::need_transcoding, CopyFromStateData::raw_buf, CopyFromStateData::raw_buf_index, and CopyFromStateData::raw_reached_eof.

Referenced by CopyReadLineText().

◆ CopyLoadRawBuf()

static void CopyLoadRawBuf ( CopyFromState  cstate)
static

Definition at line 590 of file copyfromparse.c.

591 {
592  int nbytes;
593  int inbytes;
594 
595  /*
596  * In text mode, if encoding conversion is not required, raw_buf and
597  * input_buf point to the same buffer. Their len/index better agree, too.
598  */
599  if (cstate->raw_buf == cstate->input_buf)
600  {
601  Assert(!cstate->need_transcoding);
602  Assert(cstate->raw_buf_index == cstate->input_buf_index);
603  Assert(cstate->input_buf_len <= cstate->raw_buf_len);
604  }
605 
606  /*
607  * Copy down the unprocessed data if any.
608  */
609  nbytes = RAW_BUF_BYTES(cstate);
610  if (nbytes > 0 && cstate->raw_buf_index > 0)
611  memmove(cstate->raw_buf, cstate->raw_buf + cstate->raw_buf_index,
612  nbytes);
613  cstate->raw_buf_len -= cstate->raw_buf_index;
614  cstate->raw_buf_index = 0;
615 
616  /*
617  * If raw_buf and input_buf are in fact the same buffer, adjust the
618  * input_buf variables, too.
619  */
620  if (cstate->raw_buf == cstate->input_buf)
621  {
622  cstate->input_buf_len -= cstate->input_buf_index;
623  cstate->input_buf_index = 0;
624  }
625 
626  /* Load more data */
627  inbytes = CopyGetData(cstate, cstate->raw_buf + cstate->raw_buf_len,
628  1, RAW_BUF_SIZE - cstate->raw_buf_len);
629  nbytes += inbytes;
630  cstate->raw_buf[nbytes] = '\0';
631  cstate->raw_buf_len = nbytes;
632 
633  cstate->bytes_processed += inbytes;
635 
636  if (inbytes == 0)
637  cstate->raw_reached_eof = true;
638 }
void pgstat_progress_update_param(int index, int64 val)
#define RAW_BUF_SIZE
static int CopyGetData(CopyFromState cstate, void *databuf, int minread, int maxread)
#define PROGRESS_COPY_BYTES_PROCESSED
Definition: progress.h:137

References Assert(), CopyFromStateData::bytes_processed, CopyGetData(), CopyFromStateData::input_buf, CopyFromStateData::input_buf_index, CopyFromStateData::input_buf_len, CopyFromStateData::need_transcoding, pgstat_progress_update_param(), PROGRESS_COPY_BYTES_PROCESSED, CopyFromStateData::raw_buf, RAW_BUF_BYTES, CopyFromStateData::raw_buf_index, CopyFromStateData::raw_buf_len, RAW_BUF_SIZE, and CopyFromStateData::raw_reached_eof.

Referenced by CopyLoadInputBuf(), and CopyReadBinaryData().

◆ CopyReadAttributesCSV()

static int CopyReadAttributesCSV ( CopyFromState  cstate)
static

Definition at line 1706 of file copyfromparse.c.

1707 {
1708  char delimc = cstate->opts.delim[0];
1709  char quotec = cstate->opts.quote[0];
1710  char escapec = cstate->opts.escape[0];
1711  int fieldno;
1712  char *output_ptr;
1713  char *cur_ptr;
1714  char *line_end_ptr;
1715 
1716  /*
1717  * We need a special case for zero-column tables: check that the input
1718  * line is empty, and return.
1719  */
1720  if (cstate->max_fields <= 0)
1721  {
1722  if (cstate->line_buf.len != 0)
1723  ereport(ERROR,
1724  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1725  errmsg("extra data after last expected column")));
1726  return 0;
1727  }
1728 
1729  resetStringInfo(&cstate->attribute_buf);
1730 
1731  /*
1732  * The de-escaped attributes will certainly not be longer than the input
1733  * data line, so we can just force attribute_buf to be large enough and
1734  * then transfer data without any checks for enough space. We need to do
1735  * it this way because enlarging attribute_buf mid-stream would invalidate
1736  * pointers already stored into cstate->raw_fields[].
1737  */
1738  if (cstate->attribute_buf.maxlen <= cstate->line_buf.len)
1739  enlargeStringInfo(&cstate->attribute_buf, cstate->line_buf.len);
1740  output_ptr = cstate->attribute_buf.data;
1741 
1742  /* set pointer variables for loop */
1743  cur_ptr = cstate->line_buf.data;
1744  line_end_ptr = cstate->line_buf.data + cstate->line_buf.len;
1745 
1746  /* Outer loop iterates over fields */
1747  fieldno = 0;
1748  for (;;)
1749  {
1750  bool found_delim = false;
1751  bool saw_quote = false;
1752  char *start_ptr;
1753  char *end_ptr;
1754  int input_len;
1755 
1756  /* Make sure there is enough space for the next value */
1757  if (fieldno >= cstate->max_fields)
1758  {
1759  cstate->max_fields *= 2;
1760  cstate->raw_fields =
1761  repalloc(cstate->raw_fields, cstate->max_fields * sizeof(char *));
1762  }
1763 
1764  /* Remember start of field on both input and output sides */
1765  start_ptr = cur_ptr;
1766  cstate->raw_fields[fieldno] = output_ptr;
1767 
1768  /*
1769  * Scan data for field,
1770  *
1771  * The loop starts in "not quote" mode and then toggles between that
1772  * and "in quote" mode. The loop exits normally if it is in "not
1773  * quote" mode and a delimiter or line end is seen.
1774  */
1775  for (;;)
1776  {
1777  char c;
1778 
1779  /* Not in quote */
1780  for (;;)
1781  {
1782  end_ptr = cur_ptr;
1783  if (cur_ptr >= line_end_ptr)
1784  goto endfield;
1785  c = *cur_ptr++;
1786  /* unquoted field delimiter */
1787  if (c == delimc)
1788  {
1789  found_delim = true;
1790  goto endfield;
1791  }
1792  /* start of quoted field (or part of field) */
1793  if (c == quotec)
1794  {
1795  saw_quote = true;
1796  break;
1797  }
1798  /* Add c to output string */
1799  *output_ptr++ = c;
1800  }
1801 
1802  /* In quote */
1803  for (;;)
1804  {
1805  end_ptr = cur_ptr;
1806  if (cur_ptr >= line_end_ptr)
1807  ereport(ERROR,
1808  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1809  errmsg("unterminated CSV quoted field")));
1810 
1811  c = *cur_ptr++;
1812 
1813  /* escape within a quoted field */
1814  if (c == escapec)
1815  {
1816  /*
1817  * peek at the next char if available, and escape it if it
1818  * is an escape char or a quote char
1819  */
1820  if (cur_ptr < line_end_ptr)
1821  {
1822  char nextc = *cur_ptr;
1823 
1824  if (nextc == escapec || nextc == quotec)
1825  {
1826  *output_ptr++ = nextc;
1827  cur_ptr++;
1828  continue;
1829  }
1830  }
1831  }
1832 
1833  /*
1834  * end of quoted field. Must do this test after testing for
1835  * escape in case quote char and escape char are the same
1836  * (which is the common case).
1837  */
1838  if (c == quotec)
1839  break;
1840 
1841  /* Add c to output string */
1842  *output_ptr++ = c;
1843  }
1844  }
1845 endfield:
1846 
1847  /* Terminate attribute value in output area */
1848  *output_ptr++ = '\0';
1849 
1850  /* Check whether raw input matched null marker */
1851  input_len = end_ptr - start_ptr;
1852  if (!saw_quote && input_len == cstate->opts.null_print_len &&
1853  strncmp(start_ptr, cstate->opts.null_print, input_len) == 0)
1854  cstate->raw_fields[fieldno] = NULL;
1855 
1856  fieldno++;
1857  /* Done if we hit EOL instead of a delim */
1858  if (!found_delim)
1859  break;
1860  }
1861 
1862  /* Clean up state of attribute_buf */
1863  output_ptr--;
1864  Assert(*output_ptr == '\0');
1865  cstate->attribute_buf.len = (output_ptr - cstate->attribute_buf.data);
1866 
1867  return fieldno;
1868 }
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1321
char * c
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:75
void enlargeStringInfo(StringInfo str, int needed)
Definition: stringinfo.c:283
int null_print_len
Definition: copy.h:48
char * quote
Definition: copy.h:51
char * escape
Definition: copy.h:52
char * null_print
Definition: copy.h:47
char * delim
Definition: copy.h:50
StringInfoData line_buf
CopyFormatOptions opts
StringInfoData attribute_buf

References Assert(), CopyFromStateData::attribute_buf, StringInfoData::data, CopyFormatOptions::delim, enlargeStringInfo(), ereport, errcode(), errmsg(), ERROR, CopyFormatOptions::escape, StringInfoData::len, CopyFromStateData::line_buf, CopyFromStateData::max_fields, StringInfoData::maxlen, CopyFormatOptions::null_print, CopyFormatOptions::null_print_len, CopyFromStateData::opts, CopyFormatOptions::quote, CopyFromStateData::raw_fields, repalloc(), and resetStringInfo().

Referenced by NextCopyFromRawFields().

◆ CopyReadAttributesText()

static int CopyReadAttributesText ( CopyFromState  cstate)
static

Definition at line 1478 of file copyfromparse.c.

1479 {
1480  char delimc = cstate->opts.delim[0];
1481  int fieldno;
1482  char *output_ptr;
1483  char *cur_ptr;
1484  char *line_end_ptr;
1485 
1486  /*
1487  * We need a special case for zero-column tables: check that the input
1488  * line is empty, and return.
1489  */
1490  if (cstate->max_fields <= 0)
1491  {
1492  if (cstate->line_buf.len != 0)
1493  ereport(ERROR,
1494  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1495  errmsg("extra data after last expected column")));
1496  return 0;
1497  }
1498 
1499  resetStringInfo(&cstate->attribute_buf);
1500 
1501  /*
1502  * The de-escaped attributes will certainly not be longer than the input
1503  * data line, so we can just force attribute_buf to be large enough and
1504  * then transfer data without any checks for enough space. We need to do
1505  * it this way because enlarging attribute_buf mid-stream would invalidate
1506  * pointers already stored into cstate->raw_fields[].
1507  */
1508  if (cstate->attribute_buf.maxlen <= cstate->line_buf.len)
1509  enlargeStringInfo(&cstate->attribute_buf, cstate->line_buf.len);
1510  output_ptr = cstate->attribute_buf.data;
1511 
1512  /* set pointer variables for loop */
1513  cur_ptr = cstate->line_buf.data;
1514  line_end_ptr = cstate->line_buf.data + cstate->line_buf.len;
1515 
1516  /* Outer loop iterates over fields */
1517  fieldno = 0;
1518  for (;;)
1519  {
1520  bool found_delim = false;
1521  char *start_ptr;
1522  char *end_ptr;
1523  int input_len;
1524  bool saw_non_ascii = false;
1525 
1526  /* Make sure there is enough space for the next value */
1527  if (fieldno >= cstate->max_fields)
1528  {
1529  cstate->max_fields *= 2;
1530  cstate->raw_fields =
1531  repalloc(cstate->raw_fields, cstate->max_fields * sizeof(char *));
1532  }
1533 
1534  /* Remember start of field on both input and output sides */
1535  start_ptr = cur_ptr;
1536  cstate->raw_fields[fieldno] = output_ptr;
1537 
1538  /*
1539  * Scan data for field.
1540  *
1541  * Note that in this loop, we are scanning to locate the end of field
1542  * and also speculatively performing de-escaping. Once we find the
1543  * end-of-field, we can match the raw field contents against the null
1544  * marker string. Only after that comparison fails do we know that
1545  * de-escaping is actually the right thing to do; therefore we *must
1546  * not* throw any syntax errors before we've done the null-marker
1547  * check.
1548  */
1549  for (;;)
1550  {
1551  char c;
1552 
1553  end_ptr = cur_ptr;
1554  if (cur_ptr >= line_end_ptr)
1555  break;
1556  c = *cur_ptr++;
1557  if (c == delimc)
1558  {
1559  found_delim = true;
1560  break;
1561  }
1562  if (c == '\\')
1563  {
1564  if (cur_ptr >= line_end_ptr)
1565  break;
1566  c = *cur_ptr++;
1567  switch (c)
1568  {
1569  case '0':
1570  case '1':
1571  case '2':
1572  case '3':
1573  case '4':
1574  case '5':
1575  case '6':
1576  case '7':
1577  {
1578  /* handle \013 */
1579  int val;
1580 
1581  val = OCTVALUE(c);
1582  if (cur_ptr < line_end_ptr)
1583  {
1584  c = *cur_ptr;
1585  if (ISOCTAL(c))
1586  {
1587  cur_ptr++;
1588  val = (val << 3) + OCTVALUE(c);
1589  if (cur_ptr < line_end_ptr)
1590  {
1591  c = *cur_ptr;
1592  if (ISOCTAL(c))
1593  {
1594  cur_ptr++;
1595  val = (val << 3) + OCTVALUE(c);
1596  }
1597  }
1598  }
1599  }
1600  c = val & 0377;
1601  if (c == '\0' || IS_HIGHBIT_SET(c))
1602  saw_non_ascii = true;
1603  }
1604  break;
1605  case 'x':
1606  /* Handle \x3F */
1607  if (cur_ptr < line_end_ptr)
1608  {
1609  char hexchar = *cur_ptr;
1610 
1611  if (isxdigit((unsigned char) hexchar))
1612  {
1613  int val = GetDecimalFromHex(hexchar);
1614 
1615  cur_ptr++;
1616  if (cur_ptr < line_end_ptr)
1617  {
1618  hexchar = *cur_ptr;
1619  if (isxdigit((unsigned char) hexchar))
1620  {
1621  cur_ptr++;
1622  val = (val << 4) + GetDecimalFromHex(hexchar);
1623  }
1624  }
1625  c = val & 0xff;
1626  if (c == '\0' || IS_HIGHBIT_SET(c))
1627  saw_non_ascii = true;
1628  }
1629  }
1630  break;
1631  case 'b':
1632  c = '\b';
1633  break;
1634  case 'f':
1635  c = '\f';
1636  break;
1637  case 'n':
1638  c = '\n';
1639  break;
1640  case 'r':
1641  c = '\r';
1642  break;
1643  case 't':
1644  c = '\t';
1645  break;
1646  case 'v':
1647  c = '\v';
1648  break;
1649 
1650  /*
1651  * in all other cases, take the char after '\'
1652  * literally
1653  */
1654  }
1655  }
1656 
1657  /* Add c to output string */
1658  *output_ptr++ = c;
1659  }
1660 
1661  /* Check whether raw input matched null marker */
1662  input_len = end_ptr - start_ptr;
1663  if (input_len == cstate->opts.null_print_len &&
1664  strncmp(start_ptr, cstate->opts.null_print, input_len) == 0)
1665  cstate->raw_fields[fieldno] = NULL;
1666  else
1667  {
1668  /*
1669  * At this point we know the field is supposed to contain data.
1670  *
1671  * If we de-escaped any non-7-bit-ASCII chars, make sure the
1672  * resulting string is valid data for the db encoding.
1673  */
1674  if (saw_non_ascii)
1675  {
1676  char *fld = cstate->raw_fields[fieldno];
1677 
1678  pg_verifymbstr(fld, output_ptr - fld, false);
1679  }
1680  }
1681 
1682  /* Terminate attribute value in output area */
1683  *output_ptr++ = '\0';
1684 
1685  fieldno++;
1686  /* Done if we hit EOL instead of a delim */
1687  if (!found_delim)
1688  break;
1689  }
1690 
1691  /* Clean up state of attribute_buf */
1692  output_ptr--;
1693  Assert(*output_ptr == '\0');
1694  cstate->attribute_buf.len = (output_ptr - cstate->attribute_buf.data);
1695 
1696  return fieldno;
1697 }
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1094
#define OCTVALUE(c)
Definition: copyfromparse.c:80
#define ISOCTAL(c)
Definition: copyfromparse.c:79
static int GetDecimalFromHex(char hex)
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: mbutils.c:1505

References CopyFromStateData::attribute_buf, StringInfoData::data, CopyFormatOptions::delim, enlargeStringInfo(), ereport, errcode(), errmsg(), ERROR, GetDecimalFromHex(), if(), IS_HIGHBIT_SET, ISOCTAL, StringInfoData::len, CopyFromStateData::line_buf, CopyFromStateData::max_fields, StringInfoData::maxlen, CopyFormatOptions::null_print, CopyFormatOptions::null_print_len, OCTVALUE, CopyFromStateData::opts, pg_verifymbstr(), CopyFromStateData::raw_fields, repalloc(), resetStringInfo(), and val.

Referenced by NextCopyFromRawFields().

◆ CopyReadBinaryAttribute()

static Datum CopyReadBinaryAttribute ( CopyFromState  cstate,
FmgrInfo flinfo,
Oid  typioparam,
int32  typmod,
bool isnull 
)
static

Definition at line 1875 of file copyfromparse.c.

1878 {
1879  int32 fld_size;
1880  Datum result;
1881 
1882  if (!CopyGetInt32(cstate, &fld_size))
1883  ereport(ERROR,
1884  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1885  errmsg("unexpected EOF in COPY data")));
1886  if (fld_size == -1)
1887  {
1888  *isnull = true;
1889  return ReceiveFunctionCall(flinfo, NULL, typioparam, typmod);
1890  }
1891  if (fld_size < 0)
1892  ereport(ERROR,
1893  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1894  errmsg("invalid field size")));
1895 
1896  /* reset attribute_buf to empty, and load raw data in it */
1897  resetStringInfo(&cstate->attribute_buf);
1898 
1899  enlargeStringInfo(&cstate->attribute_buf, fld_size);
1900  if (CopyReadBinaryData(cstate, cstate->attribute_buf.data,
1901  fld_size) != fld_size)
1902  ereport(ERROR,
1903  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1904  errmsg("unexpected EOF in COPY data")));
1905 
1906  cstate->attribute_buf.len = fld_size;
1907  cstate->attribute_buf.data[fld_size] = '\0';
1908 
1909  /* Call the column type's binary input converter */
1910  result = ReceiveFunctionCall(flinfo, &cstate->attribute_buf,
1911  typioparam, typmod);
1912 
1913  /* Trouble if it didn't eat the whole buffer */
1914  if (cstate->attribute_buf.cursor != cstate->attribute_buf.len)
1915  ereport(ERROR,
1916  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1917  errmsg("incorrect binary data format")));
1918 
1919  *isnull = false;
1920  return result;
1921 }
static bool CopyGetInt32(CopyFromState cstate, int32 *val)
Datum ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf, Oid typioparam, int32 typmod)
Definition: fmgr.c:1573
uintptr_t Datum
Definition: postgres.h:412

References CopyFromStateData::attribute_buf, CopyGetInt32(), CopyReadBinaryData(), StringInfoData::cursor, StringInfoData::data, enlargeStringInfo(), ereport, errcode(), errmsg(), ERROR, StringInfoData::len, ReceiveFunctionCall(), and resetStringInfo().

Referenced by NextCopyFrom().

◆ CopyReadBinaryData()

static int CopyReadBinaryData ( CopyFromState  cstate,
char *  dest,
int  nbytes 
)
static

Definition at line 701 of file copyfromparse.c.

702 {
703  int copied_bytes = 0;
704 
705  if (RAW_BUF_BYTES(cstate) >= nbytes)
706  {
707  /* Enough bytes are present in the buffer. */
708  memcpy(dest, cstate->raw_buf + cstate->raw_buf_index, nbytes);
709  cstate->raw_buf_index += nbytes;
710  copied_bytes = nbytes;
711  }
712  else
713  {
714  /*
715  * Not enough bytes in the buffer, so must read from the file. Need
716  * to loop since 'nbytes' could be larger than the buffer size.
717  */
718  do
719  {
720  int copy_bytes;
721 
722  /* Load more data if buffer is empty. */
723  if (RAW_BUF_BYTES(cstate) == 0)
724  {
725  CopyLoadRawBuf(cstate);
726  if (cstate->raw_reached_eof)
727  break; /* EOF */
728  }
729 
730  /* Transfer some bytes. */
731  copy_bytes = Min(nbytes - copied_bytes, RAW_BUF_BYTES(cstate));
732  memcpy(dest, cstate->raw_buf + cstate->raw_buf_index, copy_bytes);
733  cstate->raw_buf_index += copy_bytes;
734  dest += copy_bytes;
735  copied_bytes += copy_bytes;
736  } while (copied_bytes < nbytes);
737  }
738 
739  return copied_bytes;
740 }
#define Min(x, y)
Definition: c.h:937

References CopyLoadRawBuf(), generate_unaccent_rules::dest, Min, CopyFromStateData::raw_buf, RAW_BUF_BYTES, CopyFromStateData::raw_buf_index, and CopyFromStateData::raw_reached_eof.

Referenced by CopyGetInt16(), CopyGetInt32(), CopyReadBinaryAttribute(), NextCopyFrom(), and ReceiveCopyBinaryHeader().

◆ CopyReadLine()

static bool CopyReadLine ( CopyFromState  cstate)
static

Definition at line 1037 of file copyfromparse.c.

1038 {
1039  bool result;
1040 
1041  resetStringInfo(&cstate->line_buf);
1042  cstate->line_buf_valid = false;
1043 
1044  /* Parse data and transfer into line_buf */
1045  result = CopyReadLineText(cstate);
1046 
1047  if (result)
1048  {
1049  /*
1050  * Reached EOF. In protocol version 3, we should ignore anything
1051  * after \. up to the protocol end of copy data. (XXX maybe better
1052  * not to treat \. as special?)
1053  */
1054  if (cstate->copy_src == COPY_FRONTEND)
1055  {
1056  int inbytes;
1057 
1058  do
1059  {
1060  inbytes = CopyGetData(cstate, cstate->input_buf,
1061  1, INPUT_BUF_SIZE);
1062  } while (inbytes > 0);
1063  cstate->input_buf_index = 0;
1064  cstate->input_buf_len = 0;
1065  cstate->raw_buf_index = 0;
1066  cstate->raw_buf_len = 0;
1067  }
1068  }
1069  else
1070  {
1071  /*
1072  * If we didn't hit EOF, then we must have transferred the EOL marker
1073  * to line_buf along with the data. Get rid of it.
1074  */
1075  switch (cstate->eol_type)
1076  {
1077  case EOL_NL:
1078  Assert(cstate->line_buf.len >= 1);
1079  Assert(cstate->line_buf.data[cstate->line_buf.len - 1] == '\n');
1080  cstate->line_buf.len--;
1081  cstate->line_buf.data[cstate->line_buf.len] = '\0';
1082  break;
1083  case EOL_CR:
1084  Assert(cstate->line_buf.len >= 1);
1085  Assert(cstate->line_buf.data[cstate->line_buf.len - 1] == '\r');
1086  cstate->line_buf.len--;
1087  cstate->line_buf.data[cstate->line_buf.len] = '\0';
1088  break;
1089  case EOL_CRNL:
1090  Assert(cstate->line_buf.len >= 2);
1091  Assert(cstate->line_buf.data[cstate->line_buf.len - 2] == '\r');
1092  Assert(cstate->line_buf.data[cstate->line_buf.len - 1] == '\n');
1093  cstate->line_buf.len -= 2;
1094  cstate->line_buf.data[cstate->line_buf.len] = '\0';
1095  break;
1096  case EOL_UNKNOWN:
1097  /* shouldn't get here */
1098  Assert(false);
1099  break;
1100  }
1101  }
1102 
1103  /* Now it's safe to use the buffer in error messages */
1104  cstate->line_buf_valid = true;
1105 
1106  return result;
1107 }
@ EOL_CR
@ EOL_CRNL
@ EOL_UNKNOWN
@ EOL_NL
static bool CopyReadLineText(CopyFromState cstate)

References Assert(), COPY_FRONTEND, CopyFromStateData::copy_src, CopyGetData(), CopyReadLineText(), StringInfoData::data, EOL_CR, EOL_CRNL, EOL_NL, CopyFromStateData::eol_type, EOL_UNKNOWN, CopyFromStateData::input_buf, CopyFromStateData::input_buf_index, CopyFromStateData::input_buf_len, INPUT_BUF_SIZE, StringInfoData::len, CopyFromStateData::line_buf, CopyFromStateData::line_buf_valid, CopyFromStateData::raw_buf_index, CopyFromStateData::raw_buf_len, and resetStringInfo().

Referenced by NextCopyFromRawFields().

◆ CopyReadLineText()

static bool CopyReadLineText ( CopyFromState  cstate)
static

Definition at line 1113 of file copyfromparse.c.

1114 {
1115  char *copy_input_buf;
1116  int input_buf_ptr;
1117  int copy_buf_len;
1118  bool need_data = false;
1119  bool hit_eof = false;
1120  bool result = false;
1121 
1122  /* CSV variables */
1123  bool first_char_in_line = true;
1124  bool in_quote = false,
1125  last_was_esc = false;
1126  char quotec = '\0';
1127  char escapec = '\0';
1128 
1129  if (cstate->opts.csv_mode)
1130  {
1131  quotec = cstate->opts.quote[0];
1132  escapec = cstate->opts.escape[0];
1133  /* ignore special escape processing if it's the same as quotec */
1134  if (quotec == escapec)
1135  escapec = '\0';
1136  }
1137 
1138  /*
1139  * The objective of this loop is to transfer the entire next input line
1140  * into line_buf. Hence, we only care for detecting newlines (\r and/or
1141  * \n) and the end-of-copy marker (\.).
1142  *
1143  * In CSV mode, \r and \n inside a quoted field are just part of the data
1144  * value and are put in line_buf. We keep just enough state to know if we
1145  * are currently in a quoted field or not.
1146  *
1147  * These four characters, and the CSV escape and quote characters, are
1148  * assumed the same in frontend and backend encodings.
1149  *
1150  * The input has already been converted to the database encoding. All
1151  * supported server encodings have the property that all bytes in a
1152  * multi-byte sequence have the high bit set, so a multibyte character
1153  * cannot contain any newline or escape characters embedded in the
1154  * multibyte sequence. Therefore, we can process the input byte-by-byte,
1155  * regardless of the encoding.
1156  *
1157  * For speed, we try to move data from input_buf to line_buf in chunks
1158  * rather than one character at a time. input_buf_ptr points to the next
1159  * character to examine; any characters from input_buf_index to
1160  * input_buf_ptr have been determined to be part of the line, but not yet
1161  * transferred to line_buf.
1162  *
1163  * For a little extra speed within the loop, we copy input_buf and
1164  * input_buf_len into local variables.
1165  */
1166  copy_input_buf = cstate->input_buf;
1167  input_buf_ptr = cstate->input_buf_index;
1168  copy_buf_len = cstate->input_buf_len;
1169 
1170  for (;;)
1171  {
1172  int prev_raw_ptr;
1173  char c;
1174 
1175  /*
1176  * Load more data if needed.
1177  *
1178  * TODO: We could just force four bytes of read-ahead and avoid the
1179  * many calls to IF_NEED_REFILL_AND_NOT_EOF_CONTINUE(). That was
1180  * unsafe with the old v2 COPY protocol, but we don't support that
1181  * anymore.
1182  */
1183  if (input_buf_ptr >= copy_buf_len || need_data)
1184  {
1186 
1187  CopyLoadInputBuf(cstate);
1188  /* update our local variables */
1189  hit_eof = cstate->input_reached_eof;
1190  input_buf_ptr = cstate->input_buf_index;
1191  copy_buf_len = cstate->input_buf_len;
1192 
1193  /*
1194  * If we are completely out of data, break out of the loop,
1195  * reporting EOF.
1196  */
1197  if (INPUT_BUF_BYTES(cstate) <= 0)
1198  {
1199  result = true;
1200  break;
1201  }
1202  need_data = false;
1203  }
1204 
1205  /* OK to fetch a character */
1206  prev_raw_ptr = input_buf_ptr;
1207  c = copy_input_buf[input_buf_ptr++];
1208 
1209  if (cstate->opts.csv_mode)
1210  {
1211  /*
1212  * If character is '\\' or '\r', we may need to look ahead below.
1213  * Force fetch of the next character if we don't already have it.
1214  * We need to do this before changing CSV state, in case one of
1215  * these characters is also the quote or escape character.
1216  */
1217  if (c == '\\' || c == '\r')
1218  {
1220  }
1221 
1222  /*
1223  * Dealing with quotes and escapes here is mildly tricky. If the
1224  * quote char is also the escape char, there's no problem - we
1225  * just use the char as a toggle. If they are different, we need
1226  * to ensure that we only take account of an escape inside a
1227  * quoted field and immediately preceding a quote char, and not
1228  * the second in an escape-escape sequence.
1229  */
1230  if (in_quote && c == escapec)
1231  last_was_esc = !last_was_esc;
1232  if (c == quotec && !last_was_esc)
1233  in_quote = !in_quote;
1234  if (c != escapec)
1235  last_was_esc = false;
1236 
1237  /*
1238  * Updating the line count for embedded CR and/or LF chars is
1239  * necessarily a little fragile - this test is probably about the
1240  * best we can do. (XXX it's arguable whether we should do this
1241  * at all --- is cur_lineno a physical or logical count?)
1242  */
1243  if (in_quote && c == (cstate->eol_type == EOL_NL ? '\n' : '\r'))
1244  cstate->cur_lineno++;
1245  }
1246 
1247  /* Process \r */
1248  if (c == '\r' && (!cstate->opts.csv_mode || !in_quote))
1249  {
1250  /* Check for \r\n on first line, _and_ handle \r\n. */
1251  if (cstate->eol_type == EOL_UNKNOWN ||
1252  cstate->eol_type == EOL_CRNL)
1253  {
1254  /*
1255  * If need more data, go back to loop top to load it.
1256  *
1257  * Note that if we are at EOF, c will wind up as '\0' because
1258  * of the guaranteed pad of input_buf.
1259  */
1261 
1262  /* get next char */
1263  c = copy_input_buf[input_buf_ptr];
1264 
1265  if (c == '\n')
1266  {
1267  input_buf_ptr++; /* eat newline */
1268  cstate->eol_type = EOL_CRNL; /* in case not set yet */
1269  }
1270  else
1271  {
1272  /* found \r, but no \n */
1273  if (cstate->eol_type == EOL_CRNL)
1274  ereport(ERROR,
1275  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1276  !cstate->opts.csv_mode ?
1277  errmsg("literal carriage return found in data") :
1278  errmsg("unquoted carriage return found in data"),
1279  !cstate->opts.csv_mode ?
1280  errhint("Use \"\\r\" to represent carriage return.") :
1281  errhint("Use quoted CSV field to represent carriage return.")));
1282 
1283  /*
1284  * if we got here, it is the first line and we didn't find
1285  * \n, so don't consume the peeked character
1286  */
1287  cstate->eol_type = EOL_CR;
1288  }
1289  }
1290  else if (cstate->eol_type == EOL_NL)
1291  ereport(ERROR,
1292  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1293  !cstate->opts.csv_mode ?
1294  errmsg("literal carriage return found in data") :
1295  errmsg("unquoted carriage return found in data"),
1296  !cstate->opts.csv_mode ?
1297  errhint("Use \"\\r\" to represent carriage return.") :
1298  errhint("Use quoted CSV field to represent carriage return.")));
1299  /* If reach here, we have found the line terminator */
1300  break;
1301  }
1302 
1303  /* Process \n */
1304  if (c == '\n' && (!cstate->opts.csv_mode || !in_quote))
1305  {
1306  if (cstate->eol_type == EOL_CR || cstate->eol_type == EOL_CRNL)
1307  ereport(ERROR,
1308  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1309  !cstate->opts.csv_mode ?
1310  errmsg("literal newline found in data") :
1311  errmsg("unquoted newline found in data"),
1312  !cstate->opts.csv_mode ?
1313  errhint("Use \"\\n\" to represent newline.") :
1314  errhint("Use quoted CSV field to represent newline.")));
1315  cstate->eol_type = EOL_NL; /* in case not set yet */
1316  /* If reach here, we have found the line terminator */
1317  break;
1318  }
1319 
1320  /*
1321  * In CSV mode, we only recognize \. alone on a line. This is because
1322  * \. is a valid CSV data value.
1323  */
1324  if (c == '\\' && (!cstate->opts.csv_mode || first_char_in_line))
1325  {
1326  char c2;
1327 
1330 
1331  /* -----
1332  * get next character
1333  * Note: we do not change c so if it isn't \., we can fall
1334  * through and continue processing.
1335  * -----
1336  */
1337  c2 = copy_input_buf[input_buf_ptr];
1338 
1339  if (c2 == '.')
1340  {
1341  input_buf_ptr++; /* consume the '.' */
1342 
1343  /*
1344  * Note: if we loop back for more data here, it does not
1345  * matter that the CSV state change checks are re-executed; we
1346  * will come back here with no important state changed.
1347  */
1348  if (cstate->eol_type == EOL_CRNL)
1349  {
1350  /* Get the next character */
1352  /* if hit_eof, c2 will become '\0' */
1353  c2 = copy_input_buf[input_buf_ptr++];
1354 
1355  if (c2 == '\n')
1356  {
1357  if (!cstate->opts.csv_mode)
1358  ereport(ERROR,
1359  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1360  errmsg("end-of-copy marker does not match previous newline style")));
1361  else
1363  }
1364  else if (c2 != '\r')
1365  {
1366  if (!cstate->opts.csv_mode)
1367  ereport(ERROR,
1368  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1369  errmsg("end-of-copy marker corrupt")));
1370  else
1372  }
1373  }
1374 
1375  /* Get the next character */
1377  /* if hit_eof, c2 will become '\0' */
1378  c2 = copy_input_buf[input_buf_ptr++];
1379 
1380  if (c2 != '\r' && c2 != '\n')
1381  {
1382  if (!cstate->opts.csv_mode)
1383  ereport(ERROR,
1384  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1385  errmsg("end-of-copy marker corrupt")));
1386  else
1388  }
1389 
1390  if ((cstate->eol_type == EOL_NL && c2 != '\n') ||
1391  (cstate->eol_type == EOL_CRNL && c2 != '\n') ||
1392  (cstate->eol_type == EOL_CR && c2 != '\r'))
1393  {
1394  ereport(ERROR,
1395  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1396  errmsg("end-of-copy marker does not match previous newline style")));
1397  }
1398 
1399  /*
1400  * Transfer only the data before the \. into line_buf, then
1401  * discard the data and the \. sequence.
1402  */
1403  if (prev_raw_ptr > cstate->input_buf_index)
1405  cstate->input_buf + cstate->input_buf_index,
1406  prev_raw_ptr - cstate->input_buf_index);
1407  cstate->input_buf_index = input_buf_ptr;
1408  result = true; /* report EOF */
1409  break;
1410  }
1411  else if (!cstate->opts.csv_mode)
1412  {
1413  /*
1414  * If we are here, it means we found a backslash followed by
1415  * something other than a period. In non-CSV mode, anything
1416  * after a backslash is special, so we skip over that second
1417  * character too. If we didn't do that \\. would be
1418  * considered an eof-of copy, while in non-CSV mode it is a
1419  * literal backslash followed by a period. In CSV mode,
1420  * backslashes are not special, so we want to process the
1421  * character after the backslash just like a normal character,
1422  * so we don't increment in those cases.
1423  */
1424  input_buf_ptr++;
1425  }
1426  }
1427 
1428  /*
1429  * This label is for CSV cases where \. appears at the start of a
1430  * line, but there is more text after it, meaning it was a data value.
1431  * We are more strict for \. in CSV mode because \. could be a data
1432  * value, while in non-CSV mode, \. cannot be a data value.
1433  */
1434 not_end_of_copy:
1435  first_char_in_line = false;
1436  } /* end of outer loop */
1437 
1438  /*
1439  * Transfer any still-uncopied data to line_buf.
1440  */
1442 
1443  return result;
1444 }
#define REFILL_LINEBUF
#define NO_END_OF_COPY_GOTO
static void CopyLoadInputBuf(CopyFromState cstate)
#define IF_NEED_REFILL_AND_EOF_BREAK(extralen)
#define IF_NEED_REFILL_AND_NOT_EOF_CONTINUE(extralen)
Definition: copyfromparse.c:98
int errhint(const char *fmt,...)
Definition: elog.c:1153
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227
bool csv_mode
Definition: copy.h:45

References appendBinaryStringInfo(), CopyLoadInputBuf(), CopyFormatOptions::csv_mode, CopyFromStateData::cur_lineno, EOL_CR, EOL_CRNL, EOL_NL, CopyFromStateData::eol_type, EOL_UNKNOWN, ereport, errcode(), errhint(), errmsg(), ERROR, CopyFormatOptions::escape, IF_NEED_REFILL_AND_EOF_BREAK, IF_NEED_REFILL_AND_NOT_EOF_CONTINUE, CopyFromStateData::input_buf, INPUT_BUF_BYTES, CopyFromStateData::input_buf_index, CopyFromStateData::input_buf_len, CopyFromStateData::input_reached_eof, CopyFromStateData::line_buf, NO_END_OF_COPY_GOTO, CopyFromStateData::opts, CopyFormatOptions::quote, and REFILL_LINEBUF.

Referenced by CopyReadLine().

◆ GetDecimalFromHex()

static int GetDecimalFromHex ( char  hex)
static

Definition at line 1450 of file copyfromparse.c.

1451 {
1452  if (isdigit((unsigned char) hex))
1453  return hex - '0';
1454  else
1455  return tolower((unsigned char) hex) - 'a' + 10;
1456 }

Referenced by CopyReadAttributesText().

◆ NextCopyFrom()

bool NextCopyFrom ( CopyFromState  cstate,
ExprContext econtext,
Datum values,
bool nulls 
)

Definition at line 853 of file copyfromparse.c.

855 {
856  TupleDesc tupDesc;
857  AttrNumber num_phys_attrs,
858  attr_count,
859  num_defaults = cstate->num_defaults;
860  FmgrInfo *in_functions = cstate->in_functions;
861  Oid *typioparams = cstate->typioparams;
862  int i;
863  int *defmap = cstate->defmap;
864  ExprState **defexprs = cstate->defexprs;
865 
866  tupDesc = RelationGetDescr(cstate->rel);
867  num_phys_attrs = tupDesc->natts;
868  attr_count = list_length(cstate->attnumlist);
869 
870  /* Initialize all values for row to NULL */
871  MemSet(values, 0, num_phys_attrs * sizeof(Datum));
872  MemSet(nulls, true, num_phys_attrs * sizeof(bool));
873 
874  if (!cstate->opts.binary)
875  {
876  char **field_strings;
877  ListCell *cur;
878  int fldct;
879  int fieldno;
880  char *string;
881 
882  /* read raw fields in the next line */
883  if (!NextCopyFromRawFields(cstate, &field_strings, &fldct))
884  return false;
885 
886  /* check for overflowing fields */
887  if (attr_count > 0 && fldct > attr_count)
888  ereport(ERROR,
889  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
890  errmsg("extra data after last expected column")));
891 
892  fieldno = 0;
893 
894  /* Loop to read the user attributes on the line. */
895  foreach(cur, cstate->attnumlist)
896  {
897  int attnum = lfirst_int(cur);
898  int m = attnum - 1;
899  Form_pg_attribute att = TupleDescAttr(tupDesc, m);
900 
901  if (fieldno >= fldct)
902  ereport(ERROR,
903  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
904  errmsg("missing data for column \"%s\"",
905  NameStr(att->attname))));
906  string = field_strings[fieldno++];
907 
908  if (cstate->convert_select_flags &&
909  !cstate->convert_select_flags[m])
910  {
911  /* ignore input field, leaving column as NULL */
912  continue;
913  }
914 
915  if (cstate->opts.csv_mode)
916  {
917  if (string == NULL &&
918  cstate->opts.force_notnull_flags[m])
919  {
920  /*
921  * FORCE_NOT_NULL option is set and column is NULL -
922  * convert it to the NULL string.
923  */
924  string = cstate->opts.null_print;
925  }
926  else if (string != NULL && cstate->opts.force_null_flags[m]
927  && strcmp(string, cstate->opts.null_print) == 0)
928  {
929  /*
930  * FORCE_NULL option is set and column matches the NULL
931  * string. It must have been quoted, or otherwise the
932  * string would already have been set to NULL. Convert it
933  * to NULL as specified.
934  */
935  string = NULL;
936  }
937  }
938 
939  cstate->cur_attname = NameStr(att->attname);
940  cstate->cur_attval = string;
941  values[m] = InputFunctionCall(&in_functions[m],
942  string,
943  typioparams[m],
944  att->atttypmod);
945  if (string != NULL)
946  nulls[m] = false;
947  cstate->cur_attname = NULL;
948  cstate->cur_attval = NULL;
949  }
950 
951  Assert(fieldno == attr_count);
952  }
953  else
954  {
955  /* binary */
956  int16 fld_count;
957  ListCell *cur;
958 
959  cstate->cur_lineno++;
960 
961  if (!CopyGetInt16(cstate, &fld_count))
962  {
963  /* EOF detected (end of file, or protocol-level EOF) */
964  return false;
965  }
966 
967  if (fld_count == -1)
968  {
969  /*
970  * Received EOF marker. Wait for the protocol-level EOF, and
971  * complain if it doesn't come immediately. In COPY FROM STDIN,
972  * this ensures that we correctly handle CopyFail, if client
973  * chooses to send that now. When copying from file, we could
974  * ignore the rest of the file like in text mode, but we choose to
975  * be consistent with the COPY FROM STDIN case.
976  */
977  char dummy;
978 
979  if (CopyReadBinaryData(cstate, &dummy, 1) > 0)
980  ereport(ERROR,
981  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
982  errmsg("received copy data after EOF marker")));
983  return false;
984  }
985 
986  if (fld_count != attr_count)
987  ereport(ERROR,
988  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
989  errmsg("row field count is %d, expected %d",
990  (int) fld_count, attr_count)));
991 
992  foreach(cur, cstate->attnumlist)
993  {
994  int attnum = lfirst_int(cur);
995  int m = attnum - 1;
996  Form_pg_attribute att = TupleDescAttr(tupDesc, m);
997 
998  cstate->cur_attname = NameStr(att->attname);
999  values[m] = CopyReadBinaryAttribute(cstate,
1000  &in_functions[m],
1001  typioparams[m],
1002  att->atttypmod,
1003  &nulls[m]);
1004  cstate->cur_attname = NULL;
1005  }
1006  }
1007 
1008  /*
1009  * Now compute and insert any defaults available for the columns not
1010  * provided by the input data. Anything not processed here or above will
1011  * remain NULL.
1012  */
1013  for (i = 0; i < num_defaults; i++)
1014  {
1015  /*
1016  * The caller must supply econtext and have switched into the
1017  * per-tuple memory context in it.
1018  */
1019  Assert(econtext != NULL);
1021 
1022  values[defmap[i]] = ExecEvalExpr(defexprs[i], econtext,
1023  &nulls[defmap[i]]);
1024  }
1025 
1026  return true;
1027 }
int16 AttrNumber
Definition: attnum.h:21
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define NameStr(name)
Definition: c.h:682
#define MemSet(start, val, len)
Definition: c.h:953
static bool CopyGetInt16(CopyFromState cstate, int16 *val)
static Datum CopyReadBinaryAttribute(CopyFromState cstate, FmgrInfo *flinfo, Oid typioparam, int32 typmod, bool *isnull)
bool NextCopyFromRawFields(CopyFromState cstate, char ***fields, int *nfields)
struct cursor * cur
Definition: ecpg.c:28
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:318
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1515
int i
Definition: isn.c:73
MemoryContext CurrentMemoryContext
Definition: mcxt.c:124
int16 attnum
Definition: pg_attribute.h:83
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
static int list_length(const List *l)
Definition: pg_list.h:150
#define lfirst_int(lc)
Definition: pg_list.h:171
unsigned int Oid
Definition: postgres_ext.h:31
char string[11]
Definition: preproc-type.c:52
#define RelationGetDescr(relation)
Definition: rel.h:527
bool binary
Definition: copy.h:43
bool * force_notnull_flags
Definition: copy.h:57
bool * force_null_flags
Definition: copy.h:59
ExprState ** defexprs
const char * cur_attval
const char * cur_attname
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:255
Definition: fmgr.h:57
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92

References Assert(), attnum, CopyFromStateData::attnumlist, CopyFormatOptions::binary, CopyFromStateData::convert_select_flags, CopyGetInt16(), CopyReadBinaryAttribute(), CopyReadBinaryData(), CopyFormatOptions::csv_mode, cur, CopyFromStateData::cur_attname, CopyFromStateData::cur_attval, CopyFromStateData::cur_lineno, CurrentMemoryContext, CopyFromStateData::defexprs, CopyFromStateData::defmap, ExprContext::ecxt_per_tuple_memory, ereport, errcode(), errmsg(), ERROR, ExecEvalExpr(), CopyFormatOptions::force_notnull_flags, CopyFormatOptions::force_null_flags, i, CopyFromStateData::in_functions, InputFunctionCall(), lfirst_int, list_length(), MemSet, NameStr, TupleDescData::natts, NextCopyFromRawFields(), CopyFormatOptions::null_print, CopyFromStateData::num_defaults, CopyFromStateData::opts, CopyFromStateData::rel, RelationGetDescr, TupleDescAttr, CopyFromStateData::typioparams, and values.

Referenced by CopyFrom(), file_acquire_sample_rows(), and fileIterateForeignScan().

◆ NextCopyFromRawFields()

bool NextCopyFromRawFields ( CopyFromState  cstate,
char ***  fields,
int *  nfields 
)

Definition at line 754 of file copyfromparse.c.

755 {
756  int fldct;
757  bool done;
758 
759  /* only available for text or csv input */
760  Assert(!cstate->opts.binary);
761 
762  /* on input check that the header line is correct if needed */
763  if (cstate->cur_lineno == 0 && cstate->opts.header_line)
764  {
765  ListCell *cur;
766  TupleDesc tupDesc;
767 
768  tupDesc = RelationGetDescr(cstate->rel);
769 
770  cstate->cur_lineno++;
771  done = CopyReadLine(cstate);
772 
773  if (cstate->opts.header_line == COPY_HEADER_MATCH)
774  {
775  int fldnum;
776 
777  if (cstate->opts.csv_mode)
778  fldct = CopyReadAttributesCSV(cstate);
779  else
780  fldct = CopyReadAttributesText(cstate);
781 
782  if (fldct != list_length(cstate->attnumlist))
783  ereport(ERROR,
784  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
785  errmsg("wrong number of fields in header line: got %d, expected %d",
786  fldct, list_length(cstate->attnumlist))));
787 
788  fldnum = 0;
789  foreach(cur, cstate->attnumlist)
790  {
791  int attnum = lfirst_int(cur);
792  char *colName;
793  Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
794 
795  Assert(fldnum < cstate->max_fields);
796 
797  colName = cstate->raw_fields[fldnum++];
798  if (colName == NULL)
799  ereport(ERROR,
800  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
801  errmsg("column name mismatch in header line field %d: got null value (\"%s\"), expected \"%s\"",
802  fldnum, cstate->opts.null_print, NameStr(attr->attname))));
803 
804  if (namestrcmp(&attr->attname, colName) != 0)
805  {
806  ereport(ERROR,
807  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
808  errmsg("column name mismatch in header line field %d: got \"%s\", expected \"%s\"",
809  fldnum, colName, NameStr(attr->attname))));
810  }
811  }
812  }
813 
814  if (done)
815  return false;
816  }
817 
818  cstate->cur_lineno++;
819 
820  /* Actually read the line into memory here */
821  done = CopyReadLine(cstate);
822 
823  /*
824  * EOF at start of line means we're done. If we see EOF after some
825  * characters, we act as though it was newline followed by EOF, ie,
826  * process the line and then exit loop on next iteration.
827  */
828  if (done && cstate->line_buf.len == 0)
829  return false;
830 
831  /* Parse the line into de-escaped field values */
832  if (cstate->opts.csv_mode)
833  fldct = CopyReadAttributesCSV(cstate);
834  else
835  fldct = CopyReadAttributesText(cstate);
836 
837  *fields = cstate->raw_fields;
838  *nfields = fldct;
839  return true;
840 }
static int CopyReadAttributesCSV(CopyFromState cstate)
static int CopyReadAttributesText(CopyFromState cstate)
static bool CopyReadLine(CopyFromState cstate)
@ COPY_HEADER_MATCH
Definition: copy.h:30
int namestrcmp(Name name, const char *str)
Definition: name.c:247
CopyHeaderChoice header_line
Definition: copy.h:46

References Assert(), attnum, CopyFromStateData::attnumlist, CopyFormatOptions::binary, COPY_HEADER_MATCH, CopyReadAttributesCSV(), CopyReadAttributesText(), CopyReadLine(), CopyFormatOptions::csv_mode, cur, CopyFromStateData::cur_lineno, ereport, errcode(), errmsg(), ERROR, CopyFormatOptions::header_line, StringInfoData::len, lfirst_int, CopyFromStateData::line_buf, list_length(), NameStr, namestrcmp(), CopyFormatOptions::null_print, CopyFromStateData::opts, CopyFromStateData::raw_fields, CopyFromStateData::rel, RelationGetDescr, and TupleDescAttr.

Referenced by NextCopyFrom().

◆ ReceiveCopyBegin()

void ReceiveCopyBegin ( CopyFromState  cstate)

Definition at line 170 of file copyfromparse.c.

171 {
173  int natts = list_length(cstate->attnumlist);
174  int16 format = (cstate->opts.binary ? 1 : 0);
175  int i;
176 
177  pq_beginmessage(&buf, 'G');
178  pq_sendbyte(&buf, format); /* overall format */
179  pq_sendint16(&buf, natts);
180  for (i = 0; i < natts; i++)
181  pq_sendint16(&buf, format); /* per-column formats */
182  pq_endmessage(&buf);
183  cstate->copy_src = COPY_FRONTEND;
184  cstate->fe_msgbuf = makeStringInfo();
185  /* We *must* flush here to ensure FE knows it can send. */
186  pq_flush();
187 }
#define pq_flush()
Definition: libpq.h:46
static char format
void pq_endmessage(StringInfo buf)
Definition: pqformat.c:298
void pq_beginmessage(StringInfo buf, char msgtype)
Definition: pqformat.c:87
static void pq_sendbyte(StringInfo buf, uint8 byt)
Definition: pqformat.h:161
static void pq_sendint16(StringInfo buf, uint16 i)
Definition: pqformat.h:137
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41

References CopyFromStateData::attnumlist, CopyFormatOptions::binary, buf, COPY_FRONTEND, CopyFromStateData::copy_src, CopyFromStateData::fe_msgbuf, format, i, list_length(), makeStringInfo(), CopyFromStateData::opts, pq_beginmessage(), pq_endmessage(), pq_flush, pq_sendbyte(), and pq_sendint16().

Referenced by BeginCopyFrom().

◆ ReceiveCopyBinaryHeader()

void ReceiveCopyBinaryHeader ( CopyFromState  cstate)

Definition at line 190 of file copyfromparse.c.

191 {
192  char readSig[11];
193  int32 tmp;
194 
195  /* Signature */
196  if (CopyReadBinaryData(cstate, readSig, 11) != 11 ||
197  memcmp(readSig, BinarySignature, 11) != 0)
198  ereport(ERROR,
199  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
200  errmsg("COPY file signature not recognized")));
201  /* Flags field */
202  if (!CopyGetInt32(cstate, &tmp))
203  ereport(ERROR,
204  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
205  errmsg("invalid COPY file header (missing flags)")));
206  if ((tmp & (1 << 16)) != 0)
207  ereport(ERROR,
208  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
209  errmsg("invalid COPY file header (WITH OIDS)")));
210  tmp &= ~(1 << 16);
211  if ((tmp >> 16) != 0)
212  ereport(ERROR,
213  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
214  errmsg("unrecognized critical flags in COPY file header")));
215  /* Header extension length */
216  if (!CopyGetInt32(cstate, &tmp) ||
217  tmp < 0)
218  ereport(ERROR,
219  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
220  errmsg("invalid COPY file header (missing length)")));
221  /* Skip extension header, if present */
222  while (tmp-- > 0)
223  {
224  if (CopyReadBinaryData(cstate, readSig, 1) != 1)
225  ereport(ERROR,
226  (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
227  errmsg("invalid COPY file header (wrong length)")));
228  }
229 }
static const char BinarySignature[11]

References BinarySignature, CopyGetInt32(), CopyReadBinaryData(), ereport, errcode(), errmsg(), and ERROR.

Referenced by BeginCopyFrom().

Variable Documentation

◆ BinarySignature

const char BinarySignature[11] = "PGCOPY\n\377\r\n\0"
static

Definition at line 148 of file copyfromparse.c.

Referenced by ReceiveCopyBinaryHeader().