Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6687650

Browse files
committed
COPY and pg_dump failed to cope with zero-column tables. Fix 'em.
1 parentdb7e46a commit6687650

File tree

2 files changed

+75
-53
lines changed

2 files changed

+75
-53
lines changed

‎src/backend/commands/copy.c

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.196 2003/04/24 21:16:42 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.197 2003/04/25 02:28:22 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -808,10 +808,11 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
808808
* Get info about the columns we need to process.
809809
*
810810
* For binary copy we really only need isvarlena, but compute it all...
811+
* +1's here are to avoid palloc(0) in a zero-column table.
811812
*/
812-
out_functions= (FmgrInfo*)palloc(num_phys_attrs*sizeof(FmgrInfo));
813-
elements= (Oid*)palloc(num_phys_attrs*sizeof(Oid));
814-
isvarlena= (bool*)palloc(num_phys_attrs*sizeof(bool));
813+
out_functions= (FmgrInfo*)palloc((num_phys_attrs+1)*sizeof(FmgrInfo));
814+
elements= (Oid*)palloc((num_phys_attrs+1)*sizeof(Oid));
815+
isvarlena= (bool*)palloc((num_phys_attrs+1)*sizeof(bool));
815816
foreach(cur,attnumlist)
816817
{
817818
intattnum=lfirsti(cur);
@@ -1078,12 +1079,13 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
10781079
* relation, including the input function, the element type (to pass
10791080
* to the input function), and info about defaults and constraints.
10801081
* (We don't actually use the input function if it's a binary copy.)
1082+
* +1's here are to avoid palloc(0) in a zero-column table.
10811083
*/
1082-
in_functions= (FmgrInfo*)palloc(num_phys_attrs*sizeof(FmgrInfo));
1083-
elements= (Oid*)palloc(num_phys_attrs*sizeof(Oid));
1084-
defmap= (int*)palloc(num_phys_attrs*sizeof(int));
1085-
defexprs= (ExprState**)palloc(num_phys_attrs*sizeof(ExprState*));
1086-
constraintexprs= (ExprState**)palloc0(num_phys_attrs*sizeof(ExprState*));
1084+
in_functions= (FmgrInfo*)palloc((num_phys_attrs+1)*sizeof(FmgrInfo));
1085+
elements= (Oid*)palloc((num_phys_attrs+1)*sizeof(Oid));
1086+
defmap= (int*)palloc((num_phys_attrs+1)*sizeof(int));
1087+
defexprs= (ExprState**)palloc((num_phys_attrs+1)*sizeof(ExprState*));
1088+
constraintexprs= (ExprState**)palloc0((num_phys_attrs+1)*sizeof(ExprState*));
10871089

10881090
for (i=0;i<num_phys_attrs;i++)
10891091
{
@@ -1196,8 +1198,8 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
11961198
}
11971199
}
11981200

1199-
values= (Datum*)palloc(num_phys_attrs*sizeof(Datum));
1200-
nulls= (char*)palloc(num_phys_attrs*sizeof(char));
1201+
values= (Datum*)palloc((num_phys_attrs+1)*sizeof(Datum));
1202+
nulls= (char*)palloc((num_phys_attrs+1)*sizeof(char));
12011203

12021204
/* Make room for a PARAM_EXEC value for domain constraint checks */
12031205
if (hasConstraints)
@@ -1304,9 +1306,31 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
13041306
if (done)
13051307
break;/* out of per-row loop */
13061308

1307-
/* Complain if there are more fields on the input line */
1309+
/*
1310+
* Complain if there are more fields on the input line.
1311+
*
1312+
* Special case: if we're reading a zero-column table, we
1313+
* won't yet have called CopyReadAttribute() at all; so do that
1314+
* and check we have an empty line. Fortunately we can keep that
1315+
* silly corner case out of the main line of execution.
1316+
*/
13081317
if (result==NORMAL_ATTR)
1309-
elog(ERROR,"Extra data after last expected column");
1318+
{
1319+
if (attnumlist==NIL&& !file_has_oids)
1320+
{
1321+
string=CopyReadAttribute(delim,&result);
1322+
if (result==NORMAL_ATTR||*string!='\0')
1323+
elog(ERROR,"Extra data after last expected column");
1324+
if (result==END_OF_FILE)
1325+
{
1326+
/* EOF at start of line: all is well */
1327+
done= true;
1328+
break;
1329+
}
1330+
}
1331+
else
1332+
elog(ERROR,"Extra data after last expected column");
1333+
}
13101334

13111335
/*
13121336
* If we got some data on the line, but it was ended by EOF,

‎src/bin/pg_dump/pg_dump.c

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*by PostgreSQL
1313
*
1414
* IDENTIFICATION
15-
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.326 2003/04/04 20:42:12 momjian Exp $
15+
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.327 2003/04/25 02:28:22 tgl Exp $
1616
*
1717
*-------------------------------------------------------------------------
1818
*/
@@ -838,9 +838,6 @@ dumpClasses_nodumpData(Archive *fout, char *oid, void *dctxv)
838838
* possibility of retrieving data in the wrong column order. (The
839839
* default column ordering of COPY will not be what we want in certain
840840
* corner cases involving ADD COLUMN and inheritance.)
841-
*
842-
* NB: caller should have already determined that there are dumpable
843-
* columns, so that fmtCopyColumnList will return something.
844841
*/
845842
if (g_fout->remoteVersion >=70300)
846843
column_list=fmtCopyColumnList(tbinfo);
@@ -975,6 +972,7 @@ dumpClasses_dumpData(Archive *fout, char *oid, void *dctxv)
975972
PQExpBufferq=createPQExpBuffer();
976973
PGresult*res;
977974
inttuple;
975+
intnfields;
978976
intfield;
979977

