88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/utils/adt/rowtypes.c,v 1.3 2004/06/06 18:06:25 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/utils/adt/rowtypes.c,v 1.4 2004/08/04 19:31:15 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -58,6 +58,7 @@ record_in(PG_FUNCTION_ARGS)
5858TupleDesc tupdesc ;
5959HeapTuple tuple ;
6060RecordIOData * my_extra ;
61+ bool needComma = false;
6162int ncolumns ;
6263int i ;
6364char * ptr ;
@@ -131,6 +132,26 @@ record_in(PG_FUNCTION_ARGS)
131132ColumnIOData * column_info = & my_extra -> columns [i ];
132133Oid column_type = tupdesc -> attrs [i ]-> atttypid ;
133134
135+ /* Ignore dropped columns in datatype, but fill with nulls */
136+ if (tupdesc -> attrs [i ]-> attisdropped )
137+ {
138+ values [i ]= (Datum )0 ;
139+ nulls [i ]= 'n' ;
140+ continue ;
141+ }
142+
143+ if (needComma )
144+ {
145+ /* Skip comma that separates prior field from this one */
146+ if (* ptr == ',' )
147+ ptr ++ ;
148+ else /* *ptr must be ')' */
149+ ereport (ERROR ,
150+ (errcode (ERRCODE_INVALID_TEXT_REPRESENTATION ),
151+ errmsg ("malformed record literal: \"%s\"" ,string ),
152+ errdetail ("Too few columns." )));
153+ }
154+
134155/* Check for null: completely empty input means null */
135156if (* ptr == ',' || * ptr == ')' )
136157{
@@ -203,27 +224,9 @@ record_in(PG_FUNCTION_ARGS)
203224/*
204225 * Prep for next column
205226 */
206- if (* ptr == ',' )
207- {
208- if (i == ncolumns - 1 )
209- ereport (ERROR ,
210- (errcode (ERRCODE_INVALID_TEXT_REPRESENTATION ),
211- errmsg ("malformed record literal: \"%s\"" ,string ),
212- errdetail ("Too many columns." )));
213- ptr ++ ;
214- }
215- else
216- {
217- /* *ptr must be ')' */
218- if (i < ncolumns - 1 )
219- ereport (ERROR ,
220- (errcode (ERRCODE_INVALID_TEXT_REPRESENTATION ),
221- errmsg ("malformed record literal: \"%s\"" ,string ),
222- errdetail ("Too few columns." )));
223- }
227+ needComma = true;
224228}
225229
226- /* The check for ')' here is redundant except when ncolumns == 0 */
227230if (* ptr ++ != ')' )
228231ereport (ERROR ,
229232(errcode (ERRCODE_INVALID_TEXT_REPRESENTATION ),
@@ -259,6 +262,7 @@ record_out(PG_FUNCTION_ARGS)
259262TupleDesc tupdesc ;
260263HeapTupleData tuple ;
261264RecordIOData * my_extra ;
265+ bool needComma = false;
262266int ncolumns ;
263267int i ;
264268Datum * values ;
@@ -333,8 +337,13 @@ record_out(PG_FUNCTION_ARGS)
333337char * tmp ;
334338bool nq ;
335339
336- if (i > 0 )
340+ /* Ignore dropped columns in datatype */
341+ if (tupdesc -> attrs [i ]-> attisdropped )
342+ continue ;
343+
344+ if (needComma )
337345appendStringInfoChar (& buf ,',' );
346+ needComma = true;
338347
339348if (nulls [i ]== 'n' )
340349{
@@ -414,6 +423,8 @@ record_recv(PG_FUNCTION_ARGS)
414423HeapTuple tuple ;
415424RecordIOData * my_extra ;
416425int ncolumns ;
426+ int usercols ;
427+ int validcols ;
417428int i ;
418429Datum * values ;
419430char * nulls ;
@@ -463,13 +474,21 @@ record_recv(PG_FUNCTION_ARGS)
463474values = (Datum * )palloc (ncolumns * sizeof (Datum ));
464475nulls = (char * )palloc (ncolumns * sizeof (char ));
465476
466- /* Verify number of columns */
467- i = pq_getmsgint (buf ,4 );
468- if (i != ncolumns )
477+ /* Fetch number of columns user thinks it has */
478+ usercols = pq_getmsgint (buf ,4 );
479+
480+ /* Need to scan to count nondeleted columns */
481+ validcols = 0 ;
482+ for (i = 0 ;i < ncolumns ;i ++ )
483+ {
484+ if (!tupdesc -> attrs [i ]-> attisdropped )
485+ validcols ++ ;
486+ }
487+ if (usercols != validcols )
469488ereport (ERROR ,
470489(errcode (ERRCODE_DATATYPE_MISMATCH ),
471490errmsg ("wrong number of columns: %d, expected %d" ,
472- i , ncolumns )));
491+ usercols , validcols )));
473492
474493/* Process each column */
475494for (i = 0 ;i < ncolumns ;i ++ )
@@ -479,13 +498,21 @@ record_recv(PG_FUNCTION_ARGS)
479498Oid coltypoid ;
480499int itemlen ;
481500
501+ /* Ignore dropped columns in datatype, but fill with nulls */
502+ if (tupdesc -> attrs [i ]-> attisdropped )
503+ {
504+ values [i ]= (Datum )0 ;
505+ nulls [i ]= 'n' ;
506+ continue ;
507+ }
508+
482509/* Verify column datatype */
483510coltypoid = pq_getmsgint (buf ,sizeof (Oid ));
484511if (coltypoid != column_type )
485- ereport (ERROR ,
486- (errcode (ERRCODE_DATATYPE_MISMATCH ),
487- errmsg ("wrong data type: %u, expected %u" ,
488- coltypoid ,column_type )));
512+ ereport (ERROR ,
513+ (errcode (ERRCODE_DATATYPE_MISMATCH ),
514+ errmsg ("wrong data type: %u, expected %u" ,
515+ coltypoid ,column_type )));
489516
490517/* Get and check the item length */
491518itemlen = pq_getmsgint (buf ,4 );
@@ -570,6 +597,7 @@ record_send(PG_FUNCTION_ARGS)
570597HeapTupleData tuple ;
571598RecordIOData * my_extra ;
572599int ncolumns ;
600+ int validcols ;
573601int i ;
574602Datum * values ;
575603char * nulls ;
@@ -633,14 +661,25 @@ record_send(PG_FUNCTION_ARGS)
633661/* And build the result string */
634662pq_begintypsend (& buf );
635663
636- pq_sendint (& buf ,ncolumns ,4 );
664+ /* Need to scan to count nondeleted columns */
665+ validcols = 0 ;
666+ for (i = 0 ;i < ncolumns ;i ++ )
667+ {
668+ if (!tupdesc -> attrs [i ]-> attisdropped )
669+ validcols ++ ;
670+ }
671+ pq_sendint (& buf ,validcols ,4 );
637672
638673for (i = 0 ;i < ncolumns ;i ++ )
639674{
640675ColumnIOData * column_info = & my_extra -> columns [i ];
641676Oid column_type = tupdesc -> attrs [i ]-> atttypid ;
642677bytea * outputbytes ;
643678
679+ /* Ignore dropped columns in datatype */
680+ if (tupdesc -> attrs [i ]-> attisdropped )
681+ continue ;
682+
644683pq_sendint (& buf ,column_type ,sizeof (Oid ));
645684
646685if (nulls [i ]== 'n' )