mirror of
https://github.com/postgres/postgres.git
synced 2025-07-08 11:42:09 +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:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 */
|
||||
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);
|
||||
@ -695,10 +695,10 @@ DoCopy(const CopyStmt *stmt)
|
||||
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;
|
||||
@ -764,21 +764,21 @@ DoCopy(const CopyStmt *stmt)
|
||||
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",
|
||||
@ -850,28 +850,28 @@ DoCopy(const CopyStmt *stmt)
|
||||
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.
|
||||
@ -928,47 +928,47 @@ DoCopy(const CopyStmt *stmt)
|
||||
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))));
|
||||
}
|
||||
}
|
||||
@ -1037,7 +1037,7 @@ DoCopy(const CopyStmt *stmt)
|
||||
}
|
||||
}
|
||||
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 */
|
||||
@ -1100,7 +1100,7 @@ DoCopy(const CopyStmt *stmt)
|
||||
}
|
||||
}
|
||||
CopyTo(rel, attnumlist, binary, oids, delim, null_print, csv_mode,
|
||||
quote, escape, force_atts);
|
||||
quote, escape, force_quote_atts);
|
||||
}
|
||||
|
||||
if (!pipe)
|
||||
@ -1133,7 +1133,7 @@ DoCopy(const CopyStmt *stmt)
|
||||
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;
|
||||
@ -1180,7 +1180,7 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
&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;
|
||||
@ -1434,7 +1434,7 @@ limit_printout_length(StringInfo buf)
|
||||
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;
|
||||
@ -1447,7 +1447,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
Oid *elements;
|
||||
Oid oid_in_element;
|
||||
ExprState **constraintexprs;
|
||||
bool *literal_nullstr;
|
||||
bool *force_notnull;
|
||||
bool hasConstraints = false;
|
||||
int attnum;
|
||||
int i;
|
||||
@ -1509,7 +1509,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
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++)
|
||||
{
|
||||
@ -1526,10 +1526,10 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
&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))
|
||||
@ -1748,7 +1748,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
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;
|
||||
@ -1947,7 +1947,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
pfree(defmap);
|
||||
pfree(defexprs);
|
||||
pfree(constraintexprs);
|
||||
pfree(literal_nullstr);
|
||||
pfree(force_notnull);
|
||||
|
||||
ExecDropTupleTable(tupleTable, true);
|
||||
|
||||
@ -2558,14 +2558,13 @@ CopyAttributeOut(char *server_string, char *delim)
|
||||
*/
|
||||
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;
|
||||
@ -2583,23 +2582,23 @@ CopyAttributeOutCSV(char *server_string, char *delim, char *quote,
|
||||
*/
|
||||
|
||||
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);
|
||||
@ -2615,7 +2614,7 @@ CopyAttributeOutCSV(char *server_string, char *delim, char *quote,
|
||||
mblen = 1;
|
||||
}
|
||||
|
||||
if (need_quote)
|
||||
if (use_quote)
|
||||
CopySendChar(quotec);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user