diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 60611398173310dcd60a48c519cf4372919081a6..613a7c2f3c1101883edb35fe4e21d50990bfed3b 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.97 2000/01/19 23:54:56 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.98 2000/01/22 03:52:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -137,7 +137,8 @@ CopySendChar(char c, FILE *fp)
  *	backend->frontend functions
  *
  * CopyGetChar does the same for single characters
- * CopyGetEof checks if it's EOF on the input
+ * CopyGetEof checks if it's EOF on the input (or, check for EOF result
+ *		from CopyGetChar)
  *
  * NB: no data conversion is applied by these functions
  */
@@ -1106,18 +1107,6 @@ GetIndexRelations(Oid main_relation_oid,
 	}
 }
 
-
-/*
-   returns 1 if c is in s
-*/
-static bool
-inString(char c, char *s)
-{
-	if (s && c)
-		return strchr(s, c) != NULL;
-	return 0;
-}
-
 /*
  * Reads input from fp until an end of line is seen.
  */
@@ -1171,19 +1160,24 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_
 
 	*isnull = (bool) false;		/* set default */
 
-	if (CopyGetEof(fp))
-		goto endOfFile;
-
 	for (;;)
 	{
 		c = CopyGetChar(fp);
-		if (CopyGetEof(fp))
+		if (c == EOF)
 			goto endOfFile;
-
+		if (c == '\n')
+		{
+			*newline = 1;
+			break;
+		}
+		if (strchr(delim, c))
+		{
+			break;
+		}
 		if (c == '\\')
 		{
 			c = CopyGetChar(fp);
-			if (CopyGetEof(fp))
+			if (c == EOF)
 				goto endOfFile;
 			switch (c)
 			{
@@ -1213,14 +1207,14 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_
 							}
 							else
 							{
-								if (CopyGetEof(fp))
+								if (c == EOF)
 									goto endOfFile;
 								CopyDonePeek(fp, c, 0); /* Return to stream! */
 							}
 						}
 						else
 						{
-							if (CopyGetEof(fp))
+							if (c == EOF)
 								goto endOfFile;
 							CopyDonePeek(fp, c, 0);		/* Return to stream! */
 						}
@@ -1231,7 +1225,7 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_
                        rather then just 'N' to provide compatibility with
                        the default NULL output. -- pe */
                 case 'N':
-                    appendStringInfoChar(&attribute_buf, '\\');
+                    appendStringInfoCharMacro(&attribute_buf, '\\');
                     c = 'N';
                     break;
 				case 'b':
@@ -1257,16 +1251,9 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_
 					if (c != '\n')
 						elog(ERROR, "CopyReadAttribute - end of record marker corrupted. line: %d", lineno);
 					goto endOfFile;
-					break;
 			}
 		}
-		else if (c == '\n' || inString(c, delim))
-		{
-			if (c == '\n')
-				*newline = 1;
-			break;
-		}
-		appendStringInfoChar(&attribute_buf, c);
+		appendStringInfoCharMacro(&attribute_buf, c);
 #ifdef MULTIBYTE
 		/* get additional bytes of the char, if any */
 		s[0] = c;
@@ -1274,9 +1261,9 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_
 		for (j = 1; j < mblen; j++)
 		{
 			c = CopyGetChar(fp);
-			if (CopyGetEof(fp))
+			if (c == EOF)
 				goto endOfFile;
-			appendStringInfoChar(&attribute_buf, c);
+			appendStringInfoCharMacro(&attribute_buf, c);
 		}
 #endif
 	}
diff --git a/src/include/lib/stringinfo.h b/src/include/lib/stringinfo.h
index afdad2f8d32490130a0f0d17ccb4e56d3f2d63fd..03fc88accc507034b1577f4cb01cfc0149fa831d 100644
--- a/src/include/lib/stringinfo.h
+++ b/src/include/lib/stringinfo.h
@@ -9,7 +9,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: stringinfo.h,v 1.14 1999/08/31 01:28:21 tgl Exp $
+ * $Id: stringinfo.h,v 1.15 2000/01/22 03:52:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -89,12 +89,22 @@ extern void appendStringInfo(StringInfo str, const char *fmt,...);
  */
 extern void appendStringInfoChar(StringInfo str, char ch);
 
+/*------------------------
+ * appendStringInfoCharMacro
+ * As above, but a macro for even more speed where it matters.
+ * Caution: str argument will be evaluated multiple times.
+ */
+#define appendStringInfoCharMacro(str,ch) \
+	(((str)->len + 1 >= (str)->maxlen) ? \
+	 appendStringInfoChar(str, ch) : \
+	 ((str)->data[(str)->len] = (ch), (str)->data[++(str)->len] = '\0'))
+
 /*------------------------
  * appendBinaryStringInfo
  * Append arbitrary binary data to a StringInfo, allocating more space
  * if necessary.
  */
 extern void appendBinaryStringInfo(StringInfo str,
-					   const char *data, int datalen);
+								   const char *data, int datalen);
 
 #endif	 /* STRINGINFO_H */