@@ -32,6 +32,10 @@ static bool printtup_internal_20(TupleTableSlot *slot, DestReceiver *self);
3232static void printtup_shutdown (DestReceiver * self );
3333static void printtup_destroy (DestReceiver * self );
3434
35+ static void SendRowDescriptionCols_2 (StringInfo buf , TupleDesc typeinfo ,
36+ List * targetlist , int16 * formats );
37+ static void SendRowDescriptionCols_3 (StringInfo buf , TupleDesc typeinfo ,
38+ List * targetlist , int16 * formats );
3539
3640/* ----------------------------------------------------------------
3741 * printtup / debugtup support
@@ -161,7 +165,8 @@ printtup_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
161165 * descriptor of the tuples.
162166 */
163167 if (myState -> sendDescrip )
164- SendRowDescriptionMessage (typeinfo ,
168+ SendRowDescriptionMessage (& myState -> buf ,
169+ typeinfo ,
165170 FetchPortalTargetList (portal ),
166171 portal -> formats );
167172
@@ -189,61 +194,126 @@ printtup_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
189194 * send zeroes for the format codes in that case.
190195 */
191196void
192- SendRowDescriptionMessage (TupleDesc typeinfo , List * targetlist , int16 * formats )
197+ SendRowDescriptionMessage (StringInfo buf , TupleDesc typeinfo ,
198+ List * targetlist , int16 * formats )
193199{
194200 int natts = typeinfo -> natts ;
195201 int proto = PG_PROTOCOL_MAJOR (FrontendProtocol );
202+
203+ /* tuple descriptor message type */
204+ pq_beginmessage_reuse (buf , 'T' );
205+ /* # of attrs in tuples */
206+ pq_sendint16 (buf , natts );
207+
208+ if (proto >= 3 )
209+ SendRowDescriptionCols_3 (buf , typeinfo , targetlist , formats );
210+ else
211+ SendRowDescriptionCols_2 (buf , typeinfo , targetlist , formats );
212+
213+ pq_endmessage_reuse (buf );
214+ }
215+
216+ /*
217+ * Send description for each column when using v3+ protocol
218+ */
219+ static void
220+ SendRowDescriptionCols_3 (StringInfo buf , TupleDesc typeinfo , List * targetlist , int16 * formats )
221+ {
222+ int natts = typeinfo -> natts ;
196223 int i ;
197- StringInfoData buf ;
198224 ListCell * tlist_item = list_head (targetlist );
199225
200- pq_beginmessage (& buf , 'T' ); /* tuple descriptor message type */
201- pq_sendint (& buf , natts , 2 ); /* # of attrs in tuples */
226+ /*
227+ * Preallocate memory for the entire message to be sent. That allows to
228+ * use the significantly faster inline pqformat.h functions and to avoid
229+ * reallocations.
230+ *
231+ * Have to overestimate the size of the column-names, to account for
232+ * character set overhead.
233+ */
234+ enlargeStringInfo (buf , (NAMEDATALEN * MAX_CONVERSION_GROWTH /* attname */
235+ + sizeof (Oid ) /* resorigtbl */
236+ + sizeof (AttrNumber ) /* resorigcol */
237+ + sizeof (Oid ) /* atttypid */
238+ + sizeof (int16 ) /* attlen */
239+ + sizeof (int32 ) /* attypmod */
240+ + sizeof (int16 ) /* format */
241+ ) * natts );
202242
203243 for (i = 0 ; i < natts ; ++ i )
204244 {
205245 Form_pg_attribute att = TupleDescAttr (typeinfo , i );
206246 Oid atttypid = att -> atttypid ;
207247 int32 atttypmod = att -> atttypmod ;
248+ Oid resorigtbl ;
249+ AttrNumber resorigcol ;
250+ int16 format ;
251+
252+ /*
253+ * If column is a domain, send the base type and typmod instead.
254+ * Lookup before sending any ints, for efficiency.
255+ */
256+ atttypid = getBaseTypeAndTypmod (atttypid , & atttypmod );
208257
209- pq_sendstring (& buf , NameStr (att -> attname ));
210- /* column ID info appears in protocol 3.0 and up */
211- if (proto >= 3 )
258+ /* Do we have a non-resjunk tlist item? */
259+ while (tlist_item &&
260+ ((TargetEntry * ) lfirst (tlist_item ))-> resjunk )
261+ tlist_item = lnext (tlist_item );
262+ if (tlist_item )
212263 {
213- /* Do we have a non-resjunk tlist item? */
214- while (tlist_item &&
215- ((TargetEntry * ) lfirst (tlist_item ))-> resjunk )
216- tlist_item = lnext (tlist_item );
217- if (tlist_item )
218- {
219- TargetEntry * tle = (TargetEntry * ) lfirst (tlist_item );
220-
221- pq_sendint (& buf , tle -> resorigtbl , 4 );
222- pq_sendint (& buf , tle -> resorigcol , 2 );
223- tlist_item = lnext (tlist_item );
224- }
225- else
226- {
227- /* No info available, so send zeroes */
228- pq_sendint (& buf , 0 , 4 );
229- pq_sendint (& buf , 0 , 2 );
230- }
264+ TargetEntry * tle = (TargetEntry * ) lfirst (tlist_item );
265+
266+ resorigtbl = tle -> resorigtbl ;
267+ resorigcol = tle -> resorigcol ;
268+ tlist_item = lnext (tlist_item );
231269 }
232- /* If column is a domain, send the base type and typmod instead */
233- atttypid = getBaseTypeAndTypmod (atttypid , & atttypmod );
234- pq_sendint (& buf , (int ) atttypid , sizeof (atttypid ));
235- pq_sendint (& buf , att -> attlen , sizeof (att -> attlen ));
236- pq_sendint (& buf , atttypmod , sizeof (atttypmod ));
237- /* format info appears in protocol 3.0 and up */
238- if (proto >= 3 )
270+ else
239271 {
240- if (formats )
241- pq_sendint (& buf , formats [i ], 2 );
242- else
243- pq_sendint (& buf , 0 , 2 );
272+ /* No info available, so send zeroes */
273+ resorigtbl = 0 ;
274+ resorigcol = 0 ;
244275 }
276+
277+ if (formats )
278+ format = formats [i ];
279+ else
280+ format = 0 ;
281+
282+ pq_writestring (buf , NameStr (att -> attname ));
283+ pq_writeint32 (buf , resorigtbl );
284+ pq_writeint16 (buf , resorigcol );
285+ pq_writeint32 (buf , atttypid );
286+ pq_writeint16 (buf , att -> attlen );
287+ pq_writeint32 (buf , atttypmod );
288+ pq_writeint16 (buf , format );
289+ }
290+ }
291+
292+ /*
293+ * Send description for each column when using v2 protocol
294+ */
295+ static void
296+ SendRowDescriptionCols_2 (StringInfo buf , TupleDesc typeinfo , List * targetlist , int16 * formats )
297+ {
298+ int natts = typeinfo -> natts ;
299+ int i ;
300+
301+ for (i = 0 ; i < natts ; ++ i )
302+ {
303+ Form_pg_attribute att = TupleDescAttr (typeinfo , i );
304+ Oid atttypid = att -> atttypid ;
305+ int32 atttypmod = att -> atttypmod ;
306+
307+ /* If column is a domain, send the base type and typmod instead */
308+ atttypid = getBaseTypeAndTypmod (atttypid , & atttypmod );
309+
310+ pq_sendstring (buf , NameStr (att -> attname ));
311+ /* column ID only info appears in protocol 3.0 and up */
312+ pq_sendint32 (buf , atttypid );
313+ pq_sendint16 (buf , att -> attlen );
314+ pq_sendint32 (buf , atttypmod );
315+ /* format info only appears in protocol 3.0 and up */
245316 }
246- pq_endmessage (& buf );
247317}
248318
249319/*
0 commit comments