summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Dunstan2009-07-25 00:07:14 +0000
committerAndrew Dunstan2009-07-25 00:07:14 +0000
commita04d1c68b9b32a07fe07e85fad2d70dc516466b0 (patch)
treee9e7313dc026fee5640cb882c3a3f13d4c936e04
parenta82304c098678c4c335a1713a01fe63487df684c (diff)
Allow * as parameter for FORCE QUOTE for COPY CSV. Itagaki Takahiro.
-rw-r--r--doc/src/sgml/ref/copy.sgml6
-rw-r--r--src/backend/commands/copy.c18
-rw-r--r--src/backend/parser/gram.y4
-rw-r--r--src/test/regress/expected/copy2.out4
-rw-r--r--src/test/regress/sql/copy2.sql1
5 files changed, 29 insertions, 4 deletions
diff --git a/doc/src/sgml/ref/copy.sgml b/doc/src/sgml/ref/copy.sgml
index 75e7a816f7..c09dd60920 100644
--- a/doc/src/sgml/ref/copy.sgml
+++ b/doc/src/sgml/ref/copy.sgml
@@ -44,7 +44,7 @@ COPY { <replaceable class="parameter">tablename</replaceable> [ ( <replaceable c
[ CSV [ HEADER ]
[ QUOTE [ AS ] '<replaceable class="parameter">quote</replaceable>' ]
[ ESCAPE [ AS ] '<replaceable class="parameter">escape</replaceable>' ]
- [ FORCE QUOTE <replaceable class="parameter">column</replaceable> [, ...] ]
+ [ FORCE QUOTE { <replaceable class="parameter">column</replaceable> [, ...] | * } ]
</synopsis>
</refsynopsisdiv>
@@ -248,7 +248,9 @@ COPY { <replaceable class="parameter">tablename</replaceable> [ ( <replaceable c
<para>
In <literal>CSV</> <command>COPY TO</> mode, forces quoting to be
used for all non-<literal>NULL</> values in each specified column.
- <literal>NULL</> output is never quoted.
+ <literal>NULL</> output is never quoted. If <literal>*</> is specified,
+ non-<literal>NULL</> values for all columns of the table will be
+ quoted.
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index a1519998d3..9ee8ea2c82 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -730,6 +730,9 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
int num_phys_attrs;
uint64 processed;
+ /* a dummy list that represents 'all-columns' */
+ List all_columns = { T_List };
+
/* Allocate workspace and zero all fields */
cstate = (CopyStateData *) palloc0(sizeof(CopyStateData));
@@ -808,7 +811,11 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
- force_quote = (List *) defel->arg;
+
+ if (IsA(defel->arg, A_Star))
+ force_quote = &all_columns;
+ else
+ force_quote = (List *) defel->arg;
}
else if (strcmp(defel->defname, "force_notnull") == 0)
{
@@ -1092,7 +1099,14 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
/* Convert FORCE QUOTE name list to per-column flags, check validity */
cstate->force_quote_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
- if (force_quote)
+ if (force_quote == &all_columns)
+ {
+ int i;
+
+ for (i = 0; i < num_phys_attrs; i++)
+ cstate->force_quote_flags[i] = true;
+ }
+ else if (force_quote)
{
List *attnums;
ListCell *cur;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index eb786e96ea..38ee5585c0 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -2028,6 +2028,10 @@ copy_opt_item:
{
$$ = makeDefElem("force_quote", (Node *)$3);
}
+ | FORCE QUOTE '*'
+ {
+ $$ = makeDefElem("force_quote", (Node *)makeNode(A_Star));
+ }
| FORCE NOT NULL_P columnList
{
$$ = makeDefElem("force_notnull", (Node *)$4);
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index 7f374ac1a6..5f52d6ee6c 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -191,6 +191,10 @@ COPY y TO stdout WITH CSV FORCE QUOTE col2 ESCAPE E'\\';
"Jackson, Sam","\\h"
"It is \"perfect\"."," "
"",
+COPY y TO stdout WITH CSV FORCE QUOTE *;
+"Jackson, Sam","\h"
+"It is ""perfect""."," "
+"",
--test that we read consecutive LFs properly
CREATE TEMP TABLE testnl (a int, b text, c int);
COPY testnl FROM stdin CSV;
diff --git a/src/test/regress/sql/copy2.sql b/src/test/regress/sql/copy2.sql
index 7c23ba253c..9dee93c14c 100644
--- a/src/test/regress/sql/copy2.sql
+++ b/src/test/regress/sql/copy2.sql
@@ -128,6 +128,7 @@ INSERT INTO y VALUES ('', NULL);
COPY y TO stdout WITH CSV;
COPY y TO stdout WITH CSV QUOTE '''' DELIMITER '|';
COPY y TO stdout WITH CSV FORCE QUOTE col2 ESCAPE E'\\';
+COPY y TO stdout WITH CSV FORCE QUOTE *;
--test that we read consecutive LFs properly