Index: src/backend/commands/copy.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/copy.c,v retrieving revision 1.245 diff -c -r1.245 copy.c *** src/backend/commands/copy.c 2 Jun 2005 01:21:22 -0000 1.245 --- src/backend/commands/copy.c 27 Jun 2005 18:27:36 -0000 *************** *** 1,3 **** --- 1,4 ---- + /*------------------------------------------------------------------------- * * copy.c *************** *** 101,109 **** /* these are just for error messages, see copy_in_error_callback */ static bool copy_binary; /* is it a binary copy? */ ! static const char *copy_relname; /* table name for error messages */ static int copy_lineno; /* line number for error messages */ ! static const char *copy_attname; /* current att for error messages */ /* --- 102,110 ---- /* these are just for error messages, see copy_in_error_callback */ static bool copy_binary; /* is it a binary copy? */ ! static const char *copy_relname; /* table name for error messages */ static int copy_lineno; /* line number for error messages */ ! static const char *copy_attname; /* current att for error messages */ /* *************** *** 130,154 **** /* non-export function prototypes */ static void DoCopyTo(Relation rel, List *attnumlist, bool binary, bool oids, ! char *delim, char *null_print, bool csv_mode, char *quote, ! char *escape, List *force_quote_atts, bool header_line, bool fe_copy); static void CopyTo(Relation rel, List *attnumlist, bool binary, bool oids, ! char *delim, char *null_print, bool csv_mode, char *quote, char *escape, ! List *force_quote_atts, bool header_line); static void CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, ! char *delim, char *null_print, bool csv_mode, char *quote, char *escape, ! List *force_notnull_atts, bool header_line); ! static bool CopyReadLine(char * quote, char * escape); static char *CopyReadAttribute(const char *delim, const char *null_print, ! CopyReadResult *result, bool *isnull); static char *CopyReadAttributeCSV(const char *delim, const char *null_print, ! char *quote, char *escape, ! CopyReadResult *result, bool *isnull); static Datum CopyReadBinaryAttribute(int column_no, FmgrInfo *flinfo, ! Oid typioparam, bool *isnull); static void CopyAttributeOut(char *string, char *delim); static void CopyAttributeOutCSV(char *string, char *delim, char *quote, ! char *escape, bool force_quote); static List *CopyGetAttnums(Relation rel, List *attnamelist); static void limit_printout_length(StringInfo buf); --- 131,156 ---- /* non-export function prototypes */ static void DoCopyTo(Relation rel, List *attnumlist, bool binary, bool oids, ! char *delim, char *null_print, bool csv_mode, char *quote, ! char *escape, List *force_quote_atts, bool header_line, ! bool fe_copy); static void CopyTo(Relation rel, List *attnumlist, bool binary, bool oids, ! char *delim, char *null_print, bool csv_mode, char *quote, ! char *escape, List *force_quote_atts, bool header_line); static void CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, ! char *delim, char *null_print, bool csv_mode, char *quote, ! char *escape, List *force_notnull_atts, bool header_line); ! static bool CopyReadLine(char *quote, char *escape); static char *CopyReadAttribute(const char *delim, const char *null_print, ! CopyReadResult *result, bool *isnull); static char *CopyReadAttributeCSV(const char *delim, const char *null_print, ! char *quote, char *escape, ! CopyReadResult *result, bool *isnull); static Datum CopyReadBinaryAttribute(int column_no, FmgrInfo *flinfo, ! Oid typioparam, bool *isnull); static void CopyAttributeOut(char *string, char *delim); static void CopyAttributeOutCSV(char *string, char *delim, char *quote, ! char *escape, bool force_quote); static List *CopyGetAttnums(Relation rel, List *attnamelist); static void limit_printout_length(StringInfo buf); *************** *** 181,187 **** { if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3) { ! /* new way */ StringInfoData buf; int16 format = (binary ? 1 : 0); int i; --- 183,191 ---- { if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3) { ! /* ! * new way ! */ StringInfoData buf; int16 format = (binary ? 1 : 0); int i; *************** *** 197,221 **** } else if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2) { ! /* old way */ if (binary) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg("COPY BINARY is not supported to stdout or from stdin"))); pq_putemptymessage('H'); ! /* grottiness needed for old COPY OUT protocol */ pq_startcopyout(); copy_dest = COPY_OLD_FE; } else { ! /* very old way */ if (binary) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg("COPY BINARY is not supported to stdout or from stdin"))); pq_putemptymessage('B'); ! /* grottiness needed for old COPY OUT protocol */ pq_startcopyout(); copy_dest = COPY_OLD_FE; } --- 201,235 ---- } else if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2) { ! /* ! * old way ! */ if (binary) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg ! ("COPY BINARY is not supported to stdout or from stdin"))); pq_putemptymessage('H'); ! /* ! * grottiness needed for old COPY OUT protocol ! */ pq_startcopyout(); copy_dest = COPY_OLD_FE; } else { ! /* ! * very old way ! */ if (binary) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg ! ("COPY BINARY is not supported to stdout or from stdin"))); pq_putemptymessage('B'); ! /* ! * grottiness needed for old COPY OUT protocol ! */ pq_startcopyout(); copy_dest = COPY_OLD_FE; } *************** *** 226,232 **** { if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3) { ! /* new way */ StringInfoData buf; int16 format = (binary ? 1 : 0); int i; --- 240,248 ---- { if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3) { ! /* ! * new way ! */ StringInfoData buf; int16 format = (binary ? 1 : 0); int i; *************** *** 242,266 **** } else if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2) { ! /* old way */ if (binary) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg("COPY BINARY is not supported to stdout or from stdin"))); pq_putemptymessage('G'); copy_dest = COPY_OLD_FE; } else { ! /* very old way */ if (binary) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg("COPY BINARY is not supported to stdout or from stdin"))); pq_putemptymessage('D'); copy_dest = COPY_OLD_FE; } ! /* We *must* flush here to ensure FE knows it can send. */ pq_flush(); } --- 258,290 ---- } else if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2) { ! /* ! * old way ! */ if (binary) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg ! ("COPY BINARY is not supported to stdout or from stdin"))); pq_putemptymessage('G'); copy_dest = COPY_OLD_FE; } else { ! /* ! * very old way ! */ if (binary) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg ! ("COPY BINARY is not supported to stdout or from stdin"))); pq_putemptymessage('D'); copy_dest = COPY_OLD_FE; } ! /* ! * We *must* flush here to ensure FE knows it can send. ! */ pq_flush(); } *************** *** 271,290 **** { if (binary) { ! /* Need to flush out file trailer word */ CopySendEndOfRow(true); } else { ! /* Shouldn't have any unsent data */ Assert(copy_msgbuf->len == 0); } ! /* Send Copy Done message */ pq_putemptymessage('c'); } else { ! /* The FE/BE protocol uses \n as newline for all platforms */ CopySendData("\\.\n", 3); pq_endcopyout(false); } --- 295,322 ---- { if (binary) { ! /* ! * Need to flush out file trailer word ! */ CopySendEndOfRow(true); } else { ! /* ! * Shouldn't have any unsent data ! */ Assert(copy_msgbuf->len == 0); } ! /* ! * Send Copy Done message ! */ pq_putemptymessage('c'); } else { ! /* ! * The FE/BE protocol uses \n as newline for all platforms ! */ CopySendData("\\.\n", 3); pq_endcopyout(false); } *************** *** 314,323 **** case COPY_OLD_FE: if (pq_putbytes((char *) databuf, datasize)) { ! /* no hope of recovering connection sync, so FATAL */ ereport(FATAL, (errcode(ERRCODE_CONNECTION_FAILURE), ! errmsg("connection lost during COPY to stdout"))); } break; case COPY_NEW_FE: --- 346,357 ---- case COPY_OLD_FE: if (pq_putbytes((char *) databuf, datasize)) { ! /* ! * no hope of recovering connection sync, so FATAL ! */ ereport(FATAL, (errcode(ERRCODE_CONNECTION_FAILURE), ! errmsg("connection lost during COPY to stdout"))); } break; case COPY_NEW_FE: *************** *** 346,352 **** case COPY_FILE: if (!binary) { ! /* Default line termination depends on platform */ #ifndef WIN32 CopySendChar('\n'); #else --- 380,388 ---- case COPY_FILE: if (!binary) { ! /* ! * Default line termination depends on platform ! */ #ifndef WIN32 CopySendChar('\n'); #else *************** *** 355,371 **** } break; case COPY_OLD_FE: ! /* The FE/BE protocol uses \n as newline for all platforms */ if (!binary) CopySendChar('\n'); break; case COPY_NEW_FE: ! /* The FE/BE protocol uses \n as newline for all platforms */ if (!binary) CopySendChar('\n'); ! /* Dump the accumulated row as one CopyData message */ (void) pq_putmessage('d', copy_msgbuf->data, copy_msgbuf->len); ! /* Reset copy_msgbuf to empty */ copy_msgbuf->len = 0; copy_msgbuf->data[0] = '\0'; break; --- 391,415 ---- } break; case COPY_OLD_FE: ! /* ! * The FE/BE protocol uses \n as newline for all platforms ! */ if (!binary) CopySendChar('\n'); break; case COPY_NEW_FE: ! /* ! * The FE/BE protocol uses \n as newline for all platforms ! */ if (!binary) CopySendChar('\n'); ! /* ! * Dump the accumulated row as one CopyData message ! */ (void) pq_putmessage('d', copy_msgbuf->data, copy_msgbuf->len); ! /* ! * Reset copy_msgbuf to empty ! */ copy_msgbuf->len = 0; copy_msgbuf->data[0] = '\0'; break; *************** *** 397,403 **** case COPY_OLD_FE: if (pq_getbytes((char *) databuf, datasize)) { ! /* Only a \. terminator is legal EOF in old protocol */ ereport(ERROR, (errcode(ERRCODE_CONNECTION_FAILURE), errmsg("unexpected EOF on client connection"))); --- 441,449 ---- case COPY_OLD_FE: if (pq_getbytes((char *) databuf, datasize)) { ! /* ! * Only a \. terminator is legal EOF in old protocol ! */ ereport(ERROR, (errcode(ERRCODE_CONNECTION_FAILURE), errmsg("unexpected EOF on client connection"))); *************** *** 410,441 **** while (copy_msgbuf->cursor >= copy_msgbuf->len) { ! /* Try to receive another message */ int mtype; ! readmessage: mtype = pq_getbyte(); if (mtype == EOF) ereport(ERROR, (errcode(ERRCODE_CONNECTION_FAILURE), ! errmsg("unexpected EOF on client connection"))); if (pq_getmessage(copy_msgbuf, 0)) ereport(ERROR, (errcode(ERRCODE_CONNECTION_FAILURE), ! errmsg("unexpected EOF on client connection"))); switch (mtype) { case 'd': /* CopyData */ break; case 'c': /* CopyDone */ ! /* COPY IN correctly terminated by frontend */ fe_eof = true; return; case 'f': /* CopyFail */ ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED), errmsg("COPY from stdin failed: %s", ! pq_getmsgstring(copy_msgbuf)))); break; case 'H': /* Flush */ case 'S': /* Sync */ --- 456,493 ---- while (copy_msgbuf->cursor >= copy_msgbuf->len) { ! /* ! * Try to receive another message ! */ int mtype; ! readmessage: mtype = pq_getbyte(); if (mtype == EOF) ereport(ERROR, (errcode(ERRCODE_CONNECTION_FAILURE), ! errmsg ! ("unexpected EOF on client connection"))); if (pq_getmessage(copy_msgbuf, 0)) ereport(ERROR, (errcode(ERRCODE_CONNECTION_FAILURE), ! errmsg ! ("unexpected EOF on client connection"))); switch (mtype) { case 'd': /* CopyData */ break; case 'c': /* CopyDone */ ! /* ! * COPY IN correctly terminated by frontend ! */ fe_eof = true; return; case 'f': /* CopyFail */ ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED), errmsg("COPY from stdin failed: %s", ! pq_getmsgstring(copy_msgbuf)))); break; case 'H': /* Flush */ case 'S': /* Sync */ *************** *** 450,457 **** default: ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), ! errmsg("unexpected message type 0x%02X during COPY from stdin", ! mtype))); break; } } --- 502,510 ---- default: ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), ! errmsg ! ("unexpected message type 0x%02X during COPY from stdin", ! mtype))); break; } } *************** *** 480,486 **** ch = pq_getbyte(); if (ch == EOF) { ! /* Only a \. terminator is legal EOF in old protocol */ ereport(ERROR, (errcode(ERRCODE_CONNECTION_FAILURE), errmsg("unexpected EOF on client connection"))); --- 533,541 ---- ch = pq_getbyte(); if (ch == EOF) { ! /* ! * Only a \. terminator is legal EOF in old protocol ! */ ereport(ERROR, (errcode(ERRCODE_CONNECTION_FAILURE), errmsg("unexpected EOF on client connection"))); *************** *** 529,535 **** ch = pq_peekbyte(); if (ch == EOF) { ! /* Only a \. terminator is legal EOF in old protocol */ ereport(ERROR, (errcode(ERRCODE_CONNECTION_FAILURE), errmsg("unexpected EOF on client connection"))); --- 584,592 ---- ch = pq_peekbyte(); if (ch == EOF) { ! /* ! * Only a \. terminator is legal EOF in old protocol ! */ ereport(ERROR, (errcode(ERRCODE_CONNECTION_FAILURE), errmsg("unexpected EOF on client connection"))); *************** *** 565,579 **** case COPY_FILE: if (!pickup) { ! /* We don't want to pick it up - so put it back in there */ ungetc(c, copy_file); } ! /* If we wanted to pick it up, it's already done */ break; case COPY_OLD_FE: if (pickup) { ! /* We want to pick it up */ (void) pq_getbyte(); } --- 622,642 ---- case COPY_FILE: if (!pickup) { ! /* ! * We don't want to pick it up - so put it back in there ! */ ungetc(c, copy_file); } ! /* ! * If we wanted to pick it up, it's already done ! */ break; case COPY_OLD_FE: if (pickup) { ! /* ! * We want to pick it up ! */ (void) pq_getbyte(); } *************** *** 585,594 **** case COPY_NEW_FE: if (!pickup) { ! /* We don't want to pick it up - so put it back in there */ copy_msgbuf->cursor--; } ! /* If we wanted to pick it up, it's already done */ break; } } --- 648,661 ---- case COPY_NEW_FE: if (!pickup) { ! /* ! * We don't want to pick it up - so put it back in there ! */ copy_msgbuf->cursor--; } ! /* ! * If we wanted to pick it up, it's already done ! */ break; } } *************** *** 695,701 **** bool binary = false; bool oids = false; bool csv_mode = false; ! bool header_line = false; char *delim = NULL; char *quote = NULL; char *escape = NULL; --- 762,768 ---- bool binary = false; bool oids = false; bool csv_mode = false; ! bool header_line = false; char *delim = NULL; char *quote = NULL; char *escape = NULL; *************** *** 708,714 **** AclMode required_access = (is_from ? ACL_INSERT : ACL_SELECT); AclResult aclresult; ! /* Extract options from the statement node tree */ foreach(option, stmt->options) { DefElem *defel = (DefElem *) lfirst(option); --- 775,783 ---- AclMode required_access = (is_from ? ACL_INSERT : ACL_SELECT); AclResult aclresult; ! /* ! * Extract options from the statement node tree ! */ foreach(option, stmt->options) { DefElem *defel = (DefElem *) lfirst(option); *************** *** 794,801 **** force_notnull = (List *) defel->arg; } else ! elog(ERROR, "option \"%s\" not recognized", ! defel->defname); } if (binary && delim) --- 863,869 ---- force_notnull = (List *) defel->arg; } else ! elog(ERROR, "option \"%s\" not recognized", defel->defname); } if (binary && delim) *************** *** 813,819 **** (errcode(ERRCODE_SYNTAX_ERROR), errmsg("cannot specify NULL in BINARY mode"))); ! /* Set defaults */ if (!delim) delim = csv_mode ? "," : "\t"; --- 881,889 ---- (errcode(ERRCODE_SYNTAX_ERROR), errmsg("cannot specify NULL in BINARY mode"))); ! /* ! * Set defaults ! */ if (!delim) delim = csv_mode ? "," : "\t"; *************** *** 828,846 **** escape = quote; } ! /* Only single-character delimiter strings are supported. */ if (strlen(delim) != 1) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("COPY delimiter must be a single character"))); ! /* Check header */ if (!csv_mode && header_line) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("COPY HEADER available only in CSV mode"))); ! /* Check quote */ if (!csv_mode && quote != NULL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), --- 898,922 ---- escape = quote; } ! /* ! * Only single-character delimiter strings are supported. ! */ if (strlen(delim) != 1) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("COPY delimiter must be a single character"))); ! /* ! * Check header ! */ if (!csv_mode && header_line) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("COPY HEADER available only in CSV mode"))); ! /* ! * Check quote ! */ if (!csv_mode && quote != NULL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), *************** *** 851,857 **** (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("COPY quote must be a single character"))); ! /* Check escape */ if (!csv_mode && escape != NULL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), --- 927,935 ---- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("COPY quote must be a single character"))); ! /* ! * Check escape ! */ if (!csv_mode && escape != NULL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), *************** *** 862,868 **** (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("COPY escape must be a single character"))); ! /* Check force_quote */ if (!csv_mode && force_quote != NIL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), --- 940,948 ---- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("COPY escape must be a single character"))); ! /* ! * Check force_quote ! */ if (!csv_mode && force_quote != NIL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), *************** *** 870,909 **** if (force_quote != NIL && is_from) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg("COPY force quote only available using COPY TO"))); ! /* Check force_notnull */ if (!csv_mode && force_notnull != NIL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg("COPY force not null available only in CSV mode"))); if (force_notnull != NIL && !is_from) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg("COPY force not null only available using COPY FROM"))); ! /* Don't allow the delimiter to appear in the null string. */ if (strchr(null_print, delim[0]) != NULL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg("COPY delimiter must not appear in the NULL specification"))); ! /* Don't allow the csv quote char to appear in the null string. */ if (csv_mode && strchr(null_print, quote[0]) != NULL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg("CSV quote character must not appear in the NULL specification"))); ! /* Open and lock the relation, using the appropriate lock type. */ ! rel = heap_openrv(relation, (is_from ? RowExclusiveLock : AccessShareLock)); ! /* check read-only transaction */ ! if (XactReadOnly && !is_from && !isTempNamespace(RelationGetNamespace(rel))) ereport(ERROR, (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION), errmsg("transaction is read-only"))); ! /* Check permissions. */ aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(), required_access); if (aclresult != ACLCHECK_OK) --- 950,1006 ---- if (force_quote != NIL && is_from) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg("COPY force quote only available using COPY TO"))); ! /* ! * Check force_notnull ! */ if (!csv_mode && force_notnull != NIL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg("COPY force not null available only in CSV mode"))); if (force_notnull != NIL && !is_from) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg ! ("COPY force not null only available using COPY FROM"))); ! /* ! * Don't allow the delimiter to appear in the null string. ! */ if (strchr(null_print, delim[0]) != NULL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg ! ("COPY delimiter must not appear in the NULL specification"))); ! /* ! * Don't allow the csv quote char to appear in the null string. ! */ if (csv_mode && strchr(null_print, quote[0]) != NULL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg ! ("CSV quote character must not appear in the NULL specification"))); ! /* ! * Open and lock the relation, using the appropriate lock type. ! */ ! rel = ! heap_openrv(relation, (is_from ? RowExclusiveLock : AccessShareLock)); ! /* ! * check read-only transaction ! */ ! if (XactReadOnly && !is_from ! && !isTempNamespace(RelationGetNamespace(rel))) ereport(ERROR, (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION), errmsg("transaction is read-only"))); ! /* ! * Check permissions. ! */ aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(), required_access); if (aclresult != ACLCHECK_OK) *************** *** 914,932 **** (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be superuser to COPY to or from a file"), errhint("Anyone can COPY to stdout or from stdin. " ! "psql's \\copy command also works for anyone."))); ! /* Don't allow COPY w/ OIDs to or from a table without them */ if (oids && !rel->rd_rel->relhasoids) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("table \"%s\" does not have OIDs", RelationGetRelationName(rel)))); ! /* Generate or convert list of attributes to process */ attnumlist = CopyGetAttnums(rel, attnamelist); ! /* Check that FORCE QUOTE references valid COPY columns */ if (force_quote) { TupleDesc tupDesc = RelationGetDescr(rel); --- 1011,1035 ---- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be superuser to COPY to or from a file"), errhint("Anyone can COPY to stdout or from stdin. " ! "psql's \\copy command also works for anyone."))); ! /* ! * Don't allow COPY w/ OIDs to or from a table without them ! */ if (oids && !rel->rd_rel->relhasoids) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("table \"%s\" does not have OIDs", RelationGetRelationName(rel)))); ! /* ! * Generate or convert list of attributes to process ! */ attnumlist = CopyGetAttnums(rel, attnamelist); ! /* ! * Check that FORCE QUOTE references valid COPY columns ! */ if (force_quote) { TupleDesc tupDesc = RelationGetDescr(rel); *************** *** 942,953 **** if (!list_member_int(attnumlist, attnum)) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), ! errmsg("FORCE QUOTE column \"%s\" not referenced by COPY", ! NameStr(attr[attnum - 1]->attname)))); } } ! /* Check that FORCE NOT NULL references valid COPY columns */ if (force_notnull) { ListCell *cur; --- 1045,1059 ---- if (!list_member_int(attnumlist, attnum)) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), ! errmsg ! ("FORCE QUOTE column \"%s\" not referenced by COPY", ! NameStr(attr[attnum - 1]->attname)))); } } ! /* ! * Check that FORCE NOT NULL references valid COPY columns ! */ if (force_notnull) { ListCell *cur; *************** *** 963,974 **** if (!list_member_int(attnumlist, attnum)) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), ! errmsg("FORCE NOT NULL column \"%s\" not referenced by COPY", ! NameStr(attr[attnum - 1]->attname)))); } } ! /* Set up variables to avoid per-attribute overhead. */ initStringInfo(&attribute_buf); initStringInfo(&line_buf); line_buf_converted = false; --- 1069,1083 ---- if (!list_member_int(attnumlist, attnum)) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), ! errmsg ! ("FORCE NOT NULL column \"%s\" not referenced by COPY", ! NameStr(attr[attnum - 1]->attname)))); } } ! /* ! * Set up variables to avoid per-attribute overhead. ! */ initStringInfo(&attribute_buf); initStringInfo(&line_buf); line_buf_converted = false; *************** *** 998,1005 **** else ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), ! errmsg("cannot copy to non-table relation \"%s\"", ! RelationGetRelationName(rel)))); } if (pipe) { --- 1107,1114 ---- else ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), ! errmsg("cannot copy to non-table relation \"%s\"", ! RelationGetRelationName(rel)))); } if (pipe) { *************** *** 1017,1024 **** if (copy_file == NULL) ereport(ERROR, (errcode_for_file_access(), ! errmsg("could not open file \"%s\" for reading: %m", ! filename))); fstat(fileno(copy_file), &st); if (S_ISDIR(st.st_mode)) --- 1126,1133 ---- if (copy_file == NULL) ereport(ERROR, (errcode_for_file_access(), ! errmsg("could not open file \"%s\" for reading: %m", ! filename))); fstat(fileno(copy_file), &st); if (S_ISDIR(st.st_mode)) *************** *** 1049,1056 **** else ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), ! errmsg("cannot copy from non-table relation \"%s\"", ! RelationGetRelationName(rel)))); } if (pipe) { --- 1158,1165 ---- else ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), ! errmsg("cannot copy from non-table relation \"%s\"", ! RelationGetRelationName(rel)))); } if (pipe) { *************** *** 1071,1077 **** if (!is_absolute_path(filename)) ereport(ERROR, (errcode(ERRCODE_INVALID_NAME), ! errmsg("relative path not allowed for COPY to file"))); oumask = umask((mode_t) 022); copy_file = AllocateFile(filename, PG_BINARY_W); --- 1180,1187 ---- if (!is_absolute_path(filename)) ereport(ERROR, (errcode(ERRCODE_INVALID_NAME), ! errmsg ! ("relative path not allowed for COPY to file"))); oumask = umask((mode_t) 022); copy_file = AllocateFile(filename, PG_BINARY_W); *************** *** 1080,1087 **** if (copy_file == NULL) ereport(ERROR, (errcode_for_file_access(), ! errmsg("could not open file \"%s\" for writing: %m", ! filename))); fstat(fileno(copy_file), &st); if (S_ISDIR(st.st_mode)) --- 1190,1197 ---- if (copy_file == NULL) ereport(ERROR, (errcode_for_file_access(), ! errmsg("could not open file \"%s\" for writing: %m", ! filename))); fstat(fileno(copy_file), &st); if (S_ISDIR(st.st_mode)) *************** *** 1099,1110 **** if (!pipe) { ! /* we assume only the write case could fail here */ if (FreeFile(copy_file)) ereport(ERROR, (errcode_for_file_access(), ! errmsg("could not write to file \"%s\": %m", ! filename))); } pfree(attribute_buf.data); pfree(line_buf.data); --- 1209,1221 ---- if (!pipe) { ! /* ! * we assume only the write case could fail here ! */ if (FreeFile(copy_file)) ereport(ERROR, (errcode_for_file_access(), ! errmsg("could not write to file \"%s\": %m", filename))); } pfree(attribute_buf.data); pfree(line_buf.data); *************** *** 1178,1184 **** num_phys_attrs = tupDesc->natts; attr_count = list_length(attnumlist); ! /* Get info about the columns we need to process. */ out_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo)); force_quote = (bool *) palloc(num_phys_attrs * sizeof(bool)); foreach(cur, attnumlist) --- 1289,1297 ---- num_phys_attrs = tupDesc->natts; attr_count = list_length(attnumlist); ! /* ! * Get info about the columns we need to process. ! */ out_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo)); force_quote = (bool *) palloc(num_phys_attrs * sizeof(bool)); foreach(cur, attnumlist) *************** *** 1189,1200 **** if (binary) getTypeBinaryOutputInfo(attr[attnum - 1]->atttypid, ! &out_func_oid, ! &isvarlena); else getTypeOutputInfo(attr[attnum - 1]->atttypid, ! &out_func_oid, ! &isvarlena); fmgr_info(out_func_oid, &out_functions[attnum - 1]); if (list_member_int(force_quote_atts, attnum)) --- 1302,1311 ---- if (binary) getTypeBinaryOutputInfo(attr[attnum - 1]->atttypid, ! &out_func_oid, &isvarlena); else getTypeOutputInfo(attr[attnum - 1]->atttypid, ! &out_func_oid, &isvarlena); fmgr_info(out_func_oid, &out_functions[attnum - 1]); if (list_member_int(force_quote_atts, attnum)) *************** *** 1217,1233 **** if (binary) { ! /* Generate header for a binary copy */ int32 tmp; ! /* Signature */ CopySendData((char *) BinarySignature, 11); ! /* Flags field */ tmp = 0; if (oids) tmp |= (1 << 16); CopySendInt32(tmp); ! /* No header extension */ tmp = 0; CopySendInt32(tmp); } --- 1328,1352 ---- if (binary) { ! /* ! * Generate header for a binary copy ! */ int32 tmp; ! /* ! * Signature ! */ CopySendData((char *) BinarySignature, 11); ! /* ! * Flags field ! */ tmp = 0; if (oids) tmp |= (1 << 16); CopySendInt32(tmp); ! /* ! * No header extension ! */ tmp = 0; CopySendInt32(tmp); } *************** *** 1242,1253 **** pg_server_to_client((unsigned char *) null_print, strlen(null_print)); ! /* if a header has been requested send the line */ if (header_line) { ! bool hdr_delim = false; ! char *colname; ! foreach(cur, attnumlist) { int attnum = lfirst_int(cur); --- 1361,1374 ---- pg_server_to_client((unsigned char *) null_print, strlen(null_print)); ! /* ! * if a header has been requested send the line ! */ if (header_line) { ! bool hdr_delim = false; ! char *colname; ! foreach(cur, attnumlist) { int attnum = lfirst_int(cur); *************** *** 1280,1304 **** if (binary) { ! /* Binary per-tuple header */ CopySendInt16(attr_count); ! /* Send OID if wanted --- note attr_count doesn't include it */ if (oids) { Oid oid = HeapTupleGetOid(tuple); ! /* Hack --- assume Oid is same size as int32 */ CopySendInt32(sizeof(int32)); CopySendInt32(oid); } } else { ! /* Text format has no per-tuple header, but send OID if wanted */ if (oids) { string = DatumGetCString(DirectFunctionCall1(oidout, ! ObjectIdGetDatum(HeapTupleGetOid(tuple)))); CopySendString(string); need_delim = true; } --- 1401,1435 ---- if (binary) { ! /* ! * Binary per-tuple header ! */ CopySendInt16(attr_count); ! /* ! * Send OID if wanted --- note attr_count doesn't include it ! */ if (oids) { Oid oid = HeapTupleGetOid(tuple); ! /* ! * Hack --- assume Oid is same size as int32 ! */ CopySendInt32(sizeof(int32)); CopySendInt32(oid); } } else { ! /* ! * Text format has no per-tuple header, but send OID if wanted ! */ if (oids) { string = DatumGetCString(DirectFunctionCall1(oidout, ! ObjectIdGetDatum ! (HeapTupleGetOid ! (tuple)))); CopySendString(string); need_delim = true; } *************** *** 1330,1342 **** { if (!binary) { ! string = DatumGetCString(FunctionCall1(&out_functions[attnum - 1], ! value)); if (csv_mode) { CopyAttributeOutCSV(string, delim, quote, escape, ! (strcmp(string, null_print) == 0 || ! force_quote[attnum - 1])); } else CopyAttributeOut(string, delim); --- 1461,1474 ---- { if (!binary) { ! string = ! DatumGetCString(FunctionCall1 ! (&out_functions[attnum - 1], value)); if (csv_mode) { CopyAttributeOutCSV(string, delim, quote, escape, ! (strcmp(string, null_print) == 0 || ! force_quote[attnum - 1])); } else CopyAttributeOut(string, delim); *************** *** 1346,1354 **** { bytea *outputbytes; ! outputbytes = DatumGetByteaP(FunctionCall1(&out_functions[attnum - 1], ! value)); ! /* We assume the result will not have been toasted */ CopySendInt32(VARSIZE(outputbytes) - VARHDRSZ); CopySendData(VARDATA(outputbytes), VARSIZE(outputbytes) - VARHDRSZ); --- 1478,1489 ---- { bytea *outputbytes; ! outputbytes = ! DatumGetByteaP(FunctionCall1 ! (&out_functions[attnum - 1], value)); ! /* ! * We assume the result will not have been toasted ! */ CopySendInt32(VARSIZE(outputbytes) - VARHDRSZ); CopySendData(VARDATA(outputbytes), VARSIZE(outputbytes) - VARHDRSZ); *************** *** 1365,1371 **** if (binary) { ! /* Generate trailer for a binary copy */ CopySendInt16(-1); } --- 1500,1508 ---- if (binary) { ! /* ! * Generate trailer for a binary copy ! */ CopySendInt16(-1); } *************** *** 1384,1390 **** { if (copy_binary) { ! /* can't usefully display the data */ if (copy_attname) errcontext("COPY %s, line %d, column %s", copy_relname, copy_lineno, copy_attname); --- 1521,1529 ---- { if (copy_binary) { ! /* ! * can't usefully display the data ! */ if (copy_attname) errcontext("COPY %s, line %d, column %s", copy_relname, copy_lineno, copy_attname); *************** *** 1395,1401 **** { if (copy_attname) { ! /* error is relevant to a particular column */ limit_printout_length(&attribute_buf); errcontext("COPY %s, line %d, column %s: \"%s\"", copy_relname, copy_lineno, copy_attname, --- 1534,1542 ---- { if (copy_attname) { ! /* ! * error is relevant to a particular column ! */ limit_printout_length(&attribute_buf); errcontext("COPY %s, line %d, column %s: \"%s\"", copy_relname, copy_lineno, copy_attname, *************** *** 1403,1423 **** } else { ! /* error is relevant to a particular line */ ! if (line_buf_converted || ! client_encoding == server_encoding) { limit_printout_length(&line_buf); errcontext("COPY %s, line %d: \"%s\"", ! copy_relname, copy_lineno, ! line_buf.data); } else { /* * Here, the line buffer is still in a foreign encoding, * and indeed it's quite likely that the error is precisely ! * a failure to do encoding conversion (ie, bad data). We * dare not try to convert it, and at present there's no way * to regurgitate it without conversion. So we have to punt * and just report the line number. --- 1544,1564 ---- } else { ! /* ! * error is relevant to a particular line ! */ ! if (line_buf_converted || client_encoding == server_encoding) { limit_printout_length(&line_buf); errcontext("COPY %s, line %d: \"%s\"", ! copy_relname, copy_lineno, line_buf.data); } else { /* * Here, the line buffer is still in a foreign encoding, * and indeed it's quite likely that the error is precisely ! * a failure to do encoding conversion (ie, bad data). We * dare not try to convert it, and at present there's no way * to regurgitate it without conversion. So we have to punt * and just report the line number. *************** *** 1445,1462 **** int len; ! /* Fast path if definitely okay */ if (buf->len <= MAX_COPY_DATA_DISPLAY) return; ! /* Apply encoding-dependent truncation */ len = pg_mbcliplen(buf->data, buf->len, MAX_COPY_DATA_DISPLAY); if (buf->len <= len) return; /* no need to truncate */ buf->len = len; buf->data[len] = '\0'; ! /* Add "..." to show we truncated the input */ appendStringInfoString(buf, "..."); } --- 1586,1609 ---- int len; ! /* ! * Fast path if definitely okay ! */ if (buf->len <= MAX_COPY_DATA_DISPLAY) return; ! /* ! * Apply encoding-dependent truncation ! */ len = pg_mbcliplen(buf->data, buf->len, MAX_COPY_DATA_DISPLAY); if (buf->len <= len) return; /* no need to truncate */ buf->len = len; buf->data[len] = '\0'; ! /* ! * Add "..." to show we truncated the input ! */ appendStringInfoString(buf, "..."); } *************** *** 1510,1521 **** * code here that basically duplicated execUtils.c ...) */ resultRelInfo = makeNode(ResultRelInfo); resultRelInfo->ri_RangeTableIndex = 1; /* dummy */ resultRelInfo->ri_RelationDesc = rel; resultRelInfo->ri_TrigDesc = CopyTriggerDesc(rel->trigdesc); if (resultRelInfo->ri_TrigDesc) resultRelInfo->ri_TrigFunctions = (FmgrInfo *) ! palloc0(resultRelInfo->ri_TrigDesc->numtriggers * sizeof(FmgrInfo)); resultRelInfo->ri_TrigInstrument = NULL; ExecOpenIndices(resultRelInfo); --- 1657,1670 ---- * code here that basically duplicated execUtils.c ...) */ resultRelInfo = makeNode(ResultRelInfo); + resultRelInfo->ri_RangeTableIndex = 1; /* dummy */ resultRelInfo->ri_RelationDesc = rel; resultRelInfo->ri_TrigDesc = CopyTriggerDesc(rel->trigdesc); if (resultRelInfo->ri_TrigDesc) resultRelInfo->ri_TrigFunctions = (FmgrInfo *) ! palloc0(resultRelInfo->ri_TrigDesc->numtriggers * ! sizeof(FmgrInfo)); resultRelInfo->ri_TrigInstrument = NULL; ExecOpenIndices(resultRelInfo); *************** *** 1524,1530 **** estate->es_num_result_relations = 1; estate->es_result_relation_info = resultRelInfo; ! /* Set up a tuple slot too */ slot = MakeSingleTupleTableSlot(tupDesc); econtext = GetPerTupleExprContext(estate); --- 1673,1681 ---- estate->es_num_result_relations = 1; estate->es_result_relation_info = resultRelInfo; ! /* ! * Set up a tuple slot too ! */ slot = MakeSingleTupleTableSlot(tupDesc); econtext = GetPerTupleExprContext(estate); *************** *** 1539,1557 **** typioparams = (Oid *) palloc(num_phys_attrs * sizeof(Oid)); defmap = (int *) palloc(num_phys_attrs * sizeof(int)); defexprs = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *)); ! constraintexprs = (ExprState **) palloc0(num_phys_attrs * sizeof(ExprState *)); force_notnull = (bool *) palloc(num_phys_attrs * sizeof(bool)); for (attnum = 1; attnum <= num_phys_attrs; attnum++) { ! /* We don't need info for dropped attributes */ if (attr[attnum - 1]->attisdropped) continue; ! /* Fetch the input function and typioparam info */ if (binary) getTypeBinaryInputInfo(attr[attnum - 1]->atttypid, ! &in_func_oid, &typioparams[attnum - 1]); else getTypeInputInfo(attr[attnum - 1]->atttypid, &in_func_oid, &typioparams[attnum - 1]); --- 1690,1713 ---- typioparams = (Oid *) palloc(num_phys_attrs * sizeof(Oid)); defmap = (int *) palloc(num_phys_attrs * sizeof(int)); defexprs = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *)); ! constraintexprs = ! (ExprState **) palloc0(num_phys_attrs * sizeof(ExprState *)); force_notnull = (bool *) palloc(num_phys_attrs * sizeof(bool)); for (attnum = 1; attnum <= num_phys_attrs; attnum++) { ! /* ! * We don't need info for dropped attributes ! */ if (attr[attnum - 1]->attisdropped) continue; ! /* ! * Fetch the input function and typioparam info ! */ if (binary) getTypeBinaryInputInfo(attr[attnum - 1]->atttypid, ! &in_func_oid, &typioparams[attnum - 1]); else getTypeInputInfo(attr[attnum - 1]->atttypid, &in_func_oid, &typioparams[attnum - 1]); *************** *** 1562,1572 **** else force_notnull[attnum - 1] = false; ! /* Get default info if needed */ if (!list_member_int(attnumlist, attnum)) { ! /* attribute is NOT to be copied from input */ ! /* use default value if one exists */ Node *defexpr = build_column_default(rel, attnum); if (defexpr != NULL) --- 1718,1734 ---- else force_notnull[attnum - 1] = false; ! /* ! * Get default info if needed ! */ if (!list_member_int(attnumlist, attnum)) { ! /* ! * attribute is NOT to be copied from input ! */ ! /* ! * use default value if one exists ! */ Node *defexpr = build_column_default(rel, attnum); if (defexpr != NULL) *************** *** 1578,1584 **** } } ! /* If it's a domain type, set up to check domain constraints */ if (get_typtype(attr[attnum - 1]->atttypid) == 'd') { Param *prm; --- 1740,1748 ---- } } ! /* ! * If it's a domain type, set up to check domain constraints ! */ if (get_typtype(attr[attnum - 1]->atttypid) == 'd') { Param *prm; *************** *** 1593,1598 **** --- 1757,1763 ---- * actual datum during the data input loop. */ prm = makeNode(Param); + prm->paramkind = PARAM_EXEC; prm->paramid = 0; prm->paramtype = getBaseType(attr[attnum - 1]->atttypid); *************** *** 1608,1614 **** } } ! /* Prepare to catch AFTER triggers. */ AfterTriggerBeginQuery(); /* --- 1773,1781 ---- } } ! /* ! * Prepare to catch AFTER triggers. ! */ AfterTriggerBeginQuery(); /* *************** *** 1624,1640 **** file_has_oids = oids; /* must rely on user to tell us this... */ else { ! /* Read and verify binary header */ char readSig[11]; int32 tmp; ! /* Signature */ CopyGetData(readSig, 11); if (CopyGetEof() || memcmp(readSig, BinarySignature, 11) != 0) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), errmsg("COPY file signature not recognized"))); ! /* Flags field */ tmp = CopyGetInt32(); if (CopyGetEof()) ereport(ERROR, --- 1791,1813 ---- file_has_oids = oids; /* must rely on user to tell us this... */ else { ! /* ! * Read and verify binary header ! */ char readSig[11]; int32 tmp; ! /* ! * Signature ! */ CopyGetData(readSig, 11); if (CopyGetEof() || memcmp(readSig, BinarySignature, 11) != 0) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), errmsg("COPY file signature not recognized"))); ! /* ! * Flags field ! */ tmp = CopyGetInt32(); if (CopyGetEof()) ereport(ERROR, *************** *** 1645,1684 **** if ((tmp >> 16) != 0) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg("unrecognized critical flags in COPY file header"))); ! /* Header extension length */ tmp = CopyGetInt32(); if (CopyGetEof() || tmp < 0) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg("invalid COPY file header (missing length)"))); ! /* Skip extension header, if present */ while (tmp-- > 0) { CopyGetData(readSig, 1); if (CopyGetEof()) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg("invalid COPY file header (wrong length)"))); } } if (file_has_oids && binary) { ! getTypeBinaryInputInfo(OIDOID, ! &in_func_oid, &oid_typioparam); fmgr_info(in_func_oid, &oid_in_function); } values = (Datum *) palloc(num_phys_attrs * sizeof(Datum)); nulls = (char *) palloc(num_phys_attrs * sizeof(char)); ! /* Make room for a PARAM_EXEC value for domain constraint checks */ if (hasConstraints) econtext->ecxt_param_exec_vals = (ParamExecData *) palloc0(sizeof(ParamExecData)); ! /* Initialize static variables */ fe_eof = false; eol_type = EOL_UNKNOWN; copy_binary = binary; --- 1818,1865 ---- if ((tmp >> 16) != 0) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg ! ("unrecognized critical flags in COPY file header"))); ! /* ! * Header extension length ! */ tmp = CopyGetInt32(); if (CopyGetEof() || tmp < 0) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg("invalid COPY file header (missing length)"))); ! /* ! * Skip extension header, if present ! */ while (tmp-- > 0) { CopyGetData(readSig, 1); if (CopyGetEof()) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg("invalid COPY file header (wrong length)"))); } } if (file_has_oids && binary) { ! getTypeBinaryInputInfo(OIDOID, &in_func_oid, &oid_typioparam); fmgr_info(in_func_oid, &oid_in_function); } values = (Datum *) palloc(num_phys_attrs * sizeof(Datum)); nulls = (char *) palloc(num_phys_attrs * sizeof(char)); ! /* ! * Make room for a PARAM_EXEC value for domain constraint checks ! */ if (hasConstraints) econtext->ecxt_param_exec_vals = (ParamExecData *) palloc0(sizeof(ParamExecData)); ! /* ! * Initialize static variables ! */ fe_eof = false; eol_type = EOL_UNKNOWN; copy_binary = binary; *************** *** 1686,1702 **** copy_lineno = 0; copy_attname = NULL; ! /* Set up callback to identify error line number */ errcontext.callback = copy_in_error_callback; errcontext.arg = NULL; errcontext.previous = error_context_stack; error_context_stack = &errcontext; ! /* on input just throw the header line away */ if (header_line) { copy_lineno++; ! done = CopyReadLine(quote, escape) ; } while (!done) --- 1867,1887 ---- copy_lineno = 0; copy_attname = NULL; ! /* ! * Set up callback to identify error line number ! */ errcontext.callback = copy_in_error_callback; errcontext.arg = NULL; errcontext.previous = error_context_stack; error_context_stack = &errcontext; ! /* ! * on input just throw the header line away ! */ if (header_line) { copy_lineno++; ! done = CopyReadLine(quote, escape); } while (!done) *************** *** 1708,1720 **** copy_lineno++; ! /* Reset the per-tuple exprcontext */ ResetPerTupleExprContext(estate); ! /* Switch into its memory context */ MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); ! /* Initialize all values for row to NULL */ MemSet(values, 0, num_phys_attrs * sizeof(Datum)); MemSet(nulls, 'n', num_phys_attrs * sizeof(char)); --- 1893,1911 ---- copy_lineno++; ! /* ! * Reset the per-tuple exprcontext ! */ ResetPerTupleExprContext(estate); ! /* ! * Switch into its memory context ! */ MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); ! /* ! * Initialize all values for row to NULL ! */ MemSet(values, 0, num_phys_attrs * sizeof(Datum)); MemSet(nulls, 'n', num_phys_attrs * sizeof(char)); *************** *** 1724,1731 **** char *string; ListCell *cur; ! /* Actually read the line into memory here */ ! done = csv_mode ? CopyReadLine(quote, escape) : CopyReadLine(NULL, NULL); /* --- 1915,1924 ---- char *string; ListCell *cur; ! /* ! * Actually read the line into memory here ! */ ! done = csv_mode ? CopyReadLine(quote, escape) : CopyReadLine(NULL, NULL); /* *************** *** 1739,1745 **** if (file_has_oids) { ! /* can't be in CSV mode here */ string = CopyReadAttribute(delim, null_print, &result, &isnull); --- 1932,1940 ---- if (file_has_oids) { ! /* ! * can't be in CSV mode here ! */ string = CopyReadAttribute(delim, null_print, &result, &isnull); *************** *** 1751,1757 **** { copy_attname = "oid"; loaded_oid = DatumGetObjectId(DirectFunctionCall1(oidin, ! CStringGetDatum(string))); if (loaded_oid == InvalidOid) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), --- 1946,1953 ---- { copy_attname = "oid"; loaded_oid = DatumGetObjectId(DirectFunctionCall1(oidin, ! CStringGetDatum ! (string))); if (loaded_oid == InvalidOid) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), *************** *** 1760,1766 **** } } ! /* Loop to read the user attributes on the line. */ foreach(cur, attnumlist) { int attnum = lfirst_int(cur); --- 1956,1964 ---- } } ! /* ! * Loop to read the user attributes on the line. ! */ foreach(cur, attnumlist) { int attnum = lfirst_int(cur); *************** *** 1779,1789 **** if (csv_mode) { string = CopyReadAttributeCSV(delim, null_print, quote, ! escape, &result, &isnull); if (result == UNTERMINATED_FIELD) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg("unterminated CSV quoted field"))); } else string = CopyReadAttribute(delim, null_print, --- 1977,1987 ---- if (csv_mode) { string = CopyReadAttributeCSV(delim, null_print, quote, ! escape, &result, &isnull); if (result == UNTERMINATED_FIELD) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg("unterminated CSV quoted field"))); } else string = CopyReadAttribute(delim, null_print, *************** *** 1795,1808 **** isnull = false; } ! /* we read an SQL NULL, no need to do anything */ if (!isnull) { copy_attname = NameStr(attr[m]->attname); values[m] = FunctionCall3(&in_functions[m], CStringGetDatum(string), ! ObjectIdGetDatum(typioparams[m]), ! Int32GetDatum(attr[m]->atttypmod)); nulls[m] = ' '; copy_attname = NULL; } --- 1993,2009 ---- isnull = false; } ! /* ! * we read an SQL NULL, no need to do anything ! */ if (!isnull) { copy_attname = NameStr(attr[m]->attname); values[m] = FunctionCall3(&in_functions[m], CStringGetDatum(string), ! ObjectIdGetDatum(typioparams[m]), ! Int32GetDatum(attr[m]-> ! atttypmod)); nulls[m] = ' '; copy_attname = NULL; } *************** *** 1818,1828 **** if (result == NORMAL_ATTR && line_buf.len != 0) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg("extra data after last expected column"))); } else { ! /* binary */ int16 fld_count; ListCell *cur; --- 2019,2031 ---- if (result == NORMAL_ATTR && line_buf.len != 0) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg("extra data after last expected column"))); } else { ! /* ! * binary ! */ int16 fld_count; ListCell *cur; *************** *** 1844,1851 **** copy_attname = "oid"; loaded_oid = DatumGetObjectId(CopyReadBinaryAttribute(0, ! &oid_in_function, ! oid_typioparam, &isnull)); if (isnull || loaded_oid == InvalidOid) ereport(ERROR, --- 2047,2054 ---- copy_attname = "oid"; loaded_oid = DatumGetObjectId(CopyReadBinaryAttribute(0, ! &oid_in_function, ! oid_typioparam, &isnull)); if (isnull || loaded_oid == InvalidOid) ereport(ERROR, *************** *** 1864,1871 **** i++; values[m] = CopyReadBinaryAttribute(i, &in_functions[m], ! typioparams[m], ! &isnull); nulls[m] = isnull ? 'n' : ' '; copy_attname = NULL; } --- 2067,2073 ---- i++; values[m] = CopyReadBinaryAttribute(i, &in_functions[m], ! typioparams[m], &isnull); nulls[m] = isnull ? 'n' : ' '; copy_attname = NULL; } *************** *** 1884,1890 **** nulls[defmap[i]] = ' '; } ! /* Next apply any domain constraints */ if (hasConstraints) { ParamExecData *prmdata = &econtext->ecxt_param_exec_vals[0]; --- 2086,2094 ---- nulls[defmap[i]] = ' '; } ! /* ! * Next apply any domain constraints ! */ if (hasConstraints) { ParamExecData *prmdata = &econtext->ecxt_param_exec_vals[0]; *************** *** 1896,1902 **** if (exprstate == NULL) continue; /* no constraint for this attr */ ! /* Insert current row's value into the Param value */ prmdata->value = values[i]; prmdata->isnull = (nulls[i] == 'n'); --- 2100,2108 ---- if (exprstate == NULL) continue; /* no constraint for this attr */ ! /* ! * Insert current row's value into the Param value ! */ prmdata->value = values[i]; prmdata->isnull = (nulls[i] == 'n'); *************** *** 1905,1928 **** * expression to replace the value (consider e.g. a * timestamp precision restriction). */ ! values[i] = ExecEvalExpr(exprstate, econtext, ! &isnull, NULL); nulls[i] = isnull ? 'n' : ' '; } } ! /* And now we can form the input tuple. */ tuple = heap_formtuple(tupDesc, values, nulls); if (oids && file_has_oids) HeapTupleSetOid(tuple, loaded_oid); ! /* Triggers and stuff need to be invoked in query context. */ MemoryContextSwitchTo(oldcontext); skip_tuple = false; ! /* BEFORE ROW INSERT Triggers */ if (resultRelInfo->ri_TrigDesc && resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_INSERT] > 0) { --- 2111,2139 ---- * expression to replace the value (consider e.g. a * timestamp precision restriction). */ ! values[i] = ExecEvalExpr(exprstate, econtext, &isnull, NULL); nulls[i] = isnull ? 'n' : ' '; } } ! /* ! * And now we can form the input tuple. ! */ tuple = heap_formtuple(tupDesc, values, nulls); if (oids && file_has_oids) HeapTupleSetOid(tuple, loaded_oid); ! /* ! * Triggers and stuff need to be invoked in query context. ! */ MemoryContextSwitchTo(oldcontext); skip_tuple = false; ! /* ! * BEFORE ROW INSERT Triggers ! */ if (resultRelInfo->ri_TrigDesc && resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_INSERT] > 0) { *************** *** 1941,1973 **** if (!skip_tuple) { ! /* Place tuple in tuple slot */ ExecStoreTuple(tuple, slot, InvalidBuffer, false); ! /* Check the constraints of the tuple */ if (rel->rd_att->constr) ExecConstraints(resultRelInfo, slot, estate); ! /* OK, store the tuple and create index entries for it */ simple_heap_insert(rel, tuple); if (resultRelInfo->ri_NumIndices > 0) ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false); ! /* AFTER ROW INSERT Triggers */ ExecARInsertTriggers(estate, resultRelInfo, tuple); } } ! /* Done, clean up */ error_context_stack = errcontext.previous; MemoryContextSwitchTo(oldcontext); ! /* Execute AFTER STATEMENT insertion triggers */ ExecASInsertTriggers(estate, resultRelInfo); ! /* Handle queued AFTER triggers */ AfterTriggerEndQuery(estate); pfree(values); --- 2152,2198 ---- if (!skip_tuple) { ! /* ! * Place tuple in tuple slot ! */ ExecStoreTuple(tuple, slot, InvalidBuffer, false); ! /* ! * Check the constraints of the tuple ! */ if (rel->rd_att->constr) ExecConstraints(resultRelInfo, slot, estate); ! /* ! * OK, store the tuple and create index entries for it ! */ simple_heap_insert(rel, tuple); if (resultRelInfo->ri_NumIndices > 0) ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false); ! /* ! * AFTER ROW INSERT Triggers ! */ ExecARInsertTriggers(estate, resultRelInfo, tuple); } } ! /* ! * Done, clean up ! */ error_context_stack = errcontext.previous; MemoryContextSwitchTo(oldcontext); ! /* ! * Execute AFTER STATEMENT insertion triggers ! */ ExecASInsertTriggers(estate, resultRelInfo); ! /* ! * Handle queued AFTER triggers ! */ AfterTriggerEndQuery(estate); pfree(values); *************** *** 1996,2002 **** * by newline. */ static bool ! CopyReadLine(char * quote, char * escape) { bool result; bool change_encoding = (client_encoding != server_encoding); --- 2221,2227 ---- * by newline. */ static bool ! CopyReadLine(char *quote, char *escape) { bool result; bool change_encoding = (client_encoding != server_encoding); *************** *** 2005,2019 **** int j; unsigned char s[2]; char *cvt; ! bool in_quote = false, last_was_esc = false, csv_mode = false; ! char quotec = '\0', escapec = '\0'; if (quote) { csv_mode = true; quotec = quote[0]; escapec = escape[0]; ! /* ignore special escape processing if it's the same as quotec */ if (quotec == escapec) escapec = '\0'; } --- 2230,2249 ---- int j; unsigned char s[2]; char *cvt; ! bool in_quote = false, ! last_was_esc = false, ! csv_mode = false; ! char quotec = '\0', ! escapec = '\0'; if (quote) { csv_mode = true; quotec = quote[0]; escapec = escape[0]; ! /* ! * ignore special escape processing if it's the same as quotec ! */ if (quotec == escapec) escapec = '\0'; } *************** *** 2021,2051 **** s[1] = 0; ! /* reset line_buf to empty */ line_buf.len = 0; line_buf.data[0] = '\0'; line_buf.cursor = 0; ! /* mark that encoding conversion hasn't occurred yet */ line_buf_converted = false; ! /* set default status */ result = false; /* * In this loop we only care for detecting newlines (\r and/or \n) and ! * the end-of-copy marker (\.). * * In Text mode, for backwards compatibility we allow * backslashes to escape newline characters. Backslashes other than * the end marker get put into the line_buf, since CopyReadAttribute ! * does its own escape processing. * * In CSV mode, CR and NL inside q quoted field are just part of the * data value and are put in line_buf. We keep just enough state * to know if we are currently in a quoted field or not. * ! * These four characters, and only these four, are assumed the same in * frontend and backend encodings. * * We do not assume that second and later bytes of a frontend --- 2251,2287 ---- s[1] = 0; ! /* ! * reset line_buf to empty ! */ line_buf.len = 0; line_buf.data[0] = '\0'; line_buf.cursor = 0; ! /* ! * mark that encoding conversion hasn't occurred yet ! */ line_buf_converted = false; ! /* ! * set default status ! */ result = false; /* * In this loop we only care for detecting newlines (\r and/or \n) and ! * the end-of-copy marker (\.). * * In Text mode, for backwards compatibility we allow * backslashes to escape newline characters. Backslashes other than * the end marker get put into the line_buf, since CopyReadAttribute ! * does its own escape processing. * * In CSV mode, CR and NL inside q quoted field are just part of the * data value and are put in line_buf. We keep just enough state * to know if we are currently in a quoted field or not. * ! * These four characters, and only these four, are assumed the same in * frontend and backend encodings. * * We do not assume that second and later bytes of a frontend *************** *** 2062,2108 **** if (csv_mode) { ! /* * Dealing with quotes and escapes here is mildly tricky. If the * quote char is also the escape char, there's no problem - we * just use the char as a toggle. If they are different, we need * to ensure that we only take account of an escape inside a quoted * field and immediately preceding a quote char, and not the * second in a escape-escape sequence. ! */ if (in_quote && c == escapec) ! last_was_esc = ! last_was_esc; ! if (c == quotec && ! last_was_esc) ! in_quote = ! in_quote; if (c != escapec) last_was_esc = false; /* ! * updating the line count for embedded CR and/or LF chars is ! * necessarily a little fragile - this test is probably about * the best we can do. ! */ ! if (in_quote && c == (eol_type == EOL_CR ? '\r' : '\n')) ! copy_lineno++; } if (!in_quote && c == '\r') { if (eol_type == EOL_NL) { ! if (! csv_mode) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), errmsg("literal carriage return found in data"), ! errhint("Use \"\\r\" to represent carriage return."))); else ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg("unquoted carriage return found in CSV data"), ! errhint("Use quoted CSV field to represent carriage return."))); } ! /* Check for \r\n on first line, _and_ handle \r\n. */ if (eol_type == EOL_UNKNOWN || eol_type == EOL_CRNL) { int c2 = CopyPeekChar(); --- 2298,2349 ---- if (csv_mode) { ! /* * Dealing with quotes and escapes here is mildly tricky. If the * quote char is also the escape char, there's no problem - we * just use the char as a toggle. If they are different, we need * to ensure that we only take account of an escape inside a quoted * field and immediately preceding a quote char, and not the * second in a escape-escape sequence. ! */ if (in_quote && c == escapec) ! last_was_esc = !last_was_esc; ! if (c == quotec && !last_was_esc) ! in_quote = !in_quote; if (c != escapec) last_was_esc = false; /* ! * updating the line count for embedded CR and/or LF chars is ! * necessarily a little fragile - this test is probably about * the best we can do. ! */ ! if (in_quote && c == (eol_type == EOL_CR ? '\r' : '\n')) ! copy_lineno++; } if (!in_quote && c == '\r') { if (eol_type == EOL_NL) { ! if (!csv_mode) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), errmsg("literal carriage return found in data"), ! errhint ! ("Use \"\\r\" to represent carriage return."))); else ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg ! ("unquoted carriage return found in CSV data"), ! errhint ! ("Use quoted CSV field to represent carriage return."))); } ! /* ! * Check for \r\n on first line, _and_ handle \r\n. ! */ if (eol_type == EOL_UNKNOWN || eol_type == EOL_CRNL) { int c2 = CopyPeekChar(); *************** *** 2114,2132 **** } else { ! /* found \r, but no \n */ if (eol_type == EOL_CRNL) { if (!csv_mode) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg("literal carriage return found in data"), ! errhint("Use \"\\r\" to represent carriage return."))); else ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg("unquoted carriage return found in data"), ! errhint("Use quoted CSV field to represent carriage return."))); } --- 2355,2379 ---- } else { ! /* ! * found \r, but no \n ! */ if (eol_type == EOL_CRNL) { if (!csv_mode) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg ! ("literal carriage return found in data"), ! errhint ! ("Use \"\\r\" to represent carriage return."))); else ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg ! ("unquoted carriage return found in data"), ! errhint ! ("Use quoted CSV field to represent carriage return."))); } *************** *** 2153,2160 **** ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), errmsg("unquoted newline found in data"), ! errhint("Use quoted CSV field to represent newline."))); ! } eol_type = EOL_NL; break; --- 2400,2408 ---- ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), errmsg("unquoted newline found in data"), ! errhint ! ("Use quoted CSV field to represent newline."))); ! } eol_type = EOL_NL; break; *************** *** 2162,2169 **** if ((line_buf.len == 0 || !csv_mode) && c == '\\') { ! int c2; ! if (csv_mode) c2 = CopyPeekChar(); else --- 2410,2417 ---- if ((line_buf.len == 0 || !csv_mode) && c == '\\') { ! int c2; ! if (csv_mode) c2 = CopyPeekChar(); else *************** *** 2179,2185 **** if (c2 == '.') { if (csv_mode) ! CopyDonePeek(c2, true); /* allow keep calling GetChar() */ if (eol_type == EOL_CRNL) { --- 2427,2433 ---- if (c2 == '.') { if (csv_mode) ! CopyDonePeek(c2, true); /* allow keep calling GetChar() */ if (eol_type == EOL_CRNL) { *************** *** 2187,2193 **** if (c == '\n') ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg("end-of-copy marker does not match previous newline style"))); if (c != '\r') ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), --- 2435,2442 ---- if (c == '\n') ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg ! ("end-of-copy marker does not match previous newline style"))); if (c != '\r') ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), *************** *** 2203,2209 **** (eol_type == EOL_CR && c != '\r')) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg("end-of-copy marker does not match previous newline style"))); /* * In protocol version 3, we should ignore anything after --- 2452,2459 ---- (eol_type == EOL_CR && c != '\r')) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), ! errmsg ! ("end-of-copy marker does not match previous newline style"))); /* * In protocol version 3, we should ignore anything after *************** *** 2218,2228 **** result = true; /* report EOF */ break; } ! if (csv_mode) ! CopyDonePeek(c2, false); /* not a dot, so put it back */ else ! /* not EOF mark, so emit \ and following char literally */ appendStringInfoCharMacro(&line_buf, '\\'); } --- 2468,2480 ---- result = true; /* report EOF */ break; } ! if (csv_mode) ! CopyDonePeek(c2, false); /* not a dot, so put it back */ else ! /* ! * not EOF mark, so emit \ and following char literally ! */ appendStringInfoCharMacro(&line_buf, '\\'); } *************** *** 2254,2274 **** } } /* end of outer loop */ ! /* Done reading the line. Convert it to server encoding. */ if (change_encoding) { cvt = (char *) pg_client_to_server((unsigned char *) line_buf.data, line_buf.len); if (cvt != line_buf.data) { ! /* transfer converted data back to line_buf */ line_buf.len = 0; line_buf.data[0] = '\0'; appendBinaryStringInfo(&line_buf, cvt, strlen(cvt)); } } ! /* Now it's safe to use the buffer in error messages */ line_buf_converted = true; return result; --- 2506,2532 ---- } } /* end of outer loop */ ! /* ! * Done reading the line. Convert it to server encoding. ! */ if (change_encoding) { cvt = (char *) pg_client_to_server((unsigned char *) line_buf.data, line_buf.len); if (cvt != line_buf.data) { ! /* ! * transfer converted data back to line_buf ! */ line_buf.len = 0; line_buf.data[0] = '\0'; appendBinaryStringInfo(&line_buf, cvt, strlen(cvt)); } } ! /* ! * Now it's safe to use the buffer in error messages ! */ line_buf_converted = true; return result; *************** *** 2277,2284 **** /* * Return decimal value for a hexadecimal digit */ ! static ! int GetDecimalFromHex(char hex) { if (isdigit(hex)) return hex - '0'; --- 2535,2542 ---- /* * Return decimal value for a hexadecimal digit */ ! static int ! GetDecimalFromHex(char hex) { if (isdigit(hex)) return hex - '0'; *************** *** 2314,2324 **** int end_cursor; int input_len; ! /* reset attribute_buf to empty */ attribute_buf.len = 0; attribute_buf.data[0] = '\0'; ! /* set default status */ *result = END_OF_LINE; for (;;) --- 2572,2586 ---- int end_cursor; int input_len; ! /* ! * reset attribute_buf to empty ! */ attribute_buf.len = 0; attribute_buf.data[0] = '\0'; ! /* ! * set default status ! */ *result = END_OF_LINE; for (;;) *************** *** 2347,2353 **** case '5': case '6': case '7': ! /* handle \013 */ { int val; --- 2609,2617 ---- case '5': case '6': case '7': ! /* ! * handle \013 ! */ { int val; *************** *** 2374,2387 **** } break; case 'x': ! /* Handle \x3F */ if (line_buf.cursor < line_buf.len) { ! char hexchar = line_buf.data[line_buf.cursor]; if (isxdigit(hexchar)) { ! int val = GetDecimalFromHex(hexchar); line_buf.cursor++; if (line_buf.cursor < line_buf.len) --- 2638,2653 ---- } break; case 'x': ! /* ! * Handle \x3F ! */ if (line_buf.cursor < line_buf.len) { ! char hexchar = line_buf.data[line_buf.cursor]; if (isxdigit(hexchar)) { ! int val = GetDecimalFromHex(hexchar); line_buf.cursor++; if (line_buf.cursor < line_buf.len) *************** *** 2390,2396 **** if (isxdigit(hexchar)) { line_buf.cursor++; ! val = (val << 4) + GetDecimalFromHex(hexchar); } } c = val & 0xff; --- 2656,2664 ---- if (isxdigit(hexchar)) { line_buf.cursor++; ! val = ! (val << 4) + ! GetDecimalFromHex(hexchar); } } c = val & 0xff; *************** *** 2425,2431 **** appendStringInfoCharMacro(&attribute_buf, c); } ! /* check whether raw input matched null marker */ input_len = end_cursor - start_cursor; if (input_len == strlen(null_print) && strncmp(&line_buf.data[start_cursor], null_print, input_len) == 0) --- 2693,2701 ---- appendStringInfoCharMacro(&attribute_buf, c); } ! /* ! * check whether raw input matched null marker ! */ input_len = end_cursor - start_cursor; if (input_len == strlen(null_print) && strncmp(&line_buf.data[start_cursor], null_print, input_len) == 0) *************** *** 2477,2487 **** bool in_quote = false; bool saw_quote = false; ! /* reset attribute_buf to empty */ attribute_buf.len = 0; attribute_buf.data[0] = '\0'; ! /* set default status */ *result = END_OF_LINE; for (;;) --- 2747,2761 ---- bool in_quote = false; bool saw_quote = false; ! /* ! * reset attribute_buf to empty ! */ attribute_buf.len = 0; attribute_buf.data[0] = '\0'; ! /* ! * set default status ! */ *result = END_OF_LINE; for (;;) *************** *** 2491,2504 **** break; c = line_buf.data[line_buf.cursor++]; ! /* unquoted field delimiter */ if (!in_quote && c == delimc) { *result = NORMAL_ATTR; break; } ! /* start of quoted field (or part of field) */ if (!in_quote && c == quotec) { saw_quote = true; --- 2765,2782 ---- break; c = line_buf.data[line_buf.cursor++]; ! /* ! * unquoted field delimiter ! */ if (!in_quote && c == delimc) { *result = NORMAL_ATTR; break; } ! /* ! * start of quoted field (or part of field) ! */ if (!in_quote && c == quotec) { saw_quote = true; *************** *** 2506,2512 **** continue; } ! /* escape within a quoted field */ if (in_quote && c == escapec) { /* --- 2784,2792 ---- continue; } ! /* ! * escape within a quoted field ! */ if (in_quote && c == escapec) { /* *************** *** 2542,2548 **** if (in_quote) *result = UNTERMINATED_FIELD; ! /* check whether raw input matched null marker */ input_len = end_cursor - start_cursor; if (!saw_quote && input_len == strlen(null_print) && strncmp(&line_buf.data[start_cursor], null_print, input_len) == 0) --- 2822,2830 ---- if (in_quote) *result = UNTERMINATED_FIELD; ! /* ! * check whether raw input matched null marker ! */ input_len = end_cursor - start_cursor; if (!saw_quote && input_len == strlen(null_print) && strncmp(&line_buf.data[start_cursor], null_print, input_len) == 0) *************** *** 2578,2584 **** (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), errmsg("invalid field size"))); ! /* reset attribute_buf to empty, and load raw data in it */ attribute_buf.len = 0; attribute_buf.data[0] = '\0'; attribute_buf.cursor = 0; --- 2860,2868 ---- (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), errmsg("invalid field size"))); ! /* ! * reset attribute_buf to empty, and load raw data in it ! */ attribute_buf.len = 0; attribute_buf.data[0] = '\0'; attribute_buf.cursor = 0; *************** *** 2594,2605 **** attribute_buf.len = fld_size; attribute_buf.data[fld_size] = '\0'; ! /* Call the column type's binary input converter */ result = FunctionCall2(flinfo, PointerGetDatum(&attribute_buf), ObjectIdGetDatum(typioparam)); ! /* Trouble if it didn't eat the whole buffer */ if (attribute_buf.cursor != attribute_buf.len) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), --- 2878,2893 ---- attribute_buf.len = fld_size; attribute_buf.data[fld_size] = '\0'; ! /* ! * Call the column type's binary input converter ! */ result = FunctionCall2(flinfo, PointerGetDatum(&attribute_buf), ObjectIdGetDatum(typioparam)); ! /* ! * Trouble if it didn't eat the whole buffer ! */ if (attribute_buf.cursor != attribute_buf.len) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), *************** *** 2668,2674 **** */ if (!same_encoding) { ! /* send additional bytes of the char, if any */ mblen = pg_encoding_mblen(client_encoding, string); for (i = 1; i < mblen; i++) CopySendChar(string[i]); --- 2956,2964 ---- */ if (!same_encoding) { ! /* ! * send additional bytes of the char, if any ! */ mblen = pg_encoding_mblen(client_encoding, string); for (i = 1; i < mblen; i++) CopySendChar(string[i]); *************** *** 2709,2716 **** */ for (test_string = string; ! !use_quote && (c = *test_string) != '\0'; ! test_string += mblen) { if (c == delimc || c == quotec || c == '\n' || c == '\r') use_quote = true; --- 2999,3005 ---- */ for (test_string = string; ! !use_quote && (c = *test_string) != '\0'; test_string += mblen) { if (c == delimc || c == quotec || c == '\n' || c == '\r') use_quote = true; *************** *** 2732,2738 **** if (!same_encoding) { ! /* send additional bytes of the char, if any */ mblen = pg_encoding_mblen(client_encoding, string); for (i = 1; i < mblen; i++) CopySendChar(string[i]); --- 3021,3029 ---- if (!same_encoding) { ! /* ! * send additional bytes of the char, if any ! */ mblen = pg_encoding_mblen(client_encoding, string); for (i = 1; i < mblen; i++) CopySendChar(string[i]); *************** *** 2759,2765 **** if (attnamelist == NIL) { ! /* Generate default column list */ TupleDesc tupDesc = RelationGetDescr(rel); Form_pg_attribute *attr = tupDesc->attrs; int attr_count = tupDesc->natts; --- 3050,3058 ---- if (attnamelist == NIL) { ! /* ! * Generate default column list ! */ TupleDesc tupDesc = RelationGetDescr(rel); Form_pg_attribute *attr = tupDesc->attrs; int attr_count = tupDesc->natts; *************** *** 2774,2780 **** } else { ! /* Validate the user-supplied list and extract attnums */ ListCell *l; foreach(l, attnamelist) --- 3067,3075 ---- } else { ! /* ! * Validate the user-supplied list and extract attnums ! */ ListCell *l; foreach(l, attnamelist) *************** *** 2782,2791 **** char *name = strVal(lfirst(l)); int attnum; ! /* Lookup column name, ereport on failure */ ! /* Note we disallow system columns here */ attnum = attnameAttNum(rel, name, false); ! /* Check for duplicates */ if (list_member_int(attnums, attnum)) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_COLUMN), --- 3077,3092 ---- char *name = strVal(lfirst(l)); int attnum; ! /* ! * Lookup column name, ereport on failure ! */ ! /* ! * Note we disallow system columns here ! */ attnum = attnameAttNum(rel, name, false); ! /* ! * Check for duplicates ! */ if (list_member_int(attnums, attnum)) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_COLUMN),