aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2003-04-25 22:14:33 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2003-04-25 22:14:33 +0000
commit66e0ea47a002183901d2053ed980a78f464dea36 (patch)
treecdc7c0b6e844269dc3663b1219b87422f2e46283 /src
parentde9c299aba4161cc58c448774a6119f5b980904a (diff)
downloadpostgresql-66e0ea47a002183901d2053ed980a78f464dea36.tar.gz
postgresql-66e0ea47a002183901d2053ed980a78f464dea36.zip
Back-patch fixes for zero-column tables in COPY, pg_dump.
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/copy.c52
-rw-r--r--src/bin/pg_dump/pg_dump.c23
2 files changed, 57 insertions, 18 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 906dd277eaf..dd551659d5a 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.177.2.1 2002/12/01 17:33:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.177.2.2 2003/04/25 22:14:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -542,10 +542,11 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
* Get info about the columns we need to process.
*
* For binary copy we really only need isvarlena, but compute it all...
+ * +1's here are to avoid palloc(0) in a zero-column table.
*/
- out_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
- elements = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
- isvarlena = (bool *) palloc(num_phys_attrs * sizeof(bool));
+ out_functions = (FmgrInfo *) palloc((num_phys_attrs + 1) * sizeof(FmgrInfo));
+ elements = (Oid *) palloc((num_phys_attrs + 1) * sizeof(Oid));
+ isvarlena = (bool *) palloc((num_phys_attrs + 1) * sizeof(bool));
foreach(cur, attnumlist)
{
int attnum = lfirsti(cur);
@@ -799,13 +800,14 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
* relation, including the input function, the element type (to pass
* to the input function), and info about defaults and constraints.
* (We don't actually use the input function if it's a binary copy.)
+ * +1's here are to avoid palloc(0) in a zero-column table.
*/
- in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
- elements = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
- defmap = (int *) palloc(num_phys_attrs * sizeof(int));
- defexprs = (Node **) palloc(num_phys_attrs * sizeof(Node *));
- constraintexprs = (Node **) palloc(num_phys_attrs * sizeof(Node *));
- constraintconsts = (Const **) palloc(num_phys_attrs * sizeof(Const *));
+ in_functions = (FmgrInfo *) palloc((num_phys_attrs + 1) * sizeof(FmgrInfo));
+ elements = (Oid *) palloc((num_phys_attrs + 1) * sizeof(Oid));
+ defmap = (int *) palloc((num_phys_attrs + 1) * sizeof(int));
+ defexprs = (Node **) palloc((num_phys_attrs + 1) * sizeof(Node *));
+ constraintexprs = (Node **) palloc((num_phys_attrs + 1) * sizeof(Node *));
+ constraintconsts = (Const **) palloc((num_phys_attrs + 1) * sizeof(Const *));
MemSet(constraintexprs, 0, num_phys_attrs * sizeof(Node *));
for (i = 0; i < num_phys_attrs; i++)
@@ -917,8 +919,8 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
}
}
- values = (Datum *) palloc(num_phys_attrs * sizeof(Datum));
- nulls = (char *) palloc(num_phys_attrs * sizeof(char));
+ values = (Datum *) palloc((num_phys_attrs + 1) * sizeof(Datum));
+ nulls = (char *) palloc((num_phys_attrs + 1) * sizeof(char));
copy_lineno = 0;
fe_eof = false;
@@ -1015,9 +1017,31 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
if (done)
break; /* out of per-row loop */
- /* Complain if there are more fields on the input line */
+ /*
+ * Complain if there are more fields on the input line.
+ *
+ * Special case: if we're reading a zero-column table, we
+ * won't yet have called CopyReadAttribute() at all; so do that
+ * and check we have an empty line. Fortunately we can keep that
+ * silly corner case out of the main line of execution.
+ */
if (result == NORMAL_ATTR)
- elog(ERROR, "Extra data after last expected column");
+ {
+ if (attnumlist == NIL && !file_has_oids)
+ {
+ string = CopyReadAttribute(fp, delim, &result);
+ if (result == NORMAL_ATTR || *string != '\0')
+ elog(ERROR, "Extra data after last expected column");
+ if (result == END_OF_FILE)
+ {
+ /* EOF at start of line: all is well */
+ done = true;
+ break;
+ }
+ }
+ else
+ elog(ERROR, "Extra data after last expected column");
+ }
/*
* If we got some data on the line, but it was ended by EOF,
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 4b7e41cf063..4b77c016512 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -22,7 +22,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.305.2.3 2003/02/13 22:56:59 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.305.2.4 2003/04/25 22:14:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -960,6 +960,7 @@ dumpClasses_dumpData(Archive *fout, char *oid, void *dctxv)
PQExpBuffer q = createPQExpBuffer();
PGresult *res;
int tuple;
+ int nfields;
int field;
/*
@@ -1009,14 +1010,21 @@ dumpClasses_dumpData(Archive *fout, char *oid, void *dctxv)
exit_nicely();
}
+ nfields = PQnfields(res);
for (tuple = 0; tuple < PQntuples(res); tuple++)
{
archprintf(fout, "INSERT INTO %s ", fmtId(classname));
+ if (nfields == 0)
+ {
+ /* corner case for zero-column table */
+ archprintf(fout, "DEFAULT VALUES;\n");
+ continue;
+ }
if (attrNames == true)
{
resetPQExpBuffer(q);
appendPQExpBuffer(q, "(");
- for (field = 0; field < PQnfields(res); field++)
+ for (field = 0; field < nfields; field++)
{
if (field > 0)
appendPQExpBuffer(q, ", ");
@@ -1026,7 +1034,7 @@ dumpClasses_dumpData(Archive *fout, char *oid, void *dctxv)
archprintf(fout, "%s", q->data);
}
archprintf(fout, "VALUES (");
- for (field = 0; field < PQnfields(res); field++)
+ for (field = 0; field < nfields; field++)
{
if (field > 0)
archprintf(fout, ", ");
@@ -6702,7 +6710,10 @@ fmtQualifiedId(const char *schema, const char *id)
}
/*
- * return a column list clause for the given relation.
+ * Return a column list clause for the given relation.
+ *
+ * Special case: if there are no undropped columns in the relation, return
+ * "", not an invalid "()" column list.
*/
static const char *
fmtCopyColumnList(const TableInfo *ti)
@@ -6730,6 +6741,10 @@ fmtCopyColumnList(const TableInfo *ti)
appendPQExpBuffer(q, "%s", fmtId(attnames[i]));
needComma = true;
}
+
+ if (!needComma)
+ return ""; /* no undropped columns */
+
appendPQExpBuffer(q, ")");
return q->data;
}