diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/commands/copy.c | 40 | ||||
-rw-r--r-- | src/test/regress/expected/copy2.out | 3 | ||||
-rw-r--r-- | src/test/regress/sql/copy2.sql | 10 |
3 files changed, 39 insertions, 14 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index e79c6c4eb78..4e6a4606318 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.254.2.2 2005/12/27 18:10:57 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.254.2.3 2005/12/28 05:38:26 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -180,7 +180,7 @@ static Datum CopyReadBinaryAttribute(CopyState cstate, bool *isnull); static void CopyAttributeOutText(CopyState cstate, char *server_string); static void CopyAttributeOutCSV(CopyState cstate, char *server_string, - bool use_quote); + bool use_quote, bool single_attr); static List *CopyGetAttnums(Relation rel, List *attnamelist); static char *limit_printout_length(const char *str); @@ -1219,7 +1219,8 @@ CopyTo(CopyState cstate) colname = NameStr(attr[attnum - 1]->attname); - CopyAttributeOutCSV(cstate, colname, false); + CopyAttributeOutCSV(cstate, colname, false, + list_length(cstate->attnumlist) == 1); } CopySendEndOfRow(cstate); @@ -1294,7 +1295,8 @@ CopyTo(CopyState cstate) value)); if (cstate->csv_mode) CopyAttributeOutCSV(cstate, string, - force_quote[attnum - 1]); + force_quote[attnum - 1], + list_length(cstate->attnumlist) == 1); else CopyAttributeOutText(cstate, string); } @@ -3172,7 +3174,7 @@ CopyAttributeOutText(CopyState cstate, char *server_string) */ static void CopyAttributeOutCSV(CopyState cstate, char *server_string, - bool use_quote) + bool use_quote, bool single_attr) { char *string; char c; @@ -3197,17 +3199,27 @@ CopyAttributeOutCSV(CopyState cstate, char *server_string, */ if (!use_quote) { - for (tstring = string; (c = *tstring) != '\0'; tstring += mblen) - { - if (c == delimc || c == quotec || c == '\n' || c == '\r') + /* + * Because '\.' can be a data value, quote it if it appears + * alone on a line so it is not interpreted as the end-of-data + * marker. + */ + if (single_attr && strcmp(string, "\\.") == 0) + use_quote = true; + else + { + for (tstring = string; (c = *tstring) != '\0'; tstring += mblen) { - use_quote = true; - break; + if (c == delimc || c == quotec || c == '\n' || c == '\r') + { + use_quote = true; + break; + } + if (cstate->client_only_encoding) + mblen = pg_encoding_mblen(cstate->client_encoding, tstring); + else + mblen = 1; } - if (cstate->client_only_encoding) - mblen = pg_encoding_mblen(cstate->client_encoding, tstring); - else - mblen = 1; } } diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out index 78f20605702..524e88cbae6 100644 --- a/src/test/regress/expected/copy2.out +++ b/src/test/regress/expected/copy2.out @@ -194,6 +194,9 @@ COPY y TO stdout WITH CSV FORCE QUOTE col2 ESCAPE E'\\'; --test that we read consecutive LFs properly CREATE TEMP TABLE testnl (a int, b text, c int); COPY testnl FROM stdin CSV; +-- test end of copy marker +CREATE TEMP TABLE testeoc (a text); +COPY testeoc FROM stdin CSV; DROP TABLE x, y; DROP FUNCTION fn_x_before(); DROP FUNCTION fn_x_after(); diff --git a/src/test/regress/sql/copy2.sql b/src/test/regress/sql/copy2.sql index add8214d19d..d962d2e048e 100644 --- a/src/test/regress/sql/copy2.sql +++ b/src/test/regress/sql/copy2.sql @@ -139,6 +139,16 @@ COPY testnl FROM stdin CSV; inside",2 \. +-- test end of copy marker +CREATE TEMP TABLE testeoc (a text); + +COPY testeoc FROM stdin CSV; +a\. +\.b +c\.d +"\." +\. + DROP TABLE x, y; DROP FUNCTION fn_x_before(); |