record_out and friends need to cope with dropped columns in the row
datatype. Per example from Gaetano Mendola, 2004-07-25.
This commit is contained in:
parent
8515efa128
commit
5cc38649d4
@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
/* 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)
|
|||||||
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')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user