Commit 5cc38649 authored by Tom Lane's avatar Tom Lane

record_out and friends need to cope with dropped columns in the row

datatype.  Per example from Gaetano Mendola, 2004-07-25.
parent 8515efa1
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/rowtypes.c,v 1.3 2004/06/06 18:06:25 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/rowtypes.c,v 1.4 2004/08/04 19:31:15 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -58,6 +58,7 @@ record_in(PG_FUNCTION_ARGS) ...@@ -58,6 +58,7 @@ record_in(PG_FUNCTION_ARGS)
TupleDesc tupdesc; TupleDesc tupdesc;
HeapTuple tuple; HeapTuple tuple;
RecordIOData *my_extra; RecordIOData *my_extra;
bool needComma = false;
int ncolumns; int ncolumns;
int i; int i;
char *ptr; char *ptr;
...@@ -131,6 +132,26 @@ record_in(PG_FUNCTION_ARGS) ...@@ -131,6 +132,26 @@ record_in(PG_FUNCTION_ARGS)
ColumnIOData *column_info = &my_extra->columns[i]; ColumnIOData *column_info = &my_extra->columns[i];
Oid column_type = tupdesc->attrs[i]->atttypid; Oid column_type = tupdesc->attrs[i]->atttypid;
/* Ignore dropped columns in datatype, but fill with nulls */
if (tupdesc->attrs[i]->attisdropped)
{
values[i] = (Datum) 0;
nulls[i] = 'n';
continue;
}
if (needComma)
{
/* Skip comma that separates prior field from this one */
if (*ptr == ',')
ptr++;
else /* *ptr must be ')' */
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed record literal: \"%s\"", string),
errdetail("Too few columns.")));
}
/* Check for null: completely empty input means null */ /* Check for null: completely empty input means null */
if (*ptr == ',' || *ptr == ')') if (*ptr == ',' || *ptr == ')')
{ {
...@@ -203,27 +224,9 @@ record_in(PG_FUNCTION_ARGS) ...@@ -203,27 +224,9 @@ record_in(PG_FUNCTION_ARGS)
/* /*
* Prep for next column * Prep for next column
*/ */
if (*ptr == ',') needComma = true;
{
if (i == ncolumns-1)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed record literal: \"%s\"", string),
errdetail("Too many columns.")));
ptr++;
}
else
{
/* *ptr must be ')' */
if (i < ncolumns-1)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed record literal: \"%s\"", string),
errdetail("Too few columns.")));
}
} }
/* The check for ')' here is redundant except when ncolumns == 0 */
if (*ptr++ != ')') if (*ptr++ != ')')
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
...@@ -259,6 +262,7 @@ record_out(PG_FUNCTION_ARGS) ...@@ -259,6 +262,7 @@ record_out(PG_FUNCTION_ARGS)
TupleDesc tupdesc; TupleDesc tupdesc;
HeapTupleData tuple; HeapTupleData tuple;
RecordIOData *my_extra; RecordIOData *my_extra;
bool needComma = false;
int ncolumns; int ncolumns;
int i; int i;
Datum *values; Datum *values;
...@@ -333,8 +337,13 @@ record_out(PG_FUNCTION_ARGS) ...@@ -333,8 +337,13 @@ record_out(PG_FUNCTION_ARGS)
char *tmp; char *tmp;
bool nq; bool nq;
if (i > 0) /* Ignore dropped columns in datatype */
if (tupdesc->attrs[i]->attisdropped)
continue;
if (needComma)
appendStringInfoChar(&buf, ','); appendStringInfoChar(&buf, ',');
needComma = true;
if (nulls[i] == 'n') if (nulls[i] == 'n')
{ {
...@@ -414,6 +423,8 @@ record_recv(PG_FUNCTION_ARGS) ...@@ -414,6 +423,8 @@ record_recv(PG_FUNCTION_ARGS)
HeapTuple tuple; HeapTuple tuple;
RecordIOData *my_extra; RecordIOData *my_extra;
int ncolumns; int ncolumns;
int usercols;
int validcols;
int i; int i;
Datum *values; Datum *values;
char *nulls; char *nulls;
...@@ -463,13 +474,21 @@ record_recv(PG_FUNCTION_ARGS) ...@@ -463,13 +474,21 @@ record_recv(PG_FUNCTION_ARGS)
values = (Datum *) palloc(ncolumns * sizeof(Datum)); values = (Datum *) palloc(ncolumns * sizeof(Datum));
nulls = (char *) palloc(ncolumns * sizeof(char)); nulls = (char *) palloc(ncolumns * sizeof(char));
/* Verify number of columns */ /* Fetch number of columns user thinks it has */
i = pq_getmsgint(buf, 4); usercols = pq_getmsgint(buf, 4);
if (i != ncolumns)
/* Need to scan to count nondeleted columns */
validcols = 0;
for (i = 0; i < ncolumns; i++)
{
if (!tupdesc->attrs[i]->attisdropped)
validcols++;
}
if (usercols != validcols)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), (errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("wrong number of columns: %d, expected %d", errmsg("wrong number of columns: %d, expected %d",
i, ncolumns))); usercols, validcols)));
/* Process each column */ /* Process each column */
for (i = 0; i < ncolumns; i++) for (i = 0; i < ncolumns; i++)
...@@ -479,6 +498,14 @@ record_recv(PG_FUNCTION_ARGS) ...@@ -479,6 +498,14 @@ record_recv(PG_FUNCTION_ARGS)
Oid coltypoid; Oid coltypoid;
int itemlen; int itemlen;
/* Ignore dropped columns in datatype, but fill with nulls */
if (tupdesc->attrs[i]->attisdropped)
{
values[i] = (Datum) 0;
nulls[i] = 'n';
continue;
}
/* Verify column datatype */ /* Verify column datatype */
coltypoid = pq_getmsgint(buf, sizeof(Oid)); coltypoid = pq_getmsgint(buf, sizeof(Oid));
if (coltypoid != column_type) if (coltypoid != column_type)
...@@ -570,6 +597,7 @@ record_send(PG_FUNCTION_ARGS) ...@@ -570,6 +597,7 @@ record_send(PG_FUNCTION_ARGS)
HeapTupleData tuple; HeapTupleData tuple;
RecordIOData *my_extra; RecordIOData *my_extra;
int ncolumns; int ncolumns;
int validcols;
int i; int i;
Datum *values; Datum *values;
char *nulls; char *nulls;
...@@ -633,7 +661,14 @@ record_send(PG_FUNCTION_ARGS) ...@@ -633,7 +661,14 @@ record_send(PG_FUNCTION_ARGS)
/* And build the result string */ /* And build the result string */
pq_begintypsend(&buf); pq_begintypsend(&buf);
pq_sendint(&buf, ncolumns, 4); /* Need to scan to count nondeleted columns */
validcols = 0;
for (i = 0; i < ncolumns; i++)
{
if (!tupdesc->attrs[i]->attisdropped)
validcols++;
}
pq_sendint(&buf, validcols, 4);
for (i = 0; i < ncolumns; i++) for (i = 0; i < ncolumns; i++)
{ {
...@@ -641,6 +676,10 @@ record_send(PG_FUNCTION_ARGS) ...@@ -641,6 +676,10 @@ record_send(PG_FUNCTION_ARGS)
Oid column_type = tupdesc->attrs[i]->atttypid; Oid column_type = tupdesc->attrs[i]->atttypid;
bytea *outputbytes; bytea *outputbytes;
/* Ignore dropped columns in datatype */
if (tupdesc->attrs[i]->attisdropped)
continue;
pq_sendint(&buf, column_type, sizeof(Oid)); pq_sendint(&buf, column_type, sizeof(Oid));
if (nulls[i] == 'n') if (nulls[i] == 'n')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment