Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit e7a110b

Browse files
committed
This patch can be installed as part of 1.02.1 so people can properly
pg_dump and load to 2.0. I haven't gotten any feedback on whether people want it, so I am submitting it for others to decide. I would recommend an install in 1.02.1. I had said that the 2.0 pg_dump could dump a 1.02.1 database, but I was wrong. The copy is actually performed by the backend, and the 2.0 database will not be able to read 1.02.1 databases because of the new system columns. This patch does several things. It copies nulls out as \N, so they can be distinguished from '' strings. It fixes a problem where backslashes in the input stream were not output as double-backslashes. Without this patch, backslashes copied out were deleted upon input, or interpreted as special characters. Third, input is now terminated by backslash-period. This can not be part of a normal input stream. I tested this by creating a database with all sorts of nulls, backslash, and period fields and dumped the database and reloaded into a new database and compared them. Submitted by: Bruce
1 parent 15a6450 commit e7a110b

File tree

2 files changed

+45
-58
lines changed

2 files changed

+45
-58
lines changed

src/backend/commands/copy.c

Lines changed: 40 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
*
88
* IDENTIFICATION
9-
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.2 1996/07/23 02:23:15 scrappy Exp $
9+
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.3 1996/08/14 05:33:04 scrappy Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -107,7 +107,7 @@ DoCopy(char *relname, bool binary, bool from, bool pipe, char *filename,
107107
if (!pipe) {
108108
fclose(fp);
109109
}else if (!from && !binary) {
110-
fputs(".\n", fp);
110+
fputs("\\.\n", fp);
111111
if (IsUnderPostmaster) fflush(Pfout);
112112
}
113113
}
@@ -169,6 +169,9 @@ CopyTo(Relation rel, bool binary, FILE *fp, char *delim)
169169
CopyAttributeOut(fp, string, delim);
170170
pfree(string);
171171
}
172+
else
173+
fputs("\\N", fp); /* null indicator */
174+
172175
if (i == attr_count - 1) {
173176
fputc('\n', fp);
174177
}else {
@@ -703,40 +706,22 @@ CopyReadAttribute(int attno, FILE *fp, bool *isnull, char *delim)
703706
int done = 0;
704707
int i = 0;
705708

706-
if (feof(fp)) {
707-
*isnull = (bool) false;
709+
*isnull = (bool) false; /* set default */
710+
if (feof(fp))
708711
return(NULL);
709-
}
710712

711713
while (!done) {
712714
c = getc(fp);
713715

714-
if (feof(fp)) {
715-
*isnull = (bool) false;
716+
if (feof(fp))
716717
return(NULL);
717-
}else if (reading_from_input && attno == 0 && i == 0 && c == '.') {
718-
attribute[0] = c;
719-
c = getc(fp);
720-
if (c == '\n') {
721-
*isnull = (bool) false;
722-
return(NULL);
723-
}else if (inString(c,delim)) {
724-
attribute[1] = 0;
725-
*isnull = (bool) false;
726-
return(&attribute[0]);
727-
}else {
728-
attribute[1] = c;
729-
i = 2;
730-
}
731-
}else if (c == '\\') {
718+
else if (c == '\\') {
732719
c = getc(fp);
733720
#ifdef ESCAPE_PATCH
734721
#define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))
735722
#define VALUE(c) ((c) - '0')
736-
if (feof(fp)) {
737-
*isnull = (bool) false;
723+
if (feof(fp))
738724
return(NULL);
739-
}
740725
switch (c) {
741726
case '0':
742727
case '1':
@@ -755,21 +740,17 @@ CopyReadAttribute(int attno, FILE *fp, bool *isnull, char *delim)
755740
if (ISOCTAL(c)) {
756741
val = (val<<3) + VALUE(c);
757742
} else {
758-
if (feof(fp)) {
759-
*isnull = (bool) false;
743+
if (feof(fp))
760744
return(NULL);
761-
}
762745
ungetc(c, fp);
763746
}
764747
} else {
765-
if (feof(fp)) {
766-
*isnull = (bool) false;
748+
if (feof(fp))
767749
return(NULL);
768-
}
769750
ungetc(c, fp);
770751
}
771752
c = val & 0377;
772-
}
753+
}
773754
break;
774755
case 'b':
775756
c = '\b';
@@ -789,6 +770,16 @@ CopyReadAttribute(int attno, FILE *fp, bool *isnull, char *delim)
789770
case 'v':
790771
c = '\v';
791772
break;
773+
case 'N':
774+
attribute[0] = '\0'; /* just to be safe */
775+
*isnull = (bool) true;
776+
break;
777+
case '.':
778+
c = getc(fp);
779+
if (c != '\n')
780+
elog(WARN, "CopyReadAttribute - end of record marker corrupted");
781+
return(NULL);
782+
break;
792783
}
793784
#endif
794785
}else if (inString(c,delim) || c == '\n') {
@@ -799,13 +790,7 @@ CopyReadAttribute(int attno, FILE *fp, bool *isnull, char *delim)
799790
elog(WARN, "CopyReadAttribute - attribute length too long");
800791
}
801792
attribute[i] = '\0';
802-
if (i == 0) {
803-
*isnull = (bool) true;
804-
return(NULL);
805-
}else {
806-
*isnull = (bool) false;
807-
return(&attribute[0]);
808-
}
793+
return(&attribute[0]);
809794
}
810795

