@@ -32,6 +32,10 @@ static bool printtup_internal_20(TupleTableSlot *slot, DestReceiver *self);
32
32
static void printtup_shutdown (DestReceiver * self );
33
33
static void printtup_destroy (DestReceiver * self );
34
34
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 );
35
39
36
40
/* ----------------------------------------------------------------
37
41
* printtup / debugtup support
@@ -161,7 +165,8 @@ printtup_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
161
165
* descriptor of the tuples.
162
166
*/
163
167
if (myState -> sendDescrip )
164
- SendRowDescriptionMessage (typeinfo ,
168
+ SendRowDescriptionMessage (& myState -> buf ,
169
+ typeinfo ,
165
170
FetchPortalTargetList (portal ),
166
171
portal -> formats );
167
172
@@ -189,61 +194,126 @@ printtup_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
189
194
* send zeroes for the format codes in that case.
190
195
*/
191
196
void
192
- SendRowDescriptionMessage (TupleDesc typeinfo , List * targetlist , int16 * formats )
197
+ SendRowDescriptionMessage (StringInfo buf , TupleDesc typeinfo ,
198
+ List * targetlist , int16 * formats )
193
199
{
194
200
int natts = typeinfo -> natts ;
195
201
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 ;
196
223
int i ;
197
- StringInfoData buf ;
198
224
ListCell * tlist_item = list_head (targetlist );
199
225
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 );
202
242
203
243
for (i = 0 ; i < natts ; ++ i )
204
244
{
205
245
Form_pg_attribute att = TupleDescAttr (typeinfo , i );
206
246
Oid atttypid = att -> atttypid ;
207
247
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 );
208
257
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 )
212
263
{
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 );
231
269
}
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
239
271
{
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 ;
244
275
}
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 */
245
316
}
246
- pq_endmessage (& buf );
247
317
}
248
318
249
319
/*
0 commit comments