diff options
Diffstat (limited to 'src/backend/commands/copy.c')
-rw-r--r-- | src/backend/commands/copy.c | 50 |
1 files changed, 37 insertions, 13 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 7cb530a3cda..ec6e771aedc 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.196 2003/04/24 21:16:42 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.197 2003/04/25 02:28:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -808,10 +808,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); @@ -1078,12 +1079,13 @@ 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 = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *)); - constraintexprs = (ExprState **) palloc0(num_phys_attrs * sizeof(ExprState *)); + 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 = (ExprState **) palloc((num_phys_attrs + 1) * sizeof(ExprState *)); + constraintexprs = (ExprState **) palloc0((num_phys_attrs + 1) * sizeof(ExprState *)); for (i = 0; i < num_phys_attrs; i++) { @@ -1196,8 +1198,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)); /* Make room for a PARAM_EXEC value for domain constraint checks */ if (hasConstraints) @@ -1304,9 +1306,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(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, |