mirror of
https://github.com/postgres/postgres.git
synced 2025-06-13 07:41:39 +03:00
Depending on my interpreting (and programming) skills, this might solve
anywhere from zero to two TODO items. * Allow flag to control COPY input/output of NULLs I got this: COPY table .... [ WITH NULL AS 'string' ] which does what you'd expect. The default is \N, otherwise you can use empty strings, etc. On Copy In this acts like a filter: every data item that looks like 'string' becomes a NULL. Pretty straightforward. This also seems to be related to * Make postgres user have a password by default If I recall this discussion correctly, the problem was actually that the default password for the postgres (or any) user is in fact "\N", because of the way copy is used. With this change, the file pg_pwd is copied out with nulls as empty strings, so if someone doesn't have a password, the password is just '', which one would expect from a new account. I don't think anyone really wants a hard-coded default password. Peter Eisentraut Sernanders väg 10:115
This commit is contained in:
@ -6,7 +6,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.92 1999/11/27 21:52:53 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.93 1999/12/14 00:08:13 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -43,8 +43,8 @@
|
||||
|
||||
|
||||
/* non-export function prototypes */
|
||||
static void CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim);
|
||||
static void CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim);
|
||||
static void CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null_print);
|
||||
static void CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null_print);
|
||||
static Oid GetOutputFunction(Oid type);
|
||||
static Oid GetTypeElement(Oid type);
|
||||
static Oid GetInputFunction(Oid type);
|
||||
@ -54,7 +54,7 @@ static void GetIndexRelations(Oid main_relation_oid,
|
||||
Relation **index_rels);
|
||||
|
||||
static void CopyReadNewline(FILE *fp, int *newline);
|
||||
static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline);
|
||||
static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_print);
|
||||
|
||||
static void CopyAttributeOut(FILE *fp, char *string, char *delim);
|
||||
static int CountTuples(Relation relation);
|
||||
@ -219,7 +219,7 @@ CopyDonePeek(FILE *fp, int c, int pickup)
|
||||
|
||||
void
|
||||
DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
|
||||
char *filename, char *delim, int fileumask)
|
||||
char *filename, char *delim, char *null_print, int fileumask)
|
||||
{
|
||||
/*----------------------------------------------------------------------------
|
||||
Either unload or reload contents of class <relname>, depending on <from>.
|
||||
@ -232,7 +232,8 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
|
||||
Iff <binary>, unload or reload in the binary format, as opposed to the
|
||||
more wasteful but more robust and portable text format.
|
||||
|
||||
If in the text format, delimit columns with delimiter <delim>.
|
||||
If in the text format, delimit columns with delimiter <delim> and print
|
||||
NULL values as <null_print>.
|
||||
|
||||
<fileumask> is the umask(2) setting to use while creating an output file.
|
||||
This should usually be more liberal than the backend's normal 077 umask,
|
||||
@ -304,7 +305,7 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
|
||||
"reading. Errno = %s (%d).",
|
||||
geteuid(), filename, strerror(errno), errno);
|
||||
}
|
||||
CopyFrom(rel, binary, oids, fp, delim);
|
||||
CopyFrom(rel, binary, oids, fp, delim, null_print);
|
||||
}
|
||||
else
|
||||
{ /* copy from database to file */
|
||||
@ -336,7 +337,7 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
|
||||
"writing. Errno = %s (%d).",
|
||||
geteuid(), filename, strerror(errno), errno);
|
||||
}
|
||||
CopyTo(rel, binary, oids, fp, delim);
|
||||
CopyTo(rel, binary, oids, fp, delim, null_print);
|
||||
}
|
||||
if (!pipe)
|
||||
{
|
||||
@ -362,7 +363,7 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
|
||||
|
||||
|
||||
static void
|
||||
CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
|
||||
CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null_print)
|
||||
{
|
||||
HeapTuple tuple;
|
||||
HeapScanDesc scandesc;
|
||||
@ -449,7 +450,7 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
|
||||
pfree(string);
|
||||
}
|
||||
else
|
||||
CopySendString("\\N", fp); /* null indicator */
|
||||
CopySendString(null_print, fp); /* null indicator */
|
||||
|
||||
if (i == attr_count - 1)
|
||||
CopySendChar('\n', fp);
|
||||
@ -520,7 +521,7 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
|
||||
}
|
||||
|
||||
static void
|
||||
CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
|
||||
CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null_print)
|
||||
{
|
||||
HeapTuple tuple;
|
||||
AttrNumber attr_count;
|
||||
@ -711,7 +712,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
|
||||
lineno++;
|
||||
if (oids)
|
||||
{
|
||||
string = CopyReadAttribute(fp, &isnull, delim, &newline);
|
||||
string = CopyReadAttribute(fp, &isnull, delim, &newline, null_print);
|
||||
if (string == NULL)
|
||||
done = 1;
|
||||
else
|
||||
@ -724,7 +725,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
|
||||
}
|
||||
for (i = 0; i < attr_count && !done; i++)
|
||||
{
|
||||
string = CopyReadAttribute(fp, &isnull, delim, &newline);
|
||||
string = CopyReadAttribute(fp, &isnull, delim, &newline, null_print);
|
||||
if (isnull)
|
||||
{
|
||||
values[i] = PointerGetDatum(NULL);
|
||||
@ -1122,10 +1123,11 @@ CopyReadNewline(FILE *fp, int *newline)
|
||||
*
|
||||
* delim is the string of acceptable delimiter characters(s).
|
||||
* *newline remembers whether we've seen a newline ending this tuple.
|
||||
* null_print says how NULL values are represented
|
||||
*/
|
||||
|
||||
static char *
|
||||
CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline)
|
||||
CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_print)
|
||||
{
|
||||
StringInfoData attribute_buf;
|
||||
char c;
|
||||
@ -1207,6 +1209,13 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline)
|
||||
c = val & 0377;
|
||||
}
|
||||
break;
|
||||
/* This is a special hack to parse `\N' as <backslash-N>
|
||||
rather then just 'N' to provide compatibility with
|
||||
the default NULL output. -- pe */
|
||||
case 'N':
|
||||
appendStringInfoChar(&attribute_buf, '\\');
|
||||
c = 'N';
|
||||
break;
|
||||
case 'b':
|
||||
c = '\b';
|
||||
break;
|
||||
@ -1225,9 +1234,6 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline)
|
||||
case 'v':
|
||||
c = '\v';
|
||||
break;
|
||||
case 'N':
|
||||
*isnull = (bool) true;
|
||||
break;
|
||||
case '.':
|
||||
c = CopyGetChar(fp);
|
||||
if (c != '\n')
|
||||
@ -1266,6 +1272,9 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline)
|
||||
return cvt;
|
||||
}
|
||||
#endif
|
||||
if (strcmp(attribute_buf.data, null_print)==0)
|
||||
*isnull = true;
|
||||
|
||||
return attribute_buf.data;
|
||||
|
||||
endOfFile:
|
||||
|
Reference in New Issue
Block a user