mirror of
https://github.com/postgres/postgres.git
synced 2025-06-23 14:01:44 +03:00
Change COPY CSV keyword to be:
FORCE QUOTE to force quotes FORCE NOT NULL to quote null input values
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$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
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ COPY <replaceable class="parameter">tablename</replaceable> [ ( <replaceable cla
|
|||||||
[ NULL [ AS ] '<replaceable class="parameter">null string</replaceable>' ]
|
[ NULL [ AS ] '<replaceable class="parameter">null string</replaceable>' ]
|
||||||
[ CSV [ QUOTE [ AS ] '<replaceable class="parameter">quote</replaceable>' ]
|
[ CSV [ QUOTE [ AS ] '<replaceable class="parameter">quote</replaceable>' ]
|
||||||
[ ESCAPE [ AS ] '<replaceable class="parameter">escape</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> [, ...] ) ]
|
COPY <replaceable class="parameter">tablename</replaceable> [ ( <replaceable class="parameter">column</replaceable> [, ...] ) ]
|
||||||
TO { '<replaceable class="parameter">filename</replaceable>' | STDOUT }
|
TO { '<replaceable class="parameter">filename</replaceable>' | STDOUT }
|
||||||
@ -40,7 +40,7 @@ COPY <replaceable class="parameter">tablename</replaceable> [ ( <replaceable cla
|
|||||||
[ NULL [ AS ] '<replaceable class="parameter">null string</replaceable>' ]
|
[ NULL [ AS ] '<replaceable class="parameter">null string</replaceable>' ]
|
||||||
[ CSV [ QUOTE [ AS ] '<replaceable class="parameter">quote</replaceable>' ]
|
[ CSV [ QUOTE [ AS ] '<replaceable class="parameter">quote</replaceable>' ]
|
||||||
[ ESCAPE [ AS ] '<replaceable class="parameter">escape</replaceable>' ]
|
[ ESCAPE [ AS ] '<replaceable class="parameter">escape</replaceable>' ]
|
||||||
[ FORCE <replaceable class="parameter">column</replaceable> [, ...] ]
|
[ FORCE QUOTE <replaceable class="parameter">column</replaceable> [, ...] ]
|
||||||
</synopsis>
|
</synopsis>
|
||||||
</refsynopsisdiv>
|
</refsynopsisdiv>
|
||||||
|
|
||||||
@ -185,10 +185,10 @@ COPY <replaceable class="parameter">tablename</replaceable> [ ( <replaceable cla
|
|||||||
<term><literal>CSV</literal></term>
|
<term><literal>CSV</literal></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Enables Comma Separated Variable (<literal>CSV</>) mode. (Also called
|
Enables Comma Separated Variable (<literal>CSV</>) mode. (Also
|
||||||
Comma Separated Value). It sets the default <literal>DELIMITER</> to
|
called Comma Separated Value). It sets the default
|
||||||
comma, and <literal>QUOTE</> and <literal>ESCAPE</> values to
|
<literal>DELIMITER</> to comma, and <literal>QUOTE</> and
|
||||||
double-quote.
|
<literal>ESCAPE</> values to double-quote.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -207,38 +207,33 @@ COPY <replaceable class="parameter">tablename</replaceable> [ ( <replaceable cla
|
|||||||
<term><replaceable class="parameter">escape</replaceable></term>
|
<term><replaceable class="parameter">escape</replaceable></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Specifies the character that should appear before a <literal>QUOTE</>
|
Specifies the character that should appear before a
|
||||||
data character value in <literal>CSV</> mode. The default is the
|
<literal>QUOTE</> data character value in <literal>CSV</> mode.
|
||||||
<literal>QUOTE</> value (usually double-quote).
|
The default is the <literal>QUOTE</> value (usually double-quote).
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><literal>FORCE</></term>
|
<term><literal>FORCE QUOTE</></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
In <literal>CSV</> <command>COPY TO</> mode, forces quoting
|
In <literal>CSV</> <command>COPY TO</> mode, forces quoting to be
|
||||||
to be used for all non-<literal>NULL</> values in each specified
|
used for all non-<literal>NULL</> values in each specified column.
|
||||||
column. <literal>NULL</> output is never quoted.
|
<literal>NULL</> output is never quoted.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><literal>LITERAL</></term>
|
<term><literal>FORCE NOT NULL</></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
In <literal>CSV</> <command>COPY FROM</> mode, for each column specified,
|
In <literal>CSV</> <command>COPY FROM</> mode, process each
|
||||||
do not do a <literal>null string</> comparison; instead load the value
|
specified column as though it were quoted and hance not a
|
||||||
literally. <literal>QUOTE</> and <literal>ESCAPE</> processing are still
|
<literal>NULL</> value. For the default <literal>null string</> in
|
||||||
performed.
|
<literal>CSV</> mode (<literal>''</>), this causes a missing
|
||||||
</para>
|
values to be input as a zero-length strings.
|
||||||
<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.
|
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -483,7 +478,7 @@ COPY <replaceable class="parameter">tablename</replaceable> [ ( <replaceable cla
|
|||||||
suffixed by the <literal>QUOTE</> character, and any occurrence
|
suffixed by the <literal>QUOTE</> character, and any occurrence
|
||||||
within the value of a <literal>QUOTE</> character or the
|
within the value of a <literal>QUOTE</> character or the
|
||||||
<literal>ESCAPE</> character is preceded by the escape character.
|
<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.
|
non-<literal>NULL</> values in specific columns.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@ -496,7 +491,7 @@ COPY <replaceable class="parameter">tablename</replaceable> [ ( <replaceable cla
|
|||||||
is quoted. Therefore, using the default settings, a <literal>NULL</> is
|
is quoted. Therefore, using the default settings, a <literal>NULL</> is
|
||||||
written as an unquoted empty string, while an empty string is
|
written as an unquoted empty string, while an empty string is
|
||||||
written with double quotes (<literal>""</>). Reading values follows
|
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.
|
input comparisons for specific columns.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$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
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -713,8 +713,8 @@ testdb=>
|
|||||||
[ <literal>null [as] </literal> '<replaceable class="parameter">string</replaceable>' ]</literal>
|
[ <literal>null [as] </literal> '<replaceable class="parameter">string</replaceable>' ]</literal>
|
||||||
[ <literal>csv [ quote [as] </literal> '<replaceable class="parameter">character</replaceable>' ]
|
[ <literal>csv [ quote [as] </literal> '<replaceable class="parameter">character</replaceable>' ]
|
||||||
[ <literal>escape [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>force quote</> <replaceable class="parameter">column_list</replaceable> ]
|
||||||
[ <literal>literal</> <replaceable class="parameter">column_list</replaceable> ] ]
|
[ <literal>force not null</> <replaceable class="parameter">column_list</replaceable> ] ]
|
||||||
</term>
|
</term>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -132,10 +132,10 @@ static bool line_buf_converted;
|
|||||||
/* non-export function prototypes */
|
/* non-export function prototypes */
|
||||||
static void CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
|
static void CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||||
char *delim, char *null_print, bool csv_mode, char *quote, char *escape,
|
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,
|
static void CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||||
char *delim, char *null_print, bool csv_mode, char *quote, char *escape,
|
char *delim, char *null_print, bool csv_mode, char *quote, char *escape,
|
||||||
List *literal_atts);
|
List *force_notnull_atts);
|
||||||
static bool CopyReadLine(void);
|
static bool CopyReadLine(void);
|
||||||
static char *CopyReadAttribute(const char *delim, const char *null_print,
|
static char *CopyReadAttribute(const char *delim, const char *null_print,
|
||||||
CopyReadResult *result, bool *isnull);
|
CopyReadResult *result, bool *isnull);
|
||||||
@ -695,10 +695,10 @@ DoCopy(const CopyStmt *stmt)
|
|||||||
char *quote = NULL;
|
char *quote = NULL;
|
||||||
char *escape = NULL;
|
char *escape = NULL;
|
||||||
char *null_print = NULL;
|
char *null_print = NULL;
|
||||||
List *force = NIL;
|
List *force_quote = NIL;
|
||||||
List *literal = NIL;
|
List *force_notnull = NIL;
|
||||||
List *force_atts = NIL;
|
List *force_quote_atts = NIL;
|
||||||
List *literal_atts = NIL;
|
List *force_notnull_atts = NIL;
|
||||||
Relation rel;
|
Relation rel;
|
||||||
AclMode required_access = (is_from ? ACL_INSERT : ACL_SELECT);
|
AclMode required_access = (is_from ? ACL_INSERT : ACL_SELECT);
|
||||||
AclResult aclresult;
|
AclResult aclresult;
|
||||||
@ -764,21 +764,21 @@ DoCopy(const CopyStmt *stmt)
|
|||||||
errmsg("conflicting or redundant options")));
|
errmsg("conflicting or redundant options")));
|
||||||
escape = strVal(defel->arg);
|
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,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||||
errmsg("conflicting or redundant options")));
|
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,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||||
errmsg("conflicting or redundant options")));
|
errmsg("conflicting or redundant options")));
|
||||||
literal = (List *)defel->arg;
|
force_notnull = (List *)defel->arg;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
elog(ERROR, "option \"%s\" not recognized",
|
elog(ERROR, "option \"%s\" not recognized",
|
||||||
@ -850,28 +850,28 @@ DoCopy(const CopyStmt *stmt)
|
|||||||
errmsg("COPY escape must be a single character")));
|
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,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("COPY force available only in CSV mode")));
|
errmsg("COPY force quote available only in CSV mode")));
|
||||||
if (force != NIL && is_from)
|
if (force_quote != NIL && is_from)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(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,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("COPY literal available only in CSV mode")));
|
errmsg("COPY force not null available only in CSV mode")));
|
||||||
if (literal != NIL && !is_from)
|
if (force_notnull != NIL && !is_from)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(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.
|
* Don't allow the delimiter to appear in the null string.
|
||||||
@ -928,47 +928,47 @@ DoCopy(const CopyStmt *stmt)
|
|||||||
attnumlist = CopyGetAttnums(rel, attnamelist);
|
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);
|
TupleDesc tupDesc = RelationGetDescr(rel);
|
||||||
Form_pg_attribute *attr = tupDesc->attrs;
|
Form_pg_attribute *attr = tupDesc->attrs;
|
||||||
List *cur;
|
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);
|
int attnum = lfirsti(cur);
|
||||||
|
|
||||||
if (!intMember(attnum, attnumlist))
|
if (!intMember(attnum, attnumlist))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
(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))));
|
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;
|
List *cur;
|
||||||
TupleDesc tupDesc = RelationGetDescr(rel);
|
TupleDesc tupDesc = RelationGetDescr(rel);
|
||||||
Form_pg_attribute *attr = tupDesc->attrs;
|
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);
|
int attnum = lfirsti(cur);
|
||||||
|
|
||||||
if (!intMember(attnum, attnumlist))
|
if (!intMember(attnum, attnumlist))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
(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))));
|
NameStr(attr[attnum - 1]->attname))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1037,7 +1037,7 @@ DoCopy(const CopyStmt *stmt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
CopyFrom(rel, attnumlist, binary, oids, delim, null_print, csv_mode,
|
CopyFrom(rel, attnumlist, binary, oids, delim, null_print, csv_mode,
|
||||||
quote, escape, literal_atts);
|
quote, escape, force_notnull_atts);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* copy from database to file */
|
{ /* copy from database to file */
|
||||||
@ -1100,7 +1100,7 @@ DoCopy(const CopyStmt *stmt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
CopyTo(rel, attnumlist, binary, oids, delim, null_print, csv_mode,
|
CopyTo(rel, attnumlist, binary, oids, delim, null_print, csv_mode,
|
||||||
quote, escape, force_atts);
|
quote, escape, force_quote_atts);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pipe)
|
if (!pipe)
|
||||||
@ -1133,7 +1133,7 @@ DoCopy(const CopyStmt *stmt)
|
|||||||
static void
|
static void
|
||||||
CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
|
CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||||
char *delim, char *null_print, bool csv_mode, char *quote,
|
char *delim, char *null_print, bool csv_mode, char *quote,
|
||||||
char *escape, List *force_atts)
|
char *escape, List *force_quote_atts)
|
||||||
{
|
{
|
||||||
HeapTuple tuple;
|
HeapTuple tuple;
|
||||||
TupleDesc tupDesc;
|
TupleDesc tupDesc;
|
||||||
@ -1180,7 +1180,7 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
|
|||||||
&isvarlena[attnum - 1]);
|
&isvarlena[attnum - 1]);
|
||||||
fmgr_info(out_func_oid, &out_functions[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;
|
force_quote[attnum - 1] = true;
|
||||||
else
|
else
|
||||||
force_quote[attnum - 1] = false;
|
force_quote[attnum - 1] = false;
|
||||||
@ -1434,7 +1434,7 @@ limit_printout_length(StringInfo buf)
|
|||||||
static void
|
static void
|
||||||
CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||||
char *delim, char *null_print, bool csv_mode, char *quote,
|
char *delim, char *null_print, bool csv_mode, char *quote,
|
||||||
char *escape, List *literal_atts)
|
char *escape, List *force_notnull_atts)
|
||||||
{
|
{
|
||||||
HeapTuple tuple;
|
HeapTuple tuple;
|
||||||
TupleDesc tupDesc;
|
TupleDesc tupDesc;
|
||||||
@ -1447,7 +1447,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
|||||||
Oid *elements;
|
Oid *elements;
|
||||||
Oid oid_in_element;
|
Oid oid_in_element;
|
||||||
ExprState **constraintexprs;
|
ExprState **constraintexprs;
|
||||||
bool *literal_nullstr;
|
bool *force_notnull;
|
||||||
bool hasConstraints = false;
|
bool hasConstraints = false;
|
||||||
int attnum;
|
int attnum;
|
||||||
int i;
|
int i;
|
||||||
@ -1509,7 +1509,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
|||||||
defmap = (int *) palloc((num_phys_attrs + 1) * sizeof(int));
|
defmap = (int *) palloc((num_phys_attrs + 1) * sizeof(int));
|
||||||
defexprs = (ExprState **) palloc((num_phys_attrs + 1) * sizeof(ExprState *));
|
defexprs = (ExprState **) palloc((num_phys_attrs + 1) * sizeof(ExprState *));
|
||||||
constraintexprs = (ExprState **) palloc0((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++)
|
for (attnum = 1; attnum <= num_phys_attrs; attnum++)
|
||||||
{
|
{
|
||||||
@ -1526,10 +1526,10 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
|||||||
&in_func_oid, &elements[attnum - 1]);
|
&in_func_oid, &elements[attnum - 1]);
|
||||||
fmgr_info(in_func_oid, &in_functions[attnum - 1]);
|
fmgr_info(in_func_oid, &in_functions[attnum - 1]);
|
||||||
|
|
||||||
if (intMember(attnum, literal_atts))
|
if (intMember(attnum, force_notnull_atts))
|
||||||
literal_nullstr[attnum - 1] = true;
|
force_notnull[attnum - 1] = true;
|
||||||
else
|
else
|
||||||
literal_nullstr[attnum - 1] = false;
|
force_notnull[attnum - 1] = false;
|
||||||
|
|
||||||
/* Get default info if needed */
|
/* Get default info if needed */
|
||||||
if (!intMember(attnum, attnumlist))
|
if (!intMember(attnum, attnumlist))
|
||||||
@ -1748,7 +1748,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
|||||||
string = CopyReadAttribute(delim, null_print,
|
string = CopyReadAttribute(delim, null_print,
|
||||||
&result, &isnull);
|
&result, &isnull);
|
||||||
|
|
||||||
if (csv_mode && isnull && literal_nullstr[m])
|
if (csv_mode && isnull && force_notnull[m])
|
||||||
{
|
{
|
||||||
string = null_print; /* set to NULL string */
|
string = null_print; /* set to NULL string */
|
||||||
isnull = false;
|
isnull = false;
|
||||||
@ -1947,7 +1947,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
|||||||
pfree(defmap);
|
pfree(defmap);
|
||||||
pfree(defexprs);
|
pfree(defexprs);
|
||||||
pfree(constraintexprs);
|
pfree(constraintexprs);
|
||||||
pfree(literal_nullstr);
|
pfree(force_notnull);
|
||||||
|
|
||||||
ExecDropTupleTable(tupleTable, true);
|
ExecDropTupleTable(tupleTable, true);
|
||||||
|
|
||||||
@ -2558,14 +2558,13 @@ CopyAttributeOut(char *server_string, char *delim)
|
|||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
CopyAttributeOutCSV(char *server_string, char *delim, char *quote,
|
CopyAttributeOutCSV(char *server_string, char *delim, char *quote,
|
||||||
char *escape, bool force_quote)
|
char *escape, bool use_quote)
|
||||||
{
|
{
|
||||||
char *string;
|
char *string;
|
||||||
char c;
|
char c;
|
||||||
char delimc = delim[0];
|
char delimc = delim[0];
|
||||||
char quotec = quote[0];
|
char quotec = quote[0];
|
||||||
char escapec = escape[0];
|
char escapec = escape[0];
|
||||||
bool need_quote = force_quote;
|
|
||||||
char *test_string;
|
char *test_string;
|
||||||
bool same_encoding;
|
bool same_encoding;
|
||||||
int mblen;
|
int mblen;
|
||||||
@ -2583,23 +2582,23 @@ CopyAttributeOutCSV(char *server_string, char *delim, char *quote,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
for(test_string = string;
|
for(test_string = string;
|
||||||
!need_quote && (c = *test_string) != '\0';
|
!use_quote && (c = *test_string) != '\0';
|
||||||
test_string += mblen)
|
test_string += mblen)
|
||||||
{
|
{
|
||||||
if (c == delimc || c == quotec || c == '\n' || c == '\r')
|
if (c == delimc || c == quotec || c == '\n' || c == '\r')
|
||||||
need_quote = true;
|
use_quote = true;
|
||||||
if (!same_encoding)
|
if (!same_encoding)
|
||||||
mblen = pg_encoding_mblen(client_encoding, test_string);
|
mblen = pg_encoding_mblen(client_encoding, test_string);
|
||||||
else
|
else
|
||||||
mblen = 1;
|
mblen = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_quote)
|
if (use_quote)
|
||||||
CopySendChar(quotec);
|
CopySendChar(quotec);
|
||||||
|
|
||||||
for (; (c = *string) != '\0'; string += mblen)
|
for (; (c = *string) != '\0'; string += mblen)
|
||||||
{
|
{
|
||||||
if (need_quote && (c == quotec || c == escapec))
|
if (use_quote && (c == quotec || c == escapec))
|
||||||
CopySendChar(escapec);
|
CopySendChar(escapec);
|
||||||
|
|
||||||
CopySendChar(c);
|
CopySendChar(c);
|
||||||
@ -2615,7 +2614,7 @@ CopyAttributeOutCSV(char *server_string, char *delim, char *quote,
|
|||||||
mblen = 1;
|
mblen = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_quote)
|
if (use_quote)
|
||||||
CopySendChar(quotec);
|
CopySendChar(quotec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -370,7 +370,7 @@ static void doNegateFloat(Value *v);
|
|||||||
KEY
|
KEY
|
||||||
|
|
||||||
LANCOMPILER LANGUAGE LARGE_P LAST_P LEADING LEFT LEVEL LIKE LIMIT
|
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
|
LOCK_P
|
||||||
|
|
||||||
MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
|
MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
|
||||||
@ -1374,13 +1374,13 @@ copy_opt_item:
|
|||||||
{
|
{
|
||||||
$$ = makeDefElem("escape", (Node *)makeString($3));
|
$$ = 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);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -7496,7 +7496,6 @@ unreserved_keyword:
|
|||||||
| LAST_P
|
| LAST_P
|
||||||
| LEVEL
|
| LEVEL
|
||||||
| LISTEN
|
| LISTEN
|
||||||
| LITERAL
|
|
||||||
| LOAD
|
| LOAD
|
||||||
| LOCAL
|
| LOCAL
|
||||||
| LOCATION
|
| LOCATION
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -187,7 +187,6 @@ static const ScanKeyword ScanKeywords[] = {
|
|||||||
{"like", LIKE},
|
{"like", LIKE},
|
||||||
{"limit", LIMIT},
|
{"limit", LIMIT},
|
||||||
{"listen", LISTEN},
|
{"listen", LISTEN},
|
||||||
{"literal", LITERAL},
|
|
||||||
{"load", LOAD},
|
{"load", LOAD},
|
||||||
{"local", LOCAL},
|
{"local", LOCAL},
|
||||||
{"localtime", LOCALTIME},
|
{"localtime", LOCALTIME},
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2003, PostgreSQL Global Development Group
|
* 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 "postgres_fe.h"
|
||||||
#include "copy.h"
|
#include "copy.h"
|
||||||
@ -71,8 +71,8 @@ struct copy_options
|
|||||||
char *null;
|
char *null;
|
||||||
char *quote;
|
char *quote;
|
||||||
char *escape;
|
char *escape;
|
||||||
char *force_list;
|
char *force_quote_list;
|
||||||
char *literal_list;
|
char *force_notnull_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -88,8 +88,8 @@ free_copy_options(struct copy_options * ptr)
|
|||||||
free(ptr->null);
|
free(ptr->null);
|
||||||
free(ptr->quote);
|
free(ptr->quote);
|
||||||
free(ptr->escape);
|
free(ptr->escape);
|
||||||
free(ptr->force_list);
|
free(ptr->force_quote_list);
|
||||||
free(ptr->literal_list);
|
free(ptr->force_notnull_list);
|
||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,45 +344,56 @@ parse_slash_copy(const char *args)
|
|||||||
}
|
}
|
||||||
else if (strcasecmp(token, "force") == 0)
|
else if (strcasecmp(token, "force") == 0)
|
||||||
{
|
{
|
||||||
/* handle column list */
|
token = strtokx(NULL, whitespace, ",", "\"",
|
||||||
fetch_next = false;
|
0, false, pset.encoding);
|
||||||
for (;;)
|
if (strcasecmp(token, "quote") == 0)
|
||||||
|
{
|
||||||
|
/* 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, "not") == 0)
|
||||||
{
|
{
|
||||||
token = strtokx(NULL, whitespace, ",", "\"",
|
token = strtokx(NULL, whitespace, ",", "\"",
|
||||||
0, false, pset.encoding);
|
0, false, pset.encoding);
|
||||||
if (!token || strchr(",", token[0]))
|
if (strcasecmp(token, "null") != 0)
|
||||||
goto error;
|
goto error;
|
||||||
if (!result->force_list)
|
/* handle column list */
|
||||||
result->force_list = pg_strdup(token);
|
fetch_next = false;
|
||||||
else
|
for (;;)
|
||||||
xstrcat(&result->force_list, token);
|
{
|
||||||
token = strtokx(NULL, whitespace, ",", "\"",
|
token = strtokx(NULL, whitespace, ",", "\"",
|
||||||
0, false, pset.encoding);
|
0, false, pset.encoding);
|
||||||
if (!token || token[0] != ',')
|
if (!token || strchr(",", token[0]))
|
||||||
break;
|
goto error;
|
||||||
xstrcat(&result->force_list, token);
|
if (!result->force_notnull_list)
|
||||||
}
|
result->force_notnull_list = pg_strdup(token);
|
||||||
}
|
else
|
||||||
else if (strcasecmp(token, "literal") == 0)
|
xstrcat(&result->force_notnull_list, token);
|
||||||
{
|
token = strtokx(NULL, whitespace, ",", "\"",
|
||||||
/* handle column list */
|
0, false, pset.encoding);
|
||||||
fetch_next = false;
|
if (!token || token[0] != ',')
|
||||||
for (;;)
|
break;
|
||||||
{
|
xstrcat(&result->force_notnull_list, token);
|
||||||
token = strtokx(NULL, whitespace, ",", "\"",
|
}
|
||||||
0, false, pset.encoding);
|
|
||||||
if (!token || strchr(",", token[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);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
goto error;
|
goto error;
|
||||||
@ -493,14 +504,14 @@ do_copy(const char *args)
|
|||||||
appendPQExpBuffer(&query, " ESCAPE AS '%s'", options->escape);
|
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)
|
if (options->from)
|
||||||
|
Reference in New Issue
Block a user