980978
/*
@@ -1024,14 +1022,21 @@ dumpClasses_dumpData(Archive *fout, char *oid, void *dctxv)
10241022
exit_nicely();
10251023
}
10261024

1025+
nfields=PQnfields(res);
10271026
for (tuple=0;tuple<PQntuples(res);tuple++)
10281027
{
10291028
archprintf(fout,"INSERT INTO %s ",fmtId(classname));
1029+
if (nfields==0)
1030+
{
1031+
/* corner case for zero-column table */
1032+
archprintf(fout,"DEFAULT VALUES;\n");
1033+
continue;
1034+
}
10301035
if (attrNames== true)
10311036
{
10321037
resetPQExpBuffer(q);
10331038
appendPQExpBuffer(q,"(");
1034-
for (field=0;field<PQnfields(res);field++)
1039+
for (field=0;field<nfields;field++)
10351040
{
10361041
if (field>0)
10371042
appendPQExpBuffer(q,", ");
@@ -1041,7 +1046,7 @@ dumpClasses_dumpData(Archive *fout, char *oid, void *dctxv)
10411046
archprintf(fout,"%s",q->data);
10421047
}
10431048
archprintf(fout,"VALUES (");
1044-
for (field=0;field<PQnfields(res);field++)
1049+
for (field=0;field<nfields;field++)
10451050
{
10461051
if (field>0)
10471052
archprintf(fout,", ");
@@ -1154,45 +1159,38 @@ dumpClasses(const TableInfo *tblinfo, const int numTables, Archive *fout,
11541159

11551160
if (tblinfo[i].dump)
11561161
{
1157-
constchar*column_list;
1158-
11591162
if (g_verbose)
11601163
write_msg(NULL,"preparing to dump the contents of table %s\n",
11611164
classname);
11621165

1163-
/* Get column list first to check for zero-column table */
1164-
column_list=fmtCopyColumnList(&(tblinfo[i]));
1165-
if (column_list)
1166-
{
1167-
dumpCtx= (DumpContext*)malloc(sizeof(DumpContext));
1168-
dumpCtx->tblinfo= (TableInfo*)tblinfo;
1169-
dumpCtx->tblidx=i;
1170-
dumpCtx->oids=oids;
1166+
dumpCtx= (DumpContext*)malloc(sizeof(DumpContext));
1167+
dumpCtx->tblinfo= (TableInfo*)tblinfo;
1168+
dumpCtx->tblidx=i;
1169+
dumpCtx->oids=oids;
11711170

1172-
if (!dumpData)
1173-
{
1174-
/* Dump/restore using COPY */
1175-
dumpFn=dumpClasses_nodumpData;
1176-
resetPQExpBuffer(copyBuf);
1177-
appendPQExpBuffer(copyBuf,"COPY %s %s %sFROM stdin;\n",
1178-
fmtId(tblinfo[i].relname),
1179-
column_list,
1171+
if (!dumpData)
1172+
{
1173+
/* Dump/restore using COPY */
1174+
dumpFn=dumpClasses_nodumpData;
1175+
resetPQExpBuffer(copyBuf);
1176+
appendPQExpBuffer(copyBuf,"COPY %s %s %sFROM stdin;\n",
1177+
fmtId(tblinfo[i].relname),
1178+
fmtCopyColumnList(&(tblinfo[i])),
11801179
(oids&&tblinfo[i].hasoids) ?"WITH OIDS " :"");
1181-
copyStmt=copyBuf->data;
1182-
}
1183-
else
1184-
{
1185-
/* Restore using INSERT */
1186-
dumpFn=dumpClasses_dumpData;
1187-
copyStmt=NULL;
1188-
}
1189-
1190-
ArchiveEntry(fout,tblinfo[i].oid,tblinfo[i].relname,
1191-
tblinfo[i].relnamespace->nspname,
1192-
tblinfo[i].usename,
1193-
"TABLE DATA",NULL,"","",copyStmt,
1194-
dumpFn,dumpCtx);
1180+
copyStmt=copyBuf->data;
11951181
}
1182+
else
1183+
{
1184+
/* Restore using INSERT */
1185+
dumpFn=dumpClasses_dumpData;
1186+
copyStmt=NULL;
1187+
}
1188+
1189+
ArchiveEntry(fout,tblinfo[i].oid,tblinfo[i].relname,
1190+
tblinfo[i].relnamespace->nspname,
1191+
tblinfo[i].usename,
1192+
"TABLE DATA",NULL,"","",copyStmt,
1193+
dumpFn,dumpCtx);
11961194
}
11971195
}
11981196

@@ -6980,7 +6978,7 @@ fmtQualifiedId(const char *schema, const char *id)
69806978
* Return a column list clause for the given relation.
69816979
*
69826980
* Special case: if there are no undropped columns in the relation, return
6983-
*NULL, not an invalid "()" column list.
6981+
*"", not an invalid "()" column list.
69846982
*/
69856983
staticconstchar*
69866984
fmtCopyColumnList(constTableInfo*ti)
@@ -7010,7 +7008,7 @@ fmtCopyColumnList(const TableInfo *ti)
70107008
}
70117009

70127010
if (!needComma)
7013-
returnNULL;/* no undropped columns */
7011+
return"";/* no undropped columns */
70147012

70157013
appendPQExpBuffer(q,")");
70167014
returnq->data;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp