Index: src/backend/commands/copy.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/commands/copy.c,v
retrieving revision 1.295
diff -c -r1.295 copy.c
*** src/backend/commands/copy.c	1 Jan 2008 19:45:48 -0000	1.295
--- src/backend/commands/copy.c	29 Feb 2008 20:57:09 -0000
***************
*** 2913,2919 ****
  	for (;;)
  	{
  		bool		found_delim = false;
- 		bool		in_quote = false;
  		bool		saw_quote = false;
  		char	   *start_ptr;
  		char	   *end_ptr;
--- 3146,3151 ----
***************
*** 2934,3000 ****
  		{
  			char		c;
  
! 			end_ptr = cur_ptr;
! 			if (cur_ptr >= line_end_ptr)
! 				break;
! 			c = *cur_ptr++;
! 			/* unquoted field delimiter */
! 			if (c == delimc && !in_quote)
  			{
! 				found_delim = true;
! 				break;
! 			}
! 			/* start of quoted field (or part of field) */
! 			if (c == quotec && !in_quote)
! 			{
! 				saw_quote = true;
! 				in_quote = true;
! 				continue;
  			}
! 			/* escape within a quoted field */
! 			if (c == escapec && in_quote)
  			{
! 				/*
! 				 * peek at the next char if available, and escape it if it is
! 				 * an escape char or a quote char
! 				 */
! 				if (cur_ptr < line_end_ptr)
! 				{
! 					char		nextc = *cur_ptr;
  
! 					if (nextc == escapec || nextc == quotec)
  					{
! 						*output_ptr++ = nextc;
! 						cur_ptr++;
! 						continue;
  					}
  				}
! 			}
  
! 			/*
! 			 * end of quoted field. Must do this test after testing for escape
! 			 * in case quote char and escape char are the same (which is the
! 			 * common case).
! 			 */
! 			if (c == quotec && in_quote)
! 			{
! 				in_quote = false;
! 				continue;
  			}
- 
- 			/* Add c to output string */
- 			*output_ptr++ = c;
  		}
  
  		/* Terminate attribute value in output area */
  		*output_ptr++ = '\0';
  
- 		/* Shouldn't still be in quote mode */
- 		if (in_quote)
- 			ereport(ERROR,
- 					(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
- 					 errmsg("unterminated CSV quoted field")));
- 
  		/* Check whether raw input matched null marker */
  		input_len = end_ptr - start_ptr;
  		if (!saw_quote && input_len == cstate->null_print_len &&
--- 3166,3241 ----
  		{
  			char		c;
  
! 			/* Not in quote */
! 			for (;;)
  			{
! 				end_ptr = cur_ptr;
! 				if (cur_ptr >= line_end_ptr)
! 					goto endfield;
! 				c = *cur_ptr++;
! 				/* unquoted field delimiter */
! 				if (c == delimc)
! 				{
! 					found_delim = true;
! 					goto endfield;
! 				}
! 				/* start of quoted field (or part of field) */
! 				if (c == quotec)
! 				{
! 					saw_quote = true;
! 					break;
! 				}
! 				/* Add c to output string */
! 				*output_ptr++ = c;
  			}
! 
! 			/* In quote */
! 			for (;;)
  			{
! 				end_ptr = cur_ptr;
! 				if (cur_ptr >= line_end_ptr)
! 					ereport(ERROR,
! 							(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
! 							 errmsg("unterminated CSV quoted field")));
  
! 				c = *cur_ptr++;
! 
! 				/* escape within a quoted field */
! 				if (c == escapec)
! 				{
! 					/*
! 					 * peek at the next char if available, and escape it if it is
! 					 * an escape char or a quote char
! 					 */
! 					if (cur_ptr < line_end_ptr)
  					{
! 						char		nextc = *cur_ptr;
! 
! 						if (nextc == escapec || nextc == quotec)
! 						{
! 							*output_ptr++ = nextc;
! 							cur_ptr++;
! 							continue;
! 						}
  					}
  				}
! 				/*
! 				 * end of quoted field. Must do this test after testing for escape
! 				 * in case quote char and escape char are the same (which is the
! 				 * common case).
! 				 */
! 				if (c == quotec)
! 					break;
  
! 				/* Add c to output string */
! 				*output_ptr++ = c;
  			}
  		}
+ 	endfield:
  
  		/* Terminate attribute value in output area */
  		*output_ptr++ = '\0';
  
  		/* Check whether raw input matched null marker */
  		input_len = end_ptr - start_ptr;
  		if (!saw_quote && input_len == cstate->null_print_len &&