811796
#ifdef ESCAPE_PATCH
@@ -817,26 +802,26 @@ CopyAttributeOut(FILE *fp, char *string, char *delim)
817802
int len = strlen(string);
818803

819804
/* XXX - This is a kludge, we should check the data type */
820-
if (len && (string[0] == '{') && (string[len-1] == '}')) {
805+
if (len && (string[0] == '{') && (string[len-1] == '}'))
821806
is_array = true;
822-
}
823807

824808
for ( ; c = *string; string++) {
825-
if ((c == delim[0]) || (c == '\n')) {
809+
if (c == delim[0] || c == '\n' ||
810+
(c == '\\' && !is_array))
826811
fputc('\\', fp);
827-
} else if ((c == '\\') && is_array) {
828-
if (*(string+1) == '\\') {
829-
/* translate \\ to \\\\ */
830-
fputc('\\', fp);
831-
fputc('\\', fp);
832-
fputc('\\', fp);
833-
string++;
834-
} else if (*(string+1) == '"') {
835-
/* translate \" to \\\" */
836-
fputc('\\', fp);
837-
fputc('\\', fp);
838-
}
839-
}
812+
else
813+
if (c == '\\' && is_array)
814+
if (*(string+1) == '\\') {
815+
/* translate \\ to \\\\ */
816+
fputc('\\', fp);
817+
fputc('\\', fp);
818+
fputc('\\', fp);
819+
string++;
820+
} else if (*(string+1) == '"') {
821+
/* translate \" to \\\" */
822+
fputc('\\', fp);
823+
fputc('\\', fp);
824+
}
840825
fputc(*string, fp);
841826
}
842827
}

src/bin/pg_dump/pg_dump.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
*
2121
*
2222
* IDENTIFICATION
23-
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.5 1996/07/31 06:09:46 scrappy Exp $
23+
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.6 1996/08/14 05:33:11 scrappy Exp $
2424
*
2525
* Modifications - 6/10/96 - dave@bensoft.com - version 1.13.dhb
2626
*
@@ -1394,7 +1394,9 @@ dumpClasses(TableInfo *tblinfo, int numTables, FILE *fout, char *onlytable)
13941394
while (!copydone) {
13951395
ret = PQgetline(res->conn, copybuf, COPYBUFSIZ);
13961396

1397-
if (copybuf[0] == '.' && copybuf[1] =='\0') {
1397+
if (copybuf[0] == '\\' &&
1398+
copybuf[1] == '.' &&
1399+
copybuf[2] == '\0') {
13981400
copydone = true; /* don't print this... */
13991401
} else {
14001402
fputs(copybuf, stdout);
@@ -1410,7 +1412,7 @@ dumpClasses(TableInfo *tblinfo, int numTables, FILE *fout, char *onlytable)
14101412
}
14111413
}
14121414
}
1413-
fprintf(fout, ".\n");
1415+
fprintf(fout, "\\.\n");
14141416
PQclear(res);
14151417
PQendcopy(res->conn);
14161418
} else {

0 commit comments

Comments
 (0)