From 5cc38649d4ecc2f3134852758de5d902bf3b8989 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 4 Aug 2004 19:31:15 +0000 Subject: [PATCH] record_out and friends need to cope with dropped columns in the row datatype. Per example from Gaetano Mendola, 2004-07-25. --- src/backend/utils/adt/rowtypes.c | 99 ++++++++++++++++++++++---------- 1 file changed, 69 insertions(+), 30 deletions(-) diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c index 08189d3c14..b5ddc05bc4 100644 --- a/src/backend/utils/adt/rowtypes.c +++ b/src/backend/utils/adt/rowtypes.c @@ -8,7 +8,7 @@ * * * 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) TupleDesc tupdesc; HeapTuple tuple; RecordIOData *my_extra; + bool needComma = false; int ncolumns; int i; char *ptr; @@ -131,6 +132,26 @@ record_in(PG_FUNCTION_ARGS) ColumnIOData *column_info = &my_extra->columns[i]; 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 */ if (*ptr == ',' || *ptr == ')') { @@ -203,27 +224,9 @@ record_in(PG_FUNCTION_ARGS) /* * Prep for next column */ - if (*ptr == ',') - { - 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."))); - } + needComma = true; } - /* The check for ')' here is redundant except when ncolumns == 0 */ if (*ptr++ != ')') ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), @@ -259,6 +262,7 @@ record_out(PG_FUNCTION_ARGS) TupleDesc tupdesc; HeapTupleData tuple; RecordIOData *my_extra; + bool needComma = false; int ncolumns; int i; Datum *values; @@ -333,8 +337,13 @@ record_out(PG_FUNCTION_ARGS) char *tmp; bool nq; - if (i > 0) + /* Ignore dropped columns in datatype */ + if (tupdesc->attrs[i]->attisdropped) + continue; + + if (needComma) appendStringInfoChar(&buf, ','); + needComma = true; if (nulls[i] == 'n') { @@ -414,6 +423,8 @@ record_recv(PG_FUNCTION_ARGS) HeapTuple tuple; RecordIOData *my_extra; int ncolumns; + int usercols; + int validcols; int i; Datum *values; char *nulls; @@ -463,13 +474,21 @@ record_recv(PG_FUNCTION_ARGS) values = (Datum *) palloc(ncolumns * sizeof(Datum)); nulls = (char *) palloc(ncolumns * sizeof(char)); - /* Verify number of columns */ - i = pq_getmsgint(buf, 4); - if (i != ncolumns) + /* Fetch number of columns user thinks it has */ + usercols = pq_getmsgint(buf, 4); + + /* 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, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("wrong number of columns: %d, expected %d", - i, ncolumns))); + usercols, validcols))); /* Process each column */ for (i = 0; i < ncolumns; i++) @@ -479,13 +498,21 @@ record_recv(PG_FUNCTION_ARGS) Oid coltypoid; 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 */ coltypoid = pq_getmsgint(buf, sizeof(Oid)); if (coltypoid != column_type) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("wrong data type: %u, expected %u", - coltypoid, column_type))); + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("wrong data type: %u, expected %u", + coltypoid, column_type))); /* Get and check the item length */ itemlen = pq_getmsgint(buf, 4); @@ -570,6 +597,7 @@ record_send(PG_FUNCTION_ARGS) HeapTupleData tuple; RecordIOData *my_extra; int ncolumns; + int validcols; int i; Datum *values; char *nulls; @@ -633,7 +661,14 @@ record_send(PG_FUNCTION_ARGS) /* And build the result string */ 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++) { @@ -641,6 +676,10 @@ record_send(PG_FUNCTION_ARGS) Oid column_type = tupdesc->attrs[i]->atttypid; bytea *outputbytes; + /* Ignore dropped columns in datatype */ + if (tupdesc->attrs[i]->attisdropped) + continue; + pq_sendint(&buf, column_type, sizeof(Oid)); if (nulls[i] == 'n')