66 *
77 *
88 * IDENTIFICATION
9- * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.92 1999/11/27 21:52:53 tgl Exp $
9+ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.93 1999/12/14 00:08:13 momjian Exp $
1010 *
1111 *-------------------------------------------------------------------------
1212 */
4343
4444
4545/* non-export function prototypes */
46- static void CopyTo (Relation rel ,bool binary ,bool oids ,FILE * fp ,char * delim );
47- static void CopyFrom (Relation rel ,bool binary ,bool oids ,FILE * fp ,char * delim );
46+ static void CopyTo (Relation rel ,bool binary ,bool oids ,FILE * fp ,char * delim , char * null_print );
47+ static void CopyFrom (Relation rel ,bool binary ,bool oids ,FILE * fp ,char * delim , char * null_print );
4848static Oid GetOutputFunction (Oid type );
4949static Oid GetTypeElement (Oid type );
5050static Oid GetInputFunction (Oid type );
@@ -54,7 +54,7 @@ static void GetIndexRelations(Oid main_relation_oid,
5454Relation * * index_rels );
5555
5656static void CopyReadNewline (FILE * fp ,int * newline );
57- static char * CopyReadAttribute (FILE * fp ,bool * isnull ,char * delim ,int * newline );
57+ static char * CopyReadAttribute (FILE * fp ,bool * isnull ,char * delim ,int * newline , char * null_print );
5858
5959static void CopyAttributeOut (FILE * fp ,char * string ,char * delim );
6060static int CountTuples (Relation relation );
@@ -219,7 +219,7 @@ CopyDonePeek(FILE *fp, int c, int pickup)
219219
220220void
221221DoCopy (char * relname ,bool binary ,bool oids ,bool from ,bool pipe ,
222- char * filename ,char * delim ,int fileumask )
222+ char * filename ,char * delim ,char * null_print , int fileumask )
223223{
224224/*----------------------------------------------------------------------------
225225 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,
232232 Iff <binary>, unload or reload in the binary format, as opposed to the
233233 more wasteful but more robust and portable text format.
234234
235- If in the text format, delimit columns with delimiter <delim>.
235+ If in the text format, delimit columns with delimiter <delim> and print
236+ NULL values as <null_print>.
236237
237238 <fileumask> is the umask(2) setting to use while creating an output file.
238239 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,
304305"reading. Errno = %s (%d)." ,
305306geteuid (),filename ,strerror (errno ),errno );
306307}
307- CopyFrom (rel ,binary ,oids ,fp ,delim );
308+ CopyFrom (rel ,binary ,oids ,fp ,delim , null_print );
308309}
309310else
310311{/* copy from database to file */
@@ -336,7 +337,7 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
336337"writing. Errno = %s (%d)." ,
337338geteuid (),filename ,strerror (errno ),errno );
338339}
339- CopyTo (rel ,binary ,oids ,fp ,delim );
340+ CopyTo (rel ,binary ,oids ,fp ,delim , null_print );
340341}
341342if (!pipe )
342343{
@@ -362,7 +363,7 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
362363
363364
364365static void
365- CopyTo (Relation rel ,bool binary ,bool oids ,FILE * fp ,char * delim )
366+ CopyTo (Relation rel ,bool binary ,bool oids ,FILE * fp ,char * delim , char * null_print )
366367{
367368HeapTuple tuple ;
368369HeapScanDesc scandesc ;
@@ -449,7 +450,7 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
449450pfree (string );
450451}
451452else
452- CopySendString ("\\N" ,fp );/* null indicator */
453+ CopySendString (null_print ,fp );/* null indicator */
453454
454455if (i == attr_count - 1 )
455456CopySendChar ('\n' ,fp );
@@ -520,7 +521,7 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
520521}
521522
522523static void
523- CopyFrom (Relation rel ,bool binary ,bool oids ,FILE * fp ,char * delim )
524+ CopyFrom (Relation rel ,bool binary ,bool oids ,FILE * fp ,char * delim , char * null_print )
524525{
525526HeapTuple tuple ;
526527AttrNumber attr_count ;
@@ -711,7 +712,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
711712lineno ++ ;
712713if (oids )
713714{
714- string = CopyReadAttribute (fp ,& isnull ,delim ,& newline );
715+ string = CopyReadAttribute (fp ,& isnull ,delim ,& newline , null_print );
715716if (string == NULL )
716717done = 1 ;
717718else
@@ -724,7 +725,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
724725}
725726for (i = 0 ;i < attr_count && !done ;i ++ )
726727{
727- string = CopyReadAttribute (fp ,& isnull ,delim ,& newline );
728+ string = CopyReadAttribute (fp ,& isnull ,delim ,& newline , null_print );
728729if (isnull )
729730{
730731values [i ]= PointerGetDatum (NULL );
@@ -1122,10 +1123,11 @@ CopyReadNewline(FILE *fp, int *newline)
11221123 *
11231124 * delim is the string of acceptable delimiter characters(s).
11241125 * *newline remembers whether we've seen a newline ending this tuple.
1126+ * null_print says how NULL values are represented
11251127 */
11261128
11271129static char *
1128- CopyReadAttribute (FILE * fp ,bool * isnull ,char * delim ,int * newline )
1130+ CopyReadAttribute (FILE * fp ,bool * isnull ,char * delim ,int * newline , char * null_print )
11291131{
11301132StringInfoData attribute_buf ;
11311133char c ;
@@ -1207,6 +1209,13 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline)
12071209c = val & 0377 ;
12081210}
12091211break ;
1212+ /* This is a special hack to parse `\N' as <backslash-N>
1213+ rather then just 'N' to provide compatibility with
1214+ the default NULL output. -- pe */
1215+ case 'N' :
1216+ appendStringInfoChar (& attribute_buf ,'\\' );
1217+ c = 'N' ;
1218+ break ;
12101219case 'b' :
12111220c = '\b' ;
12121221break ;
@@ -1225,9 +1234,6 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline)
12251234case 'v' :
12261235c = '\v' ;
12271236break ;
1228- case 'N' :
1229- * isnull = (bool ) true;
1230- break ;
12311237case '.' :
12321238c = CopyGetChar (fp );
12331239if (c != '\n' )
@@ -1266,6 +1272,9 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline)
12661272return cvt ;
12671273}
12681274#endif
1275+ if (strcmp (attribute_buf .data ,null_print )== 0 )
1276+ * isnull = true;
1277+
12691278return attribute_buf .data ;
12701279
12711280endOfFile :