8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.39 1999/01/24 22:50:58 tgl Exp $
11
+ * $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.40 1999/01/27 00:36:22 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
27
27
#include <mb/pg_wchar.h>
28
28
#endif
29
29
30
+ static void printtup_setup (DestReceiver * self , TupleDesc typeinfo );
31
+ static void printtup (HeapTuple tuple , TupleDesc typeinfo , DestReceiver * self );
32
+ static void printtup_cleanup (DestReceiver * self );
33
+
30
34
/* ----------------------------------------------------------------
31
35
* printtup / debugtup support
32
36
* ----------------------------------------------------------------
@@ -64,26 +68,105 @@ getTypeOutAndElem(Oid type, Oid* typOutput, Oid* typElem)
64
68
return 0 ;
65
69
}
66
70
71
+ /* ----------------
72
+ * Private state for a printtup destination object
73
+ * ----------------
74
+ */
75
+ typedef struct { /* Per-attribute information */
76
+ Oid typoutput ; /* Oid for the attribute's type output fn */
77
+ Oid typelem ; /* typelem value to pass to the output fn */
78
+ /* more soon... */
79
+ } PrinttupAttrInfo ;
80
+
81
+ typedef struct {
82
+ DestReceiver pub ; /* publicly-known function pointers */
83
+ TupleDesc attrinfo ; /* The attr info we are set up for */
84
+ int nattrs ;
85
+ PrinttupAttrInfo * myinfo ; /* Cached info about each attr */
86
+ } DR_printtup ;
87
+
88
+ /* ----------------
89
+ * Initialize: create a DestReceiver for printtup
90
+ * ----------------
91
+ */
92
+ DestReceiver *
93
+ printtup_create_DR ()
94
+ {
95
+ DR_printtup * self = (DR_printtup * ) palloc (sizeof (DR_printtup ));
96
+
97
+ self -> pub .receiveTuple = printtup ;
98
+ self -> pub .setup = printtup_setup ;
99
+ self -> pub .cleanup = printtup_cleanup ;
100
+
101
+ self -> attrinfo = NULL ;
102
+ self -> nattrs = 0 ;
103
+ self -> myinfo = NULL ;
104
+
105
+ return (DestReceiver * ) self ;
106
+ }
107
+
108
+ static void
109
+ printtup_setup (DestReceiver * self , TupleDesc typeinfo )
110
+ {
111
+ /* ----------------
112
+ * We could set up the derived attr info at this time, but we postpone it
113
+ * until the first call of printtup, for 3 reasons:
114
+ * 1. We don't waste time (compared to the old way) if there are no
115
+ * tuples at all to output.
116
+ * 2. Checking in printtup allows us to handle the case that the tuples
117
+ * change type midway through (although this probably can't happen in
118
+ * the current executor).
119
+ * 3. Right now, ExecutorRun passes a NULL for typeinfo anyway :-(
120
+ * ----------------
121
+ */
122
+ }
123
+
124
+ static void
125
+ printtup_prepare_info (DR_printtup * myState , TupleDesc typeinfo , int numAttrs )
126
+ {
127
+ int i ;
128
+
129
+ if (myState -> myinfo )
130
+ pfree (myState -> myinfo ); /* get rid of any old data */
131
+ myState -> myinfo = NULL ;
132
+ myState -> attrinfo = typeinfo ;
133
+ myState -> nattrs = numAttrs ;
134
+ if (numAttrs <= 0 )
135
+ return ;
136
+ myState -> myinfo = (PrinttupAttrInfo * )
137
+ palloc (numAttrs * sizeof (PrinttupAttrInfo ));
138
+ for (i = 0 ; i < numAttrs ; i ++ )
139
+ {
140
+ PrinttupAttrInfo * thisState = myState -> myinfo + i ;
141
+ getTypeOutAndElem ((Oid ) typeinfo -> attrs [i ]-> atttypid ,
142
+ & thisState -> typoutput , & thisState -> typelem );
143
+ }
144
+ }
145
+
67
146
/* ----------------
68
147
* printtup
69
148
* ----------------
70
149
*/
71
- void
72
- printtup (HeapTuple tuple , TupleDesc typeinfo )
150
+ static void
151
+ printtup (HeapTuple tuple , TupleDesc typeinfo , DestReceiver * self )
73
152
{
153
+ DR_printtup * myState = (DR_printtup * ) self ;
74
154
int i ,
75
155
j ,
76
156
k ,
77
157
outputlen ;
78
158
char * outputstr ;
79
159
Datum attr ;
80
160
bool isnull ;
81
- Oid typoutput ,
82
- typelem ;
83
161
#ifdef MULTIBYTE
84
162
unsigned char * p ;
85
163
#endif
86
164
165
+ /* Set or update my derived attribute info, if needed */
166
+ if (myState -> attrinfo != typeinfo ||
167
+ myState -> nattrs != tuple -> t_data -> t_natts )
168
+ printtup_prepare_info (myState , typeinfo , tuple -> t_data -> t_natts );
169
+
87
170
/* ----------------
88
171
* tell the frontend to expect new tuple data (in ASCII style)
89
172
* ----------------
@@ -120,10 +203,11 @@ printtup(HeapTuple tuple, TupleDesc typeinfo)
120
203
attr = heap_getattr (tuple , i + 1 , typeinfo , & isnull );
121
204
if (isnull )
122
205
continue ;
123
- if (getTypeOutAndElem ((Oid ) typeinfo -> attrs [i ]-> atttypid ,
124
- & typoutput , & typelem ))
206
+ if (OidIsValid (myState -> myinfo [i ].typoutput ))
125
207
{
126
- outputstr = fmgr (typoutput , attr , typelem ,
208
+ outputstr = fmgr (myState -> myinfo [i ].typoutput ,
209
+ attr ,
210
+ myState -> myinfo [i ].typelem ,
127
211
typeinfo -> attrs [i ]-> atttypmod );
128
212
#ifdef MULTIBYTE
129
213
p = pg_server_to_client (outputstr , strlen (outputstr ));
@@ -147,6 +231,19 @@ printtup(HeapTuple tuple, TupleDesc typeinfo)
147
231
}
148
232
}
149
233
234
+ /* ----------------
235
+ * printtup_cleanup
236
+ * ----------------
237
+ */
238
+ static void
239
+ printtup_cleanup (DestReceiver * self )
240
+ {
241
+ DR_printtup * myState = (DR_printtup * ) self ;
242
+ if (myState -> myinfo )
243
+ pfree (myState -> myinfo );
244
+ pfree (myState );
245
+ }
246
+
150
247
/* ----------------
151
248
* printatt
152
249
* ----------------
@@ -190,7 +287,7 @@ showatts(char *name, TupleDesc tupleDesc)
190
287
* ----------------
191
288
*/
192
289
void
193
- debugtup (HeapTuple tuple , TupleDesc typeinfo )
290
+ debugtup (HeapTuple tuple , TupleDesc typeinfo , DestReceiver * self )
194
291
{
195
292
int i ;
196
293
Datum attr ;
@@ -221,11 +318,12 @@ debugtup(HeapTuple tuple, TupleDesc typeinfo)
221
318
* We use a different data prefix, e.g. 'B' instead of 'D' to
222
319
* indicate a tuple in internal (binary) form.
223
320
*
224
- * This is same as printtup, except we don't use the typout func.
321
+ * This is same as printtup, except we don't use the typout func,
322
+ * and therefore have no need for persistent state.
225
323
* ----------------
226
324
*/
227
325
void
228
- printtup_internal (HeapTuple tuple , TupleDesc typeinfo )
326
+ printtup_internal (HeapTuple tuple , TupleDesc typeinfo , DestReceiver * self )
229
327
{
230
328
int i ,
231
329
j ,
0 commit comments