<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/copy.sgml,v 1.56 2004/04/19 17:22:30 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/copy.sgml,v 1.57 2004/04/21 00:34:18 momjian Exp $
PostgreSQL documentation
-->
[ NULL [ AS ] '<replaceable class="parameter">null string</replaceable>' ]
[ CSV [ QUOTE [ AS ] '<replaceable class="parameter">quote</replaceable>' ]
[ ESCAPE [ AS ] '<replaceable class="parameter">escape</replaceable>' ]
- [ LITERAL <replaceable class="parameter">column</replaceable> [, ...] ]
+ [ FORCE NOT NULL <replaceable class="parameter">column</replaceable> [, ...] ]
COPY <replaceable class="parameter">tablename</replaceable> [ ( <replaceable class="parameter">column</replaceable> [, ...] ) ]
TO { '<replaceable class="parameter">filename</replaceable>' | STDOUT }
[ NULL [ AS ] '<replaceable class="parameter">null string</replaceable>' ]
[ CSV [ QUOTE [ AS ] '<replaceable class="parameter">quote</replaceable>' ]
[ ESCAPE [ AS ] '<replaceable class="parameter">escape</replaceable>' ]
- [ FORCE <replaceable class="parameter">column</replaceable> [, ...] ]
+ [ FORCE QUOTE <replaceable class="parameter">column</replaceable> [, ...] ]
</synopsis>
</refsynopsisdiv>
<term><literal>CSV</literal></term>
<listitem>
<para>
- Enables Comma Separated Variable (<literal>CSV</>) mode. (Also called
- Comma Separated Value). It sets the default <literal>DELIMITER</> to
- comma, and <literal>QUOTE</> and <literal>ESCAPE</> values to
- double-quote.
+ Enables Comma Separated Variable (<literal>CSV</>) mode. (Also
+ called Comma Separated Value). It sets the default
+ <literal>DELIMITER</> to comma, and <literal>QUOTE</> and
+ <literal>ESCAPE</> values to double-quote.
</para>
</listitem>
</varlistentry>
<term><replaceable class="parameter">escape</replaceable></term>
<listitem>
<para>
- Specifies the character that should appear before a <literal>QUOTE</>
- data character value in <literal>CSV</> mode. The default is the
- <literal>QUOTE</> value (usually double-quote).
+ Specifies the character that should appear before a
+ <literal>QUOTE</> data character value in <literal>CSV</> mode.
+ The default is the <literal>QUOTE</> value (usually double-quote).
</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><literal>FORCE</></term>
+ <term><literal>FORCE QUOTE</></term>
<listitem>
<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.
+ 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.
</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><literal>LITERAL</></term>
+ <term><literal>FORCE NOT NULL</></term>
<listitem>
<para>
- In <literal>CSV</> <command>COPY FROM</> mode, for each column specified,
- do not do a <literal>null string</> comparison; instead load the value
- literally. <literal>QUOTE</> and <literal>ESCAPE</> processing are still
- performed.
- </para>
- <para>
- If the <literal>null string</> is <literal>''</> (the default
- in <literal>CSV</> mode), a missing input value (<literal>delimiter,
- delimiter</>), will load as a zero-length string. <literal>Delimiter, quote,
- quote, delimiter</> is always treated as a zero-length string on input.
+ In <literal>CSV</> <command>COPY FROM</> mode, process each
+ specified column as though it were quoted and hance not a
+ <literal>NULL</> value. For the default <literal>null string</> in
+ <literal>CSV</> mode (<literal>''</>), this causes a missing
+ values to be input as a zero-length strings.
</para>
</listitem>
</varlistentry>
suffixed by the <literal>QUOTE</> character, and any occurrence
within the value of a <literal>QUOTE</> character or the
<literal>ESCAPE</> character is preceded by the escape character.
- You can also use <literal>FORCE</> to force quotes when outputting
+ You can also use <literal>FORCE QUOTE</> to force quotes when outputting
non-<literal>NULL</> values in specific columns.
</para>
is quoted. Therefore, using the default settings, a <literal>NULL</> is
written as an unquoted empty string, while an empty string is
written with double quotes (<literal>""</>). Reading values follows
- similar rules. You can use <literal>LITERAL</> to prevent <literal>NULL</>
+ similar rules. You can use <literal>FORCE NOT NULL</> to prevent <literal>NULL</>
input comparisons for specific columns.
</para>
<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.111 2004/04/19 17:22:30 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.112 2004/04/21 00:34:18 momjian Exp $
PostgreSQL documentation
-->
[ <literal>null [as] </literal> '<replaceable class="parameter">string</replaceable>' ]</literal>
[ <literal>csv [ quote [as] </literal> '<replaceable class="parameter">character</replaceable>' ]
[ <literal>escape [as] </literal> '<replaceable class="parameter">character</replaceable>' ]
- [ <literal>force</> <replaceable class="parameter">column_list</replaceable> ]
- [ <literal>literal</> <replaceable class="parameter">column_list</replaceable> ] ]
+ [ <literal>force quote</> <replaceable class="parameter">column_list</replaceable> ]
+ [ <literal>force not null</> <replaceable class="parameter">column_list</replaceable> ] ]
</term>
<listitem>
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.222 2004/04/19 21:58:02 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.223 2004/04/21 00:34:18 momjian Exp $
*
*-------------------------------------------------------------------------
*/
/* non-export function prototypes */
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_atts);
+ List *force_quote_atts);
static void CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
char *delim, char *null_print, bool csv_mode, char *quote, char *escape,
- List *literal_atts);
+ List *force_notnull_atts);
static bool CopyReadLine(void);
static char *CopyReadAttribute(const char *delim, const char *null_print,
CopyReadResult *result, bool *isnull);
char *quote = NULL;
char *escape = NULL;
char *null_print = NULL;
- List *force = NIL;
- List *literal = NIL;
- List *force_atts = NIL;
- List *literal_atts = NIL;
+ List *force_quote = NIL;
+ List *force_notnull = NIL;
+ List *force_quote_atts = NIL;
+ List *force_notnull_atts = NIL;
Relation rel;
AclMode required_access = (is_from ? ACL_INSERT : ACL_SELECT);
AclResult aclresult;
errmsg("conflicting or redundant options")));
escape = strVal(defel->arg);
}
- else if (strcmp(defel->defname, "force") == 0)
+ else if (strcmp(defel->defname, "force_quote") == 0)
{
- if (force)
+ if (force_quote)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
- force = (List *)defel->arg;
+ force_quote = (List *)defel->arg;
}
- else if (strcmp(defel->defname, "literal") == 0)
+ else if (strcmp(defel->defname, "force_notnull") == 0)
{
- if (literal)
+ if (force_notnull)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
- literal = (List *)defel->arg;
+ force_notnull = (List *)defel->arg;
}
else
elog(ERROR, "option \"%s\" not recognized",
errmsg("COPY escape must be a single character")));
/*
- * Check force
+ * Check force_quote
*/
- if (!csv_mode && force != NIL)
+ if (!csv_mode && force_quote != NIL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("COPY force available only in CSV mode")));
- if (force != NIL && is_from)
+ errmsg("COPY force quote available only in CSV mode")));
+ if (force_quote != NIL && is_from)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("COPY force only available using COPY TO")));
+ errmsg("COPY force quote only available using COPY TO")));
/*
- * Check literal
+ * Check force_notnull
*/
- if (!csv_mode && literal != NIL)
+ if (!csv_mode && force_notnull != NIL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("COPY literal available only in CSV mode")));
- if (literal != NIL && !is_from)
+ 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 literal only available using COPY FROM")));
+ errmsg("COPY force not null only available using COPY FROM")));
/*
* Don't allow the delimiter to appear in the null string.
attnumlist = CopyGetAttnums(rel, attnamelist);
/*
- * Check that FORCE references valid COPY columns
+ * Check that FORCE QUOTE references valid COPY columns
*/
- if (force)
+ if (force_quote)
{
TupleDesc tupDesc = RelationGetDescr(rel);
Form_pg_attribute *attr = tupDesc->attrs;
List *cur;
- force_atts = CopyGetAttnums(rel, force);
+ force_quote_atts = CopyGetAttnums(rel, force_quote);
- foreach(cur, force_atts)
+ foreach(cur, force_quote_atts)
{
int attnum = lfirsti(cur);
if (!intMember(attnum, attnumlist))
ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
- errmsg("FORCE column \"%s\" not referenced by COPY",
+ errmsg("FORCE QUOTE column \"%s\" not referenced by COPY",
NameStr(attr[attnum - 1]->attname))));
}
}
/*
- * Check that LITERAL references valid COPY columns
+ * Check that FORCE NOT NULL references valid COPY columns
*/
- if (literal)
+ if (force_notnull)
{
List *cur;
TupleDesc tupDesc = RelationGetDescr(rel);
Form_pg_attribute *attr = tupDesc->attrs;
- literal_atts = CopyGetAttnums(rel, literal);
+ force_notnull_atts = CopyGetAttnums(rel, force_notnull);
- foreach(cur, literal_atts)
+ foreach(cur, force_notnull_atts)
{
int attnum = lfirsti(cur);
if (!intMember(attnum, attnumlist))
ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
- errmsg("LITERAL column \"%s\" not referenced by COPY",
+ errmsg("FORCE NOT NULL column \"%s\" not referenced by COPY",
NameStr(attr[attnum - 1]->attname))));
}
}
}
}
CopyFrom(rel, attnumlist, binary, oids, delim, null_print, csv_mode,
- quote, escape, literal_atts);
+ quote, escape, force_notnull_atts);
}
else
{ /* copy from database to file */
}
}
CopyTo(rel, attnumlist, binary, oids, delim, null_print, csv_mode,
- quote, escape, force_atts);
+ quote, escape, force_quote_atts);
}
if (!pipe)
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_atts)
+ char *escape, List *force_quote_atts)
{
HeapTuple tuple;
TupleDesc tupDesc;
&isvarlena[attnum - 1]);
fmgr_info(out_func_oid, &out_functions[attnum - 1]);
- if (intMember(attnum, force_atts))
+ if (intMember(attnum, force_quote_atts))
force_quote[attnum - 1] = true;
else
force_quote[attnum - 1] = false;
static void
CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
char *delim, char *null_print, bool csv_mode, char *quote,
- char *escape, List *literal_atts)
+ char *escape, List *force_notnull_atts)
{
HeapTuple tuple;
TupleDesc tupDesc;
Oid *elements;
Oid oid_in_element;
ExprState **constraintexprs;
- bool *literal_nullstr;
+ bool *force_notnull;
bool hasConstraints = false;
int attnum;
int i;
defmap = (int *) palloc((num_phys_attrs + 1) * sizeof(int));
defexprs = (ExprState **) palloc((num_phys_attrs + 1) * sizeof(ExprState *));
constraintexprs = (ExprState **) palloc0((num_phys_attrs + 1) * sizeof(ExprState *));
- literal_nullstr = (bool *) palloc((num_phys_attrs + 1) * sizeof(bool));
+ force_notnull = (bool *) palloc((num_phys_attrs + 1) * sizeof(bool));
for (attnum = 1; attnum <= num_phys_attrs; attnum++)
{
&in_func_oid, &elements[attnum - 1]);
fmgr_info(in_func_oid, &in_functions[attnum - 1]);
- if (intMember(attnum, literal_atts))
- literal_nullstr[attnum - 1] = true;
+ if (intMember(attnum, force_notnull_atts))
+ force_notnull[attnum - 1] = true;
else
- literal_nullstr[attnum - 1] = false;
+ force_notnull[attnum - 1] = false;
/* Get default info if needed */
if (!intMember(attnum, attnumlist))
string = CopyReadAttribute(delim, null_print,
&result, &isnull);
- if (csv_mode && isnull && literal_nullstr[m])
+ if (csv_mode && isnull && force_notnull[m])
{
string = null_print; /* set to NULL string */
isnull = false;
pfree(defmap);
pfree(defexprs);
pfree(constraintexprs);
- pfree(literal_nullstr);
+ pfree(force_notnull);
ExecDropTupleTable(tupleTable, true);
*/
static void
CopyAttributeOutCSV(char *server_string, char *delim, char *quote,
- char *escape, bool force_quote)
+ char *escape, bool use_quote)
{
char *string;
char c;
char delimc = delim[0];
char quotec = quote[0];
char escapec = escape[0];
- bool need_quote = force_quote;
char *test_string;
bool same_encoding;
int mblen;
*/
for(test_string = string;
- !need_quote && (c = *test_string) != '\0';
+ !use_quote && (c = *test_string) != '\0';
test_string += mblen)
{
if (c == delimc || c == quotec || c == '\n' || c == '\r')
- need_quote = true;
+ use_quote = true;
if (!same_encoding)
mblen = pg_encoding_mblen(client_encoding, test_string);
else
mblen = 1;
}
- if (need_quote)
+ if (use_quote)
CopySendChar(quotec);
for (; (c = *string) != '\0'; string += mblen)
{
- if (need_quote && (c == quotec || c == escapec))
+ if (use_quote && (c == quotec || c == escapec))
CopySendChar(escapec);
CopySendChar(c);
mblen = 1;
}
- if (need_quote)
+ if (use_quote)
CopySendChar(quotec);
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.451 2004/04/19 17:22:30 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.452 2004/04/21 00:34:18 momjian Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
KEY
LANCOMPILER LANGUAGE LARGE_P LAST_P LEADING LEFT LEVEL LIKE LIMIT
- LISTEN LITERAL LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION
+ LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION
LOCK_P
MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
{
$$ = makeDefElem("escape", (Node *)makeString($3));
}
- | FORCE columnList
+ | FORCE QUOTE columnList
{
- $$ = makeDefElem("force", (Node *)$2);
+ $$ = makeDefElem("force_quote", (Node *)$3);
}
- | LITERAL columnList
+ | FORCE NOT NULL_P columnList
{
- $$ = makeDefElem("literal", (Node *)$2);
+ $$ = makeDefElem("force_notnull", (Node *)$4);
}
;
| LAST_P
| LEVEL
| LISTEN
- | LITERAL
| LOAD
| LOCAL
| LOCATION
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.148 2004/04/19 17:22:31 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.149 2004/04/21 00:34:18 momjian Exp $
*
*-------------------------------------------------------------------------
*/
{"like", LIKE},
{"limit", LIMIT},
{"listen", LISTEN},
- {"literal", LITERAL},
{"load", LOAD},
{"local", LOCAL},
{"localtime", LOCALTIME},
*
* Copyright (c) 2000-2003, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/bin/psql/copy.c,v 1.45 2004/04/19 17:42:58 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/copy.c,v 1.46 2004/04/21 00:34:18 momjian Exp $
*/
#include "postgres_fe.h"
#include "copy.h"
char *null;
char *quote;
char *escape;
- char *force_list;
- char *literal_list;
+ char *force_quote_list;
+ char *force_notnull_list;
};
free(ptr->null);
free(ptr->quote);
free(ptr->escape);
- free(ptr->force_list);
- free(ptr->literal_list);
+ free(ptr->force_quote_list);
+ free(ptr->force_notnull_list);
free(ptr);
}
}
else if (strcasecmp(token, "force") == 0)
{
- /* handle column list */
- fetch_next = false;
- for (;;)
+ token = strtokx(NULL, whitespace, ",", "\"",
+ 0, false, pset.encoding);
+ if (strcasecmp(token, "quote") == 0)
{
- token = strtokx(NULL, whitespace, ",", "\"",
- 0, false, pset.encoding);
- if (!token || strchr(",", token[0]))
- goto error;
- if (!result->force_list)
- result->force_list = pg_strdup(token);
- else
- xstrcat(&result->force_list, token);
- token = strtokx(NULL, whitespace, ",", "\"",
- 0, false, pset.encoding);
- if (!token || token[0] != ',')
- break;
- xstrcat(&result->force_list, token);
+ /* handle column list */
+ fetch_next = false;
+ for (;;)
+ {
+ token = strtokx(NULL, whitespace, ",", "\"",
+ 0, false, pset.encoding);
+ if (!token || strchr(",", token[0]))
+ goto error;
+ if (!result->force_quote_list)
+ result->force_quote_list = pg_strdup(token);
+ else
+ xstrcat(&result->force_quote_list, token);
+ token = strtokx(NULL, whitespace, ",", "\"",
+ 0, false, pset.encoding);
+ if (!token || token[0] != ',')
+ break;
+ xstrcat(&result->force_quote_list, token);
+ }
}
- }
- else if (strcasecmp(token, "literal") == 0)
- {
- /* handle column list */
- fetch_next = false;
- for (;;)
+ else if (strcasecmp(token, "not") == 0)
{
token = strtokx(NULL, whitespace, ",", "\"",
0, false, pset.encoding);
- if (!token || strchr(",", token[0]))
+ if (strcasecmp(token, "null") != 0)
goto error;
- if (!result->literal_list)
- result->literal_list = pg_strdup(token);
- else
- xstrcat(&result->literal_list, token);
- token = strtokx(NULL, whitespace, ",", "\"",
- 0, false, pset.encoding);
- if (!token || token[0] != ',')
- break;
- xstrcat(&result->literal_list, token);
+ /* handle column list */
+ fetch_next = false;
+ for (;;)
+ {
+ token = strtokx(NULL, whitespace, ",", "\"",
+ 0, false, pset.encoding);
+ if (!token || strchr(",", token[0]))
+ goto error;
+ if (!result->force_notnull_list)
+ result->force_notnull_list = pg_strdup(token);
+ else
+ xstrcat(&result->force_notnull_list, token);
+ token = strtokx(NULL, whitespace, ",", "\"",
+ 0, false, pset.encoding);
+ if (!token || token[0] != ',')
+ break;
+ xstrcat(&result->force_notnull_list, token);
+ }
}
+ else
+ goto error;
}
else
goto error;
appendPQExpBuffer(&query, " ESCAPE AS '%s'", options->escape);
}
- if (options->force_list)
+ if (options->force_quote_list)
{
- appendPQExpBuffer(&query, " FORCE %s", options->force_list);
+ appendPQExpBuffer(&query, " FORCE QUOTE %s", options->force_quote_list);
}
- if (options->literal_list)
+ if (options->force_notnull_list)
{
- appendPQExpBuffer(&query, " LITERAL %s", options->literal_list);
+ appendPQExpBuffer(&query, " FORCE NOT NULL %s", options->force_notnull_list);
}
if (options->from)